odai-dsh-agent 0.2.13 → 0.2.16
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 +25 -12
- package/build/bin/odai-dsh-agent.mjs +88 -7
- package/build/bin/odai-dsh-agent.mjs.map +1 -1
- package/build/src/control-center-installer.d.mts +32 -0
- package/build/src/control-center-installer.d.mts.map +1 -0
- package/build/src/control-center-installer.mjs +112 -0
- package/build/src/control-center-installer.mjs.map +1 -0
- package/build/src/control-center-prompt.d.mts +4 -0
- package/build/src/control-center-prompt.d.mts.map +1 -0
- package/build/src/control-center-prompt.mjs +15 -0
- package/build/src/control-center-prompt.mjs.map +1 -0
- package/build/src/installer.d.mts +3 -1
- package/build/src/installer.d.mts.map +1 -1
- package/build/src/installer.mjs +46 -4
- package/build/src/installer.mjs.map +1 -1
- package/client/client.js +517 -0
- package/control-center.cordis.patch.yml +3 -0
- package/package.json +24 -5
- package/preset/odai/agent.cordis.yml +12 -7
- package/preset/odai/runtime/canonical-reference.d.mts +15 -0
- package/preset/odai/runtime/canonical-reference.d.mts.map +1 -0
- package/preset/odai/runtime/canonical-reference.mjs +64 -0
- package/preset/odai/runtime/canonical-reference.mjs.map +1 -0
- package/preset/odai/runtime/compaction-config.mjs +1 -1
- package/preset/odai/runtime/compaction-config.mjs.map +1 -1
- package/preset/odai/runtime/context-activation.d.mts +2 -3
- package/preset/odai/runtime/context-activation.d.mts.map +1 -1
- package/preset/odai/runtime/context-activation.mjs +8 -5
- package/preset/odai/runtime/context-activation.mjs.map +1 -1
- package/preset/odai/runtime/control-center-host.d.mts +10 -0
- package/preset/odai/runtime/control-center-host.d.mts.map +1 -0
- package/preset/odai/runtime/control-center-host.mjs +15 -0
- package/preset/odai/runtime/control-center-host.mjs.map +1 -0
- package/preset/odai/runtime/control-center-runtime.d.mts +26 -0
- package/preset/odai/runtime/control-center-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/control-center-runtime.mjs +118 -0
- package/preset/odai/runtime/control-center-runtime.mjs.map +1 -0
- package/preset/odai/runtime/governance.d.mts +1 -1
- package/preset/odai/runtime/governance.d.mts.map +1 -1
- package/preset/odai/runtime/governance.mjs +0 -1
- package/preset/odai/runtime/governance.mjs.map +1 -1
- package/preset/odai/runtime/human-care.d.mts +0 -1
- package/preset/odai/runtime/human-care.d.mts.map +1 -1
- package/preset/odai/runtime/human-care.mjs +0 -1
- package/preset/odai/runtime/human-care.mjs.map +1 -1
- package/preset/odai/runtime/human-safety.d.mts +0 -1
- package/preset/odai/runtime/human-safety.d.mts.map +1 -1
- package/preset/odai/runtime/human-safety.mjs +0 -1
- package/preset/odai/runtime/human-safety.mjs.map +1 -1
- package/preset/odai/runtime/index.d.mts.map +1 -1
- package/preset/odai/runtime/index.mjs +10 -1
- package/preset/odai/runtime/index.mjs.map +1 -1
- package/preset/odai/runtime/lifecycle-runtime.d.mts +0 -2
- package/preset/odai/runtime/lifecycle-runtime.d.mts.map +1 -1
- package/preset/odai/runtime/lifecycle-runtime.mjs +3 -74
- package/preset/odai/runtime/lifecycle-runtime.mjs.map +1 -1
- package/preset/odai/runtime/output-config.d.mts +1 -1
- package/preset/odai/runtime/output-config.d.mts.map +1 -1
- package/preset/odai/runtime/output-config.mjs +2 -2
- package/preset/odai/runtime/output-config.mjs.map +1 -1
- package/preset/odai/runtime/prompt-runtime.d.mts +0 -1
- package/preset/odai/runtime/prompt-runtime.d.mts.map +1 -1
- package/preset/odai/runtime/prompt-runtime.mjs +1 -13
- package/preset/odai/runtime/prompt-runtime.mjs.map +1 -1
- package/preset/odai/runtime/responsibility-return.d.mts +1 -4
- package/preset/odai/runtime/responsibility-return.d.mts.map +1 -1
- package/preset/odai/runtime/responsibility-return.mjs +10 -25
- package/preset/odai/runtime/responsibility-return.mjs.map +1 -1
- package/preset/odai/runtime/responsibility-scope.d.mts +1 -5
- package/preset/odai/runtime/responsibility-scope.d.mts.map +1 -1
- package/preset/odai/runtime/responsibility-scope.mjs +4 -24
- package/preset/odai/runtime/responsibility-scope.mjs.map +1 -1
- package/preset/odai/runtime/role-overlays.d.mts.map +1 -1
- package/preset/odai/runtime/role-overlays.mjs +1 -4
- package/preset/odai/runtime/role-overlays.mjs.map +1 -1
- package/preset/odai/runtime/router.d.mts +3 -13
- package/preset/odai/runtime/router.d.mts.map +1 -1
- package/preset/odai/runtime/router.mjs +9 -22
- package/preset/odai/runtime/router.mjs.map +1 -1
- package/preset/odai/runtime/routing-config.d.mts +11 -2
- package/preset/odai/runtime/routing-config.d.mts.map +1 -1
- package/preset/odai/runtime/routing-config.mjs +96 -86
- package/preset/odai/runtime/routing-config.mjs.map +1 -1
- package/preset/odai/runtime/routing-context.d.mts.map +1 -1
- package/preset/odai/runtime/routing-context.mjs +3 -24
- package/preset/odai/runtime/routing-context.mjs.map +1 -1
- package/preset/odai/runtime/runtime-config.d.mts +1 -1
- package/preset/odai/runtime/runtime-config.d.mts.map +1 -1
- package/preset/odai/runtime/runtime-support.d.mts.map +1 -1
- package/preset/odai/runtime/runtime-support.mjs +1 -3
- package/preset/odai/runtime/runtime-support.mjs.map +1 -1
- package/preset/odai/runtime/runtime-types.d.mts +1 -4
- package/preset/odai/runtime/runtime-types.d.mts.map +1 -1
- package/preset/odai/runtime/skill-bundle.d.mts +8 -2
- package/preset/odai/runtime/skill-bundle.d.mts.map +1 -1
- package/preset/odai/runtime/skill-bundle.mjs +56 -22
- package/preset/odai/runtime/skill-bundle.mjs.map +1 -1
- package/preset/odai/runtime/skill-evolution.d.mts.map +1 -1
- package/preset/odai/runtime/skill-evolution.mjs +15 -4
- package/preset/odai/runtime/skill-evolution.mjs.map +1 -1
- package/preset/odai/runtime/tool-runtime.d.mts +0 -1
- package/preset/odai/runtime/tool-runtime.d.mts.map +1 -1
- package/preset/odai/runtime/tool-runtime.mjs +17 -53
- package/preset/odai/runtime/tool-runtime.mjs.map +1 -1
- package/preset/odai/skills/odai/SKILL.md +31 -34
- package/preset/odai/skills/odai/assets/routing-roles/controller.md +4 -4
- package/preset/odai/skills/odai/assets/routing-roles/planner.md +2 -3
- package/preset/odai/skills/odai/assets/routing-roles/researcher.md +1 -1
- package/preset/odai/skills/odai/assets/routing-roles/reviewer.md +2 -2
- package/preset/odai/skills/odai/manifest.json +20 -5
- package/preset/odai/skills/odai/references/leverage.md +9 -12
- package/preset/odai/skills/odai/references/support.md +7 -13
- package/preset/odai/skills/odai/references/verification.md +1 -0
- package/preset/odai/skills/odai/scripts/build-routing.mjs +71 -30
- package/preset/odai/skills/odai/scripts/install-routing.mjs +18 -22
- package/preset/odai/skills/odai/scripts/run-role.mjs +8 -59
- package/preset/odai/skills/odai/scripts/verify-routing.mjs +3 -3
- package/preset/odai/runtime/route-card.d.mts +0 -42
- package/preset/odai/runtime/route-card.d.mts.map +0 -1
- package/preset/odai/runtime/route-card.mjs +0 -180
- package/preset/odai/runtime/route-card.mjs.map +0 -1
- package/preset/odai/skills/odai/assets/routing-roles/executor.md +0 -11
- package/preset/odai/skills/odai/scripts/run-routing.mjs +0 -1154
|
@@ -19,7 +19,7 @@ process.on("uncaughtException", (error) => {
|
|
|
19
19
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
20
20
|
const builder = path.join(scriptDir, "build-routing.mjs");
|
|
21
21
|
const manifestName = "odai-routing.json";
|
|
22
|
-
const requiredRoles = ["controller", "planner", "
|
|
22
|
+
const requiredRoles = ["controller", "planner", "reviewer"];
|
|
23
23
|
const configurableRoles = [...requiredRoles, "researcher", "frontend"];
|
|
24
24
|
const args = parseArgs(process.argv.slice(2));
|
|
25
25
|
const roles = Object.freeze([
|
|
@@ -29,13 +29,13 @@ const roles = Object.freeze([
|
|
|
29
29
|
]);
|
|
30
30
|
const retiredByHost = {
|
|
31
31
|
codex: [
|
|
32
|
-
"hooks.json", "odai-route-hook.mjs",
|
|
33
|
-
"odai-run-provider-role.mjs", "agents/odai-advisor.toml", "agents/odai-implementer.toml", "agents/odai-worker.toml",
|
|
32
|
+
"hooks.json", "odai-route-hook.mjs", "odai-run-routing.mjs",
|
|
33
|
+
"odai-run-provider-role.mjs", "agents/odai-advisor.toml", "agents/odai-implementer.toml", "agents/odai-worker.toml", "agents/odai-executor.toml", "role-contracts/odai-executor.md",
|
|
34
34
|
"provider-roles/odai-controller.md", "provider-roles/odai-planner.md", "provider-roles/odai-executor.md",
|
|
35
35
|
"provider-roles/odai-advisor.md", "provider-roles/odai-implementer.md", "provider-roles/odai-worker.md", "provider-roles/odai-reviewer.md",
|
|
36
36
|
],
|
|
37
|
-
claude: ["agents/odai-advisor.md", "agents/odai-implementer.md", "agents/odai-worker.md"],
|
|
38
|
-
copilot: ["agents/odai-advisor.agent.md", "agents/odai-implementer.agent.md", "agents/odai-worker.agent.md"],
|
|
37
|
+
claude: ["agents/odai-advisor.md", "agents/odai-implementer.md", "agents/odai-worker.md", "agents/odai-executor.md"],
|
|
38
|
+
copilot: ["agents/odai-advisor.agent.md", "agents/odai-implementer.agent.md", "agents/odai-worker.agent.md", "agents/odai-executor.agent.md"],
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
if (args.help) { printHelp(); process.exit(0); }
|
|
@@ -45,7 +45,7 @@ if (!args.yes) fail("安装、更新或卸载会持久化宿主配置;取得
|
|
|
45
45
|
|
|
46
46
|
const targetRoot = resolveTarget(args.host, args.scope, args.target);
|
|
47
47
|
const configRoot = resolveConfigRoot(args.host, args.scope, targetRoot);
|
|
48
|
-
const layout = hostLayout(args.host, args.scope
|
|
48
|
+
const layout = hostLayout(args.host, args.scope);
|
|
49
49
|
layout.retiredFiles = retiredByHost[args.host];
|
|
50
50
|
const manifestPath = path.join(configRoot, manifestName);
|
|
51
51
|
const previous = loadManifest(manifestPath);
|
|
@@ -78,7 +78,7 @@ try {
|
|
|
78
78
|
if (settings) atomicWrite(path.join(configRoot, settings.file), Buffer.from(`${JSON.stringify(settings.value, null, 2)}\n`));
|
|
79
79
|
removeObsolete(configRoot, previous, files);
|
|
80
80
|
const manifest = {
|
|
81
|
-
version:
|
|
81
|
+
version: 13,
|
|
82
82
|
id: "odai-routing-installation",
|
|
83
83
|
host: args.host,
|
|
84
84
|
scope: args.scope,
|
|
@@ -112,7 +112,6 @@ function buildAdapter(outputRoot, root) {
|
|
|
112
112
|
command.push(`--${role}-model`, args[`${role}Model`]);
|
|
113
113
|
if (args[`${role}Effort`]) command.push(`--${role}-effort`, args[`${role}Effort`]);
|
|
114
114
|
}
|
|
115
|
-
if (args.planningPolicy) command.push("--planning-policy", args.planningPolicy);
|
|
116
115
|
if (args.host === "codex") command.push("--verifier-command", `node ${JSON.stringify(path.join(root, "odai-verify-routing.mjs"))}`);
|
|
117
116
|
const result = spawnSync(process.execPath, command, { encoding: "utf8", windowsHide: true });
|
|
118
117
|
if (result.status !== 0) fail(result.stderr.trim() || "路由生成失败");
|
|
@@ -151,7 +150,7 @@ function originalFileRecord(file) {
|
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
function mergeCodexConfig(original, generated) {
|
|
154
|
-
if (/^\s*\[agents\.odai_(?:planner|executor|reviewer|frontend)\]\s*$/m.test(original)) {
|
|
153
|
+
if (/^\s*\[agents\.odai_(?:researcher|planner|executor|reviewer|frontend)\]\s*$/m.test(original)) {
|
|
155
154
|
fail("既有 Codex 配置已声明 odai 角色但不受当前安装清单管理");
|
|
156
155
|
}
|
|
157
156
|
const generatedFeatures = generated.search(/^\s*\[features\]\s*$/m);
|
|
@@ -221,7 +220,7 @@ function setFeatureFlag(source, name, value) {
|
|
|
221
220
|
return lines.join("\n");
|
|
222
221
|
}
|
|
223
222
|
|
|
224
|
-
function hostLayout(host, scope
|
|
223
|
+
function hostLayout(host, scope) {
|
|
225
224
|
if (host === "codex") {
|
|
226
225
|
const researcherFiles = [
|
|
227
226
|
[".codex/agents/odai-researcher.toml", "agents/odai-researcher.toml"],
|
|
@@ -236,20 +235,17 @@ function hostLayout(host, scope, policy) {
|
|
|
236
235
|
const common = [
|
|
237
236
|
[".codex/config.toml", "config.toml"],
|
|
238
237
|
[".codex/odai-run-role.mjs", "odai-run-role.mjs"], [".codex/odai-verify-routing.mjs", "odai-verify-routing.mjs"],
|
|
239
|
-
[".codex/agents/odai-planner.toml", "agents/odai-planner.toml"],
|
|
238
|
+
[".codex/agents/odai-planner.toml", "agents/odai-planner.toml"],
|
|
240
239
|
[".codex/agents/odai-reviewer.toml", "agents/odai-reviewer.toml"],
|
|
241
240
|
[".codex/role-contracts/odai-controller.md", "role-contracts/odai-controller.md"],
|
|
242
241
|
[".codex/role-contracts/odai-planner.md", "role-contracts/odai-planner.md"],
|
|
243
|
-
[".codex/role-contracts/odai-executor.md", "role-contracts/odai-executor.md"],
|
|
244
242
|
[".codex/role-contracts/odai-reviewer.md", "role-contracts/odai-reviewer.md"],
|
|
245
243
|
...researcher,
|
|
246
244
|
...frontend,
|
|
247
245
|
];
|
|
248
|
-
const
|
|
249
|
-
const all = [...common, ...staged];
|
|
250
|
-
const generatedFiles = policy === "stage" ? all : common;
|
|
246
|
+
const generatedFiles = common;
|
|
251
247
|
return {
|
|
252
|
-
knownFiles: [...new Set([...
|
|
248
|
+
knownFiles: [...new Set([...common, ...researcherFiles, ...frontendFiles].map(([, target]) => target)), "hooks.json", "odai-route-hook.mjs", "odai-run-routing.mjs", "agents/odai-executor.toml", "role-contracts/odai-executor.md"],
|
|
253
249
|
managedFiles: generatedFiles.map(([, target]) => target),
|
|
254
250
|
generatedFiles,
|
|
255
251
|
settings: null,
|
|
@@ -364,9 +360,9 @@ function resolveTarget(host, scope, supplied) {
|
|
|
364
360
|
function resolveConfigRoot(host, scope, target) { if (scope === "user") return target; if (host === "codex") return path.join(target, ".codex"); if (host === "claude") return path.join(target, ".claude"); return path.join(target, ".github"); }
|
|
365
361
|
|
|
366
362
|
function parseArgs(values) {
|
|
367
|
-
const result = { host: "", scope: "project", target: "",
|
|
363
|
+
const result = { host: "", scope: "project", target: "", uninstall: false, yes: false, help: false };
|
|
368
364
|
for (const role of configurableRoles) { result[`${role}Model`] = ""; result[`${role}Effort`] = ""; }
|
|
369
|
-
const fields = new Map([["--host", "host"], ["--scope", "scope"], ["--target", "target"]
|
|
365
|
+
const fields = new Map([["--host", "host"], ["--scope", "scope"], ["--target", "target"]]);
|
|
370
366
|
for (const role of configurableRoles) { fields.set(`--${role}-model`, `${role}Model`); fields.set(`--${role}-effort`, `${role}Effort`); }
|
|
371
367
|
for (let index = 0; index < values.length; index += 1) {
|
|
372
368
|
const value = values[index];
|
|
@@ -379,18 +375,18 @@ function parseArgs(values) {
|
|
|
379
375
|
return result;
|
|
380
376
|
}
|
|
381
377
|
|
|
382
|
-
function hasMappingArgs(value) { return
|
|
378
|
+
function hasMappingArgs(value) { return configurableRoles.some((role) => value[`${role}Model`] || value[`${role}Effort`]); }
|
|
383
379
|
function printHelp() {
|
|
384
380
|
console.log(`由 odai 在取得用户授权后安装、更新或卸载宿主路由。
|
|
385
381
|
|
|
386
382
|
Usage:
|
|
387
383
|
node skills/odai/scripts/install-routing.mjs --host <codex|claude|copilot> --scope <project|user> [--target <path>] \\
|
|
388
|
-
--controller-model <model> --planner-model <model> --
|
|
389
|
-
[--researcher-model <model>] [--frontend-model <model>] [
|
|
384
|
+
--controller-model <model> --planner-model <model> --reviewer-model <model> \\
|
|
385
|
+
[--researcher-model <model>] [--frontend-model <model>] [--<role>-effort <effort>] --yes
|
|
390
386
|
|
|
391
387
|
node skills/odai/scripts/install-routing.mjs --host <codex|claude|copilot> --scope <project|user> [--target <path>] --uninstall --yes
|
|
392
388
|
|
|
393
|
-
安装后用户只需正常使用 odai
|
|
389
|
+
安装后用户只需正常使用 odai。总控是唯一持续任务线程并持有实施;planner、reviewer 以及可选 researcher、frontend 只在能改变结果时启动。researcher 与 frontend 映射默认不配置。更新会安全移除旧版 advisor、implementer、worker、executor 和 stage runner 托管文件。`);
|
|
394
390
|
}
|
|
395
391
|
|
|
396
392
|
function returnResult(value) { process.stdout.write(`${JSON.stringify(value, null, 2)}\n`); process.exit(0); }
|
|
@@ -14,14 +14,13 @@ process.on("uncaughtException", (error) => {
|
|
|
14
14
|
|
|
15
15
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
16
16
|
const args = parseArgs(process.argv.slice(2));
|
|
17
|
-
const supportedRoles = new Set(["controller", "researcher", "planner", "
|
|
17
|
+
const supportedRoles = new Set(["controller", "researcher", "planner", "reviewer", "frontend"]);
|
|
18
18
|
|
|
19
19
|
if (args.help) {
|
|
20
20
|
console.log(`Usage:
|
|
21
|
-
node .codex/odai-run-role.mjs --role <controller|researcher|planner|
|
|
21
|
+
node .codex/odai-run-role.mjs --role <controller|researcher|planner|reviewer|frontend> \\
|
|
22
22
|
[--input FILE] [--output FILE] [--evidence FILE] [--cwd PATH] [--manifest FILE] \\
|
|
23
|
-
[--codex-bin FILE] [--sandbox MODE] [--session-id ID] [--
|
|
24
|
-
[--route-card | --closeout-ids A1,A2]
|
|
23
|
+
[--codex-bin FILE] [--sandbox MODE] [--session-id ID] [--closeout-ids A1,A2]
|
|
25
24
|
|
|
26
25
|
从 odai 托管清单取得当前 Codex 宿主的角色、模型与推理档,运行一次实际责任并记录可核对证据。`);
|
|
27
26
|
process.exit(0);
|
|
@@ -48,17 +47,14 @@ const started = Date.now();
|
|
|
48
47
|
mkdirSync(path.dirname(outputFile), { recursive: true });
|
|
49
48
|
|
|
50
49
|
try {
|
|
51
|
-
const readOnly = args.
|
|
50
|
+
const readOnly = args.role === "researcher" || args.role === "planner" || args.role === "reviewer";
|
|
52
51
|
const closeoutIds = parseCloseoutIds(args.closeoutIds);
|
|
53
|
-
|
|
54
|
-
const schemaFile = args.routeCard
|
|
55
|
-
? writeRouteSchema(temporary)
|
|
56
|
-
: closeoutIds.length > 0 ? writeCloseoutSchema(temporary, closeoutIds) : "";
|
|
52
|
+
const schemaFile = closeoutIds.length > 0 ? writeCloseoutSchema(temporary, closeoutIds) : "";
|
|
57
53
|
const hostOwnsRouting = process.env.ODAI_ROUTING_ACTIVE === "1";
|
|
58
54
|
const shared = [
|
|
59
55
|
"--json", "--model", mapping.model,
|
|
60
56
|
...effortArgs(mapping.reasoning_effort),
|
|
61
|
-
...(hostOwnsRouting
|
|
57
|
+
...(hostOwnsRouting ? ["-c", "features.multi_agent=false"] : []),
|
|
62
58
|
...(args.sessionId ? ["-c", `sandbox_mode=${JSON.stringify(readOnly ? "read-only" : args.sandbox)}`] : []),
|
|
63
59
|
"-c", `developer_instructions=${JSON.stringify(contract)}`,
|
|
64
60
|
...(schemaFile ? ["--output-schema", schemaFile] : []),
|
|
@@ -79,8 +75,7 @@ try {
|
|
|
79
75
|
const raw = `${child.stdout || ""}${child.stderr || ""}`;
|
|
80
76
|
if (child.status !== 0) fail(`Codex ${args.role} 调用失败:${tail(raw)}`);
|
|
81
77
|
if (!existsSync(outputFile) || !readFileSync(outputFile, "utf8").trim()) fail("角色没有形成输出");
|
|
82
|
-
if (
|
|
83
|
-
else if (closeoutIds.length > 0) writeFileSync(outputFile, renderCloseout(readFileSync(outputFile, "utf8"), closeoutIds), "utf8");
|
|
78
|
+
if (closeoutIds.length > 0) writeFileSync(outputFile, renderCloseout(readFileSync(outputFile, "utf8"), closeoutIds), "utf8");
|
|
84
79
|
const events = parseJsonLines(raw);
|
|
85
80
|
const threadId = String(events.find((event) => event.type === "thread.started")?.thread_id || args.sessionId || "");
|
|
86
81
|
if (args.sessionId && threadId !== args.sessionId) fail(`Codex 恢复了错误线程:期望 ${args.sessionId},实际 ${threadId || "unknown"}`);
|
|
@@ -213,7 +208,7 @@ function lastDefined(values) { return [...values].reverse().find((value) => valu
|
|
|
213
208
|
function readJson(file, label) { if (!existsSync(file)) fail(`缺少${label}:${file}`); return JSON.parse(readFileSync(file, "utf8")); }
|
|
214
209
|
|
|
215
210
|
function parseArgs(values) {
|
|
216
|
-
const result = { role: "", input: "", output: "", evidence: "", cwd: "", manifest: "", codexBin: "", sandbox: "workspace-write", sessionId: "", closeoutIds: "", timeout: 900,
|
|
211
|
+
const result = { role: "", input: "", output: "", evidence: "", cwd: "", manifest: "", codexBin: "", sandbox: "workspace-write", sessionId: "", closeoutIds: "", timeout: 900, help: false };
|
|
217
212
|
const fields = new Map([
|
|
218
213
|
["--role", "role"], ["--input", "input"], ["--output", "output"], ["--evidence", "evidence"], ["--cwd", "cwd"],
|
|
219
214
|
["--manifest", "manifest"], ["--codex-bin", "codexBin"], ["--sandbox", "sandbox"], ["--session-id", "sessionId"], ["--closeout-ids", "closeoutIds"], ["--timeout", "timeout"],
|
|
@@ -221,8 +216,6 @@ function parseArgs(values) {
|
|
|
221
216
|
for (let index = 0; index < values.length; index += 1) {
|
|
222
217
|
const value = values[index];
|
|
223
218
|
if (value === "--help" || value === "-h") result.help = true;
|
|
224
|
-
else if (value === "--planner-may-complete-direct") result.plannerMayCompleteDirect = true;
|
|
225
|
-
else if (value === "--route-card") result.routeCard = true;
|
|
226
219
|
else if (fields.has(value)) {
|
|
227
220
|
const next = values[++index] || "";
|
|
228
221
|
if (!next || next.startsWith("--")) fail(`${value} 需要一个值`);
|
|
@@ -233,26 +226,6 @@ function parseArgs(values) {
|
|
|
233
226
|
return result;
|
|
234
227
|
}
|
|
235
228
|
|
|
236
|
-
function writeRouteSchema(directory) {
|
|
237
|
-
const file = path.join(directory, "route-card.schema.json");
|
|
238
|
-
const text = { type: "string" };
|
|
239
|
-
const schema = {
|
|
240
|
-
type: "object",
|
|
241
|
-
additionalProperties: false,
|
|
242
|
-
properties: {
|
|
243
|
-
mode: { type: "string", enum: ["direct", "planned"] }, delivery: text,
|
|
244
|
-
target: text, evidence: text, scope: text, decision: text,
|
|
245
|
-
execute: { type: "string", enum: ["none", "controller", "executor"] },
|
|
246
|
-
review_ids: { type: "array", items: { type: "string", pattern: "^A[1-9][0-9]{0,2}$" } },
|
|
247
|
-
accept: { type: "array", items: { type: "object", additionalProperties: false, properties: { id: { type: "string", pattern: "^A[1-9][0-9]{0,2}$" }, condition: text }, required: ["id", "condition"] } },
|
|
248
|
-
stop: text, steps: { type: "array", items: text },
|
|
249
|
-
},
|
|
250
|
-
required: ["mode", "delivery", "target", "evidence", "scope", "decision", "execute", "review_ids", "accept", "stop", "steps"],
|
|
251
|
-
};
|
|
252
|
-
writeFileSync(file, `${JSON.stringify(schema, null, 2)}\n`, "utf8");
|
|
253
|
-
return file;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
229
|
function writeCloseoutSchema(directory, ids) {
|
|
257
230
|
const file = path.join(directory, "closeout.schema.json");
|
|
258
231
|
const report = {
|
|
@@ -308,29 +281,5 @@ function renderCloseout(source, ids) {
|
|
|
308
281
|
return `${delivery}\n\n<odai_closeout>${JSON.stringify(value.acceptance)}</odai_closeout>\n`;
|
|
309
282
|
}
|
|
310
283
|
|
|
311
|
-
function renderRouteCard(source) {
|
|
312
|
-
let value;
|
|
313
|
-
try { value = JSON.parse(String(source || "").trim()); }
|
|
314
|
-
catch { fail("结构化路由卡不是有效 JSON"); }
|
|
315
|
-
if (value.mode === "direct") {
|
|
316
|
-
if (!String(value.delivery || "").trim()) fail("direct 路由缺少完整交付");
|
|
317
|
-
return `mode: direct\n\n${String(value.delivery).trim()}\n`;
|
|
318
|
-
}
|
|
319
|
-
for (const key of ["target", "evidence", "scope", "decision", "stop"]) if (!String(value[key] || "").trim()) fail(`planned 路由缺少 ${key}`);
|
|
320
|
-
if (!new Set(["controller", "executor"]).has(value.execute)) fail("planned 路由只能交给 controller 或 executor");
|
|
321
|
-
if (!Array.isArray(value.accept) || value.accept.length === 0) fail("planned 路由缺少验收条件");
|
|
322
|
-
const acceptance = value.accept.map((item) => {
|
|
323
|
-
const id = String(item?.id || "").trim();
|
|
324
|
-
const condition = String(item?.condition || "").trim();
|
|
325
|
-
if (!id || !condition) fail("planned 路由包含空验收条件");
|
|
326
|
-
return `- ${id}: ${condition}`;
|
|
327
|
-
});
|
|
328
|
-
const reviewIds = Array.isArray(value.review_ids) ? value.review_ids.map((item) => String(item).trim()).filter(Boolean) : [];
|
|
329
|
-
const lines = ["mode: planned", `target: ${String(value.target).trim()}`, `evidence: ${String(value.evidence).trim()}`, `scope: ${String(value.scope).trim()}`, `decision: ${String(value.decision).trim()}`, `execute: ${value.execute}`, `review: ${reviewIds.length > 0 ? `reviewer ${reviewIds.join(" ")}` : "none"}`, "accept:", ...acceptance, `stop: ${String(value.stop).trim()}`];
|
|
330
|
-
const steps = Array.isArray(value.steps) ? value.steps.map((item) => String(item).trim()).filter(Boolean) : [];
|
|
331
|
-
if (steps.length > 0) lines.push("steps:", ...steps.map((item) => `- ${item}`));
|
|
332
|
-
return `${lines.join("\n")}\n`;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
284
|
function tail(value) { return String(value || "").trim().slice(-2000); }
|
|
336
285
|
function fail(message) { throw new Error(message); }
|
|
@@ -9,19 +9,19 @@ import { fileURLToPath } from "node:url";
|
|
|
9
9
|
|
|
10
10
|
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
11
11
|
const args = parseArgs(process.argv.slice(2));
|
|
12
|
-
const mappings = new Map([["odai_researcher", "researcher"], ["odai_planner", "planner"], ["
|
|
12
|
+
const mappings = new Map([["odai_researcher", "researcher"], ["odai_planner", "planner"], ["odai_reviewer", "reviewer"], ["odai_frontend", "frontend"]]);
|
|
13
13
|
|
|
14
14
|
if (args.help) {
|
|
15
15
|
console.log(`Usage:
|
|
16
16
|
node odai-verify-routing.mjs --host codex --project <directory> \\
|
|
17
|
-
--role <odai_researcher|odai_planner|
|
|
17
|
+
--role <odai_researcher|odai_planner|odai_reviewer|odai_frontend> --after <ISO timestamp> \\
|
|
18
18
|
[--agent-path </root/task>] [--sessions <directory>]
|
|
19
19
|
|
|
20
20
|
只读取近期 Codex rollout metadata,把实际角色、模型与推理档和 odai 托管清单对账。`);
|
|
21
21
|
process.exit(0);
|
|
22
22
|
}
|
|
23
23
|
if (args.host !== "codex") fail(`不支持的 host:${args.host || "(missing)"}`);
|
|
24
|
-
if (!mappings.has(args.role)) fail("--role 必须是 odai_researcher、odai_planner、
|
|
24
|
+
if (!mappings.has(args.role)) fail("--role 必须是 odai_researcher、odai_planner、odai_reviewer 或 odai_frontend");
|
|
25
25
|
if (!args.project || !args.after) fail("缺少 --project 或 --after");
|
|
26
26
|
const after = Date.parse(args.after);
|
|
27
27
|
if (!Number.isFinite(after)) fail(`无效的 --after:${args.after}`);
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { DshAgent, DshEvent, RuntimeTool } from "./runtime-types.mjs";
|
|
2
|
-
export declare const ROUTE_CARD_PROMPT: string;
|
|
3
|
-
export type RouteAuthorizationStatus = "authorized" | "plan-only" | "unknown";
|
|
4
|
-
export interface RouteAuthorization {
|
|
5
|
-
readonly status: RouteAuthorizationStatus;
|
|
6
|
-
readonly userMessageId?: string;
|
|
7
|
-
}
|
|
8
|
-
export interface RouteCard {
|
|
9
|
-
readonly id: string;
|
|
10
|
-
readonly frozen: true;
|
|
11
|
-
readonly observableBenefit: true;
|
|
12
|
-
readonly authorization: RouteAuthorization;
|
|
13
|
-
readonly target: string;
|
|
14
|
-
readonly evidence: readonly string[];
|
|
15
|
-
readonly scope: readonly string[];
|
|
16
|
-
readonly accept: readonly string[];
|
|
17
|
-
readonly stop: string;
|
|
18
|
-
}
|
|
19
|
-
export type RouteCardToolResult = {
|
|
20
|
-
readonly action: "freeze";
|
|
21
|
-
readonly status: "frozen";
|
|
22
|
-
readonly card: RouteCard;
|
|
23
|
-
} | {
|
|
24
|
-
readonly action: "clear";
|
|
25
|
-
readonly status: "cleared";
|
|
26
|
-
readonly cardId: string;
|
|
27
|
-
} | {
|
|
28
|
-
readonly action: "clear";
|
|
29
|
-
readonly status: "absent";
|
|
30
|
-
};
|
|
31
|
-
export declare function activeRouteCard(events: readonly DshEvent[] | undefined): RouteCard | undefined;
|
|
32
|
-
export declare function unsettledRouteCard(events: readonly DshEvent[] | undefined): RouteCard | undefined;
|
|
33
|
-
export declare function routeCardById(events: readonly DshEvent[] | undefined, cardId: unknown): RouteCard | undefined;
|
|
34
|
-
export interface RouteCardToolOptions {
|
|
35
|
-
onFrozen?(agent: DshAgent, card: RouteCard): void;
|
|
36
|
-
onCleared?(agent: DshAgent, cardId: string): void;
|
|
37
|
-
activeFor?(agent: DshAgent): RouteCard | undefined;
|
|
38
|
-
unsettledFor?(agent: DshAgent): RouteCard | undefined;
|
|
39
|
-
authorizationFor?(agent: DshAgent): RouteAuthorization;
|
|
40
|
-
}
|
|
41
|
-
export declare function createRouteCardTool(options?: RouteCardToolOptions): RuntimeTool<unknown, RouteCardToolResult>;
|
|
42
|
-
//# sourceMappingURL=route-card.d.mts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"route-card.d.mts","sourceRoot":"","sources":["../src/route-card.mts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG3E,eAAO,MAAM,iBAAiB,QAOlB,CAAC;AAEb,MAAM,MAAM,wBAAwB,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAC;AAE9E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAID,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAClF;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AA6E5D,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAE9F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAEjG;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,QAAQ,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,CAQ7G;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAClD,SAAS,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAClD,SAAS,CAAC,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACnD,YAAY,CAAC,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;IACtD,gBAAgB,CAAC,CAAC,KAAK,EAAE,QAAQ,GAAG,kBAAkB,CAAC;CACxD;AAED,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,oBAAyB,GACjC,WAAW,CAAC,OAAO,EAAE,mBAAmB,CAAC,CA2E3C"}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { isUnknownRecord } from "./runtime-types.mjs";
|
|
3
|
-
export const ROUTE_CARD_PROMPT = [
|
|
4
|
-
"## Odai frozen route cards",
|
|
5
|
-
"Use odai_route_card only after planning has frozen a concrete implementation boundary and executor separation has an observable net benefit.",
|
|
6
|
-
"After the canonical executor reassessment proves observable net benefit, freeze the card before implementation continues. Otherwise continue directly without a card or process narration.",
|
|
7
|
-
"A card must preserve the target, decisive evidence, allowed and forbidden scope, acceptance conditions, and stop condition. Do not freeze a card merely because an executor model is configured or cheaper.",
|
|
8
|
-
"The controller owns the card. Child agents may not create, replace, or clear it. A card is claimed for one executor attempt and consumed only after an applied executor route receipt; validation, provider, or receipt failure releases the claim for retry. A verified provider max-token interruption may reclaim that same card only after a direct user continuation, without changing its scope or authorization. A later explicit clear is terminal and cannot be undone by a delayed release.",
|
|
9
|
-
"When the original current task already authorizes implementation, a planner that freezes a card must submit an executor responsibility gap so implementation continues automatically in the same user task. Ask the user only for a new task, plan-only request, changed scope, or missing user-owned authorization.",
|
|
10
|
-
].join("\n");
|
|
11
|
-
function nonEmptyString(value, field) {
|
|
12
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
13
|
-
throw new TypeError(`${field} must be a non-empty string`);
|
|
14
|
-
return value.trim();
|
|
15
|
-
}
|
|
16
|
-
function stringList(value, field, minimum = 0) {
|
|
17
|
-
if (!Array.isArray(value) || value.length < minimum) {
|
|
18
|
-
throw new TypeError(`${field} must be an array with at least ${minimum} item${minimum === 1 ? "" : "s"}`);
|
|
19
|
-
}
|
|
20
|
-
return Object.freeze(value.map((item, index) => nonEmptyString(item, `${field}[${index}]`)));
|
|
21
|
-
}
|
|
22
|
-
function normalizeAuthorization(value) {
|
|
23
|
-
if (!isUnknownRecord(value))
|
|
24
|
-
return Object.freeze({ status: "unknown" });
|
|
25
|
-
const status = value.status;
|
|
26
|
-
if (status !== "authorized" && status !== "plan-only" && status !== "unknown") {
|
|
27
|
-
return Object.freeze({ status: "unknown" });
|
|
28
|
-
}
|
|
29
|
-
const userMessageId = typeof value.userMessageId === "string" && value.userMessageId.length > 0 && value.userMessageId.length <= 200
|
|
30
|
-
? value.userMessageId
|
|
31
|
-
: undefined;
|
|
32
|
-
return Object.freeze({ status, ...(userMessageId ? { userMessageId } : {}) });
|
|
33
|
-
}
|
|
34
|
-
function normalizeCard(arguments_, authorization) {
|
|
35
|
-
if (arguments_.observableBenefit !== true) {
|
|
36
|
-
throw new TypeError("observableBenefit must be true before freezing an executor route card");
|
|
37
|
-
}
|
|
38
|
-
return Object.freeze({
|
|
39
|
-
id: randomUUID(),
|
|
40
|
-
frozen: true,
|
|
41
|
-
observableBenefit: true,
|
|
42
|
-
authorization: normalizeAuthorization(authorization),
|
|
43
|
-
target: nonEmptyString(arguments_.target, "target"),
|
|
44
|
-
evidence: stringList(arguments_.evidence, "evidence", 1),
|
|
45
|
-
scope: stringList(arguments_.scope, "scope", 1),
|
|
46
|
-
accept: stringList(arguments_.accept, "accept", 1),
|
|
47
|
-
stop: nonEmptyString(arguments_.stop, "stop"),
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
function isRouteCard(value) {
|
|
51
|
-
return isUnknownRecord(value)
|
|
52
|
-
&& value.frozen === true
|
|
53
|
-
&& typeof value.id === "string";
|
|
54
|
-
}
|
|
55
|
-
function routeCardInState(events, acceptedStates) {
|
|
56
|
-
const source = Array.isArray(events) ? events : [];
|
|
57
|
-
const permanentlyCleared = new Set(source.flatMap((event) => (event?.type === "odai/route-card-cleared" && typeof event.data?.cardId === "string"
|
|
58
|
-
? [event.data.cardId]
|
|
59
|
-
: [])));
|
|
60
|
-
const latestState = new Map();
|
|
61
|
-
for (let index = source.length - 1; index >= 0; index -= 1) {
|
|
62
|
-
const event = source[index];
|
|
63
|
-
const cardId = event?.data?.cardId;
|
|
64
|
-
if (typeof cardId === "string" && !latestState.has(cardId)) {
|
|
65
|
-
if (event.type === "odai/route-card-claim-released")
|
|
66
|
-
latestState.set(cardId, "active");
|
|
67
|
-
else if (event.type === "odai/route-card-claimed")
|
|
68
|
-
latestState.set(cardId, "claimed");
|
|
69
|
-
else if (["odai/route-card-cleared", "odai/route-card-consumed"].includes(event.type))
|
|
70
|
-
latestState.set(cardId, "closed");
|
|
71
|
-
}
|
|
72
|
-
if (event?.type !== "odai/route-card-frozen")
|
|
73
|
-
continue;
|
|
74
|
-
const card = event.data?.card;
|
|
75
|
-
if (!isRouteCard(card))
|
|
76
|
-
continue;
|
|
77
|
-
const state = permanentlyCleared.has(card.id) ? "closed" : (latestState.get(card.id) ?? "active");
|
|
78
|
-
if (acceptedStates.has(state))
|
|
79
|
-
return card;
|
|
80
|
-
}
|
|
81
|
-
return undefined;
|
|
82
|
-
}
|
|
83
|
-
export function activeRouteCard(events) {
|
|
84
|
-
return routeCardInState(events, new Set(["active"]));
|
|
85
|
-
}
|
|
86
|
-
export function unsettledRouteCard(events) {
|
|
87
|
-
return routeCardInState(events, new Set(["active", "claimed"]));
|
|
88
|
-
}
|
|
89
|
-
export function routeCardById(events, cardId) {
|
|
90
|
-
if (typeof cardId !== "string" || cardId === "")
|
|
91
|
-
return undefined;
|
|
92
|
-
for (let index = (Array.isArray(events) ? events.length : 0) - 1; index >= 0; index -= 1) {
|
|
93
|
-
const event = events?.[index];
|
|
94
|
-
const card = event?.data?.card;
|
|
95
|
-
if (event?.type === "odai/route-card-frozen" && isRouteCard(card) && card.id === cardId)
|
|
96
|
-
return card;
|
|
97
|
-
}
|
|
98
|
-
return undefined;
|
|
99
|
-
}
|
|
100
|
-
export function createRouteCardTool(options = {}) {
|
|
101
|
-
const onFrozen = typeof options.onFrozen === "function" ? options.onFrozen : () => { };
|
|
102
|
-
const onCleared = typeof options.onCleared === "function" ? options.onCleared : () => { };
|
|
103
|
-
const activeFor = typeof options.activeFor === "function" ? options.activeFor : () => undefined;
|
|
104
|
-
const unsettledFor = typeof options.unsettledFor === "function" ? options.unsettledFor : activeFor;
|
|
105
|
-
const authorizationFor = typeof options.authorizationFor === "function"
|
|
106
|
-
? options.authorizationFor
|
|
107
|
-
: () => Object.freeze({ status: "unknown" });
|
|
108
|
-
return {
|
|
109
|
-
name: "odai_route_card",
|
|
110
|
-
description: "Freeze or clear one structured executor route card. Use only when planning has bounded implementation and independently justified executor separation.",
|
|
111
|
-
parameters: {
|
|
112
|
-
type: "object",
|
|
113
|
-
additionalProperties: false,
|
|
114
|
-
required: ["action"],
|
|
115
|
-
properties: {
|
|
116
|
-
action: { type: "string", enum: ["freeze", "clear"] },
|
|
117
|
-
target: { type: "string" },
|
|
118
|
-
evidence: { type: "array", items: { type: "string" } },
|
|
119
|
-
scope: { type: "array", items: { type: "string" } },
|
|
120
|
-
accept: { type: "array", items: { type: "string" } },
|
|
121
|
-
stop: { type: "string" },
|
|
122
|
-
observableBenefit: { type: "boolean" },
|
|
123
|
-
cardId: { type: "string" },
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
output: {
|
|
127
|
-
schema: {
|
|
128
|
-
type: "object",
|
|
129
|
-
additionalProperties: false,
|
|
130
|
-
required: ["action", "status"],
|
|
131
|
-
properties: {
|
|
132
|
-
action: { type: "string", enum: ["freeze", "clear"] },
|
|
133
|
-
status: { type: "string", enum: ["frozen", "cleared", "absent"] },
|
|
134
|
-
card: { type: "object" },
|
|
135
|
-
cardId: { type: "string" },
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
render(_arguments, value) {
|
|
139
|
-
return [{
|
|
140
|
-
type: "text",
|
|
141
|
-
text: value.status === "frozen"
|
|
142
|
-
? `Frozen executor route card ${value.card.id}: ${value.card.target}`
|
|
143
|
-
: value.status === "cleared"
|
|
144
|
-
? `Cleared executor route card ${value.cardId}.`
|
|
145
|
-
: "No active executor route card exists.",
|
|
146
|
-
}];
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
execute(arguments_, execution) {
|
|
150
|
-
if (!execution.agent)
|
|
151
|
-
throw new Error("odai_route_card requires an owning agent session");
|
|
152
|
-
const header = execution.agent.session?.header;
|
|
153
|
-
if (header?.origin === "subagent" || (Number.isSafeInteger(header?.delegationDepth) && (header?.delegationDepth ?? 0) > 0)) {
|
|
154
|
-
throw new Error("child agents may not change Odai route cards");
|
|
155
|
-
}
|
|
156
|
-
if (!isUnknownRecord(arguments_))
|
|
157
|
-
throw new TypeError("arguments must be an object");
|
|
158
|
-
if (arguments_.action === "freeze") {
|
|
159
|
-
const active = unsettledFor(execution.agent);
|
|
160
|
-
if (active)
|
|
161
|
-
throw new Error(`executor route card ${active.id} is already active or claimed`);
|
|
162
|
-
const card = normalizeCard(arguments_, authorizationFor(execution.agent));
|
|
163
|
-
onFrozen(execution.agent, card);
|
|
164
|
-
return Promise.resolve(Object.freeze({ action: "freeze", status: "frozen", card }));
|
|
165
|
-
}
|
|
166
|
-
if (arguments_.action === "clear") {
|
|
167
|
-
const card = activeFor(execution.agent);
|
|
168
|
-
if (!card)
|
|
169
|
-
return Promise.resolve(Object.freeze({ action: "clear", status: "absent" }));
|
|
170
|
-
if (arguments_.cardId !== undefined && arguments_.cardId !== card.id) {
|
|
171
|
-
throw new Error(`route card ${String(arguments_.cardId)} does not match active card ${card.id}`);
|
|
172
|
-
}
|
|
173
|
-
onCleared(execution.agent, card.id);
|
|
174
|
-
return Promise.resolve(Object.freeze({ action: "clear", status: "cleared", cardId: card.id }));
|
|
175
|
-
}
|
|
176
|
-
throw new TypeError("action must be freeze or clear");
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
//# sourceMappingURL=route-card.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"route-card.mjs","sourceRoot":"","sources":["../src/route-card.mts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
跟随用户当前的主要语言。你是按已核实方案实施的唯一 executor,不是总控、规划者或最终验收者。只接收冻结方案与证据指针,不接收完整历史来重新解释需求。
|
|
2
|
-
|
|
3
|
-
不重新盘点仓库、论证目标或另选路线。只读完成真实产物所需的目标原件、直接依赖和必要验收入口。局部选择不改变业务语义、公共契约、用户取舍或高代价后果时,依现有接口、命名、测试风格和最小必要改动自主完成;只有上述结果会改变时才停止并回交决定缺口。
|
|
4
|
-
|
|
5
|
-
参考可读不因此可写。验证需求不自动授权改测试、基准、文档或其他证据源;项目已点名现成入口时先原样运行。写入持久文件必须有请求、项目契约或冻结方案对该载体的真实需要,不为暂存内容、证明完成或交接自造文件。
|
|
6
|
-
|
|
7
|
-
不先跑只为再次确认 planner 结论的基线检查。实施后每项必要验证只运行一次;只有失败并完成针对性修正后才重跑。决定性证据已闭合验收且没有新的失败信号时立即停止调查,直接回交。
|
|
8
|
-
|
|
9
|
-
新证据只暴露实施偏差时,在原边界内做最小修正;新证据推翻决定、范围或验收时,立即停止受影响动作,回交精确证据,不自行改路。reviewer 的 finding 只授权修正原产物,不授权新建证明文件或改写验收源。
|
|
10
|
-
|
|
11
|
-
回交必须自足:包含实际改动、改变决定的权威来源、精确 diff 摘要、真实命令与结果、未决项和停止条件。宿主提供结构化回交契约时严格遵循;否则末尾给出覆盖全部验收 ID 的唯一 `<odai_closeout>` JSON。每项包含 `status`、实际 `evidence` 和 `next`;已验证项的 `next` 为空,未决或失败项写真实继续条件。不得自行批准最终交付、虚构验证或把自报当独立验收。
|