mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-05 16:57:32 +00:00
## 为什么补这个
真实生产事故:agent 把 terminal_create 当成一次性命令执行器用。
terminal_create(command='cd /usr/lib/node_modules/@deepseek-ai && echo "=== 已安装的 dsh 包 ===" && ls -d */ | head -60 && …')
→ read /dev/ptmx: input/output error
→ 再开 term_7、term_8、term_9 …
三层成因:
① cmd 插件 auto_start=false ⇒ 工具表里没有 cmd_run,需先 plugin_start cmd
② terminal_create 的 command 参数描述写着"要执行的命令",语义上像"跑一条命令"
③ 没有文档说清"一次性命令该用 cmd_run、终端是给要持续输入的程序用的"
①③ 已分别修掉(cmd-tools skill + 本文件)。② 是设计上的引力:
参数名叫 command、描述说"要执行的命令",模型自然会塞复合命令进去。
文档要正面抵消。
## 实现方式
按 seq 的既有模式:内置插件实现 plugin.SkillProvider,
由内核统一写盘/幂等/事件/停用清理(internal/plugin/builtin_skill.go)。
· 新增 internal/plugins/agentcli/skill.go
· BuiltinSkills() 交出正文,生命周期与插件同生共死
(禁用插件后 skill 还留着 = 模型看得到说明、点进去工具却不存在)
## 文档的核心:可操作判据,不是抽象词
一句判据:**跑完就结束 → cmd_run。要一直活着、要看屏幕、要按键 → terminal。**
关键的三条(缺任何一条模型都会退回旧行为):
· 点明 cmd 插件要 plugin_start(否则模型找不到 cmd_run 就用终端)
· 点明复合命令(cd && echo && ls)属于一次性,不是"所以要用终端"
· 解释 /dev/ptmx 那个真实报错的含义(命令跑完终端已退出),
否则模型会以为终端坏了
索引行(模型每轮唯一能看到的一行)也带边界:
"交互式终端(vim/ssh/top/长驻进程)。一次性的 shell 命令不要用终端,用 cmd_run。"
## 判据(均经变异验证)
TestSkillProviderContract 编译期断言 SkillProvider + 正文非空
TestSkillSeparatesTerminalFromOneShot ★ 六条必备内容缺一即红
TestSkillIndexLineStatesBoundary 索引行必须指出替代方案
TestSkillBodyFirstParagraphStandalone 正文首段(真正注入提示词的那段)能独立看懂
变异验证(实测):把整份文档换成"终端可以执行各种命令"的弱化版本
⇒ 3 条同时红。
★ 第一版变异是"只改一句话",判据没红 —— 因为 cmd_run 在文中另有 13 处。
那次变异无效,不算验证。改成整份替换后才是真验证。
## 端到端验证(独立实例 + 假 LLM 捕获真实请求)
[plugin] agentcli: installed skill "agentcli-terminal" -> .../skills/agentcli-terminal
[clawhubadapter] skill agentcli-terminal detected, handed off to skillmgr
实际注入到 system prompt 的 [Skills] 段:
agentcli-terminal v1.0.0 - 终端给**要持续输入**的程序用(vim、ssh、top、REPL、
要按键确认的安装器);一次性的 shell 命令用 **cmd_run**(cmd 插件,需…
## 验证
go build ./... PASS
go vet ./... PASS
gofmt -l 干净
go test ./... -count=1 63 包全过,0 FAIL
干净检出(git worktree) build + 判据全绿
独立实例实测 真机装盘 + 真机注入提示词(见上)