@intella/sdk 0.0.1 → 0.0.3

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 (117) hide show
  1. package/README.md +6 -483
  2. package/dist/agent-manager.d.ts +47 -0
  3. package/dist/agent-manager.d.ts.map +1 -0
  4. package/dist/agent-manager.js +90 -0
  5. package/dist/agent-manager.js.map +1 -0
  6. package/dist/agents/base-agent.d.ts +41 -0
  7. package/dist/agents/base-agent.d.ts.map +1 -0
  8. package/dist/agents/base-agent.js +148 -0
  9. package/dist/agents/base-agent.js.map +1 -0
  10. package/dist/agents/claude-agent.d.ts +24 -0
  11. package/dist/agents/claude-agent.d.ts.map +1 -0
  12. package/dist/agents/claude-agent.js +65 -0
  13. package/dist/agents/claude-agent.js.map +1 -0
  14. package/dist/agents/codex-agent.d.ts +25 -0
  15. package/dist/agents/codex-agent.d.ts.map +1 -0
  16. package/dist/agents/codex-agent.js +62 -0
  17. package/dist/agents/codex-agent.js.map +1 -0
  18. package/dist/agents/intella-lite-agent.d.ts +21 -0
  19. package/dist/agents/intella-lite-agent.d.ts.map +1 -0
  20. package/dist/agents/intella-lite-agent.js +43 -0
  21. package/dist/agents/intella-lite-agent.js.map +1 -0
  22. package/dist/agents/opencode-agent.d.ts +20 -0
  23. package/dist/agents/opencode-agent.d.ts.map +1 -0
  24. package/dist/agents/opencode-agent.js +36 -0
  25. package/dist/agents/opencode-agent.js.map +1 -0
  26. package/dist/filesystem/base-provider.d.ts +55 -0
  27. package/dist/filesystem/base-provider.d.ts.map +1 -0
  28. package/dist/filesystem/base-provider.js +45 -0
  29. package/dist/filesystem/base-provider.js.map +1 -0
  30. package/dist/filesystem/index.d.ts +3 -0
  31. package/dist/filesystem/index.d.ts.map +1 -0
  32. package/{src/filesystem/index.ts → dist/filesystem/index.js} +1 -2
  33. package/dist/filesystem/index.js.map +1 -0
  34. package/dist/filesystem/memory-provider.d.ts +44 -0
  35. package/dist/filesystem/memory-provider.d.ts.map +1 -0
  36. package/dist/filesystem/memory-provider.js +227 -0
  37. package/dist/filesystem/memory-provider.js.map +1 -0
  38. package/dist/filesystem-manager.d.ts +75 -0
  39. package/dist/filesystem-manager.d.ts.map +1 -0
  40. package/dist/filesystem-manager.js +162 -0
  41. package/dist/filesystem-manager.js.map +1 -0
  42. package/dist/index.d.ts +18 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/{src/index.ts → dist/index.js} +4 -47
  45. package/dist/index.js.map +1 -0
  46. package/dist/orchestrator.d.ts +32 -0
  47. package/dist/orchestrator.d.ts.map +1 -0
  48. package/dist/orchestrator.js +137 -0
  49. package/dist/orchestrator.js.map +1 -0
  50. package/dist/sandbox/base-provider.d.ts +106 -0
  51. package/dist/sandbox/base-provider.d.ts.map +1 -0
  52. package/dist/sandbox/base-provider.js +74 -0
  53. package/dist/sandbox/base-provider.js.map +1 -0
  54. package/dist/sandbox/daytona-provider.d.ts +93 -0
  55. package/dist/sandbox/daytona-provider.d.ts.map +1 -0
  56. package/dist/sandbox/daytona-provider.js +378 -0
  57. package/dist/sandbox/daytona-provider.js.map +1 -0
  58. package/dist/sandbox/e2b-provider.d.ts +85 -0
  59. package/dist/sandbox/e2b-provider.d.ts.map +1 -0
  60. package/dist/sandbox/e2b-provider.js +363 -0
  61. package/dist/sandbox/e2b-provider.js.map +1 -0
  62. package/dist/sandbox/modal-provider.d.ts +92 -0
  63. package/dist/sandbox/modal-provider.d.ts.map +1 -0
  64. package/dist/sandbox/modal-provider.js +516 -0
  65. package/dist/sandbox/modal-provider.js.map +1 -0
  66. package/dist/sandbox-manager.d.ts +59 -0
  67. package/dist/sandbox-manager.d.ts.map +1 -0
  68. package/dist/sandbox-manager.js +141 -0
  69. package/dist/sandbox-manager.js.map +1 -0
  70. package/dist/sdk.d.ts +173 -0
  71. package/dist/sdk.d.ts.map +1 -0
  72. package/dist/sdk.js +277 -0
  73. package/dist/sdk.js.map +1 -0
  74. package/dist/types.d.ts +423 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +2 -0
  77. package/dist/types.js.map +1 -0
  78. package/dist/utils/code-extractor.d.ts +103 -0
  79. package/dist/utils/code-extractor.d.ts.map +1 -0
  80. package/dist/utils/code-extractor.js +133 -0
  81. package/dist/utils/code-extractor.js.map +1 -0
  82. package/package.json +23 -11
  83. package/examples/claude-code/README.md +0 -178
  84. package/examples/claude-code/advanced-config.ts +0 -55
  85. package/examples/claude-code/basic-usage.ts +0 -56
  86. package/examples/claude-code/model-comparison.ts +0 -50
  87. package/examples/claude-code/orchestration.ts +0 -70
  88. package/examples/claude-code/streaming.ts +0 -69
  89. package/examples/claude-code/tsconfig.json +0 -19
  90. package/examples/code-extractor/README.md +0 -77
  91. package/examples/code-extractor/example.ts +0 -145
  92. package/examples/filesystem/basic-usage.ts +0 -84
  93. package/examples/integrated-task/README.md +0 -68
  94. package/examples/integrated-task/integrated-usage.ts +0 -193
  95. package/examples/integrated-task/simple-example.ts +0 -51
  96. package/examples/integrated-task/tsconfig.json +0 -19
  97. package/examples/sandbox/basic-usage.ts +0 -173
  98. package/src/agent-manager.ts +0 -104
  99. package/src/agents/base-agent.ts +0 -166
  100. package/src/agents/claude-agent.ts +0 -77
  101. package/src/agents/codex-agent.ts +0 -72
  102. package/src/agents/intella-lite-agent.ts +0 -55
  103. package/src/agents/opencode-agent.ts +0 -45
  104. package/src/filesystem/agentfs-provider.ts +0 -328
  105. package/src/filesystem/base-provider.ts +0 -98
  106. package/src/filesystem/memory-provider.ts +0 -267
  107. package/src/filesystem-manager.ts +0 -213
  108. package/src/orchestrator.ts +0 -177
  109. package/src/sandbox/base-provider.ts +0 -184
  110. package/src/sandbox/daytona-provider.ts +0 -462
  111. package/src/sandbox/e2b-provider.ts +0 -419
  112. package/src/sandbox/modal-provider.ts +0 -597
  113. package/src/sandbox-manager.ts +0 -175
  114. package/src/sdk.ts +0 -401
  115. package/src/types.ts +0 -451
  116. package/src/utils/code-extractor.ts +0 -194
  117. package/tsconfig.json +0 -25
