@deepstrike/sdk 0.2.50 → 0.2.51

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.
Files changed (39) hide show
  1. package/README.md +83 -60
  2. package/dist/index.d.ts +5 -7
  3. package/dist/index.js +3 -3
  4. package/dist/kernel.d.ts +61 -31
  5. package/dist/runtime/canonical-kernel-step.d.ts +143 -0
  6. package/dist/runtime/canonical-kernel-step.js +1444 -0
  7. package/dist/runtime/execution-plane.d.ts +0 -3
  8. package/dist/runtime/execution-plane.js +0 -24
  9. package/dist/runtime/facade.js +3 -0
  10. package/dist/runtime/kernel-event-log.js +7 -13
  11. package/dist/runtime/kernel-journal.d.ts +264 -0
  12. package/dist/runtime/kernel-journal.js +741 -0
  13. package/dist/runtime/kernel-primitives-dashboard.d.ts +0 -2
  14. package/dist/runtime/kernel-primitives-dashboard.js +1 -8
  15. package/dist/runtime/kernel-step.d.ts +29 -109
  16. package/dist/runtime/kernel-step.js +47 -317
  17. package/dist/runtime/os-snapshot.d.ts +2 -2
  18. package/dist/runtime/os-snapshot.js +2 -6
  19. package/dist/runtime/payload-store.d.ts +16 -0
  20. package/dist/runtime/payload-store.js +80 -0
  21. package/dist/runtime/runner.d.ts +31 -114
  22. package/dist/runtime/runner.js +689 -774
  23. package/dist/runtime/session-log.d.ts +34 -32
  24. package/dist/runtime/session-log.js +21 -131
  25. package/dist/runtime/session-repair.d.ts +2 -36
  26. package/dist/runtime/session-repair.js +2 -47
  27. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  28. package/dist/runtime/sub-agent-orchestrator.js +42 -40
  29. package/dist/types/agent.d.ts +22 -19
  30. package/dist/types/agent.js +26 -42
  31. package/dist/workflow/public.d.ts +1 -1
  32. package/dist/workflow/public.js +1 -1
  33. package/package.json +2 -2
  34. package/dist/runtime/kernel-rebuild.d.ts +0 -13
  35. package/dist/runtime/kernel-rebuild.js +0 -75
  36. package/dist/runtime/kernel-transaction-log.d.ts +0 -61
  37. package/dist/runtime/kernel-transaction-log.js +0 -149
  38. package/dist/runtime/large-result-spool.d.ts +0 -93
  39. package/dist/runtime/large-result-spool.js +0 -214
@@ -1,22 +1,4 @@
1
1
  import { getKernel } from "../kernel.js";
