fix(claude-code-cli): render tool calls above text response
- Filter toolcall_start/delta/end events from streaming to prevent out-of-order rendering in the TUI's accumulated message content - Collect tool calls from intermediate SDK turns and include them BEFORE text content in the final AssistantMessage - The agent loop's externalToolExecution path emits proper tool_execution_start/end events for each intermediate tool call - Result: tool activity renders above the text response, not below Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a0ee03d331
commit
bbea8460b5
1 changed files with 27 additions and 8 deletions
|
|
@ -147,6 +147,8 @@ async function pumpSdkMessages(
|
|||
/** Track the last text content seen across all assistant turns for the final message. */
|
||||
let lastTextContent = "";
|
||||
let lastThinkingContent = "";
|
||||
/** Collect tool calls from intermediate SDK turns for tool_execution events. */
|
||||
const intermediateToolCalls: AssistantMessage["content"] = [];
|
||||
|
||||
try {
|
||||
// Dynamic import — the SDK is an optional dependency.
|
||||
|
|
@ -225,7 +227,14 @@ async function pumpSdkMessages(
|
|||
|
||||
const assistantEvent = builder.handleEvent(event);
|
||||
if (assistantEvent) {
|
||||
stream.push(assistantEvent);
|
||||
// Skip toolcall events — the agent loop's externalToolExecution
|
||||
// path emits tool_execution_start/end events after streamSimple
|
||||
// returns. Streaming toolcall events would render tool calls
|
||||
// out of order in the TUI's accumulated message content.
|
||||
const t = assistantEvent.type;
|
||||
if (t !== "toolcall_start" && t !== "toolcall_delta" && t !== "toolcall_end") {
|
||||
stream.push(assistantEvent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -251,13 +260,16 @@ async function pumpSdkMessages(
|
|||
const userMsg = msg as SDKUserMessage;
|
||||
if (userMsg.parent_tool_use_id !== null) break;
|
||||
|
||||
// Capture accumulated text from the builder before resetting
|
||||
// Capture content from the completed turn before resetting
|
||||
if (builder) {
|
||||
for (const block of builder.message.content) {
|
||||
if (block.type === "text" && block.text) {
|
||||
lastTextContent = block.text;
|
||||
} else if (block.type === "thinking" && block.thinking) {
|
||||
lastThinkingContent = block.thinking;
|
||||
} else if (block.type === "toolCall") {
|
||||
// Collect tool calls for externalToolExecution rendering
|
||||
intermediateToolCalls.push(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -269,15 +281,22 @@ async function pumpSdkMessages(
|
|||
case "result": {
|
||||
const result = msg as SDKResultMessage;
|
||||
|
||||
// Build final message with all content from the last assistant turn.
|
||||
// Tool calls are preserved — the agent loop's externalToolExecution
|
||||
// mode handles them without local dispatch.
|
||||
let finalContent: AssistantMessage["content"] = [];
|
||||
// Build final message. Include intermediate tool calls so the
|
||||
// agent loop's externalToolExecution path emits tool_execution
|
||||
// events for proper TUI rendering, followed by the text response.
|
||||
const finalContent: AssistantMessage["content"] = [];
|
||||
|
||||
// Add tool calls from intermediate turns first (renders above text)
|
||||
finalContent.push(...intermediateToolCalls);
|
||||
|
||||
// Add text/thinking from the last turn
|
||||
if (builder && builder.message.content.length > 0) {
|
||||
finalContent = [...builder.message.content];
|
||||
for (const block of builder.message.content) {
|
||||
if (block.type === "text" || block.type === "thinking") {
|
||||
finalContent.push(block);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fall back to captured text from complete assistant messages
|
||||
if (lastThinkingContent) {
|
||||
finalContent.push({ type: "thinking", thinking: lastThinkingContent });
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue