ppxans-harness 2.6.0 → 3.2.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.
Files changed (189) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +195 -195
  3. package/bin/ppx-channels.js +2 -2
  4. package/bin/ppx-serve.js +5 -5
  5. package/bin/ppx-setup.js +124 -0
  6. package/bin/ppx-web.js +140 -0
  7. package/bin/ppx.js +2 -2
  8. package/config/identity.md +6 -6
  9. package/config/ishiki.md +16 -16
  10. package/config/ppx.json +6 -124
  11. package/config/ppx.json.example +143 -0
  12. package/package.json +16 -6
  13. package/skills/.usage.json +6 -0
  14. package/skills/agent-professional-training/SKILL.md +94 -0
  15. package/skills/agent-professional-training/trajectories/2026-09-11-dpo-pairs.jsonl +2 -0
  16. package/skills/agent-professional-training/trajectories/2026-09-11-round2-trajectory.json +15 -0
  17. package/skills/agent-professional-training/trajectories/2026-09-13-first-run-trajectory.json +17 -0
  18. package/skills/brainstorm/SKILL.md +24 -0
  19. package/skills/cupid-lover-comms/SKILL.md +37 -0
  20. package/skills/debug/SKILL.md +26 -0
  21. package/skills/plan/SKILL.md +25 -0
  22. package/skills/ponytail/SKILL.md +25 -0
  23. package/skills/ppx-memory/SKILL.md +91 -0
  24. package/skills/ppx-memory/scripts/cli.js +192 -0
  25. package/skills/ppx-memory/scripts/experience.js +133 -0
  26. package/skills/ppx-memory/scripts/fact-store.js +842 -0
  27. package/skills/ppx-memory/scripts/l0.js +52 -0
  28. package/skills/ppx-memory/scripts/l2.js +146 -0
  29. package/skills/ppx-memory/scripts/l3.js +112 -0
  30. package/skills/ppx-memory/scripts/memory-ticker.js +238 -0
  31. package/skills/ppx-memory/scripts/pii.js +42 -0
  32. package/skills/ppx-memory/scripts/schema.js +80 -0
  33. package/skills/ppx-memory/scripts/session.js +398 -0
  34. package/skills/ppx-memory/scripts/similarity.js +43 -0
  35. package/skills/ppx-memory/scripts/store.js +116 -0
  36. package/skills/ppx-memory/scripts/wal.js +38 -0
  37. package/skills/ppx-selfheal/SKILL.md +24 -0
  38. package/skills/ppx-selfheal/scripts/cli.js +80 -0
  39. package/skills/ppx-selfheal/scripts/healer.js +184 -0
  40. package/skills/ppx-selfheal/scripts/logger.js +17 -0
  41. package/skills/ppx-selfheal/scripts/store.js +116 -0
  42. package/skills/prompt-depth-kit/SKILL.md +28 -0
  43. package/skills/session-naming/SKILL.md +36 -0
  44. package/skills/verify/SKILL.md +25 -0
  45. package/src/agent/index.js +1352 -717
  46. package/src/agent/prompts.js +46 -2
  47. package/src/aml-server.js +197 -151
  48. package/src/ans/eviction.js +123 -143
  49. package/src/ans/guard.js +159 -120
  50. package/src/ans/lifecycle.js +96 -93
  51. package/src/ans/proactive.js +112 -129
  52. package/src/ans/reward.js +95 -111
  53. package/src/ans/values.js +15 -15
  54. package/src/audit/audit-chain.js +43 -7
  55. package/src/audit/verifier.js +157 -120
  56. package/src/bus/circuit-breaker.js +9 -1
  57. package/src/bus/runtime-bus.js +107 -93
  58. package/src/channels/base.js +57 -34
  59. package/src/channels/feishu.js +118 -126
  60. package/src/channels/http.js +1090 -651
  61. package/src/channels/index.js +111 -110
  62. package/src/channels/log.js +29 -29
  63. package/src/channels/wechat-crypto.js +73 -74
  64. package/src/channels/wechat.js +191 -197
  65. package/src/channels/workspace.js +94 -0
  66. package/src/channels-cli.js +126 -124
  67. package/src/cli.js +129 -120
  68. package/src/commands/index.js +142 -0
  69. package/src/config/channels.js +137 -170
  70. package/src/config/index.js +277 -224
  71. package/src/config/placeholder.js +31 -0
  72. package/src/config/providers.js +148 -182
  73. package/src/config/settings.js +156 -182
  74. package/src/core/policy.js +69 -18
  75. package/src/core/trace.js +8 -6
  76. package/src/edit/editblock.js +266 -0
  77. package/src/edit/snapshot.js +67 -0
  78. package/src/evidence/index.js +153 -0
  79. package/src/evolve/playbook.js +9 -10
  80. package/src/hooks/index.js +113 -0
  81. package/src/llm/client.js +4 -3
  82. package/src/llm/dsml.js +74 -74
  83. package/src/llm/embedder.js +41 -35
  84. package/src/llm/fence.js +52 -52
  85. package/src/llm/index.js +4 -4
  86. package/src/llm/local-embedder.js +94 -0
  87. package/src/llm/presets.js +113 -0
  88. package/src/llm/pricing.js +93 -0
  89. package/src/llm/retry.js +73 -73
  90. package/src/llm/router.js +92 -89
  91. package/src/mcp/admin.js +44 -10
  92. package/src/mcp/client.js +487 -477
  93. package/src/mcp/http.js +23 -37
  94. package/src/mcp/index.js +116 -116
  95. package/src/mcp/server.js +23 -18
  96. package/src/mcp/tasks.js +9 -14
  97. package/src/memory/asset-hub.js +6 -11
  98. package/src/memory/canvas.js +2 -5
  99. package/src/memory/compaction.js +28 -28
  100. package/src/memory/experience.js +133 -122
  101. package/src/memory/fact-store.js +914 -698
  102. package/src/memory/failure-episode.js +20 -11
  103. package/src/memory/fork.js +17 -8
  104. package/src/memory/index.js +8 -6
  105. package/src/memory/l0.js +53 -52
  106. package/src/memory/l2.js +145 -130
  107. package/src/memory/l3.js +111 -111
  108. package/src/memory/legion-board.js +71 -0
  109. package/src/memory/memory-ticker.js +239 -240
  110. package/src/memory/session.js +398 -397
  111. package/src/memory/sqlite-store.js +581 -0
  112. package/src/mode/blackboard.js +49 -49
  113. package/src/mode/graph.js +42 -41
  114. package/src/mode/index.js +64 -64
  115. package/src/mode/legion.js +54 -51
  116. package/src/mode/plan-exec.js +50 -50
  117. package/src/mode/router.js +28 -40
  118. package/src/orchestrator/agent-worker.js +69 -69
  119. package/src/orchestrator/dag.js +90 -83
  120. package/src/orchestrator/experts.js +76 -0
  121. package/src/orchestrator/index.js +1 -1
  122. package/src/orchestrator/legion.js +179 -187
  123. package/src/orchestrator/supervisor.js +6 -8
  124. package/src/permissions/index.js +378 -0
  125. package/src/persona/index.js +28 -29
  126. package/src/plugin/builtin.js +313 -215
  127. package/src/plugin/context.js +80 -79
  128. package/src/plugin/index.js +62 -62
  129. package/src/plugin/v3.js +73 -0
  130. package/src/protocol/index.js +148 -0
  131. package/src/repomap/index.js +309 -0
  132. package/src/review/index.js +393 -0
  133. package/src/seam/registry.js +3 -0
  134. package/src/seam/shell.js +55 -55
  135. package/src/security/injection.js +79 -0
  136. package/src/selfheal/evolve.js +67 -67
  137. package/src/selfheal/healer.js +184 -167
  138. package/src/selfheal/run.js +9 -9
  139. package/src/server.js +63 -60
  140. package/src/services/diagnose.js +180 -0
  141. package/src/services/learning-service.js +9 -0
  142. package/src/services/memory-health.js +34 -6
  143. package/src/services/memory-service.js +42 -9
  144. package/src/services/triage.js +138 -0
  145. package/src/session/parts.js +76 -0
  146. package/src/session/projection.js +73 -0
  147. package/src/session/rollout.js +54 -0
  148. package/src/session/turn.js +137 -0
  149. package/src/skills/lint.js +72 -0
  150. package/src/skills/loader.js +231 -150
  151. package/src/skills/search.js +58 -0
  152. package/src/skills/verify.js +95 -100
  153. package/src/tools/advanced.js +388 -352
  154. package/src/tools/builtin.js +384 -297
  155. package/src/tools/catalog.js +283 -159
  156. package/src/tools/command-guard.js +112 -112
  157. package/src/tools/custom.js +47 -47
  158. package/src/tools/delegate.js +383 -297
  159. package/src/tools/document.js +254 -253
  160. package/src/tools/git.js +151 -0
  161. package/src/tools/governance.js +47 -20
  162. package/src/tools/index.js +16 -11
  163. package/src/tools/methods.js +178 -178
  164. package/src/tools/ocr.js +59 -59
  165. package/src/tools/sandbox-worker.js +40 -0
  166. package/src/tools/sandbox.js +92 -0
  167. package/src/tools/seam.js +162 -125
  168. package/src/tools/selfmod.js +196 -176
  169. package/src/tools/v3.js +225 -0
  170. package/src/tools/vad.js +176 -0
  171. package/src/tools/voice.js +238 -0
  172. package/src/utils/async.js +14 -0
  173. package/src/utils/config-file.js +53 -0
  174. package/src/utils/crashguard.js +88 -0
  175. package/src/utils/http.js +53 -0
  176. package/src/utils/id.js +8 -0
  177. package/src/utils/json-state.js +33 -0
  178. package/src/utils/logger.js +17 -17
  179. package/src/utils/ndjson.js +25 -0
  180. package/src/utils/pii.js +42 -42
  181. package/src/utils/rate-limit.js +50 -0
  182. package/src/utils/schema.js +80 -0
  183. package/src/utils/similarity.js +43 -0
  184. package/src/utils/store.js +170 -108
  185. package/src/utils/text.js +15 -15
  186. package/src/utils/trace.js +153 -153
  187. package/src/utils/wal.js +39 -0
  188. package/src/utils/winutf8.js +16 -15
  189. package/src/wiki/index.js +170 -0
