@deepstrike/sdk 0.2.43 → 0.2.44

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.
@@ -19,7 +19,6 @@ export function restoreKernelRuntime(runtime, snapshot) {
19
19
  }, 1);
20
20
  kernelWireStates.set(runtime, { operationId, nextEventSequence });
21
21
  }
22
- let nextOperationSequence = 1;
23
22
  const kernelWireStates = new WeakMap();
24
23
  function tryParseJson(s) {
25
24
  try {
@@ -370,8 +369,12 @@ function mapKernelAction(raw) {
370
369
  function stepInput(runtime, event) {
371
370
  let state = kernelWireStates.get(runtime);
372
371
  if (!state) {
372
+ // Globally unique, never a process-local counter: durable session logs key the kernel
373
+ // genesis/transaction chains by (sessionId, operationId) and outlive this process, so a
374
+ // counter that restarts at 1 collides with yesterday's chain on the same session (genesis
375
+ // digest conflict, or step_seq successor violation when the policy digest happens to match).
373
376
  state = {
374
- operationId: `node-operation-${nextOperationSequence++}`,
377
+ operationId: `node-operation-${crypto.randomUUID()}`,
375
378
  nextEventSequence: 1,
376
379
  };
377
380
  kernelWireStates.set(runtime, state);
@@ -74,7 +74,7 @@ export declare class LargeResultSpool {
74
74
  /**
75
75
  * Persist a kernel-spooled tool output to disk. Returns the on-disk path ref.
76
76
  */
77
- persistOutput(callId: string, content: string): Promise<string>;
77
+ persistOutput(sessionId: string, callId: string, content: string): Promise<string>;
78
78
  /**
79
79
  * Read a spooled result back from disk.
80
80
  */
@@ -85,7 +85,7 @@ export declare class LargeResultSpool {
85
85
  * for the hashed call-key prefix; returns `undefined` if nothing was ever spooled
86
86
  * for that call (e.g. it never actually exceeded the threshold, or the spool dir was cleaned up).
87
87
  */
88
- findByCallId(callId: string): Promise<string | undefined>;
88
+ findByCallId(sessionId: string, callId: string): Promise<string | undefined>;
89
89
  /**
90
90
  * Clean up old spool files (optional maintenance).
91
91
  */
@@ -46,8 +46,11 @@ export class LargeResultSpool {
46
46
  getSpoolPath(hash) {
47
47
  return path.join(this.spoolDir, `${hash}.txt`);
48
48
  }
49
- callKey(callId) {
50
- return this.hashContent(callId).slice(0, 32);
49
+ callKey(sessionId, callId) {
50
+ // Session-scoped: the spool dir is shared across sessions and outlives runs, while vendor
51
+ // call ids can be index-style ("call_0") and repeat — an unscoped key lets read_result in
52
+ // one session fetch another session's spooled output.
53
+ return this.hashContent(`${sessionId}\u0000${callId}`).slice(0, 32);
51
54
  }
52
55
  async atomicWrite(spoolPath, content) {
53
56
  const tempPath = `${spoolPath}.${process.pid}.${crypto.randomUUID()}.tmp`;
@@ -128,9 +131,9 @@ omitted: ${omitted} chars
128
131
  /**
129
132
  * Persist a kernel-spooled tool output to disk. Returns the on-disk path ref.
130
133
  */
131
- async persistOutput(callId, content) {
134
+ async persistOutput(sessionId, callId, content) {
132
135
  const hash = this.hashContent(content);
133
- const spoolPath = this.getSpoolPath(`${this.callKey(callId)}-${hash.slice(0, 16)}`);
136
+ const spoolPath = this.getSpoolPath(`${this.callKey(sessionId, callId)}-${hash.slice(0, 16)}`);
134
137
  let promise = this.activeWrites.get(spoolPath);
135
138
  if (!promise) {
136
139
  promise = (async () => {
@@ -165,7 +168,7 @@ omitted: ${omitted} chars
165
168
  * for the hashed call-key prefix; returns `undefined` if nothing was ever spooled
166
169
  * for that call (e.g. it never actually exceeded the threshold, or the spool dir was cleaned up).
167
170
  */
168
- async findByCallId(callId) {
171
+ async findByCallId(sessionId, callId) {
169
172
  let files;
170
173
  try {
171
174
  files = await fs.readdir(this.spoolDir);
@@ -173,7 +176,7 @@ omitted: ${omitted} chars
173
176
  catch {
174
177
  return undefined;
175
178
  }
176
- const prefix = `${this.callKey(callId)}-`;
179
+ const prefix = `${this.callKey(sessionId, callId)}-`;
177
180
  const match = files.find(f => f.startsWith(prefix) && f.endsWith('.txt'));
178
181
  if (!match)
179
182
  return undefined;
@@ -1340,7 +1340,7 @@ export class RuntimeRunner {
1340
1340
  let full;
1341
1341
  const spool = this.opts.resultSpool ?? new LargeResultSpool();
1342
1342
  try {
1343
- full = await spool.findByCallId(callId);
1343
+ full = await spool.findByCallId(sessionId, callId);
1344
1344
  }
1345
1345
  catch {
1346
1346
  full = undefined;
@@ -1856,7 +1856,7 @@ export class RuntimeRunner {
1856
1856
  let spoolRef;
1857
1857
  let error;
1858
1858
  try {
1859
- spoolRef = await spool.persistOutput(action.callId, action.output);
1859
+ spoolRef = await spool.persistOutput(sessionId, action.callId, action.output);
1860
1860
  }
1861
1861
  catch (cause) {
1862
1862
  error = formatToolError(cause);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.43",
3
+ "version": "0.2.44",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "dependencies": {
74
74
  "@anthropic-ai/sdk": "^0.99.0",
75
- "@deepstrike/core": "0.2.43",
75
+ "@deepstrike/core": "0.2.44",
76
76
  "@google/generative-ai": "^0.24.1",
77
77
  "openai": "^5.23.2"
78
78
  },