MCPcopy Create free account
hub / github.com/Zoo-Code-Org/Zoo-Code / flushPendingToolResultsToHistory

Method flushPendingToolResultsToHistory

src/core/task/Task.ts:935–997  ·  view source on GitHub ↗

* Flush any pending tool results to the API conversation history. * * This is critical when the task is about to be * delegated (e.g., via new_task). Before delegation, if other tools were * called in the same turn before new_task, their tool_result blocks are * accumulated in `userMessage

()

Source from the content-addressed store, hash-verified

933 * So we usually only need to flush the pending user message with tool_results.
934 */
935 public async flushPendingToolResultsToHistory(): Promise<boolean> {
936 // Only flush if there's actually pending content to save
937 if (this.userMessageContent.length === 0) {
938 return true
939 }
940
941 // CRITICAL: Wait for the assistant message to be saved to API history first.
942 // Without this, tool_result blocks would appear BEFORE tool_use blocks in the
943 // conversation history, causing API errors like:
944 // "unexpected `tool_use_id` found in `tool_result` blocks"
945 //
946 // This can happen when parallel tools are called (e.g., update_todo_list + new_task).
947 // Tools execute during streaming via presentAssistantMessage, BEFORE the assistant
948 // message is saved. When new_task triggers delegation, it calls this method to
949 // flush pending results - but the assistant message hasn't been saved yet.
950 //
951 // The assistantMessageSavedToHistory flag is:
952 // - Reset to false at the start of each API request
953 // - Set to true after the assistant message is saved in recursivelyMakeClineRequests
954 if (!this.assistantMessageSavedToHistory) {
955 await pWaitFor(() => this.assistantMessageSavedToHistory || this.abort, {
956 interval: 50,
957 timeout: 30_000, // 30 second timeout as safety net
958 }).catch(() => {
959 // If timeout or abort, log and proceed anyway to avoid hanging
960 console.warn(
961 `[Task#${this.taskId}] flushPendingToolResultsToHistory: timed out waiting for assistant message to be saved`,
962 )
963 })
964 }
965
966 // If task was aborted while waiting, don't flush
967 if (this.abort) {
968 return false
969 }
970
971 // Save the user message with tool_result blocks
972 const userMessage: Anthropic.MessageParam = {
973 role: "user",
974 content: this.userMessageContent,
975 }
976
977 // Validate and fix tool_result IDs when the previous *effective* message is an assistant message.
978 const effectiveHistoryForValidation = getEffectiveApiHistory(this.apiConversationHistory)
979 const lastEffective = effectiveHistoryForValidation[effectiveHistoryForValidation.length - 1]
980 const historyForValidation = lastEffective?.role === "assistant" ? effectiveHistoryForValidation : []
981 const validatedMessage = validateAndFixToolResultIds(userMessage, historyForValidation)
982 const userMessageWithTs = { ...validatedMessage, ts: Date.now() }
983 this.apiConversationHistory.push(userMessageWithTs as ApiMessage)
984
985 const saved = await this.saveApiConversationHistory()
986
987 if (saved) {
988 // Clear the pending content since it's now saved
989 this.userMessageContent = []
990 } else {
991 console.warn(
992 `[Task#${this.taskId}] flushPendingToolResultsToHistory: save failed, retaining pending tool results in memory`,

Calls 4

getEffectiveApiHistoryFunction · 0.90
warnMethod · 0.65

Tested by

no test coverage detected