@@ -0,0 +1,151 @@
1
+ // src/tools/git.js - Git 集成工具 (结构化 + 护栏)
2
+ // 对齐主流 Agent 实践 (aider 自动提交 / Claude Code / OpenHands / Cline):
3
+ // 版本控制是编码 Agent 的标配一等工具, 但必须有硬护栏 —
4
+ // ① 只读工具 (status/diff/log) 幂等无副作用;
5
+ // ② git_commit 仅限 add+commit, 禁止 push / reset / rebase / clean / force (无此工具即无此能力);
6
+ // ③ 全部走 execFile 参数数组, 不经 shell, 命令注入不可能;
7
+ // ④ 输出截断到 toolResultBudget 级别, 防 diff 巨型化撑爆上下文。
8
+ // 2026-10-01 新增 (GitHub 主流 Agent 对标轮)。
9
+ import { execFileSync } from "node:child_process";
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+
13
+ const OUT_CAP = 4000;
14
+ const MSG_CAP = 500;
15
+
16
+ function findRepoRoot(rootDir) {
17
+ let dir = path.resolve(rootDir);
18
+ for (let i = 0; i < 32; i++) {
19
+ if (fs.existsSync(path.join(dir, ".git"))) return dir;
20
+ const parent = path.dirname(dir);
21
+ if (parent === dir) return null;
22
+ dir = parent;
23
+ }
24
+ return null;
25
+ }
26
+
27
+ function git(rootDir, args, timeoutMs = 15000) {
28
+ const repo = findRepoRoot(rootDir);
29
+ if (!repo) throw new Error("不在 git 仓库内 (未找到 .git)");
30
+ return execFileSync("git", args, {
31
+ cwd: repo,
32
+ timeout: timeoutMs,
33
+ maxBuffer: 8 * 1024 * 1024,
34
+ encoding: "utf8",
35
+ });
36
+ }
37
+
38
+ function cap(s) {
39
+ return String(s || "").length > OUT_CAP
40
+ ? String(s).slice(0, OUT_CAP) + `\n…[已截断, 共 ${String(s).length} 字符]`
41
+ : String(s || "");
42
+ }
43
+
44
+ export function registerGitTools(catalog, { rootDir } = {}) {
45
+ // 1. git_status — 分支 + 变更清单 (结构化)
46
+ catalog.register({
47
+ name: "git_status",
48
+ description: "查看 git 仓库状态: 当前分支与变更文件清单 (结构化 JSON)。提交前先看这里。",
49
+ parameters: { type: "object", properties: {}, required: [] },
50
+ category: "vcs",
51
+ power: "user",
52
+ idempotent: true,
53
+ execute: async () => {
54
+ try {
55
+ const branch = git(rootDir, ["rev-parse", "--abbrev-ref", "HEAD"]).trim();
56
+ const porcelain = git(rootDir, ["status", "--porcelain", "-b"]);
57
+ const lines = porcelain.split("\n").filter(Boolean);
58
+ const changes = lines.filter((l) => !l.startsWith("##"));
59
+ return JSON.stringify({
60
+ branch,
61
+ clean: changes.length === 0,
62
+ entries: changes.map((l) => ({ x: l.slice(0, 2).trim(), file: l.slice(3).trim() })),
63
+ });
64
+ } catch (e) {
65
+ return JSON.stringify({ error: (e.message || "").slice(0, 200) });
66
+ }
67
+ },
68
+ });
69
+
70
+ // 2. git_diff — 查看改动内容
71
+ catalog.register({
72
+ name: "git_diff",
73
+ description: "查看未提交改动 (git diff)。staged=true 只看已暂存区; path 可限定单个文件。",
74
+ parameters: {
75
+ type: "object",
76
+ properties: { staged: { type: "boolean" }, path: { type: "string" } },
77
+ required: [],
78
+ },
79
+ category: "vcs",
80
+ power: "user",
81
+ idempotent: true,
82
+ execute: async (args) => {
83
+ try {
84
+ const a = ["diff", "--no-color"];
85
+ if (args.staged) a.push("--staged");
86
+ if (args.path) a.push("--", args.path);
87
+ return cap(git(rootDir, a));
88
+ } catch (e) {
89
+ return "[git 错误] " + (e.message || "").slice(0, 200);
90
+ }
91
+ },
92
+ });
93
+
94
+ // 3. git_log — 最近提交历史
95
+ catalog.register({
96
+ name: "git_log",
97
+ description: "查看最近提交历史 (默认 10 条, 上限 50)。",
98
+ parameters: { type: "object", properties: { n: { type: "number" } }, required: [] },
99
+ category: "vcs",
100
+ power: "user",
101
+ idempotent: true,
102
+ execute: async (args) => {
103
+ const n = Math.min(Math.max(Number(args.n) || 10, 1), 50);
104
+ try {
105
+ const raw = git(rootDir, ["log", `-${n}`, "--pretty=format:%h|%an|%ad|%s", "--date=short"]);
106
+ return JSON.stringify({
107
+ commits: raw.split("\n").filter(Boolean).map((l) => {
108
+ const [hash, author, date, ...rest] = l.split("|");
109
+ return { hash, author, date, subject: rest.join("|") };
110
+ }),
111
+ });
112
+ } catch {
113
+ return JSON.stringify({ commits: [] }); // 空仓库 (尚无任何提交)
114
+ }
115
+ },
116
+ });
117
+
118
+ // 4. git_commit — 受限提交 (唯一写操作; 无 push/reset/rebase 能力)
119
+ catalog.register({
120
+ name: "git_commit",
121
+ description: "提交当前改动 (仅 add+commit)。add_all=true 时先暂存全部改动。禁止也不支持 push/reset 等危险操作。",
122
+ parameters: {
123
+ type: "object",
124
+ properties: {
125
+ message: { type: "string", description: "提交信息 (≤500 字符)" },
126
+ add_all: { type: "boolean", description: "先暂存全部改动 (git add -A)" },
127
+ },
128
+ required: ["message"],
129
+ },
130
+ category: "vcs",
131
+ power: "agent",
132
+ execute: async (args) => {
133
+ const message = String(args.message || "").trim();
134
+ if (!message) return "[工具错误] git_commit: 需要 message";
135
+ if (message.length > MSG_CAP) return `[工具错误] git_commit: message 超过 ${MSG_CAP} 字符`;
136
+ const staged = args.add_all === true;
137
+ if (staged) git(rootDir, ["add", "-A"]);
138
+ // 无暂存改动时 commit 会失败, 先探测给出可读错误
139
+ const nothing = git(rootDir, ["status", "--porcelain"]).split("\n").filter(Boolean).length === 0
140
+ && git(rootDir, ["diff", "--staged", "--quiet"]).length === 0;
141
+ if (nothing && !staged) return JSON.stringify({ ok: false, error: "没有可提交的改动 (工作区干净且暂存区为空)" });
142
+ try {
143
+ const out = git(rootDir, ["commit", "-m", message]);
144
+ const hash = (out.match(/\[[^\]]+ ([0-9a-f]+)\]/) || [])[1] || "";
145
+ return JSON.stringify({ ok: true, hash, message });
146
+ } catch (e) {
147
+ return JSON.stringify({ ok: false, error: (e.message || "").slice(0, 300) });
148
+ }
149
+ },
150
+ });
151
+ }
@@ -3,6 +3,10 @@
3
3
  // + audit_verify, 以及 ppx-memory/ppx-selfheal 暴露的 persona_build/persona_read/selfheal_run。
