agentfs-sdk 0.2.3-pre.7 → 0.3.0-pre.4

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.
@@ -15,10 +15,13 @@ export interface Stats {
15
15
  }
16
16
  export declare class Filesystem {
17
17
  private db;
18
- private initialized;
19
18
  private rootIno;
20
19
  private chunkSize;
21
- constructor(db: Database);
20
+ private constructor();
21
+ /**
22
+ * Create a Filesystem from an existing database connection
23
+ */
24
+ static fromDatabase(db: Database): Promise<Filesystem>;
22
25
  /**
23
26
  * Get the configured chunk size
24
27
  */
@@ -62,12 +65,10 @@ export declare class Filesystem {
62
65
  private getLinkCount;
63
66
  writeFile(path: string, content: string | Buffer): Promise<void>;
64
67
  private updateFileContent;
65
- readFile(path: string, encoding?: BufferEncoding): Promise<Buffer | string>;
68
+ readFile(path: string, options?: BufferEncoding | {
69
+ encoding?: BufferEncoding;
70
+ }): Promise<Buffer | string>;
66
71
  readdir(path: string): Promise<string[]>;
67
72
  deleteFile(path: string): Promise<void>;
68
73
  stat(path: string): Promise<Stats>;
69
- /**
70
- * Wait for initialization to complete
71
- */
72
- ready(): Promise<void>;
73
74
  }
@@ -15,7 +15,14 @@ class Filesystem {
15
15
  this.rootIno = 1;
16
16
  this.chunkSize = DEFAULT_CHUNK_SIZE;
17
17
  this.db = db;
18
- this.initialized = this.initialize();
18
+ }
19
+ /**
20
+ * Create a Filesystem from an existing database connection
21
+ */
22
+ static async fromDatabase(db) {
23
+ const fs = new Filesystem(db);
24
+ await fs.initialize();
25
+ return fs;
19
26
  }
20
27
  /**
21
28
  * Get the configured chunk size
@@ -24,16 +31,6 @@ class Filesystem {
24
31
  return this.chunkSize;
25
32
  }
26
33
  async initialize() {
27
- // Ensure database is connected
28
- try {
29
- await this.db.connect();
30
- }
31
- catch (error) {
32
- // Ignore "already connected" errors
33
- if (!error.message?.includes('already')) {
34
- throw error;
35
- }
36
- }
37
34
  // Create the config table
38
35
  await this.db.exec(`
39
36
  CREATE TABLE IF NOT EXISTS fs_config (
@@ -141,7 +138,6 @@ class Filesystem {
141
138
  * Resolve a path to an inode number
142
139
  */
143
140
  async resolvePath(path) {
144
- await this.initialized;
145
141
  const normalized = this.normalizePath(path);
146
142
  // Root directory
147
143
  if (normalized === '/') {
@@ -239,7 +235,6 @@ class Filesystem {
239
235
  return result.count;
240
236
  }
241
237
  async writeFile(path, content) {
242
- await this.initialized;
243
238
  // Ensure parent directories exist
244
239
  await this.ensureParentDirs(path);
245
240
  // Check if file already exists
@@ -289,8 +284,11 @@ class Filesystem {
289
284
  `);
290
285
  await updateStmt.run(buffer.length, now, ino);
291
286
  }
292
- async readFile(path, encoding) {
293
- await this.initialized;
287
+ async readFile(path, options) {
288
+ // Normalize options
289
+ const encoding = typeof options === 'string'
290
+ ? options
291
+ : options?.encoding;
294
292
  const ino = await this.resolvePath(path);
295
293
  if (ino === null) {
296
294
  throw new Error(`ENOENT: no such file or directory, open '${path}'`);
@@ -321,7 +319,6 @@ class Filesystem {
321
319
  return combined;
322
320
  }
323
321
  async readdir(path) {
324
- await this.initialized;
325
322
  const ino = await this.resolvePath(path);
326
323
  if (ino === null) {
327
324
  throw new Error(`ENOENT: no such file or directory, scandir '${path}'`);
@@ -336,7 +333,6 @@ class Filesystem {
336
333
  return rows.map(row => row.name);
337
334
  }
338
335
  async deleteFile(path) {
339
- await this.initialized;
340
336
  const ino = await this.resolvePath(path);
341
337
  if (ino === null) {
342
338
  throw new Error(`ENOENT: no such file or directory, unlink '${path}'`);
@@ -363,7 +359,6 @@ class Filesystem {
363
359
  }
364
360
  }
365
361
  async stat(path) {
366
- await this.initialized;
367
362
  const ino = await this.resolvePath(path);
368
363
  if (ino === null) {
369
364
  throw new Error(`ENOENT: no such file or directory, stat '${path}'`);
@@ -393,11 +388,5 @@ class Filesystem {
393
388
  isSymbolicLink: () => (row.mode & S_IFMT) === S_IFLNK,
394
389
  };
395
390
  }
396
- /**
397
- * Wait for initialization to complete
398
- */
399
- async ready() {
400
- await this.initialized;
401
- }
402
391
  }
403
392
  exports.Filesystem = Filesystem;
package/dist/index.d.ts CHANGED
@@ -45,6 +45,7 @@ export declare class AgentFS {
45
45
  * ```
46
46
  */
47
47
  static open(options: AgentFSOptions): Promise<AgentFS>;
48
+ static openWith(db: Database): Promise<AgentFS>;
48
49
  /**
49
50
  * Get the underlying Database instance
50
51
  */
package/dist/index.js CHANGED
@@ -58,15 +58,14 @@ class AgentFS {
58
58
  const db = new database_1.Database(dbPath);
59
59
  // Connect to the database to ensure it's created
60
60
  await db.connect();
61
- // Create subsystems
62
- const kv = new kvstore_1.KvStore(db);
63
- const fs = new filesystem_1.Filesystem(db);
64
- const tools = new toolcalls_1.ToolCalls(db);
65
- // Wait for all subsystems to initialize
66
- await kv.ready();
67
- await fs.ready();
68
- await tools.ready();
69
- // Return fully initialized instance
61
+ return await AgentFS.openWith(db);
62
+ }
63
+ static async openWith(db) {
64
+ const [kv, fs, tools] = await Promise.all([
65
+ kvstore_1.KvStore.fromDatabase(db),
66
+ filesystem_1.Filesystem.fromDatabase(db),
67
+ toolcalls_1.ToolCalls.fromDatabase(db),
68
+ ]);
70
69
  return new AgentFS(db, kv, fs, tools);
71
70
  }
72
71
  /**
package/dist/kvstore.d.ts CHANGED
@@ -1,14 +1,17 @@
1
1
  import { Database } from '@tursodatabase/database';
2
2
  export declare class KvStore {
3
3
  private db;
4
- private initialized;
5
- constructor(db: Database);
4
+ private constructor();
5
+ /**
6
+ * Create a KvStore from an existing database connection
7
+ */
8
+ static fromDatabase(db: Database): Promise<KvStore>;
6
9
  private initialize;
7
10
  set(key: string, value: any): Promise<void>;
8
- get(key: string): Promise<any>;
11
+ get<T = any>(key: string): Promise<T | undefined>;
12
+ list(prefix: string): Promise<{
13
+ key: string;
14
+ value: any;
15
+ }[]>;
9
16
  delete(key: string): Promise<void>;
10
- /**
11
- * Wait for initialization to complete
12
- */
13
- ready(): Promise<void>;
14
17
  }
package/dist/kvstore.js CHANGED
@@ -4,19 +4,16 @@ exports.KvStore = void 0;
4
4
  class KvStore {
5
5
  constructor(db) {
6
6
  this.db = db;
7
- this.initialized = this.initialize();
7
+ }
8
+ /**
9
+ * Create a KvStore from an existing database connection
10
+ */
11
+ static async fromDatabase(db) {
12
+ const kv = new KvStore(db);
13
+ await kv.initialize();
14
+ return kv;
8
15
  }
9
16
  async initialize() {
10
- // Ensure database is connected
11
- try {
12
- await this.db.connect();
13
- }
14
- catch (error) {
15
- // Ignore "already connected" errors
16
- if (!error.message?.includes('already')) {
17
- throw error;
18
- }
19
- }
20
17
  // Create the key-value store table if it doesn't exist
21
18
  await this.db.exec(`
22
19
  CREATE TABLE IF NOT EXISTS kv_store (
@@ -33,7 +30,6 @@ class KvStore {
33
30
  `);
34
31
  }
35
32
  async set(key, value) {
36
- await this.initialized;
37
33
  // Serialize the value to JSON
38
34
  const serializedValue = JSON.stringify(value);
39
35
  // Use prepared statement to insert or update
@@ -47,7 +43,6 @@ class KvStore {
47
43
  await stmt.run(key, serializedValue);
48
44
  }
49
45
  async get(key) {
50
- await this.initialized;
51
46
  const stmt = this.db.prepare(`SELECT value FROM kv_store WHERE key = ?`);
52
47
  const row = await stmt.get(key);
53
48
  if (!row) {
@@ -56,16 +51,15 @@ class KvStore {
56
51
  // Deserialize the JSON value
57
52
  return JSON.parse(row.value);
58
53
  }
54
+ async list(prefix) {
55
+ const stmt = this.db.prepare(`SELECT key, value FROM kv_store WHERE key LIKE ? ESCAPE '\\'`);
56
+ const escaped = prefix.replace('\\', '\\\\').replace('%', '\\%').replace('_', '\\_');
57
+ const rows = await stmt.all(escaped + '%');
58
+ return rows.map(r => ({ key: r.key, value: JSON.parse(r.value) }));
59
+ }
59
60
  async delete(key) {
60
- await this.initialized;
61
61
  const stmt = this.db.prepare(`DELETE FROM kv_store WHERE key = ?`);
62
62
  await stmt.run(key);
63
63
  }
64
- /**
65
- * Wait for initialization to complete
66
- */
67
- async ready() {
68
- await this.initialized;
69
- }
70
64
  }
71
65
  exports.KvStore = KvStore;
@@ -19,8 +19,11 @@ export interface ToolCallStats {
19
19
  }
20
20
  export declare class ToolCalls {
21
21
  private db;
22
- private initialized;
23
- constructor(db: Database);
22
+ private constructor();
23
+ /**
24
+ * Create a ToolCalls from an existing database connection
25
+ */
26
+ static fromDatabase(db: Database): Promise<ToolCalls>;
24
27
  private initialize;
25
28
  /**
26
29
  * Start a new tool call and mark it as pending
@@ -62,8 +65,4 @@ export declare class ToolCalls {
62
65
  * Helper to convert database row to ToolCall object
63
66
  */
64
67
  private rowToToolCall;
65
- /**
66
- * Wait for initialization to complete
67
- */
68
- ready(): Promise<void>;
69
68
  }
package/dist/toolcalls.js CHANGED
@@ -4,19 +4,16 @@ exports.ToolCalls = void 0;
4
4
  class ToolCalls {
5
5
  constructor(db) {
6
6
  this.db = db;
7
- this.initialized = this.initialize();
7
+ }
8
+ /**
9
+ * Create a ToolCalls from an existing database connection
10
+ */
11
+ static async fromDatabase(db) {
12
+ const tools = new ToolCalls(db);
13
+ await tools.initialize();
14
+ return tools;
8
15
  }
9
16
  async initialize() {
10
- // Ensure database is connected
11
- try {
12
- await this.db.connect();
13
- }
14
- catch (error) {
15
- // Ignore "already connected" errors
16
- if (!error.message?.includes('already')) {
17
- throw error;
18
- }
19
- }
20
17
  // Create the tool_calls table
21
18
  await this.db.exec(`
22
19
  CREATE TABLE IF NOT EXISTS tool_calls (
@@ -46,7 +43,6 @@ class ToolCalls {
46
43
  * Returns the ID of the created tool call record
47
44
  */
48
45
  async start(name, parameters) {
49
- await this.initialized;
50
46
  const serializedParams = parameters !== undefined ? JSON.stringify(parameters) : null;
51
47
  const started_at = Math.floor(Date.now() / 1000);
52
48
  const stmt = this.db.prepare(`
@@ -60,7 +56,6 @@ class ToolCalls {
60
56
  * Mark a tool call as successful
61
57
  */
62
58
  async success(id, result) {
63
- await this.initialized;
64
59
  const serializedResult = result !== undefined ? JSON.stringify(result) : null;
65
60
  const completed_at = Math.floor(Date.now() / 1000);
66
61
  // Get the started_at time to calculate duration
@@ -81,7 +76,6 @@ class ToolCalls {
81
76
  * Mark a tool call as failed
82
77
  */
83
78
  async error(id, error) {
84
- await this.initialized;
85
79
  const completed_at = Math.floor(Date.now() / 1000);
86
80
  // Get the started_at time to calculate duration
87
81
  const getStmt = this.db.prepare('SELECT started_at FROM tool_calls WHERE id = ?');
@@ -103,7 +97,6 @@ class ToolCalls {
103
97
  * Returns the ID of the created tool call record
104
98
  */
105
99
  async record(name, started_at, completed_at, parameters, result, error) {
106
- await this.initialized;
107
100
  const serializedParams = parameters !== undefined ? JSON.stringify(parameters) : null;
108
101
  const serializedResult = result !== undefined ? JSON.stringify(result) : null;
109
102
  const duration_ms = (completed_at - started_at) * 1000;
@@ -119,7 +112,6 @@ class ToolCalls {
119
112
  * Get a specific tool call by ID
120
113
  */
121
114
  async get(id) {
122
- await this.initialized;
123
115
  const stmt = this.db.prepare(`
124
116
  SELECT * FROM tool_calls WHERE id = ?
125
117
  `);
@@ -133,7 +125,6 @@ class ToolCalls {
133
125
  * Query tool calls by name
134
126
  */
135
127
  async getByName(name, limit) {
136
- await this.initialized;
137
128
  const limitClause = limit !== undefined ? `LIMIT ${limit}` : '';
138
129
  const stmt = this.db.prepare(`
139
130
  SELECT * FROM tool_calls
@@ -148,7 +139,6 @@ class ToolCalls {
148
139
  * Query recent tool calls
149
140
  */
150
141
  async getRecent(since, limit) {
151
- await this.initialized;
152
142
  const limitClause = limit !== undefined ? `LIMIT ${limit}` : '';
153
143
  const stmt = this.db.prepare(`
154
144
  SELECT * FROM tool_calls
@@ -164,7 +154,6 @@ class ToolCalls {
164
154
  * Only includes completed calls (success or failed), not pending ones
165
155
  */
166
156
  async getStats() {
167
- await this.initialized;
168
157
  const stmt = this.db.prepare(`
169
158
  SELECT
170
159
  name,
@@ -202,11 +191,5 @@ class ToolCalls {
202
191
  duration_ms: row.duration_ms !== null ? row.duration_ms : undefined,
203
192
  };
204
193
  }
205
- /**
206
- * Wait for initialization to complete
207
- */
208
- async ready() {
209
- await this.initialized;
210
- }
211
194
  }
212
195
  exports.ToolCalls = ToolCalls;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentfs-sdk",
3
- "version": "0.2.3-pre.7",
3
+ "version": "0.3.0-pre.4",
4
4
  "description": "AgentFS SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,6 +24,10 @@
24
24
  ],
25
25
  "author": "",
26
26
  "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/tursodatabase/agentfs"
30
+ },
27
31
  "devDependencies": {
28
32
  "@types/node": "^20.0.0",
29
33
  "@vitest/ui": "^4.0.1",