@deepstrike/wasm 0.2.68 → 0.2.70

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 (38) hide show
  1. package/dist/index.d.ts +8 -1
  2. package/dist/index.js +3 -0
  3. package/dist/providers/anthropic.d.ts +8 -5
  4. package/dist/providers/anthropic.js +12 -1
  5. package/dist/providers/base.d.ts +5 -5
  6. package/dist/providers/base.js +1 -1
  7. package/dist/providers/openai.d.ts +6 -4
  8. package/dist/providers/openai.js +28 -24
  9. package/dist/providers/prepared-request.d.ts +4 -0
  10. package/dist/providers/prepared-request.js +78 -0
  11. package/dist/providers/request-plan.d.ts +8 -1
  12. package/dist/providers/request-plan.js +4 -3
  13. package/dist/runtime/canonical-kernel-step.d.ts +4 -3
  14. package/dist/runtime/canonical-kernel-step.js +16 -7
  15. package/dist/runtime/context.d.ts +28 -0
  16. package/dist/runtime/context.js +16 -0
  17. package/dist/runtime/eval.d.ts +2 -2
  18. package/dist/runtime/evolution.d.ts +189 -0
  19. package/dist/runtime/evolution.js +25 -0
  20. package/dist/runtime/kernel-step.d.ts +8 -7
  21. package/dist/runtime/provider-replay.d.ts +2 -2
  22. package/dist/runtime/provider-replay.js +1 -1
  23. package/dist/runtime/replay-fixture.d.ts +4 -4
  24. package/dist/runtime/replay-fixture.js +2 -2
  25. package/dist/runtime/replay-provider.d.ts +3 -3
  26. package/dist/runtime/runner.d.ts +8 -6
  27. package/dist/runtime/runner.js +22 -5
  28. package/dist/runtime/session-log.d.ts +9 -4
  29. package/dist/runtime/session-log.js +1 -0
  30. package/dist/runtime/session-repair.d.ts +3 -4
  31. package/dist/runtime/session-repair.js +1 -4
  32. package/dist/runtime/sub-agent-orchestrator.js +1 -1
  33. package/dist/runtime/types/agent.d.ts +4 -4
  34. package/dist/runtime/verifiable-report.d.ts +59 -0
  35. package/dist/runtime/verifiable-report.js +64 -0
  36. package/dist/tools/index.d.ts +2 -2
  37. package/dist/types.d.ts +19 -10
  38. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@ export { CANONICAL_CONTENT_PARTS_PREFIX, encodeCanonicalContentParts, decodeCano
5
5
  export type { ReplayProviderOpts, Criterion, Verdict, VerdictDetail, JudgeArgs, } from "./runtime/index.js";
6
6
  export type { NativeOsProfile, OsProfileId, MemoryPolicy, MemoryWriteRateLimit, ResourceQuota, RuntimeOptions, PromptBudget, SchedulerPolicy, SignalPolicy, SessionEvent, SessionEventKind, SessionLog, RunContext, ExecutionPlane, KernelEventCategory, KernelPrimitive, } from "./runtime/index.js";
7
7
  export { primitiveForCategory, primitiveForKind } from "./runtime/index.js";
8
+ export { VERIFIABLE_REPORT_SCHEMA, VERIFIABLE_FORK_SCHEMA, assertVerifiableReportSchema, createVerifiableRuntimeAdapter, createNativeVerifiableRuntimeAdapter, VerifiableOperation, } from "./runtime/verifiable-report.js";
9
+ export type { VerifiableCommand, CheckVerdict, VerifiableForkManifest, ForkPlan, VerifiableEvidence, VerifyOptions, ReplayOptions, VerifiableRuntimeAdapter, VerifiableReport, VerifiableOperationJson, } from "./runtime/verifiable-report.js";
8
10
  export { FilteredExecutionPlane } from "./runtime/filtered-plane.js";
9
11
  export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } from "./runtime/sub-agent-orchestrator.js";
10
12
  export type { SubAgentRunContext } from "./runtime/sub-agent-orchestrator.js";
@@ -35,6 +37,8 @@ export type { RankableMemory, RankedMemory, RankOptions } from "./memory/ranking
35
37
  export { extractSessionMemories, parseExtractedMemories } from "./memory/extraction.js";
36
38
  export type { MemoryStore, Memory, MemorySearchOptions, SessionStore, SessionData, SessionMessage, MemoryRecord, MemoryRecall, MemoryRecallLifecycle, MemoryQuery, MemoryScope, MemoryProvenance, MemoryKind, MemoryAuthor, MemoryTrustLevel, } from "./memory/index.js";
37
39
  export type { KnowledgeSource } from "./knowledge/index.js";
40
+ export { createEvolutionRuntimeAdapter, createNativeEvolutionRuntimeAdapter, EvolutionRuntime } from "./runtime/evolution.js";
41
+ export type { ActivationBinding, ArtifactKind, ArtifactManifest, ArtifactRef, ArtifactSet, ArtifactVersion, ContextEntryRef, ContextEntrySource, ContextExecutionInput, ContextPlan, ContextPlanAction, ContextPreparationRequest, ContextSelection, ContextState, EvaluationContextBinding, EvaluationFact, EvaluationGate, EvaluationMetric, EvaluationRun, EvolutionBundle, EvolutionProposal, EvolutionReport, EvolutionVerdict, PromotionDecision, PromotionOutcome, EvolutionStore, } from "./runtime/evolution.js";
38
42
  export { AttemptLoop, RuntimeAttemptBody, VerdictFnJudge, LlmEvalJudge, HybridJudge, continueSession, freshWithFeedback, freshWithDigest, } from "./harness/index.js";