2
- /** Map kernel spawn observation → host manifest. */
3
- export function spawnObservationToManifest(obs, spec, parentSessionId) {
4
- const o = obs;
5
- return {
6
- kind: "agent_process_changed",
7
- turn: o.turn,
8
- agent_id: String(o.agent_id ?? spec.identity.agentId),
9
- parent_session_id: String(o.parent_session_id ?? parentSessionId),
10
- role: String(o.role ?? spec.role),
11
- isolation: String(o.isolation ?? spec.isolation ?? "shared"),
12
- context_inheritance: String(o.context_inheritance ?? "none"),
13
- permitted_capability_ids: o.permitted_capability_ids ?? [],
14
- };
15
- }
16
- export function findSpawnProcessObservation(observations) {
17
- const hit = observations.find(o => o.kind === "agent_process_changed" && typeof o.agent_id === "string");
18
- return hit;
19
- }
20
2
  export function agentIdentitySub(agentId, sessionId, parentSessionId) {
21
3
  return {
22
4
  agentId,
@@ -97,6 +79,9 @@ export function subAgentResultToKernel(result) {
97
79
  const attempt = result.result.attempt;
98
80
  return {
99
81
  agent_id: result.agentId,
82
+ ...(result.submittedNodes?.length
83
+ ? { submitted_nodes: result.submittedNodes.map(workflowNodeSpecToKernel) }
84
+ : {}),
100
85
  result: {
101
86
  termination: result.result.termination,
102
87
  final_message: finalMessage
@@ -151,6 +136,18 @@ export function milestoneCheckPass(phaseId) {
151
136
  export function milestoneCheckFail(phaseId, reason) {
152
137
  return { phaseId, passed: false, reason };
153
138
  }
139
+ /**
140
+ * R-B27: the conservative resolution the runner feeds back when an `evaluate_milestone` effect
141
+ * arrives with no phase `verifier` and no host `onMilestoneEvaluate` hook. Nothing can attest the
142
+ * phase, but the kernel is already holding the effect in its pending table — returning without an
143
+ * answer leaves a dangling effect that a logical-checkpoint recovery cannot resolve. The current
144
+ * `MilestoneResult` wire has no error field, so "could not be verified" is expressed with the
145
+ * shape the wire does have: `passed: false` (the phase does not advance — fail-closed).
146
+ *
147
+ * The string is part of the cross-SDK contract: WASM (`wasm/src/runtime/types/agent.ts`),
148
+ * Python (`deepstrike/types/agent.py`) and Rust must feed back the byte-identical reason.
149
+ */
150
+ export const MILESTONE_UNVERIFIED_REASON = "milestone unverified: no verifier configured and no host evaluation hook (fail-closed)";
154
151
  export function workflowNodeStatusFromTermination(termination) {
155
152
  if (termination === "completed")
156
153
  return "completed";
@@ -196,6 +193,15 @@ export function workflowBudgetNote(budget) {
196
193
  if (budget.tokens_remaining != null && budget.tokens_max != null) {
197
194
  parts.push(`tokens ${budget.tokens_used ?? 0}/${budget.tokens_max} used, ${budget.tokens_remaining} remaining`);
198
195
  }
196
+ if (budget.max_total_tokens != null) {
197
+ parts.push(`tokens capped at ${budget.max_total_tokens}`);
198
+ }
199
+ if (budget.max_turns != null) {
200
+ parts.push(`turns capped at ${budget.max_turns}`);
201
+ }
202
+ if (budget.max_concurrency != null) {
203
+ parts.push(`concurrency capped at ${budget.max_concurrency}`);
204
+ }
199
205
  if (parts.length === 0)
200
206
  return "";
201
207
  return (`[workflow budget] ${parts.join(" · ")}. ` +
@@ -230,7 +236,7 @@ function nodeKindToKernel(n) {
230
236
  return { type: "tournament", entrants: n.tournament.entrants.map(workflowTaskToKernel) };
231
237
  return undefined;
232
238
  }
233
- /** Map one host `WorkflowNodeSpec` to its snake_case kernel JSON. Shared by `load_workflow` (the
239
+ /** Map one host `WorkflowNodeSpec` to its snake_case canonical JSON. Shared by the workflow root (the
234
240
  * whole spec) and `submit_workflow_nodes` (R3-1 runtime append) so the two encodings never drift. */
235
241
  export function workflowNodeSpecToKernel(n) {
236
242
  const kind = nodeKindToKernel(n);
@@ -254,32 +260,10 @@ export function workflowNodeSpecToKernel(n) {
254
260
  dep_policy: n.depPolicy ?? "all_success",
255
261
  };
256
262
  }
257
- /** Map a host `WorkflowSpec` to the snake_case kernel JSON (`load_workflow.spec`). */
263
+ /** Map a host `WorkflowSpec` to the canonical workflow-root JSON. */
258
264
  export function workflowSpecToKernel(spec) {
259
265
  return { nodes: spec.nodes.map(workflowNodeSpecToKernel) };
260
266
  }
261
- /** R3-1: map a batch of host nodes to the `submit_workflow_nodes` kernel event body. G1: pass
262
- * `submitterAgentId` (the node that requested the append) so the kernel can enforce no-privilege-
263
- * escalation — a quarantined submitter's nodes are coerced to quarantined. Omitted ⇒ no coercion. */
264
- export function submitWorkflowNodesToKernel(nodes, submitterAgentId) {
265
- return {
266
- kind: "submit_workflow_nodes",
267
- nodes: nodes.map(workflowNodeSpecToKernel),
268
- ...(submitterAgentId ? { submitter_agent_id: submitterAgentId } : {}),
269
- };
270
- }
271
- /** M5/G1: map an agent-authored spec to the `submit_workflow` kernel event body (the agent-reachable
272
- * `Syscall::LoadWorkflow`). The kernel bootstraps the DAG when none is active, else flattens onto it.
273
- * `parentSessionId` seeds child session ids on bootstrap; `submitterAgentId` carries G1 trust coercion
274
- * on the flatten case (a quarantined author's nodes are coerced quarantined). */
275
- export function submitWorkflowToKernel(spec, parentSessionId, submitterAgentId) {
276
- return {
277
- kind: "submit_workflow",
278
- spec: workflowSpecToKernel(spec),
279
- parent_session_id: parentSessionId,
280
- ...(submitterAgentId ? { submitter_agent_id: submitterAgentId } : {}),
281
- };
282
- }
283
267
  /** Shared JSON-Schema for a workflow-node batch (a DAG). Used by both `submit_workflow_nodes`
284
268
  * (append) and `start_workflow` (M5 v1: author a sub-workflow), so the two tools never drift. */
285
269
  const workflowNodesArraySchema = {
@@ -3,7 +3,7 @@ export type { SubAgentRunContext } from "../runtime/sub-agent-orchestrator.js";
3
3
  export { builtinReducers, resolveReducer } from "../runtime/reducers.js";
4
4
  export type { Reducer, ReducerRegistry, ReducerInput } from "../runtime/reducers.js";
5
5
  export { FileWorkflowStore } from "../runtime/workflow-store.js";
6
- export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, } from "../types/agent.js";
6
+ export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, MILESTONE_UNVERIFIED_REASON, } from "../types/agent.js";
7
7
  export type { AgentCapabilityFilter, AgentIdentity, AgentIsolation, AgentRunSpec, AgentProcessChangedObservation, ContextInheritance, KernelAgentRole, LoopResult, MilestoneCheckResult, MilestoneContract, MilestonePhase, MilestonePolicy, SubAgentResult, TerminationReason, WorkflowSpawnInfo, WorkflowTaskSpec, WorkflowDependencyPolicy, WorkflowNodeStatus, WorkflowNodeOutcome, WorkflowOutcome, } from "../types/agent.js";
8
8
  export type { AcceptanceCriterion, VerificationContract, ContractCheckResult } from "../collaboration/contract.js";
9
9
  export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings } from "../collaboration/contract.js";
@@ -5,7 +5,7 @@
5
5
  export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } from "../runtime/sub-agent-orchestrator.js";
6
6
  export { builtinReducers, resolveReducer } from "../runtime/reducers.js";
7
7
  export { FileWorkflowStore } from "../runtime/workflow-store.js";
8
- export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, } from "../types/agent.js";
8
+ export { submitWorkflowNodesTool, startWorkflowTool, generateAndFilter, verifyRules, genEval, milestoneCheckPass, milestoneCheckFail, MILESTONE_UNVERIFIED_REASON, } from "../types/agent.js";
9
9
  export { ContractBuilder, formatContractForSystemPrompt, contractToCriteriaStrings } from "../collaboration/contract.js";
10
10
  export { HandoffBus } from "../collaboration/handoff.js";
11
11
  export { CreatorVerifierMode, OrchestrationMode } from "../collaboration/modes/creator-verifier.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.50",
3
+ "version": "0.2.51",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@anthropic-ai/sdk": "^0.99.0",
75
- "@deepstrike/core": "0.2.50",
75
+ "@deepstrike/core": "0.2.51",
76
76
  "@google/generative-ai": "^0.24.1",
77
77
  "openai": "^5.23.2"
78
78
  },
@@ -1,13 +0,0 @@
1
- import type { KernelRuntimeHandle } from "./kernel-step.js";
2
- import { type KernelOperationCursor, type KernelOperationGenesis, type KernelTransaction } from "./kernel-transaction-log.js";
3
- export interface KernelRebuildResult {
4
- runtime: KernelRuntimeHandle;
5
- cursor: KernelOperationCursor;
6
- }
7
- /**
8
- * Deterministically fold an authoritative operation stream into a fresh runtime.
9
- *
10
- * The caller owns runtime construction, but its initial policy and replay-affecting defaults must
11
- * exactly match genesis. A failure leaves the supplied runtime unusable; callers must discard it.
12
- */
13
- export declare function rebuildKernelRuntime(runtime: KernelRuntimeHandle, genesis: KernelOperationGenesis, transactions: readonly KernelTransaction[]): KernelRebuildResult;
@@ -1,75 +0,0 @@
1
- import { KernelLogIntegrityError, kernelRecordDigest, verifyKernelTransactionStream, } from "./kernel-transaction-log.js";
2
- /**
3
- * Deterministically fold an authoritative operation stream into a fresh runtime.
4
- *
5
- * The caller owns runtime construction, but its initial policy and replay-affecting defaults must
6
- * exactly match genesis. A failure leaves the supplied runtime unusable; callers must discard it.
7
- */
8
- export function rebuildKernelRuntime(runtime, genesis, transactions) {
9
- const cursor = verifyKernelTransactionStream(genesis, transactions);
10
- assertFreshRuntimeMatchesGenesis(runtime, genesis);
11
- for (const transaction of transactions) {
12
- const prepared = JSON.parse(runtime.prepareStep(JSON.stringify(transaction.input)));
13
- const token = prepared.prepare_token;
14
- try {
15
- if (prepared.status !== "prepared" || !token) {
16
- throw new KernelLogIntegrityError(`kernel rebuild step ${transaction.step_seq} was not accepted as a new transition`);
17
- }
18
- if (prepared.base_generation !== transaction.base_generation) {
19
- throw new KernelLogIntegrityError(`kernel rebuild generation ${prepared.base_generation} does not match transaction ${transaction.base_generation}`);
20
- }
21
- if (prepared.step.step_seq !== transaction.step_seq) {
22
- throw new KernelLogIntegrityError(`kernel rebuild step_seq ${prepared.step.step_seq} does not match transaction ${transaction.step_seq}`);
23
- }
24
- if (kernelRecordDigest(prepared.input) !== transaction.input_digest) {
25
- throw new KernelLogIntegrityError(`kernel rebuild normalized input diverged at step ${transaction.step_seq}`);
26
- }
27
- if (kernelRecordDigest(prepared.step) !== transaction.step_digest) {
28
- throw new KernelLogIntegrityError(`kernel rebuild planned step diverged at step ${transaction.step_seq}`);
29
- }
30
- const committed = JSON.parse(runtime.commitPrepared(token));
31
- if (kernelRecordDigest(committed) !== transaction.step_digest) {
32
- throw new KernelLogIntegrityError(`kernel rebuild committed step diverged at step ${transaction.step_seq}`);
33
- }
34
- }
35
- catch (error) {
36
- if (token && prepared.status === "prepared") {
37
- try {
38
- runtime.abortPrepared(token);
39
- }
40
- catch {
41
- // The caller must discard a failed rebuild runtime; preserve the primary integrity error.
42
- }
43
- }
44
- throw error;
45
- }
46
- }
47
- return { runtime, cursor };
48
- }
49
- function assertFreshRuntimeMatchesGenesis(runtime, genesis) {
50
- const snapshot = JSON.parse(runtime.snapshot());
51
- if (snapshot.abi_version !== genesis.abi_version) {
52
- throw new KernelLogIntegrityError("kernel runtime ABI version does not match operation genesis");
53
- }
54
- if (genesis.default_policy_version !== 1) {
55
- throw new KernelLogIntegrityError("kernel operation uses an unsupported default policy version");
56
- }
57
- if (snapshot.operation_id || snapshot.next_step_seq !== 1 || snapshot.accepted_inputs.length !== 0) {
58
- throw new KernelLogIntegrityError("kernel rebuild requires a fresh runtime");
59
- }
60
- if (kernelRecordDigest(snapshot.initial_policy) !== kernelRecordDigest(genesis.initial_scheduler_policy)) {
61
- throw new KernelLogIntegrityError("kernel runtime initial policy does not match operation genesis");
62
- }
63
- const defaults = resolvedRuntimeDefaults(snapshot);
64
- if (kernelRecordDigest(defaults) !== kernelRecordDigest(genesis.resolved_runtime_defaults)) {
65
- throw new KernelLogIntegrityError("kernel runtime defaults do not match operation genesis");
66
- }
67
- }
68
- function resolvedRuntimeDefaults(snapshot) {
69
- return {
70
- snapshot_version: snapshot.snapshot_version,
71
- snapshot_input_limit: snapshot.snapshot_input_limit,
72
- max_input_bytes: snapshot.max_input_bytes,
73
- snapshot_journal_bytes_limit: snapshot.snapshot_journal_bytes_limit,
74
- };
75
- }
@@ -1,61 +0,0 @@
1
- export declare const KERNEL_LOG_RECORD_VERSION: 1;
2
- export interface KernelOperationGenesisBody {
3
- record_version: typeof KERNEL_LOG_RECORD_VERSION;
4
- abi_version: number;
5
- operation_id: string;
6
- initial_scheduler_policy: Record<string, unknown>;
7
- resolved_runtime_defaults: Record<string, unknown>;
8
- default_policy_version: number;
9
- }
10
- export interface KernelOperationGenesis extends KernelOperationGenesisBody {
11
- genesis_digest: string;
12
- }
13
- export interface KernelTransactionBody {
14
- record_version: typeof KERNEL_LOG_RECORD_VERSION;
15
- operation_id: string;
16
- step_seq: number;
17
- base_generation: number;
18
- input: Record<string, unknown>;
19
- input_digest: string;
20
- previous_transaction_digest: string;
21
- step_digest: string;
22
- }
23
- export interface KernelTransaction extends KernelTransactionBody {
24
- transaction_digest: string;
25
- }
26
- export interface KernelGenesisReceipt {
27
- log_seq: number;
28
- genesis_digest: string;
29
- }
30
- export interface DurableAppendReceipt {
31
- log_seq: number;
32
- transaction_digest: string;
33
- }
34
- export interface KernelOperationCursor {
35
- operation_id: string;
36
- next_event_sequence: number;
37
- next_step_seq: number;
38
- transaction_head_digest: string;
39
- }
40
- export declare class KernelLogConflictError extends Error {
41
- constructor(message: string);
42
- }
43
- export declare class KernelLogIntegrityError extends Error {
44
- constructor(message: string);
45
- }
46
- export declare function canonicalKernelJson(value: unknown): string;
47
- export declare function kernelRecordDigest(value: unknown): string;
48
- export declare function createKernelOperationGenesis(input: Omit<KernelOperationGenesisBody, "record_version">): Promise<KernelOperationGenesis>;
49
- export declare function createKernelTransaction(input: {
50
- operation_id: string;
51
- step_seq: number;
52
- base_generation: number;
53
- input: Record<string, unknown>;
54
- step: Record<string, unknown>;
55
- previous_transaction_digest: string;
56
- }): Promise<KernelTransaction>;
57
- export declare function verifyKernelOperationGenesis(genesis: KernelOperationGenesis): void;
58
- export declare function verifyKernelTransaction(transaction: KernelTransaction): void;
59
- export declare function verifyKernelTransactionSuccessor(previous: KernelTransaction | undefined, transaction: KernelTransaction): void;
60
- /** Validate one complete authoritative operation stream and derive its next wire cursor. */
61
- export declare function verifyKernelTransactionStream(genesis: KernelOperationGenesis, transactions: readonly KernelTransaction[]): KernelOperationCursor;
@@ -1,149 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- export const KERNEL_LOG_RECORD_VERSION = 1;
3
- export class KernelLogConflictError extends Error {
4
- constructor(message) {
5
- super(message);
6
- this.name = "KernelLogConflictError";
7
- }
8
- }
9
- export class KernelLogIntegrityError extends Error {
10
- constructor(message) {
11
- super(message);
12
- this.name = "KernelLogIntegrityError";
13
- }
14
- }
15
- export function canonicalKernelJson(value) {
16
- if (value === null)
17
- return "null";
18
- if (typeof value === "string" || typeof value === "boolean")
19
- return JSON.stringify(value);
20
- if (typeof value === "number") {
21
- if (!Number.isFinite(value))
22
- throw new KernelLogIntegrityError("canonical records require finite numbers");
23
- if (Number.isSafeInteger(value))
24
- return JSON.stringify(Object.is(value, -0) ? 0 : value);
25
- if (Number.isInteger(value)) {
26
- throw new KernelLogIntegrityError("canonical record integer exceeds the cross-SDK safe range");
27
- }
28
- const bytes = new Uint8Array(8);
29
- new DataView(bytes.buffer).setFloat64(0, value, false);
30
- return `f64:${Array.from(bytes, byte => byte.toString(16).padStart(2, "0")).join("")}`;
31
- }
32
- if (Array.isArray(value))
33
- return `[${value.map(canonicalKernelJson).join(",")}]`;
34
- if (typeof value === "object") {
35
- const object = value;
36
- const keys = Object.keys(object).sort();
37
- return `{${keys.map(key => `${JSON.stringify(key)}:${canonicalKernelJson(object[key])}`).join(",")}}`;
38
- }
39
- throw new KernelLogIntegrityError(`unsupported canonical record value: ${typeof value}`);
40
- }
41
- export function kernelRecordDigest(value) {
42
- return createHash("sha256").update(canonicalKernelJson(value), "utf8").digest("hex");
43
- }
44
- export async function createKernelOperationGenesis(input) {
45
- const body = {
46
- record_version: KERNEL_LOG_RECORD_VERSION,
47
- ...input,
48
- };
49
- validateGenesisBody(body);
50
- return { ...body, genesis_digest: kernelRecordDigest(body) };
51
- }
52
- export async function createKernelTransaction(input) {
53
- const body = {
54
- record_version: KERNEL_LOG_RECORD_VERSION,
55
- operation_id: input.operation_id,
56
- step_seq: input.step_seq,
57
- base_generation: input.base_generation,
58
- input: input.input,
59
- input_digest: kernelRecordDigest(input.input),
60
- previous_transaction_digest: input.previous_transaction_digest,
61
- step_digest: kernelRecordDigest(input.step),
62
- };
63
- validateTransactionBody(body);
64
- return { ...body, transaction_digest: kernelRecordDigest(body) };
65
- }
66
- export function verifyKernelOperationGenesis(genesis) {
67
- const { genesis_digest, ...body } = genesis;
68
- validateGenesisBody(body);
69
- if (kernelRecordDigest(body) !== genesis_digest) {
70
- throw new KernelLogIntegrityError("kernel genesis digest does not match its canonical body");
71
- }
72
- }
73
- export function verifyKernelTransaction(transaction) {
74
- const { transaction_digest, ...body } = transaction;
75
- validateTransactionBody(body);
76
- if (kernelRecordDigest(body.input) !== body.input_digest) {
77
- throw new KernelLogIntegrityError("kernel transaction input digest does not match its input");
78
- }
79
- if (kernelRecordDigest(body) !== transaction_digest) {
80
- throw new KernelLogIntegrityError("kernel transaction digest does not match its canonical body");
81
- }
82
- }
83
- export function verifyKernelTransactionSuccessor(previous, transaction) {
84
- const expectedStepSeq = previous ? previous.step_seq + 1 : 1;
85
- const expectedGeneration = previous ? previous.base_generation + 1 : 0;
86
- if (transaction.step_seq !== expectedStepSeq) {
87
- throw new KernelLogIntegrityError(`kernel transaction step_seq ${transaction.step_seq} does not follow ${expectedStepSeq - 1}`);
88
- }
89
- if (transaction.base_generation !== expectedGeneration) {
90
- throw new KernelLogIntegrityError(`kernel transaction base_generation ${transaction.base_generation} does not match ${expectedGeneration}`);
91
- }
92
- if (transaction.input.operation_id !== transaction.operation_id) {
93
- throw new KernelLogIntegrityError("kernel transaction input operation_id does not match its envelope");
94
- }
95
- }
96
- /** Validate one complete authoritative operation stream and derive its next wire cursor. */
97
- export function verifyKernelTransactionStream(genesis, transactions) {
98
- verifyKernelOperationGenesis(genesis);
99
- let previous;
100
- let head = genesis.genesis_digest;
101
- for (const transaction of transactions) {
102
- verifyKernelTransaction(transaction);
103
- if (transaction.operation_id !== genesis.operation_id) {
104
- throw new KernelLogIntegrityError("kernel transaction operation_id does not match genesis");
105
- }
106
- if (transaction.previous_transaction_digest !== head) {
107
- throw new KernelLogIntegrityError("kernel transaction digest chain is not continuous");
108
- }
109
- verifyKernelTransactionSuccessor(previous, transaction);
110
- previous = transaction;
111
- head = transaction.transaction_digest;
112
- }
113
- const nextSequence = (previous?.step_seq ?? 0) + 1;
114
- return {
115
- operation_id: genesis.operation_id,
116
- next_event_sequence: nextSequence,
117
- next_step_seq: nextSequence,
118
- transaction_head_digest: head,
119
- };
120
- }
121
- function validateGenesisBody(genesis) {
122
- if (genesis.record_version !== KERNEL_LOG_RECORD_VERSION) {
123
- throw new KernelLogIntegrityError("unsupported kernel genesis record version");
124
- }
125
- if (!Number.isSafeInteger(genesis.abi_version) || genesis.abi_version <= 0) {
126
- throw new KernelLogIntegrityError("kernel genesis abi_version must be a positive safe integer");
127
- }
128
- if (!genesis.operation_id)
129
- throw new KernelLogIntegrityError("kernel genesis operation_id is required");
130
- if (!Number.isSafeInteger(genesis.default_policy_version) || genesis.default_policy_version <= 0) {
131
- throw new KernelLogIntegrityError("kernel genesis default_policy_version must be a positive safe integer");
132
- }
133
- }
134
- function validateTransactionBody(transaction) {
135
- if (transaction.record_version !== KERNEL_LOG_RECORD_VERSION) {
136
- throw new KernelLogIntegrityError("unsupported kernel transaction record version");
137
- }
138
- if (!transaction.operation_id)
139
- throw new KernelLogIntegrityError("kernel transaction operation_id is required");
140
- if (!Number.isSafeInteger(transaction.step_seq) || transaction.step_seq <= 0) {
141
- throw new KernelLogIntegrityError("kernel transaction step_seq must be a positive safe integer");
142
- }
143
- if (!Number.isSafeInteger(transaction.base_generation) || transaction.base_generation < 0) {
144
- throw new KernelLogIntegrityError("kernel transaction base_generation must be a non-negative safe integer");
145
- }
146
- if (!transaction.previous_transaction_digest) {
147
- throw new KernelLogIntegrityError("kernel transaction previous_transaction_digest is required");
148
- }
149
- }
@@ -1,93 +0,0 @@
1
- /**
2
- * Large result spool (Layer 1 of 5-layer compression pyramid).
3
- *
4
- * When a single tool result exceeds 50KB, write the full content to disk
5
- * and keep only a 2KB preview in the message. Zero API overhead.
6
- *
7
- * Design principles:
8
- * - Kernel defines policy (thresholds)
9
- * - SDK performs I/O (disk write/read)
10
- * - Model can retrieve full content via Read tool when needed
11
- */
12
- export interface ToolResult {
13
- callId: string;
14
- tool: string;
15
- output: string;
16
- isError?: boolean;
17
- }
18
- export interface SpooledToolResult {
19
- originalOutput: string;
20
- preview: string;
21
- spoolRef: string;
22
- wasSpooled: boolean;
23
- }
24
- /**
25
- * Large result spool configuration (mirrors kernel ContextConfig).
26
- */
27
- export interface SpoolConfig {
28
- /** Single result size threshold (bytes) */
29
- spoolThresholdBytes: number;
30
- /** Preview token count (~2KB) */
31
- previewTokens: number;
32
- /** Total message limit (bytes) */
33
- totalMessageLimitBytes: number;
34
- /** Custom spool directory path */
35
- spoolDir?: string;
36
- /** Maximum age of spooled files (default 7 days) */
37
- maxAgeMs?: number;
38
- }
39
- export declare const DEFAULT_SPOOL_CONFIG: SpoolConfig;
40
- /**
41
- * Large result spool manager.
42
- */
43
- export declare class LargeResultSpool {
44
- private config;
45
- private spoolDir;
46
- private activeWrites;
47
- constructor(config?: Partial<SpoolConfig>);
48
- /**
49
- * Check if a tool result needs spooling.
50
- */
51
- private needsSpool;
52
- /**
53
- * Hash content for spool reference.
54
- */
55
- private hashContent;
56
- /**
57
- * Get spool file path for a hash.
58
- */
59
- private getSpoolPath;
60
- private callKey;
61
- private atomicWrite;
62
- /**
63
- * Write large result to disk.
64
- */
65
- private writeToDisk;
66
- /**
67
- * Generate preview for a tool result.
68
- */
69
- private generatePreview;
70
- /**
71
- * Process a tool result: spool if large, return spooled result.
72
- */
73
- processToolResult(result: ToolResult): Promise<SpooledToolResult>;
74
- /**
75
- * Persist a kernel-spooled tool output to disk. Returns the on-disk path ref.
76
- */
77
- persistOutput(sessionId: string, callId: string, content: string): Promise<string>;
78
- /**
79
- * Read a spooled result back from disk.
80
- */
81
- readSpooledResult(spoolRef: string): Promise<string>;
82
- /**
83
- * O7: locate a spooled output by the tool call's id (the `read_result` meta-tool only knows
84
- * `call_id`, not the content-hashed file name `persistOutput` chose). Scans the spool directory
85
- * for the hashed call-key prefix; returns `undefined` if nothing was ever spooled
86
- * for that call (e.g. it never actually exceeded the threshold, or the spool dir was cleaned up).
87
- */
88
- findByCallId(sessionId: string, callId: string): Promise<string | undefined>;
89
- /**
90
- * Clean up old spool files (optional maintenance).
91
- */
92
- cleanup(maxAgeMs?: number): Promise<number>;
93
- }