09473fa7ed
* .NET: Bind tool-approval responses to surfaced approval requests Harden the tool-approval flow so an approved tool call always matches the request the framework surfaced for approval. Add ApprovalResponseBindingChatClient as the outermost decorator above FunctionInvokingChatClient. It records each model-originated ToolApprovalRequestContent in the session state and, on the next request, binds every ToolApprovalResponseContent to its recorded request: the response tool call is rebound to the recorded call, matched entries are consumed for one-time use, and only approvals tied to a framework-issued request take effect. Apply the same binding in the ToolApprovalAgent harness by tracking the requests it surfaces and binding collected responses to them during a queue cycle. Add ChatClientAgentOptions.DisableApprovalResponseBinding (default off) and a UseApprovalResponseBinding builder extension for custom chat client stacks. Includes unit tests for the decorator and the harness. * .NET: Bind approval responses once per turn and avoid re-enumeration Address review feedback on the approval-response binding decorator: consume a matched request from the per-turn lookup so a duplicate response with the same request id in one turn is honored only once, and return the materialized message list instead of the original enumerable so a single-use sequence is not enumerated twice. Rename the local pending list to pendingRequests for clarity. Adds a duplicate-response regression test. * .NET: Snapshot recorded approval requests and consume duplicates in the harness Address review feedback on ToolApprovalAgent: store a snapshot of each surfaced/pending approval request (cloned tool call with a copied arguments dictionary) so a later mutation of the caller-visible instance cannot change the recorded call used to bind the response, and consume a surfaced request on match so a duplicate response with the same request id in one pass is honored only once. Apply both symmetrically in the harness and the ApprovalResponseBindingChatClient decorator. Adds regression tests for the snapshot and duplicate-response cases. * .NET: Address review feedback on approval-response binding - Harness: store surfaced approval requests in a dictionary and consume matches directly, drop the extra hashset and the redundant record-time dedup; replace clear-on-resolution with a debug assert. - Harness pipeline: add UseApprovalResponseBinding() as the outermost decorator in HarnessAgent (it uses UseProvidedChatClientAsIs) behind a new DisableApprovalResponseBinding option, with tests. - Decorator: avoid message/content allocations when nothing changes, keep the original content when a response already matches the recorded call, clear pending each inbound turn, and shorten helpers. * .NET: Compare tool calls by fields instead of serializing Replace the JSON-serialization comparison in the approval-response binding decorator with a direct field comparison. Fast-path FunctionCallContent by comparing CallId, Name, and arguments field by field; any other tool call shape rebinds. The comparison only skips an allocation (the call is always rebound to the recorded request otherwise), so a miss just triggers a safe rebuild. Adds a test that a matching response is forwarded unchanged. * .NET: Bind approval responses against requests present in history Fix a merge-queue regression where AG-UI mixed server/client tool invocation stopped executing the server tool. The binding decorator validated approval responses only against its own recorded pending state, so a matched approval request/response pair replayed from conversation history was treated as unbound and dropped, and the auto-approved server tool never ran. Treat known requests as the recorded pending state plus any approval requests already present in the current messages, and stop dropping approval requests (a request in history is the pairing authority). A response with no known request anywhere is still dropped, so a forged approval cannot execute. Also address review feedback: return the mutable contents buffer from a helper instead of a null-forgiving operator, and use clearer naming (PrepareMutableContentsBuffer / mutableContentsBuffer). Adds regression tests for a request in history and a response bound to a history request with empty pending state.