@deepstrike/sdk 0.1.16 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/collaboration/harness.d.ts +4 -1
- package/dist/collaboration/harness.js +20 -6
- package/dist/collaboration/modes/creator-verifier.d.ts +8 -2
- package/dist/collaboration/modes/creator-verifier.js +9 -3
- package/dist/collaboration/pool.d.ts +24 -3
- package/dist/collaboration/pool.js +65 -5
- package/dist/harness/harness.d.ts +5 -1
- package/dist/harness/harness.js +23 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +5 -0
- package/dist/kernel.d.ts +12 -43
- package/dist/kernel.js +1 -1
- package/dist/providers/anthropic.js +3 -1
- package/dist/runtime/archive.d.ts +15 -0
- package/dist/runtime/archive.js +35 -0
- package/dist/runtime/execution-plane.js +14 -4
- package/dist/runtime/filtered-plane.d.ts +14 -0
- package/dist/runtime/filtered-plane.js +45 -0
- package/dist/runtime/kernel-step.d.ts +88 -0
- package/dist/runtime/kernel-step.js +262 -0
- package/dist/runtime/process-sandbox-plane.d.ts +4 -4
- package/dist/runtime/process-sandbox-plane.js +5 -5
- package/dist/runtime/provider-replay.js +7 -2
- package/dist/runtime/replay-sanitize.d.ts +5 -0
- package/dist/runtime/replay-sanitize.js +25 -0
- package/dist/runtime/runner.d.ts +60 -4
- package/dist/runtime/runner.js +589 -86
- package/dist/runtime/session-log.d.ts +93 -1
- package/dist/runtime/session-repair.d.ts +37 -0
- package/dist/runtime/session-repair.js +77 -0
- package/dist/runtime/sub-agent-orchestrator.d.ts +19 -0
- package/dist/runtime/sub-agent-orchestrator.js +114 -0
- package/dist/skills/watcher.d.ts +19 -0
- package/dist/skills/watcher.js +38 -0
- package/dist/tools/index.d.ts +4 -1
- package/dist/tools/index.js +82 -11
- package/dist/types/agent.d.ts +68 -0
- package/dist/types/agent.js +78 -0
- package/dist/types.d.ts +27 -0
- package/package.json +2 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Message, RenderedContext, TaskUpdate, ToolCall, ToolResult, ToolSchema } from "../types.js";
|
|
2
|
+
import type { SkillMetadata } from "../skills/loader.js";
|
|
3
|
+
import type { RollbackReason } from "./session-log.js";
|
|
4
|
+
export declare const KERNEL_ABI_VERSION = 1;
|
|
5
|
+
export interface KernelRuntimeHandle {
|
|
6
|
+
step(inputJson: string): string;
|
|
7
|
+
isTerminal(): boolean;
|
|
8
|
+
turn(): number;
|
|
9
|
+
recoveryContentBytes(): number;
|
|
10
|
+
render(): RenderedContext;
|
|
11
|
+
drainNewMessages(): Message[];
|
|
12
|
+
preservedRefs(): string[];
|
|
13
|
+
}
|
|
14
|
+
export interface KernelLoopResult {
|
|
15
|
+
termination: string;
|
|
16
|
+
turnsUsed: number;
|
|
17
|
+
totalTokensUsed: number;
|
|
18
|
+
}
|
|
19
|
+
export type MilestoneVerifierKind = {
|
|
20
|
+
kind: "machine_check";
|
|
21
|
+
} | {
|
|
22
|
+
kind: "harness_eval";
|
|
23
|
+
} | {
|
|
24
|
+
kind: "llm_judge";
|
|
25
|
+
} | {
|
|
26
|
+
kind: "human_approval";
|
|
27
|
+
} | {
|
|
28
|
+
kind: "external_command";
|
|
29
|
+
cmd: string;
|
|
30
|
+
};
|
|
31
|
+
export type KernelRunnerAction = {
|
|
32
|
+
kind: "call_provider";
|
|
33
|
+
context: RenderedContext;
|
|
34
|
+
tools: ToolSchema[];
|
|
35
|
+
} | {
|
|
36
|
+
kind: "execute_tool";
|
|
37
|
+
calls: ToolCall[];
|
|
38
|
+
} | {
|
|
39
|
+
kind: "evaluate_milestone";
|
|
40
|
+
phaseId: string;
|
|
41
|
+
criteria: string[];
|
|
42
|
+
verifier?: MilestoneVerifierKind;
|
|
43
|
+
requiredEvidence: string[];
|
|
44
|
+
} | {
|
|
45
|
+
kind: "done";
|
|
46
|
+
result: KernelLoopResult;
|
|
47
|
+
};
|
|
48
|
+
export interface KernelObservation {
|
|
49
|
+
kind: string;
|
|
50
|
+
action?: string;
|
|
51
|
+
rho_after?: number;
|
|
52
|
+
sprint?: number;
|
|
53
|
+
summary?: string;
|
|
54
|
+
archived?: Message[];
|
|
55
|
+
turn?: number;
|
|
56
|
+
checkpoint_history_len?: number;
|
|
57
|
+
history_len?: number;
|
|
58
|
+
added?: string[];
|
|
59
|
+
removed?: string[];
|
|
60
|
+
change_kind?: string;
|
|
61
|
+
capability_id?: string;
|
|
62
|
+
version?: string;
|
|
63
|
+
mounted_by?: string;
|
|
64
|
+
mount_reason?: string;
|
|
65
|
+
phase_id?: string;
|
|
66
|
+
capabilities_unlocked?: string[];
|
|
67
|
+
evidence?: string[];
|
|
68
|
+
reason?: RollbackReason;
|
|
69
|
+
agent_id?: string;
|
|
70
|
+
parent_session_id?: string;
|
|
71
|
+
role?: string;
|
|
72
|
+
isolation?: string;
|
|
73
|
+
context_inheritance?: string;
|
|
74
|
+
permitted_capability_ids?: string[];
|
|
75
|
+
}
|
|
76
|
+
export declare function toolSchemaToKernel(schema: ToolSchema): Record<string, unknown>;
|
|
77
|
+
export declare function skillMetadataToKernel(skill: SkillMetadata): Record<string, unknown>;
|
|
78
|
+
export declare function messageToKernelMessage(message: Message): Record<string, unknown>;
|
|
79
|
+
export declare function toolResultToKernel(result: ToolResult): Record<string, unknown>;
|
|
80
|
+
export declare function taskUpdateToKernel(update: TaskUpdate): Record<string, unknown>;
|
|
81
|
+
export declare function capabilityTool(schema: ToolSchema): Record<string, unknown>;
|
|
82
|
+
export declare function capabilitySkill(skill: SkillMetadata): Record<string, unknown>;
|
|
83
|
+
export declare function capabilityMarker(kind: string, id: string, description: string): Record<string, unknown>;
|
|
84
|
+
export declare function capabilityCommandMount(capability: Record<string, unknown>, mountedBy?: string, mountReason?: string): Record<string, unknown>;
|
|
85
|
+
export declare function capabilityCommandUnmount(capabilityKind: string, id: string): Record<string, unknown>;
|
|
86
|
+
export declare function kernelApply(runtime: KernelRuntimeHandle, pending: KernelObservation[], event: Record<string, unknown>): KernelObservation[];
|
|
87
|
+
export declare function kernelAction(runtime: KernelRuntimeHandle, pending: KernelObservation[], event: Record<string, unknown>): KernelRunnerAction;
|
|
88
|
+
export declare function forceCompact(runtime: KernelRuntimeHandle, pending: KernelObservation[]): boolean;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
export const KERNEL_ABI_VERSION = 1;
|
|
2
|
+
function tryParseJson(s) {
|
|
3
|
+
try {
|
|
4
|
+
return JSON.parse(s);
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function toolSchemaToKernel(schema) {
|
|
11
|
+
return {
|
|
12
|
+
name: schema.name,
|
|
13
|
+
description: schema.description,
|
|
14
|
+
parameters: tryParseJson(schema.parameters) ?? {},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function skillMetadataToKernel(skill) {
|
|
18
|
+
const out = {
|
|
19
|
+
name: skill.name,
|
|
20
|
+
description: skill.description,
|
|
21
|
+
estimated_tokens: skill.estimatedTokens ?? 0,
|
|
22
|
+
};
|
|
23
|
+
if (skill.whenToUse)
|
|
24
|
+
out.when_to_use = skill.whenToUse;
|
|
25
|
+
if (skill.effort !== undefined)
|
|
26
|
+
out.effort = skill.effort;
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
export function messageToKernelMessage(message) {
|
|
30
|
+
const out = {
|
|
31
|
+
role: message.role,
|
|
32
|
+
tool_calls: (message.toolCalls ?? []).map(tc => ({
|
|
33
|
+
id: tc.id,
|
|
34
|
+
name: tc.name,
|
|
35
|
+
arguments: tryParseJson(tc.arguments) ?? {},
|
|
36
|
+
})),
|
|
37
|
+
};
|
|
38
|
+
if (message.tokenCount !== undefined) {
|
|
39
|
+
out.token_count = message.tokenCount;
|
|
40
|
+
}
|
|
41
|
+
if (message.contentParts && message.contentParts.length > 0) {
|
|
42
|
+
out.content = message.contentParts.map(part => {
|
|
43
|
+
if (part.type === "text")
|
|
44
|
+
return { type: "text", text: part.text };
|
|
45
|
+
if (part.type === "tool_result") {
|
|
46
|
+
return {
|
|
47
|
+
type: "tool_result",
|
|
48
|
+
call_id: part.callId,
|
|
49
|
+
output: part.output,
|
|
50
|
+
is_error: part.isError,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (part.type === "image") {
|
|
54
|
+
return {
|
|
55
|
+
type: "image",
|
|
56
|
+
url: part.url,
|
|
57
|
+
data: part.data,
|
|
58
|
+
media_type: part.mediaType,
|
|
59
|
+
detail: part.detail,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
if (part.type === "audio") {
|
|
63
|
+
return { type: "audio", data: part.data, media_type: part.mediaType };
|
|
64
|
+
}
|
|
65
|
+
return { type: "text", text: message.content };
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
out.content = message.content;
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
export function toolResultToKernel(result) {
|
|
74
|
+
const out = {
|
|
75
|
+
call_id: result.callId,
|
|
76
|
+
output: result.output,
|
|
77
|
+
is_error: result.isError,
|
|
78
|
+
is_fatal: result.isFatal ?? false,
|
|
79
|
+
token_count: result.tokenCount ?? null,
|
|
80
|
+
};
|
|
81
|
+
if (result.errorKind !== undefined) {
|
|
82
|
+
out.error_kind = result.errorKind;
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
export function taskUpdateToKernel(update) {
|
|
87
|
+
return {
|
|
88
|
+
plan: update.plan,
|
|
89
|
+
current_step: update.currentStep,
|
|
90
|
+
progress: update.progress,
|
|
91
|
+
scratchpad: update.scratchpad,
|
|
92
|
+
blocked_on: update.blockedOn,
|
|
93
|
+
preserved_refs: update.preservedRefs,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function capabilityTool(schema) {
|
|
97
|
+
return {
|
|
98
|
+
id: schema.name,
|
|
99
|
+
kind: "tool",
|
|
100
|
+
description: schema.description,
|
|
101
|
+
tool_schema: toolSchemaToKernel(schema),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function capabilitySkill(skill) {
|
|
105
|
+
return {
|
|
106
|
+
id: skill.name,
|
|
107
|
+
kind: "skill",
|
|
108
|
+
description: skill.description,
|
|
109
|
+
skill: skillMetadataToKernel(skill),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export function capabilityMarker(kind, id, description) {
|
|
113
|
+
return { id, kind, description };
|
|
114
|
+
}
|
|
115
|
+
export function capabilityCommandMount(capability, mountedBy = "sdk:runtime", mountReason = "dynamic_register") {
|
|
116
|
+
return {
|
|
117
|
+
kind: "capability_command",
|
|
118
|
+
command: {
|
|
119
|
+
action: "mount",
|
|
120
|
+
capability,
|
|
121
|
+
mounted_by: mountedBy,
|
|
122
|
+
mount_reason: mountReason,
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
export function capabilityCommandUnmount(capabilityKind, id) {
|
|
127
|
+
return {
|
|
128
|
+
kind: "capability_command",
|
|
129
|
+
command: { action: "unmount", kind: capabilityKind, id },
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function parseStep(raw) {
|
|
133
|
+
return JSON.parse(raw);
|
|
134
|
+
}
|
|
135
|
+
function kernelMessageToSdk(raw) {
|
|
136
|
+
const content = raw.content;
|
|
137
|
+
const message = {
|
|
138
|
+
role: raw.role,
|
|
139
|
+
content: typeof content === "string"
|
|
140
|
+
? content
|
|
141
|
+
: Array.isArray(content)
|
|
142
|
+
? content
|
|
143
|
+
.filter((part) => {
|
|
144
|
+
return typeof part === "object" && part !== null && part.type === "text";
|
|
145
|
+
})
|
|
146
|
+
.map(part => String(part.text ?? ""))
|
|
147
|
+
.join("")
|
|
148
|
+
: "",
|
|
149
|
+
toolCalls: (raw.tool_calls ?? []).map(tc => ({
|
|
150
|
+
id: String(tc.id ?? ""),
|
|
151
|
+
name: String(tc.name ?? ""),
|
|
152
|
+
arguments: JSON.stringify(tc.arguments ?? {}),
|
|
153
|
+
})),
|
|
154
|
+
};
|
|
155
|
+
if (typeof raw.token_count === "number") {
|
|
156
|
+
message.tokenCount = raw.token_count;
|
|
157
|
+
}
|
|
158
|
+
if (Array.isArray(content)) {
|
|
159
|
+
message.contentParts = content
|
|
160
|
+
.filter((part) => typeof part === "object" && part !== null)
|
|
161
|
+
.map(part => {
|
|
162
|
+
if (part.type === "text") {
|
|
163
|
+
return { type: "text", text: String(part.text ?? "") };
|
|
164
|
+
}
|
|
165
|
+
if (part.type === "tool_result") {
|
|
166
|
+
return {
|
|
167
|
+
type: "tool_result",
|
|
168
|
+
callId: String(part.call_id ?? ""),
|
|
169
|
+
output: String(part.output ?? ""),
|
|
170
|
+
isError: Boolean(part.is_error),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (part.type === "image") {
|
|
174
|
+
return {
|
|
175
|
+
type: "image",
|
|
176
|
+
url: part.url,
|
|
177
|
+
data: part.data,
|
|
178
|
+
mediaType: part.media_type,
|
|
179
|
+
detail: part.detail,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
if (part.type === "audio") {
|
|
183
|
+
return {
|
|
184
|
+
type: "audio",
|
|
185
|
+
data: String(part.data ?? ""),
|
|
186
|
+
mediaType: String(part.media_type ?? "audio/wav"),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return { type: "text", text: "" };
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return message;
|
|
193
|
+
}
|
|
194
|
+
function renderedContextToSdk(raw) {
|
|
195
|
+
return {
|
|
196
|
+
systemText: String(raw.system_text ?? raw.systemText ?? ""),
|
|
197
|
+
turns: (raw.turns ?? []).map(kernelMessageToSdk),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function mapKernelAction(raw) {
|
|
201
|
+
switch (raw.kind) {
|
|
202
|
+
case "call_provider":
|
|
203
|
+
return {
|
|
204
|
+
kind: "call_provider",
|
|
205
|
+
context: renderedContextToSdk(raw.context ?? {}),
|
|
206
|
+
tools: (raw.tools ?? []).map(t => ({
|
|
207
|
+
name: String(t.name ?? ""),
|
|
208
|
+
description: String(t.description ?? ""),
|
|
209
|
+
parameters: JSON.stringify(t.parameters ?? {}),
|
|
210
|
+
})),
|
|
211
|
+
};
|
|
212
|
+
case "execute_tool":
|
|
213
|
+
return {
|
|
214
|
+
kind: "execute_tool",
|
|
215
|
+
calls: (raw.calls ?? []).map(c => ({
|
|
216
|
+
id: String(c.id ?? ""),
|
|
217
|
+
name: String(c.name ?? ""),
|
|
218
|
+
arguments: JSON.stringify(c.arguments ?? {}),
|
|
219
|
+
})),
|
|
220
|
+
};
|
|
221
|
+
case "evaluate_milestone":
|
|
222
|
+
return {
|
|
223
|
+
kind: "evaluate_milestone",
|
|
224
|
+
phaseId: String(raw.phase_id ?? ""),
|
|
225
|
+
criteria: raw.criteria ?? [],
|
|
226
|
+
verifier: raw.verifier,
|
|
227
|
+
requiredEvidence: raw.required_evidence ?? [],
|
|
228
|
+
};
|
|
229
|
+
case "done": {
|
|
230
|
+
const result = raw.result ?? {};
|
|
231
|
+
return {
|
|
232
|
+
kind: "done",
|
|
233
|
+
result: {
|
|
234
|
+
termination: String(result.termination ?? "error"),
|
|
235
|
+
turnsUsed: Number(result.turns_used ?? 0),
|
|
236
|
+
totalTokensUsed: Number(result.total_tokens_used ?? 0),
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
default:
|
|
241
|
+
throw new Error(`unknown KernelAction kind: ${String(raw.kind)}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function stepInput(event) {
|
|
245
|
+
return JSON.stringify({ version: KERNEL_ABI_VERSION, event });
|
|
246
|
+
}
|
|
247
|
+
export function kernelApply(runtime, pending, event) {
|
|
248
|
+
const step = parseStep(runtime.step(stepInput(event)));
|
|
249
|
+
pending.push(...step.observations);
|
|
250
|
+
return step.observations;
|
|
251
|
+
}
|
|
252
|
+
export function kernelAction(runtime, pending, event) {
|
|
253
|
+
const step = parseStep(runtime.step(stepInput(event)));
|
|
254
|
+
pending.push(...step.observations);
|
|
255
|
+
const raw = step.actions[0];
|
|
256
|
+
if (!raw)
|
|
257
|
+
throw new Error("kernel transition must return one action");
|
|
258
|
+
return mapKernelAction(raw);
|
|
259
|
+
}
|
|
260
|
+
export function forceCompact(runtime, pending) {
|
|
261
|
+
return kernelApply(runtime, pending, { kind: "force_compact" }).some(o => o.kind === "compressed");
|
|
262
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LocalExecutionPlane } from "./execution-plane.js";
|
|
2
2
|
export interface SandboxOptions {
|
|
3
|
-
/** Working directory for all subprocesses.
|
|
3
|
+
/** Working directory for all subprocesses. This is not an OS-enforced filesystem boundary. */
|
|
4
4
|
sandboxDir: string;
|
|
5
5
|
/** Env var names from the host environment to forward into subprocesses. Default: none. */
|
|
6
6
|
allowedEnvKeys?: string[];
|
|
@@ -10,14 +10,14 @@ export interface SandboxOptions {
|
|
|
10
10
|
maxOutputBytes?: number;
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
|
-
* ExecutionPlane that
|
|
13
|
+
* ExecutionPlane that runs subprocesses with a sandbox directory as cwd.
|
|
14
14
|
* Extends LocalExecutionPlane with two built-in tools:
|
|
15
15
|
* - `run_bash` — executes a bash command inside sandboxDir.
|
|
16
16
|
* - `run_node` — evaluates a Node.js script inside sandboxDir.
|
|
17
17
|
*
|
|
18
18
|
* All registered JS tools continue to run in-process (identical to LocalExecutionPlane).
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* Subprocesses are launched with a stripped environment and sandboxDir as cwd;
|
|
20
|
+
* this is execution hygiene, not an OS-enforced filesystem sandbox.
|
|
21
21
|
*/
|
|
22
22
|
export declare class ProcessSandboxPlane extends LocalExecutionPlane {
|
|
23
23
|
private readonly sandboxDir;
|
|
@@ -3,14 +3,14 @@ import { mkdir } from "node:fs/promises";
|
|
|
3
3
|
import { tool } from "../tools/index.js";
|
|
4
4
|
import { LocalExecutionPlane } from "./execution-plane.js";
|
|
5
5
|
/**
|
|
6
|
-
* ExecutionPlane that
|
|
6
|
+
* ExecutionPlane that runs subprocesses with a sandbox directory as cwd.
|
|
7
7
|
* Extends LocalExecutionPlane with two built-in tools:
|
|
8
8
|
* - `run_bash` — executes a bash command inside sandboxDir.
|
|
9
9
|
* - `run_node` — evaluates a Node.js script inside sandboxDir.
|
|
10
10
|
*
|
|
11
11
|
* All registered JS tools continue to run in-process (identical to LocalExecutionPlane).
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Subprocesses are launched with a stripped environment and sandboxDir as cwd;
|
|
13
|
+
* this is execution hygiene, not an OS-enforced filesystem sandbox.
|
|
14
14
|
*/
|
|
15
15
|
export class ProcessSandboxPlane extends LocalExecutionPlane {
|
|
16
16
|
sandboxDir;
|
|
@@ -77,7 +77,7 @@ export class ProcessSandboxPlane extends LocalExecutionPlane {
|
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
79
|
makeBashTool() {
|
|
80
|
-
return tool("run_bash", "Run a bash command
|
|
80
|
+
return tool("run_bash", "Run a bash command with the sandbox directory as cwd and a stripped environment. This is not an OS-enforced filesystem sandbox.", {
|
|
81
81
|
type: "object",
|
|
82
82
|
properties: {
|
|
83
83
|
command: { type: "string", description: "The bash command to execute." },
|
|
@@ -92,7 +92,7 @@ export class ProcessSandboxPlane extends LocalExecutionPlane {
|
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
94
|
makeNodeTool() {
|
|
95
|
-
return tool("run_node", "Evaluate a Node.js script
|
|
95
|
+
return tool("run_node", "Evaluate a Node.js script with the sandbox directory as cwd and a stripped environment.", {
|
|
96
96
|
type: "object",
|
|
97
97
|
properties: {
|
|
98
98
|
code: { type: "string", description: "The JavaScript code to evaluate." },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { effectiveProviderReplay } from "./session-repair.js";
|
|
1
2
|
function sortObjectKeys(val) {
|
|
2
3
|
if (val === null || typeof val !== "object") {
|
|
3
4
|
return val;
|
|
@@ -37,9 +38,13 @@ export function seedProviderReplayFromEvents(provider, events) {
|
|
|
37
38
|
if (!provider.seedProviderReplay)
|
|
38
39
|
return;
|
|
39
40
|
for (const { event } of events) {
|
|
40
|
-
if (event.kind !== "llm_completed"
|
|
41
|
+
if (event.kind !== "llm_completed")
|
|
41
42
|
continue;
|
|
42
|
-
|
|
43
|
+
const toolCalls = event.tool_calls ?? [];
|
|
44
|
+
const replay = effectiveProviderReplay(event.content, toolCalls, event.provider_replay);
|
|
45
|
+
if (!replay)
|
|
46
|
+
continue;
|
|
47
|
+
provider.seedProviderReplay({ content: event.content, toolCalls }, replay);
|
|
43
48
|
}
|
|
44
49
|
}
|
|
45
50
|
export function peekProviderReplay(provider, content, toolCalls) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** UTF-8-safe text helpers for session replay (defense in depth). */
|
|
2
|
+
/** Soft cap — only snip very large llm_completed bodies before preload. */
|
|
3
|
+
export declare const REPLAY_CONTENT_MAX_BYTES = 32768;
|
|
4
|
+
export declare function truncateBytesAtCharBoundary(text: string, maxBytes: number): string;
|
|
5
|
+
export declare function sanitizeReplayText(text: string, maxBytes?: number): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** UTF-8-safe text helpers for session replay (defense in depth). */
|
|
2
|
+
/** Soft cap — only snip very large llm_completed bodies before preload. */
|
|
3
|
+
export const REPLAY_CONTENT_MAX_BYTES = 32_768;
|
|
4
|
+
export function truncateBytesAtCharBoundary(text, maxBytes) {
|
|
5
|
+
const data = Buffer.from(text, "utf8");
|
|
6
|
+
if (data.length <= maxBytes)
|
|
7
|
+
return text;
|
|
8
|
+
let end = maxBytes;
|
|
9
|
+
while (end > 0) {
|
|
10
|
+
const slice = data.subarray(0, end).toString("utf8");
|
|
11
|
+
if (Buffer.byteLength(slice, "utf8") <= end)
|
|
12
|
+
return slice;
|
|
13
|
+
end -= 1;
|
|
14
|
+
}
|
|
15
|
+
return "";
|
|
16
|
+
}
|
|
17
|
+
export function sanitizeReplayText(text, maxBytes = REPLAY_CONTENT_MAX_BYTES) {
|
|
18
|
+
if (!text)
|
|
19
|
+
return text;
|
|
20
|
+
const safe = Buffer.from(text, "utf8").toString("utf8");
|
|
21
|
+
if (Buffer.byteLength(safe, "utf8") <= maxBytes)
|
|
22
|
+
return safe;
|
|
23
|
+
const prefix = truncateBytesAtCharBoundary(safe, maxBytes);
|
|
24
|
+
return `${prefix}… [replay truncated]`;
|
|
25
|
+
}
|
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import type { LLMProvider, StreamEvent, ToolSuspendEvent } from "../types.js";
|
|
2
|
-
import type { DreamStore
|
|
1
|
+
import type { LLMProvider, Message, ToolSchema, StreamEvent, ToolSuspendEvent } from "../types.js";
|
|
2
|
+
import type { DreamStore } from "../memory/protocols.js";
|
|
3
3
|
import type { KnowledgeSource } from "../knowledge/source.js";
|
|
4
4
|
import type { SignalSource } from "../signals/types.js";
|
|
5
|
-
import type { SessionLog } from "./session-log.js";
|
|
5
|
+
import type { SessionLog, SessionEvent } from "./session-log.js";
|
|
6
|
+
import type { ArchiveStore } from "./archive.js";
|
|
6
7
|
import type { ExecutionPlane } from "./execution-plane.js";
|
|
8
|
+
import type { AgentRunSpec, MilestoneCheckResult, MilestoneContract, MilestonePolicy } from "../types/agent.js";
|
|
9
|
+
import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
7
10
|
export interface RuntimeOptions {
|
|
8
11
|
provider: LLMProvider;
|
|
9
12
|
sessionLog: SessionLog;
|
|
@@ -27,23 +30,76 @@ export interface RuntimeOptions {
|
|
|
27
30
|
retryAfterMs?: number;
|
|
28
31
|
};
|
|
29
32
|
};
|
|
33
|
+
tokenizer?: string;
|
|
34
|
+
enablePlanTool?: boolean;
|
|
35
|
+
compressionStore?: ArchiveStore;
|
|
30
36
|
onToolSuspend?: (event: ToolSuspendEvent) => Promise<unknown> | unknown;
|
|
37
|
+
/** Default: terminate — stop with milestone_pending when a phase needs evaluation. */
|
|
38
|
+
milestonePolicy?: MilestonePolicy;
|
|
39
|
+
/** Optional external verifier when milestonePolicy is not auto_pass. */
|
|
40
|
+
onMilestoneEvaluate?: (ctx: {
|
|
41
|
+
phaseId: string;
|
|
42
|
+
criteria: string[];
|
|
43
|
+
requiredEvidence: string[];
|
|
44
|
+
}) => Promise<MilestoneCheckResult> | MilestoneCheckResult;
|
|
45
|
+
/** Passed to kernel start_run for role/isolation metadata. */
|
|
46
|
+
runSpec?: AgentRunSpec;
|
|
47
|
+
/** Loaded via load_milestone_contract before run start. */
|
|
48
|
+
milestoneContract?: MilestoneContract;
|
|
49
|
+
/** Custom sub-agent host driver; defaults to SubAgentOrchestrator. */
|
|
50
|
+
subAgentOrchestrator?: SubAgentOrchestrator;
|
|
51
|
+
/** Optional system prompt injected into the dream synthesis call. */
|
|
52
|
+
dreamSystemPrompt?: string;
|
|
31
53
|
}
|
|
32
54
|
export declare class RuntimeRunner {
|
|
33
55
|
private readonly opts;
|
|
34
56
|
private interrupted;
|
|
57
|
+
private activeKernel;
|
|
58
|
+
private pendingObservations;
|
|
59
|
+
private currentSessionId;
|
|
60
|
+
private nextArchiveStart;
|
|
35
61
|
constructor(opts: RuntimeOptions);
|
|
62
|
+
/** Host configuration (for coordinator / sub-agent spawn). */
|
|
63
|
+
get hostOptions(): RuntimeOptions;
|
|
64
|
+
/** Mount a tool capability on the currently-running kernel runtime. No-op if not running. */
|
|
65
|
+
mountTool(schema: ToolSchema): void;
|
|
66
|
+
/** Mount a skill capability on the currently-running kernel runtime. No-op if not running. */
|
|
67
|
+
mountSkill(name: string, description: string): void;
|
|
68
|
+
/** Mount a generic marker capability (e.g. MCP server, agent) on the active run. No-op if not running. */
|
|
69
|
+
mountMarker(kind: string, id: string, description: string): void;
|
|
70
|
+
/** Unmount a capability by kind + id from the active run. No-op if not running. */
|
|
71
|
+
unmountCapability(kind: string, id: string): void;
|
|
72
|
+
/** Push a large artifact into the kernel artifacts partition (not inlined in history). */
|
|
73
|
+
pushArtifact(message: Message, tokens?: number): void;
|
|
74
|
+
/**
|
|
75
|
+
* Spawn an isolated sub-agent via the kernel, run it on the host, and feed the result back.
|
|
76
|
+
* Requires an active parent run (`run()` / `wake()` in progress or paused at milestone).
|
|
77
|
+
*/
|
|
78
|
+
spawnSubAgent(spec: AgentRunSpec): AsyncIterable<StreamEvent>;
|
|
36
79
|
interrupt(): void;
|
|
37
80
|
run(req: {
|
|
38
81
|
sessionId: string;
|
|
39
82
|
goal: string;
|
|
40
83
|
criteria?: string[];
|
|
41
84
|
extensions?: Record<string, unknown>;
|
|
85
|
+
/** Parent transcript to preload (e.g. sub-agent full context inheritance). */
|
|
86
|
+
inheritEvents?: Array<{
|
|
87
|
+
seq: number;
|
|
88
|
+
event: SessionEvent;
|
|
89
|
+
}>;
|
|
42
90
|
}): AsyncIterable<StreamEvent>;
|
|
43
91
|
wake(sessionId: string, extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
44
|
-
dream(agentId: string, nowMs?: number):
|
|
92
|
+
dream(agentId: string, nowMs?: number): AsyncIterable<StreamEvent>;
|
|
45
93
|
private execute;
|
|
46
94
|
private appendObservations;
|
|
47
95
|
}
|
|
96
|
+
export declare function replayMessages(events: Array<{
|
|
97
|
+
seq: number;
|
|
98
|
+
event: SessionEvent;
|
|
99
|
+
}>, maxBytes?: number): Message[];
|
|
100
|
+
export declare function replayMessagesAsync(events: Array<{
|
|
101
|
+
seq: number;
|
|
102
|
+
event: SessionEvent;
|
|
103
|
+
}>, maxBytes?: number, loadArchive?: (archiveRef: string) => Promise<Message[]>): Promise<Message[]>;
|
|
48
104
|
/** Collect all text_delta events from a run into a single string. */
|
|
49
105
|
export declare function collectText(stream: AsyncIterable<StreamEvent>): Promise<string>;
|