4
4
  // 改写: ppx-v2 原版用 cordis 的 defineTool + @deepseek-ai/schemastery (z.object) 声明,
5
5
  // 这里改写为 ppx-agent 原生的 ToolCatalog.register 风格, 剥离全部外部依赖。
6
+ //
7
+ // 2026-09-18 重构: 原先是一个 250 行的单一注册函数 (10 个工具挤在一起)。
8
+ // 现按文件头注自身的分组拆成三个具名函数, 找某个工具时可直接跳到对应组;
9
+ // 对外的 registerGovernanceTools 签名与返回值完全不变。
6
10
  import fs from "node:fs";
7
11
  import path from "node:path";
8
12
  import { safePath } from "./builtin.js";
@@ -10,8 +14,19 @@ import { ensureDir, nowISO } from "../utils/store.js";
10
14
 
11
15
  // 记忆治理 + 审计 + 运维工具注册
12
16
  // deps: { rootDir, facts, audit, personaStore, healer, experience, dataDir }
13
- export function registerGovernanceTools(catalog, { rootDir, facts, audit, personaStore, healer, experience, dataDir } = {}) {
17
+ export function registerGovernanceTools(catalog, deps = {}) {
18
+ registerMemoryGovernanceTools(catalog, deps);
19
+ registerAuditTools(catalog, deps);
20
+ registerOpsTools(catalog, deps);
21
+ return catalog;
22
+ }
23
+
24
+ // ---- 组 1: 记忆治理 (forget / restore / list_deleted / export / import / clear_layer) ----
25
+ // 设计原则: 默认软删可回滚, 物理删除必须显式 hard=true —— 治理动作不可逆是最大的风险面。
26
+ function registerMemoryGovernanceTools(catalog, { rootDir, facts, dataDir } = {}) {
14
27
  const exportsDir = path.join(rootDir || dataDir || ".", "exports");
28
+ // 记忆服务未装配时的统一降级响应 (6 个 memory_* 工具共用, 改文案只动这一处)
29
+ const noFacts = () => JSON.stringify({ error: "记忆未初始化" });
15
30
 
16
31
  // 1. 遗忘 (软删, 可回滚) —— ppx-agent 原版只有不可逆硬删, 这是最大的治理缺口
17
32
  catalog.register({
@@ -21,17 +36,21 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
21
36
  type: "object",
22
37
  properties: {
23
38
  id_or_content: { type: "string", description: "记忆 id 或内容 (按内容精确匹配, 去记忆动词前缀后比对)" },
39
+ id: { type: "string", description: "记忆 id (与 id_or_content 二选一, 与 memory_restore 参数名对齐)" },
24
40
  reason: { type: "string", description: "遗忘原因 (记入审计, 便于后续复核)" },
25
41
  },
26
- required: ["id_or_content"],
42
+ required: [],
27
43
  },
28
44
  category: "memory",
29
45
  power: "user",
30
46
  idempotent: true,
31
47
  execute: async (args) => {
32
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
33
- const f = facts.forget(args.id_or_content, { reason: args.reason || null });
34
- if (!f) return JSON.stringify({ error: "未找到匹配记忆", target: args.id_or_content });
48
+ if (!facts) return noFacts();
49
+ // 2026-10-03 统一: 兼容接受 id (与 memory_restore 同名), 消除两个工具参数命名不一致
50
+ const target = args.id_or_content || args.id;
51
+ if (!target) return JSON.stringify({ error: "缺少必填参数 id 或 id_or_content" });
52
+ const f = facts.forget(target, { reason: args.reason || null });
53
+ if (!f) return JSON.stringify({ error: "未找到匹配记忆", target });
35
54
  return JSON.stringify({ ok: true, id: f.id, content: f.content, status: f.status, note: "已软删, 可用 memory_restore 回滚" });
36
55
  },
37
56
  });
@@ -42,16 +61,21 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
42
61
  description: "恢复一条被遗忘 (软删) 的记忆。",
43
62
  parameters: {
44
63
  type: "object",
45
- properties: { id: { type: "string", description: "记忆 id" } },
46
- required: ["id"],
64
+ properties: {
65
+ id: { type: "string", description: "记忆 id" },
66
+ id_or_content: { type: "string", description: "记忆 id 或内容 (与 id 二选一, 兼容 memory_forget 参数名)" },
67
+ },
68
+ required: [],
47
69
  },
48
70
  category: "memory",
49
71
  power: "user",
50
72
  idempotent: true,
51
73
  execute: async (args) => {
52
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
53
- const f = facts.restore(args.id);
54
- if (!f) return JSON.stringify({ error: "未找到该记忆", id: args.id });
74
+ if (!facts) return noFacts();
75
+ // 2026-10-03 统一: 兼容接受 id_or_content (与 memory_forget 同名)
76
+ const target = args.id || args.id_or_content;
77
+ const f = facts.restore(target);
78
+ if (!f) return JSON.stringify({ error: "未找到该记忆", id: target });
55
79
  return JSON.stringify({ ok: true, id: f.id, content: f.content, status: f.status });
56
80
  },
57
81
  });
