@deepstrike/wasm 0.2.41 → 0.2.43
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/harness/index.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface AttemptRequest {
|
|
|
7
7
|
sessionId?: string;
|
|
8
8
|
goal: string;
|
|
9
9
|
criteria?: Criterion[];
|
|
10
|
+
/**
|
|
11
|
+
* Multimodal inputs (images / audio) attached to the task. Forwarded to every attempt
|
|
12
|
+
* unconditionally; the runner seeds them per session idempotently, so fresh-session carries
|
|
13
|
+
* re-seed while same-session carries do not double.
|
|
14
|
+
*/
|
|
15
|
+
attachments?: import("../types.js").ContentPart[];
|
|
10
16
|
extensions?: Record<string, unknown>;
|
|
11
17
|
inheritEvents?: Array<{
|
|
12
18
|
seq: number;
|
package/dist/harness/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export class RuntimeAttemptBody {
|
|
|
14
14
|
sessionId: context.sessionId,
|
|
15
15
|
goal: context.goal,
|
|
16
16
|
criteria: (context.criteria ?? []).map(criterion => criterion.text),
|
|
17
|
+
...(context.attachments?.length ? { attachments: context.attachments } : {}),
|
|
17
18
|
extensions: context.extensions,
|
|
18
19
|
...(context.attempt === 1 && context.inheritEvents
|
|
19
20
|
? { inheritEvents: context.inheritEvents }
|
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export interface ResourceQuota {
|
|
|
22
22
|
maxConcurrentSubagents?: number;
|
|
23
23
|
/** Max sub-agent nesting depth (direct children of the root loop are depth 1). */
|
|
24
24
|
maxSpawnDepth?: number;
|
|
25
|
+
/** Max nodes in one in-kernel workflow DAG, including dynamically submitted nodes. */
|
|
26
|
+
maxWorkflowNodes?: number;
|
|
25
27
|
/** Rolling-window memory-write rate limit: at most `maxWrites` per any `windowMs` span. */
|
|
26
28
|
memoryWritesPerWindow?: MemoryWriteRateLimit;
|
|
27
29
|
}
|
package/dist/runtime/runner.js
CHANGED
|
@@ -41,6 +41,17 @@ function pendingCallIds(action) {
|
|
|
41
41
|
default: return "effectId" in action ? [action.effectId] : [];
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
function controlRequestRejection(observations, operation) {
|
|
45
|
+
const rejected = observations.find(observation => observation.kind === "control_request_rejected"
|
|
46
|
+
&& (!operation || observation.operation === operation));
|
|
47
|
+
if (!rejected)
|
|
48
|
+
return undefined;
|
|
49
|
+
return {
|
|
50
|
+
operation: rejected.operation ?? operation ?? "control_request",
|
|
51
|
+
...(rejected.subject ? { subject: rejected.subject } : {}),
|
|
52
|
+
reason: typeof rejected.reason === "string" ? rejected.reason : "request denied",
|
|
53
|
+
};
|
|
54
|
+
}
|
|
44
55
|
export class RuntimeRunner {
|
|
45
56
|
opts;
|
|
46
57
|
interrupted = false;
|
|
@@ -147,6 +158,12 @@ export class RuntimeRunner {
|
|
|
147
158
|
async *run(req) {
|
|
148
159
|
const prior = req.inheritEvents ?? await this.opts.sessionLog.read(req.sessionId);
|
|
149
160
|
const midRun = isMidRun(prior);
|
|
161
|
+
// Idempotent per session: an earlier run's `run_started` already carries these attachments
|
|
162
|
+
// (same-session retry attempt), so replay reconstructs them — recording and seeding again
|
|
163
|
+
// would double them in history. Deduping at the append keeps live and replay in agreement.
|
|
164
|
+
const attachments = req.attachments?.length && !attachmentsAlreadySeeded(prior, req.attachments)
|
|
165
|
+
? req.attachments
|
|
166
|
+
: undefined;
|
|
150
167
|
if (!midRun) {
|
|
151
168
|
await this.opts.sessionLog.append(req.sessionId, {
|
|
152
169
|
kind: "run_started",
|
|
@@ -155,10 +172,10 @@ export class RuntimeRunner {
|
|
|
155
172
|
criteria: req.criteria ?? [],
|
|
156
173
|
agent_id: this.opts.agentId,
|
|
157
174
|
system_prompt: this.opts.systemPrompt,
|
|
158
|
-
...(
|
|
175
|
+
...(attachments ? { attachments } : {}),
|
|
159
176
|
});
|
|
160
177
|
}
|
|
161
|
-
yield* this.execute(req.sessionId, req.goal, req.criteria ?? [], req.extensions, prior.length > 0 ? prior : undefined, midRun,
|
|
178
|
+
yield* this.execute(req.sessionId, req.goal, req.criteria ?? [], req.extensions, prior.length > 0 ? prior : undefined, midRun, attachments);
|
|
162
179
|
}
|
|
163
180
|
async *wake(sessionId, extensions) {
|
|
164
181
|
const events = await this.opts.sessionLog.read(sessionId);
|
|
@@ -869,7 +886,7 @@ export class RuntimeRunner {
|
|
|
869
886
|
const spec = parseStartWorkflowSpec(call.arguments);
|
|
870
887
|
if (spec) {
|
|
871
888
|
this.pendingAuthoredWorkflows.push(spec);
|
|
872
|
-
const out = "workflow
|
|
889
|
+
const out = "workflow submitted for governance adjudication";
|
|
873
890
|
toolResults.push({ callId: call.id, output: out, isError: false });
|
|
874
891
|
yield { type: "tool_result", callId: call.id, content: out, isError: false };
|
|
875
892
|
continue;
|
|
@@ -879,8 +896,9 @@ export class RuntimeRunner {
|
|
|
879
896
|
? parseStartWorkflowArgs(call.arguments)
|
|
880
897
|
: parseSubmitWorkflowNodesArgs(call.arguments);
|
|
881
898
|
yield { type: "workflow_nodes_submitted", nodes };
|
|
882
|
-
|
|
883
|
-
|
|
899
|
+
const out = "workflow nodes submitted for parent governance adjudication";
|
|
900
|
+
toolResults.push({ callId: call.id, output: out, isError: false });
|
|
901
|
+
yield { type: "tool_result", callId: call.id, content: out, isError: false };
|
|
884
902
|
}
|
|
885
903
|
// O5 (PreToolUse-hook analog): stateful host veto over each kernel-approved call.
|
|
886
904
|
// A blocked call never executes; its reason reaches the model as a denied result.
|
|
@@ -1189,8 +1207,25 @@ export class RuntimeRunner {
|
|
|
1189
1207
|
});
|
|
1190
1208
|
this.nextArchiveStart = await this.appendObservations(parentSessionId, runtime, this.nextArchiveStart);
|
|
1191
1209
|
const spawned = findSpawnProcessObservation(observations);
|
|
1192
|
-
if (!spawned)
|
|
1210
|
+
if (!spawned) {
|
|
1211
|
+
const rejected = controlRequestRejection(observations, "spawn_sub_agent");
|
|
1212
|
+
if (rejected) {
|
|
1213
|
+
return {
|
|
1214
|
+
agentId: rejected.subject ?? spec.identity.agentId,
|
|
1215
|
+
result: {
|
|
1216
|
+
termination: "error",
|
|
1217
|
+
finalMessage: {
|
|
1218
|
+
role: "assistant",
|
|
1219
|
+
content: `spawn_sub_agent denied: ${rejected.reason}`,
|
|
1220
|
+
toolCalls: [],
|
|
1221
|
+
},
|
|
1222
|
+
turnsUsed: 0,
|
|
1223
|
+
totalTokensUsed: 0,
|
|
1224
|
+
},
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1193
1227
|
throw new Error("spawn_sub_agent did not emit agent_process_changed");
|
|
1228
|
+
}
|
|
1194
1229
|
const manifest = spawnObservationToManifest(spawned, spec, parentSessionId);
|
|
1195
1230
|
const orchestrator = this.opts.subAgentOrchestrator ?? defaultSubAgentOrchestrator;
|
|
1196
1231
|
const result = await orchestrator.run({
|
|
@@ -1392,6 +1427,7 @@ export class RuntimeRunner {
|
|
|
1392
1427
|
config.resource_quota = {
|
|
1393
1428
|
...(q.maxConcurrentSubagents !== undefined ? { max_concurrent_subagents: q.maxConcurrentSubagents } : {}),
|
|
1394
1429
|
...(q.maxSpawnDepth !== undefined ? { max_spawn_depth: q.maxSpawnDepth } : {}),
|
|
1430
|
+
...(q.maxWorkflowNodes !== undefined ? { max_workflow_nodes: q.maxWorkflowNodes } : {}),
|
|
1395
1431
|
...(q.memoryWritesPerWindow !== undefined
|
|
1396
1432
|
? { memory_writes_per_window: [q.memoryWritesPerWindow.maxWrites, q.memoryWritesPerWindow.windowMs] }
|
|
1397
1433
|
: {}),
|
|
@@ -1641,6 +1677,11 @@ export class RuntimeRunner {
|
|
|
1641
1677
|
}
|
|
1642
1678
|
if (!initialAction)
|
|
1643
1679
|
return { nodeOutcomes: [], outputs: {} };
|
|
1680
|
+
const workflowRejection = controlRequestRejection(observations);
|
|
1681
|
+
if (initialAction.kind === "call_provider" && workflowRejection) {
|
|
1682
|
+
this.workflowContinuation = initialAction;
|
|
1683
|
+
return { nodeOutcomes: [], outputs: {}, rejection: workflowRejection };
|
|
1684
|
+
}
|
|
1644
1685
|
if (initialAction.kind !== "spawn_workflow") {
|
|
1645
1686
|
throw new Error(`workflow load returned unexpected kernel effect: ${initialAction.kind}`);
|
|
1646
1687
|
}
|
|
@@ -1687,6 +1728,22 @@ export class RuntimeRunner {
|
|
|
1687
1728
|
const observationStart = this.pendingObservations.length;
|
|
1688
1729
|
const submitAction = kernelMaybeAction(runtime, this.pendingObservations, submitEvent);
|
|
1689
1730
|
const subObs = this.pendingObservations.slice(observationStart);
|
|
1731
|
+
const nodesRejected = subObs.find(observation => observation.kind === "nodes_rejected");
|
|
1732
|
+
const rejected = controlRequestRejection(subObs, "submit_workflow_nodes")
|
|
1733
|
+
?? (nodesRejected
|
|
1734
|
+
? { operation: "submit_workflow_nodes", reason: String(nodesRejected.reason ?? "request denied") }
|
|
1735
|
+
: undefined);
|
|
1736
|
+
if (rejected) {
|
|
1737
|
+
const denial = `workflow node submission denied: ${rejected.reason}`;
|
|
1738
|
+
result.result = {
|
|
1739
|
+
...result.result,
|
|
1740
|
+
termination: "error",
|
|
1741
|
+
finalMessage: { role: "assistant", content: denial, toolCalls: [] },
|
|
1742
|
+
};
|
|
1743
|
+
outputs.set(result.agentId, denial);
|
|
1744
|
+
if (stableId !== result.agentId)
|
|
1745
|
+
outputs.set(stableId, denial);
|
|
1746
|
+
}
|
|
1690
1747
|
if (submitAction?.kind === "spawn_workflow") {
|
|
1691
1748
|
nextNodes.push(...submitAction.nodes);
|
|
1692
1749
|
budget = submitAction.budget ?? budget;
|
|
@@ -2092,6 +2149,15 @@ function signalToKernelEvent(delivery) {
|
|
|
2092
2149
|
},
|
|
2093
2150
|
};
|
|
2094
2151
|
}
|
|
2152
|
+
/**
|
|
2153
|
+
* True when an earlier run in this session already seeded the same attachments. Replay
|
|
2154
|
+
* reconstructs the attachment message from that run's `run_started`, so recording and
|
|
2155
|
+
* live-seeding them again (a same-session retry attempt) would double them in history.
|
|
2156
|
+
*/
|
|
2157
|
+
function attachmentsAlreadySeeded(prior, attachments) {
|
|
2158
|
+
const wanted = JSON.stringify(attachments);
|
|
2159
|
+
return prior.some(({ event }) => event.kind === "run_started" && JSON.stringify(event.attachments ?? []) === wanted);
|
|
2160
|
+
}
|
|
2095
2161
|
/** Convert SDK ContentParts (camelCase mediaType) to kernel serde shape (media_type). */
|
|
2096
2162
|
function attachmentsToKernelMessage(parts) {
|
|
2097
2163
|
const content = parts.map(p => {
|
|
@@ -196,9 +196,15 @@ export interface WorkflowNodeOutcome {
|
|
|
196
196
|
termination?: TerminationReason;
|
|
197
197
|
output?: Message;
|
|
198
198
|
}
|
|
199
|
+
export interface ControlRequestRejection {
|
|
200
|
+
operation: string;
|
|
201
|
+
subject?: string;
|
|
202
|
+
reason: string;
|
|
203
|
+
}
|
|
199
204
|
export interface WorkflowOutcome {
|
|
200
205
|
nodeOutcomes: WorkflowNodeOutcome[];
|
|
201
206
|
outputs: Record<string, string>;
|
|
207
|
+
rejection?: ControlRequestRejection;
|
|
202
208
|
}
|
|
203
209
|
export declare function workflowNodeOutcomeFromKernel(raw: KernelWorkflowNodeOutcome): WorkflowNodeOutcome;
|
|
204
210
|
/** Per-node spawn descriptor carried in the `workflow_batch_spawned` observation. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.43",
|
|
4
4
|
"description": "DeepStrike WASM SDK — browser, Cloudflare Workers, Deno Deploy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"README.md"
|
|
11
11
|
],
|
|
12
12
|
"scripts": {
|
|
13
|
-
"build:wasm": "wasm-pack build
|
|
13
|
+
"build:wasm": "wasm-pack build ../crates/deepstrike-wasm --target bundler --out-dir ../../wasm/pkg",
|
|
14
14
|
"build": "tsc",
|
|
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.43"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/jest": "^30.0.0",
|