@deepstrike/wasm 0.2.74 → 0.2.76

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.
@@ -27,6 +27,8 @@ export interface ExecutionPlane {
27
27
  schemas(): ToolSchema[];
28
28
  executeAll(calls: ToolCall[], ctx: RunContext): AsyncIterable<StreamEvent>;
29
29
  }
30
+ /** A skill file's body without its YAML frontmatter. */
31
+ export declare function stripSkillFrontmatter(content: string): string;
30
32
  export declare class LocalExecutionPlane implements ExecutionPlane {
31
33
  private tools;
32
34
  register(...tools: RegisteredTool[]): this;
@@ -1,5 +1,7 @@
1
1
  import { formatToolError } from "../tools/errors.js";
2
- function stripFrontmatter(content) {
2
+ import { parseToolCallArguments } from "./tool-arguments.js";
3
+ /** A skill file's body without its YAML frontmatter. */
4
+ export function stripSkillFrontmatter(content) {
3
5
  const s = content.trimStart();
4
6
  if (!s.startsWith("---"))
5
7
  return s;
@@ -31,7 +33,7 @@ export class LocalExecutionPlane {
31
33
  const args = tryParseJson(c.arguments);
32
34
  const name = String(args?.name ?? "");
33
35
  const raw = ctx.skillContentMap?.get(name);
34
- const content = raw != null ? stripFrontmatter(raw) : null;
36
+ const content = raw != null ? stripSkillFrontmatter(raw) : null;
35
37
  yield {
36
38
  type: "tool_result",
37
39
  callId: c.id,
@@ -81,7 +83,12 @@ export class LocalExecutionPlane {
81
83
  },
82
84
  };
83
85
  try {
84
- const args = JSON.parse(call.arguments || "{}");
86
+ const parsedArgs = parseToolCallArguments(call.arguments);
87
+ if (!parsedArgs.ok) {
88
+ yield { type: "tool_result", callId: call.id, name: call.name, content: `invalid arguments: ${parsedArgs.error}`, isError: true };
89
+ continue;
90
+ }
91
+ const args = parsedArgs.args;
85
92
  // M3/G4: pass the run context (incl. `cwd`, `audit`) for tool-ABI parity with Node/Python.
86
93
  const output = await registered.execute(args, callCtx);
87
94
  for (const f of auditFailures) {
@@ -1,3 +1,4 @@
1
+ import { toolArgumentsFromWire, toolArgumentsToWire } from "./tool-arguments.js";
1
2
  export const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
2
3
  /**
3
4
  * Browser/worker-safe transport for typed content. `btoa` and `atob` operate on
@@ -82,7 +83,7 @@ export function messageToKernelMessage(message) {
82
83
  tool_calls: (message.toolCalls ?? []).map(tc => ({
83
84
  id: tc.id,
84
85
  name: tc.name,
85
- arguments: tryParseJson(tc.arguments) ?? {},
86
+ arguments: toolArgumentsToWire(tc.arguments),
86
87
  })),
87
88
  };
88
89
  // Multimodal: serialize typed content parts to the kernel `Content::Parts` shape when present
@@ -164,10 +165,11 @@ export function kernelMessageToSdk(raw) {
164
165
  .map(part => String(part.text ?? ""))
165
166
  .join("")
166
167
  : "",
168
+ // The canonical ProviderMessage names a call `call_id`; `id` is the legacy SDK spelling.
167
169
  toolCalls: (raw.tool_calls ?? []).map(tc => ({
168
- id: String(tc.id ?? ""),
170
+ id: String(tc.call_id ?? tc.id ?? ""),
169
171
  name: String(tc.name ?? ""),
170
- arguments: JSON.stringify(tc.arguments ?? {}),
172
+ arguments: toolArgumentsFromWire(tc.arguments),
171
173
  })),
172
174
  };
173
175
  if (typeof content === "string") {
@@ -209,6 +211,15 @@ export function kernelMessageToSdk(raw) {
209
211
  message.contentParts = contentParts;
210
212
  }
211
213
  }
214
+ // A tool message the kernel paired through `tool_call_id` is a structural tool result.
215
+ if (!message.contentParts && typeof raw.tool_call_id === "string") {
216
+ message.contentParts = [{
217
+ type: "tool_result",
218
+ callId: raw.tool_call_id,
219
+ output: message.content,
220
+ isError: raw.is_error === true,
221
+ }];
222
+ }
212
223
  return message;
213
224
  }
214
225
  export function renderedContextToSdk(raw) {
@@ -23,6 +23,7 @@
23
23
  * Tokenizer: by default a `chars/4` estimator (±20% for English; worse for code/JSON). For tighter
24
24
  * numbers plug `opts.tokenizer = tiktokenEncoder` or similar.
25
25
  */
26
+ import { malformedToolArguments } from "./tool-arguments.js";
26
27
  const DEFAULT_DESCRIPTOR = {
27
28
  provider: "replay",
28
29
  protocol: "openai-chat",
@@ -92,10 +93,10 @@ export class ReplayProvider {
92
93
  args = JSON.parse(tc.arguments || "{}");
93
94
  }
94
95
  catch {
95
- // Malformed recorded arguments — pass an empty object. The runner's downstream tool
96
- // execution will surface the error if the tool needs them.
96
+ // Malformed recorded arguments: `rawArguments` carries the text so the replayed call
97
+ // fails as invalid, exactly as the recorded one did.
97
98
  }
98
- const call = { type: "tool_call", id: tc.id, name: tc.name, arguments: args };
99
+ const call = { type: "tool_call", id: tc.id, name: tc.name, arguments: args, ...malformedToolArguments(tc.arguments) };
99
100
  yield call;
100
101
  }
101
102
  }
@@ -5,7 +5,7 @@ import type { KnowledgeSource } from "../knowledge/index.js";
5
5
  import type { SignalSource, RuntimeSignal } from "../signals/index.js";
6
6
  import type { SessionLog, SessionEvent } from "./session-log.js";
7
7
  import type { ExecutionPlane } from "./execution-plane.js";
8
- import { type GovernancePolicy } from "../governance.js";
8
+ import { type GovernancePolicy, type LivePolicyPatch } from "../governance.js";
9
9
  import type { KernelJournal } from "./kernel-journal.js";
10
10
  import type { AgentRunSpec, MilestonePolicy, MilestoneContract, MilestoneCheckResult, WorkflowSpec, WorkflowOutcome } from "./types/agent.js";
11
11
  import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
@@ -57,6 +57,8 @@ export interface MemoryPolicy {
57
57
  validationEnabled?: boolean;
58
58
  maxContentBytes?: number;
59
59
  maxNameLength?: number;
60
+ /** M4: recall count at which the kernel suggests promoting a record. Omitted = no suggestions. */
61
+ promotionRecallThreshold?: number;
60
62
  }
61
63
  export interface KernelReliabilityOptions {
62
64
  providerRecoveryAttempts?: number;
@@ -64,6 +66,16 @@ export interface KernelReliabilityOptions {
64
66
  /** Max canonical JSON bytes accepted for one kernel input, 256..64MiB. */
65
67
  maxInputBytes?: number;
66
68
  }
69
+ interface InboundSignalDelivery {
70
+ signalId: string;
71
+ deliveryId: string;
72
+ deliveryAttempt: number;
73
+ signal: RuntimeSignal;
74
+ /** A host note (`injectNote`): delivered as a plain-text payload the model reads verbatim. */
75
+ note?: string;
76
+ ack(): Promise<boolean>;
77
+ nack(): Promise<boolean>;
78
+ }
67
79
  export interface ArchiveStore {
68
80
  write(sessionId: string, startSeq: number, messages: ModelMessage[]): Promise<string | undefined>;
69
81
  read?(archiveRef: string): Promise<ModelMessage[]>;
@@ -275,6 +287,9 @@ export declare class RuntimeRunner {
275
287
  private fallbackPayloadStore;
276
288
  /** O2 (system-reminder channel): host-pushed notes awaiting the next turn-boundary drain. */
277
289
  private injectedSignals;
290
+ /** Host control commands queued by the public control methods; the main loop applies them
291
+ * between effects so a command that publishes an effect never races an in-flight one. */
292
+ private pendingControl;
278
293
  /** Skill names whose content has already been pushed into the durable `knowledge` slot this
279
294
  * run — guards against re-pushing a duplicate entry if the model calls `skill(name)` again for
280
295
  * an already-active skill (loading is idempotent; the knowledge push should be too). */
@@ -338,8 +353,22 @@ export declare class RuntimeRunner {
338
353
  }>;
339
354
  }): AsyncIterable<StreamEvent>;
340
355
  wake(sessionId: string, extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
341
- writeMemory(memory: MemoryRecord, sessionId?: string): Promise<void>;
342
- private appendMemorySyscallObservations;
356
+ /**
357
+ * §22.13 · a host-authored memory write. The kernel decides whether it may happen: a live
358
+ * operation answers through `admit_memory_write` (the model's validation rule and rolling write
359
+ * quota); with no live operation the same kernel rule answers statelessly. Resolves `true` when
360
+ * the record was persisted.
361
+ */
362
+ writeMemory(memory: MemoryRecord, sessionId?: string): Promise<boolean>;
363
+ private admitMemoryWrite;
364
+ /** The run's memory policy as the kernel's canonical wire carries it. */
365
+ private kernelMemoryPolicyWire;
366
+ /**
367
+ * M3/M4 · a host-initiated recall (prefetch). The store reports the counts it holds; the kernel
368
+ * derives the next counts and the promotion edge, and the host only mirrors them — the same
369
+ * derivation a model `query_memory` resolution journals as `memory_recalled`.
370
+ */
371
+ private recordHostMemoryRecall;
343
372
  /** Push content into Slot 2 (system_knowledge) via add_knowledge_message.
344
373
  * K1: `opts.key` gives the entry identity — a same-key push upserts (applied at the next
345
374
  * compaction/renewal boundary) instead of appending a duplicate. `opts.pinned` exempts the
@@ -354,6 +383,22 @@ export declare class RuntimeRunner {
354
383
  removeKnowledge(key: string): Promise<void>;
355
384
  /** K3: host-driven skill deactivation — toolset re-widens at the next provider call, the
356
385
  * skill's knowledge pin drops at the next boundary. Errs-open: not-active is a no-op. */
386
+ /** §13.2 live policy patch (signal / governance / resource quota / recovery), guarded by the
387
+ * policy revision. Mirrors Node: the runtime tracks the committed revision; after a restore
388
+ * `expectedRevision` must be given. Rejects when the kernel refuses the patch. */
389
+ applyPolicyPatch(patch: LivePolicyPatch, opts?: {
390
+ expectedRevision?: number;
391
+ }): Promise<void>;
392
+ /** Move the operation's absolute deadline (epoch ms), or clear it with `null`. */
393
+ updateDeadline(deadlineMs: number | null): Promise<void>;
394
+ /** Ask the kernel to compact context now; any archive it owes runs as a normal page-out effect. */
395
+ forceCompact(): Promise<void>;
396
+ /** Host-driven skill activation, admitted by the kernel against the operation's skill catalog. */
397
+ activateSkill(name: string, opts?: {
398
+ leaseTurns?: number;
399
+ }): Promise<void>;
400
+ private enqueueControl;
401
+ private rejectPendingControl;
357
402
  deactivateSkill(name: string): Promise<void>;
358
403
  private resolveKernelSuspend;
359
404
  private execute;
@@ -418,3 +463,10 @@ export declare function replayMessages(events: Array<{
418
463
  event: SessionEvent;
419
464
  }>, maxBytes?: number, archiveStore?: ArchiveStore): Promise<ModelMessage[]>;
420
465
  export declare function collectText(stream: AsyncIterable<StreamEvent>): Promise<string>;
466
+ /** Lower a claimed signal delivery straight into the kernel's `LogicalSignal` vocabulary. Shared by
467
+ * the main loop's per-turn poll and #2-B-ii's workflow-batch preemption monitor (so the two never
468
+ * drift). `signalType` / `coalesceKey` / `coalescedCount` are signal-source concepts the canonical
469
+ * wire deliberately does not carry (§5n); the absolute `deadlineMs` becomes the duration the kernel
470
+ * anchors to its own accepted time. */
471
+ export declare function signalToKernelEvent(delivery: InboundSignalDelivery | (Omit<InboundSignalDelivery, "ack" | "nack">), nowMs?: number): Record<string, unknown>;
472
+ export {};