Skip to content

Commit cd3b8d1

Browse files
committed
Fix tool calling UI rounds
1 parent fcf74bd commit cd3b8d1

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

ui/src/pages/chat/useChat.ts

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -875,9 +875,11 @@ export function useChat({
875875
reasoningContent = event.text;
876876
streamingStore.setReasoningContent(storeKey, reasoningContent);
877877
} else if (event.type === "response.output_text.done" && event.text) {
878-
// Use the final text from done event
878+
// Use the final text from done event for the local content.
879+
// Don't call setContent on the streaming store — appendContent
880+
// already accumulated the right content, and setContent would
881+
// overwrite content from earlier rounds in multi-round tool use.
879882
content = event.text;
880-
streamingStore.setContent(storeKey, content);
881883
} else if (event.type === "response.output_item.done" && event.item) {
882884
// Handle file_search_call output items (server-side file search)
883885
if (event.item.type === "file_search_call" && event.item.results) {
@@ -983,7 +985,7 @@ export function useChat({
983985
?.filter((c) => c.type === "output_text")
984986
.map((c) => c.text || "")
985987
)
986-
.join("");
988+
.join("\n\n---\n\n");
987989

988990
// If no output_text, try to extract from reasoning content (for reasoning models)
989991
// This is useful for modes like "elected" where we need to parse a vote number
@@ -1326,8 +1328,17 @@ export function useChat({
13261328
}
13271329
}
13281330

1329-
// Accumulate content
1330-
accumulatedContent = result.content; // Use latest content (continuation replaces)
1331+
// Accumulate content across rounds with separator.
1332+
// Skip reasoning-only rounds (where content was set from reasoning fallback
1333+
// rather than actual output text — e.g., rounds that only call display_artifacts).
1334+
const isActualOutput = result.content && result.content !== result.reasoningContent;
1335+
if (isActualOutput) {
1336+
if (accumulatedContent) {
1337+
accumulatedContent += "\n\n---\n\n" + result.content;
1338+
} else {
1339+
accumulatedContent = result.content;
1340+
}
1341+
}
13311342
lastReasoningContent = result.reasoningContent;
13321343

13331344
// Accumulate usage (sum tokens across iterations)
@@ -1538,6 +1549,14 @@ export function useChat({
15381549

15391550
// Clear tool calls from streaming store before next iteration
15401551
streamingStore.clearToolCalls(storeKey);
1552+
1553+
// Add separator to streaming store so the next round's appendContent
1554+
// builds on top of the accumulated content with a visual break.
1555+
// Only add if this round had actual text output (avoid double separators
1556+
// from rounds that only had tool calls with no text).
1557+
if (isActualOutput) {
1558+
streamingStore.appendContent(storeKey, "\n\n---\n\n");
1559+
}
15411560
}
15421561

15431562
// Complete debug capture successfully

0 commit comments

Comments
 (0)