Repository navigation
Conversation
`ToolExecutionDelegate.pendingMessages(in:)` is asked after each round of tool calls, before the model's next request, and returns `[Prompt]`, so a message can carry images. Someone can steer a long response while it runs. The default adds nothing. Each message's prompt entry is built once, by shared code (`pendingPrompts`), and every provider whose tool loop continues after a round sends it with the same conversion it replays a transcript's prompts with, as huggingface#325 does for tool calls: the request is the same now and when a later response replays it, so a prompt cache still matches. That's OpenAI (Chat Completions and Responses), Open Responses, Gemini, MLX and llama.cpp, and Anthropic's and Ollama's streaming loops; their nonstreaming responses make one request. `SystemLanguageModel` documents that it doesn't ask, as Foundation Models runs its own tool loop. Steering doesn't reset the tool-round limit. Messages the delegate has handed over are the response's: if it fails, they follow the session's `transcriptErrorHandlingPolicy` like its other entries, which the method's documentation says. Messages still waiting when a response ends without another round stay with the app, which can send them next. Resolves huggingface#360. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4WBsc1Jp8fGufe89MhQFB
gtokman
added a commit
to gtokman/AnyLanguageModel
that referenced
this pull request
Oct 29, 2026
`ToolExecutionDelegate.pendingMessages(in:)` returns `[Prompt]` rather than `[String]`, as huggingface#376 has it. Each message's prompt entry is built once, with the prompt's own transcript segments, and sent with the same conversion as the transcript's prompts, so a photo sent while a response runs goes with its message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B4WBsc1Jp8fGufe89MhQFB
mattt
reviewed
Oct 29, 2026
mattt
left a comment
Collaborator
There was a problem hiding this comment.
Thanks, @gtokman. This follows what we discussed on #360, and returning [Prompt] works out nicely.
Two non-blocking notes:
- The description says the message is byte-for-byte the same in flight and on replay, but the test compares decoded dictionaries. Either is fine with me; the test and the description should just agree.
- The round-limit test could also check that the error's transcript entries include the steering prompt.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #360.
ToolExecutionDelegate.pendingMessages(in:)is asked after each round of tool calls, before the model's next request. Someone can steer a long response while it runs. The policy around it (an inbox, an acknowledgment, what interrupts the final text) stays in the app. The default adds nothing.Following your notes on the issue:
[Prompt], so a message can carry images.SystemLanguageModeldoesn't ask, since Foundation Models runs its own tool loop, and the method's documentation says so.pendingPrompts(Shared/PendingMessages.swift). Each provider sends it with the same conversion it replays a transcript's prompts with, pulled into one function where that was inline, as Replay OpenAI tool calls as plain, stable JSON #325 does for tool calls. A request made now and the replay of it on a later turn match, so a prompt cache still matches.transcriptErrorHandlingPolicylike its other entries, and they aren't handed back.Tests
The full suite has the same failures as
mainhere: the 13 tests that need live services.This touches some of the files #375 does, and the two branches merge cleanly in either order.
🤖 Generated with Claude Code
https://claude.ai/code/session_01B4WBsc1Jp8fGufe89MhQFB