fix(proxy): rescue leaked tool-call XML + honor Anthropic tool_choice#7
Merged
Merged
Conversation
Kiro's backend occasionally emits a model's tool call as plain text in assistantResponseEvent (the raw <function_calls>/<invoke>/<parameter> XML, sometimes with the <function_calls> open tag corrupted to "count"), split across streaming frames. The old path passed text through untouched, so the XML leaked to users as visible text and the client never received a structured tool_use -- the tool was never executed and the agent task stalled. Add a stateful cross-frame filter (proxy/tool_leak_filter.go) that: - buffers assistant text and splits normal text from leaked tool XML - restores bool/int/float/null types while preserving raw strings - holds back partial trailing tags at frame boundaries - at stream end, dedups rescued tools against structured toolUseEvents already seen (same name+input dropped) and injects the rest as synthetic tool_use blocks Wired into parseEventStream and gated by KIRO_TOOL_LEAK_FIX (default on, "off" to bypass) and KIRO_TOOL_LEAK_DEBUG=1. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Kiro's backend has no native tool_choice concept, so translate the
Anthropic semantics during ClaudeToKiro:
- "none": omit all tools so the model cannot call any (text-only turn)
- "any": keep tools and append a backend directive requiring at least
one tool call this turn
- {"type":"tool","name":X}: append a directive naming the specific tool,
resolving the client name to the sanitized Kiro tool name
Adds claudeToolChoiceTypeAndName (handles string / json.RawMessage / map
/ arbitrary shapes), buildClaudeToolChoiceDirective,
resolveKiroToolChoiceName, and appendBackendDirective, plus tests for
the any / tool / none cases.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
本 PR 移植自上游 Kiro-Go PR Quorinex#114,包含两个独立改动(各一个 commit):
1. fix: 救回泄漏成文本的工具调用 XML
Kiro 后端偶发故障,会把本该走结构化
toolUseEvent通道的工具调用,错误地当作普通文本塞进assistantResponseEvent。泄漏出来的是 Anthropic 风格的<function_calls>/<invoke>/<parameter>XML(<function_calls>有时损坏成纯文本count),且可能跨多个流式帧分片。结果是:原始 XML 泄漏成可见脏文本,客户端拿不到结构化 tool_use → 工具不执行、Agent 任务中断。修复:新增有状态的跨帧过滤器
proxy/tool_leak_filter.go,接入parseEventStream:<invoke>为结构化 tool_use,还原 bool/int/float/null 类型(字符串保留原始空白)KIRO_TOOL_LEAK_FIX=off回退直通,KIRO_TOOL_LEAK_DEBUG=1打印调试日志2. feat: 支持 Anthropic tool_choice(Claude 路径)
Kiro 后端无原生
tool_choice概念,本改动在ClaudeToKiro中模拟其语义:none→ 不向 Kiro 发送任何工具any→ 照常发工具,并在用户消息追加指令强制模型调用至少一个工具tool→ 同上,并把指定工具名解析为 sanitized Kiro 名后点名要求调用Test plan
go build ./...通过go vet ./...通过Notes
convertClaudeTools为单参;本仓库已演进为双参(带ToolDescReplaceRules),合并时已适配,工具描述替换行为不变。🤖 Generated with Claude Code