39
43
  export type { AttemptBody, AttemptBodyContext, AttemptBodyEvent, AttemptBodyTerminal, AttemptJudge, AttemptLoopEvent, AttemptLoopOptions, AttemptOutcome, AttemptOutcomeKind, AttemptProgressEvent, AttemptRequest, CarryPolicy, JudgeContext, JudgeResult, PreparedAttempt, StopPolicy, VerdictFn, } from "./harness/index.js";
40
44
  export { ScheduledPrompt } from "./signals/index.js";
@@ -49,6 +53,9 @@ export type { CanonicalStopReason } from "./providers/stop-reason.js";
49
53
  export { ContentPolicyError, contentDispositionFor, requireContentDisposition } from "./providers/content-policy.js";
50
54
  export type { ContentDisposition, ContentPlacement, InputModality } from "./providers/content-policy.js";
51
55
  export type { PermissionDecision } from "./safety/index.js";
52
- export type { Message, ToolCall, ToolResult, ToolSchema, RenderedContext, ProviderRunState, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, EntropySample, EntropySampleEvent, EntropyAlertEvent, EntropyWatchOptions, LLMProvider, CacheBreakpointStrategy, ProviderWireEvidence, ProviderTransportTelemetry, } from "./types.js";
56
+ export type { ProviderMessage, ToolCall, ToolExecutionResult, ToolSchema, RenderedContext, ProviderRunState, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, EntropySample, EntropySampleEvent, EntropyAlertEvent, EntropyWatchOptions, LLMProvider, CacheBreakpointStrategy, ProviderWireEvidence, ProviderTransportTelemetry, } from "./types.js";
53
57
  export { DurableContentError, decodeDurableContent, decodeDurableToolResult, encodeDurableContent, encodeDurableToolResult, toolOutputBlocksToDurable, durableBlocksToToolOutput } from "./runtime/durable-content.js";
54
58
  export type { DurableContent, DurableContentBlock, DurableSource, DurableToolResult } from "./runtime/durable-content.js";
59
+ export { createContextPreparationAdapter, createNativeContextPreparationAdapter } from "./runtime/context.js";
60
+ export type { ContextPrepareJson, ContextVerifyJson, ContextPrepared, ContextProviderPreparationRequest } from "./runtime/context.js";
61
+ export type { PreparedProviderRequest } from "./types.js";
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ export { DriverKernelJournal, InMemoryJournalDriver, InMemoryKernelJournal, Jour
4
4
  // ── content-parts-v1 registered encoding (F14/B5; byte-pinned by sdk-conformance) ──
5
5
  export { CANONICAL_CONTENT_PARTS_PREFIX, encodeCanonicalContentParts, decodeCanonicalContentParts, } from "./runtime/kernel-step.js";
6
6
  export { primitiveForCategory, primitiveForKind } from "./runtime/index.js";
7
+ export { VERIFIABLE_REPORT_SCHEMA, VERIFIABLE_FORK_SCHEMA, assertVerifiableReportSchema, createVerifiableRuntimeAdapter, createNativeVerifiableRuntimeAdapter, VerifiableOperation, } from "./runtime/verifiable-report.js";
7
8
  export { FilteredExecutionPlane } from "./runtime/filtered-plane.js";
8
9
  export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } from "./runtime/sub-agent-orchestrator.js";
9
10
  export { workflowSpecToKernel, workflowNodeSpecToKernel, submitWorkflowNodesTool, startWorkflowTool, fanoutSynthesize, generateAndFilter, genEval, verifyRules } from "./runtime/types/agent.js";
@@ -21,6 +22,7 @@ export { InMemoryMemoryStore } from "./memory/in-memory-store.js";
21
22
  export { memoryRetentionScore } from "./memory/retention.js";
22
23
  export { rankMemories } from "./memory/ranking.js";
23
24
  export { extractSessionMemories, parseExtractedMemories } from "./memory/extraction.js";
25
+ export { createEvolutionRuntimeAdapter, createNativeEvolutionRuntimeAdapter, EvolutionRuntime } from "./runtime/evolution.js";
24
26
  export { AttemptLoop, RuntimeAttemptBody, VerdictFnJudge, LlmEvalJudge, HybridJudge, continueSession, freshWithFeedback, freshWithDigest, } from "./harness/index.js";
25
27
  export { ScheduledPrompt } from "./signals/index.js";
26
28
  export { PermissionManager, PermissionMode } from "./safety/index.js";
