odai-dsh-agent 0.0.2 → 0.0.4
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 +21 -21
- package/README.md +86 -86
- package/bin/odai-dsh-agent.mjs +106 -87
- package/package.json +68 -68
- package/preset/odai/agent.cordis.yml +260 -260
- package/preset/odai/preset.yml +3 -3
- package/preset/odai/runtime/governance.mjs +120 -120
- package/preset/odai/runtime/index.mjs +587 -584
- package/preset/odai/runtime/router.mjs +290 -290
- package/preset/odai/runtime/routing-config.mjs +323 -322
- package/preset/odai/runtime/session-compat.mjs +387 -0
- package/preset/odai/runtime/session-evidence.mjs +344 -0
- package/preset/odai/skills/odai/SKILL.md +65 -65
- package/preset/odai/skills/odai/agents/openai.yaml +4 -4
- package/preset/odai/skills/odai/assets/claude-agents/agent.md +11 -11
- package/preset/odai/skills/odai/assets/codex-agents/config.toml +11 -11
- package/preset/odai/skills/odai/assets/codex-agents/role.toml +5 -5
- package/preset/odai/skills/odai/assets/copilot-agents/agent.md +13 -13
- package/preset/odai/skills/odai/assets/hooks-policy.example.json +24 -24
- package/preset/odai/skills/odai/assets/routing-roles/controller.md +15 -15
- package/preset/odai/skills/odai/assets/routing-roles/executor.md +11 -11
- package/preset/odai/skills/odai/assets/routing-roles/planner.md +29 -29
- package/preset/odai/skills/odai/assets/routing-roles/reviewer.md +11 -11
- package/preset/odai/skills/odai/assets/task-state.md +12 -12
- package/preset/odai/skills/odai/references/craft.md +53 -53
- package/preset/odai/skills/odai/references/dao.md +30 -30
- package/preset/odai/skills/odai/references/leverage.md +45 -45
- package/preset/odai/skills/odai/references/support.md +36 -36
- package/preset/odai/skills/odai/references/verification.md +23 -23
- package/preset/odai/skills/odai/scripts/build-hooks.mjs +273 -273
- package/preset/odai/skills/odai/scripts/build-routing.mjs +239 -239
- package/preset/odai/skills/odai/scripts/install-routing.mjs +375 -375
- package/preset/odai/skills/odai/scripts/odai-hook.mjs +457 -457
- package/preset/odai/skills/odai/scripts/run-role.mjs +336 -336
- package/preset/odai/skills/odai/scripts/run-routing.mjs +1154 -1154
- package/preset/odai/skills/odai/scripts/verify-routing.mjs +103 -103
- package/scripts/verify-agent-load.mjs +246 -217
- package/src/dsh-version.mjs +20 -0
- package/src/installer.mjs +323 -270
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
export const DEFAULT_CHILD_DENIED_TOOLS = Object.freeze([
|
|
2
|
-
"write",
|
|
3
|
-
"edit",
|
|
4
|
-
"str_replace_editor",
|
|
5
|
-
"bash",
|
|
6
|
-
"pwsh",
|
|
7
|
-
"ask_user_question",
|
|
8
|
-
"subagent",
|
|
9
|
-
"subagent_fork",
|
|
10
|
-
"subagent_codex",
|
|
11
|
-
"subagent_claude_code",
|
|
12
|
-
"send_message",
|
|
13
|
-
"interrupt_agent",
|
|
14
|
-
"list_agents",
|
|
15
|
-
"workflow",
|
|
16
|
-
"ralph",
|
|
17
|
-
"job_output",
|
|
18
|
-
"job_list",
|
|
19
|
-
"job_kill",
|
|
20
|
-
]);
|
|
21
|
-
|
|
22
|
-
export const DEFAULT_PROTECTED_CONTROLLER_ALLOWED_TOOLS = Object.freeze([
|
|
23
|
-
"read",
|
|
24
|
-
"read_image",
|
|
25
|
-
"glob",
|
|
26
|
-
"grep",
|
|
27
|
-
"web_search",
|
|
28
|
-
"web_fetch",
|
|
29
|
-
"ask_user_question",
|
|
30
|
-
"get_goal",
|
|
31
|
-
"list_agents",
|
|
32
|
-
"job_output",
|
|
33
|
-
"job_list",
|
|
34
|
-
"skill",
|
|
35
|
-
]);
|
|
36
|
-
|
|
37
|
-
export function isSubagent(agent) {
|
|
38
|
-
const header = agent?.session?.header;
|
|
39
|
-
return header?.origin === "subagent"
|
|
40
|
-
|| (Number.isSafeInteger(header?.delegationDepth) && header.delegationDepth > 0);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function createChildToolGuard(options = {}) {
|
|
44
|
-
const denied = new Set([
|
|
45
|
-
...DEFAULT_CHILD_DENIED_TOOLS,
|
|
46
|
-
...(Array.isArray(options.additionalDeniedTools) ? options.additionalDeniedTools : []),
|
|
47
|
-
]);
|
|
48
|
-
const onDenied = typeof options.onDenied === "function" ? options.onDenied : () => {};
|
|
49
|
-
|
|
50
|
-
return (execution) => {
|
|
51
|
-
if (!isSubagent(execution?.agent)) return undefined;
|
|
52
|
-
if (!denied.has(execution?.name)) return undefined;
|
|
53
|
-
|
|
54
|
-
const reason = `ODAI_SUBAGENT_BOUNDARY: child agents may not execute ${execution.name}; return evidence to the controller instead.`;
|
|
55
|
-
onDenied(execution, reason);
|
|
56
|
-
return reason;
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function activeRouteProtection(agent) {
|
|
61
|
-
if (isSubagent(agent)) return undefined;
|
|
62
|
-
const events =
|
|
63
|
-
if (!Array.isArray(events)) return undefined;
|
|
64
|
-
|
|
65
|
-
let currentTurn;
|
|
66
|
-
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
67
|
-
const event = events[index];
|
|
68
|
-
if (event?.type !== "odai/route-decided") continue;
|
|
69
|
-
if (!Number.isSafeInteger(event.data?.turn)) return undefined;
|
|
70
|
-
currentTurn = event.data.turn;
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
if (currentTurn === undefined) return undefined;
|
|
74
|
-
|
|
75
|
-
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
76
|
-
const event = events[index];
|
|
77
|
-
if (event?.type !== "odai/route-protection") continue;
|
|
78
|
-
if (event.data?.turn === currentTurn && event.data?.mode === "read-only") return event.data;
|
|
79
|
-
}
|
|
80
|
-
return undefined;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function createRouteProtectionGuard(options = {}) {
|
|
84
|
-
const allowed = new Set(DEFAULT_PROTECTED_CONTROLLER_ALLOWED_TOOLS);
|
|
85
|
-
for (const name of Array.isArray(options.additionalDeniedTools) ? options.additionalDeniedTools : []) {
|
|
86
|
-
allowed.delete(name);
|
|
87
|
-
}
|
|
88
|
-
const onDenied = typeof options.onDenied === "function" ? options.onDenied : () => {};
|
|
89
|
-
const protectionFor = typeof options.protectionFor === "function"
|
|
90
|
-
? options.protectionFor
|
|
91
|
-
: activeRouteProtection;
|
|
92
|
-
|
|
93
|
-
return (execution) => {
|
|
94
|
-
if (isSubagent(execution?.agent)) return undefined;
|
|
95
|
-
if (allowed.has(execution?.name)) return undefined;
|
|
96
|
-
const protection = protectionFor(execution?.agent);
|
|
97
|
-
if (!protection) return undefined;
|
|
98
|
-
|
|
99
|
-
const reasonCode = protection.reasonCode ?? "unresolved-high-impact-route";
|
|
100
|
-
const reason = `ODAI_HIGH_IMPACT_ROUTE_BLOCKED: controller may not execute ${execution.name} while ${reasonCode} remains unresolved; use read-only evidence and provide an actionable decision path.`;
|
|
101
|
-
onDenied(execution, reason);
|
|
102
|
-
return reason;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function summarizeToolResult(execution, result) {
|
|
107
|
-
const summary = {
|
|
108
|
-
callId: String(execution.callId),
|
|
109
|
-
rootCallId: String(execution.rootCallId),
|
|
110
|
-
tool: execution.name,
|
|
111
|
-
child: isSubagent(execution.agent),
|
|
112
|
-
isError: result.isError === true,
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (result.isError === true && result.error?.code) {
|
|
116
|
-
summary.errorCode = String(result.error.code);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return summary;
|
|
120
|
-
}
|
|
1
|
+
export const DEFAULT_CHILD_DENIED_TOOLS = Object.freeze([
|
|
2
|
+
"write",
|
|
3
|
+
"edit",
|
|
4
|
+
"str_replace_editor",
|
|
5
|
+
"bash",
|
|
6
|
+
"pwsh",
|
|
7
|
+
"ask_user_question",
|
|
8
|
+
"subagent",
|
|
9
|
+
"subagent_fork",
|
|
10
|
+
"subagent_codex",
|
|
11
|
+
"subagent_claude_code",
|
|
12
|
+
"send_message",
|
|
13
|
+
"interrupt_agent",
|
|
14
|
+
"list_agents",
|
|
15
|
+
"workflow",
|
|
16
|
+
"ralph",
|
|
17
|
+
"job_output",
|
|
18
|
+
"job_list",
|
|
19
|
+
"job_kill",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
export const DEFAULT_PROTECTED_CONTROLLER_ALLOWED_TOOLS = Object.freeze([
|
|
23
|
+
"read",
|
|
24
|
+
"read_image",
|
|
25
|
+
"glob",
|
|
26
|
+
"grep",
|
|
27
|
+
"web_search",
|
|
28
|
+
"web_fetch",
|
|
29
|
+
"ask_user_question",
|
|
30
|
+
"get_goal",
|
|
31
|
+
"list_agents",
|
|
32
|
+
"job_output",
|
|
33
|
+
"job_list",
|
|
34
|
+
"skill",
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
export function isSubagent(agent) {
|
|
38
|
+
const header = agent?.session?.header;
|
|
39
|
+
return header?.origin === "subagent"
|
|
40
|
+
|| (Number.isSafeInteger(header?.delegationDepth) && header.delegationDepth > 0);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function createChildToolGuard(options = {}) {
|
|
44
|
+
const denied = new Set([
|
|
45
|
+
...DEFAULT_CHILD_DENIED_TOOLS,
|
|
46
|
+
...(Array.isArray(options.additionalDeniedTools) ? options.additionalDeniedTools : []),
|
|
47
|
+
]);
|
|
48
|
+
const onDenied = typeof options.onDenied === "function" ? options.onDenied : () => {};
|
|
49
|
+
|
|
50
|
+
return (execution) => {
|
|
51
|
+
if (!isSubagent(execution?.agent)) return undefined;
|
|
52
|
+
if (!denied.has(execution?.name)) return undefined;
|
|
53
|
+
|
|
54
|
+
const reason = `ODAI_SUBAGENT_BOUNDARY: child agents may not execute ${execution.name}; return evidence to the controller instead.`;
|
|
55
|
+
onDenied(execution, reason);
|
|
56
|
+
return reason;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function activeRouteProtection(agent, recordedEvents = agent?.session?.events) {
|
|
61
|
+
if (isSubagent(agent)) return undefined;
|
|
62
|
+
const events = recordedEvents;
|
|
63
|
+
if (!Array.isArray(events)) return undefined;
|
|
64
|
+
|
|
65
|
+
let currentTurn;
|
|
66
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
67
|
+
const event = events[index];
|
|
68
|
+
if (event?.type !== "odai/route-decided") continue;
|
|
69
|
+
if (!Number.isSafeInteger(event.data?.turn)) return undefined;
|
|
70
|
+
currentTurn = event.data.turn;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
if (currentTurn === undefined) return undefined;
|
|
74
|
+
|
|
75
|
+
for (let index = events.length - 1; index >= 0; index -= 1) {
|
|
76
|
+
const event = events[index];
|
|
77
|
+
if (event?.type !== "odai/route-protection") continue;
|
|
78
|
+
if (event.data?.turn === currentTurn && event.data?.mode === "read-only") return event.data;
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function createRouteProtectionGuard(options = {}) {
|
|
84
|
+
const allowed = new Set(DEFAULT_PROTECTED_CONTROLLER_ALLOWED_TOOLS);
|
|
85
|
+
for (const name of Array.isArray(options.additionalDeniedTools) ? options.additionalDeniedTools : []) {
|
|
86
|
+
allowed.delete(name);
|
|
87
|
+
}
|
|
88
|
+
const onDenied = typeof options.onDenied === "function" ? options.onDenied : () => {};
|
|
89
|
+
const protectionFor = typeof options.protectionFor === "function"
|
|
90
|
+
? options.protectionFor
|
|
91
|
+
: activeRouteProtection;
|
|
92
|
+
|
|
93
|
+
return (execution) => {
|
|
94
|
+
if (isSubagent(execution?.agent)) return undefined;
|
|
95
|
+
if (allowed.has(execution?.name)) return undefined;
|
|
96
|
+
const protection = protectionFor(execution?.agent);
|
|
97
|
+
if (!protection) return undefined;
|
|
98
|
+
|
|
99
|
+
const reasonCode = protection.reasonCode ?? "unresolved-high-impact-route";
|
|
100
|
+
const reason = `ODAI_HIGH_IMPACT_ROUTE_BLOCKED: controller may not execute ${execution.name} while ${reasonCode} remains unresolved; use read-only evidence and provide an actionable decision path.`;
|
|
101
|
+
onDenied(execution, reason);
|
|
102
|
+
return reason;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function summarizeToolResult(execution, result) {
|
|
107
|
+
const summary = {
|
|
108
|
+
callId: String(execution.callId),
|
|
109
|
+
rootCallId: String(execution.rootCallId),
|
|
110
|
+
tool: execution.name,
|
|
111
|
+
child: isSubagent(execution.agent),
|
|
112
|
+
isError: result.isError === true,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (result.isError === true && result.error?.code) {
|
|
116
|
+
summary.errorCode = String(result.error.code);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return summary;
|
|
120
|
+
}
|