@@ -69,7 +93,7 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
69
93
  power: "user",
70
94
  idempotent: true,
71
95
  execute: async (args) => {
72
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
96
+ if (!facts) return noFacts();
73
97
  const list = facts.deletedList().slice(0, args.limit || 20);
74
98
  if (!list.length) return "(无已遗忘的记忆)";
75
99
  return list.map((f) => `- ${f.id} | ${f.deletedAt || "?"} | ${f.deleteReason || "无原因"} | ${f.content}`).join("\n");
@@ -92,7 +116,7 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
92
116
  power: "user",
93
117
  idempotent: true,
94
118
  execute: async (args) => {
95
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
119
+ if (!facts) return noFacts();
96
120
  const dump = facts.exportAll({ includeDeleted: args.include_deleted !== false });
97
121
  let out;
98
122
  if (args.file) {
@@ -123,7 +147,7 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
123
147
  power: "user",
124
148
  idempotent: false,
125
149
  execute: async (args) => {
126
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
150
+ if (!facts) return noFacts();
127
151
  const fp = safePath(rootDir || ".", args.file);
128
152
  if (!fs.existsSync(fp)) return JSON.stringify({ error: "文件不存在", file: args.file });
129
153
  let payload;
@@ -149,13 +173,15 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
149
173
  power: "user",
150
174
  idempotent: false,
151
175
  execute: async (args) => {
152
- if (!facts) return JSON.stringify({ error: "记忆未初始化" });
176
+ if (!facts) return noFacts();
153
177
  const r = facts.clearLayer(Number(args.layer), { hard: args.hard === true });
154
178
  return JSON.stringify({ ok: true, ...r, note: r.hard ? "已物理删除" : "已软删, 可用 memory_restore 逐条回滚" });
155
179
  },
156
180
  });
181
+ }
157
182
 
158
- // 7. 审计链校验 (吸收自 ppx-v2 audit.js: SHA-256 哈希链防篡改验证)
183
+ // ---- 组 2: 审计链校验 (吸收自 ppx-v2 audit.js: SHA-256 哈希链防篡改验证) ----
184
+ function registerAuditTools(catalog, { audit } = {}) {
159
185
  catalog.register({
160
186
  name: "audit_verify",
161
187
  description: "校验工具调用审计日志的 SHA-256 哈希链完整性, 定位首个被篡改/截断的位置。quarantine=true 时隔离损坏段并重建空链。",
@@ -187,8 +213,11 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
187
213
  return JSON.stringify(out);
188
214
  },
189
215
  });
216
+ }
190
217
 
