@deepstrike/wasm 0.2.50 → 0.2.52
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 +2 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/runtime/canonical-kernel-step.d.ts +155 -0
- package/dist/runtime/canonical-kernel-step.js +1523 -0
- package/dist/runtime/execution-plane.d.ts +0 -3
- package/dist/runtime/execution-plane.js +0 -25
- package/dist/runtime/facade.js +3 -0
- package/dist/runtime/index.d.ts +7 -7
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/kernel-event-log.d.ts +0 -1
- package/dist/runtime/kernel-event-log.js +7 -13
- package/dist/runtime/kernel-journal.d.ts +332 -0
- package/dist/runtime/kernel-journal.js +681 -0
- package/dist/runtime/kernel-step.d.ts +34 -89
- package/dist/runtime/kernel-step.js +67 -167
- package/dist/runtime/os-snapshot.d.ts +2 -2
- package/dist/runtime/os-snapshot.js +2 -6
- package/dist/runtime/payload-store.d.ts +30 -0
- package/dist/runtime/payload-store.js +66 -0
- package/dist/runtime/runner.d.ts +27 -75
- package/dist/runtime/runner.js +408 -632
- package/dist/runtime/session-log.d.ts +24 -27
- package/dist/runtime/session-log.js +11 -52
- package/dist/runtime/session-repair.d.ts +2 -36
- package/dist/runtime/session-repair.js +2 -47
- package/dist/runtime/sub-agent-orchestrator.d.ts +2 -2
- package/dist/runtime/sub-agent-orchestrator.js +36 -40
- package/dist/runtime/types/agent.d.ts +13 -16
- package/dist/runtime/types/agent.js +16 -41
- package/package.json +4 -3
- package/dist/runtime/kernel-rebuild.d.ts +0 -8
- package/dist/runtime/kernel-rebuild.js +0 -65
- package/dist/runtime/kernel-transaction-log.d.ts +0 -61
- package/dist/runtime/kernel-transaction-log.js +0 -140
- package/dist/runtime/large-result-spool.d.ts +0 -57
- package/dist/runtime/large-result-spool.js +0 -169
|
@@ -18,68 +18,13 @@ interface SkillMetadata {
|
|
|
18
18
|
* `stable-core ∪ allowedTools`. Absent ⇒ no narrowing (back-compat). */
|
|
19
19
|
allowedTools?: string[];
|
|
20
20
|
}
|
|
21
|
-
export declare const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
restore(snapshotJson: string): void;
|
|
29
|
-
diagnostics(): string;
|
|
30
|
-
isTerminal(): boolean;
|
|
31
|
-
turn(): number;
|
|
32
|
-
recoveryContentBytes(): number;
|
|
33
|
-
render(): RenderedContext;
|
|
34
|
-
drainNewMessages(): Message[];
|
|
35
|
-
preservedRefs(): string[];
|
|
36
|
-
}
|
|
37
|
-
export type KernelPreparationStatus = "prepared" | "replayed" | "rejected";
|
|
38
|
-
export interface KernelPreparedStep {
|
|
39
|
-
status: KernelPreparationStatus;
|
|
40
|
-
base_generation: number;
|
|
41
|
-
prepare_token?: string;
|
|
42
|
-
input: Record<string, unknown>;
|
|
43
|
-
step: KernelStepJson;
|
|
44
|
-
}
|
|
45
|
-
export interface KernelDiagnostics {
|
|
46
|
-
lifecycle: string;
|
|
47
|
-
next_step_seq: number;
|
|
48
|
-
accepted_input_count: number;
|
|
49
|
-
accepted_input_bytes: number;
|
|
50
|
-
snapshot_input_limit: number;
|
|
51
|
-
snapshot_journal_bytes_limit: number;
|
|
52
|
-
max_input_bytes: number;
|
|
53
|
-
snapshot_overflowed: boolean;
|
|
54
|
-
recorded_event_count: number;
|
|
55
|
-
completed_effect_count: number;
|
|
56
|
-
pending_effect_count: number;
|
|
57
|
-
}
|
|
58
|
-
export declare function readKernelDiagnostics(runtime: KernelRuntimeHandle): KernelDiagnostics;
|
|
59
|
-
export interface KernelSnapshot {
|
|
60
|
-
snapshot_version: 2;
|
|
61
|
-
abi_version: 2;
|
|
62
|
-
initial_policy: {
|
|
63
|
-
max_tokens: number;
|
|
64
|
-
max_turns: number;
|
|
65
|
-
max_total_tokens: string;
|
|
66
|
-
max_wall_ms?: string;
|
|
67
|
-
};
|
|
68
|
-
lifecycle: string;
|
|
69
|
-
operation_id?: string;
|
|
70
|
-
next_step_seq: number;
|
|
71
|
-
snapshot_input_limit: number;
|
|
72
|
-
max_input_bytes: number;
|
|
73
|
-
snapshot_journal_bytes_limit: number;
|
|
74
|
-
accepted_input_bytes: number;
|
|
75
|
-
accepted_inputs: Array<{
|
|
76
|
-
event_id: string;
|
|
77
|
-
[key: string]: unknown;
|
|
78
|
-
}>;
|
|
79
|
-
last_step?: Record<string, unknown>;
|
|
80
|
-
}
|
|
81
|
-
export declare function snapshotKernelRuntime(runtime: KernelRuntimeHandle): KernelSnapshot;
|
|
82
|
-
export declare function restoreKernelRuntime(runtime: KernelRuntimeHandle, snapshot: KernelSnapshot): void;
|
|
21
|
+
export declare const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts:v1]]";
|
|
22
|
+
/**
|
|
23
|
+
* Browser/worker-safe transport for typed content. `btoa` and `atob` operate on
|
|
24
|
+
* binary strings, so explicitly bridge UTF-8 bytes rather than assuming Latin-1.
|
|
25
|
+
*/
|
|
26
|
+
export declare function encodeCanonicalContentParts(parts: unknown[]): string;
|
|
27
|
+
export declare function decodeCanonicalContentParts(content: string): Array<Record<string, unknown>> | undefined;
|
|
83
28
|
export interface PaceDecision {
|
|
84
29
|
action: "continue" | "sleep" | "stop";
|
|
85
30
|
delayMs?: number;
|
|
@@ -91,6 +36,7 @@ export interface KernelLoopResult {
|
|
|
91
36
|
termination: string;
|
|
92
37
|
turnsUsed: number;
|
|
93
38
|
totalTokensUsed: number;
|
|
39
|
+
finalMessage?: Message;
|
|
94
40
|
/** ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs). */
|
|
95
41
|
paceDecision?: PaceDecision;
|
|
96
42
|
}
|
|
@@ -121,6 +67,10 @@ export type KernelRunnerAction = {
|
|
|
121
67
|
kind: "preempt_sub_agents";
|
|
122
68
|
effectId: string;
|
|
123
69
|
agentIds: string[];
|
|
70
|
+
attempts?: Array<{
|
|
71
|
+
task_id: string;
|
|
72
|
+
attempt_id: string;
|
|
73
|
+
}>;
|
|
124
74
|
reason: string;
|
|
125
75
|
} | {
|
|
126
76
|
kind: "persist_memory";
|
|
@@ -131,28 +81,36 @@ export type KernelRunnerAction = {
|
|
|
131
81
|
effectId: string;
|
|
132
82
|
query: Record<string, unknown>;
|
|
133
83
|
requestedK: number;
|
|
134
|
-
} | {
|
|
135
|
-
kind: "spool_large_result";
|
|
136
|
-
effectId: string;
|
|
137
|
-
callId: string;
|
|
138
|
-
tool: string;
|
|
139
|
-
output: string;
|
|
140
|
-
originalSize: number;
|
|
141
|
-
previewSize: number;
|
|
142
84
|
} | {
|
|
143
85
|
kind: "archive_page_out";
|
|
144
86
|
effectId: string;
|
|
145
|
-
turn
|
|
146
|
-
action
|
|
87
|
+
turn?: number;
|
|
88
|
+
action?: string;
|
|
147
89
|
summary?: string;
|
|
148
90
|
archived: Message[];
|
|
149
|
-
tier
|
|
91
|
+
tier?: string;
|
|
92
|
+
handleId?: string;
|
|
93
|
+
payload?: {
|
|
94
|
+
content: string;
|
|
95
|
+
digest: string;
|
|
96
|
+
original_size: string;
|
|
97
|
+
preview?: string;
|
|
98
|
+
};
|
|
99
|
+
} | {
|
|
100
|
+
kind: "load_payload";
|
|
101
|
+
effectId: string;
|
|
102
|
+
handleId: string;
|
|
103
|
+
payloadRef: string;
|
|
150
104
|
} | {
|
|
151
105
|
kind: "evaluate_milestone";
|
|
152
106
|
effectId: string;
|
|
153
107
|
phaseId: string;
|
|
154
108
|
criteria: string[];
|
|
155
109
|
requiredEvidence?: string[];
|
|
110
|
+
} | {
|
|
111
|
+
kind: "unsupported_effect";
|
|
112
|
+
effectId: string;
|
|
113
|
+
effectKind: string;
|
|
156
114
|
} | {
|
|
157
115
|
kind: "done";
|
|
158
116
|
effectId: string;
|
|
@@ -181,7 +139,7 @@ export interface KernelObservation {
|
|
|
181
139
|
evidence?: string[];
|
|
182
140
|
reason?: RollbackReason | string;
|
|
183
141
|
agent_id?: string;
|
|
184
|
-
|
|
142
|
+
parent_task_id?: string;
|
|
185
143
|
role?: string;
|
|
186
144
|
isolation?: string;
|
|
187
145
|
context_inheritance?: string;
|
|
@@ -210,7 +168,6 @@ export interface KernelObservation {
|
|
|
210
168
|
tier?: string;
|
|
211
169
|
message_count?: number;
|
|
212
170
|
archive_ref?: string;
|
|
213
|
-
spool_ref?: string;
|
|
214
171
|
record_id?: string;
|
|
215
172
|
scope?: {
|
|
216
173
|
tenant_id: string;
|
|
@@ -249,16 +206,6 @@ export interface KernelObservation {
|
|
|
249
206
|
window_turns?: number;
|
|
250
207
|
threshold?: number;
|
|
251
208
|
}
|
|
252
|
-
interface KernelStepJson {
|
|
253
|
-
version: number;
|
|
254
|
-
actions: Array<Record<string, unknown>>;
|
|
255
|
-
observations: KernelObservation[];
|
|
256
|
-
faults?: Array<{
|
|
257
|
-
code?: string;
|
|
258
|
-
message?: string;
|
|
259
|
-
effect_id?: string;
|
|
260
|
-
}>;
|
|
261
|
-
}
|
|
262
209
|
export declare function toolSchemaToKernel(schema: ToolSchema): Record<string, unknown>;
|
|
263
210
|
export declare function skillMetadataToKernel(skill: SkillMetadata): Record<string, unknown>;
|
|
264
211
|
export declare function messageToKernelMessage(message: Message): Record<string, unknown>;
|
|
@@ -267,8 +214,6 @@ export declare function taskUpdateToKernel(update: TaskUpdate): Record<string, u
|
|
|
267
214
|
export declare function capabilityTool(schema: ToolSchema): Record<string, unknown>;
|
|
268
215
|
export declare function capabilitySkill(skill: SkillMetadata): Record<string, unknown>;
|
|
269
216
|
export declare function capabilityMarker(kind: string, id: string, description: string): Record<string, unknown>;
|
|
270
|
-
export declare function
|
|
271
|
-
export declare function
|
|
272
|
-
/** Like kernelAction but tolerates zero-action steps (e.g. queued signals). */
|
|
273
|
-
export declare function kernelMaybeAction(runtime: KernelRuntimeHandle, pending: KernelObservation[], event: Record<string, unknown>): KernelRunnerAction | null;
|
|
217
|
+
export declare function kernelMessageToSdk(raw: Record<string, unknown>): Message;
|
|
218
|
+
export declare function renderedContextToSdk(raw: Record<string, unknown>): RenderedContext;
|
|
274
219
|
export {};
|
|
@@ -1,24 +1,30 @@
|
|
|
1
|
-
export const
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
export const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts:v1]]";
|
|
2
|
+
/**
|
|
3
|
+
* Browser/worker-safe transport for typed content. `btoa` and `atob` operate on
|
|
4
|
+
* binary strings, so explicitly bridge UTF-8 bytes rather than assuming Latin-1.
|
|
5
|
+
*/
|
|
6
|
+
export function encodeCanonicalContentParts(parts) {
|
|
7
|
+
const bytes = new TextEncoder().encode(JSON.stringify(parts));
|
|
8
|
+
let binary = "";
|
|
9
|
+
for (const byte of bytes)
|
|
10
|
+
binary += String.fromCharCode(byte);
|
|
11
|
+
return `${CANONICAL_CONTENT_PARTS_PREFIX}${btoa(binary)}`;
|
|
12
|
+
}
|
|
13
|
+
export function decodeCanonicalContentParts(content) {
|
|
14
|
+
if (!content.startsWith(CANONICAL_CONTENT_PARTS_PREFIX))
|
|
15
|
+
return undefined;
|
|
16
|
+
try {
|
|
17
|
+
const binary = atob(content.slice(CANONICAL_CONTENT_PARTS_PREFIX.length));
|
|
18
|
+
const bytes = Uint8Array.from(binary, character => character.charCodeAt(0));
|
|
19
|
+
const decoded = JSON.parse(new TextDecoder().decode(bytes));
|
|
20
|
+
return Array.isArray(decoded)
|
|
21
|
+
? decoded.filter((part) => Boolean(part) && typeof part === "object")
|
|
22
|
+
: undefined;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
14
26
|
}
|
|
15
|
-
const nextEventSequence = snapshot.accepted_inputs.reduce((next, input) => {
|
|
16
|
-
const match = input.event_id.match(/-event-(\d+)$/);
|
|
17
|
-
return match ? Math.max(next, Number(match[1]) + 1) : next;
|
|
18
|
-
}, 1);
|
|
19
|
-
kernelWireStates.set(runtime, { operationId, nextEventSequence });
|
|
20
27
|
}
|
|
21
|
-
const kernelWireStates = new WeakMap();
|
|
22
28
|
function tryParseJson(s) {
|
|
23
29
|
try {
|
|
24
30
|
return JSON.parse(s);
|
|
@@ -126,10 +132,7 @@ export function capabilitySkill(skill) {
|
|
|
126
132
|
export function capabilityMarker(kind, id, description) {
|
|
127
133
|
return { id, kind, description };
|
|
128
134
|
}
|
|
129
|
-
function
|
|
130
|
-
return JSON.parse(raw);
|
|
131
|
-
}
|
|
132
|
-
function kernelMessageToSdk(raw) {
|
|
135
|
+
export function kernelMessageToSdk(raw) {
|
|
133
136
|
const content = raw.content;
|
|
134
137
|
const message = {
|
|
135
138
|
role: raw.role,
|
|
@@ -152,9 +155,49 @@ function kernelMessageToSdk(raw) {
|
|
|
152
155
|
if (typeof raw.token_count === "number") {
|
|
153
156
|
message.tokenCount = raw.token_count;
|
|
154
157
|
}
|
|
158
|
+
if (typeof content === "string") {
|
|
159
|
+
const parts = decodeCanonicalContentParts(content);
|
|
160
|
+
if (parts) {
|
|
161
|
+
const contentParts = [];
|
|
162
|
+
for (const part of parts) {
|
|
163
|
+
switch (part.type) {
|
|
164
|
+
case "text":
|
|
165
|
+
contentParts.push({ type: "text", text: String(part.text ?? "") });
|
|
166
|
+
break;
|
|
167
|
+
case "tool_result":
|
|
168
|
+
contentParts.push({
|
|
169
|
+
type: "tool_result",
|
|
170
|
+
callId: String(part.call_id ?? ""),
|
|
171
|
+
output: String(part.output ?? ""),
|
|
172
|
+
isError: Boolean(part.is_error),
|
|
173
|
+
});
|
|
174
|
+
break;
|
|
175
|
+
case "image":
|
|
176
|
+
contentParts.push({
|
|
177
|
+
type: "image",
|
|
178
|
+
...(part.url ? { url: String(part.url) } : {}),
|
|
179
|
+
...(part.data ? { data: String(part.data) } : {}),
|
|
180
|
+
...(part.media_type ? { mediaType: String(part.media_type) } : {}),
|
|
181
|
+
...(part.detail === "auto" || part.detail === "low" || part.detail === "high"
|
|
182
|
+
? { detail: part.detail }
|
|
183
|
+
: {}),
|
|
184
|
+
});
|
|
185
|
+
break;
|
|
186
|
+
case "audio":
|
|
187
|
+
contentParts.push({
|
|
188
|
+
type: "audio",
|
|
189
|
+
data: String(part.data ?? ""),
|
|
190
|
+
...(part.media_type ? { mediaType: String(part.media_type) } : {}),
|
|
191
|
+
});
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
message.contentParts = contentParts;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
155
198
|
return message;
|
|
156
199
|
}
|
|
157
|
-
function renderedContextToSdk(raw) {
|
|
200
|
+
export function renderedContextToSdk(raw) {
|
|
158
201
|
const rawStateTurn = (raw.state_turn ?? raw.stateTurn);
|
|
159
202
|
const frozenLen = (raw.frozen_prefix_len ?? raw.frozenPrefixLen);
|
|
160
203
|
const ctx = {
|
|
@@ -169,146 +212,3 @@ function renderedContextToSdk(raw) {
|
|
|
169
212
|
ctx.frozenPrefixLen = frozenLen;
|
|
170
213
|
return ctx;
|
|
171
214
|
}
|
|
172
|
-
function mapKernelAction(raw) {
|
|
173
|
-
const effectId = String(raw.effect_id ?? "");
|
|
174
|
-
if (!effectId)
|
|
175
|
-
throw new Error(`kernel action ${String(raw.kind)} is missing effect_id`);
|
|
176
|
-
switch (raw.kind) {
|
|
177
|
-
case "call_provider":
|
|
178
|
-
return {
|
|
179
|
-
kind: "call_provider",
|
|
180
|
-
effectId,
|
|
181
|
-
context: renderedContextToSdk(raw.context ?? {}),
|
|
182
|
-
tools: (raw.tools ?? []).map(t => ({
|
|
183
|
-
name: String(t.name ?? ""),
|
|
184
|
-
description: String(t.description ?? ""),
|
|
185
|
-
parameters: JSON.stringify(t.parameters ?? {}),
|
|
186
|
-
})),
|
|
187
|
-
};
|
|
188
|
-
case "execute_tool":
|
|
189
|
-
return {
|
|
190
|
-
kind: "execute_tool",
|
|
191
|
-
effectId,
|
|
192
|
-
calls: (raw.calls ?? []).map(c => ({
|
|
193
|
-
id: String(c.id ?? ""),
|
|
194
|
-
name: String(c.name ?? ""),
|
|
195
|
-
arguments: JSON.stringify(c.arguments ?? {}),
|
|
196
|
-
})),
|
|
197
|
-
};
|
|
198
|
-
case "request_approval":
|
|
199
|
-
return {
|
|
200
|
-
kind: "request_approval", effectId,
|
|
201
|
-
requests: (raw.requests ?? []).map(request => ({
|
|
202
|
-
callId: String(request.call_id ?? ""), tool: String(request.tool ?? ""),
|
|
203
|
-
arguments: JSON.stringify(request.arguments ?? {}), reason: String(request.reason ?? ""),
|
|
204
|
-
})),
|
|
205
|
-
};
|
|
206
|
-
case "spawn_workflow":
|
|
207
|
-
return {
|
|
208
|
-
kind: "spawn_workflow", effectId,
|
|
209
|
-
nodes: raw.nodes ?? [],
|
|
210
|
-
...(raw.budget && typeof raw.budget === "object" ? { budget: raw.budget } : {}),
|
|
211
|
-
};
|
|
212
|
-
case "preempt_sub_agents":
|
|
213
|
-
return { kind: "preempt_sub_agents", effectId, agentIds: raw.agent_ids ?? [], reason: String(raw.reason ?? "") };
|
|
214
|
-
case "persist_memory":
|
|
215
|
-
return { kind: "persist_memory", effectId, memory: raw.memory ?? {} };
|
|
216
|
-
case "query_memory":
|
|
217
|
-
return { kind: "query_memory", effectId, query: raw.query ?? {}, requestedK: Number(raw.requested_k ?? 0) };
|
|
218
|
-
case "spool_large_result":
|
|
219
|
-
return {
|
|
220
|
-
kind: "spool_large_result", effectId, callId: String(raw.call_id ?? ""), tool: String(raw.tool ?? ""),
|
|
221
|
-
output: String(raw.output ?? ""), originalSize: Number(raw.original_size ?? 0), previewSize: Number(raw.preview_size ?? 0),
|
|
222
|
-
};
|
|
223
|
-
case "archive_page_out":
|
|
224
|
-
return {
|
|
225
|
-
kind: "archive_page_out", effectId, turn: Number(raw.turn ?? 0), action: String(raw.action ?? "auto_compact"),
|
|
226
|
-
...(typeof raw.summary === "string" ? { summary: raw.summary } : {}),
|
|
227
|
-
archived: (raw.archived ?? []).map(kernelMessageToSdk),
|
|
228
|
-
tier: String(raw.tier ?? "durable"),
|
|
229
|
-
};
|
|
230
|
-
case "evaluate_milestone":
|
|
231
|
-
return {
|
|
232
|
-
kind: "evaluate_milestone",
|
|
233
|
-
effectId,
|
|
234
|
-
phaseId: String(raw.phase_id ?? ""),
|
|
235
|
-
criteria: raw.criteria ?? [],
|
|
236
|
-
requiredEvidence: raw.required_evidence ?? [],
|
|
237
|
-
};
|
|
238
|
-
case "done": {
|
|
239
|
-
const result = raw.result ?? {};
|
|
240
|
-
const pace = result.pace_decision;
|
|
241
|
-
return {
|
|
242
|
-
kind: "done",
|
|
243
|
-
effectId,
|
|
244
|
-
result: {
|
|
245
|
-
termination: String(result.termination ?? "error"),
|
|
246
|
-
turnsUsed: Number(result.turns_used ?? 0),
|
|
247
|
-
totalTokensUsed: Number(result.total_tokens_used ?? 0),
|
|
248
|
-
// ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs).
|
|
249
|
-
...(pace
|
|
250
|
-
? {
|
|
251
|
-
paceDecision: {
|
|
252
|
-
action: (pace.action ?? "stop"),
|
|
253
|
-
delayMs: pace.delay_ms,
|
|
254
|
-
reason: pace.reason ?? "",
|
|
255
|
-
coercedFrom: pace.coerced_from,
|
|
256
|
-
},
|
|
257
|
-
}
|
|
258
|
-
: {}),
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
default:
|
|
263
|
-
throw new Error(`unknown KernelAction kind: ${String(raw.kind)}`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
function stepInput(runtime, event) {
|
|
267
|
-
let state = kernelWireStates.get(runtime);
|
|
268
|
-
if (!state) {
|
|
269
|
-
// Globally unique, never a process-local counter: durable session logs key the kernel
|
|
270
|
-
// genesis/transaction chains by (sessionId, operationId) and outlive this isolate, so a
|
|
271
|
-
// counter that restarts at 1 collides with a prior chain on the same session.
|
|
272
|
-
state = { operationId: `wasm-operation-${crypto.randomUUID()}`, nextEventSequence: 1 };
|
|
273
|
-
kernelWireStates.set(runtime, state);
|
|
274
|
-
}
|
|
275
|
-
const correlatedEvent = event.kind === "cancel_operation"
|
|
276
|
-
? { ...event, operation_id: state.operationId }
|
|
277
|
-
: event;
|
|
278
|
-
return JSON.stringify({
|
|
279
|
-
version: KERNEL_ABI_VERSION,
|
|
280
|
-
operation_id: state.operationId,
|
|
281
|
-
event_id: `${state.operationId}-event-${state.nextEventSequence++}`,
|
|
282
|
-
observed_at_ms: Date.now(),
|
|
283
|
-
event: correlatedEvent,
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
export function kernelApply(runtime, pending, event) {
|
|
287
|
-
const step = parseStep(runtime.step(stepInput(runtime, event)));
|
|
288
|
-
const fault = step.faults?.[0];
|
|
289
|
-
if (fault)
|
|
290
|
-
throw new Error(`${fault.code ?? "kernel_fault"}: ${fault.message ?? "kernel transition failed"}`);
|
|
291
|
-
pending.push(...step.observations);
|
|
292
|
-
return step.observations;
|
|
293
|
-
}
|
|
294
|
-
export function kernelAction(runtime, pending, event) {
|
|
295
|
-
const step = parseStep(runtime.step(stepInput(runtime, event)));
|
|
296
|
-
const fault = step.faults?.[0];
|
|
297
|
-
if (fault)
|
|
298
|
-
throw new Error(`${fault.code ?? "kernel_fault"}: ${fault.message ?? "kernel transition failed"}`);
|
|
299
|
-
pending.push(...step.observations);
|
|
300
|
-
const raw = step.actions[0];
|
|
301
|
-
if (!raw)
|
|
302
|
-
throw new Error("kernel transition must return one action");
|
|
303
|
-
return mapKernelAction(raw);
|
|
304
|
-
}
|
|
305
|
-
/** Like kernelAction but tolerates zero-action steps (e.g. queued signals). */
|
|
306
|
-
export function kernelMaybeAction(runtime, pending, event) {
|
|
307
|
-
const step = parseStep(runtime.step(stepInput(runtime, event)));
|
|
308
|
-
const fault = step.faults?.[0];
|
|
309
|
-
if (fault)
|
|
310
|
-
throw new Error(`${fault.code ?? "kernel_fault"}: ${fault.message ?? "kernel transition failed"}`);
|
|
311
|
-
pending.push(...step.observations);
|
|
312
|
-
const raw = step.actions[0];
|
|
313
|
-
return raw ? mapKernelAction(raw) : null;
|
|
314
|
-
}
|
|
@@ -9,7 +9,8 @@ export interface OsSnapshot {
|
|
|
9
9
|
processByAgent: Array<{
|
|
10
10
|
turn: number;
|
|
11
11
|
agent_id: string;
|
|
12
|
-
|
|
12
|
+
parent_task_id?: string;
|
|
13
|
+
parent_session_id?: string;
|
|
13
14
|
state: string;
|
|
14
15
|
}>;
|
|
15
16
|
budgetExceeded: Array<{
|
|
@@ -43,7 +44,6 @@ export interface OsSnapshot {
|
|
|
43
44
|
}>;
|
|
44
45
|
pageOutCount: number;
|
|
45
46
|
pageInCount: number;
|
|
46
|
-
spoolCount: number;
|
|
47
47
|
toolGatedCount: number;
|
|
48
48
|
}
|
|
49
49
|
export declare function rebuildOsSnapshotFromSessionEvents(events: SessionEvent[]): OsSnapshot;
|
|
@@ -2,7 +2,6 @@ const KERNEL_KINDS = new Set([
|
|
|
2
2
|
"compressed",
|
|
3
3
|
"page_out",
|
|
4
4
|
"page_in",
|
|
5
|
-
"large_result_spooled",
|
|
6
5
|
"capability_changed",
|
|
7
6
|
"context_renewed",
|
|
8
7
|
"suspended",
|
|
@@ -27,7 +26,6 @@ export function rebuildOsSnapshotFromSessionEvents(events) {
|
|
|
27
26
|
signals: [],
|
|
28
27
|
pageOutCount: 0,
|
|
29
28
|
pageInCount: 0,
|
|
30
|
-
spoolCount: 0,
|
|
31
29
|
toolGatedCount: 0,
|
|
32
30
|
};
|
|
33
31
|
const index = new Map();
|
|
@@ -53,7 +51,8 @@ export function rebuildOsSnapshotFromSessionEvents(events) {
|
|
|
53
51
|
const record = {
|
|
54
52
|
turn: event.turn,
|
|
55
53
|
agent_id: event.agent_id,
|
|
56
|
-
|
|
54
|
+
...(event.parent_task_id ? { parent_task_id: event.parent_task_id } : {}),
|
|
55
|
+
...(event.parent_session_id ? { parent_session_id: event.parent_session_id } : {}),
|
|
57
56
|
state: event.state ?? "running",
|
|
58
57
|
};
|
|
59
58
|
const idx = index.get(event.agent_id);
|
|
@@ -91,9 +90,6 @@ export function rebuildOsSnapshotFromSessionEvents(events) {
|
|
|
91
90
|
case "page_in":
|
|
92
91
|
snap.pageInCount += 1;
|
|
93
92
|
break;
|
|
94
|
-
case "large_result_spooled":
|
|
95
|
-
snap.spoolCount += 1;
|
|
96
|
-
break;
|
|
97
93
|
default:
|
|
98
94
|
break;
|
|
99
95
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface PayloadStorageDriver {
|
|
2
|
+
write(key: string, content: string): Promise<void> | void;
|
|
3
|
+
read(key: string): Promise<string | undefined> | string | undefined;
|
|
4
|
+
delete(key: string): Promise<void> | void;
|
|
5
|
+
list(): Promise<string[]> | string[];
|
|
6
|
+
mtime?(key: string): Promise<number> | number;
|
|
7
|
+
}
|
|
8
|
+
export declare class MemoryPayloadDriver implements PayloadStorageDriver {
|
|
9
|
+
private readonly values;
|
|
10
|
+
write(key: string, content: string): Promise<void>;
|
|
11
|
+
read(key: string): Promise<string | undefined>;
|
|
12
|
+
delete(key: string): Promise<void>;
|
|
13
|
+
list(): Promise<string[]>;
|
|
14
|
+
mtime(key: string): Promise<number>;
|
|
15
|
+
}
|
|
16
|
+
export interface PayloadStoreConfig {
|
|
17
|
+
driver?: PayloadStorageDriver;
|
|
18
|
+
maxAgeMs?: number;
|
|
19
|
+
}
|
|
20
|
+
/** Driver-backed storage for canonical opaque payload locators. */
|
|
21
|
+
export declare class PayloadStore {
|
|
22
|
+
private readonly driver;
|
|
23
|
+
private readonly maxAgeMs?;
|
|
24
|
+
private readonly activeWrites;
|
|
25
|
+
constructor(config?: PayloadStoreConfig);
|
|
26
|
+
private key;
|
|
27
|
+
persistPayload(sessionId: string, payloadRef: string, content: string): Promise<void>;
|
|
28
|
+
loadPayload(sessionId: string, payloadRef: string): Promise<string | undefined>;
|
|
29
|
+
cleanup(maxAgeMs?: number): Promise<number>;
|
|
30
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class MemoryPayloadDriver {
|
|
2
|
+
values = new Map();
|
|
3
|
+
async write(key, content) {
|
|
4
|
+
this.values.set(key, { content, mtime: Date.now() });
|
|
5
|
+
}
|
|
6
|
+
async read(key) {
|
|
7
|
+
return this.values.get(key)?.content;
|
|
8
|
+
}
|
|
9
|
+
async delete(key) {
|
|
10
|
+
this.values.delete(key);
|
|
11
|
+
}
|
|
12
|
+
async list() {
|
|
13
|
+
return [...this.values.keys()];
|
|
14
|
+
}
|
|
15
|
+
async mtime(key) {
|
|
16
|
+
return this.values.get(key)?.mtime ?? 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function sha256(value) {
|
|
20
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
|
|
21
|
+
return [...new Uint8Array(digest)]
|
|
22
|
+
.map(byte => byte.toString(16).padStart(2, "0"))
|
|
23
|
+
.join("");
|
|
24
|
+
}
|
|
25
|
+
/** Driver-backed storage for canonical opaque payload locators. */
|
|
26
|
+
export class PayloadStore {
|
|
27
|
+
driver;
|
|
28
|
+
maxAgeMs;
|
|
29
|
+
activeWrites = new Map();
|
|
30
|
+
constructor(config = {}) {
|
|
31
|
+
this.driver = config.driver ?? new MemoryPayloadDriver();
|
|
32
|
+
this.maxAgeMs = config.maxAgeMs;
|
|
33
|
+
}
|
|
34
|
+
async key(sessionId, payloadRef) {
|
|
35
|
+
return `payload/${await sha256(`${sessionId}\u0000${payloadRef}`)}`;
|
|
36
|
+
}
|
|
37
|
+
async persistPayload(sessionId, payloadRef, content) {
|
|
38
|
+
const key = await this.key(sessionId, payloadRef);
|
|
39
|
+
let write = this.activeWrites.get(key);
|
|
40
|
+
if (!write) {
|
|
41
|
+
write = Promise.resolve(this.driver.write(key, content)).finally(() => {
|
|
42
|
+
this.activeWrites.delete(key);
|
|
43
|
+
});
|
|
44
|
+
this.activeWrites.set(key, write);
|
|
45
|
+
}
|
|
46
|
+
await write;
|
|
47
|
+
}
|
|
48
|
+
async loadPayload(sessionId, payloadRef) {
|
|
49
|
+
return await this.driver.read(await this.key(sessionId, payloadRef));
|
|
50
|
+
}
|
|
51
|
+
async cleanup(maxAgeMs = this.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000) {
|
|
52
|
+
if (!this.driver.mtime)
|
|
53
|
+
return 0;
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
let removed = 0;
|
|
56
|
+
for (const key of await this.driver.list()) {
|
|
57
|
+
if (!key.startsWith("payload/"))
|
|
58
|
+
continue;
|
|
59
|
+
if (now - await this.driver.mtime(key) > maxAgeMs) {
|
|
60
|
+
await this.driver.delete(key);
|
|
61
|
+
removed += 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return removed;
|
|
65
|
+
}
|
|
66
|
+
}
|