@deepstrike/wasm 0.2.37 → 0.2.39

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 CHANGED
@@ -25,4 +25,4 @@ export { ScheduledPrompt } from "./signals/index.js";
25
25
  export type { RuntimeSignal, SignalSource } from "./signals/index.js";
26
26
  export { PermissionManager, PermissionMode } from "./safety/index.js";
27
27
  export type { PermissionDecision } from "./safety/index.js";
28
- export type { Message, ToolCall, ToolResult, ToolSchema, RenderedContext, ProviderRunState, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, LLMProvider, CacheBreakpointStrategy, } from "./types.js";
28
+ 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, } from "./types.js";
@@ -88,6 +88,25 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
88
88
  turn: t,
89
89
  history_len: obs.history_len ?? 0,
90
90
  };
91
+ case "entropy_sample":
92
+ return {
93
+ kind: "entropy_sample",
94
+ turn: t,
95
+ score: obs.score ?? 0,
96
+ score_version: obs.score_version ?? 0,
97
+ rho: obs.rho ?? 0,
98
+ repeat_pressure: obs.repeat_pressure ?? 0,
99
+ failure_rate: obs.failure_rate ?? 0,
100
+ rollbacks_in_window: obs.rollbacks_in_window ?? 0,
101
+ window_turns: obs.window_turns ?? 0,
102
+ };
103
+ case "entropy_alert":
104
+ return {
105
+ kind: "entropy_alert",
106
+ turn: t,
107
+ score: obs.score ?? 0,
108
+ threshold: obs.threshold ?? 0,
109
+ };
91
110
  case "agent_process_changed":
92
111
  return {
93
112
  kind: "agent_process_changed",
@@ -115,6 +115,14 @@ export interface KernelObservation {
115
115
  }>;
116
116
  completed?: string[];
117
117
  failed?: string[];
118
+ score?: number;
119
+ score_version?: number;
120
+ rho?: number;
121
+ repeat_pressure?: number;
122
+ failure_rate?: number;
123
+ rollbacks_in_window?: number;
124
+ window_turns?: number;
125
+ threshold?: number;
118
126
  }
119
127
  export declare function toolSchemaToKernel(schema: ToolSchema): Record<string, unknown>;
120
128
  export declare function skillMetadataToKernel(skill: SkillMetadata): Record<string, unknown>;
@@ -1,4 +1,4 @@
1
- import type { LLMProvider, Message, StreamEvent, PermissionRequestEvent, PermissionResponse, DreamSummarizer } from "../types.js";
1
+ import type { LLMProvider, Message, StreamEvent, PermissionRequestEvent, PermissionResponse, EntropySample, EntropyWatchOptions, DreamSummarizer } from "../types.js";
2
2
  import type { ToolSuspendEvent } from "./execution-plane.js";
3
3
  import type { DreamStore, DreamResult } from "../memory/index.js";
4
4
  import type { KnowledgeSource } from "../knowledge/index.js";
