@deepstrike/wasm 0.2.33 → 0.2.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/providers/anthropic.js +3 -0
- package/dist/providers/openai.js +11 -1
- package/dist/runtime/runner.js +27 -24
- package/dist/types.d.ts +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/kongusen/deepstrike">
|
|
3
|
+
<img src="https://raw.githubusercontent.com/kongusen/deepstrike/main/docs/public/banner.png" alt="DeepStrike" width="420" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
1
7
|
# DeepStrike WASM SDK
|
|
2
8
|
|
|
3
9
|
Runtime framework built on a Rust kernel compiled to WebAssembly. Runs in browsers, Cloudflare Workers, Deno Deploy, and Vercel Edge — anywhere that supports `fetch` and WASM.
|
|
@@ -250,6 +250,8 @@ export class AnthropicProvider {
|
|
|
250
250
|
const inputTokens = uncachedInput + cacheReadTokens + cacheCreationTokens;
|
|
251
251
|
if (inputTokens > 0 || outputTokens > 0) {
|
|
252
252
|
const bySlot = estimateCacheReadBySlot(cacheReadTokens, slotBp);
|
|
253
|
+
// stop_reason rides on message_delta; "max_tokens" drives output-cap recovery.
|
|
254
|
+
const stopReason = evt.delta?.stop_reason;
|
|
253
255
|
yield {
|
|
254
256
|
type: "usage",
|
|
255
257
|
totalTokens: inputTokens + outputTokens,
|
|
@@ -258,6 +260,7 @@ export class AnthropicProvider {
|
|
|
258
260
|
cacheReadInputTokens: cacheReadTokens,
|
|
259
261
|
cacheCreationInputTokens: cacheCreationTokens,
|
|
260
262
|
...(bySlot ? { cacheReadInputTokensBySlot: bySlot } : {}),
|
|
263
|
+
...(stopReason ? { stopReason } : {}),
|
|
261
264
|
};
|
|
262
265
|
}
|
|
263
266
|
}
|
package/dist/providers/openai.js
CHANGED
|
@@ -37,6 +37,9 @@ export class OpenAIProvider {
|
|
|
37
37
|
const reader = resp.body.getReader();
|
|
38
38
|
const decoder = new TextDecoder();
|
|
39
39
|
let buf = "";
|
|
40
|
+
// Phase 4: OpenAI signals an output-cap truncation via finish_reason="length"; the kernel
|
|
41
|
+
// treats it as a truncation (== Anthropic "max_tokens") and drives output-cap recovery.
|
|
42
|
+
let finishReason;
|
|
40
43
|
while (true) {
|
|
41
44
|
const { done, value } = await reader.read();
|
|
42
45
|
if (done)
|
|
@@ -48,10 +51,17 @@ export class OpenAIProvider {
|
|
|
48
51
|
if (!line.startsWith("data: "))
|
|
49
52
|
continue;
|
|
50
53
|
const data = line.slice(6).trim();
|
|
51
|
-
if (data === "[DONE]")
|
|
54
|
+
if (data === "[DONE]") {
|
|
55
|
+
// Surface an output-cap truncation (finish_reason="length") to the runner/kernel. Emitted
|
|
56
|
+
// as a usage frame (the channel the runner reads stopReason from) before the early return.
|
|
57
|
+
if (finishReason)
|
|
58
|
+
yield { type: "usage", totalTokens: 0, stopReason: finishReason };
|
|
52
59
|
return;
|
|
60
|
+
}
|
|
53
61
|
try {
|
|
54
62
|
const chunk = JSON.parse(data);
|
|
63
|
+
if (chunk.choices?.[0]?.finish_reason)
|
|
64
|
+
finishReason = chunk.choices[0].finish_reason ?? undefined;
|
|
55
65
|
const delta = chunk.choices?.[0]?.delta;
|
|
56
66
|
if (!delta)
|
|
57
67
|
continue;
|
package/dist/runtime/runner.js
CHANGED
|
@@ -5,7 +5,7 @@ import { peekProviderReplay, seedProviderReplayFromEvents } from "./provider-rep
|
|
|
5
5
|
import { sanitizeReplayText } from "./replay-sanitize.js";
|
|
6
6
|
import { formatToolError } from "../tools/errors.js";
|
|
7
7
|
import { buildLlmCompletedEvent, buildRunTerminalEvent, buildWorkflowNodeCompletedEvent, buildWorkflowNodesSubmittedEvent, recoverCompletedWorkflowNodes, recoverSubmittedWorkflowNodes, repairEventsForRecovery, } from "./session-repair.js";
|
|
8
|
-
import {
|
|
8
|
+
import { kernelAction, kernelApply, kernelMaybeAction, messageToKernelMessage, skillMetadataToKernel, toolResultToKernel, toolSchemaToKernel, } from "./kernel-step.js";
|
|
9
9
|
import { agentRunSpecToKernel, findSpawnProcessObservation, milestoneCheckPass, milestoneCheckResultToKernel, spawnObservationToManifest, subAgentResultToKernel, submitWorkflowNodesToKernel, submitWorkflowToKernel, workflowBudgetNote, workflowNodeToManifest, workflowNodeToSpec, workflowSpecToKernel, } from "./types/agent.js";
|
|
10
10
|
import { defaultSubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
11
11
|
import { extractJsonValue, schemaInstruction, schemaRetryInstruction, validateAgainstSchema, } from "./output-schema.js";
|
|
@@ -408,7 +408,6 @@ export class RuntimeRunner {
|
|
|
408
408
|
let action = resumeMidRun
|
|
409
409
|
? kernelAction(runtime, this.pendingObservations, { kind: "resume" })
|
|
410
410
|
: kernelAction(runtime, this.pendingObservations, startPayload);
|
|
411
|
-
let hasAttemptedReactiveCompact = false;
|
|
412
411
|
// P0-C: the skill loaded and in effect going into the current turn → per-turn `activeSkill` metric.
|
|
413
412
|
let activeSkill;
|
|
414
413
|
// I0b: kernel-throw safety net — see Node runner for full rationale.
|
|
@@ -466,7 +465,7 @@ export class RuntimeRunner {
|
|
|
466
465
|
let turnCacheReadTokens = 0;
|
|
467
466
|
let turnCacheCreationTokens = 0;
|
|
468
467
|
let turnCacheReadBySlot;
|
|
469
|
-
let
|
|
468
|
+
let turnStopReason;
|
|
470
469
|
const abortSignal = this.abortController?.signal;
|
|
471
470
|
try {
|
|
472
471
|
for await (const evt of this.opts.provider.stream(context, tools, Object.keys(ext).length ? ext : undefined, providerState, abortSignal)) {
|
|
@@ -483,6 +482,9 @@ export class RuntimeRunner {
|
|
|
483
482
|
turnCacheCreationTokens = usageEvt.cacheCreationInputTokens ?? 0;
|
|
484
483
|
// I1: per-slot attribution forwarded to TurnMetrics; undefined on non-Anthropic providers.
|
|
485
484
|
turnCacheReadBySlot = usageEvt.cacheReadInputTokensBySlot;
|
|
485
|
+
// Phase 4: stop_reason drives the kernel's max-output-tokens recovery.
|
|
486
|
+
if (usageEvt.stopReason)
|
|
487
|
+
turnStopReason = usageEvt.stopReason;
|
|
486
488
|
continue;
|
|
487
489
|
}
|
|
488
490
|
yield evt;
|
|
@@ -495,23 +497,31 @@ export class RuntimeRunner {
|
|
|
495
497
|
}
|
|
496
498
|
}
|
|
497
499
|
catch (err) {
|
|
498
|
-
// #2-B-ii: an aborted in-flight request surfaces as an AbortError — treat as an interrupt.
|
|
499
500
|
if (abortSignal?.aborted) {
|
|
501
|
+
// #2-B-ii: an aborted in-flight request surfaces as an AbortError — treat it as an
|
|
502
|
+
// interrupt (the post-stream `aborted` check below converts it to a clean
|
|
503
|
+
// timeout/UserAbort), not a crash or a provider error.
|
|
500
504
|
this.interrupted = true;
|
|
501
505
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
506
|
+
else {
|
|
507
|
+
// Reactive recovery is now a kernel decision. Forward the raw provider error and
|
|
508
|
+
// dispatch whatever the kernel returns: `call_provider` to retry with a freshly
|
|
509
|
+
// compacted context, or `done` to terminate with an honest `ContextOverflow`. The
|
|
510
|
+
// classify + compact + retry + give-up policy lives in the kernel (one place), not
|
|
511
|
+
// duplicated across the four SDK runners.
|
|
512
|
+
action = kernelAction(runtime, this.pendingObservations, {
|
|
513
|
+
kind: "provider_error",
|
|
514
|
+
message: formatToolError(err),
|
|
515
|
+
});
|
|
516
|
+
// Withholding (query.ts parity): surface the raw provider error only when the kernel
|
|
517
|
+
// could NOT recover (it returned a terminal). On a recovered retry (`call_provider`)
|
|
518
|
+
// the error stays hidden. `continue` re-enters the loop: a recovered turn persists its
|
|
519
|
+
// compaction archive via the loop-top appendObservations, and a terminal `done` exits
|
|
520
|
+
// through `isTerminal()`.
|
|
521
|
+
if (action.kind === "done") {
|
|
522
|
+
yield { type: "error", message: formatToolError(err) };
|
|
509
523
|
}
|
|
510
|
-
|
|
511
|
-
if (!shouldRetry) {
|
|
512
|
-
yield { type: "error", message: formatToolError(err) };
|
|
513
|
-
action = kernelAction(runtime, this.pendingObservations, { kind: "timeout" });
|
|
514
|
-
break;
|
|
524
|
+
continue;
|
|
515
525
|
}
|
|
516
526
|
}
|
|
517
527
|
// #2-B-ii: stream aborted (preempt/interrupt) via the break path — end the turn now.
|
|
@@ -519,14 +529,6 @@ export class RuntimeRunner {
|
|
|
519
529
|
action = kernelAction(runtime, this.pendingObservations, { kind: "timeout" });
|
|
520
530
|
break;
|
|
521
531
|
}
|
|
522
|
-
if (shouldRetry) {
|
|
523
|
-
action = {
|
|
524
|
-
kind: "call_provider",
|
|
525
|
-
context: runtime.render(),
|
|
526
|
-
tools,
|
|
527
|
-
};
|
|
528
|
-
continue;
|
|
529
|
-
}
|
|
530
532
|
const assistantMessage = {
|
|
531
533
|
role: "assistant",
|
|
532
534
|
content: finalText,
|
|
@@ -539,6 +541,7 @@ export class RuntimeRunner {
|
|
|
539
541
|
...(turnInputTokens > 0 ? { observed_input_tokens: turnInputTokens } : {}),
|
|
540
542
|
...(turnOutputTokens > 0 ? { observed_output_tokens: turnOutputTokens } : {}),
|
|
541
543
|
now_ms: Date.now(),
|
|
544
|
+
...(turnStopReason ? { stop_reason: turnStopReason } : {}),
|
|
542
545
|
};
|
|
543
546
|
let nextAction = kernelMaybeAction(runtime, this.pendingObservations, providerEvent);
|
|
544
547
|
const hasSuspended = this.pendingObservations.some(o => o.kind === "suspended");
|
package/dist/types.d.ts
CHANGED
|
@@ -73,7 +73,8 @@ export interface UsageEvent extends StreamEvent {
|
|
|
73
73
|
system?: number;
|
|
74
74
|
tools?: number;
|
|
75
75
|
messages?: number;
|
|
76
|
-
};
|
|
76
|
+
}; /** Provider stop reason — `max_tokens` (Anthropic) / `length` (OpenAI) flag an output-cap truncation driving the kernel's max-output-tokens recovery. */
|
|
77
|
+
stopReason?: string;
|
|
77
78
|
}
|
|
78
79
|
export interface ThinkingDelta extends StreamEvent {
|
|
79
80
|
type: "thinking_delta";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.35",
|
|
4
4
|
"description": "DeepStrike WASM SDK — browser, Cloudflare Workers, Deno Deploy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test": "node --experimental-vm-modules node_modules/.bin/jest"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@deepstrike/wasm-kernel": "0.2.
|
|
18
|
+
"@deepstrike/wasm-kernel": "0.2.35"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/jest": "^30.0.0",
|