@@ -1,328 +0,0 @@
1
- // Note: agentfs-sdk needs to be installed separately
2
- // npm install agentfs-sdk
3
- import { AgentFS } from 'agentfs-sdk';
4
- import type {
5
- FilesystemConfig,
6
- FileStats,
7
- DirectoryEntry,
8
- ToolCallMetadata,
9
- } from '../types.js';
10
- import { BaseFilesystemProvider } from './base-provider.js';
11
-
12
- /**
13
- * AgentFS filesystem provider
14
- * Uses Turso's AgentFS SDK for SQLite-based agent filesystem
15
- */
16
- export class AgentFSProvider extends BaseFilesystemProvider {
17
- private agentFS: any = null; // AgentFS instance (typed as any due to SDK)
18
-
19
- constructor() {
20
- super('agentfs');
21
- }
22
-
23
- /**
24
- * Initialize AgentFS filesystem
25
- */
26
- async initialize(config?: FilesystemConfig): Promise<void> {
27
- this.config = { ...this.config, ...config };
28
-
29
- try {
30
- // Initialize AgentFS based on configuration
31
- if (this.config.dbPath) {
32
- // Use explicit database path
33
- this.agentFS = await AgentFS.open({ path: this.config.dbPath });
34
- } else if (this.config.agentId) {
35
- // Use agent ID (creates .agentfs/{agentId}.db)
36
- this.agentFS = await AgentFS.open({ id: this.config.agentId });
37
- } else {
38
- throw new Error('No agent ID or database path provided');
39
- }
40
-
41
- this.initialized = true;
42
- } catch (error) {
43
- throw new Error(`Failed to initialize AgentFS: ${error instanceof Error ? error.message : String(error)}`);
44
- }
45
- }
46
-
47
- /**
48
- * Close AgentFS filesystem
49
- */
50
- async close(): Promise<void> {
51
- if (this.agentFS) {
52
- // AgentFS doesn't expose a close method in the SDK,
53
- // but we can clear the reference
54
- this.agentFS = null;
55
- this.initialized = false;
56
- }
57
- }
58
-
59
- // Filesystem operations
60
- async readFile(path: string): Promise<Buffer | string> {
61
- this.ensureInitialized();
62
- const normalizedPath = this.normalizePath(path);
63
- try {
64
- const content = await this.agentFS.fs.readFile(normalizedPath);
65
- // AgentFS may return string or Buffer, return as-is
66
- return content;
67
- } catch (error) {
68
- throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);
69
- }
70
- }
71
-
72
- async writeFile(path: string, data: Buffer | string): Promise<void> {
73
- this.ensureInitialized();
74
- const normalizedPath = this.normalizePath(path);
75
- try {
76
- await this.agentFS.fs.writeFile(normalizedPath, data);
77
- } catch (error) {
78
- throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);
79
- }
80
- }
81
-
82
- async appendFile(path: string, data: Buffer | string): Promise<void> {
83
- this.ensureInitialized();
84
- const normalizedPath = this.normalizePath(path);
85
- try {
86
- // Read existing content
87
- let existingContent = '';
88
- try {
89
- const existing = await this.agentFS.fs.readFile(normalizedPath);
90
- existingContent = existing instanceof Buffer ? existing.toString() : existing;
91
- } catch {
92
- // File doesn't exist, start with empty string
93
- }
94
-
95
- // Write combined content
96
- const newContent = existingContent + (data instanceof Buffer ? data.toString() : data);
97
- await this.agentFS.fs.writeFile(normalizedPath, newContent);
98
- } catch (error) {
99
- throw new Error(`Failed to append to file ${path}: ${error instanceof Error ? error.message : String(error)}`);
100
- }
101
- }
102
-
103
- async exists(path: string): Promise<boolean> {
104
- this.ensureInitialized();
105
- const normalizedPath = this.normalizePath(path);
106
- try {
107
- await this.agentFS.fs.stat(normalizedPath);
108
- return true;
109
- } catch {
110
- return false;
111
- }
112
- }
113
-
114
- async stat(path: string): Promise<FileStats> {
115
- this.ensureInitialized();
116
- const normalizedPath = this.normalizePath(path);
117
- try {
118
- const stats = await this.agentFS.fs.stat(normalizedPath);
119
- return {
120
- size: stats.size || 0,
121
- isDirectory: stats.isDirectory || false,
122
- isFile: stats.isFile || false,
123
- createdAt: stats.createdAt,
124
- modifiedAt: stats.modifiedAt,
125
- };
126
- } catch (error) {
127
- throw new Error(`Failed to stat ${path}: ${error instanceof Error ? error.message : String(error)}`);
128
- }
129
- }
130
-
131
- async readdir(path: string): Promise<DirectoryEntry[]> {
132
- this.ensureInitialized();
133
- const normalizedPath = this.normalizePath(path);
134
- try {
135
- const entries = await this.agentFS.fs.readdir(normalizedPath);
136
- const result: DirectoryEntry[] = [];
137
-
138
- for (const entry of entries) {
139
- const entryPath = normalizedPath === '' ? entry : `${normalizedPath}/${entry}`;
140
- const stats = await this.stat(entryPath);
141
- result.push({
142
- name: entry,
143
- path: entryPath,
144
- stats,
145
- });
146
- }
147
-
148
- return result;
149
- } catch (error) {
150
- throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);
151
- }
152
- }
153
-
154
- async mkdir(path: string, recursive = false): Promise<void> {
155
- this.ensureInitialized();
156
- const normalizedPath = this.normalizePath(path);
157
- try {
158
- // AgentFS may support recursive mkdir through the SDK
159
- // If not, we'll create parent directories manually if recursive is true
160
- if (recursive) {
161
- const parts = normalizedPath.split('/');
162
- let currentPath = '';
163
- for (const part of parts) {
164
- currentPath = currentPath ? `${currentPath}/${part}` : part;
165
- try {
166
- await this.agentFS.fs.mkdir(currentPath);
167
- } catch (err: any) {
168
- // Ignore if directory already exists
169
- if (!err?.message?.includes('exists')) {
170
- throw err;
171
- }
172
- }
173
- }
174
- } else {
175
- await this.agentFS.fs.mkdir(normalizedPath);
176
- }
177
- } catch (error) {
178
- throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);
179
- }
180
- }
181
-
182
- async unlink(path: string, recursive = false): Promise<void> {
183
- this.ensureInitialized();
184
- const normalizedPath = this.normalizePath(path);
185
- try {
186
- const stats = await this.stat(normalizedPath);
187
- if (stats.isDirectory) {
188
- if (recursive) {
189
- const entries = await this.readdir(normalizedPath);
190
- for (const entry of entries) {
191
- await this.unlink(entry.path, true);
192
- }
193
- }
194
- await this.agentFS.fs.rmdir(normalizedPath);
195
- } else {
196
- await this.agentFS.fs.unlink(normalizedPath);
197
- }
198
- } catch (error) {
199
- throw new Error(`Failed to delete ${path}: ${error instanceof Error ? error.message : String(error)}`);
200
- }
201
- }
202
-
203
- async copy(src: string, dest: string): Promise<void> {
204
- this.ensureInitialized();
205
- const normalizedSrc = this.normalizePath(src);
206
- const normalizedDest = this.normalizePath(dest);
207
- try {
208
- const content = await this.readFile(normalizedSrc);
209
- await this.writeFile(normalizedDest, content);
210
- } catch (error) {
211
- throw new Error(`Failed to copy ${src} to ${dest}: ${error instanceof Error ? error.message : String(error)}`);
212
- }
213
- }
214
-
215
- async move(src: string, dest: string): Promise<void> {
216
- this.ensureInitialized();
217
- const normalizedSrc = this.normalizePath(src);
218
- const normalizedDest = this.normalizePath(dest);
219
- try {
220
- await this.copy(normalizedSrc, normalizedDest);
221
- await this.unlink(normalizedSrc);
222
- } catch (error) {
223
- throw new Error(`Failed to move ${src} to ${dest}: ${error instanceof Error ? error.message : String(error)}`);
224
- }
225
- }
226
-
227
- // Key-value operations
228
- async get(key: string): Promise<unknown> {
229
- this.ensureInitialized();
230
- try {
231
- return await this.agentFS.kv.get(key);
232
- } catch (error) {
233
- throw new Error(`Failed to get key ${key}: ${error instanceof Error ? error.message : String(error)}`);
234
- }
235
- }
236
-
237
- async set(key: string, value: unknown): Promise<void> {
238
- this.ensureInitialized();
239
- try {
240
- await this.agentFS.kv.set(key, value);
241
- } catch (error) {
242
- throw new Error(`Failed to set key ${key}: ${error instanceof Error ? error.message : String(error)}`);
243
- }
244
- }
245
-
246
- async delete(key: string): Promise<void> {
247
- this.ensureInitialized();
248
- try {
249
- await this.agentFS.kv.delete(key);
250
- } catch (error) {
251
- throw new Error(`Failed to delete key ${key}: ${error instanceof Error ? error.message : String(error)}`);
252
- }
253
- }
254
-
255
- async listKeys(prefix?: string): Promise<string[]> {
256
- this.ensureInitialized();
257
- try {
258
- // AgentFS may have a list method or we need to query directly
259
- // For now, we'll use a method that might exist or throw a not implemented error
260
- if (this.agentFS.kv.list) {
261
- return await this.agentFS.kv.list(prefix);
262
- }
263
- // If list method doesn't exist, we'll need to implement it differently
264
- // This might require direct SQLite access which isn't exposed by the SDK
265
- throw new Error('listKeys is not directly supported by AgentFS SDK. Consider using SQL queries directly.');
266
- } catch (error) {
267
- throw new Error(`Failed to list keys: ${error instanceof Error ? error.message : String(error)}`);
268
- }
269
- }
270
-
271
- async hasKey(key: string): Promise<boolean> {
272
- this.ensureInitialized();
273
- try {
274
- const value = await this.get(key);
275
- return value !== null && value !== undefined;
276
- } catch {
277
- return false;
278
- }
279
- }
280
-
281
- // Tool call tracking
282
- async recordToolCall(metadata: ToolCallMetadata): Promise<void> {
283
- this.ensureInitialized();
284
- try {
285
- await this.agentFS.tools.record(
286
- metadata.tool,
287
- metadata.startedAt,
288
- metadata.endedAt,
289
- metadata.input || {},
290
- metadata.output || {}
291
- );
292
- } catch (error) {
293
- throw new Error(`Failed to record tool call: ${error instanceof Error ? error.message : String(error)}`);
294
- }
295
- }
296
-
297
- async getToolCallHistory(filter?: {
298
- tool?: string;
299
- status?: ToolCallMetadata['status'];
300
- since?: number;
301
- until?: number;
302
- limit?: number;
303
- }): Promise<ToolCallMetadata[]> {
304
- this.ensureInitialized();
305
- try {
306
- // AgentFS tools API might have a query method
307
- // If not, we'll need to query the SQLite database directly
308
- if (this.agentFS.tools.query) {
309
- const results = await this.agentFS.tools.query(filter);
310
- return results.map((r: any) => ({
311
- tool: r.tool,
312
- startedAt: r.startedAt,
313
- endedAt: r.endedAt,
314
- input: r.input,
315
- output: r.output,
316
- status: r.status,
317
- error: r.error,
318
- }));
319
- }
320
- // If query method doesn't exist, return empty array for now
321
- // In a real implementation, you might want to access the database directly
322
- throw new Error('getToolCallHistory is not directly supported by AgentFS SDK. Consider using SQL queries directly.');
323
- } catch (error) {
324
- throw new Error(`Failed to get tool call history: ${error instanceof Error ? error.message : String(error)}`);
325
- }
326
- }
327
- }
328
-
@@ -1,98 +0,0 @@
1
- import type {
2
- FilesystemProviderType,
3
- FilesystemConfig,
4
- FileStats,
5
- DirectoryEntry,
6
- ToolCallMetadata,
7
- IFilesystemProvider,
8
- } from '../types.js';
9
-
10
- /**
11
- * Base filesystem provider
12
- * Abstract implementation that provides common functionality
13
- */
14
- export abstract class BaseFilesystemProvider implements IFilesystemProvider {
15
- protected initialized = false;
16
- protected config: FilesystemConfig = {};
17
- public readonly type: FilesystemProviderType;
18
-
19
- constructor(type: FilesystemProviderType) {
20
- this.type = type;
21
- }
22
-
23
- /**
24
- * Initialize the filesystem
25
- */
26
- abstract initialize(config?: FilesystemConfig): Promise<void>;
27
-
28
- /**
29
- * Check if filesystem is initialized
30
- */
31
- isInitialized(): boolean {
32
- return this.initialized;
33
- }
34
-
35
- /**
36
- * Close/cleanup the filesystem
37
- */
38
- abstract close(): Promise<void>;
39
-
40
- // Filesystem operations
41
- abstract readFile(path: string): Promise<Buffer | string>;
42
- abstract writeFile(path: string, data: Buffer | string): Promise<void>;
43
- abstract appendFile(path: string, data: Buffer | string): Promise<void>;
44
- abstract exists(path: string): Promise<boolean>;
45
- abstract stat(path: string): Promise<FileStats>;
46
- abstract readdir(path: string): Promise<DirectoryEntry[]>;
47
- abstract mkdir(path: string, recursive?: boolean): Promise<void>;
48
- abstract unlink(path: string, recursive?: boolean): Promise<void>;
49
- abstract copy(src: string, dest: string): Promise<void>;
50
- abstract move(src: string, dest: string): Promise<void>;
51
-
52
- // Key-value operations
53
- abstract get(key: string): Promise<unknown>;
54
- abstract set(key: string, value: unknown): Promise<void>;
55
- abstract delete(key: string): Promise<void>;
56
- abstract listKeys(prefix?: string): Promise<string[]>;
57
- abstract hasKey(key: string): Promise<boolean>;
58
-
59
- // Tool call tracking
60
- abstract recordToolCall(metadata: ToolCallMetadata): Promise<void>;
61
- abstract getToolCallHistory(filter?: {
62
- tool?: string;
63
- status?: ToolCallMetadata['status'];
64
- since?: number;
65
- until?: number;
66
- limit?: number;
67
- }): Promise<ToolCallMetadata[]>;
68
-
69
- /**
70
- * Normalize path (remove leading/trailing slashes, handle ..)
71
- */
72
- protected normalizePath(path: string): string {
73
- return path
74
- .split('/')
75
- .filter((segment) => segment !== '' && segment !== '.')
76
- .reduce((acc, segment) => {
77
- if (segment === '..') {
78
- acc.pop();
79
- } else {
80
- acc.push(segment);
81
- }
82
- return acc;
83
- }, [] as string[])
84
- .join('/');
85
- }
86
-
87
- /**
88
- * Ensure filesystem is initialized before operation
89
- */
90
- protected ensureInitialized(): void {
91
- if (!this.initialized) {
92
- throw new Error(
93
- `Filesystem provider ${this.type} is not initialized. Call initialize() first.`
94
- );
95
- }
96
- }
97
- }
98
-
@@ -1,267 +0,0 @@
1
- import type {
2
- FilesystemConfig,
3
- FileStats,
4
- DirectoryEntry,
5
- ToolCallMetadata,
6
- } from '../types.js';
7
- import { BaseFilesystemProvider } from './base-provider.js';
8
-
9
- /**
10
- * In-memory filesystem provider
11
- * Useful for testing and ephemeral operations
12
- */
13
- export class MemoryFilesystemProvider extends BaseFilesystemProvider {
14
- private fs: Map<string, Buffer | string> = new Map();
15
- private kv: Map<string, unknown> = new Map();
16
- private toolCalls: ToolCallMetadata[] = [];
17
-
18
- constructor() {
19
- super('memory');
20
- }
21
-
22
- /**
23
- * Initialize memory filesystem (no-op for memory provider)
24
- */
25
- async initialize(config?: FilesystemConfig): Promise<void> {
26
- this.config = { ...this.config, ...config };
27
- this.initialized = true;
28
- }
29
-
30
- /**
31
- * Close memory filesystem (clears all data)
32
- */
33
- async close(): Promise<void> {
34
- this.fs.clear();
35
- this.kv.clear();
36
- this.toolCalls = [];
37
- this.initialized = false;
38
- }
39
-
40
- // Filesystem operations
41
- async readFile(path: string): Promise<Buffer | string> {
42
- this.ensureInitialized();
43
- const normalizedPath = this.normalizePath(path);
44
- const content = this.fs.get(normalizedPath);
45
- if (content === undefined) {
46
- throw new Error(`File not found: ${path}`);
47
- }
48
- return content;
49
- }
50
-
51
- async writeFile(path: string, data: Buffer | string): Promise<void> {
52
- this.ensureInitialized();
53
- const normalizedPath = this.normalizePath(path);
54
- // Ensure parent directory exists
55
- const parentDir = normalizedPath.split('/').slice(0, -1).join('/');
56
- if (parentDir && !this.fs.has(parentDir)) {
57
- this.fs.set(parentDir, Buffer.from('')); // Mark as directory
58
- }
59
- this.fs.set(normalizedPath, typeof data === 'string' ? data : data);
60
- }
61
-
62
- async appendFile(path: string, data: Buffer | string): Promise<void> {
63
- this.ensureInitialized();
64
- const normalizedPath = this.normalizePath(path);
65
- const existing = this.fs.get(normalizedPath);
66
- const existingContent: string = existing instanceof Buffer
67
- ? existing.toString()
68
- : (typeof existing === 'string' ? existing : '');
69
- const newData: string = data instanceof Buffer ? data.toString() : (typeof data === 'string' ? data : '');
70
- this.fs.set(normalizedPath, existingContent + newData);
71
- }
72
-
73
- async exists(path: string): Promise<boolean> {
74
- this.ensureInitialized();
75
- const normalizedPath = this.normalizePath(path);
76
- return this.fs.has(normalizedPath);
77
- }
78
-
79
- async stat(path: string): Promise<FileStats> {
80
- this.ensureInitialized();
81
- const normalizedPath = this.normalizePath(path);
82
- const content = this.fs.get(normalizedPath);
83
- if (content === undefined) {
84
- throw new Error(`Path not found: ${path}`);
85
- }
86
-
87
- const isDirectory = typeof content === 'string' && content === '';
88
- const isFile = !isDirectory;
89
-
90
- return {
91
- size: isFile ? (content instanceof Buffer ? content.length : content.length) : 0,
92
- isDirectory,
93
- isFile,
94
- createdAt: Date.now() / 1000,
95
- modifiedAt: Date.now() / 1000,
96
- };
97
- }
98
-
99
- async readdir(path: string): Promise<DirectoryEntry[]> {
100
- this.ensureInitialized();
101
- const normalizedPath = this.normalizePath(path);
102
- const prefix = normalizedPath === '' ? '' : `${normalizedPath}/`;
103
- const entries: DirectoryEntry[] = [];
104
- const seen = new Set<string>();
105
-
106
- for (const [filePath] of this.fs.entries()) {
107
- if (filePath.startsWith(prefix) || (prefix === '' && !filePath.includes('/'))) {
108
- const relativePath = filePath.startsWith(prefix) ? filePath.slice(prefix.length) : filePath;
109
- const parts = relativePath.split('/');
110
- const name = parts[0];
111
- const entryPath = prefix === '' ? name : `${prefix}${name}`;
112
-
113
- if (name && !seen.has(entryPath)) {
114
- seen.add(entryPath);
115
- try {
116
- const stats = await this.stat(entryPath);
117
- entries.push({
118
- name,
119
- path: entryPath,
120
- stats,
121
- });
122
- } catch {
123
- // Skip if stat fails
124
- }
125
- }
126
- }
127
- }
128
-
129
- return entries;
130
- }
131
-
132
- async mkdir(path: string, recursive = false): Promise<void> {
133
- this.ensureInitialized();
134
- const normalizedPath = this.normalizePath(path);
135
-
136
- if (recursive) {
137
- const parts = normalizedPath.split('/');
138
- let currentPath = '';
139
- for (const part of parts) {
140
- currentPath = currentPath ? `${currentPath}/${part}` : part;
141
- if (!this.fs.has(currentPath)) {
142
- this.fs.set(currentPath, Buffer.from('')); // Mark as directory
143
- }
144
- }
145
- } else {
146
- if (this.fs.has(normalizedPath)) {
147
- throw new Error(`Directory already exists: ${path}`);
148
- }
149
- this.fs.set(normalizedPath, Buffer.from('')); // Mark as directory
150
- }
151
- }
152
-
153
- async unlink(path: string, recursive = false): Promise<void> {
154
- this.ensureInitialized();
155
- const normalizedPath = this.normalizePath(path);
156
-
157
- if (!this.fs.has(normalizedPath)) {
158
- throw new Error(`Path not found: ${path}`);
159
- }
160
-
161
- const stats = await this.stat(normalizedPath);
162
- const prefix = `${normalizedPath}/`;
163
-
164
- if (stats.isDirectory) {
165
- if (recursive) {
166
- // Remove all files/directories under this path
167
- for (const [filePath] of this.fs.entries()) {
168
- if (filePath.startsWith(prefix) || filePath === normalizedPath) {
169
- this.fs.delete(filePath);
170
- }
171
- }
172
- } else {
173
- // Check if directory is empty
174
- const entries = await this.readdir(normalizedPath);
175
- if (entries.length > 0) {
176
- throw new Error(`Directory not empty: ${path}`);
177
- }
178
- this.fs.delete(normalizedPath);
179
- }
180
- } else {
181
- this.fs.delete(normalizedPath);
182
- }
183
- }
184
-
185
- async copy(src: string, dest: string): Promise<void> {
186
- this.ensureInitialized();
187
- const normalizedSrc = this.normalizePath(src);
188
- const normalizedDest = this.normalizePath(dest);
189
- const content = this.fs.get(normalizedSrc);
190
- if (content === undefined) {
191
- throw new Error(`Source not found: ${src}`);
192
- }
193
- this.fs.set(normalizedDest, content);
194
- }
195
-
196
- async move(src: string, dest: string): Promise<void> {
197
- await this.copy(src, dest);
198
- await this.unlink(src);
199
- }
200
-
201
- // Key-value operations
202
- async get(key: string): Promise<unknown> {
203
- this.ensureInitialized();
204
- return this.kv.get(key);
205
- }
206
-
207
- async set(key: string, value: unknown): Promise<void> {
208
- this.ensureInitialized();
209
- this.kv.set(key, value);
210
- }
211
-
212
- async delete(key: string): Promise<void> {
213
- this.ensureInitialized();
214
- this.kv.delete(key);
215
- }
216
-
217
- async listKeys(prefix?: string): Promise<string[]> {
218
- this.ensureInitialized();
219
- if (!prefix) {
220
- return Array.from(this.kv.keys());
221
- }
222
- return Array.from(this.kv.keys()).filter((key) => key.startsWith(prefix));
223
- }
224
-
225
- async hasKey(key: string): Promise<boolean> {
226
- this.ensureInitialized();
227
- return this.kv.has(key);
228
- }
229
-
230
- // Tool call tracking
231
- async recordToolCall(metadata: ToolCallMetadata): Promise<void> {
232
- this.ensureInitialized();
233
- this.toolCalls.push(metadata);
234
- }
235
-
236
- async getToolCallHistory(filter?: {
237
- tool?: string;
238
- status?: ToolCallMetadata['status'];
239
- since?: number;
240
- until?: number;
241
- limit?: number;
242
- }): Promise<ToolCallMetadata[]> {
243
- this.ensureInitialized();
244
- let results = [...this.toolCalls];
245
-
246
- if (filter) {
247
- if (filter.tool) {
248
- results = results.filter((tc) => tc.tool === filter.tool);
249
- }
250
- if (filter.status) {
251
- results = results.filter((tc) => tc.status === filter.status);
252
- }
253
- if (filter.since !== undefined) {
254
- results = results.filter((tc) => tc.startedAt >= filter.since!);
255
- }
256
- if (filter.until !== undefined) {
257
- results = results.filter((tc) => tc.startedAt <= filter.until!);
258
- }
259
- if (filter.limit !== undefined) {
260
- results = results.slice(0, filter.limit);
261
- }
262
- }
263
-
264
- return results.reverse(); // Most recent first
265
- }
266
- }
267
-