mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-05 16:57:32 +00:00
fix(agent): 子 agent 继承技能索引 —— 修 agent 把终端当命令执行器用
## 缺陷(生产实测)
`SetSkillIndexProvider` 只在 cmd/homed/bootstrap.go 里对**根 agent** 调了一次。
rtchild / 驻留子各自 `New(AgentConfig{...})` 构造载体,都没传这个字段 ⇒
子的 system prompt 里**完全没有 skill 索引**。
症状(日志实录):A2A 会话由「临时分诊助手」(驻留子)接手,它手上没有
`cmd_run`(cmd 插件 `auto_start=false`),而 `cmd-tools` skill 正文里写着
「先 plugin_start cmd」。它看不到这条 skill,于是把 `terminal_create` 当成
命令执行器:每条 `cd … && echo … && grep …` 开一个新终端,终端随命令结束退出,
`terminal_read` 立刻撞 `read /dev/ptmx: input/output error`,然后为下一条命令
再开一个 —— 终端列表被填满,每一条都死在半路。
与本仓 Security 那次同型:父有的能力,子没继承。
## 修法
rtchild 与驻留子的 AgentConfig 各补一行 `SkillIndexProvider: a.skillIndex`,
与 `SystemPrompt` / `StageHost` / `Security` 同一组「必须继承父」的字段。
## 顺带两件事
### 1. 内置 skill 的更新永远到不了已部署机器
原落盘规则是「目标目录已存在就跳过」,本意是保住用户改动。但它把两件事混成一件:
用户改过的版本 ⇒ 应该保留
内核自己写过的旧版 ⇒ 应该随内核更新
两者都表现为「目录已存在」,于是 b850fea 把 `memory_recall` 改成
`stablemem_recall` 后,生产机的 kernel-memory 一直停在旧名,模型照着
旧名调工具必然失败,而日志里一个字都没有。
改为用 `.builtin-sha256` 摘要区分:
当前内容 == stamp ⇒ 没人动过 ⇒ 可安全覆盖成新版
当前内容 != stamp ⇒ 用户改过 ⇒ 保留
没有 stamp(老目录)⇒ 保守视为用户版本,不覆盖
### 2. 新增 kernel-terminal skill
工具描述只说「适用于交互式程序」,没说何时**不该**用;`command` 参数又鼓励
传整条命令。补一条内置 skill 讲清 cmd_run 与 terminal_create 的边界、
以及终端的 input/key/notify 用法。描述控制在 80 字符内(进索引不截断)。
## 判据(均经变异验证)
TestRTChild_InheritsSkillIndex 删掉接线 ⇒ 红(实测确认)
TestResident_InheritsSkillIndex 同上(生产实际中招的那一类)
TestRootAgent_SkillIndexStillInjected 确认没改坏根 agent 路径
TestChildWithoutSkillIndexIsNotBroken 父无索引时子不 panic
TestMaterializeBuiltinSkills_* 5 条:覆盖语义四条成组断言
(改回旧行为 ⇒ OverwritesUnmodified 红,实测确认)
判据测的是**生成的 prompt**,不是 `skillIndex != nil`:
后者接上了但注入那段被删照样绿。
## 验证
go build ./... PASS
go vet ./... PASS
gofmt -l 干净
go test ./... -count=1 62 包全过,0 FAIL
干净检出(git worktree)单独验证 PASS
This commit is contained in:
@ -16,7 +16,7 @@ Four stores, one rule each:
|
||||
## Retrieving
|
||||
|
||||
| Need | Tool |
|
||||
|---|---|
|
||||
| --- | --- |
|
||||
| A past episode in full | `coldcontext_query` |
|
||||
| A fact or relation | `stablemem_recall` |
|
||||
| Written reference material | `knowledge_search` |
|
||||
@ -33,5 +33,5 @@ again later, it lives on in the timeline until pruning moves it back.
|
||||
## Writing
|
||||
|
||||
- Facts worth keeping: `stablemem_commit` (triples).
|
||||
- Written knowledge: `knowledge_write`.
|
||||
- Written knowledge: `knowledge_create`.
|
||||
- Do not commit transient chatter, tool output, or your own status lines.
|
||||
|
||||
65
internal/plugins/skillmgr/builtin/kernel-terminal/SKILL.md
Normal file
65
internal/plugins/skillmgr/builtin/kernel-terminal/SKILL.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
name: kernel-terminal
|
||||
description: Terminal waits for input; it is NOT cmd_run. Read before using vim/ssh/top.
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
# Terminals vs one-shot commands
|
||||
|
||||
Two different tools. Picking the wrong one looks like it works, then fails in a way that
|
||||
points somewhere else.
|
||||
|
||||
| Tool | Use for | Lifetime |
|
||||
| --- | --- | --- |
|
||||
| `cmd_run` | **One** command, then done: queries, scripts, `cd && … && grep …`, pipes, redirects, heredocs | Process exits when the command exits |
|
||||
| `terminal_create` | A program that **keeps running and keeps asking for input**: `vim`, `ssh`, `top`, `less`, an interactive REPL | Stays open until you `terminal_close` or its `timeout` expires |
|
||||
|
||||
## The failure this prevents
|
||||
|
||||
Running `terminal_create` with a compound one-shot command
|
||||
(`cd /x && echo … && ls … && grep …`) creates a terminal that exits the moment the command
|
||||
finishes. Reading it then fails with `read /dev/ptmx: input/output error`. The next instinct is
|
||||
to create another terminal for the next command — and now every "command" costs a terminal,
|
||||
fills the terminal list, and each one dies mid-read.
|
||||
|
||||
**If the command runs to completion on its own, it belongs in `cmd_run`.** A terminal is only
|
||||
justified when the thing you are talking to is *still running and waiting for you*.
|
||||
|
||||
## Driving a terminal
|
||||
|
||||
`terminal_create` returns an ID. From then on the terminal is **silent by default** — it does
|
||||
not push output at you.
|
||||
|
||||
1. `terminal_read(id)` — read what is on screen now. Do this after acting, not on a timer.
|
||||
2. `terminal_write(id, input=..., key=...)` — send text and/or a key (`Enter`, `Escape`, `C-c`)
|
||||
in **one call**. `input` without `key` does not submit; the program just sits there.
|
||||
3. `terminal_close(id)` — release it. Terminals default to a 5-minute `timeout`; leaving them
|
||||
open wastes a slot.
|
||||
|
||||
`notify` is opt-in. Without it you get nothing. Add it only when you genuinely want a wake-up
|
||||
(`exit` for "tell me when it finished", `buffer=8192` for "tell me when there is a lot of
|
||||
unread output"). Watching a fast-scrolling program with `interval` produces noise, not signal.
|
||||
|
||||
## Sending keystrokes
|
||||
|
||||
`key` is for **control**, `input` is for **text**:
|
||||
|
||||
| Want | Send |
|
||||
| --- | --- |
|
||||
| Submit a command line | `input="ls -la"`, `key="Enter"` |
|
||||
| Interrupt a running program | `key="C-c"` |
|
||||
| Leave a pager or editor without saving | `key="Escape"`, then `key="q"` for pagers |
|
||||
| Quit `vim` without saving | `key="Escape"`, then `input=":q!"`, `key="Enter"` |
|
||||
|
||||
## Reading output that scrolled past
|
||||
|
||||
`terminal_read` returns what is currently visible plus recent scrollback. If the output you need
|
||||
scrolled out of range, do not blindly re-read in a loop — either grow `rows` at create time, or
|
||||
for one-shot inspection prefer `cmd_run`, whose result is returned whole.
|
||||
|
||||
## Checklist before reaching for a terminal
|
||||
|
||||
- Does the command finish by itself? → `cmd_run`.
|
||||
- Does it need me to type at it more than once? → `terminal_create`.
|
||||
- Am I about to create a second terminal for "the next command"? → stop; the first one was
|
||||
the wrong tool.
|
||||
Reference in New Issue
Block a user