@deepstrike/sdk 0.2.50 → 0.2.52

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.
Files changed (39) hide show
  1. package/README.md +83 -60
  2. package/dist/index.d.ts +5 -7
  3. package/dist/index.js +3 -3
  4. package/dist/kernel.d.ts +61 -31
  5. package/dist/runtime/canonical-kernel-step.d.ts +152 -0
  6. package/dist/runtime/canonical-kernel-step.js +1483 -0
  7. package/dist/runtime/execution-plane.d.ts +0 -3
  8. package/dist/runtime/execution-plane.js +0 -24
  9. package/dist/runtime/facade.js +3 -0
  10. package/dist/runtime/kernel-event-log.js +7 -13
  11. package/dist/runtime/kernel-journal.d.ts +264 -0
  12. package/dist/runtime/kernel-journal.js +741 -0
  13. package/dist/runtime/kernel-primitives-dashboard.d.ts +0 -2
  14. package/dist/runtime/kernel-primitives-dashboard.js +1 -8
  15. package/dist/runtime/kernel-step.d.ts +29 -109
  16. package/dist/runtime/kernel-step.js +47 -317
  17. package/dist/runtime/os-snapshot.d.ts +2 -2
  18. package/dist/runtime/os-snapshot.js +2 -6
  19. package/dist/runtime/payload-store.d.ts +16 -0
  20. package/dist/runtime/payload-store.js +80 -0
  21. package/dist/runtime/runner.d.ts +31 -114
  22. package/dist/runtime/runner.js +689 -774
  23. package/dist/runtime/session-log.d.ts +34 -32
  24. package/dist/runtime/session-log.js +21 -131
  25. package/dist/runtime/session-repair.d.ts +2 -36
  26. package/dist/runtime/session-repair.js +2 -47
  27. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  28. package/dist/runtime/sub-agent-orchestrator.js +42 -40
  29. package/dist/types/agent.d.ts +22 -19
  30. package/dist/types/agent.js +26 -42
  31. package/dist/workflow/public.d.ts +1 -1
  32. package/dist/workflow/public.js +1 -1
  33. package/package.json +2 -2
  34. package/dist/runtime/kernel-rebuild.d.ts +0 -13
  35. package/dist/runtime/kernel-rebuild.js +0 -75
  36. package/dist/runtime/kernel-transaction-log.d.ts +0 -61
  37. package/dist/runtime/kernel-transaction-log.js +0 -149
  38. package/dist/runtime/large-result-spool.d.ts +0 -93
  39. package/dist/runtime/large-result-spool.js +0 -214
