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
This commit is contained in:
justsisyphus
2026-01-30 11:45:58 +09:00
parent c905e1cb7a
commit 30f893b766
3 changed files with 24 additions and 27 deletions

View File

@@ -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)
})

View File

@@ -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
}

View File

@@ -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 {