191
- // 8. 画像重建 (ppx-v2 ppx-memory 的 persona_build, 这里薄包装 l3 PersonaStore)
218
+ // ---- 组 3: 运维 (画像重建/读取 + 自愈体检) ----
219
+ function registerOpsTools(catalog, { personaStore, healer, experience, facts } = {}) {
220
+ // 7. 画像重建 (ppx-v2 ppx-memory 的 persona_build, 这里薄包装 l3 PersonaStore)
192
221
  catalog.register({
193
222
  name: "persona_build",
194
223
  description: "从当前记忆与经验重新提炼用户画像 / agent 人格, 写入 L3 层。",
@@ -217,7 +246,7 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
217
246
  },
218
247
  });
219
248
 
220
- // 9. 画像读取
249
+ // 8. 画像读取
221
250
  catalog.register({
222
251
  name: "persona_read",
223
252
  description: "读取 L3 层沉淀的用户画像 / agent 人格全文。",
@@ -237,7 +266,7 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
237
266
  },
238
267
  });
239
268
 
240
- // 10. 自愈体检 (ppx-v2 selfheal_run, 薄包装 Healer)
269
+ // 9. 自愈体检 (ppx-v2 selfheal_run, 薄包装 Healer)
241
270
  catalog.register({
242
271
  name: "selfheal_run",
243
272
  description: "手动跑一次自愈体检: 补建缺失目录、修复损坏 JSON、清理崩溃残留与过期备份。",
@@ -255,6 +284,4 @@ export function registerGovernanceTools(catalog, { rootDir, facts, audit, person
255
284
  return JSON.stringify({ ok: true, healedAt: nowISO(), health });
256
285
  },
257
286
  });
258
-
259
- return catalog;
260
287
  }