@@ -1,214 +0,0 @@
1
- /**
2
- * Large result spool (Layer 1 of 5-layer compression pyramid).
3
- *
4
- * When a single tool result exceeds 50KB, write the full content to disk
5
- * and keep only a 2KB preview in the message. Zero API overhead.
6
- *
7
- * Design principles:
8
- * - Kernel defines policy (thresholds)
9
- * - SDK performs I/O (disk write/read)
10
- * - Model can retrieve full content via Read tool when needed
11
- */
12
- import * as crypto from 'crypto';
13
- import * as fs from 'fs/promises';
14
- import * as path from 'path';
15
- export const DEFAULT_SPOOL_CONFIG = {
16
- spoolThresholdBytes: 50 * 1024, // 50KB
17
- previewTokens: 500, // ~2KB
18
- totalMessageLimitBytes: 200 * 1024, // 200KB
19
- };
20
- /**
21
- * Large result spool manager.
22
- */
23
- export class LargeResultSpool {
24
- config;
25
- spoolDir;
26
- activeWrites = new Map();
27
- constructor(config = {}) {
28
- this.config = { ...DEFAULT_SPOOL_CONFIG, ...config };
29
- this.spoolDir = config.spoolDir ?? '.spool';
30
- }
31
- /**
32
- * Check if a tool result needs spooling.
33
- */
34
- needsSpool(result) {
35
- return result.output.length > this.config.spoolThresholdBytes;
36
- }
37
- /**
38
- * Hash content for spool reference.
39
- */
40
- hashContent(content) {
41
- return crypto.createHash('sha256').update(content).digest('hex');
42
- }
43
- /**
44
- * Get spool file path for a hash.
45
- */
46
- getSpoolPath(hash) {
47
- return path.join(this.spoolDir, `${hash}.txt`);
48
- }
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);
54
- }
55
- async atomicWrite(spoolPath, content) {
56
- const tempPath = `${spoolPath}.${process.pid}.${crypto.randomUUID()}.tmp`;
57
- let handle;
58
- try {
59
- handle = await fs.open(tempPath, 'wx');
60
- await handle.writeFile(content, 'utf-8');
61
- await handle.sync();
62
- await handle.close();
63
- handle = undefined;
64
- await fs.rename(tempPath, spoolPath);
65
- }
66
- finally {
67
- await handle?.close().catch(() => undefined);
68
- await fs.unlink(tempPath).catch(() => undefined);
69
- }
70
- }
71
- /**
72
- * Write large result to disk.
73
- */
74
- async writeToDisk(content, hash) {
75
- const spoolPath = this.getSpoolPath(hash);
76
- let promise = this.activeWrites.get(spoolPath);
77
- if (!promise) {
78
- promise = (async () => {
79
- try {
80
- await fs.mkdir(this.spoolDir, { recursive: true });
81
- await this.atomicWrite(spoolPath, content);
82
- return spoolPath;
83
- }
84
- finally {
85
- this.activeWrites.delete(spoolPath);
86
- }
87
- })();
88
- this.activeWrites.set(spoolPath, promise);
89
- }
90
- return promise;
91
- }
92
- /**
93
- * Generate preview for a tool result.
94
- */
95
- generatePreview(content) {
96
- const previewTokens = Math.min(this.config.previewTokens, content.length / 4);
97
- const preview = content.substring(0, previewTokens);
98
- const omitted = content.length - previewTokens;
99
- return `[tool_result_spooled]
100
- size: ${content.length} bytes
101
- preview: first ${previewTokens} chars
102
- omitted: ${omitted} chars
103
- [full content available via Read tool]
104
- `;
105
- }
106
- /**
107
- * Process a tool result: spool if large, return spooled result.
108
- */
109
- async processToolResult(result) {
110
- if (!this.needsSpool(result)) {
111
- return {
112
- originalOutput: result.output,
113
- preview: result.output,
114
- spoolRef: '',
115
- wasSpooled: false
116
- };
117
- }
118
- // Hash the content
119
- const hash = this.hashContent(result.output);
120
- // Write to disk
121
- const spoolRef = await this.writeToDisk(result.output, hash);
122
- // Generate preview
123
- const preview = this.generatePreview(result.output);
124
- return {
125
- originalOutput: result.output,
126
- preview,
127
- spoolRef,
128
- wasSpooled: true
129
- };
130
- }
131
- /**
132
- * Persist a kernel-spooled tool output to disk. Returns the on-disk path ref.
133
- */
134
- async persistOutput(sessionId, callId, content) {
135
- const hash = this.hashContent(content);
136
- const spoolPath = this.getSpoolPath(`${this.callKey(sessionId, callId)}-${hash.slice(0, 16)}`);
137
- let promise = this.activeWrites.get(spoolPath);
138
- if (!promise) {
139
- promise = (async () => {
140
- try {
141
- await fs.mkdir(this.spoolDir, { recursive: true });
142
- await this.atomicWrite(spoolPath, content);
143
- return spoolPath;
144
- }
145
- finally {
146
- this.activeWrites.delete(spoolPath);
147
- }
148
- })();
149
- this.activeWrites.set(spoolPath, promise);
150
- }
151
- return promise;
152
- }
153
- /**
154
- * Read a spooled result back from disk.
155
- */
156
- async readSpooledResult(spoolRef) {
157
- try {
158
- const content = await fs.readFile(spoolRef, 'utf-8');
159
- return content;
160
- }
161
- catch (error) {
162
- throw new Error(`Failed to read spooled result: ${error}`);
163
- }
164
- }
165
- /**
166
- * O7: locate a spooled output by the tool call's id (the `read_result` meta-tool only knows
167
- * `call_id`, not the content-hashed file name `persistOutput` chose). Scans the spool directory
168
- * for the hashed call-key prefix; returns `undefined` if nothing was ever spooled
169
- * for that call (e.g. it never actually exceeded the threshold, or the spool dir was cleaned up).
170
- */
171
- async findByCallId(sessionId, callId) {
172
- let files;
173
- try {
174
- files = await fs.readdir(this.spoolDir);
175
- }
176
- catch {
177
- return undefined;
178
- }
179
- const prefix = `${this.callKey(sessionId, callId)}-`;
180
- const match = files.find(f => f.startsWith(prefix) && f.endsWith('.txt'));
181
- if (!match)
182
- return undefined;
183
- try {
184
- return await fs.readFile(path.join(this.spoolDir, match), 'utf-8');
185
- }
186
- catch {
187
- return undefined;
188
- }
189
- }
190
- /**
191
- * Clean up old spool files (optional maintenance).
192
- */
193
- async cleanup(maxAgeMs) {
194
- const limit = maxAgeMs ?? this.config.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;
195
- try {
196
- const files = await fs.readdir(this.spoolDir);
197
- let count = 0;
198
- const now = Date.now();
199
- for (const file of files) {
200
- const filePath = path.join(this.spoolDir, file);
201
- const stats = await fs.stat(filePath);
202
- if (now - stats.mtimeMs > limit) {
203
- await fs.unlink(filePath);
204
- count++;
205
- }
206
- }
207
- return count;
208
- }
209
- catch (error) {
210
- // Ignore if directory doesn't exist or other file error
211
- return 0;
212
- }
213
- }
214
- }