Qwen Code 改进建议
April 5, 2026 · View on GitHub
核心洞察:在终端环境中,当 Agent 执行耗时极长的任务(例如全量检索 500 个文件,或者运行一个需要 30 秒的端到端测试脚本)时,传统的终端往往只会显示一个单调的“加载圈 (Spinner)”。这种缺乏进度反馈的黑盒状态会让用户陷入焦虑,甚至误以为程序已经卡死(Hang)而强制按
Ctrl+C中断。Claude Code 巧妙地在全局状态库中引入了statusLineText,允许底层的工具甚至大模型在执行途中实时更新终端底部的文字;而 Qwen Code 目前在工具执行期间缺乏细粒度的进度广播机制。返回 改进建议总览
一、黑盒等待带来的焦虑感
1. Qwen Code 现状:静态的 Spinner
目前,当 Qwen Code 调用一个工具时,界面通常显示为:
[ ⠧ ] Running shell command...
- 痛点:如果这个 shell 命令是
npm run build,它可能要跑 1 分钟。在这 1 分钟内,屏幕上的信息完全静止。用户不知道系统是在下载依赖,还是在编译代码,亦或是底层已经抛出了需要用户输入的(y/n)提示从而死锁。
2. Claude Code 解决方案:全局贯通的进度插槽
在 Claude Code 的 state/AppStateStore.ts 和 components/StatusLine.tsx 中,存在一个贯穿整个应用生命周期的全局状态。
机制一:底层的细粒度更新 (Granular Progress Updates)
Claude Code 的底层工具执行器(例如 FileReadTool 或者 GrepTool)被赋予了修改全局 UI 状态的权限。
当 GrepTool 正在遍历一个庞大的工程时,它会在一个非阻塞的循环中定期调用 setAppState({ statusLineText: 'Searching src/components/...' })。
在 UI 层,Spinner 的旁边会高频闪过这些具体的子任务进度。这让用户吃了一颗定心丸:“它没卡住,它正在努力干活”。
机制二:防抖与节流 (Debounced Rendering)
为了防止底层工具在一秒内更新 100 次 statusLineText 导致 React Ink 引擎重绘爆栈,Claude Code 在状态分发层做了精准的防抖过滤。只有当文本真正发生语义改变,或者距离上次重绘超过一定间隔时,才会将新文本刷入 TUI。
机制三:自定义脚本挂载
Claude Code 甚至允许高阶用户在 settings.json 中配置自定义的 Shell 命令(比如 git branch --show-current)。状态栏会定期在后台静默运行这个脚本,并将执行结果(如当前的 Git 分支、甚至股票价格)挂载在状态栏的右侧。
二、Qwen Code 的改进路径 (P3 优先级)
让“自动化的黑盒”变得透明、可知、可控。
阶段 1:打通状态事件总线 (Event Bus)
- 在
packages/core/src/agents/runtime/agent-events.ts中新增一个事件:AgentEventType.TOOL_PROGRESS。 - 允许工具的
execute方法接收一个可选的onProgress(text: string)回调函数。
阶段 2:重写 TUI 状态栏组件
- 修改 CLI 前端的
Spinner或Footer组件,订阅TOOL_PROGRESS事件。 - 将原本固定的文字
Running Tool...升级为Running: [最新的 progress text]。
阶段 3:工具层的适配接入
针对耗时工具进行改造:
- Shell 工具:可以结合此前讨论过的
Shell Output FD Bypass,将提取到的最后一条stdout的前 50 个字符截断后作为progress text。 - Grep / Glob 工具:在遍历目录流时,每隔 500ms 抽出当前正在处理的文件夹名称抛出。
三、改进收益评估
- 实现成本:低。无需更改大模型的交互逻辑,只需梳理状态上报通道,几十行代码即可实现。
- 直接收益:
- 极 致 的 安 全 感:彻底消除长任务期间的“不知道程序在干啥”的用户焦虑。
- 方便死锁排查:当程序真的因为某个文件权限卡住时,屏幕上最后定格的
statusLineText能让开发者瞬间定位到肇事文件。