@@ -1,11 +1,16 @@
1
- // src/tools/index.js - 工具系统统一出口
2
- export { ToolCatalog, TOOL_ERROR_PREFIX } from "./catalog.js";
3
- export { normalizeMeta, runWithPolicy, toDescriptor } from "./seam.js";
4
- export { registerBuiltinTools } from "./builtin.js";
5
- export { registerAdvancedTools, Scheduler } from "./advanced.js";
6
- export { registerMethodTools } from "./methods.js";
7
- export { registerSelfmodTools } from "./selfmod.js";
8
- export { registerCustomTools } from "./custom.js";
9
- export { registerDocumentTools } from "./document.js";
10
- // 记忆治理 + 审计 + 运维 (吸收自 ppx-v2)
11
- export { registerGovernanceTools } from "./governance.js";
1
+ // src/tools/index.js - 工具系统统一出口
2
+ export { ToolCatalog, TOOL_ERROR_PREFIX } from "./catalog.js";
3
+ export { normalizeMeta, runWithPolicy, toDescriptor } from "./seam.js";
4
+ export { registerBuiltinTools } from "./builtin.js";
5
+ export { registerAdvancedTools, Scheduler } from "./advanced.js";
6
+ export { registerMethodTools } from "./methods.js";
7
+ export { registerSelfmodTools } from "./selfmod.js";
8
+ export { registerCustomTools } from "./custom.js";
9
+ export { registerDocumentTools } from "./document.js";
10
+ // 记忆治理 + 审计 + 运维 (吸收自 ppx-v2)
11
+ export { registerGovernanceTools } from "./governance.js";
12
+ export { registerGitTools } from "./git.js";
13
+ export { registerVoiceTools, resolveVoice, resolveLocalAsr, voiceStatus } from "./voice.js";
14
+ // v3.1: 内置 JS 沙箱执行器 (CodeAct) + 语音活动检测 (VAD)
15
+ export { registerSandboxTools, runInSandbox } from "./sandbox.js";
16
+ export { registerVadTools, energyVad, parseWavPcm16 } from "./vad.js";