@mastra/agentfs 0.2.0 → 0.2.1-alpha.0
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.
- package/LICENSE.md +6 -4
- package/dist/filesystem/index.d.ts.map +1 -1
- package/dist/index.cjs +481 -504
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +452 -493
- package/dist/index.js.map +1 -1
- package/package.json +17 -17
- package/CHANGELOG.md +0 -89
package/dist/index.cjs
CHANGED
|
@@ -1,524 +1,501 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let fs = require("fs");
|
|
25
|
+
let os = require("os");
|
|
26
|
+
os = __toESM(os, 1);
|
|
27
|
+
let path = require("path");
|
|
28
|
+
path = __toESM(path, 1);
|
|
29
|
+
let _mastra_core_workspace = require("@mastra/core/workspace");
|
|
30
|
+
let agentfs_sdk = require("agentfs-sdk");
|
|
31
|
+
//#region src/filesystem/index.ts
|
|
32
|
+
/**
|
|
33
|
+
* AgentFS Filesystem Provider
|
|
34
|
+
*
|
|
35
|
+
* Implements WorkspaceFilesystem backed by AgentFS (Turso/SQLite).
|
|
36
|
+
* Follows the same pattern as S3Filesystem.
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Expand a leading `~` to the user's home directory.
|
|
40
|
+
* Node.js path APIs don't handle tilde — only the shell does.
|
|
41
|
+
*/
|
|
15
42
|
function expandTilde(p) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
return p;
|
|
43
|
+
if (p === "~") return os.default.homedir();
|
|
44
|
+
if (p.startsWith("~/") || p.startsWith("~\\")) return path.default.join(os.default.homedir(), p.slice(2));
|
|
45
|
+
return p;
|
|
21
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a database path to an absolute path.
|
|
49
|
+
* Expands tilde and resolves relative paths against cwd (at construction time).
|
|
50
|
+
*/
|
|
22
51
|
function resolveDbPath(p) {
|
|
23
|
-
|
|
52
|
+
return path.default.resolve(expandTilde(p));
|
|
24
53
|
}
|
|
25
54
|
function normalizePath(input) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (result.length > 1 && result.endsWith("/")) {
|
|
43
|
-
result = result.slice(0, -1);
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
55
|
+
if (input === "" || input === ".") return "/";
|
|
56
|
+
let path$1 = input.startsWith("/") ? input : "/" + input;
|
|
57
|
+
let result = "";
|
|
58
|
+
let prevSlash = false;
|
|
59
|
+
for (let i = 0; i < path$1.length; i++) {
|
|
60
|
+
const ch = path$1[i];
|
|
61
|
+
if (ch === "/") {
|
|
62
|
+
if (!prevSlash) result += ch;
|
|
63
|
+
prevSlash = true;
|
|
64
|
+
} else {
|
|
65
|
+
result += ch;
|
|
66
|
+
prevSlash = false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (result.length > 1 && result.endsWith("/")) result = result.slice(0, -1);
|
|
70
|
+
return result;
|
|
46
71
|
}
|
|
47
|
-
function getParentPath(path) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
72
|
+
function getParentPath(path$2) {
|
|
73
|
+
const normalized = normalizePath(path$2);
|
|
74
|
+
if (normalized === "/") return "/";
|
|
75
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
76
|
+
return lastSlash <= 0 ? "/" : normalized.slice(0, lastSlash);
|
|
52
77
|
}
|
|
53
78
|
function joinPath(base, name) {
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
if (base === "/") return normalizePath("/" + name);
|
|
80
|
+
return normalizePath(base + "/" + name);
|
|
56
81
|
}
|
|
57
|
-
function getBaseName(path) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
function getBaseName(path$3) {
|
|
83
|
+
const normalized = normalizePath(path$3);
|
|
84
|
+
if (normalized === "/") return "";
|
|
85
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
86
|
+
return normalized.slice(lastSlash + 1);
|
|
62
87
|
}
|
|
63
88
|
function isErrnoError(error) {
|
|
64
|
-
|
|
89
|
+
return typeof error === "object" && error !== null && "code" in error;
|
|
65
90
|
}
|
|
66
|
-
function mapError(error, path, context = "file") {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
return new workspace.NotDirectoryError(path);
|
|
79
|
-
case "ENOTEMPTY":
|
|
80
|
-
return new workspace.DirectoryNotEmptyError(path);
|
|
81
|
-
case "EPERM":
|
|
82
|
-
case "EACCES":
|
|
83
|
-
return new workspace.PermissionError(path, "access");
|
|
84
|
-
default:
|
|
85
|
-
return error instanceof Error ? error : new Error(String(error));
|
|
86
|
-
}
|
|
91
|
+
function mapError(error, path$4, context = "file") {
|
|
92
|
+
if (!isErrnoError(error)) return error instanceof Error ? error : new Error(String(error));
|
|
93
|
+
switch (error.code) {
|
|
94
|
+
case "ENOENT": return context === "directory" ? new _mastra_core_workspace.DirectoryNotFoundError(path$4) : new _mastra_core_workspace.FileNotFoundError(path$4);
|
|
95
|
+
case "EEXIST": return new _mastra_core_workspace.FileExistsError(path$4);
|
|
96
|
+
case "EISDIR": return new _mastra_core_workspace.IsDirectoryError(path$4);
|
|
97
|
+
case "ENOTDIR": return new _mastra_core_workspace.NotDirectoryError(path$4);
|
|
98
|
+
case "ENOTEMPTY": return new _mastra_core_workspace.DirectoryNotEmptyError(path$4);
|
|
99
|
+
case "EPERM":
|
|
100
|
+
case "EACCES": return new _mastra_core_workspace.PermissionError(path$4, "access");
|
|
101
|
+
default: return error instanceof Error ? error : new Error(String(error));
|
|
102
|
+
}
|
|
87
103
|
}
|
|
88
104
|
function hasCode(error, code) {
|
|
89
|
-
|
|
105
|
+
return isErrnoError(error) && error.code === code;
|
|
90
106
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
throw error;
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
// ---------------------------------------------------------------------------
|
|
458
|
-
// Private helpers
|
|
459
|
-
// ---------------------------------------------------------------------------
|
|
460
|
-
/**
|
|
461
|
-
* Recursively create directories, ignoring EEXIST errors.
|
|
462
|
-
*/
|
|
463
|
-
async mkdirRecursive(agent, path) {
|
|
464
|
-
if (path === "/") return;
|
|
465
|
-
const segments = path.split("/").filter(Boolean);
|
|
466
|
-
let current = "";
|
|
467
|
-
for (const segment of segments) {
|
|
468
|
-
current += "/" + segment;
|
|
469
|
-
try {
|
|
470
|
-
await agent.fs.mkdir(current);
|
|
471
|
-
} catch (error) {
|
|
472
|
-
if (!hasCode(error, "EEXIST")) {
|
|
473
|
-
throw mapError(error, current, "directory");
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
/**
|
|
479
|
-
* Recursively copy a directory tree.
|
|
480
|
-
*/
|
|
481
|
-
async copyDirRecursive(agent, src, dest, options) {
|
|
482
|
-
await this.mkdirRecursive(agent, dest);
|
|
483
|
-
const entries = await agent.fs.readdirPlus(src);
|
|
484
|
-
for (const entry of entries) {
|
|
485
|
-
const srcChild = joinPath(src, entry.name);
|
|
486
|
-
const destChild = joinPath(dest, entry.name);
|
|
487
|
-
if (entry.stats.isDirectory()) {
|
|
488
|
-
await this.copyDirRecursive(agent, srcChild, destChild, options);
|
|
489
|
-
} else {
|
|
490
|
-
if (options?.overwrite === false) {
|
|
491
|
-
try {
|
|
492
|
-
await agent.fs.access(destChild);
|
|
493
|
-
throw new workspace.FileExistsError(destChild);
|
|
494
|
-
} catch (error) {
|
|
495
|
-
if (error instanceof workspace.FileExistsError) throw error;
|
|
496
|
-
if (!hasCode(error, "ENOENT")) throw mapError(error, destChild, "file");
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
await agent.fs.copyFile(srcChild, destChild);
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
}
|
|
107
|
+
/**
|
|
108
|
+
* AgentFS filesystem implementation.
|
|
109
|
+
*
|
|
110
|
+
* Stores files in a Turso/SQLite database via the AgentFS SDK.
|
|
111
|
+
*
|
|
112
|
+
* @example Using agentId
|
|
113
|
+
* ```typescript
|
|
114
|
+
* import { AgentFSFilesystem } from '@mastra/agentfs';
|
|
115
|
+
*
|
|
116
|
+
* const fs = new AgentFSFilesystem({ agentId: 'my-agent' });
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @example Using a pre-opened instance
|
|
120
|
+
* ```typescript
|
|
121
|
+
* import { AgentFS } from 'agentfs-sdk';
|
|
122
|
+
* import { AgentFSFilesystem } from '@mastra/agentfs';
|
|
123
|
+
*
|
|
124
|
+
* const agent = await AgentFS.open({ id: 'my-agent' });
|
|
125
|
+
* const fs = new AgentFSFilesystem({ agent });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
var AgentFSFilesystem = class extends _mastra_core_workspace.MastraFilesystem {
|
|
129
|
+
id;
|
|
130
|
+
name = "AgentFSFilesystem";
|
|
131
|
+
provider = "agentfs";
|
|
132
|
+
readOnly;
|
|
133
|
+
status = "pending";
|
|
134
|
+
displayName;
|
|
135
|
+
icon;
|
|
136
|
+
description;
|
|
137
|
+
_agent = null;
|
|
138
|
+
_ownsAgent;
|
|
139
|
+
_agentId;
|
|
140
|
+
_path;
|
|
141
|
+
constructor(options) {
|
|
142
|
+
if (!options.agentId && !options.path && !options.agent) throw new Error("AgentFSFilesystem requires at least one of 'agentId', 'path', or 'agent'.");
|
|
143
|
+
super({
|
|
144
|
+
...options,
|
|
145
|
+
name: "AgentFSFilesystem"
|
|
146
|
+
});
|
|
147
|
+
this.id = options.id ?? `agentfs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
148
|
+
this._agentId = options.agentId;
|
|
149
|
+
this._path = options.path ? resolveDbPath(options.path) : void 0;
|
|
150
|
+
this.readOnly = options.readOnly;
|
|
151
|
+
if (options.agent) {
|
|
152
|
+
this._agent = options.agent;
|
|
153
|
+
this._ownsAgent = false;
|
|
154
|
+
} else this._ownsAgent = true;
|
|
155
|
+
this.icon = options.icon ?? "database";
|
|
156
|
+
this.displayName = options.displayName ?? "AgentFS";
|
|
157
|
+
this.description = options.description;
|
|
158
|
+
}
|
|
159
|
+
/** The underlying AgentFS instance, or null if not yet initialized. */
|
|
160
|
+
get agent() {
|
|
161
|
+
return this._agent;
|
|
162
|
+
}
|
|
163
|
+
getInfo() {
|
|
164
|
+
return {
|
|
165
|
+
id: this.id,
|
|
166
|
+
name: this.name,
|
|
167
|
+
provider: this.provider,
|
|
168
|
+
status: this.status,
|
|
169
|
+
error: this.error,
|
|
170
|
+
readOnly: this.readOnly,
|
|
171
|
+
icon: this.icon,
|
|
172
|
+
metadata: {
|
|
173
|
+
...this._agentId && { agentId: this._agentId },
|
|
174
|
+
...this._path && { dbPath: this._path }
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
getInstructions() {
|
|
179
|
+
return `AgentFS storage for ${this._agentId ? `agent "${this._agentId}"` : "database"}. ${this.readOnly ? "Read-only" : "Persistent"} SQLite-backed filesystem — files are retained across sessions.`;
|
|
180
|
+
}
|
|
181
|
+
async init() {
|
|
182
|
+
if (this._agent) return;
|
|
183
|
+
const openOptions = {};
|
|
184
|
+
if (this._agentId) openOptions.id = this._agentId;
|
|
185
|
+
if (this._path) {
|
|
186
|
+
openOptions.path = this._path;
|
|
187
|
+
(0, fs.mkdirSync)(path.default.dirname(this._path), { recursive: true });
|
|
188
|
+
}
|
|
189
|
+
this._agent = await agentfs_sdk.AgentFS.open(openOptions);
|
|
190
|
+
}
|
|
191
|
+
async destroy() {
|
|
192
|
+
if (this._agent && this._ownsAgent) await this._agent.close();
|
|
193
|
+
this._agent = null;
|
|
194
|
+
}
|
|
195
|
+
async getAgent() {
|
|
196
|
+
await this.ensureReady();
|
|
197
|
+
return this._agent;
|
|
198
|
+
}
|
|
199
|
+
assertWritable(operation) {
|
|
200
|
+
if (this.readOnly) throw new _mastra_core_workspace.WorkspaceReadOnlyError(operation);
|
|
201
|
+
}
|
|
202
|
+
async readFile(path$5, options) {
|
|
203
|
+
const agent = await this.getAgent();
|
|
204
|
+
const normalized = normalizePath(path$5);
|
|
205
|
+
try {
|
|
206
|
+
if (options?.encoding) return await agent.fs.readFile(normalized, options.encoding);
|
|
207
|
+
return await agent.fs.readFile(normalized);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
throw mapError(error, normalized, "file");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async writeFile(path$6, content, options) {
|
|
213
|
+
this.assertWritable("writeFile");
|
|
214
|
+
const agent = await this.getAgent();
|
|
215
|
+
const normalized = normalizePath(path$6);
|
|
216
|
+
if (options?.recursive !== false) await this.mkdirRecursive(agent, getParentPath(normalized));
|
|
217
|
+
if (options?.overwrite === false) try {
|
|
218
|
+
await agent.fs.access(normalized);
|
|
219
|
+
throw new _mastra_core_workspace.FileExistsError(normalized);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
if (error instanceof _mastra_core_workspace.FileExistsError) throw error;
|
|
222
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalized, "file");
|
|
223
|
+
}
|
|
224
|
+
try {
|
|
225
|
+
const data = typeof content === "string" ? content : Buffer.from(content);
|
|
226
|
+
await agent.fs.writeFile(normalized, data);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
throw mapError(error, normalized, "file");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async appendFile(path$7, content) {
|
|
232
|
+
this.assertWritable("appendFile");
|
|
233
|
+
let existing = Buffer.alloc(0);
|
|
234
|
+
try {
|
|
235
|
+
const current = await this.readFile(path$7);
|
|
236
|
+
existing = Buffer.isBuffer(current) ? Buffer.from(current) : Buffer.from(current);
|
|
237
|
+
} catch (error) {
|
|
238
|
+
if (error instanceof _mastra_core_workspace.FileNotFoundError) {} else throw error;
|
|
239
|
+
}
|
|
240
|
+
const appendBuffer = typeof content === "string" ? Buffer.from(content, "utf-8") : Buffer.from(content);
|
|
241
|
+
await this.writeFile(path$7, Buffer.concat([existing, appendBuffer]));
|
|
242
|
+
}
|
|
243
|
+
async deleteFile(path$8, options) {
|
|
244
|
+
this.assertWritable("deleteFile");
|
|
245
|
+
const agent = await this.getAgent();
|
|
246
|
+
const normalized = normalizePath(path$8);
|
|
247
|
+
try {
|
|
248
|
+
if ((await agent.fs.stat(normalized)).isDirectory()) throw new _mastra_core_workspace.IsDirectoryError(normalized);
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error instanceof _mastra_core_workspace.IsDirectoryError) throw error;
|
|
251
|
+
if (hasCode(error, "ENOENT")) {
|
|
252
|
+
if (options?.force) return;
|
|
253
|
+
throw new _mastra_core_workspace.FileNotFoundError(normalized);
|
|
254
|
+
}
|
|
255
|
+
throw mapError(error, normalized, "file");
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
await agent.fs.unlink(normalized);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
261
|
+
throw mapError(error, normalized, "file");
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
async copyFile(src, dest, options) {
|
|
265
|
+
this.assertWritable("copyFile");
|
|
266
|
+
const agent = await this.getAgent();
|
|
267
|
+
const normalizedSrc = normalizePath(src);
|
|
268
|
+
const normalizedDest = normalizePath(dest);
|
|
269
|
+
if (options?.overwrite === false) try {
|
|
270
|
+
await agent.fs.access(normalizedDest);
|
|
271
|
+
throw new _mastra_core_workspace.FileExistsError(normalizedDest);
|
|
272
|
+
} catch (error) {
|
|
273
|
+
if (error instanceof _mastra_core_workspace.FileExistsError) throw error;
|
|
274
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalizedDest, "file");
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
if ((await agent.fs.stat(normalizedSrc)).isDirectory()) {
|
|
278
|
+
if (!options?.recursive) throw new _mastra_core_workspace.IsDirectoryError(normalizedSrc);
|
|
279
|
+
await this.copyDirRecursive(agent, normalizedSrc, normalizedDest, options);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
await this.mkdirRecursive(agent, getParentPath(normalizedDest));
|
|
283
|
+
await agent.fs.copyFile(normalizedSrc, normalizedDest);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
if (error instanceof _mastra_core_workspace.IsDirectoryError || error instanceof _mastra_core_workspace.FileExistsError) throw error;
|
|
286
|
+
throw mapError(error, normalizedSrc, "file");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
async moveFile(src, dest, options) {
|
|
290
|
+
this.assertWritable("moveFile");
|
|
291
|
+
const agent = await this.getAgent();
|
|
292
|
+
const normalizedSrc = normalizePath(src);
|
|
293
|
+
const normalizedDest = normalizePath(dest);
|
|
294
|
+
if (options?.overwrite === false) try {
|
|
295
|
+
await agent.fs.access(normalizedDest);
|
|
296
|
+
throw new _mastra_core_workspace.FileExistsError(normalizedDest);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof _mastra_core_workspace.FileExistsError) throw error;
|
|
299
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalizedDest, "file");
|
|
300
|
+
}
|
|
301
|
+
await this.mkdirRecursive(agent, getParentPath(normalizedDest));
|
|
302
|
+
try {
|
|
303
|
+
await agent.fs.rename(normalizedSrc, normalizedDest);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
throw mapError(error, normalizedSrc, "file");
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
async mkdir(path$9, options) {
|
|
309
|
+
this.assertWritable("mkdir");
|
|
310
|
+
const agent = await this.getAgent();
|
|
311
|
+
const normalized = normalizePath(path$9);
|
|
312
|
+
if (options?.recursive !== false) {
|
|
313
|
+
await this.mkdirRecursive(agent, normalized);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
await agent.fs.mkdir(normalized);
|
|
318
|
+
} catch (error) {
|
|
319
|
+
throw mapError(error, normalized, "directory");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
async rmdir(path$10, options) {
|
|
323
|
+
this.assertWritable("rmdir");
|
|
324
|
+
const agent = await this.getAgent();
|
|
325
|
+
const normalized = normalizePath(path$10);
|
|
326
|
+
if (options?.recursive) {
|
|
327
|
+
try {
|
|
328
|
+
await agent.fs.rm(normalized, { recursive: true });
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
331
|
+
throw mapError(error, normalized, "directory");
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
if ((await agent.fs.readdir(normalized)).length > 0) throw new _mastra_core_workspace.DirectoryNotEmptyError(normalized);
|
|
337
|
+
await agent.fs.rmdir(normalized);
|
|
338
|
+
} catch (error) {
|
|
339
|
+
if (error instanceof _mastra_core_workspace.DirectoryNotEmptyError) throw error;
|
|
340
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
341
|
+
throw mapError(error, normalized, "directory");
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async readdir(path$11, options) {
|
|
345
|
+
const agent = await this.getAgent();
|
|
346
|
+
const normalized = normalizePath(path$11);
|
|
347
|
+
try {
|
|
348
|
+
if (!(await agent.fs.stat(normalized)).isDirectory()) throw new _mastra_core_workspace.NotDirectoryError(normalized);
|
|
349
|
+
let entries = (await agent.fs.readdirPlus(normalized)).map((entry) => ({
|
|
350
|
+
name: entry.name,
|
|
351
|
+
type: entry.stats.isDirectory() ? "directory" : "file",
|
|
352
|
+
size: entry.stats.size
|
|
353
|
+
}));
|
|
354
|
+
if (options?.extension) {
|
|
355
|
+
const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];
|
|
356
|
+
entries = entries.filter((entry) => {
|
|
357
|
+
if (entry.type === "directory") return true;
|
|
358
|
+
return extensions.some((ext) => entry.name.endsWith(ext));
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
if (options?.recursive) {
|
|
362
|
+
const maxDepth = options.maxDepth ?? Infinity;
|
|
363
|
+
const subdirs = entries.filter((e) => e.type === "directory");
|
|
364
|
+
for (const dir of subdirs) if (maxDepth > 1) {
|
|
365
|
+
const subEntries = await this.readdir(joinPath(normalized, dir.name), {
|
|
366
|
+
...options,
|
|
367
|
+
maxDepth: maxDepth - 1
|
|
368
|
+
});
|
|
369
|
+
for (const sub of subEntries) entries.push({
|
|
370
|
+
...sub,
|
|
371
|
+
name: dir.name + "/" + sub.name
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return entries;
|
|
376
|
+
} catch (error) {
|
|
377
|
+
if (error instanceof _mastra_core_workspace.NotDirectoryError || error instanceof _mastra_core_workspace.DirectoryNotFoundError) throw error;
|
|
378
|
+
throw mapError(error, normalized, "directory");
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
async exists(path$12) {
|
|
382
|
+
const agent = await this.getAgent();
|
|
383
|
+
const normalized = normalizePath(path$12);
|
|
384
|
+
try {
|
|
385
|
+
await agent.fs.access(normalized);
|
|
386
|
+
return true;
|
|
387
|
+
} catch {
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
async stat(path$13) {
|
|
392
|
+
const agent = await this.getAgent();
|
|
393
|
+
const normalized = normalizePath(path$13);
|
|
394
|
+
try {
|
|
395
|
+
const st = await agent.fs.stat(normalized);
|
|
396
|
+
return {
|
|
397
|
+
name: getBaseName(normalized) || "",
|
|
398
|
+
path: normalized,
|
|
399
|
+
type: st.isDirectory() ? "directory" : "file",
|
|
400
|
+
size: st.size,
|
|
401
|
+
createdAt: /* @__PURE__ */ new Date(st.ctime * 1e3),
|
|
402
|
+
modifiedAt: /* @__PURE__ */ new Date(st.mtime * 1e3)
|
|
403
|
+
};
|
|
404
|
+
} catch (error) {
|
|
405
|
+
throw mapError(error, normalized, "file");
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Check if the path points to a file.
|
|
410
|
+
* Returns `false` if the path doesn't exist.
|
|
411
|
+
*/
|
|
412
|
+
async isFile(path$14) {
|
|
413
|
+
try {
|
|
414
|
+
return (await this.stat(path$14)).type === "file";
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (error instanceof _mastra_core_workspace.FileNotFoundError) return false;
|
|
417
|
+
throw error;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Check if the path points to a directory.
|
|
422
|
+
* Returns `false` if the path doesn't exist.
|
|
423
|
+
*/
|
|
424
|
+
async isDirectory(path$15) {
|
|
425
|
+
try {
|
|
426
|
+
return (await this.stat(path$15)).type === "directory";
|
|
427
|
+
} catch (error) {
|
|
428
|
+
if (error instanceof _mastra_core_workspace.FileNotFoundError) return false;
|
|
429
|
+
throw error;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Recursively create directories, ignoring EEXIST errors.
|
|
434
|
+
*/
|
|
435
|
+
async mkdirRecursive(agent, path$16) {
|
|
436
|
+
if (path$16 === "/") return;
|
|
437
|
+
const segments = path$16.split("/").filter(Boolean);
|
|
438
|
+
let current = "";
|
|
439
|
+
for (const segment of segments) {
|
|
440
|
+
current += "/" + segment;
|
|
441
|
+
try {
|
|
442
|
+
await agent.fs.mkdir(current);
|
|
443
|
+
} catch (error) {
|
|
444
|
+
if (!hasCode(error, "EEXIST")) throw mapError(error, current, "directory");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* Recursively copy a directory tree.
|
|
450
|
+
*/
|
|
451
|
+
async copyDirRecursive(agent, src, dest, options) {
|
|
452
|
+
await this.mkdirRecursive(agent, dest);
|
|
453
|
+
const entries = await agent.fs.readdirPlus(src);
|
|
454
|
+
for (const entry of entries) {
|
|
455
|
+
const srcChild = joinPath(src, entry.name);
|
|
456
|
+
const destChild = joinPath(dest, entry.name);
|
|
457
|
+
if (entry.stats.isDirectory()) await this.copyDirRecursive(agent, srcChild, destChild, options);
|
|
458
|
+
else {
|
|
459
|
+
if (options?.overwrite === false) try {
|
|
460
|
+
await agent.fs.access(destChild);
|
|
461
|
+
throw new _mastra_core_workspace.FileExistsError(destChild);
|
|
462
|
+
} catch (error) {
|
|
463
|
+
if (error instanceof _mastra_core_workspace.FileExistsError) throw error;
|
|
464
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, destChild, "file");
|
|
465
|
+
}
|
|
466
|
+
await agent.fs.copyFile(srcChild, destChild);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
503
470
|
};
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/provider.ts
|
|
473
|
+
const agentfsFilesystemProvider = {
|
|
474
|
+
id: "agentfs",
|
|
475
|
+
name: "AgentFS",
|
|
476
|
+
description: "Turso/SQLite-backed filesystem via AgentFS",
|
|
477
|
+
configSchema: {
|
|
478
|
+
type: "object",
|
|
479
|
+
properties: {
|
|
480
|
+
agentId: {
|
|
481
|
+
type: "string",
|
|
482
|
+
description: "Agent ID — creates database at .agentfs/<agentId>.db"
|
|
483
|
+
},
|
|
484
|
+
path: {
|
|
485
|
+
type: "string",
|
|
486
|
+
description: "Explicit database file path (alternative to agentId)"
|
|
487
|
+
},
|
|
488
|
+
readOnly: {
|
|
489
|
+
type: "boolean",
|
|
490
|
+
description: "Mount as read-only",
|
|
491
|
+
default: false
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
createFilesystem: (config) => new AgentFSFilesystem(config)
|
|
519
496
|
};
|
|
520
|
-
|
|
497
|
+
//#endregion
|
|
521
498
|
exports.AgentFSFilesystem = AgentFSFilesystem;
|
|
522
499
|
exports.agentfsFilesystemProvider = agentfsFilesystemProvider;
|
|
523
|
-
|
|
500
|
+
|
|
524
501
|
//# sourceMappingURL=index.cjs.map
|