odai-dsh-agent 0.2.5 → 0.2.7
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 +3 -3
- package/build/bin/odai-dsh-agent.d.mts +3 -0
- package/build/bin/odai-dsh-agent.d.mts.map +1 -0
- package/build/bin/odai-dsh-agent.mjs +114 -0
- package/build/bin/odai-dsh-agent.mjs.map +1 -0
- package/build/src/dsh-version.d.mts +16 -0
- package/build/src/dsh-version.d.mts.map +1 -0
- package/build/src/dsh-version.mjs +20 -0
- package/build/src/dsh-version.mjs.map +1 -0
- package/build/src/installer.d.mts +46 -0
- package/build/src/installer.d.mts.map +1 -0
- package/build/src/installer.mjs +398 -0
- package/build/src/installer.mjs.map +1 -0
- package/package.json +13 -12
- package/preset/odai/runtime/compaction-config.d.mts +66 -0
- package/preset/odai/runtime/compaction-config.d.mts.map +1 -0
- package/preset/odai/runtime/compaction-config.mjs +320 -342
- package/preset/odai/runtime/compaction-config.mjs.map +1 -0
- package/preset/odai/runtime/compaction-runtime.d.mts +68 -0
- package/preset/odai/runtime/compaction-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/compaction-runtime.mjs +157 -0
- package/preset/odai/runtime/compaction-runtime.mjs.map +1 -0
- package/preset/odai/runtime/context-activation.d.mts +31 -0
- package/preset/odai/runtime/context-activation.d.mts.map +1 -0
- package/preset/odai/runtime/context-activation.mjs +55 -49
- package/preset/odai/runtime/context-activation.mjs.map +1 -0
- package/preset/odai/runtime/context-capability.d.mts +16 -0
- package/preset/odai/runtime/context-capability.d.mts.map +1 -0
- package/preset/odai/runtime/context-capability.mjs +79 -74
- package/preset/odai/runtime/context-capability.mjs.map +1 -0
- package/preset/odai/runtime/governance.d.mts +30 -0
- package/preset/odai/runtime/governance.d.mts.map +1 -0
- package/preset/odai/runtime/governance.mjs +126 -113
- package/preset/odai/runtime/governance.mjs.map +1 -0
- package/preset/odai/runtime/human-care.d.mts +13 -0
- package/preset/odai/runtime/human-care.d.mts.map +1 -0
- package/preset/odai/runtime/human-care.mjs +45 -42
- package/preset/odai/runtime/human-care.mjs.map +1 -0
- package/preset/odai/runtime/human-safety-continuity-store.d.mts +43 -0
- package/preset/odai/runtime/human-safety-continuity-store.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety-continuity-store.mjs +193 -215
- package/preset/odai/runtime/human-safety-continuity-store.mjs.map +1 -0
- package/preset/odai/runtime/human-safety-continuity.d.mts +27 -0
- package/preset/odai/runtime/human-safety-continuity.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety-continuity.mjs +205 -216
- package/preset/odai/runtime/human-safety-continuity.mjs.map +1 -0
- package/preset/odai/runtime/human-safety.d.mts +14 -0
- package/preset/odai/runtime/human-safety.d.mts.map +1 -0
- package/preset/odai/runtime/human-safety.mjs +50 -47
- package/preset/odai/runtime/human-safety.mjs.map +1 -0
- package/preset/odai/runtime/index.d.mts +8 -0
- package/preset/odai/runtime/index.d.mts.map +1 -0
- package/preset/odai/runtime/index.mjs +190 -2473
- package/preset/odai/runtime/index.mjs.map +1 -0
- package/preset/odai/runtime/lifecycle-runtime.d.mts +83 -0
- package/preset/odai/runtime/lifecycle-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/lifecycle-runtime.mjs +1140 -0
- package/preset/odai/runtime/lifecycle-runtime.mjs.map +1 -0
- package/preset/odai/runtime/model-route.d.mts +22 -0
- package/preset/odai/runtime/model-route.d.mts.map +1 -0
- package/preset/odai/runtime/model-route.mjs +68 -60
- package/preset/odai/runtime/model-route.mjs.map +1 -0
- package/preset/odai/runtime/output-config.d.mts +54 -0
- package/preset/odai/runtime/output-config.d.mts.map +1 -0
- package/preset/odai/runtime/output-config.mjs +289 -315
- package/preset/odai/runtime/output-config.mjs.map +1 -0
- package/preset/odai/runtime/output-policy-state.d.mts +3 -0
- package/preset/odai/runtime/output-policy-state.d.mts.map +1 -0
- package/preset/odai/runtime/output-policy-state.mjs +41 -29
- package/preset/odai/runtime/output-policy-state.mjs.map +1 -0
- package/preset/odai/runtime/prompt-runtime.d.mts +55 -0
- package/preset/odai/runtime/prompt-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/prompt-runtime.mjs +303 -0
- package/preset/odai/runtime/prompt-runtime.mjs.map +1 -0
- package/preset/odai/runtime/research-packet.d.mts +30 -0
- package/preset/odai/runtime/research-packet.d.mts.map +1 -0
- package/preset/odai/runtime/research-packet.mjs +116 -117
- package/preset/odai/runtime/research-packet.mjs.map +1 -0
- package/preset/odai/runtime/responsibility-gap.d.mts +26 -0
- package/preset/odai/runtime/responsibility-gap.d.mts.map +1 -0
- package/preset/odai/runtime/responsibility-gap.mjs +93 -85
- package/preset/odai/runtime/responsibility-gap.mjs.map +1 -0
- package/preset/odai/runtime/responsibility-scope.d.mts +69 -0
- package/preset/odai/runtime/responsibility-scope.d.mts.map +1 -0
- package/preset/odai/runtime/responsibility-scope.mjs +199 -171
- package/preset/odai/runtime/responsibility-scope.mjs.map +1 -0
- package/preset/odai/runtime/role-overlays.d.mts +5 -0
- package/preset/odai/runtime/role-overlays.d.mts.map +1 -0
- package/preset/odai/runtime/role-overlays.mjs +15 -14
- package/preset/odai/runtime/role-overlays.mjs.map +1 -0
- package/preset/odai/runtime/route-card.d.mts +42 -0
- package/preset/odai/runtime/route-card.d.mts.map +1 -0
- package/preset/odai/runtime/route-card.mjs +158 -146
- package/preset/odai/runtime/route-card.mjs.map +1 -0
- package/preset/odai/runtime/router.d.mts +80 -0
- package/preset/odai/runtime/router.d.mts.map +1 -0
- package/preset/odai/runtime/router.mjs +509 -559
- package/preset/odai/runtime/router.mjs.map +1 -0
- package/preset/odai/runtime/routing-config.d.mts +76 -0
- package/preset/odai/runtime/routing-config.d.mts.map +1 -0
- package/preset/odai/runtime/routing-config.mjs +373 -438
- package/preset/odai/runtime/routing-config.mjs.map +1 -0
- package/preset/odai/runtime/routing-context.d.mts +64 -0
- package/preset/odai/runtime/routing-context.d.mts.map +1 -0
- package/preset/odai/runtime/routing-context.mjs +398 -277
- package/preset/odai/runtime/routing-context.mjs.map +1 -0
- package/preset/odai/runtime/runtime-config.d.mts +24 -0
- package/preset/odai/runtime/runtime-config.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-config.mjs +181 -0
- package/preset/odai/runtime/runtime-config.mjs.map +1 -0
- package/preset/odai/runtime/runtime-support.d.mts +91 -0
- package/preset/odai/runtime/runtime-support.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-support.mjs +371 -0
- package/preset/odai/runtime/runtime-support.mjs.map +1 -0
- package/preset/odai/runtime/runtime-types.d.mts +237 -0
- package/preset/odai/runtime/runtime-types.d.mts.map +1 -0
- package/preset/odai/runtime/runtime-types.mjs +4 -0
- package/preset/odai/runtime/runtime-types.mjs.map +1 -0
- package/preset/odai/runtime/semantic-memory-store.d.mts +110 -0
- package/preset/odai/runtime/semantic-memory-store.d.mts.map +1 -0
- package/preset/odai/runtime/semantic-memory-store.mjs +271 -385
- package/preset/odai/runtime/semantic-memory-store.mjs.map +1 -0
- package/preset/odai/runtime/semantic-memory.d.mts +88 -0
- package/preset/odai/runtime/semantic-memory.d.mts.map +1 -0
- package/preset/odai/runtime/semantic-memory.mjs +790 -750
- package/preset/odai/runtime/semantic-memory.mjs.map +1 -0
- package/preset/odai/runtime/session-compat.d.mts +31 -0
- package/preset/odai/runtime/session-compat.d.mts.map +1 -0
- package/preset/odai/runtime/session-compat.mjs +301 -328
- package/preset/odai/runtime/session-compat.mjs.map +1 -0
- package/preset/odai/runtime/session-evidence.d.mts +25 -0
- package/preset/odai/runtime/session-evidence.d.mts.map +1 -0
- package/preset/odai/runtime/session-evidence.mjs +309 -287
- package/preset/odai/runtime/session-evidence.mjs.map +1 -0
- package/preset/odai/runtime/skill-bundle.d.mts +53 -0
- package/preset/odai/runtime/skill-bundle.d.mts.map +1 -0
- package/preset/odai/runtime/skill-bundle.mjs +286 -276
- package/preset/odai/runtime/skill-bundle.mjs.map +1 -0
- package/preset/odai/runtime/skill-evolution.d.mts +112 -0
- package/preset/odai/runtime/skill-evolution.d.mts.map +1 -0
- package/preset/odai/runtime/skill-evolution.mjs +1287 -1261
- package/preset/odai/runtime/skill-evolution.mjs.map +1 -0
- package/preset/odai/runtime/skill-selection-state.d.mts +5 -0
- package/preset/odai/runtime/skill-selection-state.d.mts.map +1 -0
- package/preset/odai/runtime/skill-selection-state.mjs +59 -43
- package/preset/odai/runtime/skill-selection-state.mjs.map +1 -0
- package/preset/odai/runtime/skill-selector.d.mts +28 -0
- package/preset/odai/runtime/skill-selector.d.mts.map +1 -0
- package/preset/odai/runtime/skill-selector.mjs +100 -109
- package/preset/odai/runtime/skill-selector.mjs.map +1 -0
- package/preset/odai/runtime/skill-source-config.d.mts +32 -0
- package/preset/odai/runtime/skill-source-config.d.mts.map +1 -0
- package/preset/odai/runtime/skill-source-config.mjs +200 -210
- package/preset/odai/runtime/skill-source-config.mjs.map +1 -0
- package/preset/odai/runtime/store-lock.d.mts +2 -0
- package/preset/odai/runtime/store-lock.d.mts.map +1 -0
- package/preset/odai/runtime/store-lock.mjs +92 -87
- package/preset/odai/runtime/store-lock.mjs.map +1 -0
- package/preset/odai/runtime/tool-runtime.d.mts +43 -0
- package/preset/odai/runtime/tool-runtime.d.mts.map +1 -0
- package/preset/odai/runtime/tool-runtime.mjs +221 -0
- package/preset/odai/runtime/tool-runtime.mjs.map +1 -0
- package/bin/odai-dsh-agent.mjs +0 -108
- package/scripts/verify-agent-load.mjs +0 -260
- package/src/dsh-version.mjs +0 -24
- package/src/installer.mjs +0 -385
|
@@ -1,321 +1,442 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
|
|
2
|
+
import { classifyResponsibilityInterruptionText } from "./router.mjs";
|
|
3
|
+
import { isUnknownRecord } from "./runtime-types.mjs";
|
|
3
4
|
const DEFAULT_MAX_CHARS = 12_000;
|
|
4
5
|
const DEFAULT_MAX_EVENTS = 80;
|
|
6
|
+
const DEFAULT_MAX_ENTRY_CHARS = 4_000;
|
|
5
7
|
const REQUIREMENT_PATTERNS = [/requirement/iu, /acceptance/iu, /需求/u, /要求/u, /目标/u, /验收/u];
|
|
6
|
-
const ACCEPTANCE_PATTERNS = [/\bA\d+\b/u, /accept(?:ance)?/iu, /验收/u, /通过条件/u, /完成条件/u];
|
|
7
8
|
const DIFF_OUTPUT_PATTERNS = [/diff --git/iu, /^---\s+a\/[^\n]+\n\+\+\+\s+b\//imu];
|
|
8
9
|
const DIFF_COMMAND_PATTERNS = [/^\s*git(?:\.exe)?\s+diff(?:\s|$)/iu];
|
|
9
10
|
const TEST_COMMAND_PATTERNS = [
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
/^\s*(?:&\s*)?(?:"[^"\r\n]*[\\/]node(?:\.exe)?"|[A-Za-z]:\\[^\s"\r\n]*[\\/]node(?:\.exe)?|\/[^\s"\r\n]*\/node|node(?:\.exe)?)\s+--test(?:\s|$)/iu,
|
|
12
|
+
/^\s*(?:npm|pnpm|yarn)(?:\.cmd)?(?:\s+--(?:prefix|dir)\s+(?:"[^"]+"|\S+))?\s+(?:run\s+)?test(?:[:.][\w.-]+)?(?:\s|$)/iu,
|
|
13
|
+
/^\s*(?:(?:npx|pnpm\s+exec|yarn\s+exec)(?:\.cmd)?|npm(?:\.cmd)?\s+exec(?:\s+--)?)\s+(?:--yes\s+)?(?:pytest|vitest|jest|mocha)(?:\.cmd)?(?:\s|$)/iu,
|
|
14
|
+
/^\s*(?:pytest|vitest|jest|mocha)(?:\.cmd)?(?:\s|$)/iu,
|
|
15
|
+
/^\s*(?:go|cargo|dotnet)\s+test(?:\s|$)/iu,
|
|
16
|
+
/^\s*(?:(?:\.\/)?(?:[\w.-]+\/)*mvnw(?:\.cmd)?|mvn(?:\.cmd)?)\s+(?:[^\r\n]*\s)?(?:test|verify)(?:\s|$)/iu,
|
|
17
|
+
/^\s*(?:\.\/)?gradlew(?:\.bat)?\s+(?:[^\r\n]*\s)?test(?:\s|$)/iu,
|
|
14
18
|
];
|
|
15
19
|
const TEST_SUCCESS_PATTERNS = [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
/exit code:\s*0/iu,
|
|
21
|
+
/(?:^|\n)[^\n]*(?:pass|passed)\s*[:=]?\s*[1-9]\d*/iu,
|
|
22
|
+
/(?:^|\n)[^\n]*[1-9]\d*\s+passed\b/iu,
|
|
23
|
+
/(?:^|\n)[^\n]*fail(?:ed)?\s*[:=]?\s*0\b/iu,
|
|
24
|
+
/\btests?\s+\d+[^\n]*(?:pass|passed)\s+[1-9]\d*[^\n]*fail(?:ed)?\s+0\b/iu,
|
|
21
25
|
];
|
|
22
26
|
const TEST_FAILURE_PATTERNS = [
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
27
|
+
/exit code:\s*[1-9]\d*/iu,
|
|
28
|
+
/(?:^|\n)[^\n]*fail(?:ed)?\s*[:=]?\s*[1-9]\d*/iu,
|
|
29
|
+
/\b(?:tests?|test suite) failed\b/iu,
|
|
26
30
|
];
|
|
27
31
|
const WRITE_TOOL_NAMES = new Set(["edit", "write", "apply_patch"]);
|
|
28
32
|
const SHELL_TOOL_NAMES = new Set(["bash", "pwsh", "shell", "powershell"]);
|
|
29
33
|
const SHELL_CONTROL_PATTERN = /[;&|<>]/u;
|
|
30
34
|
const READ_ONLY_SHELL_COMMAND_PATTERNS = [
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
/^\s*git(?:\.exe)?\s+(?:status|log|show|rev-parse|ls-files|branch)(?:\s|$)/iu,
|
|
36
|
+
/^\s*(?:Get-[A-Za-z]+|Select-String|Test-Path)(?:\s|$)/iu,
|
|
37
|
+
/^\s*(?:rg|grep|find|ls|pwd|cat|head|tail|wc|where|which|lsof|ps|netstat|ss)(?:\.exe)?(?:\s|$)/iu,
|
|
38
|
+
/^\s*(?:npx(?:\.cmd)?|pnpm(?:\.cmd)?\s+exec|yarn(?:\.cmd)?\s+exec|npm(?:\.cmd)?\s+exec(?:\s+--)?)?\s*prettier(?:\.cmd)?\s+--check(?:\s|$)/iu,
|
|
39
|
+
/^\s*node(?:\.exe)?\s+--check(?:\s|$)/iu,
|
|
35
40
|
];
|
|
36
41
|
const WRITE_COMMAND_PATTERNS = [
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
/(?:^|\s)(?:git\s+apply|apply_patch|sed\s+-i|perl\s+-pi)(?:\s|$)/iu,
|
|
43
|
+
/(?:^|\s)(?:Set-Content|Add-Content|Out-File|Remove-Item|Move-Item|Copy-Item|New-Item)(?:\s|$)/iu,
|
|
44
|
+
/(?:^|\s)(?:rm|mv|cp|mkdir|touch)(?:\s|$)/u,
|
|
40
45
|
];
|
|
41
|
-
|
|
42
46
|
function textBlocks(value, depth = 0) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (depth > 5 || value === null || value === undefined)
|
|
48
|
+
return [];
|
|
49
|
+
if (typeof value === "string")
|
|
50
|
+
return [value];
|
|
51
|
+
if (Array.isArray(value))
|
|
52
|
+
return value.flatMap((item) => textBlocks(item, depth + 1));
|
|
53
|
+
if (!isUnknownRecord(value))
|
|
54
|
+
return [];
|
|
55
|
+
if (value.type === "text" && typeof value.text === "string")
|
|
56
|
+
return [value.text];
|
|
57
|
+
const keys = ["content", "message", "output", "result", "data", "text", "value", "command", "args", "input"];
|
|
58
|
+
return keys.flatMap((key) => key in value ? textBlocks(value[key], depth + 1) : []);
|
|
50
59
|
}
|
|
51
|
-
|
|
52
60
|
function matchesAny(text, patterns) {
|
|
53
|
-
|
|
61
|
+
return patterns.some((pattern) => pattern.test(text));
|
|
62
|
+
}
|
|
63
|
+
function directUserMessage(event) {
|
|
64
|
+
const message = isUnknownRecord(event.data?.message) ? event.data.message : event.data;
|
|
65
|
+
const source = isUnknownRecord(message?.source) ? message.source : undefined;
|
|
66
|
+
if (typeof message?.role === "string" && message.role !== "user")
|
|
67
|
+
return undefined;
|
|
68
|
+
return source?.kind === "user" ? message : undefined;
|
|
69
|
+
}
|
|
70
|
+
function isDirectUserEvent(event) {
|
|
71
|
+
return directUserMessage(event) !== undefined;
|
|
54
72
|
}
|
|
55
|
-
|
|
56
73
|
function toolResultBlocks(value, depth = 0) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
74
|
+
if (depth > 5 || value === null || value === undefined)
|
|
75
|
+
return [];
|
|
76
|
+
if (Array.isArray(value))
|
|
77
|
+
return value.flatMap((item) => toolResultBlocks(item, depth + 1));
|
|
78
|
+
if (!isUnknownRecord(value))
|
|
79
|
+
return [];
|
|
80
|
+
const own = value.type === "tool-result" ? [value] : [];
|
|
81
|
+
return own.concat(Object.values(value).flatMap((item) => toolResultBlocks(item, depth + 1)));
|
|
62
82
|
}
|
|
63
|
-
|
|
64
83
|
function nativeToolResult(data) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
const blocks = toolResultBlocks(data);
|
|
85
|
+
if (blocks.length !== 1)
|
|
86
|
+
return undefined;
|
|
87
|
+
const block = blocks[0];
|
|
88
|
+
const message = isUnknownRecord(data.message) ? data.message : undefined;
|
|
89
|
+
const source = isUnknownRecord(message?.source) ? message.source : undefined;
|
|
90
|
+
if (source?.kind !== "tool"
|
|
91
|
+
|| typeof source.callId !== "string"
|
|
92
|
+
|| !source.callId
|
|
93
|
+
|| block?.toolCallId !== source.callId
|
|
94
|
+
|| typeof block.isError !== "boolean"
|
|
95
|
+
|| !Array.isArray(block.content))
|
|
96
|
+
return undefined;
|
|
97
|
+
return Object.freeze({
|
|
98
|
+
callId: source.callId,
|
|
99
|
+
successful: block.isError === false && !data.error,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function commandFromArguments(value) {
|
|
103
|
+
let arguments_ = value;
|
|
104
|
+
if (typeof arguments_ === "string") {
|
|
105
|
+
const trimmed = arguments_.trim();
|
|
106
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
|
|
107
|
+
return Object.freeze({ command: arguments_, parsed: true });
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
arguments_ = JSON.parse(trimmed);
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
return Object.freeze({ command: "", parsed: false });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (!isUnknownRecord(arguments_))
|
|
117
|
+
return Object.freeze({ command: "", parsed: false });
|
|
118
|
+
for (const field of ["command", "cmd", "script"]) {
|
|
119
|
+
if (typeof arguments_[field] === "string")
|
|
120
|
+
return Object.freeze({ command: arguments_[field], parsed: true });
|
|
121
|
+
}
|
|
122
|
+
return Object.freeze({ command: "", parsed: true });
|
|
81
123
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (typeof args === "string") return args;
|
|
86
|
-
if (!args || typeof args !== "object" || Array.isArray(args)) return "";
|
|
87
|
-
for (const field of ["command", "cmd", "script"]) {
|
|
88
|
-
if (typeof args[field] === "string") return args[field];
|
|
89
|
-
}
|
|
90
|
-
return "";
|
|
124
|
+
function normalizedToolName(name) {
|
|
125
|
+
const segments = name.split(/[.:/]/u).filter(Boolean);
|
|
126
|
+
return segments.at(-1) ?? name;
|
|
91
127
|
}
|
|
92
|
-
|
|
93
128
|
function resultReferencesCall(event, call) {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
129
|
+
return Number.isSafeInteger(call?.seq)
|
|
130
|
+
&& Array.isArray(event?.sourceEventSeqs)
|
|
131
|
+
&& event.sourceEventSeqs.length === 1
|
|
132
|
+
&& event.sourceEventSeqs[0] === call.seq;
|
|
98
133
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
134
|
+
function nativeToolCalls(events) {
|
|
135
|
+
const calls = new Map();
|
|
136
|
+
const duplicates = new Set();
|
|
137
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
138
|
+
const event = events[index];
|
|
139
|
+
if (event?.type !== "tool/call")
|
|
140
|
+
continue;
|
|
141
|
+
const callId = event.data?.callId;
|
|
142
|
+
const name = event.data?.name;
|
|
143
|
+
if (typeof callId !== "string" || !callId || typeof name !== "string" || !name || !Number.isSafeInteger(event.seq))
|
|
144
|
+
continue;
|
|
145
|
+
if (calls.has(callId)) {
|
|
146
|
+
calls.delete(callId);
|
|
147
|
+
duplicates.add(callId);
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (duplicates.has(callId))
|
|
151
|
+
continue;
|
|
152
|
+
calls.set(callId, Object.freeze({ index, seq: event.seq, name, arguments: event.data?.arguments }));
|
|
113
153
|
}
|
|
114
|
-
|
|
115
|
-
calls.set(callId, Object.freeze({
|
|
116
|
-
index,
|
|
117
|
-
seq: event.seq,
|
|
118
|
-
name,
|
|
119
|
-
arguments: event.data?.arguments,
|
|
120
|
-
}));
|
|
121
|
-
}
|
|
122
|
-
return calls;
|
|
154
|
+
return calls;
|
|
123
155
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (matchesAny(text, ACCEPTANCE_PATTERNS)) kinds.push("acceptance");
|
|
136
|
-
return { index, source: "assistant", kinds, label: "controller claim", text };
|
|
137
|
-
}
|
|
138
|
-
if (event?.type === "odai/route-card-frozen" && event.data?.card) {
|
|
139
|
-
return {
|
|
140
|
-
index,
|
|
141
|
-
source: "route-card",
|
|
142
|
-
kinds: ["acceptance"],
|
|
143
|
-
label: `frozen route card ${event.data.card.id ?? "(unknown)"}`,
|
|
144
|
-
text: JSON.stringify(event.data.card),
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
if (event?.type === "tool/result") {
|
|
148
|
-
const result = nativeToolResult(event.data);
|
|
149
|
-
const call = result ? calls.get(result.callId) : undefined;
|
|
150
|
-
if (!call || call.index >= index || !resultReferencesCall(event, call)) return undefined;
|
|
151
|
-
const callId = result.callId;
|
|
152
|
-
const successful = result.successful;
|
|
153
|
-
const command = commandFromCall(call);
|
|
154
|
-
const simpleCommand = !SHELL_CONTROL_PATTERN.test(command);
|
|
155
|
-
const diffCommand = simpleCommand && matchesAny(command, DIFF_COMMAND_PATTERNS);
|
|
156
|
-
const testCommand = simpleCommand && matchesAny(command, TEST_COMMAND_PATTERNS);
|
|
157
|
-
const explicitWrite = WRITE_TOOL_NAMES.has(call.name) || matchesAny(command, WRITE_COMMAND_PATTERNS);
|
|
158
|
-
const unknownShellMutation = SHELL_TOOL_NAMES.has(call.name)
|
|
159
|
-
&& !diffCommand
|
|
160
|
-
&& !testCommand
|
|
161
|
-
&& (SHELL_CONTROL_PATTERN.test(command) || !matchesAny(command, READ_ONLY_SHELL_COMMAND_PATTERNS));
|
|
162
|
-
const writeCommand = explicitWrite || unknownShellMutation;
|
|
163
|
-
if (!successful && !testCommand && !writeCommand) return undefined;
|
|
164
|
-
const output = textBlocks(event.data).join("\n").trim();
|
|
165
|
-
const kinds = successful ? ["tool"] : [];
|
|
166
|
-
if (successful && diffCommand && matchesAny(output, DIFF_OUTPUT_PATTERNS)) kinds.push("diff");
|
|
167
|
-
if (writeCommand) kinds.push("write");
|
|
168
|
-
if (testCommand) {
|
|
169
|
-
const testPassed = successful
|
|
170
|
-
&& matchesAny(output, TEST_SUCCESS_PATTERNS)
|
|
171
|
-
&& !matchesAny(output, TEST_FAILURE_PATTERNS);
|
|
172
|
-
kinds.push(testPassed ? "test" : "test-failed");
|
|
156
|
+
function eventEvidence(event, index, calls, directUserMessageIds, diagnostics) {
|
|
157
|
+
if (event?.type === "user/message") {
|
|
158
|
+
if (!isDirectUserEvent(event))
|
|
159
|
+
return undefined;
|
|
160
|
+
const text = textBlocks(event.data).join("\n").trim();
|
|
161
|
+
if (!text)
|
|
162
|
+
return undefined;
|
|
163
|
+
if (classifyResponsibilityInterruptionText(text) === "continue") {
|
|
164
|
+
return { index, source: "user", kinds: ["continuation"], label: "direct-user continuation", text };
|
|
165
|
+
}
|
|
166
|
+
return { index, source: "user", kinds: ["requirement", "acceptance"], label: "user-owned requirement and acceptance", text };
|
|
173
167
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
168
|
+
if (["assistant/message", "agent/message", "message/assistant"].includes(event?.type)) {
|
|
169
|
+
const text = textBlocks(event.data).join("\n").trim();
|
|
170
|
+
if (!text)
|
|
171
|
+
return undefined;
|
|
172
|
+
const kinds = ["assistant-claim"];
|
|
173
|
+
if (matchesAny(text, REQUIREMENT_PATTERNS))
|
|
174
|
+
kinds.push("requirement");
|
|
175
|
+
return { index, source: "assistant", kinds, label: "controller claim", text };
|
|
176
|
+
}
|
|
177
|
+
if (event?.type === "odai/route-card-frozen" && isUnknownRecord(event.data?.card)) {
|
|
178
|
+
const authorization = isUnknownRecord(event.data.card.authorization) ? event.data.card.authorization : undefined;
|
|
179
|
+
const userMessageId = typeof authorization?.userMessageId === "string" ? authorization.userMessageId : undefined;
|
|
180
|
+
if (authorization?.status !== "authorized"
|
|
181
|
+
|| !userMessageId
|
|
182
|
+
|| !directUserMessageIds.has(userMessageId)
|
|
183
|
+
|| !Array.isArray(event.data.card.accept)
|
|
184
|
+
|| event.data.card.accept.length === 0)
|
|
185
|
+
return undefined;
|
|
186
|
+
return {
|
|
187
|
+
index, source: "route-card", kinds: ["acceptance"],
|
|
188
|
+
label: `authorized frozen route card ${typeof event.data.card.id === "string" ? event.data.card.id : "(unknown)"}`,
|
|
189
|
+
text: JSON.stringify(event.data.card),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (event?.type === "tool/result") {
|
|
193
|
+
const result = nativeToolResult(event.data);
|
|
194
|
+
if (!result) {
|
|
195
|
+
diagnostics.malformedToolResultCount += 1;
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
const call = calls.get(result.callId);
|
|
199
|
+
if (!call || call.index >= index || !resultReferencesCall(event, call)) {
|
|
200
|
+
diagnostics.unlinkedToolResultCount += 1;
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
diagnostics.linkedToolResultCount += 1;
|
|
204
|
+
const decoded = commandFromArguments(call.arguments);
|
|
205
|
+
if (!decoded.parsed)
|
|
206
|
+
diagnostics.unparsedToolArgumentsCount += 1;
|
|
207
|
+
const command = decoded.command;
|
|
208
|
+
const toolName = normalizedToolName(call.name);
|
|
209
|
+
const simpleCommand = command !== "" && !SHELL_CONTROL_PATTERN.test(command);
|
|
210
|
+
const diffCommand = simpleCommand && matchesAny(command, DIFF_COMMAND_PATTERNS);
|
|
211
|
+
const testCommand = simpleCommand && matchesAny(command, TEST_COMMAND_PATTERNS);
|
|
212
|
+
const explicitWrite = WRITE_TOOL_NAMES.has(toolName) || matchesAny(command, WRITE_COMMAND_PATTERNS);
|
|
213
|
+
const unknownShellMutation = SHELL_TOOL_NAMES.has(toolName)
|
|
214
|
+
&& !diffCommand && !testCommand
|
|
215
|
+
&& (SHELL_CONTROL_PATTERN.test(command) || !matchesAny(command, READ_ONLY_SHELL_COMMAND_PATTERNS));
|
|
216
|
+
if (SHELL_TOOL_NAMES.has(toolName) && !diffCommand && !testCommand && !explicitWrite
|
|
217
|
+
&& !matchesAny(command, READ_ONLY_SHELL_COMMAND_PATTERNS))
|
|
218
|
+
diagnostics.unclassifiedShellResultCount += 1;
|
|
219
|
+
const writeCommand = explicitWrite || unknownShellMutation;
|
|
220
|
+
if (!result.successful && !testCommand && !writeCommand)
|
|
221
|
+
return undefined;
|
|
222
|
+
const output = textBlocks(event.data).join("\n").trim();
|
|
223
|
+
const kinds = result.successful ? ["tool"] : [];
|
|
224
|
+
if (result.successful && diffCommand) {
|
|
225
|
+
if (matchesAny(output, DIFF_OUTPUT_PATTERNS))
|
|
226
|
+
kinds.push("diff");
|
|
227
|
+
else
|
|
228
|
+
diagnostics.diffWithoutPatchCount += 1;
|
|
229
|
+
}
|
|
230
|
+
if (writeCommand)
|
|
231
|
+
kinds.push("write");
|
|
232
|
+
if (testCommand) {
|
|
233
|
+
const testPassed = result.successful && matchesAny(output, TEST_SUCCESS_PATTERNS) && !matchesAny(output, TEST_FAILURE_PATTERNS);
|
|
234
|
+
if (result.successful && !matchesAny(output, TEST_SUCCESS_PATTERNS) && !matchesAny(output, TEST_FAILURE_PATTERNS)) {
|
|
235
|
+
diagnostics.testWithoutVerdictCount += 1;
|
|
236
|
+
}
|
|
237
|
+
kinds.push(testPassed ? "test" : "test-failed");
|
|
238
|
+
}
|
|
239
|
+
const identity = `tool-call:${result.callId}`;
|
|
240
|
+
const text = [command ? `command: ${command}` : "", output || "(no textual result)"].filter(Boolean).join("\n\n");
|
|
241
|
+
return { index, source: "tool", kinds, label: `tool ${call.name} (${identity})`, identity, text };
|
|
242
|
+
}
|
|
243
|
+
if (event?.type === "odai/tool-observed" && event.data?.isError === false) {
|
|
244
|
+
const identity = typeof event.data.callId === "string" ? `tool-call:${event.data.callId}` : undefined;
|
|
245
|
+
const tool = typeof event.data.tool === "string" ? event.data.tool : "unknown";
|
|
246
|
+
const normalized = normalizedToolName(tool);
|
|
247
|
+
return {
|
|
248
|
+
index, source: "tool", kinds: ["tool", ...(WRITE_TOOL_NAMES.has(normalized) ? ["write"] : [])],
|
|
249
|
+
label: `observed tool ${tool}${identity ? ` (${identity})` : ""}`,
|
|
250
|
+
...(identity ? { identity } : {}), text: JSON.stringify(event.data),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return undefined;
|
|
198
254
|
}
|
|
199
|
-
|
|
200
255
|
function truncateText(text, limit) {
|
|
201
|
-
|
|
202
|
-
|
|
256
|
+
if (text.length <= limit)
|
|
257
|
+
return { text, truncated: false };
|
|
258
|
+
return { text: `${text.slice(0, Math.max(0, limit - 24))}\n...[packet truncated]`, truncated: true };
|
|
203
259
|
}
|
|
204
|
-
|
|
205
260
|
function digestPacket(value) {
|
|
206
|
-
|
|
261
|
+
return createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
207
262
|
}
|
|
208
|
-
|
|
209
263
|
function coverageFor(currentTask, entries) {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
failedTestCount: failedTestEntries.length,
|
|
233
|
-
writeCount: matching("write").length,
|
|
234
|
-
toolEvidenceCount: matching("tool").length,
|
|
235
|
-
latestWriteIndex,
|
|
236
|
-
latestDiffIndex,
|
|
237
|
-
latestTestIndex,
|
|
238
|
-
latestFailedTestIndex,
|
|
239
|
-
currentEvidence,
|
|
240
|
-
});
|
|
264
|
+
const matching = (kind) => entries.filter((entry) => entry.kinds.includes(kind));
|
|
265
|
+
const latestIndex = (kind) => matching(kind).reduce((latest, entry) => Math.max(latest, entry.index), -1);
|
|
266
|
+
const acceptanceCount = matching("acceptance").length;
|
|
267
|
+
const diffEntries = matching("diff");
|
|
268
|
+
const testEntries = matching("test");
|
|
269
|
+
const failedTestEntries = matching("test-failed");
|
|
270
|
+
const latestWriteIndex = latestIndex("write");
|
|
271
|
+
const latestDiffIndex = latestIndex("diff");
|
|
272
|
+
const latestTestIndex = latestIndex("test");
|
|
273
|
+
const latestFailedTestIndex = latestIndex("test-failed");
|
|
274
|
+
const currentEvidence = acceptanceCount > 0
|
|
275
|
+
&& latestDiffIndex >= 0 && latestTestIndex >= 0
|
|
276
|
+
&& latestDiffIndex > latestWriteIndex && latestTestIndex > latestDiffIndex
|
|
277
|
+
&& latestTestIndex > latestFailedTestIndex
|
|
278
|
+
&& diffEntries.some((diff) => testEntries.some((testResult) => diff.identity !== testResult.identity));
|
|
279
|
+
return Object.freeze({
|
|
280
|
+
requirements: Boolean(currentTask) || matching("requirement").length > 0,
|
|
281
|
+
acceptanceCount, diffCount: diffEntries.length, testCount: testEntries.length,
|
|
282
|
+
failedTestCount: failedTestEntries.length, writeCount: matching("write").length,
|
|
283
|
+
toolEvidenceCount: matching("tool").length, latestWriteIndex, latestDiffIndex,
|
|
284
|
+
latestTestIndex, latestFailedTestIndex, currentEvidence,
|
|
285
|
+
});
|
|
241
286
|
}
|
|
242
|
-
|
|
243
287
|
export function buildRoleContextPacket(agent, role, taskText, options = {}) {
|
|
244
|
-
|
|
245
|
-
? options.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
?
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
288
|
+
const maxChars = Number.isSafeInteger(options.maxChars) && (options.maxChars ?? 0) > 0 ? options.maxChars : DEFAULT_MAX_CHARS;
|
|
289
|
+
const maxEvents = Number.isSafeInteger(options.maxEvents) && (options.maxEvents ?? 0) > 0 ? options.maxEvents : DEFAULT_MAX_EVENTS;
|
|
290
|
+
const taskBudget = Math.max(32, Math.floor(maxChars / 3));
|
|
291
|
+
const task = truncateText(String(taskText ?? "").trim(), taskBudget);
|
|
292
|
+
const events = Array.isArray(agent?.session?.events) ? agent.session.events : [];
|
|
293
|
+
const calls = nativeToolCalls(events);
|
|
294
|
+
const directUserMessageIds = new Set(events.flatMap((event) => {
|
|
295
|
+
if (event?.type !== "user/message")
|
|
296
|
+
return [];
|
|
297
|
+
const message = directUserMessage(event);
|
|
298
|
+
return message && typeof message.id === "string" ? [message.id] : [];
|
|
299
|
+
}));
|
|
300
|
+
const mutableDiagnostics = {
|
|
301
|
+
rawEventCount: events.length,
|
|
302
|
+
evidenceEventCount: 0,
|
|
303
|
+
selectedEvidenceCount: 0,
|
|
304
|
+
omittedEvidenceCount: 0,
|
|
305
|
+
nativeToolCallCount: calls.size,
|
|
306
|
+
linkedToolResultCount: 0,
|
|
307
|
+
malformedToolResultCount: 0,
|
|
308
|
+
unlinkedToolResultCount: 0,
|
|
309
|
+
unparsedToolArgumentsCount: 0,
|
|
310
|
+
unclassifiedShellResultCount: 0,
|
|
311
|
+
diffWithoutPatchCount: 0,
|
|
312
|
+
testWithoutVerdictCount: 0,
|
|
313
|
+
};
|
|
314
|
+
const allEvidence = [];
|
|
315
|
+
const preTruncatedIndices = new Set();
|
|
316
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
317
|
+
const event = events[index];
|
|
318
|
+
if (!event)
|
|
319
|
+
continue;
|
|
320
|
+
const entry = eventEvidence(event, index, calls, directUserMessageIds, mutableDiagnostics);
|
|
321
|
+
if (!entry)
|
|
322
|
+
continue;
|
|
323
|
+
const bounded = truncateText(entry.text, DEFAULT_MAX_ENTRY_CHARS);
|
|
324
|
+
if (bounded.truncated)
|
|
325
|
+
preTruncatedIndices.add(entry.index);
|
|
326
|
+
allEvidence.push(Object.freeze({ ...entry, kinds: Object.freeze([...new Set(entry.kinds)]), text: bounded.text }));
|
|
327
|
+
}
|
|
328
|
+
mutableDiagnostics.evidenceEventCount = allEvidence.length;
|
|
329
|
+
const recent = allEvidence.slice(-maxEvents);
|
|
330
|
+
const anchors = ["requirement", "acceptance"].flatMap((kind) => {
|
|
331
|
+
const entry = allEvidence.findLast((candidate) => candidate.kinds.includes(kind));
|
|
332
|
+
return entry ? [entry] : [];
|
|
333
|
+
});
|
|
334
|
+
const candidateByIndex = new Map();
|
|
335
|
+
for (const entry of [...recent, ...anchors])
|
|
336
|
+
candidateByIndex.set(entry.index, entry);
|
|
337
|
+
const candidates = [...candidateByIndex.values()].sort((left, right) => left.index - right.index);
|
|
338
|
+
mutableDiagnostics.selectedEvidenceCount = candidates.length;
|
|
339
|
+
mutableDiagnostics.omittedEvidenceCount = Math.max(0, allEvidence.length - candidates.length);
|
|
340
|
+
const priorityKinds = ["requirement", "acceptance", "write", "diff", "test-failed", "test"];
|
|
341
|
+
const prioritized = [];
|
|
342
|
+
const prioritizedIndices = new Set();
|
|
343
|
+
for (const kind of priorityKinds) {
|
|
344
|
+
const entry = candidates.findLast((candidate) => candidate.kinds.includes(kind));
|
|
345
|
+
if (entry && !prioritizedIndices.has(entry.index)) {
|
|
346
|
+
prioritized.push(entry);
|
|
347
|
+
prioritizedIndices.add(entry.index);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
for (let index = candidates.length - 1; index >= 0; index -= 1) {
|
|
351
|
+
const entry = candidates[index];
|
|
352
|
+
if (entry && !prioritizedIndices.has(entry.index)) {
|
|
353
|
+
prioritized.push(entry);
|
|
354
|
+
prioritizedIndices.add(entry.index);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const rendered = [];
|
|
358
|
+
let evidenceChars = 0;
|
|
359
|
+
let textTruncated = task.truncated || prioritized.some((entry) => preTruncatedIndices.has(entry.index));
|
|
360
|
+
const availableChars = Math.max(0, maxChars - task.text.length);
|
|
361
|
+
const maxEntryChars = Math.max(96, Math.min(DEFAULT_MAX_ENTRY_CHARS, Math.floor(availableChars / 6)));
|
|
362
|
+
for (const entry of prioritized) {
|
|
363
|
+
const remaining = maxChars - task.text.length - evidenceChars;
|
|
364
|
+
if (remaining < 96) {
|
|
365
|
+
textTruncated = true;
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
const bounded = truncateText(entry.text, Math.min(remaining, maxEntryChars));
|
|
369
|
+
rendered.push(Object.freeze({ ...entry, text: bounded.text }));
|
|
370
|
+
evidenceChars += bounded.text.length;
|
|
371
|
+
textTruncated ||= bounded.truncated;
|
|
372
|
+
}
|
|
373
|
+
rendered.sort((left, right) => left.index - right.index);
|
|
374
|
+
const entries = Object.freeze(rendered);
|
|
375
|
+
const coverage = coverageFor(task.text, entries);
|
|
376
|
+
const diagnostics = Object.freeze({
|
|
377
|
+
...mutableDiagnostics,
|
|
378
|
+
hostEvidenceAvailable: mutableDiagnostics.linkedToolResultCount > 0,
|
|
379
|
+
});
|
|
380
|
+
const truncated = textTruncated || mutableDiagnostics.omittedEvidenceCount > 0 || rendered.length < candidates.length;
|
|
381
|
+
const evidenceCoverage = coverageFor(task.text, candidates);
|
|
382
|
+
const evidenceMarkers = priorityKinds.map((kind) => {
|
|
383
|
+
const entry = candidates.findLast((candidate) => candidate.kinds.includes(kind));
|
|
384
|
+
return entry ? { kind, index: entry.index, identity: entry.identity } : { kind, index: -1 };
|
|
385
|
+
});
|
|
386
|
+
const evidenceDigest = digestPacket({
|
|
387
|
+
coverage: {
|
|
388
|
+
requirements: evidenceCoverage.requirements,
|
|
389
|
+
acceptanceCount: evidenceCoverage.acceptanceCount,
|
|
390
|
+
diffCount: evidenceCoverage.diffCount,
|
|
391
|
+
testCount: evidenceCoverage.testCount,
|
|
392
|
+
failedTestCount: evidenceCoverage.failedTestCount,
|
|
393
|
+
writeCount: evidenceCoverage.writeCount,
|
|
394
|
+
latestWriteIndex: evidenceCoverage.latestWriteIndex,
|
|
395
|
+
latestDiffIndex: evidenceCoverage.latestDiffIndex,
|
|
396
|
+
latestTestIndex: evidenceCoverage.latestTestIndex,
|
|
397
|
+
latestFailedTestIndex: evidenceCoverage.latestFailedTestIndex,
|
|
398
|
+
currentEvidence: evidenceCoverage.currentEvidence,
|
|
399
|
+
},
|
|
400
|
+
markers: evidenceMarkers,
|
|
401
|
+
diagnostics: {
|
|
402
|
+
malformedToolResultCount: diagnostics.malformedToolResultCount,
|
|
403
|
+
unlinkedToolResultCount: diagnostics.unlinkedToolResultCount,
|
|
404
|
+
unparsedToolArgumentsCount: diagnostics.unparsedToolArgumentsCount,
|
|
405
|
+
unclassifiedShellResultCount: diagnostics.unclassifiedShellResultCount,
|
|
406
|
+
diffWithoutPatchCount: diagnostics.diffWithoutPatchCount,
|
|
407
|
+
testWithoutVerdictCount: diagnostics.testWithoutVerdictCount,
|
|
408
|
+
hostEvidenceAvailable: diagnostics.hostEvidenceAvailable,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
const packetBody = Object.freeze({
|
|
412
|
+
schemaVersion: 1, role, currentTask: task.text, entries, coverage, diagnostics, truncated, evidenceDigest,
|
|
413
|
+
});
|
|
414
|
+
const digest = digestPacket(packetBody);
|
|
415
|
+
const reviewerSufficient = coverage.requirements && coverage.acceptanceCount > 0
|
|
416
|
+
&& coverage.diffCount > 0 && coverage.testCount > 0 && coverage.toolEvidenceCount > 0 && coverage.currentEvidence;
|
|
417
|
+
return Object.freeze({
|
|
418
|
+
...packetBody, digest, evidenceCount: entries.length, toolEvidenceCount: coverage.toolEvidenceCount,
|
|
419
|
+
sufficient: role === "reviewer" ? reviewerSufficient : Boolean(task.text),
|
|
420
|
+
});
|
|
296
421
|
}
|
|
297
|
-
|
|
298
422
|
export function renderRoleContextPacket(packet) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
"
|
|
317
|
-
evidence,
|
|
318
|
-
"",
|
|
319
|
-
"Treat assistant text and route-card contents as claims. Tool entries are evidence only for the exact command/result they contain.",
|
|
320
|
-
].join("\n");
|
|
423
|
+
const evidence = packet.entries.length
|
|
424
|
+
? packet.entries.map((entry, index) => [
|
|
425
|
+
`### E${index + 1}: ${entry.label}`,
|
|
426
|
+
`kinds: ${entry.kinds.join(", ")}`,
|
|
427
|
+
entry.text,
|
|
428
|
+
].join("\n")).join("\n\n")
|
|
429
|
+
: "(no prior evidence entries)";
|
|
430
|
+
return [
|
|
431
|
+
"# Odai bounded role context packet",
|
|
432
|
+
`role: ${packet.role}`,
|
|
433
|
+
`digest: sha256:${packet.digest}`,
|
|
434
|
+
`evidenceDigest: sha256:${packet.evidenceDigest}`,
|
|
435
|
+
`truncated: ${packet.truncated}`,
|
|
436
|
+
`coverage: ${JSON.stringify(packet.coverage)}`,
|
|
437
|
+
`diagnostics: ${JSON.stringify(packet.diagnostics)}`,
|
|
438
|
+
"", "## Current task", packet.currentTask || "(empty)", "", "## Evidence", evidence, "",
|
|
439
|
+
"Treat assistant text and route-card contents as claims. Tool entries are evidence only for the exact command/result they contain.",
|
|
440
|
+
].join("\n");
|
|
321
441
|
}
|
|
442
|
+
//# sourceMappingURL=routing-context.mjs.map
|