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.
- package/LICENSE +201 -201
- package/README.md +195 -195
- 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 +6 -124
- package/config/ppx.json.example +143 -0
- package/package.json +16 -6
- package/skills/.usage.json +6 -0
- package/skills/agent-professional-training/SKILL.md +94 -0
- package/skills/agent-professional-training/trajectories/2026-09-11-dpo-pairs.jsonl +2 -0
- package/skills/agent-professional-training/trajectories/2026-09-11-round2-trajectory.json +15 -0
- package/skills/agent-professional-training/trajectories/2026-09-13-first-run-trajectory.json +17 -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 +1352 -717
- package/src/agent/prompts.js +46 -2
- 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 -651
- 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 -182
- 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 +4 -3
- package/src/llm/dsml.js +74 -74
- package/src/llm/embedder.js +41 -35
- package/src/llm/fence.js +52 -52
- 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 -89
- package/src/mcp/admin.js +44 -10
- package/src/mcp/client.js +487 -477
- package/src/mcp/http.js +23 -37
- package/src/mcp/index.js +116 -116
- package/src/mcp/server.js +23 -18
- package/src/mcp/tasks.js +9 -14
- 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 -215
- 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/tools/seam.js
CHANGED
|
@@ -1,125 +1,162 @@
|
|
|
1
|
-
// src/tools/seam.js - 能力缝(Capability Seam)辅助层
|
|
2
|
-
// 参考 deepseek-harness 的 Capability Seam 三分法:
|
|
3
|
-
// Service Definition(声明/元数据) / Service Provider(execute 实现) / Consumer(runWithPolicy 统一策略入口)
|
|
4
|
-
// 零依赖, 纯 Node 原生。保留皮皮虾原有错误语义, 追加超时门禁/禁用门禁/追踪回调。
|
|
5
|
-
|
|
6
|
-
export const TOOL_ERROR_PREFIX = "[工具错误]";
|
|
7
|
-
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
1
|
+
// src/tools/seam.js - 能力缝(Capability Seam)辅助层
|
|
2
|
+
// 参考 deepseek-harness 的 Capability Seam 三分法:
|
|
3
|
+
// Service Definition(声明/元数据) / Service Provider(execute 实现) / Consumer(runWithPolicy 统一策略入口)
|
|
4
|
+
// 零依赖, 纯 Node 原生。保留皮皮虾原有错误语义, 追加超时门禁/禁用门禁/追踪回调。
|
|
5
|
+
|
|
6
|
+
export const TOOL_ERROR_PREFIX = "[工具错误]";
|
|
7
|
+
|
|
8
|
+
// ---- B1: 工具结果标准化 (吸收 codex format_exec_output_for_model) ----
|
|
9
|
+
// 命令类工具返回统一元数据头, 模型不靠猜判断成败:
|
|
10
|
+
// [exit=0 time=0.42s out=3行] <内容>
|
|
11
|
+
// [exit=1 time=1.02s out=0行][stderr] <错误>
|
|
12
|
+
// [exit=timeout time=30000ms] command timed out after 30000ms
|
|
13
|
+
// 纯函数, 可独立测试 (B1 验收点)。
|
|
14
|
+
// opts = { ms, lineCount, timedOut, exitCode, timedOutMs }
|
|
15
|
+
export function formatToolResultHeader({
|
|
16
|
+
ms = 0,
|
|
17
|
+
lineCount = 0,
|
|
18
|
+
timedOut = false,
|
|
19
|
+
exitCode = null,
|
|
20
|
+
timedOutMs = 0,
|
|
21
|
+
} = {}) {
|
|
22
|
+
if (timedOut) {
|
|
23
|
+
return `[exit=timeout time=${ms}ms] command timed out after ${timedOutMs || ms}ms`;
|
|
24
|
+
}
|
|
25
|
+
const codeStr = exitCode === null ? "?" : String(exitCode);
|
|
26
|
+
return `[exit=${codeStr} time=${(ms / 1000).toFixed(2)}s out=${lineCount}行]`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 计算文本行数 (B1 辅助): 去尾随空行, 纯空白算 0
|
|
30
|
+
// 修正: 尾部换行不应多计一行 (echo 输出 "abc\r\n" 应为 1 行)
|
|
31
|
+
export function countLines(text) {
|
|
32
|
+
const s = String(text ?? "");
|
|
33
|
+
const t = s.replace(/\r\n/g, "\n").replace(/\n\s*$/, "").trim();
|
|
34
|
+
if (!t) return 0;
|
|
35
|
+
return t.split("\n").length;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// power 权限级: user < agent < super
|
|
39
|
+
export const POWER_LEVEL = { user: 0, agent: 1, super: 2 };
|
|
40
|
+
|
|
41
|
+
// ---- Definition 层: 元数据归一化 + 校验 ----
|
|
42
|
+
export function normalizeMeta(def = {}) {
|
|
43
|
+
if (!def || typeof def.name !== "string" || !def.name) {
|
|
44
|
+
throw new Error("能力缝 Definition 失败: 需 name");
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
name: def.name,
|
|
48
|
+
description: def.description || "",
|
|
49
|
+
parameters: def.parameters || { type: "object", properties: {}, required: [] },
|
|
50
|
+
// 能力缝新增元数据
|
|
51
|
+
category: def.category || "misc", // 能力域: file/net/system/memory/selfmod/...
|
|
52
|
+
power: def.power || "user", // 权限级: user/agent(0栓塞)
|
|
53
|
+
timeoutMs: Number(def.timeoutMs) || 0, // 0 = 不限时
|
|
54
|
+
idempotent: !!def.idempotent, // 是否可安全重试
|
|
55
|
+
enabled: def.enabled !== false, // 默认启用
|
|
56
|
+
// 工具能力声明 (2026-10-02 吸收 ZCode PermissionToolCapability):
|
|
57
|
+
// readOnly 只读不产生副作用
|
|
58
|
+
// destructive 破坏性操作 (不可逆/删数据)
|
|
59
|
+
// riskLevel low | medium | high | critical
|
|
60
|
+
// alwaysAsk 无论何种模式都需人工确认 (压过一切放行分支)
|
|
61
|
+
// sideEffect 副作用域: "none" | "workspace" | "network" | "system"
|
|
62
|
+
capability: def.capability || null,
|
|
63
|
+
execute: def.execute,
|
|
64
|
+
// 工具钩子链 (吸收 OpenClaw before/after 钩子):
|
|
65
|
+
// before(args, ctx) -> undefined 继续 | 字符串短路 | throw 拒绝
|
|
66
|
+
// after(args, result, ctx) -> 后处理(结果审计/清理), 错误不阻塞
|
|
67
|
+
before: typeof def.before === "function" ? def.before : null,
|
|
68
|
+
after: typeof def.after === "function" ? def.after : null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ---- Consumer 层: 统一策略执行 ----
|
|
73
|
+
// 统一处理: 禁用门禁 / 实现缺失 / 超时门禁 / 标准错误语义 / 追踪回调
|
|
74
|
+
export async function runWithPolicy(meta, args, ctx = {}) {
|
|
75
|
+
if (meta.enabled === false) {
|
|
76
|
+
return `${TOOL_ERROR_PREFIX} ${meta.name}: 能力已禁用`;
|
|
77
|
+
}
|
|
78
|
+
// power 权限门禁: 仅当 ctx.power 明确提供时生效(向后兼容, 无 ctx.power 默认放行)
|
|
79
|
+
if (ctx && ctx.power) {
|
|
80
|
+
const need = POWER_LEVEL[meta.power] ?? 0;
|
|
81
|
+
const have = POWER_LEVEL[ctx.power] ?? 0;
|
|
82
|
+
if (have < need) {
|
|
83
|
+
return `${TOOL_ERROR_PREFIX} ${meta.name}: 权限不足(需要 ${meta.power}, 当前 ${ctx.power})`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const fn = meta.execute;
|
|
87
|
+
if (typeof fn !== "function") {
|
|
88
|
+
return `${TOOL_ERROR_PREFIX} ${meta.name}: 无实现(Provider 缺失)`;
|
|
89
|
+
}
|
|
90
|
+
// before 钩子: 返回非 undefined 则短路(不执行), throw 则拒绝
|
|
91
|
+
if (meta.before) {
|
|
92
|
+
try {
|
|
93
|
+
const shortCircuit = await meta.before(args, ctx);
|
|
94
|
+
if (shortCircuit !== undefined && shortCircuit !== null) {
|
|
95
|
+
return typeof shortCircuit === "string" ? shortCircuit : JSON.stringify(shortCircuit);
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return `${TOOL_ERROR_PREFIX} ${meta.name}: before 钩子拒绝: ${e.message}`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
let timer = null;
|
|
102
|
+
let timedOut = false;
|
|
103
|
+
const ctrl = new AbortController();
|
|
104
|
+
// 超时预算: 工具级声明优先 (meta.timeoutMs > 0), 否则全局默认 (ctx.timeoutMs, agent 从 config.agent.tool_timeout_ms 传入)
|
|
105
|
+
// v1.6.0 (第四刀): 无声明工具不再永不超时 — 有保守全局默认兑底, 避免单个慢工具卡死整个对话
|
|
106
|
+
const effectiveTimeout = meta.timeoutMs > 0 ? meta.timeoutMs : (Number(ctx.timeoutMs) || 0);
|
|
107
|
+
if (effectiveTimeout > 0) {
|
|
108
|
+
timer = setTimeout(() => { timedOut = true; ctrl.abort(); }, effectiveTimeout);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
// v1.6.0 (第四刀): 双层超时兜底 —
|
|
112
|
+
// 1) signal 传给 execute: 配合的工具提前终止释放资源 (资源超时)
|
|
113
|
+
// 2) Promise.race 强制超时返回: 不响应 signal 的工具也不至于永远挂住对话 (语义超时兜底)
|
|
114
|
+
// 这是文档指出的灰色地带: 光靠 abort 信号, 不配合的工具会无限期挂着。
|
|
115
|
+
const run = () => (fn.length >= 2 ? fn(args, { ...ctx, signal: ctrl.signal }) : fn(args));
|
|
116
|
+
let result;
|
|
117
|
+
if (effectiveTimeout > 0) {
|
|
118
|
+
let raceTimer = null;
|
|
119
|
+
const timeoutGuard = new Promise((_, reject) => {
|
|
120
|
+
raceTimer = setTimeout(() => reject(Object.assign(new Error("timeout"), { timedOut: true })), effectiveTimeout);
|
|
121
|
+
});
|
|
122
|
+
const pRun = Promise.resolve().then(run);
|
|
123
|
+
// 哨兵: 超时赢时工具方后到的 reject 忽略, 防 unhandledRejection 崩进程
|
|
124
|
+
pRun.catch(() => {});
|
|
125
|
+
try {
|
|
126
|
+
result = await Promise.race([pRun, timeoutGuard]);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
if (e && e.timedOut) timedOut = true;
|
|
129
|
+
throw e;
|
|
130
|
+
} finally {
|
|
131
|
+
if (raceTimer) clearTimeout(raceTimer);
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
result = await run();
|
|
135
|
+
}
|
|
136
|
+
if (timedOut) return `${TOOL_ERROR_PREFIX} ${meta.name}: 超时`;
|
|
137
|
+
if (meta.after) {
|
|
138
|
+
try { await meta.after(args, result, ctx); } catch { /* after 钩子错误不阻塞 */ }
|
|
139
|
+
}
|
|
140
|
+
if (typeof ctx.onResult === "function") ctx.onResult(meta.name, "ok", null);
|
|
141
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
if (typeof ctx.onResult === "function") ctx.onResult(meta.name, "error", e.message);
|
|
144
|
+
return `${TOOL_ERROR_PREFIX} ${meta.name}: ${timedOut ? "超时" : e.message}`;
|
|
145
|
+
} finally {
|
|
146
|
+
if (timer) clearTimeout(timer);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 供 selfmod 工具 / 追踪用的纯净元数据(不含 execute 实现)
|
|
151
|
+
export function toDescriptor(meta) {
|
|
152
|
+
return {
|
|
153
|
+
name: meta.name,
|
|
154
|
+
description: meta.description,
|
|
155
|
+
parameters: meta.parameters,
|
|
156
|
+
category: meta.category,
|
|
157
|
+
power: meta.power,
|
|
158
|
+
timeoutMs: meta.timeoutMs,
|
|
159
|
+
idempotent: meta.idempotent,
|
|
160
|
+
enabled: meta.enabled,
|
|
161
|
+
};
|
|
162
|
+
}
|