@@ -29,3 +31,4 @@ export { FULL_FOOTPRINT_USAGE_ACCOUNTING_POLICY, providerAttemptToRecord, tryNor
29
31
  export { decodeCanonicalStopReason, normalizeProviderStopReason } from "./providers/stop-reason.js";
30
32
  export { ContentPolicyError, contentDispositionFor, requireContentDisposition } from "./providers/content-policy.js";
31
33
  export { DurableContentError, decodeDurableContent, decodeDurableToolResult, encodeDurableContent, encodeDurableToolResult, toolOutputBlocksToDurable, durableBlocksToToolOutput } from "./runtime/durable-content.js";
34
+ export { createContextPreparationAdapter, createNativeContextPreparationAdapter } from "./runtime/context.js";
@@ -1,4 +1,5 @@
1
- import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, Message, ProviderDescriptor, ProviderReplay } from "../types.js";
1
+ import type { PreparedProviderRequest, ProviderRunState } from "../types.js";
2
+ import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, ProviderMessage, ProviderDescriptor, ProviderReplay } from "../types.js";
2
3
  export declare class AnthropicProvider implements LLMProvider {
3
4
  private readonly apiKey;
4
5
  private readonly model;
@@ -15,9 +16,11 @@ export declare class AnthropicProvider implements LLMProvider {
15
16
  baseURL: string;
16
17
  };
17
18
  };
18
- peekProviderReplay(message: Pick<Message, "content" | "toolCalls">): ProviderReplay | undefined;
19
- seedProviderReplay(message: Pick<Message, "content" | "toolCalls">, replay: ProviderReplay): void;
20
- complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
21
- stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, _state?: unknown, signal?: AbortSignal): AsyncIterable<StreamEvent>;
19
+ peekProviderReplay(message: Pick<ProviderMessage, "content" | "toolCalls">): ProviderReplay | undefined;
20
+ seedProviderReplay(message: Pick<ProviderMessage, "content" | "toolCalls">, replay: ProviderReplay): void;
21
+ complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<ProviderMessage>;
22
+ prepareRequest(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): PreparedProviderRequest;
23
+ stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState, signal?: AbortSignal): AsyncIterable<StreamEvent>;
24
+ private streamBody;
22
25
  private rememberNativeBlocks;
23
26
  }
@@ -1,3 +1,4 @@
1
+ import { requestSnapshot } from "./prepared-request.js";
1
2
  import { assistantReplayKey, collectStreamMessage, toAnthropicMessages } from "./base.js";
2
3
  /** Anthropic accepts at most this many cache_control breakpoints per request. */
3
4
  const MAX_CACHE_BREAKPOINTS = 4;
