Commit Graph

2 Commits

Author SHA1 Message Date
116dc413f0 feat(seq): 新增 seq_help —— 格式说明 + 可照抄示例
动机来自真机实跑:模型写序列时踩了三个坑,各试 1~3 次才改对
  ① tools 漏末尾的 ';'       → 「末尾缺少 ';'」
  ② group 的 in 传成字符串     → 重试 3 次
  ③ as 指向未声明的 out 槽      → 静态校验拦下
这三处都是**格式细节**,塞不进工具描述(有长度限制),却恰是模型最易错处。
散落在七个描述里等于没有集中入口。

实现(help.go + tools.go + plugin.go):
· seq_help 无参数、纯文本返回(与仓内 output_send__*_help 同范式)
· 「格式要点」逐条写明:in/out 必须是**对象**、tools 必须是**字符串**、
  每个 tool 后(含最后一个)都要 ';'、as 必须在 out 声明、
  groups 与 file 二选一、组内并行组间串行
· 「条件 when」列出支持的表达式形态
· 「可照抄的完整示例」给一行**单行紧凑**的合法序列

★ 判据(plugin_test.go,3 条):
· seq_help 已注册、有 description、不声明并发安全
· 内容覆盖真机踩过的**每一个**坑(判据从"坑"出发而非从"打算写什么")
· ★ 示例**自己能被本包解析器接受**:validateHelpExample 从帮助文本里
  抽出示例喂给 Parse —— 模型是照抄的,示例自己解析不过就是给模型挖坑。
  而"从文本里有没有某个词"是看不出这类 bug 的。

过程中判据自己错了两次(都被这条示例判据照出来):
1. 抽取用 strings.Index(help, `{"name"`) ⇒ 先命中「格式要点」里**有意写的**
   示意片段,截到非示例的内容,报出莫名其妙的 invalid character '…'。
2. 修完又混用两套偏移基准(base 的下标拿去切 help)⇒ invalid character '\xaf'。
   ⇒ 重写为全程在同一 base 上定位。
★ 两次都说明:**判据的抽取逻辑本身就是需要验证的代码**,
它出错时报出的信息极具误导性(看起来像实现有 bug)。

示例形态也改过一次:原为多行缩进 JSON,改为**单行紧凑** —— 模型照抄时
免去缩进/换行带来的额外风险。

变异验证:去掉示例里的末尾 ';' ⇒ 示例判据 FAIL。

另一处:加 seq_help 后「恰好注册 6 个工具」判据 FAIL(实际 7)——
这正是那条判据的用意(防止悄悄多加工具稀释工具面),已更新并注明原因。

回归:go build ./... 通过;internal/plugins/... core sdk 全绿。
2026-09-27 13:48:15 +08:00
71c894c182 feat(seq): 六个 seq_* 工具、插件装配,并补内核两处缺口(插件线 P4)
内核缺口(都是 P3 落地时暴露的真实缺陷):
· **GetAllTools 丢 ParallelSafe**:它只带出 Name/Description/Parameters,
  插件看到的设备工具一律"不可并发" ⇒ 设备工具的并发声明**对插件不可见**。
· **ToolAPI 缺按名查**:新增 ToolDefByName。插件需要在**运行前**判断目标
  是否存在/是否并发安全(工具动态注册,"不存在"是常态),
  而 GetAllTools 只能拿到全量列表。查不到返回 nil,不 panic。

seq 插件:
· plugin.go:插件骨架 + kernelRunner(把 sdk.ToolAPI 收窄成三个方法,
  判据因此能用假实现驱动,不必构造整个内核)
· tools.go:六个工具定义(独立真相源,注册/判据/文档都从它取)
· handlers.go:seq_create/list/delete/run/call/when_call 的实现
· register.go + all.go:按 skillmgr 同一范式 init 注册

★ 过程中解决一个**我自己的设计矛盾**:
判据原先要求 `seq_call` / `seq_when_call` 进黑名单,但"按名调用
group/序列"恰恰是本包的核心能力——禁掉它,序列就退化成单层脚本。
分层澄清后:黑名单只管**对外发消息 / 起子 agent / 改插件表 / 再跑整条
序列**;seq_call 系列留给序列内部组合,其递归由 maxCallDepth + 环检测
负责(设计文档 §8.3 本来就是这么定的,我把两层混了)。
`seq_run` 留在黑名单:序列内再跑整条序列语义上是递归。

**六个工具一律不声明 ParallelSafe**:seq_run/seq_call 会执行一串工具,
其中可能含写操作;标成并发安全会让内核把两条 seq_run 并发跑,
两个序列的执行顺序交错、变量表互相污染。

安全性:序列名与文件路径都做穿越防护(`..` 段、分隔符、空名)。

过程中四次自伤:
1. 臆造 `jsonMarshalIndent`(不存在)→ 改 encoding/json.MarshalIndent;
   并把 execGroup 的 runner 传错成 p(应 p.runner)。
2. seq 判据里写了 `black(name)`,而 blacklisted 是**谓词**不是函数。
3. 一次 python 替换删漏,把「跨序列目标存在性检查」那段从 CheckNew
   里整段摘掉又贴回原处——靠编译错误发现。
4. ★ 注册失败我写了 panic:内置插件在 main() 装配期加载,panic 会
   **直接拖垮内核启动**,而"某个工具没注册上"只该让该工具不可用。
   已改为 log.Printf + 继续(与 clawhubadapter / mcp 一致)。

变异验证:把 seq_run 移出黑名单 ⇒ 黑名单判据 FAIL。

判据(plugin_test.go,6 条):六个工具全部注册且 description/参数 schema
非空;seq_create 声明 required 并说明 groups/file 二选一;
seq_run 说明"按数组顺序";六个工具均未声明 ParallelSafe;
黑名单含递归风险项且**不误伤** seq_call 与普通工具。

回归:seq -race 全绿;internal/sdk/... internal/plugins/... 12 包全绿。
2026-09-27 13:05:28 +08:00