ppxans-harness 2.4.0 → 3.2.0
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/LICENSE +201 -201
- package/README.md +218 -265
- package/bin/ppx-channels.js +2 -2
- package/bin/ppx-serve.js +5 -5
- package/bin/ppx-setup.js +124 -0
- package/bin/ppx-web.js +140 -0
- package/bin/ppx.js +2 -2
- package/config/identity.md +6 -6
- package/config/ishiki.md +16 -16
- package/config/ppx.json +15 -151
- package/config/ppx.json.example +143 -0
- package/package.json +17 -10
- package/skills/.usage.json +6 -0
- package/skills/agent-professional-training/SKILL.md +94 -0
- package/skills/brainstorm/SKILL.md +24 -0
- package/skills/cupid-lover-comms/SKILL.md +37 -0
- package/skills/debug/SKILL.md +26 -0
- package/skills/plan/SKILL.md +25 -0
- package/skills/ponytail/SKILL.md +25 -0
- package/skills/ppx-memory/SKILL.md +91 -0
- package/skills/ppx-memory/scripts/cli.js +192 -0
- package/skills/ppx-memory/scripts/experience.js +133 -0
- package/skills/ppx-memory/scripts/fact-store.js +842 -0
- package/skills/ppx-memory/scripts/l0.js +52 -0
- package/skills/ppx-memory/scripts/l2.js +146 -0
- package/skills/ppx-memory/scripts/l3.js +112 -0
- package/skills/ppx-memory/scripts/memory-ticker.js +238 -0
- package/skills/ppx-memory/scripts/pii.js +42 -0
- package/skills/ppx-memory/scripts/schema.js +80 -0
- package/skills/ppx-memory/scripts/session.js +398 -0
- package/skills/ppx-memory/scripts/similarity.js +43 -0
- package/skills/ppx-memory/scripts/store.js +116 -0
- package/skills/ppx-memory/scripts/wal.js +38 -0
- package/skills/ppx-selfheal/SKILL.md +24 -0
- package/skills/ppx-selfheal/scripts/cli.js +80 -0
- package/skills/ppx-selfheal/scripts/healer.js +184 -0
- package/skills/ppx-selfheal/scripts/logger.js +17 -0
- package/skills/ppx-selfheal/scripts/store.js +116 -0
- package/skills/prompt-depth-kit/SKILL.md +28 -0
- package/skills/session-naming/SKILL.md +36 -0
- package/skills/verify/SKILL.md +25 -0
- package/src/agent/index.js +1340 -717
- package/src/agent/prompts.js +47 -3
- package/src/aml-server.js +197 -151
- package/src/ans/eviction.js +123 -143
- package/src/ans/guard.js +159 -120
- package/src/ans/lifecycle.js +96 -93
- package/src/ans/proactive.js +112 -129
- package/src/ans/reward.js +95 -111
- package/src/ans/values.js +15 -15
- package/src/audit/audit-chain.js +43 -7
- package/src/audit/verifier.js +157 -120
- package/src/bus/circuit-breaker.js +9 -1
- package/src/bus/runtime-bus.js +107 -93
- package/src/channels/base.js +57 -34
- package/src/channels/feishu.js +118 -126
- package/src/channels/http.js +1090 -592
- package/src/channels/index.js +111 -110
- package/src/channels/log.js +29 -29
- package/src/channels/wechat-crypto.js +73 -74
- package/src/channels/wechat.js +191 -197
- package/src/channels/workspace.js +94 -0
- package/src/channels-cli.js +126 -124
- package/src/cli.js +129 -120
- package/src/commands/index.js +142 -0
- package/src/config/channels.js +137 -170
- package/src/config/index.js +277 -224
- package/src/config/placeholder.js +31 -0
- package/src/config/providers.js +148 -188
- package/src/config/settings.js +156 -182
- package/src/core/policy.js +69 -18
- package/src/core/trace.js +8 -6
- package/src/edit/editblock.js +266 -0
- package/src/edit/snapshot.js +67 -0
- package/src/evidence/index.js +153 -0
- package/src/evolve/playbook.js +9 -10
- package/src/hooks/index.js +113 -0
- package/src/llm/client.js +188 -446
- package/src/llm/dsml.js +74 -74
- package/src/llm/embedder.js +41 -35
- package/src/llm/fence.js +52 -105
- package/src/llm/index.js +4 -4
- package/src/llm/local-embedder.js +94 -0
- package/src/llm/presets.js +113 -0
- package/src/llm/pricing.js +93 -0
- package/src/llm/retry.js +73 -73
- package/src/llm/router.js +92 -97
- package/src/mcp/admin.js +326 -0
- package/src/mcp/client.js +487 -375
- package/src/mcp/http.js +203 -0
- package/src/mcp/index.js +116 -116
- package/src/mcp/server.js +392 -0
- package/src/mcp/tasks.js +133 -0
- package/src/memory/asset-hub.js +6 -11
- package/src/memory/canvas.js +2 -5
- package/src/memory/compaction.js +28 -28
- package/src/memory/experience.js +133 -122
- package/src/memory/fact-store.js +914 -698
- package/src/memory/failure-episode.js +20 -11
- package/src/memory/fork.js +17 -8
- package/src/memory/index.js +8 -6
- package/src/memory/l0.js +53 -52
- package/src/memory/l2.js +145 -130
- package/src/memory/l3.js +111 -111
- package/src/memory/legion-board.js +71 -0
- package/src/memory/memory-ticker.js +239 -240
- package/src/memory/session.js +398 -397
- package/src/memory/sqlite-store.js +581 -0
- package/src/mode/blackboard.js +49 -49
- package/src/mode/graph.js +42 -41
- package/src/mode/index.js +64 -64
- package/src/mode/legion.js +54 -51
- package/src/mode/plan-exec.js +50 -50
- package/src/mode/router.js +28 -40
- package/src/orchestrator/agent-worker.js +69 -69
- package/src/orchestrator/dag.js +90 -83
- package/src/orchestrator/experts.js +76 -0
- package/src/orchestrator/index.js +1 -1
- package/src/orchestrator/legion.js +179 -187
- package/src/orchestrator/supervisor.js +6 -8
- package/src/permissions/index.js +378 -0
- package/src/persona/index.js +28 -29
- package/src/plugin/builtin.js +313 -212
- package/src/plugin/context.js +80 -79
- package/src/plugin/index.js +62 -62
- package/src/plugin/v3.js +73 -0
- package/src/protocol/index.js +148 -0
- package/src/repomap/index.js +309 -0
- package/src/review/index.js +393 -0
- package/src/seam/registry.js +3 -0
- package/src/seam/shell.js +55 -55
- package/src/security/injection.js +79 -0
- package/src/selfheal/evolve.js +67 -67
- package/src/selfheal/healer.js +184 -167
- package/src/selfheal/run.js +9 -9
- package/src/server.js +63 -60
- package/src/services/diagnose.js +180 -0
- package/src/services/learning-service.js +9 -0
- package/src/services/memory-health.js +34 -6
- package/src/services/memory-service.js +42 -9
- package/src/services/triage.js +138 -0
- package/src/session/parts.js +76 -0
- package/src/session/projection.js +73 -0
- package/src/session/rollout.js +54 -0
- package/src/session/turn.js +137 -0
- package/src/skills/lint.js +72 -0
- package/src/skills/loader.js +231 -150
- package/src/skills/search.js +58 -0
- package/src/skills/verify.js +95 -100
- package/src/tools/advanced.js +388 -352
- package/src/tools/builtin.js +384 -297
- package/src/tools/catalog.js +283 -159
- package/src/tools/command-guard.js +112 -112
- package/src/tools/custom.js +47 -47
- package/src/tools/delegate.js +383 -297
- package/src/tools/document.js +254 -253
- package/src/tools/git.js +151 -0
- package/src/tools/governance.js +47 -20
- package/src/tools/index.js +16 -11
- package/src/tools/methods.js +178 -178
- package/src/tools/ocr.js +59 -59
- package/src/tools/sandbox-worker.js +40 -0
- package/src/tools/sandbox.js +92 -0
- package/src/tools/seam.js +162 -125
- package/src/tools/selfmod.js +196 -176
- package/src/tools/v3.js +225 -0
- package/src/tools/vad.js +176 -0
- package/src/tools/voice.js +238 -0
- package/src/utils/async.js +14 -0
- package/src/utils/config-file.js +53 -0
- package/src/utils/crashguard.js +88 -0
- package/src/utils/http.js +53 -0
- package/src/utils/id.js +8 -0
- package/src/utils/json-state.js +33 -0
- package/src/utils/logger.js +17 -17
- package/src/utils/ndjson.js +25 -0
- package/src/utils/pii.js +42 -42
- package/src/utils/rate-limit.js +50 -0
- package/src/utils/schema.js +80 -0
- package/src/utils/similarity.js +43 -0
- package/src/utils/store.js +170 -108
- package/src/utils/text.js +15 -15
- package/src/utils/trace.js +153 -153
- package/src/utils/wal.js +39 -0
- package/src/utils/winutf8.js +16 -15
- package/src/wiki/index.js +170 -0
package/src/plugin/builtin.js
CHANGED
|
@@ -1,212 +1,313 @@
|
|
|
1
|
-
// src/plugin/builtin.js - 皮皮虾内置插件集 (一切皆插件)
|
|
2
|
-
// 借鉴 deepseek-harness 的 "everything is a plugin": 每个模块是一个插件, 通过 ctx.provide 注册服务。
|
|
3
|
-
// 装配顺序即依赖顺序 (依赖在前), 任何插件都可被用户插件替换或扩展。
|
|
4
|
-
import path from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
ctx.provide("
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
ctx.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
ctx.provide("
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
ctx.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ctx.provide("
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
ctx.provide("
|
|
164
|
-
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
export const
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
//
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
]
|
|
1
|
+
// src/plugin/builtin.js - 皮皮虾内置插件集 (一切皆插件)
|
|
2
|
+
// 借鉴 deepseek-harness 的 "everything is a plugin": 每个模块是一个插件, 通过 ctx.provide 注册服务。
|
|
3
|
+
// 装配顺序即依赖顺序 (依赖在前), 任何插件都可被用户插件替换或扩展。
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { info, warn } from "../utils/logger.js";
|
|
6
|
+
import { Healer } from "../selfheal/healer.js";
|
|
7
|
+
import { Persona } from "../persona/index.js";
|
|
8
|
+
import { FactStore, SqliteFactStore, MemoryTicker, Experience, L0Recorder, SceneStore, PersonaStore, LegionBoard } from "../memory/index.js";
|
|
9
|
+
import { SessionStore } from "../memory/session.js";
|
|
10
|
+
import {
|
|
11
|
+
ToolCatalog, registerBuiltinTools, registerAdvancedTools, Scheduler,
|
|
12
|
+
registerMethodTools, registerSelfmodTools, registerCustomTools, registerDocumentTools,
|
|
13
|
+
registerGovernanceTools,
|
|
14
|
+
registerVoiceTools,
|
|
15
|
+
registerSandboxTools,
|
|
16
|
+
registerVadTools,
|
|
17
|
+
} from "../tools/index.js";
|
|
18
|
+
import { embedderFromConfig } from "../llm/embedder.js";
|
|
19
|
+
import { LocalShellProvider } from "../seam/shell.js";
|
|
20
|
+
import { registerDelegateTools } from "../tools/delegate.js";
|
|
21
|
+
import { Traces } from "../utils/trace.js";
|
|
22
|
+
import { AuditLog } from "../audit/audit-chain.js";
|
|
23
|
+
import { RuntimeBus } from "../bus/runtime-bus.js";
|
|
24
|
+
import { PlaybookStore } from "../evolve/playbook.js";
|
|
25
|
+
import { MemoryHealthMonitor } from "../services/memory-health.js";
|
|
26
|
+
import { FailureEpisodeStore } from "../memory/failure-episode.js";
|
|
27
|
+
import { CanvasStore } from "../memory/canvas.js";
|
|
28
|
+
import { AssetHub } from "../memory/asset-hub.js";
|
|
29
|
+
import { exportMemorySnapshot, mergeSnapshotBack, hasSnapshot } from "../memory/fork.js";
|
|
30
|
+
// v3.0 (codex 对齐): 新工具 (repo_map/apply_patch/review_code/goal_board)
|
|
31
|
+
import { registerV3Tools } from "../tools/v3.js";
|
|
32
|
+
// v3.0.1 (GitHub 主流 Agent 对标): git 集成工具 (aider/Claude Code/OpenHands 标配, 带硬护栏)
|
|
33
|
+
import { registerGitTools } from "../tools/git.js";
|
|
34
|
+
|
|
35
|
+
// fork 工具 (供 ctx.consume("fork") 取用)
|
|
36
|
+
const forkTools = { exportMemorySnapshot, mergeSnapshotBack, hasSnapshot };
|
|
37
|
+
// LLM 路由: import 本地绑定 + re-export 向后兼容 (v2.5.0 修复: 仅 export-from 不产生本地绑定,
|
|
38
|
+
// 导致 llmPlugin 里 resolveLLM/resolveAllLLMs 未定义, 插件装配被隔离且 LLM 实际未注入)
|
|
39
|
+
import { isUsableProvider, resolveLLM, resolveAllLLMs } from "../llm/router.js";
|
|
40
|
+
export { isUsableProvider, resolveLLM, resolveAllLLMs };
|
|
41
|
+
import { ModeRegistry, registerDefaultModes } from "../mode/index.js";
|
|
42
|
+
import { planExecExecutor } from "../mode/plan-exec.js";
|
|
43
|
+
import { routerExecutor } from "../mode/router.js";
|
|
44
|
+
import { blackboardExecutor } from "../mode/blackboard.js";
|
|
45
|
+
import { graphExecutor } from "../mode/graph.js";
|
|
46
|
+
import { legionExecutor } from "../mode/legion.js";
|
|
47
|
+
|
|
48
|
+
// ---- LLM 路由 (唯一真相源已迁至 src/llm/router.js, 此文件仅 re-export 向后兼容) ----
|
|
49
|
+
// router.js 负责: 占位死配置过滤 / 云端真key优先 / 本地零配置兜底 / 健康排序 / PPX_PROVIDER 强制
|
|
50
|
+
// 此处保留导出名, agent/热重载/插件继续用 builtin.resolveLLM 等旧引用。
|
|
51
|
+
|
|
52
|
+
// ---- 内置插件: 每个 (ctx) => void, 用 ctx.provide 注册服务 ----
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
export const busPlugin = (ctx) => {
|
|
56
|
+
// ②循环系: 全局 Runtime 总线。必须最先装配, 其他插件可 ctx.consume("bus") 挂订阅/注册命令。
|
|
57
|
+
const bus = new RuntimeBus();
|
|
58
|
+
ctx.provide("bus", bus);
|
|
59
|
+
// 状态槽: sessionKey 归属 (给观测/审计看当前活跃会话)
|
|
60
|
+
bus.set("bootedAt", Date.now());
|
|
61
|
+
return bus;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const healerPlugin = (ctx) => {
|
|
65
|
+
// v1.0.8 修复 (P1-2): 必须传真实数据目录, 否则自愈体检/崩溃标记会落到 root/data 硬编码路径,
|
|
66
|
+
// 在 PPX_DATA_DIR 自定义时与真实数据目录分叉 (详见 selfheal/healer.js 注释)。
|
|
67
|
+
const healer = new Healer(ctx.consume("root"), ctx.consume("dataDir"));
|
|
68
|
+
healer.markDirty();
|
|
69
|
+
const health = healer.heal();
|
|
70
|
+
ctx.provide("healer", healer);
|
|
71
|
+
ctx.provide("health", health);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export const personaPlugin = (ctx) => {
|
|
75
|
+
ctx.provide("persona", new Persona(ctx.consume("root")));
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export const factsPlugin = (ctx) => {
|
|
79
|
+
const config = ctx.consume("config");
|
|
80
|
+
const dataDir = ctx.consume("dataDir");
|
|
81
|
+
// 记忆后端选择 (2026-10-03): "json" (默认, 向后兼容) | "sqlite" (内嵌库, FTS5+WAL) | "auto" (优先 sqlite)
|
|
82
|
+
// 选 sqlite 的收益: 增量写 (实测 800 条 18.7x 更快, JSON 版每次 add 都全量重写)、
|
|
83
|
+
// 事务级并发安全 (无文件锁忙等)、崩溃可恢复 (WAL)、数据量增大时检索不退化 (JSON 版全量重扫)。
|
|
84
|
+
// 代价: 文件体积更大 (FTS 索引+WAL), 依赖 Node >= 22.5 的 node:sqlite (不可用会自动回落 JSON)。
|
|
85
|
+
const backend = String(config.memory?.backend || "json").toLowerCase();
|
|
86
|
+
let facts = null;
|
|
87
|
+
if (backend === "sqlite" || backend === "auto") {
|
|
88
|
+
try {
|
|
89
|
+
facts = new SqliteFactStore(dataDir, config.memory || {});
|
|
90
|
+
info(`[memory] 记忆后端: SQLite 内嵌库 (FTS5=${facts.ftsReady}, WAL)`);
|
|
91
|
+
} catch (e) {
|
|
92
|
+
warn(`[memory] SQLite 后端不可用, 回落 JSON: ${e.message}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!facts) {
|
|
96
|
+
// 2026-10-03 深度优化 (P2 写放大): 主链路默认开启 FactStore WAL 增量落盘 ——
|
|
97
|
+
// 原默认每次变更全量原子重写 facts.json (高频对话下写放大显著, SQLite 注释自认 18.7x 差距)。
|
|
98
|
+
// WAL 模式: 变更走追加日志, 达阈值才 compact 全量写。仅主链路开启 (轻量构造/测试保持旧行为);
|
|
99
|
+
// config.memory.wal 可显式关。agent.shutdown 时 flush 兜底。
|
|
100
|
+
facts = new FactStore(dataDir, { wal: true, walThreshold: 50, ...(config.memory || {}) });
|
|
101
|
+
if (backend === "sqlite") warn("[memory] 显式指定了 sqlite 后端但不可用, 已回落 JSON");
|
|
102
|
+
}
|
|
103
|
+
ctx.provide("facts", facts);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const experiencePlugin = (ctx) => {
|
|
107
|
+
// 经验库走全局共享目录 (ANS 全局记忆): 跨 agent 共享经验, 写入用文件锁防并发覆盖
|
|
108
|
+
ctx.provide("experience", new Experience(ctx.consume("globalDataDir") || ctx.consume("dataDir")));
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const legionBoardPlugin = (ctx) => {
|
|
112
|
+
// 军团共享记忆板 (2026-10-02): 走全局共享目录, 主 agent 与 worker 实时互通
|
|
113
|
+
ctx.provide("legionBoard", new LegionBoard(ctx.consume("globalDataDir") || ctx.consume("dataDir")));
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export const sessionPlugin = (ctx) => {
|
|
117
|
+
const config = ctx.consume("config");
|
|
118
|
+
const sessions = new SessionStore(ctx.consume("dataDir"));
|
|
119
|
+
// 启动时清理过期会话 (config.memory.session_max_age_days, 默认 30; 0/负=不清理)
|
|
120
|
+
const maxAge = Number(config.memory?.session_max_age_days ?? 30);
|
|
121
|
+
if (maxAge > 0) {
|
|
122
|
+
const removed = sessions.pruneOld({ maxAgeDays: maxAge });
|
|
123
|
+
if (removed.length) info(`[sessions] 清理过期会话 ${removed.length} 个: ${removed.join(", ")}`);
|
|
124
|
+
}
|
|
125
|
+
ctx.provide("sessions", sessions);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const memoryPlugin = (ctx) => {
|
|
129
|
+
const facts = ctx.consume("facts");
|
|
130
|
+
const sessions = ctx.consume("sessions");
|
|
131
|
+
ctx.provide("memory", new MemoryTicker(ctx.consume("dataDir"), facts, null, sessions));
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const llmPlugin = (ctx) => {
|
|
135
|
+
const config = ctx.consume("config");
|
|
136
|
+
ctx.provide("llm", resolveLLM(config));
|
|
137
|
+
ctx.provide("allProviders", resolveAllLLMs(config));
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export const memoryLayersPlugin = (ctx) => {
|
|
141
|
+
const sessions = ctx.consume("sessions");
|
|
142
|
+
const dataDir = ctx.consume("dataDir");
|
|
143
|
+
const userName = ctx.consume("userName") || "兄弟";
|
|
144
|
+
ctx.provide("l0", new L0Recorder(sessions, dataDir));
|
|
145
|
+
ctx.provide("scenes", new SceneStore(dataDir));
|
|
146
|
+
ctx.provide("personaStore", new PersonaStore(dataDir, { userName }));
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const tracesPlugin = (ctx) => {
|
|
150
|
+
ctx.provide("traces", new Traces(ctx.consume("dataDir")));
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
export const auditPlugin = (ctx) => {
|
|
154
|
+
// 审计哈希链 (吸收自 ppx-v2): append-only + SHA-256 链式防篡改账本。
|
|
155
|
+
// 与 core/trace.js 的事件流互补 —— trace 面向"可观测", audit 面向"可追责/防篡改"。
|
|
156
|
+
// config.audit.enabled === false 时关闭 (供性能敏感场景), 默认开启。
|
|
157
|
+
const config = ctx.consume("config");
|
|
158
|
+
if (config?.audit?.enabled === false) {
|
|
159
|
+
ctx.provide("audit", null);
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
const audit = new AuditLog(ctx.consume("dataDir"));
|
|
163
|
+
ctx.provide("audit", audit);
|
|
164
|
+
return audit;
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export const toolsPlugin = (ctx) => {
|
|
168
|
+
const root = ctx.consume("root");
|
|
169
|
+
const dataDir = ctx.consume("dataDir");
|
|
170
|
+
const config = ctx.consume("config");
|
|
171
|
+
const facts = ctx.consume("facts");
|
|
172
|
+
const memory = ctx.consume("memory");
|
|
173
|
+
const tools = new ToolCatalog();
|
|
174
|
+
registerBuiltinTools(tools, { rootDir: root, facts, memory });
|
|
175
|
+
// 2026-09-18: onFire 兜底 —— 重启恢复的持久化任务无 action 闭包, 触发时按 job.name 还原行为
|
|
176
|
+
const scheduler = new Scheduler(dataDir, { onFire: (job) => facts.add(`定时任务触发: ${job?.name || "?"}`, { source: "schedule" }) });
|
|
177
|
+
ctx.provide("scheduler", scheduler);
|
|
178
|
+
registerAdvancedTools(tools, { dataDir, scheduler, onMemoryNote: (note) => facts.add(note, { source: "schedule" }) });
|
|
179
|
+
registerMethodTools(tools);
|
|
180
|
+
registerSelfmodTools(tools, { skillsDir: path.join(root, "skills") });
|
|
181
|
+
// 用户自定义工具 (不改源码扩展能力)
|
|
182
|
+
const customDir = path.join(root, (config.tools && config.tools.custom_dir) || "custom-tools");
|
|
183
|
+
registerCustomTools(tools, customDir);
|
|
184
|
+
// 文档加载器 (RAG: read_document / ingest_document)
|
|
185
|
+
registerDocumentTools(tools, { rootDir: root });
|
|
186
|
+
// 语音能力 (ASR voice_transcribe / TTS voice_speak): 走 OpenAI 兼容端点, 零依赖
|
|
187
|
+
// v3.1: voice.asr 支持 backend:"local" (nodejs-whisper 可选依赖, 离线转写)
|
|
188
|
+
registerVoiceTools(tools, { config, rootDir: root });
|
|
189
|
+
// v3.1 新能力: 内置 JS 沙箱执行器 (CodeAct, 零依赖) + 语音活动检测 (VAD)
|
|
190
|
+
registerSandboxTools(tools, { rootDir: root });
|
|
191
|
+
registerVadTools(tools, { rootDir: root });
|
|
192
|
+
// 向量化: 配了 config.embedding 则自动注入 embedder, 检索切 dense+BM25 RRF; 否则纯 BM25 兜底
|
|
193
|
+
const embedder = embedderFromConfig(config);
|
|
194
|
+
if (embedder) facts.setEmbedder(embedder);
|
|
195
|
+
// 军团共享记忆板 (2026-10-02): 所有 agent (主 + worker) 实时共享知识
|
|
196
|
+
const board = ctx.consume("legionBoard");
|
|
197
|
+
// 多 agent 自主协作: spawn_agent 工具 (agent 自主派生子 agent 分工)
|
|
198
|
+
// 传入军团记忆板: share_board 自动发布子任务结论 + 仲裁前自动读板
|
|
199
|
+
registerDelegateTools(tools, { board });
|
|
200
|
+
if (board) {
|
|
201
|
+
const fromName = () => ctx.consume("agent")?.config?.agent?.name || "main";
|
|
202
|
+
tools.register({
|
|
203
|
+
name: "board_publish",
|
|
204
|
+
description: "向军团共享记忆板发布一条知识/发现/结论, 所有 agent 实时可见。跨 agent 协作时用。",
|
|
205
|
+
parameters: {
|
|
206
|
+
type: "object",
|
|
207
|
+
properties: {
|
|
208
|
+
topic: { type: "string", description: "频道/主题 (如 数据分析/代码审查), 默认 general" },
|
|
209
|
+
content: { type: "string", description: "要共享的内容" },
|
|
210
|
+
tags: { type: "array", items: { type: "string" }, description: "检索标签, 可选" },
|
|
211
|
+
},
|
|
212
|
+
required: ["content"],
|
|
213
|
+
},
|
|
214
|
+
execute: async (args) => {
|
|
215
|
+
try {
|
|
216
|
+
const e = board.publish({ from: fromName(), topic: args.topic, content: args.content, tags: args.tags });
|
|
217
|
+
return JSON.stringify({ ok: true, id: e.id });
|
|
218
|
+
} catch (e) { return JSON.stringify({ error: e.message }); }
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
tools.register({
|
|
222
|
+
name: "board_query",
|
|
223
|
+
description: "查询军团共享记忆板: 看其他 agent 发布的知识/发现/结论 (实时, 跨进程)。",
|
|
224
|
+
parameters: {
|
|
225
|
+
type: "object",
|
|
226
|
+
properties: {
|
|
227
|
+
q: { type: "string", description: "关键词 (匹配内容/主题/标签)" },
|
|
228
|
+
topic: { type: "string", description: "按频道过滤, 可选" },
|
|
229
|
+
from: { type: "string", description: "按发布者过滤, 可选" },
|
|
230
|
+
limit: { type: "number", description: "返回条数, 默认 10" },
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
execute: async (args) => {
|
|
234
|
+
const rs = board.query(args);
|
|
235
|
+
if (!rs.length) return "(记忆板暂无匹配内容)";
|
|
236
|
+
return rs.map((r) => `- [${r.ts}] ${r.from}@${r.topic}: ${r.content}`).join("\n");
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
// Shell 能力 seam: 命令执行解耦为可替换 provider (本地/未来沙箱/Docker)
|
|
241
|
+
ctx.provide("shell", new LocalShellProvider());
|
|
242
|
+
// 审计哈希链接入工具执行收口 (未启用时为 null, catalog 内部零开销跳过)
|
|
243
|
+
tools.setAudit(ctx.consume("audit"));
|
|
244
|
+
// 记忆治理 + 审计校验 + 运维工具 (吸收自 ppx-v2, 共 10 个)
|
|
245
|
+
registerGovernanceTools(tools, {
|
|
246
|
+
rootDir: root,
|
|
247
|
+
dataDir,
|
|
248
|
+
facts,
|
|
249
|
+
audit: ctx.consume("audit"),
|
|
250
|
+
personaStore: ctx.consume("personaStore"),
|
|
251
|
+
healer: ctx.consume("healer"),
|
|
252
|
+
experience: ctx.consume("experience"),
|
|
253
|
+
});
|
|
254
|
+
// v3.0 (codex 对齐): repo_map / apply_patch / review_code / goal_board
|
|
255
|
+
registerV3Tools(tools, { rootDir: root, agent: ctx.consume("agent") });
|
|
256
|
+
// git 集成 (2026-10-01): status/diff/log/commit, 仅 add+commit, 禁 push/reset
|
|
257
|
+
registerGitTools(tools, { rootDir: root });
|
|
258
|
+
ctx.provide("tools", tools);
|
|
259
|
+
ctx.provide("toolsEnabled", config.tools?.enabled !== false);
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
export const modePlugin = (ctx) => {
|
|
263
|
+
const registry = new ModeRegistry();
|
|
264
|
+
registerDefaultModes(registry);
|
|
265
|
+
// 更多编排模式 (可插拔): plan-exec / router / blackboard / graph
|
|
266
|
+
registry.register("plan-exec", planExecExecutor);
|
|
267
|
+
registry.register("router", routerExecutor);
|
|
268
|
+
registry.register("blackboard", blackboardExecutor);
|
|
269
|
+
registry.register("graph", graphExecutor);
|
|
270
|
+
registry.register("legion", legionExecutor);
|
|
271
|
+
ctx.provide("modes", registry);
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// P2⑧: 内置插件权限位 (函数外赋值, compose 调用前即可读)
|
|
275
|
+
// tools/shell 属敏感服务 (SENSITIVE_SERVICES), 需 full-access
|
|
276
|
+
toolsPlugin.access = "full-access";
|
|
277
|
+
|
|
278
|
+
export const evolvePlugin = (ctx) => {
|
|
279
|
+
// P1④⑤⑥: 进化系插件 —— Playbook 引擎 / 记忆健康监控 / 故障记忆
|
|
280
|
+
// P2⑥⑦: 符号画布 / 会话 fork 基线
|
|
281
|
+
//
|
|
282
|
+
// ⚠ 接线状态 (2026-09-17 核对): 本插件注册的 6 个服务在 src/ 内**当前均无消费方**
|
|
283
|
+
// (grep consume("playbook"|"memoryHealth"|"failures"|"canvas"|"fork"|"assets") = 0 命中)。
|
|
284
|
+
// 即: 构造它们只有极小的初始化开销, 但没有任何链路在读写 —— 属"能力就绪、未接线"。
|
|
285
|
+
// 保留原因: 单测已覆盖, 且是后续进化的现成骨架。
|
|
286
|
+
// 提醒: 读到本插件的服务不等于功能已生效; 接入消费方 (写入 + 注入) 后才算真正启用。
|
|
287
|
+
const dataDir = ctx.consume("dataDir");
|
|
288
|
+
ctx.provide("playbook", new PlaybookStore(dataDir)); // 预留: 语境 bullets 引擎
|
|
289
|
+
ctx.provide("memoryHealth", new MemoryHealthMonitor()); // 预留: 记忆管线健康
|
|
290
|
+
ctx.provide("failures", new FailureEpisodeStore(dataDir)); // 预留: 故障病历
|
|
291
|
+
ctx.provide("canvas", new CanvasStore(dataDir)); // 预留: 符号画布
|
|
292
|
+
ctx.provide("fork", forkTools); // 预留: 会话 fork 基线 (函数集, 供 spawn 流程调用)
|
|
293
|
+
ctx.provide("assets", new AssetHub(dataDir)); // P3⑩: 记忆资产中枢 (预留)
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
// 默认内置插件装配顺序 (依赖在前)
|
|
297
|
+
export const builtinPlugins = [
|
|
298
|
+
busPlugin, // ②循环系: 全局总线必须最先 (依赖在前)
|
|
299
|
+
healerPlugin,
|
|
300
|
+
personaPlugin,
|
|
301
|
+
factsPlugin,
|
|
302
|
+
experiencePlugin,
|
|
303
|
+
legionBoardPlugin, // 军团共享记忆板 (toolsPlugin 依赖, 必须在前)
|
|
304
|
+
sessionPlugin,
|
|
305
|
+
memoryPlugin,
|
|
306
|
+
llmPlugin,
|
|
307
|
+
memoryLayersPlugin,
|
|
308
|
+
tracesPlugin,
|
|
309
|
+
auditPlugin, // 审计哈希链 (toolsPlugin 依赖它注入 catalog, 必须在前)
|
|
310
|
+
toolsPlugin,
|
|
311
|
+
evolvePlugin, // P1: playbook / memoryHealth / failures (tools 之后, 依赖 dataDir)
|
|
312
|
+
modePlugin,
|
|
313
|
+
];
|