@@ -160,7 +161,7 @@ export class AnthropicProvider {
160
161
  async complete(context, tools, extensions) {
161
162
  return collectStreamMessage(this.stream(context, tools, extensions));
162
163
  }
163
- async *stream(context, tools, extensions, _state, signal) {
164
+ prepareRequest(context, tools, extensions, state) {
164
165
  const strategy = resolveCacheBreakpointStrategy(extensions);
165
166
  const emitOnSystemBlocks = strategy === "default" || strategy === "system-only";
166
167
  const cc = { type: "ephemeral" };
@@ -198,6 +199,16 @@ export class AnthropicProvider {
198
199
  if (extensions?.enable_thinking) {
199
200
  body.thinking = { type: "enabled", budget_tokens: 8000 };
200
201
  }
202
+ const frozenBody = requestSnapshot(body);
203
+ return {
204
+ scope: "encoded_body", request: requestSnapshot(frozenBody), state: requestSnapshot(state ?? null),
205
+ stream: signal => this.streamBody(frozenBody, slotBp, signal),
206
+ };
207
+ }
208
+ async *stream(context, tools, extensions, state, signal) {
209
+ yield* this.prepareRequest(context, tools, extensions, state).stream(signal);
210
+ }
211
+ async *streamBody(body, slotBp, signal) {
201
212
  const resp = await fetch("https://api.anthropic.com/v1/messages", {
202
213
  method: "POST",
203
214
  headers: {
@@ -1,4 +1,4 @@
1
- import type { Message, RenderedContext } from "../types.js";
1
+ import type { ProviderMessage, RenderedContext } from "../types.js";
2
2
  import { assistantReplayKey } from "../runtime/provider-replay.js";
3
3
  export declare class UnsupportedModalityError extends Error {
4
4
  readonly modality: string;
@@ -9,16 +9,16 @@ export declare class UnsupportedModalityError extends Error {
9
9
  * (OpenAI), keeping the history a stable cacheable prefix. Anthropic appends it
10
10
  * after the cache breakpoint. Absent on un-rebuilt bindings — then the state is
11
11
  * already inside `turns`. */
12
- export declare function turnsWithStateAppended(context: RenderedContext): Message[];
12
+ export declare function turnsWithStateAppended(context: RenderedContext): ProviderMessage[];
13
13
  /** Build OpenAI-compatible chat messages from a RenderedContext. */
14
14
  export declare function toOpenAIMessages(context: RenderedContext): Array<Record<string, unknown>>;
15
- export declare function toAnthropicMessages(context: RenderedContext, nativeReplay?: (message: Message) => Array<Record<string, unknown>> | undefined): Array<Record<string, unknown>>;
16
- /** Collect a non-streaming assistant Message from stream events. */
15
+ export declare function toAnthropicMessages(context: RenderedContext, nativeReplay?: (message: ProviderMessage) => Array<Record<string, unknown>> | undefined): Array<Record<string, unknown>>;
16
+ /** Collect a non-streaming assistant ProviderMessage from stream events. */
17
17
  export declare function collectStreamMessage(stream: AsyncIterable<{
18
18
  type: string;
19
19
  delta?: string;
20
20
  id?: string;
21
21
  name?: string;
22
22
  arguments?: Record<string, unknown>;
23
- }>): Promise<Message>;
23
+ }>): Promise<ProviderMessage>;
24
24
  export { assistantReplayKey };
@@ -135,7 +135,7 @@ export function toAnthropicMessages(context, nativeReplay) {
135
135
  }
136
136
  return result;
137
137
  }
138
- /** Collect a non-streaming assistant Message from stream events. */
138
+ /** Collect a non-streaming assistant ProviderMessage from stream events. */
139
139
  export async function collectStreamMessage(stream) {
140
140
  let content = "";
141
141
  const toolCalls = [];
@@ -1,4 +1,5 @@
1
- import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, Message, ProviderDescriptor } from "../types.js";
1
+ import type { PreparedProviderRequest, ProviderRunState } from "../types.js";
2
+ import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, ProviderMessage, ProviderDescriptor } from "../types.js";
2
3
  type OpenAIProviderDialect = "openai" | "qwen" | "deepseek" | "minimax";
3
4
  export interface OpenAIProviderOptions {
4
5
  apiKey: string;
@@ -41,9 +42,10 @@ export declare class OpenAIProvider implements LLMProvider {
41
42
  parameters: any;
42
43
  };
43
44
  }[];
44
- complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
45
- protected streamInner(context: RenderedContext, tools: ToolSchema[], extraBody: Record<string, unknown>, exposeReasoning?: boolean, signal?: AbortSignal): AsyncIterable<StreamEvent>;
46
- stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, _state?: unknown, signal?: AbortSignal): AsyncIterable<StreamEvent>;
45
+ complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<ProviderMessage>;
46
+ private streamBody;
47
+ prepareRequest(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): PreparedProviderRequest;
48
+ stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState, signal?: AbortSignal): AsyncIterable<StreamEvent>;
47
49
  }
48
50
  export declare function qwen(options: BackendProviderOptions): LLMProvider;
49
51
  export declare function deepseek(options: BackendProviderOptions): LLMProvider;
@@ -1,3 +1,4 @@
1
+ import { requestSnapshot } from "./prepared-request.js";
1
2
  import { collectStreamMessage, toOpenAIMessages } from "./base.js";
2
3
  const DEEPSEEK_REASONERS = new Set(["deepseek-reasoner", "deepseek-r1"]);
3
4
  const MINIMAX_REASONERS = new Set(["MiniMax-M1", "minimax-m1"]);
@@ -42,14 +43,7 @@ export class OpenAIProvider {
42
43
  async complete(context, tools, extensions) {
43
44
  return collectStreamMessage(this.stream(context, tools, extensions));
44
45
  }
45
- async *streamInner(context, tools, extraBody, exposeReasoning = false, signal) {
46
- const body = {
47
- model: this.model,
48
- messages: toOpenAIMessages(context),
49
- stream: true,
50
- ...(tools.length ? { tools: this.buildTools(tools) } : {}),
51
- ...extraBody,
52
- };
46
+ async *streamBody(body, exposeReasoning = false, signal) {
53
47
  const resp = await fetch(`${this.baseUrl}/chat/completions`, {
54
48
  method: "POST",
55
49
  headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
@@ -116,28 +110,38 @@ export class OpenAIProvider {
116
110
  yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
117
111
  }
118
112
  }
119
- async *stream(context, tools, extensions, _state, signal) {
113
+ prepareRequest(context, tools, extensions, state) {
114
+ let requestTools = tools;
115
+ let extraBody;
116
+ let exposeReasoning = false;
120
117
  if (this.dialect === "qwen") {
121
118
  const enableThinking = Boolean(extensions?.enableThinking);
122
119
  const thinkingBudget = extensions?.thinkingBudget;
123
120
  const { enableThinking: _, thinkingBudget: __, expose_reasoning: ___, exposeReasoning: ____, ...passthrough } = extensions ?? {};
124
- yield* this.streamInner(context, tools, {
125
- ...passthrough,
126
- ...(enableThinking ? { enable_thinking: true, ...(thinkingBudget ? { thinking_budget: thinkingBudget } : {}) } : {}),
127
- }, enableThinking, signal);
128
- return;
121
+ extraBody = { ...passthrough, ...(enableThinking ? { enable_thinking: true, ...(thinkingBudget ? { thinking_budget: thinkingBudget } : {}) } : {}) };
122
+ exposeReasoning = enableThinking;
129
123
  }
130
- if (this.dialect === "deepseek" || this.dialect === "minimax") {
131
- const exposeReasoning = Boolean(extensions?.exposeReasoning);
132
- const isReasoner = this.dialect === "deepseek"
133
- ? DEEPSEEK_REASONERS.has(this.model)
134
- : MINIMAX_REASONERS.has(this.model);
135
- const { exposeReasoning: _, expose_reasoning: __, ...passthrough } = extensions ?? {};
136
- yield* this.streamInner(context, isReasoner ? [] : tools, passthrough, exposeReasoning, signal);
137
- return;
124
+ else {
125
+ const { expose_reasoning: _, exposeReasoning: __, ...passthrough } = extensions ?? {};
126
+ extraBody = passthrough;
127
+ if (this.dialect === "deepseek" || this.dialect === "minimax") {
128
+ exposeReasoning = Boolean(extensions?.exposeReasoning);
129
+ const isReasoner = this.dialect === "deepseek" ? DEEPSEEK_REASONERS.has(this.model) : MINIMAX_REASONERS.has(this.model);
130
+ if (isReasoner)
131
+ requestTools = [];
132
+ }
138
133
  }
139
- const { expose_reasoning: _, exposeReasoning: __, ...passthrough } = extensions ?? {};
140
- yield* this.streamInner(context, tools, passthrough, false, signal);
134
+ const body = requestSnapshot({
135
+ model: this.model, messages: toOpenAIMessages(context), stream: true,
136
+ ...(requestTools.length ? { tools: this.buildTools(requestTools) } : {}), ...extraBody,
137
+ });
138
+ return {
139
+ scope: "encoded_body", request: requestSnapshot(body), state: requestSnapshot(state ?? null),
140
+ stream: signal => this.streamBody(body, exposeReasoning, signal),
141
+ };
142
+ }
143
+ async *stream(context, tools, extensions, state, signal) {
144
+ yield* this.prepareRequest(context, tools, extensions, state).stream(signal);
141
145
  }
142
146
  }
143
147
  export function qwen(options) {
@@ -0,0 +1,4 @@
1
+ import type { LLMProvider, PreparedProviderRequest, ProviderRunState, RenderedContext, ToolSchema } from "../types.js";
2
+ /** JSON value snapshots sever aliases to mutable provider replay and continuation state. */
3
+ export declare function requestSnapshot<T>(value: T): T;
4
+ export declare function prepareProviderRequest(provider: LLMProvider, context: RenderedContext, tools: ToolSchema[], options?: Record<string, unknown>, state?: ProviderRunState): PreparedProviderRequest;
@@ -0,0 +1,78 @@
1
+ import { materialOptions } from "./request-plan.js";
2
+ /** JSON value snapshots sever aliases to mutable provider replay and continuation state. */
3
+ export function requestSnapshot(value) {
4
+ return value === undefined ? value : JSON.parse(JSON.stringify(value));
5
+ }
6
+ /** A fallback can freeze only JSON state without silently discarding execution semantics. */
7
+ function assertJsonRunState(state) {
8
+ if (state === undefined)
9
+ return;
10
+ const seen = new WeakSet();
11
+ const reject = (path) => {
12
+ throw new TypeError(`Custom provider state at ${path} is not losslessly JSON representable; implement prepareRequest() for opaque state`);
13
+ };
14
+ const visit = (value, path) => {
15
+ if (value === null || typeof value === "string" || typeof value === "boolean")
16
+ return;
17
+ if (typeof value === "number") {
18
+ if (!Number.isFinite(value) || Object.is(value, -0))
19
+ reject(path);
20
+ return;
21
+ }
22
+ if (typeof value !== "object")
23
+ reject(path);
24
+ const object = value;
25
+ if (seen.has(object))
26
+ reject(path);
27
+ seen.add(object);
28
+ const array = Array.isArray(object);
29
+ if (!array && Object.getPrototypeOf(object) !== Object.prototype && Object.getPrototypeOf(object) !== null)
30
+ reject(path);
31
+ if (Object.getOwnPropertySymbols(object).length)
32
+ reject(path);
33
+ const descriptors = Object.getOwnPropertyDescriptors(object);
34
+ if (array) {
35
+ const values = object;
36
+ for (let index = 0; index < values.length; index++) {
37
+ if (!Object.hasOwn(descriptors, String(index)))
38
+ reject(`${path}[${index}]`);
39
+ }
40
+ }
41
+ for (const [key, descriptor] of Object.entries(descriptors)) {
42
+ if (array && key === "length")
43
+ continue;
44
+ if (array && (!/^(0|[1-9]\d*)$/.test(key) || Number(key) >= object.length))
45
+ reject(`${path}.${key}`);
46
+ if (!descriptor.enumerable || !("value" in descriptor))
47
+ reject(`${path}.${key}`);
48
+ visit(descriptor.value, `${path}.${key}`);
49
+ }
50
+ };
51
+ visit(state, "state");
52
+ }
53
+ export function prepareProviderRequest(provider, context, tools, options, state) {
54
+ if (provider.prepareRequest)
55
+ return provider.prepareRequest(context, tools, options, state);
56
+ assertJsonRunState(state);
57
+ const input = requestSnapshot({ context, tools, options, state });
58
+ const replay = context.turns.map(message => provider.peekProviderReplay?.(message) ?? null);
59
+ const frozenState = input.state;
60
+ return {
61
+ scope: "adapter_input",
62
+ request: requestSnapshot({ context: input.context, tools: input.tools, options: materialOptions(input.options ?? {}), replay }),
63
+ state: requestSnapshot(frozenState ?? null),
64
+ ...(provider.countTokens ? { countTokens: () => {
65
+ const counted = requestSnapshot(input);
66
+ return provider.countTokens(counted.context, counted.tools, counted.options, counted.state);
67
+ } } : {}),
68
+ async *stream(signal) {
69
+ // Keep the run-state object's identity while restoring the frozen preflight input.
70
+ if (state && frozenState && typeof state === "object" && typeof frozenState === "object") {
71
+ for (const key of Object.keys(state))
72
+ delete state[key];
73
+ Object.assign(state, requestSnapshot(frozenState));
74
+ }
75
+ yield* provider.stream(input.context, input.tools, input.options, state ?? frozenState, signal);
76
+ },
77
+ };
78
+ }
@@ -5,6 +5,11 @@ export interface ProviderRequestEndpoint {
5
5
  baseURL: string;
6
6
  }
7
7
  export interface ProviderRequestPlan {
8
+ execution?: {
9
+ scope: "encoded_body" | "adapter_input";
10
+ request: unknown;
11
+ state: unknown;
12
+ };
8
13
  providerId: string;
9
14
  modelId: string;
10
15
  endpoint: ProviderRequestEndpoint;
@@ -38,6 +43,7 @@ export interface ProviderUsage {
38
43
  }
39
44
  /** P4 §1.3 mirror of the node ResolvedProviderRoute (content-addressed route evidence). */
40
45
  export interface ResolvedProviderRoute {
46
+ request_fingerprint_scope?: "encoded_body" | "adapter_input";
41
47
  routeId: string;
42
48
  provider: string;
43
49
  protocol: ProviderProtocol;
@@ -90,11 +96,12 @@ export declare function createProviderRequestPlanForProvider(provider: {
90
96
  baseURL?: string;
91
97
  };
92
98
  };
93
- }, context: RenderedContext, tools: ToolSchema[], options?: Record<string, unknown>): ProviderRequestPlan;
99
+ }, context: RenderedContext, tools: ToolSchema[], options?: Record<string, unknown>, execution?: ProviderRequestPlan["execution"]): ProviderRequestPlan;
94
100
  export declare function recordPromptMeasurement(plan: Pick<ProviderRequestPlan, "fingerprint">, measurement: Omit<RecordedPromptMeasurement, "requestFingerprint">): RecordedPromptMeasurement;
95
101
  export declare function measurementForPlan(plan: Pick<ProviderRequestPlan, "fingerprint">, record: RecordedPromptMeasurement | undefined): RecordedPromptMeasurement | undefined;
96
102
  export declare function normalizeProviderUsage(usage: ProviderUsage): NormalizedProviderUsage;
97
103
  export declare function priceProviderUsage(usage: NormalizedProviderUsage, snapshot: PricingSnapshot, observedAt?: string | Date): CostObservation;
104
+ export declare function materialOptions(options: Record<string, unknown>): Record<string, unknown>;
98
105
  /**
99
106
  * P4-S1: assemble the run's route once at runner construction (P4 §0.2 — the provider is
100
107
  * fixed for the run today; a future failover resolver re-evaluates per attempt with the same
@@ -9,10 +9,11 @@ export function createProviderRequestPlan(input) {
9
9
  const value = {
10
10
  providerId: input.providerId, modelId: input.modelId, endpoint: sanitizeEndpoint(input.endpoint),
11
11
  context: clone(input.context), tools: clone(input.tools), options: materialOptions(input.options ?? {}),
12
+ ...(input.execution ? { execution: clone(input.execution) } : {}),
12
13
  };
13
14
  return { ...value, fingerprint: sha256Hex(stableJson(value)) };
14
15
  }
15
- export function createProviderRequestPlanForProvider(provider, context, tools, options) {
16
+ export function createProviderRequestPlanForProvider(provider, context, tools, options, execution) {
16
17
  const descriptor = provider.descriptor?.() ?? { provider: "unknown", protocol: "unknown", model: "unknown" };
17
18
  const identity = provider.requestPlanIdentity?.();
18
19
  return createProviderRequestPlan({
@@ -23,7 +24,7 @@ export function createProviderRequestPlanForProvider(provider, context, tools, o
23
24
  protocol: identity?.endpoint?.protocol ?? descriptor.protocol,
24
25
  baseURL: identity?.endpoint?.baseURL ?? "",
25
26
  },
26
- context, tools, options,
27
+ context, tools, options, execution,
27
28
  });
28
29
  }
29
30
  export function recordPromptMeasurement(plan, measurement) {
@@ -90,7 +91,7 @@ export function priceProviderUsage(usage, snapshot, observedAt = new Date()) {
90
91
  + (usage.reasoningTokens ?? 0) * (rates.reasoning ?? 0)) / 1_000_000;
91
92
  return { source: "snapshot", currency: snapshot.currency, amount, pricingVersion: snapshot.version };
92
93
  }
93
- function materialOptions(options) {
94
+ export function materialOptions(options) {
94
95
  return sanitizeMaterialValue(options);
95
96
  }
96
97
  function sanitizeEndpoint(endpoint) {
@@ -1,5 +1,5 @@
1
1
  import type { CanonicalKernel as CanonicalKernelInstance, CanonicalRestoreCost } from "@deepstrike/wasm-kernel";
2
- import type { Message } from "../types.js";
2
+ import type { ProviderMessage } from "../types.js";
3
3
  import { type InstalledCheckpoint, type KernelJournal } from "./kernel-journal.js";
4
4
  import { type KernelObservation, type KernelRunnerAction } from "./kernel-step.js";
5
5
  export declare const MAX_CHAIN_POSITION = 1000000000000;
@@ -37,7 +37,7 @@ export interface CanonicalTransition {
37
37
  replayed: boolean;
38
38
  }
39
39
  export declare function canonicalUnsupportedEffectResolution(effectId: string, effectKind: string): CanonicalKernelInput;
40
- /** Adapt the additive core CurrentProjection JSON into the existing WASM action surface. */
40
+ /** Adapt the core-owned KernelProjection JSON into the WASM action surface. */
41
41
  export declare function canonicalActionFromProjectionJson(raw: string): KernelRunnerAction | null;
42
42
  export declare class CanonicalKernelRejectedError extends Error {
43
43
  readonly fault: Record<string, unknown>;
@@ -85,6 +85,7 @@ export interface CanonicalRunnerRuntimeOptions {
85
85
  maxTurns?: number;
86
86
  maxTotalTokens?: number;
87
87
  maxWallMs?: number;
88
+ artifactSetDigest?: string;
88
89
  memoryBindingId?: string;
89
90
  persistPayload?: (callId: string, content: string, previewBytes: number) => Promise<{
90
91
  payloadRef: string;
@@ -120,7 +121,7 @@ export declare class CanonicalRunnerRuntime {
120
121
  isTerminal(): boolean;
121
122
  recoveryContentBytes(): number;
122
123
  preservedRefs(): string[];
123
- drainNewMessages(): Message[];
124
+ drainNewMessages(): ProviderMessage[];
124
125
  drainHostObservations(): KernelObservationLike[];
125
126
  terminal(): Record<string, unknown> | undefined;
126
127
  localSubagentsSpawned(): number;
@@ -66,7 +66,7 @@ function canonicalDoneFromTerminal(terminal) {
66
66
  termination = asObject(terminal.failure).code === "provider_recovery_exhausted" ? "context_overflow" : "error";
67
67
  return { kind: "done", effectId: "", result: { termination, turnsUsed, totalTokensUsed: totalUsageTokens(terminal) } };
68
68
  }
69
- /** Adapt the additive core CurrentProjection JSON into the existing WASM action surface. */
69
+ /** Adapt the core-owned KernelProjection JSON into the WASM action surface. */
70
70
  export function canonicalActionFromProjectionJson(raw) {
71
71
  const projection = asObject(JSON.parse(raw));
72
72
  const state = String(projection.state ?? "idle");
@@ -106,6 +106,7 @@ export function canonicalActionFromProjectionJson(raw) {
106
106
  kind: "call_provider",
107
107
  effectId,
108
108
  context: renderedContextToSdk(context),
109
+ contextEffect: payload,
109
110
  tools: (Array.isArray(payload.tools) ? payload.tools : []).map(raw => {
110
111
  const tool = asObject(raw);
111
112
  return {
@@ -664,6 +665,9 @@ export class CanonicalRunnerRuntime {
664
665
  this.host = new CanonicalKernelHost(kernel, journal, operationId);
665
666
  this.memoryBindingId = options.memoryBindingId ?? "wasm-memory";
666
667
  this.config = {
668
+ ...(options.artifactSetDigest
669
+ ? { artifact_set_binding: { artifact_set_digest: options.artifactSetDigest } }
670
+ : {}),
667
671
  execution_policy: {
668
672
  max_context_tokens: options.maxContextTokens,
669
673
  ...(options.maxTurns !== undefined ? { max_turns: options.maxTurns } : {}),
@@ -842,12 +846,16 @@ export class CanonicalRunnerRuntime {
842
846
  }
843
847
  case "tool_results": {
844
848
  const results = [];
849
+ const measurements = [];
845
850
  for (const value of Array.isArray(event.results) ? event.results : []) {
846
851
  const result = asObject(value);
847
852
  const callId = String(result.call_id ?? "");
848
853
  const output = String(result.output ?? "");
849
854
  const isError = Boolean(result.is_error);
850
855
  const disposition = result.is_fatal ? "fatal" : "recoverable";
856
+ if (result.token_count !== null && result.token_count !== undefined) {
857
+ measurements.push({ call_id: callId, tokens: Number(result.token_count) });
858
+ }
851
859
  const bytes = utf8ByteLength(output);
852
860
  if (bytes > this.payloadInlineThreshold && this.options.persistPayload) {
853
861
  const persisted = await this.options.persistPayload(callId, output, this.payloadPreviewBytes);
@@ -870,15 +878,16 @@ export class CanonicalRunnerRuntime {
870
878
  output,
871
879
  ...(isError ? { is_error: true } : {}),
872
880
  disposition,
873
- ...(result.token_count !== null && result.token_count !== undefined
874
- ? { tokens: Number(result.token_count) }
875
- : {}),
876
881
  },
877
882
  });
878
883
  }
879
884
  this.newMessages.push({ role: "tool", content: output, toolCalls: [] });
880
885
  }
881
- input = this.succeededEffect(event, { kind: "tools", results });
886
+ input = this.succeededEffect(event, {
887
+ kind: "tools",
888
+ results,
889
+ ...(measurements.length > 0 ? { measurements } : {}),
890
+ });
882
891
  break;
883
892
  }
884
893
  case "approval_result":
@@ -1072,7 +1081,7 @@ export class CanonicalRunnerRuntime {
1072
1081
  input = { kind: "host_control", command: this.canonicalCapabilityCommand(asObject(event.command)) };
1073
1082
  break;
1074
1083
  case "add_history_message":
1075
- throw new Error("running ABI v3 operations accept history only through effects or external events");
1084
+ throw new Error("running ABI operations accept history only through effects or external events");
1076
1085
  default:
1077
1086
  throw new Error(`WASM host fact has no canonical ABI input: ${String(event.kind)}`);
1078
1087
  }
@@ -1142,7 +1151,7 @@ export class CanonicalRunnerRuntime {
1142
1151
  }
1143
1152
  }
1144
1153
  currentAction() {
1145
- return canonicalActionFromProjectionJson(this.host.kernel.currentProjectionJson());
1154
+ return canonicalActionFromProjectionJson(this.host.kernel.projectionJson());
1146
1155
  }
1147
1156
  pendingEffects() {
1148
1157
  return JSON.parse(this.host.kernel.pendingEffectsJson());
@@ -0,0 +1,28 @@
1
+ import type { RecordedPromptMeasurement, ResolvedProviderRoute } from "../providers/request-plan.js";
2
+ import type { ContextExecutionInput, ContextPlan, ContextState, EvaluationContextBinding } from "./evolution.js";
3
+ /** Host evidence completing the kernel's immutable context candidate. */
4
+ export interface ContextProviderPreparationRequest {
5
+ readonly effect: Record<string, unknown>;
6
+ readonly request_fingerprint: string;
7
+ readonly provider_route: ResolvedProviderRoute;
8
+ readonly prompt_measurement: RecordedPromptMeasurement;
9
+ }
10
+ export interface ContextPrepared {
11
+ readonly state: ContextState;
12
+ readonly provider_route: ResolvedProviderRoute;
13
+ readonly prompt_measurement: RecordedPromptMeasurement;
14
+ readonly execution_input: ContextExecutionInput;
15
+ readonly plan: ContextPlan;
16
+ readonly binding: EvaluationContextBinding;
17
+ }
18
+ export type ContextPrepareJson = (request: string) => string;
19
+ export type ContextVerifyJson = (request: string) => string;
20
+ /** All validation and content addressing are delegated to the Rust authority. */
21
+ export declare function createContextPreparationAdapter(prepareJson: ContextPrepareJson, verifyJson: ContextVerifyJson): {
22
+ verify(effect: Record<string, unknown>, preparation: ContextPrepared): boolean;
23
+ prepare(request: ContextProviderPreparationRequest): ContextPrepared;
24
+ };
25
+ export declare function createNativeContextPreparationAdapter(): Promise<{
26
+ verify(effect: Record<string, unknown>, preparation: ContextPrepared): boolean;
27
+ prepare(request: ContextProviderPreparationRequest): ContextPrepared;
28
+ }>;
@@ -0,0 +1,16 @@
1
+ import { getKernel } from "./kernel.js";
2
+ /** All validation and content addressing are delegated to the Rust authority. */
3
+ export function createContextPreparationAdapter(prepareJson, verifyJson) {
4
+ return {
5
+ verify(effect, preparation) {
6
+ return JSON.parse(verifyJson(JSON.stringify({ effect, preparation })));
7
+ },
8
+ prepare(request) {
9
+ return JSON.parse(prepareJson(JSON.stringify(request)));
10
+ },
11
+ };
12
+ }
13
+ export async function createNativeContextPreparationAdapter() {
14
+ const kernel = await getKernel();
15
+ return createContextPreparationAdapter(kernel.contextPrepareJson, kernel.contextVerifyJson);
16
+ }
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * See node/src/runtime/eval.ts for the full design rationale.
9
9
  */
10
- import type { LLMProvider, Message } from "../types.js";
10
+ import type { LLMProvider, ProviderMessage } from "../types.js";
11
11
  export interface Criterion {
12
12
  text: string;
13
13
  required?: boolean;
@@ -35,7 +35,7 @@ export interface JudgeArgs {
35
35
  signal?: AbortSignal;
36
36
  }
37
37
  /** Build the kernel's eval prompt for (goal, criteria, result). Async — the WASM kernel loads lazily. */
38
- export declare function buildEvalMessages(goal: string, criteria: Criterion[], result: string): Promise<Message[]>;
38
+ export declare function buildEvalMessages(goal: string, criteria: Criterion[], result: string): Promise<ProviderMessage[]>;
39
39
  /** Parse a Verdict from raw judge-LLM text. */
40
40
  export declare function parseVerdict(text: string): Promise<Verdict>;
41
41
  /** The JSON Schema the kernel expects judge output to conform to. */