Recover tool calls wrapped in a markdown code fence
还没有人认领这个 Issue。
评估
调研方向
从 internal/agent/agent.go 中的 normalizeMessage 开始,strings.HasPrefix(stripped, "{") 守卫和 <tool_call> 分支决定内容是否为工具调用。在该判断之前添加一个小步骤:去掉开头和结尾的三重反引号围栏,再次修剪空白,然后交给现有逻辑处理。完成标准是:internal/agent/agent_test.go 中的新用例通过,Turn 对带围栏的 JSON 返回 Rounds == 1,并且纯文本及非工具调用围栏的测试保持不变。
由索引模型根据 Issue 内容生成。
描述
What
normalizeMessage recovers tool calls a model writes as plain text, but the entry guard only accepts content whose trimmed form starts with { or <tool_call>. When a model wraps the JSON in a markdown code fence (```json ... ```), the guard bails out and the call is silently dropped — rounds=0, and the raw JSON (or the fence) gets printed to the user as if it were the answer.
Evidence
Real qwen2.5-coder:7b session, prompted to run a command:
great now can you run a command in the terminal to echo the contents of job.go?
stats rounds=0 prompt_tok=1456 ...
{"name": "run_command", "arguments": {"command": "cat", "arguments": ["job.go"]}}
The call is well-formed and safe to run (it would hit the confirmation prompt). It is only missed because of the ```json prefix.
Where
internal/agent/agent.go, normalizeMessage — the strings.HasPrefix(stripped, "{") guard and the <tool_call> branch.
Proposed fix
Before the existing gate, strip a markdown code fence if present:
- If the trimmed content starts with three backticks, drop that first line (the fence plus an optional language tag such as
jsonorjson5), and drop a trailing three-backtick line if present. - Then
TrimSpaceand fall through to the current logic. - Handle the fence appearing around or inside
<tool_call>tags too, whichever ordering is simplest.
Keep the "starts with {" requirement after stripping — that is what keeps prose safe.
Acceptance criteria
- A fenced JSON tool call runs through
Turn(Rounds == 1) and reaches the tool with the correct arguments. - New tests in
internal/agent/agent_test.go: fenced withjsontag, fenced bare, fenced with trailing fence, fenced inside<tool_call>. - Existing negative cases still pass untouched: prose, and a fenced block that is not a tool call.
go build ./...,go vet ./...,go test ./..., andgofmt -l .all clean.
Notes
- Keep it a small, separate branch in
normalizeMessage, matching the style there. - Do not loosen the guard to "content contains
{anywhere" — that would turn any answer containing a JSON snippet into a tool call.
- 主要语言
- Go
- 星标
- 1
- 派生
- 2
- 平均合并
- 1 小时 31 分钟
- 30 天内合并 PR
- 7
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
Edwin-metcalf/MetCode 的其他 Issue
-
documentation enhancement help wanted
难度 2/5 1-3 小时 新手友好度 62/100
Edwin-metcalf/MetCode#19 ·
-
enhancement good first issue
难度 2/5 1-3 小时 新手友好度 68/100
Edwin-metcalf/MetCode#16 ·
-
testing
难度 2/5 1-3 小时 新手友好度 88/100
Edwin-metcalf/MetCode#9 ·
-
Add a Makefile未关闭enhancement good first issue help wanted
难度 2/5 1-3 小时 新手友好度 76/100
Edwin-metcalf/MetCode#8 ·
-
enhancement
难度 2/5 1-3 小时 新手友好度 84/100
Edwin-metcalf/MetCode#7 ·
查看 Edwin-metcalf/MetCode 的全部 Issue
相似的 Issue
-
area/import kind/bug
难度 2/5 1-3 小时 新手友好度 62/100
维护者通常 1 天内回复
-
kind/documentation
难度 2/5 1-3 小时 新手友好度 80/100
kubernetes-sigs/dra-driver-nvidia-gpu#1569 ·
维护者通常 1 天内回复
-
clawsweeper:fix-shape-clear clawsweeper:queueable-fix clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster no-stale P2
难度 2/5 1-3 小时 新手友好度 65/100
openclaw/openclaw-enterprise#2571 · 1 条评论 · 1 个 reaction ·
维护者通常 1 天内回复
-
难度 1/5 1-3 小时 新手友好度 72/100
-
难度 2/5 1-3 小时 新手友好度 72/100
维护者通常 1 天内回复