@xgjktech/xg-openclaw-harness-tools 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -148
- package/dist/plan-view-tool.js +4 -4
- package/dist/plan-view.d.ts +1 -1
- package/dist/plan-view.js +4 -4
- package/dist/plan-write-tool.d.ts.map +1 -1
- package/dist/plan-write-tool.js +17 -14
- package/openclaw.plugin.json +14 -14
- package/package.json +57 -55
package/README.md
CHANGED
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
# @xgjktech/xg-openclaw-harness-tools
|
|
2
|
-
|
|
3
|
-
OpenClaw 第三方工具插件:企业计划工具 `xg_plan_write` / `xg_plan_view`。
|
|
4
|
-
|
|
5
|
-
用一份持久化的计划(SQLite 落盘)取代内置 `update_plan`(无状态、只回显、不落库),
|
|
6
|
-
`xg_plan_write` 整张维护草稿计划,`xg_plan_view` 只读查看计划或最近摘要。
|
|
7
|
-
|
|
8
|
-
## 架构裁决:实时事件当前处于事实性休眠(务必先读)
|
|
9
|
-
|
|
10
|
-
**当前 OpenClaw 2026.6.10 版本下,实时事件推送链路休眠**:工具 execute/factory 期没有
|
|
11
|
-
正当途径获取真实 runId(详见 `docs/notes-plugin-entry.md` N2),且 0.3.0 已移除工具侧
|
|
12
|
-
`notify.ts`。`xg_plan_write` 落库后不发事件,`xg_plan_view` 全程只读。
|
|
13
|
-
|
|
14
|
-
**因此 IM 侧(或任何下游消费方)不得依赖实时事件感知计划进度。** 当前唯一可靠的主感知路径是:
|
|
15
|
-
|
|
16
|
-
1. **SQLite 读取**——IM 用 `openPlanStoreReadonly(dbPath)` 按 origin 只读反查
|
|
17
|
-
`<stateDir>/xgjktech/plans.sqlite` 并推送全量快照,这是权威状态源。
|
|
18
|
-
2. **agent 最终回复**——agent 完成任务后的文本回复本身会体现进度。
|
|
19
|
-
|
|
20
|
-
事件契约(`PlanEventPayload` / `isPlanEventPayload` / `planEventStream`)在 shared 中原样保留,
|
|
21
|
-
仅用于下游编译兼容。未来恢复实时事件需要重新实现工具侧生产与 IM 侧消费,并单独发布。
|
|
22
|
-
|
|
23
|
-
## 环境要求
|
|
24
|
-
|
|
25
|
-
- **Node ≥ 22.19.0**(依赖 `node:sqlite`,与 OpenClaw 自身 `engines` 一致)。
|
|
26
|
-
- monorepo 用 npm workspaces。
|
|
27
|
-
|
|
28
|
-
## 安装与构建
|
|
29
|
-
|
|
30
|
-
本仓库是包含 `@xgjktech/xg-openclaw-shared`(存储层+事件契约层)和
|
|
31
|
-
`@xgjktech/xg-openclaw-harness-tools`(本插件)两个 workspace 的 monorepo。**`xg-shared` 必须先于
|
|
32
|
-
本插件构建**(本插件依赖它的编译产物);npm workspaces 拓扑已保证顺序,直接在仓库根执行:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm install
|
|
36
|
-
npm run build
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
产物:`packages/xg-harness-tools/dist/`(含 `index.js` 与 `.d.ts`)。
|
|
40
|
-
|
|
41
|
-
将本插件安装到 OpenClaw 的具体命令/目录约定,请对照 OpenClaw 的第三方插件安装机制
|
|
42
|
-
(global / workspace / config origin,本插件按非 bundled 第三方路径运行)以及
|
|
43
|
-
`package.json` 里的 `openclaw.*` 字段块(`extensions`/`install.localPath` 等)。
|
|
44
|
-
P1 阶段不锁死具体安装命令,避免与实际安装流程漂移(详见 `docs/05-部署文档.md` §3.3)。
|
|
45
|
-
|
|
46
|
-
## 配置
|
|
47
|
-
|
|
48
|
-
### 1. 屏蔽内置 update_plan(deny,唯一权威路径)
|
|
49
|
-
|
|
50
|
-
```jsonc
|
|
51
|
-
{
|
|
52
|
-
"tools": {
|
|
53
|
-
"deny": ["update_plan"]
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
无论生产 profile / allowlist 取何值(包括 `allow:["*"]`),`deny` 都一票否决,
|
|
59
|
-
与 profile 取值解耦。
|
|
60
|
-
|
|
61
|
-
### 2. 启用本插件两个工具(allow)
|
|
62
|
-
|
|
63
|
-
本插件两个工具都以 `optional:true` 注册,**默认不启用**,必须 allowlist 显式命中才会注册:
|
|
64
|
-
|
|
65
|
-
```jsonc
|
|
66
|
-
{
|
|
67
|
-
"tools": {
|
|
68
|
-
"allow": ["xg_plan_write", "xg_plan_view"],
|
|
69
|
-
"deny": ["update_plan"]
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
可直接套用的完整样例见仓库根 [`deploy/tools.config.sample.jsonc`](../../deploy/tools.config.sample.jsonc)(带注释)。
|
|
75
|
-
|
|
76
|
-
### 3. stateDir 与数据库路径
|
|
77
|
-
|
|
78
|
-
插件运行时数据库路径固定为:
|
|
79
|
-
|
|
80
|
-
```
|
|
81
|
-
<stateDir>/xgjktech/plans.sqlite
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
`stateDir` 取自 OpenClaw 全局状态目录(`api.runtime.state.resolveStateDir()`,默认
|
|
85
|
-
`~/.openclaw/`,`OPENCLAW_STATE_DIR` 覆盖时同步),插件首次运行时通过 `resolvePlanDbPath`
|
|
86
|
-
自动 `mkdir -p` 出 `xgjktech/` 子目录,无需手动创建。IM 插件若要接入同一份数据,应复用
|
|
87
|
-
同一个 `resolvePlanDbPath` 以保证路径约定一致。
|
|
88
|
-
|
|
89
|
-
## 两个工具说明
|
|
90
|
-
|
|
91
|
-
### `xg_plan_write`
|
|
92
|
-
|
|
93
|
-
整张创建或覆盖一份草稿计划(goal + tasks[])并写入 SQLite。更新时必须重交所有要保留的
|
|
94
|
-
task;写入 schema 不接受 steps,但读取旧计划仍兼容旧 steps 数据。
|
|
95
|
-
|
|
96
|
-
### `xg_plan_view`
|
|
97
|
-
|
|
98
|
-
只读查看计划,**不会执行任何任务**。带 planId 返回完整紧凑 view;不带 planId 返回最近 10 条
|
|
99
|
-
计划摘要,用于跨会话找回 planId。更新进度统一使用 `xg_plan_write` 整张重交。
|
|
100
|
-
|
|
101
|
-
> 工具名用 `view` 而非 `execute` 是有意的:`plan_view`/`plan_write` 都只是台账,不执行、不调度、
|
|
102
|
-
> 无后台运行。二者 description 均明确"保存/查看 ≠ 执行",且结果带 `reminder` 字段引导模型
|
|
103
|
-
> 继续逐项实际执行任务——避免模型调用计划工具后误以为工作已在后台完成而停住。
|
|
104
|
-
|
|
105
|
-
两个工具的完整参数 schema 见 `src/plan-write-tool.ts` / `src/plan-view-tool.ts`
|
|
106
|
-
中的 `PLAN_WRITE_DESCRIPTION` / `PLAN_VIEW_DESCRIPTION`。
|
|
107
|
-
|
|
108
|
-
## 部署 checklist
|
|
109
|
-
|
|
110
|
-
- [ ] Node ≥ 22.19.0
|
|
111
|
-
- [ ] monorepo 构建成功(`xg-shared` 先于本插件构建,workspaces 拓扑自动保证)
|
|
112
|
-
- [ ] 插件已安装且被 OpenClaw 识别为已加载的第三方插件(非 bundled)
|
|
113
|
-
- [ ] `tools.deny` 含 `update_plan`
|
|
114
|
-
- [ ] `tools.allow` 含 `xg_plan_write` + `xg_plan_view`(或经 `group:plugins` / `*` 放行)
|
|
115
|
-
- [ ] 实拉一个 agent,验证工具清单**有本插件两工具、无 update_plan**(步骤见下节)
|
|
116
|
-
- [ ] `<stateDir>/xgjktech/` 可写,首次运行能生成 `plans.sqlite`
|
|
117
|
-
- [ ] (互通)IM 侧已依赖 `@xgjktech/xg-openclaw-shared` 并按 `docs/04-互通设计.md` 接入只读反查
|
|
118
|
-
|
|
119
|
-
## 实机验证步骤(可复现)+ 当前实际执行情况说明
|
|
120
|
-
|
|
121
|
-
**验收标准要求部署方按 checklist 实拉一个 agent,确认工具清单里有 `xg_plan_write`/
|
|
122
|
-
`xg_plan_view`、没有 `update_plan`。以下是可复现的验证步骤:**
|
|
123
|
-
|
|
124
|
-
1. 按上文"配置"章节把 `tools.deny`/`tools.allow` 写入生产 agent/profile 配置。
|
|
125
|
-
2. 安装并加载本插件(确认加载日志/插件列表里出现 `xg-harness-tools`,origin 为第三方非 bundled)。
|
|
126
|
-
3. 拉起一个真实 agent 会话,触发一次会列出可用工具的动作(例如让 agent 描述自己有哪些工具,
|
|
127
|
-
或查看 gateway/日志里该次 attempt 实际注册的工具名列表)。
|
|
128
|
-
4. 核对该工具列表:应包含 `xg_plan_write` 与 `xg_plan_view`,**不应包含** `update_plan`。
|
|
129
|
-
5. 调用一次 `xg_plan_write` 建一份最小计划,确认返回 `planId + view`;再用该 planId 调
|
|
130
|
-
`xg_plan_view`,确认只读 view 一致。用 `openPlanStoreReadonly` 反查并核对落盘内容。
|
|
131
|
-
|
|
132
|
-
**本项在本次交付中未在真实 OpenClaw gateway 环境实机执行**——本仓库当前开发环境没有可用的
|
|
133
|
-
真实 OpenClaw gateway/agent 运行环境,因此无法诚实地报告"已实拉 agent 验证通过"。以下是
|
|
134
|
-
已经做过、可以作为间接佐证的验证,但**明确说明这不等于实机验证**:
|
|
135
|
-
|
|
136
|
-
- 当前 factory 集成测试用**手工构造的 mock `api`**捕获 2 个工具的注册工厂,并提供带
|
|
137
|
-
`sessionKey`/`deliveryContext` 的 `toolContext`:`xg_plan_write` 写入后通过只读存储反查
|
|
138
|
-
`origin`,`xg_plan_view` 校验指定计划的 view 与最近计划列表。**这验证的是插件代码本身
|
|
139
|
-
可以被正确加载、注册并贯通当前契约**,但 mock `api` 不是真实 OpenClaw gateway 的
|
|
140
|
-
`tools.allow`/`deny` 策略引擎,**不能**佐证"生产 deny/allow 配置生效后工具清单精确符合
|
|
141
|
-
预期"这一条——那一条必须在真实 gateway 环境按上面 5 步实测。
|
|
142
|
-
- T6 阶段(`packages/xg-harness-tools/src/integration.test.ts`)用真实的 `SqlitePlanStore`
|
|
143
|
-
(临时目录)+ 真实工具函数(`buildPlanWriteTool`/`buildPlanViewTool`)跑通了完整的
|
|
144
|
-
写入→整张重交→execute 只读查看→SQLite 只读反查链路,但同样不经过 OpenClaw 的工具
|
|
145
|
-
allowlist/deny 策略引擎。
|
|
146
|
-
|
|
147
|
-
**结论:部署方在生产环境落实上述配置后,必须按"实机验证步骤"重新执行一次实拉 agent 验证,
|
|
148
|
-
不能以本仓库现有的 mock/集成测试结果代替。**
|
|
1
|
+
# @xgjktech/xg-openclaw-harness-tools
|
|
2
|
+
|
|
3
|
+
OpenClaw 第三方工具插件:企业计划工具 `xg_plan_write` / `xg_plan_view`。
|
|
4
|
+
|
|
5
|
+
用一份持久化的计划(SQLite 落盘)取代内置 `update_plan`(无状态、只回显、不落库),
|
|
6
|
+
`xg_plan_write` 整张维护草稿计划,`xg_plan_view` 只读查看计划或最近摘要。
|
|
7
|
+
|
|
8
|
+
## 架构裁决:实时事件当前处于事实性休眠(务必先读)
|
|
9
|
+
|
|
10
|
+
**当前 OpenClaw 2026.6.10 版本下,实时事件推送链路休眠**:工具 execute/factory 期没有
|
|
11
|
+
正当途径获取真实 runId(详见 `docs/notes-plugin-entry.md` N2),且 0.3.0 已移除工具侧
|
|
12
|
+
`notify.ts`。`xg_plan_write` 落库后不发事件,`xg_plan_view` 全程只读。
|
|
13
|
+
|
|
14
|
+
**因此 IM 侧(或任何下游消费方)不得依赖实时事件感知计划进度。** 当前唯一可靠的主感知路径是:
|
|
15
|
+
|
|
16
|
+
1. **SQLite 读取**——IM 用 `openPlanStoreReadonly(dbPath)` 按 origin 只读反查
|
|
17
|
+
`<stateDir>/xgjktech/plans.sqlite` 并推送全量快照,这是权威状态源。
|
|
18
|
+
2. **agent 最终回复**——agent 完成任务后的文本回复本身会体现进度。
|
|
19
|
+
|
|
20
|
+
事件契约(`PlanEventPayload` / `isPlanEventPayload` / `planEventStream`)在 shared 中原样保留,
|
|
21
|
+
仅用于下游编译兼容。未来恢复实时事件需要重新实现工具侧生产与 IM 侧消费,并单独发布。
|
|
22
|
+
|
|
23
|
+
## 环境要求
|
|
24
|
+
|
|
25
|
+
- **Node ≥ 22.19.0**(依赖 `node:sqlite`,与 OpenClaw 自身 `engines` 一致)。
|
|
26
|
+
- monorepo 用 npm workspaces。
|
|
27
|
+
|
|
28
|
+
## 安装与构建
|
|
29
|
+
|
|
30
|
+
本仓库是包含 `@xgjktech/xg-openclaw-shared`(存储层+事件契约层)和
|
|
31
|
+
`@xgjktech/xg-openclaw-harness-tools`(本插件)两个 workspace 的 monorepo。**`xg-shared` 必须先于
|
|
32
|
+
本插件构建**(本插件依赖它的编译产物);npm workspaces 拓扑已保证顺序,直接在仓库根执行:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
产物:`packages/xg-harness-tools/dist/`(含 `index.js` 与 `.d.ts`)。
|
|
40
|
+
|
|
41
|
+
将本插件安装到 OpenClaw 的具体命令/目录约定,请对照 OpenClaw 的第三方插件安装机制
|
|
42
|
+
(global / workspace / config origin,本插件按非 bundled 第三方路径运行)以及
|
|
43
|
+
`package.json` 里的 `openclaw.*` 字段块(`extensions`/`install.localPath` 等)。
|
|
44
|
+
P1 阶段不锁死具体安装命令,避免与实际安装流程漂移(详见 `docs/05-部署文档.md` §3.3)。
|
|
45
|
+
|
|
46
|
+
## 配置
|
|
47
|
+
|
|
48
|
+
### 1. 屏蔽内置 update_plan(deny,唯一权威路径)
|
|
49
|
+
|
|
50
|
+
```jsonc
|
|
51
|
+
{
|
|
52
|
+
"tools": {
|
|
53
|
+
"deny": ["update_plan"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
无论生产 profile / allowlist 取何值(包括 `allow:["*"]`),`deny` 都一票否决,
|
|
59
|
+
与 profile 取值解耦。
|
|
60
|
+
|
|
61
|
+
### 2. 启用本插件两个工具(allow)
|
|
62
|
+
|
|
63
|
+
本插件两个工具都以 `optional:true` 注册,**默认不启用**,必须 allowlist 显式命中才会注册:
|
|
64
|
+
|
|
65
|
+
```jsonc
|
|
66
|
+
{
|
|
67
|
+
"tools": {
|
|
68
|
+
"allow": ["xg_plan_write", "xg_plan_view"],
|
|
69
|
+
"deny": ["update_plan"]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
可直接套用的完整样例见仓库根 [`deploy/tools.config.sample.jsonc`](../../deploy/tools.config.sample.jsonc)(带注释)。
|
|
75
|
+
|
|
76
|
+
### 3. stateDir 与数据库路径
|
|
77
|
+
|
|
78
|
+
插件运行时数据库路径固定为:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
<stateDir>/xgjktech/plans.sqlite
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`stateDir` 取自 OpenClaw 全局状态目录(`api.runtime.state.resolveStateDir()`,默认
|
|
85
|
+
`~/.openclaw/`,`OPENCLAW_STATE_DIR` 覆盖时同步),插件首次运行时通过 `resolvePlanDbPath`
|
|
86
|
+
自动 `mkdir -p` 出 `xgjktech/` 子目录,无需手动创建。IM 插件若要接入同一份数据,应复用
|
|
87
|
+
同一个 `resolvePlanDbPath` 以保证路径约定一致。
|
|
88
|
+
|
|
89
|
+
## 两个工具说明
|
|
90
|
+
|
|
91
|
+
### `xg_plan_write`
|
|
92
|
+
|
|
93
|
+
整张创建或覆盖一份草稿计划(goal + tasks[])并写入 SQLite。更新时必须重交所有要保留的
|
|
94
|
+
task;写入 schema 不接受 steps,但读取旧计划仍兼容旧 steps 数据。
|
|
95
|
+
|
|
96
|
+
### `xg_plan_view`
|
|
97
|
+
|
|
98
|
+
只读查看计划,**不会执行任何任务**。带 planId 返回完整紧凑 view;不带 planId 返回最近 10 条
|
|
99
|
+
计划摘要,用于跨会话找回 planId。更新进度统一使用 `xg_plan_write` 整张重交。
|
|
100
|
+
|
|
101
|
+
> 工具名用 `view` 而非 `execute` 是有意的:`plan_view`/`plan_write` 都只是台账,不执行、不调度、
|
|
102
|
+
> 无后台运行。二者 description 均明确"保存/查看 ≠ 执行",且结果带 `reminder` 字段引导模型
|
|
103
|
+
> 继续逐项实际执行任务——避免模型调用计划工具后误以为工作已在后台完成而停住。
|
|
104
|
+
|
|
105
|
+
两个工具的完整参数 schema 见 `src/plan-write-tool.ts` / `src/plan-view-tool.ts`
|
|
106
|
+
中的 `PLAN_WRITE_DESCRIPTION` / `PLAN_VIEW_DESCRIPTION`。
|
|
107
|
+
|
|
108
|
+
## 部署 checklist
|
|
109
|
+
|
|
110
|
+
- [ ] Node ≥ 22.19.0
|
|
111
|
+
- [ ] monorepo 构建成功(`xg-shared` 先于本插件构建,workspaces 拓扑自动保证)
|
|
112
|
+
- [ ] 插件已安装且被 OpenClaw 识别为已加载的第三方插件(非 bundled)
|
|
113
|
+
- [ ] `tools.deny` 含 `update_plan`
|
|
114
|
+
- [ ] `tools.allow` 含 `xg_plan_write` + `xg_plan_view`(或经 `group:plugins` / `*` 放行)
|
|
115
|
+
- [ ] 实拉一个 agent,验证工具清单**有本插件两工具、无 update_plan**(步骤见下节)
|
|
116
|
+
- [ ] `<stateDir>/xgjktech/` 可写,首次运行能生成 `plans.sqlite`
|
|
117
|
+
- [ ] (互通)IM 侧已依赖 `@xgjktech/xg-openclaw-shared` 并按 `docs/04-互通设计.md` 接入只读反查
|
|
118
|
+
|
|
119
|
+
## 实机验证步骤(可复现)+ 当前实际执行情况说明
|
|
120
|
+
|
|
121
|
+
**验收标准要求部署方按 checklist 实拉一个 agent,确认工具清单里有 `xg_plan_write`/
|
|
122
|
+
`xg_plan_view`、没有 `update_plan`。以下是可复现的验证步骤:**
|
|
123
|
+
|
|
124
|
+
1. 按上文"配置"章节把 `tools.deny`/`tools.allow` 写入生产 agent/profile 配置。
|
|
125
|
+
2. 安装并加载本插件(确认加载日志/插件列表里出现 `xg-harness-tools`,origin 为第三方非 bundled)。
|
|
126
|
+
3. 拉起一个真实 agent 会话,触发一次会列出可用工具的动作(例如让 agent 描述自己有哪些工具,
|
|
127
|
+
或查看 gateway/日志里该次 attempt 实际注册的工具名列表)。
|
|
128
|
+
4. 核对该工具列表:应包含 `xg_plan_write` 与 `xg_plan_view`,**不应包含** `update_plan`。
|
|
129
|
+
5. 调用一次 `xg_plan_write` 建一份最小计划,确认返回 `planId + view`;再用该 planId 调
|
|
130
|
+
`xg_plan_view`,确认只读 view 一致。用 `openPlanStoreReadonly` 反查并核对落盘内容。
|
|
131
|
+
|
|
132
|
+
**本项在本次交付中未在真实 OpenClaw gateway 环境实机执行**——本仓库当前开发环境没有可用的
|
|
133
|
+
真实 OpenClaw gateway/agent 运行环境,因此无法诚实地报告"已实拉 agent 验证通过"。以下是
|
|
134
|
+
已经做过、可以作为间接佐证的验证,但**明确说明这不等于实机验证**:
|
|
135
|
+
|
|
136
|
+
- 当前 factory 集成测试用**手工构造的 mock `api`**捕获 2 个工具的注册工厂,并提供带
|
|
137
|
+
`sessionKey`/`deliveryContext` 的 `toolContext`:`xg_plan_write` 写入后通过只读存储反查
|
|
138
|
+
`origin`,`xg_plan_view` 校验指定计划的 view 与最近计划列表。**这验证的是插件代码本身
|
|
139
|
+
可以被正确加载、注册并贯通当前契约**,但 mock `api` 不是真实 OpenClaw gateway 的
|
|
140
|
+
`tools.allow`/`deny` 策略引擎,**不能**佐证"生产 deny/allow 配置生效后工具清单精确符合
|
|
141
|
+
预期"这一条——那一条必须在真实 gateway 环境按上面 5 步实测。
|
|
142
|
+
- T6 阶段(`packages/xg-harness-tools/src/integration.test.ts`)用真实的 `SqlitePlanStore`
|
|
143
|
+
(临时目录)+ 真实工具函数(`buildPlanWriteTool`/`buildPlanViewTool`)跑通了完整的
|
|
144
|
+
写入→整张重交→execute 只读查看→SQLite 只读反查链路,但同样不经过 OpenClaw 的工具
|
|
145
|
+
allowlist/deny 策略引擎。
|
|
146
|
+
|
|
147
|
+
**结论:部署方在生产环境落实上述配置后,必须按"实机验证步骤"重新执行一次实拉 agent 验证,
|
|
148
|
+
不能以本仓库现有的 mock/集成测试结果代替。**
|
package/dist/plan-view-tool.js
CHANGED
|
@@ -7,13 +7,13 @@ export const PlanViewParams = Type.Object({
|
|
|
7
7
|
planId: Type.Optional(Type.String({ description: "要查看的计划 id;留空则列出最近计划" })),
|
|
8
8
|
}, { additionalProperties: false });
|
|
9
9
|
export const PLAN_VIEW_DESCRIPTION = [
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"用途:只读查看已保存的 todo 状态,用于前端 UI 展示、恢复工作上下文和汇报进度;不会执行任何任务,也不会修改计划。",
|
|
11
|
+
"只能看到当前聊天范围(同一 channel/to)的 todo;在同一部署和 stateDir 下,即使重新创建 agent session,也可找回该范围内的 todo。",
|
|
12
12
|
"",
|
|
13
13
|
"- 带 planId:返回该计划当前的完整清单。",
|
|
14
14
|
"- 不带 planId:返回最近计划的摘要列表,用于忘记或跨会话找回 planId。",
|
|
15
15
|
"",
|
|
16
|
-
"
|
|
16
|
+
"重要:查看只恢复记录,不会自动推进状态。若当前请求需要继续这项工作,再按 todo 状态推进,并在状态变化后用 xg_plan_write 回写。",
|
|
17
17
|
].join("\n");
|
|
18
18
|
function summarizePlan(plan) {
|
|
19
19
|
const taskCounts = { total: 0, completed: 0, blocked: 0, inProgress: 0 };
|
|
@@ -66,7 +66,7 @@ export function buildPlanViewTool(deps) {
|
|
|
66
66
|
planId: plan.planId,
|
|
67
67
|
view: renderPlanView(plan),
|
|
68
68
|
...(reminder !== undefined
|
|
69
|
-
? { reminder:
|
|
69
|
+
? { reminder: `该 todo 有未完成项;查看只恢复记录,不会自动推进状态。${reminder}` }
|
|
70
70
|
: {}),
|
|
71
71
|
};
|
|
72
72
|
return toolJsonResult(result);
|
package/dist/plan-view.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type Plan } from "@xgjktech/xg-openclaw-shared";
|
|
2
2
|
export declare function renderPlanView(plan: Plan): string;
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* 生成当前 todo 的状态提醒,帮助模型恢复工作上下文并及时回写状态。
|
|
5
5
|
* 规则:优先 in_progress(继续手头任务)→ 其次 pending(开新任务)→ 只剩 blocked 时提示等待;
|
|
6
6
|
* 全部完成或已取消则返回 undefined。
|
|
7
7
|
*/
|
package/dist/plan-view.js
CHANGED
|
@@ -28,7 +28,7 @@ export function renderPlanView(plan) {
|
|
|
28
28
|
return lines.join("\n");
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
*
|
|
31
|
+
* 生成当前 todo 的状态提醒,帮助模型恢复工作上下文并及时回写状态。
|
|
32
32
|
* 规则:优先 in_progress(继续手头任务)→ 其次 pending(开新任务)→ 只剩 blocked 时提示等待;
|
|
33
33
|
* 全部完成或已取消则返回 undefined。
|
|
34
34
|
*/
|
|
@@ -40,15 +40,15 @@ export function buildPlanReminder(plan) {
|
|
|
40
40
|
return undefined;
|
|
41
41
|
const inProgress = unfinished.find((task) => task.status === "in_progress");
|
|
42
42
|
if (inProgress !== undefined) {
|
|
43
|
-
return
|
|
43
|
+
return `当前 todo:继续处理「${singleLine(inProgress.title)}」;状态变化后用 xg_plan_write 回写`;
|
|
44
44
|
}
|
|
45
45
|
const pending = unfinished.find((task) => task.status === "pending");
|
|
46
46
|
if (pending !== undefined) {
|
|
47
|
-
return
|
|
47
|
+
return `当前 todo:待处理「${singleLine(pending.title)}」;开始后将状态更新为 in_progress`;
|
|
48
48
|
}
|
|
49
49
|
const blockedCount = unfinished.filter((task) => task.status === "blocked").length;
|
|
50
50
|
if (blockedCount > 0) {
|
|
51
|
-
return
|
|
51
|
+
return `当前 todo 有 ${blockedCount} 项 blocked,等待 note 中记录的条件满足后再推进`;
|
|
52
52
|
}
|
|
53
53
|
return undefined;
|
|
54
54
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-write-tool.d.ts","sourceRoot":"","sources":["../src/plan-write-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EAGf,MAAM,8BAA8B,CAAC;AA8BtC,eAAO,MAAM,eAAe;;;;;;;;;EAwB3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"plan-write-tool.d.ts","sourceRoot":"","sources":["../src/plan-write-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,KAAK,MAAM,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAIL,KAAK,UAAU,EACf,KAAK,SAAS,EAGf,MAAM,8BAA8B,CAAC;AA8BtC,eAAO,MAAM,eAAe;;;;;;;;;EAwB3B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D,eAAO,MAAM,sBAAsB,QA2BvB,CAAC;AA0Eb,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,YAAY,CA0HtF"}
|
package/dist/plan-write-tool.js
CHANGED
|
@@ -33,22 +33,25 @@ export const PlanWriteParams = Type.Object({
|
|
|
33
33
|
cancel: Type.Optional(Type.Boolean({ description: "取消该计划;true 时只需带 planId,不带 goal/tasks" })),
|
|
34
34
|
}, { additionalProperties: false });
|
|
35
35
|
export const PLAN_WRITE_DESCRIPTION = [
|
|
36
|
-
"
|
|
36
|
+
"用途:维护模型当前工作的 todo 状态,供前端 UI 展示,并可在后续回合恢复。每次调用都是整张替换,不是增量更新。",
|
|
37
37
|
"",
|
|
38
|
-
"
|
|
39
|
-
"-
|
|
40
|
-
"-
|
|
41
|
-
"-
|
|
38
|
+
"调用判断:收到执行型请求后,先在内部拆解工作项;满足以下任一条件,必须在开始实际工作前调用本工具,不需要等用户明确要求:",
|
|
39
|
+
"- 用户明确要求计划、任务清单或进度追踪。",
|
|
40
|
+
"- 需要等待用户回复、审批或外部系统。",
|
|
41
|
+
"- 有 3 个或以上用户可感知、可独立汇报完成状态的工作项。",
|
|
42
|
+
"- 同时包含调查、实施、验证等多个阶段。",
|
|
43
|
+
"- 涉及多个组件且工作项之间存在依赖,或可能中断后继续。",
|
|
42
44
|
"",
|
|
43
|
-
"
|
|
44
|
-
"-
|
|
45
|
-
"-
|
|
46
|
-
"- 用户明确要求任务清单或进度追踪。",
|
|
45
|
+
"以下情况直接执行,不建计划:",
|
|
46
|
+
"- 纯问答、查询、解释或闲聊,不涉及后续执行。",
|
|
47
|
+
"- 只有 1-2 个原子动作,且无需等待、恢复或向用户展示进度。",
|
|
47
48
|
"",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"-
|
|
49
|
+
"判断要求:不要以自己能否在当前回合完成作为判断依据;不要把分析、思考和试错过程写成 task,只记录需要向用户展示的工作项。",
|
|
50
|
+
"",
|
|
51
|
+
"工作协议(必须遵守):",
|
|
52
|
+
"- 本工具只记录 todo 状态并供 UI 展示:不执行、不调度、无后台运行。保存 todo ≠ 完成工作。",
|
|
53
|
+
"- 写入后继续处理当前请求;任务开始、完成、暂停或阻塞时,用本工具回写最新整张清单。",
|
|
54
|
+
"- 无法当场完成或需等待外部条件的项,标 in_progress(进行中)或 blocked(note 写明原因),后续回合恢复时再判断。",
|
|
52
55
|
"",
|
|
53
56
|
"提交规则:",
|
|
54
57
|
"- 新建时不传 planId;更新时传入原 planId。",
|
|
@@ -200,7 +203,7 @@ export function buildPlanWriteTool(store, origin) {
|
|
|
200
203
|
view: renderPlanView(plan),
|
|
201
204
|
...(warnings !== undefined ? { warnings } : {}),
|
|
202
205
|
...(reminder !== undefined
|
|
203
|
-
? { reminder:
|
|
206
|
+
? { reminder: `todo 已保存(仅记录,未执行)。${reminder}` }
|
|
204
207
|
: {}),
|
|
205
208
|
};
|
|
206
209
|
return toolJsonResult(result);
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
{
|
|
2
|
-
"id": "xg-harness-tools",
|
|
3
|
-
"name": "XG Harness Tools",
|
|
4
|
-
"description": "企业工具插件:计划管理与通用动作分发(plan_write / plan_view / action_dispatch)",
|
|
5
|
-
"version": "0.1
|
|
6
|
-
"configSchema": {
|
|
7
|
-
"type": "object",
|
|
8
|
-
"additionalProperties": true,
|
|
9
|
-
"properties": {}
|
|
10
|
-
},
|
|
11
|
-
"contracts": {
|
|
12
|
-
"tools": ["xg_plan_write", "xg_plan_view", "xg_action_dispatch"]
|
|
13
|
-
}
|
|
14
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"id": "xg-harness-tools",
|
|
3
|
+
"name": "XG Harness Tools",
|
|
4
|
+
"description": "企业工具插件:计划管理与通用动作分发(plan_write / plan_view / action_dispatch)",
|
|
5
|
+
"version": "0.4.1",
|
|
6
|
+
"configSchema": {
|
|
7
|
+
"type": "object",
|
|
8
|
+
"additionalProperties": true,
|
|
9
|
+
"properties": {}
|
|
10
|
+
},
|
|
11
|
+
"contracts": {
|
|
12
|
+
"tools": ["xg_plan_write", "xg_plan_view", "xg_action_dispatch"]
|
|
13
|
+
}
|
|
14
|
+
}
|
package/package.json
CHANGED
|
@@ -1,55 +1,57 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@xgjktech/xg-openclaw-harness-tools",
|
|
3
|
-
"version": "0.4.
|
|
4
|
-
"description": "企业工具插件:plan_write / plan_view / action_dispatch(OpenClaw 第三方工具插件)",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=22.19.0"
|
|
9
|
-
},
|
|
10
|
-
"main": "dist/index.js",
|
|
11
|
-
"types": "dist/index.d.ts",
|
|
12
|
-
"files": [
|
|
13
|
-
"dist/**/*",
|
|
14
|
-
"!dist/*.test.*",
|
|
15
|
-
"openclaw.plugin.json"
|
|
16
|
-
],
|
|
17
|
-
"publishConfig": {
|
|
18
|
-
"access": "public",
|
|
19
|
-
"registry": "https://registry.npmjs.org/"
|
|
20
|
-
},
|
|
21
|
-
"scripts": {
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@xgjktech/xg-openclaw-harness-tools",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "企业工具插件:plan_write / plan_view / action_dispatch(OpenClaw 第三方工具插件)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.19.0"
|
|
9
|
+
},
|
|
10
|
+
"main": "dist/index.js",
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"files": [
|
|
13
|
+
"dist/**/*",
|
|
14
|
+
"!dist/*.test.*",
|
|
15
|
+
"openclaw.plugin.json"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public",
|
|
19
|
+
"registry": "https://registry.npmjs.org/"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
23
|
+
"prebuild": "npm run clean",
|
|
24
|
+
"build": "tsc -p tsconfig.json",
|
|
25
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
26
|
+
"pretest": "npm run build",
|
|
27
|
+
"test": "node --test dist/*.test.js",
|
|
28
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"typebox": "1.1.39",
|
|
32
|
+
"@xgjktech/xg-openclaw-shared": "^0.2.2"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^22.19.0",
|
|
36
|
+
"openclaw": "2026.6.10",
|
|
37
|
+
"typescript": "^5.6.0"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"openclaw": ">=2026.6.10"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"openclaw": {
|
|
44
|
+
"optional": true
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"openclaw": {
|
|
48
|
+
"extensions": [
|
|
49
|
+
"./dist/index.js"
|
|
50
|
+
],
|
|
51
|
+
"installDependencies": false,
|
|
52
|
+
"install": {
|
|
53
|
+
"localPath": ".",
|
|
54
|
+
"defaultChoice": "local"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|