feat(statusline): include memfs metadata in command payload (#1389)

Co-authored-by: Letta Code <noreply@letta.com>
This commit is contained in:
jnjpng
2026-03-16 15:34:08 -07:00
committed by GitHub
parent 3edaf91ee4
commit aba5ecc62a
5 changed files with 95 additions and 0 deletions

View File

@@ -2493,6 +2493,12 @@ export default function App({
// Configurable status line hook
const sessionStatsSnapshot = sessionStatsRef.current.getSnapshot();
const contextWindowSize = llmConfigRef.current?.context_window;
const reflectionSettings = getReflectionSettings();
const memfsEnabled = settingsManager.isMemfsEnabled(agentId);
const memfsDirectory =
memfsEnabled && agentId && agentId !== "loading"
? getMemoryFilesystemRoot(agentId)
: null;
const statusLine = useConfigurableStatusLine({
modelId: llmConfigRef.current?.model ?? null,
modelDisplayName: currentModelDisplay,
@@ -2511,6 +2517,12 @@ export default function App({
totalOutputTokens: sessionStatsSnapshot.usage.completionTokens,
contextWindowSize,
usedContextTokens: contextTrackerRef.current.lastContextTokens,
stepCount: sessionStatsSnapshot.usage.stepCount,
turnCount: contextTrackerRef.current.currentTurnId,
reflectionMode: reflectionSettings.trigger,
reflectionStepCount: reflectionSettings.stepCount,
memfsEnabled,
memfsDirectory,
permissionMode: uiPermissionMode,
networkPhase,
terminalWidth: chromeColumns,
@@ -7625,6 +7637,19 @@ export default function App({
contextWindowSize: llmConfigRef.current?.context_window,
usedContextTokens:
contextTrackerRef.current.lastContextTokens,
stepCount: stats.usage.stepCount,
turnCount: contextTrackerRef.current.currentTurnId,
reflectionMode: getReflectionSettings().trigger,
reflectionStepCount: getReflectionSettings().stepCount,
memfsEnabled:
agentId !== "loading"
? settingsManager.isMemfsEnabled(agentId)
: false,
memfsDirectory:
agentId !== "loading" &&
settingsManager.isMemfsEnabled(agentId)
? getMemoryFilesystemRoot(agentId)
: null,
permissionMode: uiPermissionMode,
networkPhase,
terminalWidth: chromeColumns,

View File

@@ -18,6 +18,12 @@ export interface StatusLinePayloadBuildInput {
totalOutputTokens?: number;
contextWindowSize?: number;
usedContextTokens?: number;
stepCount?: number;
turnCount?: number;
reflectionMode?: "off" | "step-count" | "compaction-event" | null;
reflectionStepCount?: number;
memfsEnabled?: boolean;
memfsDirectory?: string | null;
permissionMode?: string;
networkPhase?: "upload" | "download" | "error" | null;
terminalWidth?: number;
@@ -82,6 +88,16 @@ export interface StatusLinePayload {
id: string | null;
name: string | null;
};
step_count: number;
turn_count: number;
reflection: {
mode: "off" | "step-count" | "compaction-event" | null;
step_count: number;
};
memfs: {
enabled: boolean;
memory_dir: string | null;
};
permission_mode: string | null;
network_phase: "upload" | "download" | "error" | null;
terminal_width: number | null;
@@ -128,6 +144,12 @@ export function buildStatusLinePayload(
0,
Math.floor(input.usedContextTokens ?? 0),
);
const stepCount = Math.max(0, Math.floor(input.stepCount ?? 0));
const turnCount = Math.max(0, Math.floor(input.turnCount ?? 0));
const reflectionStepCount = Math.max(
0,
Math.floor(input.reflectionStepCount ?? 0),
);
const percentages =
contextWindowSize > 0
@@ -175,6 +197,16 @@ export function buildStatusLinePayload(
id: input.agentId ?? null,
name: input.agentName ?? null,
},
step_count: stepCount,
turn_count: turnCount,
reflection: {
mode: input.reflectionMode ?? null,
step_count: reflectionStepCount,
},
memfs: {
enabled: input.memfsEnabled ?? false,
memory_dir: input.memfsDirectory ?? null,
},
permission_mode: input.permissionMode ?? null,
network_phase: input.networkPhase ?? null,
terminal_width: input.terminalWidth ?? null,

View File

@@ -15,6 +15,12 @@ export const STATUSLINE_NATIVE_FIELDS: StatusLineFieldSpec[] = [
{ path: "model.display_name" },
{ path: "agent.id" },
{ path: "agent.name" },
{ path: "step_count" },
{ path: "turn_count" },
{ path: "reflection.mode" },
{ path: "reflection.step_count" },
{ path: "memfs.enabled" },
{ path: "memfs.memory_dir" },
{ path: "cost.total_duration_ms" },
{ path: "cost.total_api_duration_ms" },
{ path: "context_window.context_window_size" },

View File

@@ -36,6 +36,12 @@ export interface StatusLineInputs {
totalOutputTokens?: number;
contextWindowSize?: number;
usedContextTokens?: number;
stepCount?: number;
turnCount?: number;
reflectionMode?: "off" | "step-count" | "compaction-event" | null;
reflectionStepCount?: number;
memfsEnabled?: boolean;
memfsDirectory?: string | null;
permissionMode?: string;
networkPhase?: "upload" | "download" | "error" | null;
terminalWidth?: number;
@@ -79,6 +85,12 @@ function toPayloadInput(inputs: StatusLineInputs): StatusLinePayloadBuildInput {
totalOutputTokens: inputs.totalOutputTokens,
contextWindowSize: inputs.contextWindowSize,
usedContextTokens: inputs.usedContextTokens,
stepCount: inputs.stepCount,
turnCount: inputs.turnCount,
reflectionMode: inputs.reflectionMode,
reflectionStepCount: inputs.reflectionStepCount,
memfsEnabled: inputs.memfsEnabled,
memfsDirectory: inputs.memfsDirectory,
permissionMode: inputs.permissionMode,
networkPhase: inputs.networkPhase,
terminalWidth: inputs.terminalWidth,

View File

@@ -19,6 +19,12 @@ describe("statusLinePayload", () => {
totalOutputTokens: 450,
contextWindowSize: 200_000,
usedContextTokens: 40_000,
stepCount: 7,
turnCount: 3,
reflectionMode: "step-count",
reflectionStepCount: 10,
memfsEnabled: true,
memfsDirectory: "/Users/test/.letta/agents/agent-123/memory",
permissionMode: "default",
networkPhase: "download",
terminalWidth: 120,
@@ -31,6 +37,14 @@ describe("statusLinePayload", () => {
expect(payload.model.display_name).toBe("Sonnet");
expect(payload.context_window.used_percentage).toBe(20);
expect(payload.context_window.remaining_percentage).toBe(80);
expect(payload.step_count).toBe(7);
expect(payload.turn_count).toBe(3);
expect(payload.reflection.mode).toBe("step-count");
expect(payload.reflection.step_count).toBe(10);
expect(payload.memfs.enabled).toBe(true);
expect(payload.memfs.memory_dir).toBe(
"/Users/test/.letta/agents/agent-123/memory",
);
expect(payload.permission_mode).toBe("default");
expect(payload.network_phase).toBe("download");
expect(payload.terminal_width).toBe(120);
@@ -45,6 +59,12 @@ describe("statusLinePayload", () => {
expect(payload.transcript_path).toBeNull();
expect(payload.output_style.name).toBeNull();
expect(payload.vim).toBeNull();
expect(payload.step_count).toBe(0);
expect(payload.turn_count).toBe(0);
expect(payload.reflection.mode).toBeNull();
expect(payload.reflection.step_count).toBe(0);
expect(payload.memfs.enabled).toBe(false);
expect(payload.memfs.memory_dir).toBeNull();
expect(payload.cost.total_cost_usd).toBeNull();
expect(payload.context_window.current_usage).toBeNull();
});