From 30f893b76668988ae5f630f668500ec94412659d Mon Sep 17 00:00:00 2001 From: justsisyphus Date: Fri, 30 Jan 2026 11:45:58 +0900 Subject: [PATCH] fix(cli/run): fix [undefine] tag and add text preview to verbose log - Fix sessionTag showing '[undefine]' when sessionID is undefined - System events now display as '[system]' instead - Fix message.updated expecting non-existent 'content' field - SDK's EventMessageUpdated only contains info metadata, not content - Content is streamed via message.part.updated events - Add text preview to message.part.updated verbose logging - Update MessageUpdatedProps type to match SDK structure - Update tests to reflect actual SDK behavior --- src/cli/run/events.test.ts | 12 +++++------- src/cli/run/events.ts | 30 ++++++++++++------------------ src/cli/run/types.ts | 9 +++++++-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/cli/run/events.test.ts b/src/cli/run/events.test.ts index ecd82435d..7b46bb0ac 100644 --- a/src/cli/run/events.test.ts +++ b/src/cli/run/events.test.ts @@ -148,7 +148,7 @@ describe("event handling", () => { expect(state.hasReceivedMeaningfulWork).toBe(false) }) - it("message.updated with assistant content sets hasReceivedMeaningfulWork", async () => { + it("message.updated with assistant role sets hasReceivedMeaningfulWork", async () => { // #given const ctx = createMockContext("my-session") const state = createEventState() @@ -157,7 +157,6 @@ describe("event handling", () => { type: "message.updated", properties: { info: { sessionID: "my-session", role: "assistant" }, - content: "Hello, I will fix this bug.", }, } @@ -171,16 +170,15 @@ describe("event handling", () => { expect(state.hasReceivedMeaningfulWork).toBe(true) }) - it("message.updated with empty assistant content does not set hasReceivedMeaningfulWork", async () => { - // #given - empty assistant message (race condition: message created but no content yet) + it("message.updated with user role does not set hasReceivedMeaningfulWork", async () => { + // #given - user message should not count as meaningful work const ctx = createMockContext("my-session") const state = createEventState() const payload: EventPayload = { type: "message.updated", properties: { - info: { sessionID: "my-session", role: "assistant" }, - content: "", + info: { sessionID: "my-session", role: "user" }, }, } @@ -190,7 +188,7 @@ describe("event handling", () => { // #when await processEvents(ctx, events, state) - // #then - empty content should not count as meaningful work + // #then - user role should not count as meaningful work expect(state.hasReceivedMeaningfulWork).toBe(false) }) diff --git a/src/cli/run/events.ts b/src/cli/run/events.ts index e8d342600..af0fabbd7 100644 --- a/src/cli/run/events.ts +++ b/src/cli/run/events.ts @@ -116,7 +116,9 @@ function logEventVerbose(ctx: RunContext, payload: EventPayload): void { const isMainSession = sessionID === ctx.sessionID const sessionTag = isMainSession ? pc.green("[MAIN]") - : pc.yellow(`[${String(sessionID).slice(0, 8)}]`) + : sessionID + ? pc.yellow(`[${String(sessionID).slice(0, 8)}]`) + : pc.dim("[system]") switch (payload.type) { case "session.idle": @@ -127,8 +129,6 @@ function logEventVerbose(ctx: RunContext, payload: EventPayload): void { } case "message.part.updated": { - // Skip verbose logging for partial message updates - // Only log tool invocation state changes, not text streaming const partProps = props as MessagePartUpdatedProps | undefined const part = partProps?.part if (part?.type === "tool-invocation") { @@ -136,6 +136,11 @@ function logEventVerbose(ctx: RunContext, payload: EventPayload): void { console.error( pc.dim(`${sessionTag} message.part (tool): ${toolPart.toolName} [${toolPart.state}]`) ) + } else if (part?.type === "text" && part.text) { + const preview = part.text.slice(0, 80).replace(/\n/g, "\\n") + console.error( + pc.dim(`${sessionTag} message.part (text): "${preview}${part.text.length > 80 ? "..." : ""}"`) + ) } break } @@ -143,11 +148,10 @@ function logEventVerbose(ctx: RunContext, payload: EventPayload): void { case "message.updated": { const msgProps = props as MessageUpdatedProps | undefined const role = msgProps?.info?.role ?? "unknown" - const content = msgProps?.content ?? "" - const preview = content.slice(0, 100).replace(/\n/g, "\\n") - console.error( - pc.dim(`${sessionTag} message.updated (${role}): "${preview}${content.length > 100 ? "..." : ""}"`) - ) + const model = msgProps?.info?.modelID + const agent = msgProps?.info?.agent + const details = [role, agent, model].filter(Boolean).join(", ") + console.error(pc.dim(`${sessionTag} message.updated (${details})`)) break } @@ -261,16 +265,6 @@ function handleMessageUpdated( if (props?.info?.sessionID !== ctx.sessionID) return if (props?.info?.role !== "assistant") return - const content = props.content - if (!content || content === state.lastOutput) return - - if (state.lastPartText.length === 0) { - const newContent = content.slice(state.lastOutput.length) - if (newContent) { - process.stdout.write(newContent) - } - } - state.lastOutput = content state.hasReceivedMeaningfulWork = true } diff --git a/src/cli/run/types.ts b/src/cli/run/types.ts index 2d2a50e62..e23861582 100644 --- a/src/cli/run/types.ts +++ b/src/cli/run/types.ts @@ -44,8 +44,13 @@ export interface SessionStatusProps { } export interface MessageUpdatedProps { - info?: { sessionID?: string; role?: string } - content?: string + info?: { + sessionID?: string + role?: string + modelID?: string + providerID?: string + agent?: string + } } export interface MessagePartUpdatedProps {