@deepstrike/wasm 0.2.66 → 0.2.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/memory/index.d.ts +0 -1
- package/dist/providers/base.js +8 -10
- package/dist/runtime/kernel-step.js +5 -12
- package/dist/runtime/replay-fixture.d.ts +2 -3
- package/dist/runtime/replay-fixture.js +2 -5
- package/dist/runtime/replay-provider.d.ts +1 -2
- package/dist/runtime/replay-provider.js +2 -4
- package/dist/runtime/runner.js +2 -12
- package/dist/runtime/session-repair.d.ts +1 -1
- package/dist/runtime/session-repair.js +2 -5
- package/dist/runtime/types/agent.d.ts +0 -1
- package/dist/runtime/types/agent.js +0 -2
- package/dist/runtime/verifiable-report.d.ts +59 -0
- package/dist/runtime/verifiable-report.js +64 -0
- package/dist/types.d.ts +1 -6
- 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";
|
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";
|
package/dist/memory/index.d.ts
CHANGED
package/dist/providers/base.js
CHANGED
|
@@ -31,16 +31,16 @@ function openaiAudioFormat(mediaType) {
|
|
|
31
31
|
function openAIPartsContent(parts) {
|
|
32
32
|
return parts.map(p => {
|
|
33
33
|
if (p.type === "image") {
|
|
34
|
-
const url = p.
|
|
34
|
+
const url = p.source?.kind === "base64" ? `data:${p.mediaType ?? "image/png"};base64,${p.source.data}` : p.source?.kind === "url" ? p.source.url : "";
|
|
35
35
|
return { type: "image_url", image_url: { url, ...(p.detail ? { detail: p.detail } : {}) } };
|
|
36
36
|
}
|
|
37
37
|
if (p.type === "audio") {
|
|
38
38
|
// OpenAI audio has no URL form — a part without base64 data cannot be sent.
|
|
39
|
-
if (
|
|
40
|
-
throw new UnsupportedModalityError("audio (no
|
|
39
|
+
if (p.source?.kind !== "base64")
|
|
40
|
+
throw new UnsupportedModalityError("audio (no durable base64 source)", "openai");
|
|
41
41
|
return {
|
|
42
42
|
type: "input_audio",
|
|
43
|
-
input_audio: { data: p.data, format: openaiAudioFormat(p.mediaType) },
|
|
43
|
+
input_audio: { data: p.source.data, format: openaiAudioFormat(p.mediaType) },
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
return { type: "text", text: p.text ?? p.output ?? "" };
|
|
@@ -50,9 +50,9 @@ function openAIPartsContent(parts) {
|
|
|
50
50
|
function anthropicPartsContent(parts) {
|
|
51
51
|
return parts.map(p => {
|
|
52
52
|
if (p.type === "image") {
|
|
53
|
-
const source = p.
|
|
54
|
-
? { type: "base64", media_type: p.mediaType ?? "image/png", data: p.data }
|
|
55
|
-
: { type: "url", url: p.url
|
|
53
|
+
const source = p.source?.kind === "base64"
|
|
54
|
+
? { type: "base64", media_type: p.mediaType ?? "image/png", data: p.source.data }
|
|
55
|
+
: { type: "url", url: p.source?.kind === "url" ? p.source.url : "" };
|
|
56
56
|
return { type: "image", source };
|
|
57
57
|
}
|
|
58
58
|
if (p.type === "audio") {
|
|
@@ -139,7 +139,6 @@ export function toAnthropicMessages(context, nativeReplay) {
|
|
|
139
139
|
export async function collectStreamMessage(stream) {
|
|
140
140
|
let content = "";
|
|
141
141
|
const toolCalls = [];
|
|
142
|
-
let outputTokens;
|
|
143
142
|
for await (const evt of stream) {
|
|
144
143
|
if (evt.type === "text_delta" && evt.delta)
|
|
145
144
|
content += evt.delta;
|
|
@@ -147,9 +146,8 @@ export async function collectStreamMessage(stream) {
|
|
|
147
146
|
toolCalls.push({ id: evt.id, name: evt.name, arguments: JSON.stringify(evt.arguments ?? {}) });
|
|
148
147
|
}
|
|
149
148
|
else if (evt.type === "usage") {
|
|
150
|
-
outputTokens = evt.outputTokens ?? evt.totalTokens;
|
|
151
149
|
}
|
|
152
150
|
}
|
|
153
|
-
return { role: "assistant", content, ...(
|
|
151
|
+
return { role: "assistant", content, ...(toolCalls.length ? { toolCalls } : {}) };
|
|
154
152
|
}
|
|
155
153
|
export { assistantReplayKey };
|
|
@@ -85,9 +85,6 @@ export function messageToKernelMessage(message) {
|
|
|
85
85
|
arguments: tryParseJson(tc.arguments) ?? {},
|
|
86
86
|
})),
|
|
87
87
|
};
|
|
88
|
-
if (message.tokenCount !== undefined) {
|
|
89
|
-
out.token_count = message.tokenCount;
|
|
90
|
-
}
|
|
91
88
|
// Multimodal: serialize typed content parts to the kernel `Content::Parts` shape when present
|
|
92
89
|
// (image/audio must survive the reconstruction→preload path, not just live ingress).
|
|
93
90
|
if (message.contentParts && message.contentParts.length > 0) {
|
|
@@ -98,10 +95,10 @@ export function messageToKernelMessage(message) {
|
|
|
98
95
|
return { type: "tool_result", call_id: part.callId, output: part.output, is_error: part.isError };
|
|
99
96
|
}
|
|
100
97
|
if (part.type === "image") {
|
|
101
|
-
return { type: "image",
|
|
98
|
+
return { type: "image", source: part.source, media_type: part.mediaType, detail: part.detail };
|
|
102
99
|
}
|
|
103
100
|
if (part.type === "audio") {
|
|
104
|
-
return { type: "audio",
|
|
101
|
+
return { type: "audio", source: part.source, media_type: part.mediaType };
|
|
105
102
|
}
|
|
106
103
|
return { type: "text", text: message.content };
|
|
107
104
|
});
|
|
@@ -112,12 +109,12 @@ export function messageToKernelMessage(message) {
|
|
|
112
109
|
return out;
|
|
113
110
|
}
|
|
114
111
|
export function toolResultToKernel(result) {
|
|
112
|
+
// Usage evidence enters through the host event contract; content alone cannot establish usage.
|
|
115
113
|
const out = {
|
|
116
114
|
call_id: result.callId,
|
|
117
115
|
output: result.output,
|
|
118
116
|
is_error: result.isError,
|
|
119
117
|
is_fatal: result.isFatal ?? false,
|
|
120
|
-
token_count: result.tokenCount ?? null,
|
|
121
118
|
};
|
|
122
119
|
if (result.errorKind !== undefined) {
|
|
123
120
|
out.error_kind = result.errorKind;
|
|
@@ -173,9 +170,6 @@ export function kernelMessageToSdk(raw) {
|
|
|
173
170
|
arguments: JSON.stringify(tc.arguments ?? {}),
|
|
174
171
|
})),
|
|
175
172
|
};
|
|
176
|
-
if (typeof raw.token_count === "number") {
|
|
177
|
-
message.tokenCount = raw.token_count;
|
|
178
|
-
}
|
|
179
173
|
if (typeof content === "string") {
|
|
180
174
|
const parts = decodeCanonicalContentParts(content);
|
|
181
175
|
if (parts) {
|
|
@@ -196,8 +190,7 @@ export function kernelMessageToSdk(raw) {
|
|
|
196
190
|
case "image":
|
|
197
191
|
contentParts.push({
|
|
198
192
|
type: "image",
|
|
199
|
-
...(part.
|
|
200
|
-
...(part.data ? { data: String(part.data) } : {}),
|
|
193
|
+
...(part.source ? { source: part.source } : {}),
|
|
201
194
|
...(part.media_type ? { mediaType: String(part.media_type) } : {}),
|
|
202
195
|
...(part.detail === "auto" || part.detail === "low" || part.detail === "high"
|
|
203
196
|
? { detail: part.detail }
|
|
@@ -207,7 +200,7 @@ export function kernelMessageToSdk(raw) {
|
|
|
207
200
|
case "audio":
|
|
208
201
|
contentParts.push({
|
|
209
202
|
type: "audio",
|
|
210
|
-
|
|
203
|
+
source: part.source,
|
|
211
204
|
...(part.media_type ? { mediaType: String(part.media_type) } : {}),
|
|
212
205
|
});
|
|
213
206
|
break;
|
|
@@ -14,9 +14,8 @@ import type { SessionEvent } from "./session-log.js";
|
|
|
14
14
|
* Walks `llm_completed` events (which is what the runner appends for every LLM call) and produces
|
|
15
15
|
* one Message per event. Pass the result directly to `new ReplayProvider(messages)`.
|
|
16
16
|
*
|
|
17
|
-
* Accepts both wire shapes
|
|
18
|
-
*
|
|
19
|
-
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case)
|
|
17
|
+
* Accepts both camelCase and snake_case tool-call wire shapes. Token usage remains session
|
|
18
|
+
* evidence; the returned public Message mirror carries no token projection.
|
|
20
19
|
*
|
|
21
20
|
* @param events Session events, in original order. Accepts both `{ event, seq }` (the shape
|
|
22
21
|
* `SessionLog.read()` returns) and a bare `SessionEvent[]`.
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
* Walks `llm_completed` events (which is what the runner appends for every LLM call) and produces
|
|
13
13
|
* one Message per event. Pass the result directly to `new ReplayProvider(messages)`.
|
|
14
14
|
*
|
|
15
|
-
* Accepts both wire shapes
|
|
16
|
-
*
|
|
17
|
-
* - serialised session-log: `{ tool_calls, token_count, provider_replay }` (snake_case)
|
|
15
|
+
* Accepts both camelCase and snake_case tool-call wire shapes. Token usage remains session
|
|
16
|
+
* evidence; the returned public Message mirror carries no token projection.
|
|
18
17
|
*
|
|
19
18
|
* @param events Session events, in original order. Accepts both `{ event, seq }` (the shape
|
|
20
19
|
* `SessionLog.read()` returns) and a bare `SessionEvent[]`.
|
|
@@ -27,14 +26,12 @@ export function extractRecordedMessages(events) {
|
|
|
27
26
|
continue;
|
|
28
27
|
const e = event;
|
|
29
28
|
const tcRaw = (e.toolCalls ?? e.tool_calls);
|
|
30
|
-
const tokenCount = (e.tokenCount ?? e.token_count);
|
|
31
29
|
out.push({
|
|
32
30
|
role: "assistant",
|
|
33
31
|
content: typeof e.content === "string" ? e.content : "",
|
|
34
32
|
...(Array.isArray(tcRaw) && tcRaw.length > 0
|
|
35
33
|
? { toolCalls: normalizeToolCalls(tcRaw) }
|
|
36
34
|
: {}),
|
|
37
|
-
...(tokenCount !== undefined ? { tokenCount } : {}),
|
|
38
35
|
});
|
|
39
36
|
}
|
|
40
37
|
return out;
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
* - `inputTokens` is ESTIMATED from the rendered context this call carries (NOT a recorded value
|
|
17
17
|
* from the original run). That's the point of replay-for-benchmarking: prompt may differ across
|
|
18
18
|
* variants, response is pinned, so a cost Δ purely reflects the prompt change.
|
|
19
|
-
* - `outputTokens` is
|
|
20
|
-
* `message.content.length / 4`.
|
|
19
|
+
* - `outputTokens` is estimated from `message.content.length / 4`.
|
|
21
20
|
* - `cacheReadInputTokens` / `cacheCreationInputTokens` are emitted as 0 — replay has no real
|
|
22
21
|
* cache state. Mechanisms whose Δ depends on cache behavior must validate with a live A/B too.
|
|
23
22
|
*
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
* - `inputTokens` is ESTIMATED from the rendered context this call carries (NOT a recorded value
|
|
17
17
|
* from the original run). That's the point of replay-for-benchmarking: prompt may differ across
|
|
18
18
|
* variants, response is pinned, so a cost Δ purely reflects the prompt change.
|
|
19
|
-
* - `outputTokens` is
|
|
20
|
-
* `message.content.length / 4`.
|
|
19
|
+
* - `outputTokens` is estimated from `message.content.length / 4`.
|
|
21
20
|
* - `cacheReadInputTokens` / `cacheCreationInputTokens` are emitted as 0 — replay has no real
|
|
22
21
|
* cache state. Mechanisms whose Δ depends on cache behavior must validate with a live A/B too.
|
|
23
22
|
*
|
|
@@ -68,13 +67,12 @@ export class ReplayProvider {
|
|
|
68
67
|
role: "assistant",
|
|
69
68
|
content: msg.content,
|
|
70
69
|
...(msg.toolCalls ? { toolCalls: msg.toolCalls } : {}),
|
|
71
|
-
...(msg.tokenCount !== undefined ? { tokenCount: msg.tokenCount } : {}),
|
|
72
70
|
};
|
|
73
71
|
}
|
|
74
72
|
async *stream(context, tools, _extensions, _state, _signal) {
|
|
75
73
|
const msg = this.pull();
|
|
76
74
|
const inputTokens = this.estimateInputTokens(context, tools);
|
|
77
|
-
const outputTokens =
|
|
75
|
+
const outputTokens = this.tokenizer(msg.content || "");
|
|
78
76
|
const usage = {
|
|
79
77
|
type: "usage",
|
|
80
78
|
totalTokens: inputTokens + outputTokens,
|
package/dist/runtime/runner.js
CHANGED
|
@@ -869,7 +869,6 @@ export class RuntimeRunner {
|
|
|
869
869
|
role: "assistant",
|
|
870
870
|
content: finalText,
|
|
871
871
|
toolCalls: finalToolCalls,
|
|
872
|
-
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
873
872
|
};
|
|
874
873
|
// P4 §2: assemble the measurement from the exact numbers that cross the boundary today
|
|
875
874
|
// (input/output turn counters + the cache split). An invalid frame degrades to no
|
|
@@ -919,7 +918,6 @@ export class RuntimeRunner {
|
|
|
919
918
|
await this.opts.sessionLog.append(sessionId, buildLlmCompletedEvent({
|
|
920
919
|
turn: runtime.turn(),
|
|
921
920
|
content: finalText,
|
|
922
|
-
tokenCount: turnOutputTokens || turnTokens || undefined,
|
|
923
921
|
toolCalls: finalToolCalls,
|
|
924
922
|
providerReplay,
|
|
925
923
|
effectId: providerEffectId,
|
|
@@ -1213,7 +1211,6 @@ export class RuntimeRunner {
|
|
|
1213
1211
|
call_id: r.callId,
|
|
1214
1212
|
output: r.output,
|
|
1215
1213
|
is_error: r.isError,
|
|
1216
|
-
token_count: r.tokenCount,
|
|
1217
1214
|
content: { blocks: toolOutputBlocksToDurable(r.contentParts?.length ? r.contentParts : [{ type: "text", text: r.output }]) },
|
|
1218
1215
|
})),
|
|
1219
1216
|
});
|
|
@@ -1390,7 +1387,6 @@ export class RuntimeRunner {
|
|
|
1390
1387
|
const newMsgs = runtime.drainNewMessages().map(m => ({
|
|
1391
1388
|
role: m.role,
|
|
1392
1389
|
content: m.content,
|
|
1393
|
-
tokenCount: m.tokenCount,
|
|
1394
1390
|
toolCalls: m.toolCalls?.length ? m.toolCalls : undefined,
|
|
1395
1391
|
}));
|
|
1396
1392
|
if (newMsgs.length > 0) {
|
|
@@ -2027,7 +2023,6 @@ export async function replayMessages(events, maxBytes, archiveStore) {
|
|
|
2027
2023
|
content: userText,
|
|
2028
2024
|
...(contentParts ? { contentParts } : {}),
|
|
2029
2025
|
toolCalls: [],
|
|
2030
|
-
tokenCount: Math.max(1, Math.ceil(userText.length / 4)),
|
|
2031
2026
|
});
|
|
2032
2027
|
}
|
|
2033
2028
|
else if (e.kind === "compressed") {
|
|
@@ -2040,7 +2035,6 @@ export async function replayMessages(events, maxBytes, archiveStore) {
|
|
|
2040
2035
|
role: "system",
|
|
2041
2036
|
content: systemText,
|
|
2042
2037
|
toolCalls: [],
|
|
2043
|
-
tokenCount: Math.max(1, Math.ceil(systemText.length / 4)),
|
|
2044
2038
|
});
|
|
2045
2039
|
}
|
|
2046
2040
|
}
|
|
@@ -2057,7 +2051,6 @@ export async function replayMessages(events, maxBytes, archiveStore) {
|
|
|
2057
2051
|
const systemText = `[Compressed context: turn ${e.turn}]\n${e.summary}`;
|
|
2058
2052
|
messages.push({
|
|
2059
2053
|
role: "system", content: systemText, toolCalls: [],
|
|
2060
|
-
tokenCount: Math.max(1, Math.ceil(systemText.length / 4)),
|
|
2061
2054
|
});
|
|
2062
2055
|
}
|
|
2063
2056
|
}
|
|
@@ -2067,7 +2060,6 @@ export async function replayMessages(events, maxBytes, archiveStore) {
|
|
|
2067
2060
|
role: "assistant",
|
|
2068
2061
|
content: sanitizeReplayText(e.content, maxBytes),
|
|
2069
2062
|
toolCalls: e.tool_calls ?? [],
|
|
2070
|
-
tokenCount: e.token_count,
|
|
2071
2063
|
});
|
|
2072
2064
|
}
|
|
2073
2065
|
else if (e.kind === "tool_completed") {
|
|
@@ -2082,7 +2074,6 @@ export async function replayMessages(events, maxBytes, archiveStore) {
|
|
|
2082
2074
|
content: "",
|
|
2083
2075
|
toolCalls: [],
|
|
2084
2076
|
contentParts: [{ type: "tool_result", callId: durable.call_id, output: sanitizeReplayText(r.output, maxBytes), isError: durable.is_error, ...(durable.blocks.length ? { contentParts: durableBlocksToToolOutput(durable.blocks) } : {}) }],
|
|
2085
|
-
tokenCount: r.token_count,
|
|
2086
2077
|
});
|
|
2087
2078
|
}
|
|
2088
2079
|
}
|
|
@@ -2183,14 +2174,13 @@ function attachmentsToKernelMessage(parts) {
|
|
|
2183
2174
|
if (p.type === "image") {
|
|
2184
2175
|
return {
|
|
2185
2176
|
type: "image",
|
|
2186
|
-
...(p.
|
|
2187
|
-
...(p.data ? { data: p.data } : {}),
|
|
2177
|
+
...(p.source ? { source: p.source } : {}),
|
|
2188
2178
|
...(p.mediaType ? { media_type: p.mediaType } : {}),
|
|
2189
2179
|
...(p.detail ? { detail: p.detail } : {}),
|
|
2190
2180
|
};
|
|
2191
2181
|
}
|
|
2192
2182
|
if (p.type === "audio")
|
|
2193
|
-
return { type: "audio",
|
|
2183
|
+
return { type: "audio", source: p.source, media_type: p.mediaType };
|
|
2194
2184
|
if (p.type === "text")
|
|
2195
2185
|
return { type: "text", text: p.text };
|
|
2196
2186
|
return { type: "text", text: "" };
|
|
@@ -4,7 +4,7 @@ import type { WorkflowNodeStatus } from "./types/agent.js";
|
|
|
4
4
|
export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
|
|
5
5
|
/**
|
|
6
6
|
* Normalize a persisted llm_completed event for recovery. Content is sanitized
|
|
7
|
-
* and token_count
|
|
7
|
+
* and any existing token_count remains raw evidence, but the stored `provider_replay` envelope is
|
|
8
8
|
* passed through verbatim — this layer is provider-neutral and never
|
|
9
9
|
* synthesizes protocol-specific replay shapes. Canonical replay seeding is the
|
|
10
10
|
* responsibility of the target provider's `seedProviderReplay`.
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { sanitizeReplayText } from "./replay-sanitize.js";
|
|
2
2
|
export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
|
|
3
|
-
function estimateTokenCount(text) {
|
|
4
|
-
return Math.max(1, Math.ceil(text.length / 4));
|
|
5
|
-
}
|
|
6
3
|
/**
|
|
7
4
|
* Normalize a persisted llm_completed event for recovery. Content is sanitized
|
|
8
|
-
* and token_count
|
|
5
|
+
* and any existing token_count remains raw evidence, but the stored `provider_replay` envelope is
|
|
9
6
|
* passed through verbatim — this layer is provider-neutral and never
|
|
10
7
|
* synthesizes protocol-specific replay shapes. Canonical replay seeding is the
|
|
11
8
|
* responsibility of the target provider's `seedProviderReplay`.
|
|
@@ -19,7 +16,7 @@ export function normalizeLlmCompleted(event, maxBytes) {
|
|
|
19
16
|
turn: event.turn,
|
|
20
17
|
content,
|
|
21
18
|
tool_calls: toolCalls,
|
|
22
|
-
token_count: event.token_count
|
|
19
|
+
...(event.token_count !== undefined ? { token_count: event.token_count } : {}),
|
|
23
20
|
...(providerReplay ? { provider_replay: providerReplay } : {}),
|
|
24
21
|
// P4 §3: the evidence-plane fields ride along verbatim — recovery never reads them
|
|
25
22
|
// (SessionLog is evidence, not authority), so normalize must neither synthesize nor drop them.
|
|
@@ -92,7 +92,6 @@ export function subAgentResultToKernel(result) {
|
|
|
92
92
|
name: tc.name,
|
|
93
93
|
arguments: safeParseToolArgs(tc.arguments),
|
|
94
94
|
})),
|
|
95
|
-
...(finalMessage.tokenCount !== undefined ? { token_count: finalMessage.tokenCount } : {}),
|
|
96
95
|
}
|
|
97
96
|
: null,
|
|
98
97
|
turns_used: result.result.turnsUsed,
|
|
@@ -146,7 +145,6 @@ export function workflowNodeOutcomeFromKernel(raw) {
|
|
|
146
145
|
name: call.name,
|
|
147
146
|
arguments: JSON.stringify(call.arguments ?? {}),
|
|
148
147
|
})),
|
|
149
|
-
...(output.token_count != null ? { tokenCount: output.token_count } : {}),
|
|
150
148
|
},
|
|
151
149
|
}
|
|
152
150
|
: {}),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/** Framework-facing API plus the Rust verifiable-runtime report ABI. */
|
|
2
|
+
export declare const VERIFIABLE_REPORT_SCHEMA: "verifiable-report/v1";
|
|
3
|
+
export declare const VERIFIABLE_FORK_SCHEMA: "verifiable-fork/v1";
|
|
4
|
+
export type VerifiableCommand = "inspect" | "verify" | "replay" | "fork";
|
|
5
|
+
export type CheckVerdict = "pass" | "degraded" | "fail" | "unavailable";
|
|
6
|
+
export type ReplayVerdict = "pass" | "fail" | "unavailable";
|
|
7
|
+
export type VerifiableReport = {
|
|
8
|
+
readonly schema: typeof VERIFIABLE_REPORT_SCHEMA;
|
|
9
|
+
readonly command: VerifiableCommand;
|
|
10
|
+
readonly operation_id: string;
|
|
11
|
+
readonly [key: string]: unknown;
|
|
12
|
+
};
|
|
13
|
+
export interface VerifiableEvidence {
|
|
14
|
+
readonly journal: ReadonlyArray<Uint8Array>;
|
|
15
|
+
readonly sessionLogs?: ReadonlyArray<ReadonlyArray<Uint8Array>>;
|
|
16
|
+
readonly checkpoints?: ReadonlyArray<Uint8Array>;
|
|
17
|
+
}
|
|
18
|
+
export interface VerifyOptions {
|
|
19
|
+
readonly strict?: boolean;
|
|
20
|
+
readonly requireComplete?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ReplayOptions {
|
|
23
|
+
readonly strict?: boolean;
|
|
24
|
+
readonly atStep?: number;
|
|
25
|
+
}
|
|
26
|
+
export interface VerifiableForkManifest {
|
|
27
|
+
schema: typeof VERIFIABLE_FORK_SCHEMA;
|
|
28
|
+
operation_id: string;
|
|
29
|
+
at_step: string;
|
|
30
|
+
parent_record_digest: string;
|
|
31
|
+
parent_input_id: string;
|
|
32
|
+
source_records: number;
|
|
33
|
+
}
|
|
34
|
+
export type ForkPlan = VerifiableForkManifest;
|
|
35
|
+
export interface VerifiableRuntimeAdapter {
|
|
36
|
+
inspect(operationId: string, evidence: VerifiableEvidence, strict: boolean): VerifiableReport;
|
|
37
|
+
verify(operationId: string, evidence: VerifiableEvidence, options: VerifyOptions): VerifiableReport;
|
|
38
|
+
replay(operationId: string, evidence: VerifiableEvidence, options: ReplayOptions): VerifiableReport;
|
|
39
|
+
prepareFork(operationId: string, evidence: VerifiableEvidence, atStep: number, strict: boolean): ForkPlan;
|
|
40
|
+
}
|
|
41
|
+
export type VerifiableOperationJson = (request: string) => string;
|
|
42
|
+
/** Create the SDK adapter backed by the Rust core JSON bridge. */
|
|
43
|
+
export declare function createVerifiableRuntimeAdapter(operationJson: VerifiableOperationJson): VerifiableRuntimeAdapter;
|
|
44
|
+
/** Create the adapter from the lazily loaded WASM binding. */
|
|
45
|
+
export declare function createNativeVerifiableRuntimeAdapter(): Promise<VerifiableRuntimeAdapter>;
|
|
46
|
+
/** Storage-neutral framework handle. Store access remains in the host adapter. */
|
|
47
|
+
export declare class VerifiableOperation {
|
|
48
|
+
readonly operationId: string;
|
|
49
|
+
readonly evidence: VerifiableEvidence;
|
|
50
|
+
private readonly adapter;
|
|
51
|
+
constructor(operationId: string, evidence: VerifiableEvidence, adapter: VerifiableRuntimeAdapter);
|
|
52
|
+
inspect(strict?: boolean): VerifiableReport;
|
|
53
|
+
verify(options?: VerifyOptions): VerifiableReport;
|
|
54
|
+
replay(options?: ReplayOptions): VerifiableReport;
|
|
55
|
+
prepareFork(atStep: number, strict?: boolean): ForkPlan;
|
|
56
|
+
}
|
|
57
|
+
export declare function assertVerifiableReportSchema(value: {
|
|
58
|
+
schema?: unknown;
|
|
59
|
+
}): void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { getKernel } from "./kernel.js";
|
|
2
|
+
/** Framework-facing API plus the Rust verifiable-runtime report ABI. */
|
|
3
|
+
export const VERIFIABLE_REPORT_SCHEMA = "verifiable-report/v1";
|
|
4
|
+
export const VERIFIABLE_FORK_SCHEMA = "verifiable-fork/v1";
|
|
5
|
+
/** Create the SDK adapter backed by the Rust core JSON bridge. */
|
|
6
|
+
export function createVerifiableRuntimeAdapter(operationJson) {
|
|
7
|
+
const call = (operationId, evidence, command, options = {}) => {
|
|
8
|
+
const result = JSON.parse(operationJson(JSON.stringify({
|
|
9
|
+
operation_id: operationId,
|
|
10
|
+
command,
|
|
11
|
+
evidence: {
|
|
12
|
+
journal: evidence.journal.map((bytes) => Array.from(bytes)),
|
|
13
|
+
session_logs: (evidence.sessionLogs ?? []).map((stream) => stream.map((bytes) => Array.from(bytes))),
|
|
14
|
+
checkpoints: (evidence.checkpoints ?? []).map((bytes) => Array.from(bytes)),
|
|
15
|
+
},
|
|
16
|
+
strict: options.strict ?? false,
|
|
17
|
+
require_complete: "requireComplete" in options ? options.requireComplete ?? false : false,
|
|
18
|
+
at_step: "atStep" in options ? options.atStep : undefined,
|
|
19
|
+
})));
|
|
20
|
+
if (command === "fork")
|
|
21
|
+
return result;
|
|
22
|
+
assertVerifiableReportSchema(result);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
return {
|
|
26
|
+
inspect: (operationId, evidence, strict) => call(operationId, evidence, "inspect", { strict }),
|
|
27
|
+
verify: (operationId, evidence, options) => call(operationId, evidence, "verify", options),
|
|
28
|
+
replay: (operationId, evidence, options) => call(operationId, evidence, "replay", options),
|
|
29
|
+
prepareFork: (operationId, evidence, atStep, strict) => call(operationId, evidence, "fork", { atStep, strict }),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Create the adapter from the lazily loaded WASM binding. */
|
|
33
|
+
export async function createNativeVerifiableRuntimeAdapter() {
|
|
34
|
+
const kernel = await getKernel();
|
|
35
|
+
return createVerifiableRuntimeAdapter(kernel.verifiableOperationJson);
|
|
36
|
+
}
|
|
37
|
+
/** Storage-neutral framework handle. Store access remains in the host adapter. */
|
|
38
|
+
export class VerifiableOperation {
|
|
39
|
+
operationId;
|
|
40
|
+
evidence;
|
|
41
|
+
adapter;
|
|
42
|
+
constructor(operationId, evidence, adapter) {
|
|
43
|
+
this.operationId = operationId;
|
|
44
|
+
this.evidence = evidence;
|
|
45
|
+
this.adapter = adapter;
|
|
46
|
+
}
|
|
47
|
+
inspect(strict = false) {
|
|
48
|
+
return this.adapter.inspect(this.operationId, this.evidence, strict);
|
|
49
|
+
}
|
|
50
|
+
verify(options = {}) {
|
|
51
|
+
return this.adapter.verify(this.operationId, this.evidence, options);
|
|
52
|
+
}
|
|
53
|
+
replay(options = {}) {
|
|
54
|
+
return this.adapter.replay(this.operationId, this.evidence, options);
|
|
55
|
+
}
|
|
56
|
+
prepareFork(atStep, strict = false) {
|
|
57
|
+
return this.adapter.prepareFork(this.operationId, this.evidence, atStep, strict);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function assertVerifiableReportSchema(value) {
|
|
61
|
+
if (value.schema !== VERIFIABLE_REPORT_SCHEMA) {
|
|
62
|
+
throw new Error(`unsupported verifiable report schema: ${String(value.schema)}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -2,10 +2,7 @@ import type { WorkflowNodeSpec } from "./runtime/types/agent.js";
|
|
|
2
2
|
export interface ContentPart {
|
|
3
3
|
type: "text" | "image" | "audio" | "tool_result";
|
|
4
4
|
text?: string;
|
|
5
|
-
|
|
6
|
-
url?: string;
|
|
7
|
-
/** Raw base64-encoded bytes (image/audio). */
|
|
8
|
-
data?: string;
|
|
5
|
+
source?: MediaSource;
|
|
9
6
|
/** MIME type, e.g. `"image/png"`. */
|
|
10
7
|
mediaType?: string;
|
|
11
8
|
/** OpenAI vision detail level. */
|
|
@@ -45,7 +42,6 @@ export type ToolOutputBlock = {
|
|
|
45
42
|
export interface Message {
|
|
46
43
|
role: "system" | "user" | "assistant" | "tool";
|
|
47
44
|
content: string;
|
|
48
|
-
tokenCount?: number;
|
|
49
45
|
toolCalls?: ToolCall[];
|
|
50
46
|
/** Multimodal parts (text + image/audio). When present, providers render these
|
|
51
47
|
* instead of the plain `content` string. */
|
|
@@ -63,7 +59,6 @@ export interface ToolResult {
|
|
|
63
59
|
isError: boolean;
|
|
64
60
|
isFatal?: boolean;
|
|
65
61
|
errorKind?: ToolErrorKind;
|
|
66
|
-
tokenCount?: number;
|
|
67
62
|
contentParts?: ToolOutputBlock[];
|
|
68
63
|
}
|
|
69
64
|
export interface ToolSchema {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.69",
|
|
4
4
|
"description": "DeepStrike WASM SDK — browser, Cloudflare Workers, Deno Deploy",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"test:canonical-binding": "wasm-pack build ../crates/deepstrike-wasm --target nodejs --dev --out-dir ../../wasm/pkg-node && node tests/canonical-binding.node.cjs && node tests/golden-fixtures-sweep.node.cjs"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@deepstrike/wasm-kernel": "0.2.
|
|
20
|
+
"@deepstrike/wasm-kernel": "0.2.69"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/jest": "^30.0.0",
|