Show sleep history as wait status

This commit is contained in:
murashit 2026-06-19 10:44:49 +09:00
parent 357a6d9f9f
commit 6f0fb20bdb
6 changed files with 24 additions and 9 deletions

View file

@ -273,11 +273,9 @@ function imageViewMessageStreamItem(item: ImageViewItem, turnId?: string): Messa
function sleepMessageStreamItem(item: SleepItem, turnId?: string): MessageStreamItem {
return {
...turnItemSourceFields(item, turnId),
kind: "tool",
kind: "wait",
role: "tool",
toolName: "sleep",
primaryTarget: { kind: "value", value: `${String(item.durationMs)} ms` },
output: "",
text: `Waited ${durationLabel(item.durationMs)}`,
executionState: "completed",
};
}
@ -569,3 +567,9 @@ function jsonTargetPrimitive(value: unknown): string | null {
function executionStateFromStatus(status: string, states: ExecutionStateByStatus): ExecutionState {
return states[status] ?? null;
}
function durationLabel(durationMs: number): string {
if (durationMs < 1000) return `${String(durationMs)}ms`;
if (durationMs % 1000 === 0) return `${String(durationMs / 1000)}s`;
return `${String(durationMs / 1000)}s`;
}

View file

@ -10,6 +10,7 @@ export type MessageStreamItemKind =
| "agent"
| "hook"
| "reasoning"
| "wait"
| "contextCompaction"
| "system"
| "goal"
@ -246,6 +247,12 @@ interface ContextCompactionMessageStreamItem extends MessageStreamBase {
readonly role: "tool";
}
interface WaitMessageStreamItem extends MessageStreamBase {
readonly kind: "wait";
readonly role: "tool";
readonly text: string;
}
interface TaskProgressStep {
readonly step: string;
readonly status: "pending" | "inProgress" | "completed";
@ -304,6 +311,7 @@ export type MessageStreamItem =
| ToolCallMessageStreamItem
| HookMessageStreamItem
| ReasoningMessageStreamItem
| WaitMessageStreamItem
| ContextCompactionMessageStreamItem
| TaskProgressMessageStreamItem
| AgentMessageStreamItem

View file

@ -85,6 +85,8 @@ function meaningForMessageStreamItem(item: MessageStreamItem): MessageStreamMean
return { plane: "execution", event: "evidence" };
case "reasoning":
return { plane: "execution", event: "progress" };
case "wait":
return { plane: "execution", event: "progress" };
case "taskProgress":
return { plane: "execution", event: "progress" };
case "agent":

View file

@ -19,6 +19,7 @@ export function messageStreamRenderFamily(classification: MessageStreamSemanticC
return "detail";
case "taskProgress":
case "reasoning":
case "wait":
case "contextCompaction":
return "status";
}

View file

@ -683,7 +683,7 @@ describe("turn item conversion preserves app-server semantics", () => {
});
});
it("preserves sleep items as completed wait tool summaries", () => {
it("preserves sleep items as completed wait status summaries", () => {
const item: TurnItem = {
type: "sleep",
id: "sleep-1",
@ -691,10 +691,8 @@ describe("turn item conversion preserves app-server semantics", () => {
};
expect(messageStreamItemFromTurnItem(item, "t1")).toMatchObject({
kind: "tool",
toolName: "sleep",
primaryTarget: { kind: "value", value: "2500 ms" },
output: "",
kind: "wait",
text: "Waited 2.5s",
executionState: "completed",
});
});

View file

@ -79,6 +79,7 @@ describe("message stream semantic classification", () => {
{ id: "tool", kind: "tool", role: "tool", text: "tool", toolCall: { arguments: { k: "v" } } },
{ id: "hook", kind: "hook", role: "tool", text: "hook" },
{ id: "reasoning", kind: "reasoning", role: "tool", text: "thinking" },
{ id: "wait", kind: "wait", role: "tool", text: "Waited 2.5s", executionState: "completed" },
]);
expect(semantic.map(({ meaning }) => meaning)).toEqual([
@ -87,6 +88,7 @@ describe("message stream semantic classification", () => {
{ plane: "execution", event: "evidence" },
{ plane: "execution", event: "evidence" },
{ plane: "execution", event: "progress" },
{ plane: "execution", event: "progress" },
]);
});