[Bug]: 流式工具调用续片带空串 id/name 时累加器丢弃参数片段,导致 "Arguments are invalid JSON"
Les mainteneurs répondent en général sous 1 jour
@wsp1911 y travaille déjà.
Depuis le 8/10/2026.
Évaluation
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Accessibilité débutants
- 72/100
Piste de recherche
Start with the openbitfun_agent_stream::tool_call_accumulator mentioned in the issue and inspect how streaming tool-call continuations are matched to existing calls. Reproduce with chunks whose continuation has empty id and name, then verify that arguments are accumulated by index and form valid JSON; compare with continuations where those fields are omitted. Done when both forms work without invalid-JSON retries.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
简述
部分按 OpenAI 流式规范分片发送工具调用参数、且续片把 id/name 写成空字符串 "" 的模型(如 glm-5.2),其工具调用会被 tool_call_accumulator 判定为 Arguments are invalid JSON. 而整轮失败重试。根因不在模型:模型实际发出了合法 JSON,但累加器只保留了每个工具调用的第一片 {,后续参数片段被丢弃。
环境
- OpenBitFun Desktop: 1.0.1(Windows)
- 模型:
glm-5.2(provider: sensenova,OpenAI 兼容流式) - 出现会话:
20260923T213930、20260924T163057(前者参数解析失败 9 次,后者 8 次)
复现
让 glm-5.2 在一轮里并行发起两个工具调用(如 ExecCommand + Glob)。app.log 出现:
[ERROR][openbitfun_agent_stream::tool_call_accumulator] Tool call arguments parsing failed at boundary=finish_reason: tool_id=call_9072c7daa3af466782cee2ea, tool_name=Glob, raw_len=1, error=EOF while parsing an object at line 1 column 1, parse_error_category=eof, parse_error_is_eof=true, completion=Unknown
[ERROR][openbitfun_agent_stream] SSE Error: Has invalid tool calls
[ERROR][openbitfun_core::agentic::tools::pipeline::tool_pipeline] Tool execution failed: error=Validation error: Arguments are invalid JSON.
[WARN][openbitfun_core::agentic::execution::round_executor] Retrying stream because provider returned only invalid tool arguments: ... local_retry=1/10
关键:raw_len=1 —— 累加器里每个工具调用只剩 1 个字符 {。
根因(SSE 证据)
模型把同一工具调用的 arguments 拆成多个 SSE chunk 发送,首片带 id/name,续片把它们写成空串:
17: tool_calls[0] id="call_b45..." name="ExecCommand" arguments="{"
18: tool_calls[0] id="" name="" arguments="\"cmd\": "
19: tool_calls[0] id="" name="" arguments="\"Get-"
...(续片累积命令字符串)
28: tool_calls[0] id="" name="" arguments="\"}"
29: tool_calls[1] id="call_907..." name="Glob" arguments="{"
30: tool_calls[1] id="" name="" arguments="\"pattern\": "
33: tool_calls[1] id="" name="" arguments="}"
34: finish_reason="tool_calls"
把续片 arguments 顺序拼接,得到的是合法 JSON:
- ExecCommand →
{"cmd": "Get-Date; Write-Output \"PowerShell 工具运行正常"} - Glob →
{"pattern": "*.md"}
但累加器只保留了首片的 {,续片全部丢失 → 解析到 EOF while parsing an object at line 1 column 1。
为什么"有些模型"出问题(对比)
同一台机器上 qwen3.8-27b-uncensored 基本正常。其续片是把 id/name 字段省略(而非空串):
"tool_calls":[{"index":0,"type":"function","function":{"arguments":"{"}}]
"tool_calls":[{"index":0,"type":"function","function":{"arguments":"\"file_path\":"}}]
glm-5.2 的续片则是空串:
"tool_calls":[{"index":0,"id":"","type":"function","function":{"name":"","arguments":"\"cmd\": "}}]
两种写法都符合 OpenAI 流式语义,但实现细节不同:省略字段 → serde 反序列化为 None,累加器走续片追加分支(正常);空串 "" → 累加器按 id 查归属工具调用,查不到(真 id 是 call_xxx),于是丢弃该参数片段,缓冲区永远停在 {。
(注:9/21 那次 qwen 的唯一失败是另一类:boundary=graceful_shutdown、raw_len=67、completion=Interrupted,是流被中途打断导致参数真的截断,且已累积到 67 字符,反证 qwen 的累加本身是工作的。)
期望行为
续片无论 id/name 是省略还是空串,都应视为"无 id/无 name"的续片,按 index 追加到对应工具调用的参数缓冲区。两种写法都应正确合并出完整 JSON。
修复建议(openbitfun_agent_stream::tool_call_accumulator)
- 续片归属应按
index匹配,而不是按id;或 - 当
id为空串 /name为空串时,等价于None,走续片追加分支,而非当成新 id 去查表。
影响范围
凡按 OpenAI 规范分片发送 arguments、且续片带空串 id/name 的模型都会 100% 失败并触发整轮重试(local_retry 最多 10 次)。续片字段被省略的模型不受影响。已用本机真实 SSE 流量验证(上述日志片段为原始截取,仅脱敏用户路径)。
- Langage dominant
- Rust
- Étoiles
- 2.3k
- Forks
- 236
- Merge moyen
- 3 h 47 min
- PR mergées (30 j)
- 264
Préparer son environnement
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de GCWing/OpenBitFun
-
[Feature]: 模型服务表单缺少「图像生成」分类入口 —— 后端已支持 default_models.image_generationPeut-être pris @skyfireitdiy l’a pris il y a 2 jours. Ouverte
Difficulté 2/5 Une demi-journée Accessibilité débutants 74/100
GCWing/OpenBitFun#3279 · 1 réaction ·
Les mainteneurs répondent en général sous 1 jour
-
[Bug]: 界面写“敏感诊断信息默认关闭”,但后端配置当前实际默认是 truePeut-être pris @xiechimon l’a pris il y a 24 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
GCWing/OpenBitFun#3213 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
GCWing/OpenBitFun#2363 ·
Les mainteneurs répondent en général sous 1 jour
-
question
Difficulté 1/5 Moins d'une heure Accessibilité débutants 78/100
GCWing/OpenBitFun#2340 ·
Les mainteneurs répondent en général sous 1 jour
-
[Bug]: 本地wsl 不能访问文件目录Ouverte
Difficulté 3/5 1-2 jours Accessibilité débutants 45/100
GCWing/OpenBitFun#3435 ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de GCWing/OpenBitFun
Issues similaires
-
The book has a Nix install section that chelis.ch lacks, and it names two of the three systemsOuvertearea:ecosystem documentation
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Chelis-Lang/chelis#3866 ·
Les mainteneurs répondent en général sous 1 jour
-
[安卓Feature]: 数字键盘左侧符号区域大小优化Ouverteenhancement
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
metasequoiaime/msime#8620 ·
Les mainteneurs répondent en général sous 1 jour
-
agent-detection macos p2 triaged
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
Les mainteneurs répondent en général sous 1 jour
-
bug documentation sev-0
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 86/100
Les mainteneurs répondent en général sous 1 jour