@deepstrike/wasm 0.2.49 → 0.2.50
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/runtime/runner.d.ts
CHANGED
|
@@ -209,11 +209,52 @@ export interface RuntimeOptions {
|
|
|
209
209
|
requiredEvidence: string[];
|
|
210
210
|
}) => Promise<MilestoneCheckResult> | MilestoneCheckResult;
|
|
211
211
|
runSpec?: AgentRunSpec;
|
|
212
|
-
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
212
|
+
/**
|
|
213
|
+
* The run's **exposure ceiling** — the outer bound on what this run may EVER advertise to the
|
|
214
|
+
* model. Not a static profile: it is an INTERSECTION applied on every turn (`exposed ⊆ ceiling`),
|
|
215
|
+
* so every narrowing mechanism operates *within* it and none can widen past it. Skills narrow
|
|
216
|
+
* inside the ceiling (`allowed_tools`), `baselineToolIds` selects which of the ceiling's tools are
|
|
217
|
+
* exposed before any skill activates, and `stableCoreToolIds` pins tools against skill narrowing.
|
|
218
|
+
*
|
|
219
|
+
* Exempt on the id axis: the kernel-owned meta-tools (`skill`, `memory`, `knowledge`,
|
|
220
|
+
* `update_plan`, `read_result`) stay exposed regardless of this list — a ceiling that hid `skill`
|
|
221
|
+
* would make progressive disclosure unreachable. The KIND axis
|
|
222
|
+
* (`runSpec.capabilityFilter.allowedKinds`) still applies to them.
|
|
223
|
+
*
|
|
224
|
+
* Byte-stable across the run, so it never busts the prompt-cache prefix. Lowers to the same
|
|
225
|
+
* `capability_filter` sub-agents use: augments `runSpec`'s filter when both are set, else
|
|
226
|
+
* synthesizes a minimal run spec. Omitted **or empty** ⇒ no ceiling (all registered tools) — the
|
|
227
|
+
* empty array is NOT a minimal surface here; use `baselineToolIds: []` for that.
|
|
228
|
+
*
|
|
229
|
+
* Enforcement: `toolDispatchGate` (default `"exposed"`) makes this a real boundary — a call to a
|
|
230
|
+
* tool outside the advertised set never executes.
|
|
231
|
+
*/
|
|
216
232
|
allowedToolIds?: string[];
|
|
233
|
+
/**
|
|
234
|
+
* The **pre-activation** exposure surface, selected from under the `allowedToolIds` ceiling.
|
|
235
|
+
* Makes the narrow→wide progressive-disclosure shape expressible: start the run advertising only
|
|
236
|
+
* these tools, and let a skill activation widen the surface by exactly its declared
|
|
237
|
+
* `allowed_tools` (still ∩ the ceiling). Per turn:
|
|
238
|
+
*
|
|
239
|
+
* `exposed = meta ∪ ((baseline ∪ stableCore ∪ ⋃ activeSkills.allowed_tools) ∩ ceiling)`
|
|
240
|
+
*
|
|
241
|
+
* An active skill that declares no `allowed_tools` contributes nothing — with a baseline set the
|
|
242
|
+
* surface stays narrow (strict; the legacy errs-open widening is deliberately not inherited).
|
|
243
|
+
*
|
|
244
|
+
* `undefined` ⇒ legacy behavior, byte-identical. `[]` is a legitimate, distinct value: the minimal
|
|
245
|
+
* surface (meta-tools + `stableCoreToolIds` only) — the `allowedToolIds` "empty means no gating"
|
|
246
|
+
* trap does NOT recur here. Entries outside the ceiling silently intersect away.
|
|
247
|
+
*/
|
|
248
|
+
baselineToolIds?: string[];
|
|
249
|
+
/**
|
|
250
|
+
* Dispatch enforcement for the exposure surface. `"exposed"` (default) is fail-closed: a tool call
|
|
251
|
+
* the model was never advertised this turn never reaches the host — the kernel commits a
|
|
252
|
+
* model-visible `governance_denied` result instead, which feeds the repeat fuse like any other
|
|
253
|
+
* denial. Allowed siblings in the same batch still execute; `pace` and the meta-tool family always
|
|
254
|
+
* pass through. `"registered"` is the escape hatch restoring the pre-gate permissive behavior (any
|
|
255
|
+
* registered tool the model names executes, even if it was gated out of the tools schema).
|
|
256
|
+
*/
|
|
257
|
+
toolDispatchGate?: "exposed" | "registered";
|
|
217
258
|
/** P0-C: optional per-turn metrics sink for tool-gating telemetry (see `TurnMetrics`). Pure
|
|
218
259
|
* observation; invoked once per LLM turn. Never throws into the run loop (errors are swallowed). */
|
|
219
260
|
onTurnMetrics?: (metrics: TurnMetrics) => void;
|
package/dist/runtime/runner.js
CHANGED
|
@@ -539,20 +539,26 @@ export class RuntimeRunner {
|
|
|
539
539
|
kind: "start_run",
|
|
540
540
|
task: { goal, criteria },
|
|
541
541
|
};
|
|
542
|
-
// P0-A: lower an explicit `runSpec
|
|
543
|
-
//
|
|
544
|
-
// gating (铁律: no config = old behavior).
|
|
542
|
+
// P0-A: lower an explicit `runSpec`, the `allowedToolIds` ceiling, and/or the `baselineToolIds`
|
|
543
|
+
// pre-activation surface to the kernel run spec (reuses the existing run_spec wire — no new
|
|
544
|
+
// ABI). Unset on all ⇒ no gating (铁律: no config = old behavior).
|
|
545
545
|
const allowedToolIds = this.opts.allowedToolIds;
|
|
546
546
|
const hasProfile = allowedToolIds !== undefined && allowedToolIds.length > 0;
|
|
547
|
-
|
|
547
|
+
// NOT the `length > 0` idiom above: `baselineToolIds: []` is the legitimate minimal surface
|
|
548
|
+
// (meta + stable-core only), so mere presence triggers the lowering.
|
|
549
|
+
const baselineToolIds = this.opts.baselineToolIds;
|
|
550
|
+
const hasBaseline = baselineToolIds !== undefined;
|
|
551
|
+
if (this.opts.runSpec || hasProfile || hasBaseline) {
|
|
548
552
|
const baseSpec = this.opts.runSpec ?? {
|
|
549
553
|
identity: { agentId: this.opts.agentId ?? "root", sessionId, isSubAgent: false },
|
|
550
554
|
role: "custom",
|
|
551
555
|
goal,
|
|
552
556
|
};
|
|
553
|
-
|
|
557
|
+
let spec = hasProfile
|
|
554
558
|
? { ...baseSpec, capabilityFilter: { ...baseSpec.capabilityFilter, allowedIds: allowedToolIds } }
|
|
555
559
|
: baseSpec;
|
|
560
|
+
if (hasBaseline)
|
|
561
|
+
spec = { ...spec, exposureBaseline: baselineToolIds };
|
|
556
562
|
startPayload.run_spec = agentRunSpecToKernel(spec);
|
|
557
563
|
}
|
|
558
564
|
this.applyKernelPolicies(runtime);
|
|
@@ -1458,6 +1464,11 @@ export class RuntimeRunner {
|
|
|
1458
1464
|
if (this.opts.criteriaGate !== undefined) {
|
|
1459
1465
|
config.criteria_gate = this.opts.criteriaGate;
|
|
1460
1466
|
}
|
|
1467
|
+
// P1: fail-closed dispatch selector (absent ⇒ kernel default "exposed"). "registered" is the
|
|
1468
|
+
// escape hatch back to permissive dispatch; the kernel rejects any other value.
|
|
1469
|
+
if (this.opts.toolDispatchGate !== undefined) {
|
|
1470
|
+
config.tool_dispatch_gate = this.opts.toolDispatchGate;
|
|
1471
|
+
}
|
|
1461
1472
|
// K2: knowledge budget ratio (absent ⇒ kernel default 0.25; 0 disables).
|
|
1462
1473
|
if (this.opts.knowledgeBudgetRatio !== undefined) {
|
|
1463
1474
|
config.knowledge_budget_ratio = this.opts.knowledgeBudgetRatio;
|
|
@@ -41,6 +41,14 @@ export interface AgentRunSpec {
|
|
|
41
41
|
/** ③ loop-agent rounds: presence makes this run ONE round of a paced loop (gates the
|
|
42
42
|
* kernel `pace` meta-tool and arms the pacing trap). */
|
|
43
43
|
loopRound?: LoopRoundSpec;
|
|
44
|
+
/** Exposure baseline — the PRE-ACTIVATION tool surface *under* the `capabilityFilter` ceiling.
|
|
45
|
+
* The ceiling bounds what this run may EVER expose; the baseline selects which of those are
|
|
46
|
+
* advertised before any skill activates, so `exposed = meta ∪ ((baseline ∪ stableCore ∪
|
|
47
|
+
* ⋃ activeSkills.allowed_tools) ∩ ceiling)`. That makes narrow→wide progressive disclosure
|
|
48
|
+
* expressible. Absent ⇒ legacy behavior. `[]` is meaningful and distinct from absent: the minimal
|
|
49
|
+
* surface (meta-tools + stable-core only). Entries outside the ceiling silently intersect away.
|
|
50
|
+
* Lowered from `RuntimeOptions.baselineToolIds`. */
|
|
51
|
+
exposureBaseline?: string[];
|
|
44
52
|
/** M1/G3: per-agent model preference; the host resolves it via `RuntimeOptions.providerFor`.
|
|
45
53
|
* Host-side routing only — not sent to the kernel. */
|
|
46
54
|
modelHint?: string;
|
|
@@ -54,6 +54,11 @@ export function agentRunSpecToKernel(spec) {
|
|
|
54
54
|
...(spec.loopRound.defaultAction !== undefined ? { default_action: spec.loopRound.defaultAction } : {}),
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
+
// Exposure baseline: `undefined` ⇒ omit the field entirely (kernel `None` = legacy behavior);
|
|
58
|
+
// `[]` ⇒ send `[]` (kernel `Some([])` = the minimal surface). The unset/minimal distinction is
|
|
59
|
+
// load-bearing, so this is deliberately NOT the `length > 0` idiom `allowedToolIds` uses.
|
|
60
|
+
if (spec.exposureBaseline !== undefined)
|
|
61
|
+
out.exposure_baseline = [...spec.exposureBaseline];
|
|
57
62
|
return out;
|
|
58
63
|
}
|
|
59
64
|
export function milestoneContractToKernel(contract) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.50",
|
|
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.50"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/jest": "^30.0.0",
|