反馈 / #2037
#2037 serve: tool_call_recovery misses fenced JSON inside an explicit tool-call wrapper
open · @bettercallcaleb · 0 评论 · 去 GitHub 看
说明
## Summary
With `tool_call_recovery` enabled, Strata recovers JSON for a declared tool inside an explicit `<tool_call>` wrapper, but fails to recognize the same JSON if the model wraps it in a Markdown ```json fence. The response is emitted as regular content, with no `tool_call`.
This is a code-fence handling issue, **not** a JSON-string escaping issue: literal backticks inside a JSON string work in the unfenced case.
## Reproduction (parser-only; no model required)
````python
import json
from serve.frontend import OutputParser
tools = [
{
"name": "write_file",
"parameters": {
"type": "object",
"properties": {"content": {"type": "string"}},
},
}
]
payload = json.dumps({
"name": "write_file",
"arguments": {"content": "hello `world`"},
})
cases = {
"bare": f"<tool_call>\n{payload}\n</tool_call>",
"fenced": f"<tool_call>\n```json\n{payload}\n```\n</tool_call>",
}
for name, raw in cases.items():
parser = OutputParser(thinking=False, tools=tools, recover=True)
events = parser.feed(raw) + parser.finish()
calls = [event.call.arguments for event in events if event.kind == "tool_call"]
print(name, calls)
````
## Actual
```text
bare [{'content': 'hello `world`'}]
fenced []
```
The fenced case instead emits the wrapper and fenced JSON as `content`, without an error. Reproduced against the current `serve/frontend.py` on `main` with whole-input, 1-character, and 7-character chunks, both `stream_tools=False` and `True`.
## Expected
When recovery is **explicitly enabled**, an otherwise valid JSON call for a declared tool inside an explicit `<tool_call>` wrapper should either be recovered despite an optional Markdown JSON fence, or produce a clear diagnostic. It should not silently become a normal assistant reply.
Fenced JSON in ordinary prose/reasoning must **remain text**, not execute as a tool call. Any recovery should be narrowly scoped to the explicit wrapper and a declared tool.
## Where
- `serve/frontend.py`: `OutputParser._follower()` recognizes JSON only when the text following `<tool_call>` begins with `{`.
- Related to the opt-in recovery behavior in #1172; the quote/fence safeguards from #1058 should remain intact.
本站相关内容
相关页面的快捷入口。