@@ -122,6 +122,10 @@ export interface RuntimeOptions {
122
122
  * warn-once observation + oldest unpinned non-skill entries evicted at the next boundary.
123
123
  * Pinned/skill entries are exempt. `0` disables. Default: kernel's 0.25. */
124
124
  knowledgeBudgetRatio?: number;
125
+ /** Opt-in kernel entropy watch: threshold alerting over the per-turn session-entropy score
126
+ * (`entropy_sample` events stream unconditionally regardless). See the Node SDK's
127
+ * `entropyWatch` for the canonical documentation. Absent ⇒ disabled (kernel default). */
128
+ entropyWatch?: EntropyWatchOptions;
125
129
  /** K3: default lease (in turns) for every skill activation — auto-deactivates after N turns
126
130
  * (toolset re-widens, knowledge pin boundary-swept). Absent ⇒ permanent (default). */
127
131
  skillLeaseTurns?: number;
@@ -192,6 +196,8 @@ export declare class RuntimeRunner {
192
196
  * run — guards against re-pushing a duplicate entry if the model calls `skill(name)` again for
193
197
  * an already-active skill (loading is idempotent; the knowledge push should be too). */
194
198
  private knowledgePushedSkills;
199
+ /** Most recent kernel entropy sample of the active/last run (see `latestEntropy`). */
200
+ private lastEntropySample;
195
201
  /** K4: the active run's goal, kept for the renewal-boundary memory re-query. */
196
202
  private currentGoal;
197
203
  private nextArchiveStart;
@@ -208,6 +214,9 @@ export declare class RuntimeRunner {
208
214
  * the kernel disposition ladder: `"normal"` queues (default), `"high"` soft-interrupts, `"critical"`
209
215
  * preempts. */
210
216
  injectNote(text: string, urgency?: RuntimeSignal["urgency"]): void;
217
+ /** The most recent kernel session-entropy sample (one per completed turn), or `null` before the
218
+ * first boundary. A pull companion to the streamed `entropy_sample` events. */
219
+ latestEntropy(): EntropySample | null;
211
220
  /** Injected-note drain shared with the main loop's per-turn poll: injected notes first (FIFO), then
212
221
  * the configured `signalSource` — one code path so the two inbound channels never drift. */
213
222
  private nextInboundSignal;
@@ -28,6 +28,8 @@ export class RuntimeRunner {
28
28
  * run — guards against re-pushing a duplicate entry if the model calls `skill(name)` again for
29
29
  * an already-active skill (loading is idempotent; the knowledge push should be too). */
30
30
  knowledgePushedSkills = new Set();
31
+ /** Most recent kernel entropy sample of the active/last run (see `latestEntropy`). */
32
+ lastEntropySample = null;
31
33
  /** K4: the active run's goal, kept for the renewal-boundary memory re-query. */
32
34
  currentGoal = "";
33
35
  nextArchiveStart = 0;
@@ -48,6 +50,11 @@ export class RuntimeRunner {
48
50
  injectNote(text, urgency = "normal") {
49
51
  this.injectedSignals.push({ source: "custom", signalType: "event", urgency, payload: { goal: text } });
50
52
  }
53
+ /** The most recent kernel session-entropy sample (one per completed turn), or `null` before the
54
+ * first boundary. A pull companion to the streamed `entropy_sample` events. */
55
+ latestEntropy() {
56
+ return this.lastEntropySample;
57
+ }
51
58
  /** Injected-note drain shared with the main loop's per-turn poll: injected notes first (FIFO), then
52
59
  * the configured `signalSource` — one code path so the two inbound channels never drift. */
53
60
  async nextInboundSignal() {
@@ -859,10 +866,35 @@ export class RuntimeRunner {
859
866
  }
860
867
  catch { /* skip */ }
861
868
  }
869
+ const entropyObsStart = this.pendingObservations.length;
862
870
  action = kernelAction(runtime, this.pendingObservations, {
863
871
  kind: "tool_results",
864
872
  results: toolResults.map(toolResultToKernel),
865
873
  });
874
+ // Surface the boundary's entropy measurement live (the heartbeat watch source).
875
+ for (const obs of this.pendingObservations.slice(entropyObsStart)) {
876
+ if (obs.kind === "entropy_sample") {
877
+ this.lastEntropySample = {
878
+ turn: obs.turn ?? 0,
879
+ score: obs.score ?? 0,
880
+ scoreVersion: obs.score_version ?? 0,
881
+ rho: obs.rho ?? 0,
882
+ repeatPressure: obs.repeat_pressure ?? 0,
883
+ failureRate: obs.failure_rate ?? 0,
884
+ rollbacksInWindow: obs.rollbacks_in_window ?? 0,
885
+ windowTurns: obs.window_turns ?? 0,
886
+ };
887
+ yield { type: "entropy_sample", sample: this.lastEntropySample };
888
+ }
889
+ else if (obs.kind === "entropy_alert") {
890
+ yield {
891
+ type: "entropy_alert",
892
+ turn: obs.turn ?? 0,
893
+ score: obs.score ?? 0,
894
+ threshold: obs.threshold ?? 0,
895
+ };
896
+ }
897
+ }
866
898
  }
867
899
  else if (action.kind === "evaluate_milestone") {
868
900
  const milestonePolicy = this.opts.milestonePolicy ?? "require_verifier";
@@ -1174,6 +1206,17 @@ export class RuntimeRunner {
1174
1206
  if (this.opts.knowledgeBudgetRatio !== undefined) {
1175
1207
  config.knowledge_budget_ratio = this.opts.knowledgeBudgetRatio;
1176
1208
  }
1209
+ // Entropy watch (opt-in): threshold alerting over the per-turn session-entropy score.
1210
+ if (this.opts.entropyWatch !== undefined) {
1211
+ const ew = this.opts.entropyWatch;
1212
+ config.entropy_watch = {
1213
+ enabled: ew.enabled ?? true,
1214
+ ...(ew.threshold !== undefined ? { threshold: ew.threshold } : {}),
1215
+ ...(ew.hysteresis !== undefined ? { hysteresis: ew.hysteresis } : {}),
1216
+ ...(ew.cooldownTurns !== undefined ? { cooldown_turns: ew.cooldownTurns } : {}),
1217
+ ...(ew.notifyModel !== undefined ? { notify_model: ew.notifyModel } : {}),
1218
+ };
1219
+ }
1177
1220
  kernelApply(runtime, this.pendingObservations, { kind: "configure_run", config });
1178
1221
  if (this.opts.memoryPolicy) {
1179
1222
  const m = this.opts.memoryPolicy;
@@ -159,6 +159,21 @@ export type SessionEvent = {
159
159
  kind: "checkpoint_taken";
160
160
  turn: number;
161
161
  history_len: number;
162
+ } | {
163
+ kind: "entropy_sample";
164
+ turn: number;
165
+ score: number;
166
+ score_version: number;
167
+ rho: number;
168
+ repeat_pressure: number;
169
+ failure_rate: number;
170
+ rollbacks_in_window: number;
171
+ window_turns: number;
172
+ } | {
173
+ kind: "entropy_alert";
174
+ turn: number;
175
+ score: number;
176
+ threshold: number;
162
177
  } | {
163
178
  kind: "agent_process_changed";
164
179
  turn: number;
package/dist/types.d.ts CHANGED
@@ -155,6 +155,38 @@ export interface ToolArgumentRepairedEvent extends StreamEvent {
155
155
  originalArguments: string;
156
156
  repairedArguments: string;
157
157
  }
158
+ /** Kernel session-entropy measurement at a completed turn boundary (see the Node SDK's
159
+ * `EntropySample` for the canonical documentation; this is the WASM mirror). */
160
+ export interface EntropySample {
161
+ turn: number;
162
+ score: number;
163
+ scoreVersion: number;
164
+ rho: number;
165
+ repeatPressure: number;
166
+ failureRate: number;
167
+ rollbacksInWindow: number;
168
+ windowTurns: number;
169
+ }
170
+ /** One kernel entropy sample, emitted once per completed turn (a heartbeat watch source). */
171
+ export interface EntropySampleEvent extends StreamEvent {
172
+ type: "entropy_sample";
173
+ sample: EntropySample;
174
+ }
175
+ /** The opt-in kernel entropy watch tripped (see `RunnerOptions.entropyWatch`). */
176
+ export interface EntropyAlertEvent extends StreamEvent {
177
+ type: "entropy_alert";
178
+ turn: number;
179
+ score: number;
180
+ threshold: number;
181
+ }
182
+ /** Opt-in kernel-side threshold watch over the per-turn entropy score (Node SDK mirror). */
183
+ export interface EntropyWatchOptions {
184
+ enabled?: boolean;
185
+ threshold?: number;
186
+ hysteresis?: number;
187
+ cooldownTurns?: number;
188
+ notifyModel?: boolean;
189
+ }
158
190
  /**
159
191
  * Opaque per-run state owned by the provider (e.g. OpenAI Responses continuation).
160
192
  * The framework creates and threads this object; providers may read/write it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/wasm",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
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.37"
18
+ "@deepstrike/wasm-kernel": "0.2.39"
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/jest": "^30.0.0",