@deepstrike/wasm 0.2.43 → 0.2.45
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.
|
@@ -18,7 +18,6 @@ export function restoreKernelRuntime(runtime, snapshot) {
|
|
|
18
18
|
}, 1);
|
|
19
19
|
kernelWireStates.set(runtime, { operationId, nextEventSequence });
|
|
20
20
|
}
|
|
21
|
-
let nextOperationSequence = 1;
|
|
22
21
|
const kernelWireStates = new WeakMap();
|
|
23
22
|
function tryParseJson(s) {
|
|
24
23
|
try {
|
|
@@ -267,7 +266,10 @@ function mapKernelAction(raw) {
|
|
|
267
266
|
function stepInput(runtime, event) {
|
|
268
267
|
let state = kernelWireStates.get(runtime);
|
|
269
268
|
if (!state) {
|
|
270
|
-
|
|
269
|
+
// Globally unique, never a process-local counter: durable session logs key the kernel
|
|
270
|
+
// genesis/transaction chains by (sessionId, operationId) and outlive this isolate, so a
|
|
271
|
+
// counter that restarts at 1 collides with a prior chain on the same session.
|
|
272
|
+
state = { operationId: `wasm-operation-${crypto.randomUUID()}`, nextEventSequence: 1 };
|
|
271
273
|
kernelWireStates.set(runtime, state);
|
|
272
274
|
}
|
|
273
275
|
const correlatedEvent = event.kind === "cancel_operation"
|
|
@@ -43,14 +43,15 @@ export declare class LargeResultSpool {
|
|
|
43
43
|
private writeToDriver;
|
|
44
44
|
private generatePreview;
|
|
45
45
|
processToolResult(result: ToolResult): Promise<SpooledToolResult>;
|
|
46
|
-
|
|
46
|
+
private callKey;
|
|
47
|
+
persistOutput(sessionId: string, callId: string, content: string): Promise<string>;
|
|
47
48
|
readSpooledResult(spoolRef: string): Promise<string>;
|
|
48
49
|
/**
|
|
49
50
|
* O7: locate a spooled output by the tool call's id (the `read_result` meta-tool only knows
|
|
50
51
|
* `call_id`, not the content-hashed key `persistOutput` chose). Scans the driver's key list for
|
|
51
|
-
* the
|
|
52
|
+
* the hashed session-scoped call-key prefix; returns `undefined` if nothing was ever
|
|
52
53
|
* spooled for that call.
|
|
53
54
|
*/
|
|
54
|
-
findByCallId(callId: string): Promise<string | undefined>;
|
|
55
|
+
findByCallId(sessionId: string, callId: string): Promise<string | undefined>;
|
|
55
56
|
cleanup(maxAgeMs?: number): Promise<number>;
|
|
56
57
|
}
|
|
@@ -92,9 +92,16 @@ omitted: ${omitted} chars
|
|
|
92
92
|
wasSpooled: true,
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
callKey(sessionId, callId) {
|
|
96
|
+
// Session-scoped and hashed: the driver's key space is shared across sessions and outlives
|
|
97
|
+
// runs, while vendor call ids can be index-style ("call_0") and repeat — an unscoped key
|
|
98
|
+
// lets read_result in one session fetch another session's spooled output. Hashing also keeps
|
|
99
|
+
// untrusted call-id characters out of driver keys (parity with Node/Python).
|
|
100
|
+
return simpleHash(`${sessionId}\u0000${callId}`);
|
|
101
|
+
}
|
|
102
|
+
async persistOutput(sessionId, callId, content) {
|
|
96
103
|
const hash = simpleHash(content);
|
|
97
|
-
const key = `.spool/${callId}-${hash.slice(0, 16)}.txt`;
|
|
104
|
+
const key = `.spool/${this.callKey(sessionId, callId)}-${hash.slice(0, 16)}.txt`;
|
|
98
105
|
let promise = this.activeWrites.get(key);
|
|
99
106
|
if (!promise) {
|
|
100
107
|
promise = (async () => {
|
|
@@ -116,10 +123,10 @@ omitted: ${omitted} chars
|
|
|
116
123
|
/**
|
|
117
124
|
* O7: locate a spooled output by the tool call's id (the `read_result` meta-tool only knows
|
|
118
125
|
* `call_id`, not the content-hashed key `persistOutput` chose). Scans the driver's key list for
|
|
119
|
-
* the
|
|
126
|
+
* the hashed session-scoped call-key prefix; returns `undefined` if nothing was ever
|
|
120
127
|
* spooled for that call.
|
|
121
128
|
*/
|
|
122
|
-
async findByCallId(callId) {
|
|
129
|
+
async findByCallId(sessionId, callId) {
|
|
123
130
|
let keys;
|
|
124
131
|
try {
|
|
125
132
|
keys = await this.driver.list();
|
|
@@ -127,7 +134,7 @@ omitted: ${omitted} chars
|
|
|
127
134
|
catch {
|
|
128
135
|
return undefined;
|
|
129
136
|
}
|
|
130
|
-
const prefix = `.spool/${callId}-`;
|
|
137
|
+
const prefix = `.spool/${this.callKey(sessionId, callId)}-`;
|
|
131
138
|
const match = keys.find(k => k.startsWith(prefix) && k.endsWith('.txt'));
|
|
132
139
|
if (!match)
|
|
133
140
|
return undefined;
|
package/dist/runtime/runner.js
CHANGED
|
@@ -358,7 +358,7 @@ export class RuntimeRunner {
|
|
|
358
358
|
let full;
|
|
359
359
|
if (full === undefined && this.opts.resultSpool) {
|
|
360
360
|
try {
|
|
361
|
-
full = await this.opts.resultSpool.findByCallId(callId);
|
|
361
|
+
full = await this.opts.resultSpool.findByCallId(sessionId, callId);
|
|
362
362
|
}
|
|
363
363
|
catch {
|
|
364
364
|
full = undefined;
|
|
@@ -807,7 +807,7 @@ export class RuntimeRunner {
|
|
|
807
807
|
let spoolRef;
|
|
808
808
|
let error;
|
|
809
809
|
try {
|
|
810
|
-
spoolRef = await spool.persistOutput(action.callId, action.output);
|
|
810
|
+
spoolRef = await spool.persistOutput(sessionId, action.callId, action.output);
|
|
811
811
|
}
|
|
812
812
|
catch (cause) {
|
|
813
813
|
error = formatToolError(cause);
|
package/dist/tools/index.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { formatToolError } from "./errors.js";
|
|
2
2
|
export function tool(name, description, parameters, fn) {
|
|
3
|
+
// Fail at registration, not as a vendor 400 at call time: every major provider rejects a tool
|
|
4
|
+
// whose parameters root is not `type: "object"` — wrap union variants under an object root.
|
|
5
|
+
if (!parameters || typeof parameters !== "object" || Array.isArray(parameters) || parameters.type !== "object") {
|
|
6
|
+
throw new Error(`tool "${name}": parameters must be a JSON Schema with root type "object" `
|
|
7
|
+
+ `(got type: ${JSON.stringify(parameters?.type ?? null)})`);
|
|
8
|
+
}
|
|
3
9
|
return {
|
|
4
10
|
schema: { name, description, parameters: JSON.stringify(parameters) },
|
|
5
11
|
async execute(args, ctx) { return fn(args, ctx); },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.45",
|
|
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.45"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/jest": "^30.0.0",
|