From e6eebbc9ad77289e87c60eae0804bfc9751b948a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 29 May 2026 12:20:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(web):=20tool=5Fcall=20=E6=A0=87=E9=A2=98?= =?UTF-8?q?=E8=A1=8C=E6=94=B9=E6=98=BE=E4=B8=AD=E6=96=87=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=20+=20=E4=BF=AE=20args=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dev.html 实时流读 ev.data.arguments 但后端 emit 的是 args,字段名对不上 导致参数永远为空、连带 artifact 路径提取失效。新增 toolActivityLabel 按 12 个工具的关键参数套中文动词(执行命令/运行 Python/读写编辑文件/查找搜索 /联网搜索/抓取网页/加载技能/生成图像视频),实时流与历史回放两处同步;完整 参数仍在折叠
 里。

Co-Authored-By: Claude Opus 4.8 (1M context) 
---
 PROGRESS.md         |  3 ++-
 web/static/dev.html | 40 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/PROGRESS.md b/PROGRESS.md
index 6c8ff57..6986d80 100644
--- a/PROGRESS.md
+++ b/PROGRESS.md
@@ -2,7 +2,7 @@
 
 > 配合 `DESIGN.md`。本文件只记 phase 状态、决策偏差、文件量、下一步。每条 1-2 句:做了啥 + 关键判断;细节查 `git log` / `git diff` / `DESIGN §7.9`。
 
-最后更新:2026-05-29(删 docker exec argv 里的 setsid 修延迟 stdout 丢失 + `_run_subprocess` 重写修 communicate poll loop bug + 3 个 SKILL.md sandbox 凭证可用性校准)
+最后更新:2026-05-29(删 docker exec argv 里的 setsid 修延迟 stdout 丢失 + `_run_subprocess` 重写修 communicate poll loop bug + 3 个 SKILL.md sandbox 凭证可用性校准 + web 端 tool_call 标题行改显中文活动描述并修 args 字段 bug)
 
 ---
 
@@ -23,6 +23,7 @@
 
 ### 2026-05-29
 
+- **web 端 tool_call 标题行改显中文活动描述(`dev.html`)**:用户反馈 web 端工具调用只显示 `工具调用:run_python` / `shell` 等工具名,看不出"在干啥"。**根因有个真 bug**:`dev.html` 实时流分支(`tool_call`)读 `ev.data.arguments`,但后端 `core/loop.py::_execute_tool_call` emit 的字段叫 `args`(已解析 dict)+ `args_preview`(截 200 字),字段名对不上 → 前端拿到的永远是空串,`
` 是空的、连带 `extractArtifactRels(argsStr,...)` 也抽不到产物路径。**改法**:① 新增 `toolActivityLabel(name, args)` helper(挨着 `_workingDirName`),按 12 个工具的"关键代表参数"套中文动词 + 截断值:read/write/edit→`读取/写入/编辑文件: {path}`、glob→`查找文件: {pattern}`、grep→`搜索内容: {pattern}`、shell→`执行命令: {command}`、run_python→`运行 Python: {code}`、web_fetch→`抓取网页: {url}`、web_search→`联网搜索: {query}`、load_skill→`加载技能: {name}`、seedream/seedance→`生成图像/视频: {prompt}`,未知工具回退到 `name {JSON截断}` 或 `工具调用: name`;clip 把空白压一行 + 超长加 `…`。② 实时流分支 `ev.data.arguments` → `ev.data.args`(修字段 bug)并把 `` 文案换成 label。③ 历史消息回放分支(`p.tool_calls`,LiteLLM 格式 `tc.function.arguments` 是 JSON 字符串)同步:先 `JSON.parse` 成 `argsObj` 再生成 label,保持实时 / 历史一致。完整参数仍在折叠 `
` 里,展开可看。**选型**:用前端静态模板(零成本 / 不走模型 / 立即生效),否决"让模型每次调用前产出一句中文意图"(改 prompt + 每调用烧 token + 依赖模型配合)。**纯前端改**,`DESIGN.md` / `RUN.md` / `SKILL_LIST.md` 不动(无架构 / CLI / env / skill 变化)。**生效**:刷新 web 页面即可,无需重启后端。
 - **删 `_exec_shell` / `_exec_python` argv 里的 `setsid` 修 docker exec 延迟 stdout 丢失**:上一条 `_run_subprocess` 重写后用户实测 LLM 拿 `cement energy efficiency` 跑 paper_server 检索仍返空 `[exit 0]` 8 字符,且 `print(f"共命中 {len(papers)} 条结果\n")` 这种必有输出的代码也丢。**根因 = `setsid`,不是 `_run_subprocess` 的 poll loop**(上一条修对了一个独立的 bug,但不是用户当下症状的元凶)。**实证差异**:`docker exec ... setsid python -c "import time; time.sleep(2); print('hello')"` 等满 2.06s 但输出空;同条件去掉 setsid `docker exec ... python -c "..."` 等满 2.08s + 输出 `hello`。`setsid` 调 `setsid()` syscall 把进程变 new session leader without controlling terminal **之后** execvp(python),docker exec / runc 的 stdio attach 对"调用方变 session leader"敏感(具体哪一层没深挖到 runc 源码,经验上 docker exec + setsid + 延迟输出 = stdout 数据被截断,业界踩过的坑)。短输出(`print('hello')` 瞬时完成)能在窗口内漏出去,延迟输出(`search()` 等 httpx 1-2s)就全丢 —— 完美解释为什么 LLM 简单 `print(version)` 测试时部分输出能回但真业务调用全空。**为什么之前 host 侧 `docker exec ... python -c "from skills.research.paper import search; ..."` 2.94s 拿 10 条成功**:那条**没有** setsid,docker exec 等的就是 python 本身,3s 全程都阻塞读 stdout 不会丢。`setsid` 历史上是 §7.5 Stage C **Step 3b PGID kill 协议**铺路用的(PROGRESS 上有"延后到外部用户开放前"这条 work item),**协议没实现的当下 setsid 是空头载荷 + 副作用**。**改法**:`core/executor_docker.py:141` 和 `:177` 各删 1 行的 `"setsid"`,argv 形态变 `docker exec ...  bash -c ` / `... python