@mastra/agentfs 0.1.0-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/CHANGELOG.md +25 -0
- package/LICENSE.md +30 -0
- package/README.md +58 -0
- package/dist/filesystem/index.d.ts +109 -0
- package/dist/filesystem/index.d.ts.map +1 -0
- package/dist/index.cjs +524 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +516 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +16 -0
- package/dist/provider.d.ts.map +1 -0
- package/package.json +67 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var fs = require('fs');
|
|
4
|
+
var os = require('os');
|
|
5
|
+
var nodePath = require('path');
|
|
6
|
+
var workspace = require('@mastra/core/workspace');
|
|
7
|
+
var agentfsSdk = require('agentfs-sdk');
|
|
8
|
+
|
|
9
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
|
|
11
|
+
var os__default = /*#__PURE__*/_interopDefault(os);
|
|
12
|
+
var nodePath__default = /*#__PURE__*/_interopDefault(nodePath);
|
|
13
|
+
|
|
14
|
+
// src/filesystem/index.ts
|
|
15
|
+
function expandTilde(p) {
|
|
16
|
+
if (p === "~") return os__default.default.homedir();
|
|
17
|
+
if (p.startsWith("~/") || p.startsWith("~\\")) {
|
|
18
|
+
return nodePath__default.default.join(os__default.default.homedir(), p.slice(2));
|
|
19
|
+
}
|
|
20
|
+
return p;
|
|
21
|
+
}
|
|
22
|
+
function resolveDbPath(p) {
|
|
23
|
+
return nodePath__default.default.resolve(expandTilde(p));
|
|
24
|
+
}
|
|
25
|
+
function normalizePath(input) {
|
|
26
|
+
if (input === "" || input === ".") return "/";
|
|
27
|
+
let path = input.startsWith("/") ? input : "/" + input;
|
|
28
|
+
let result = "";
|
|
29
|
+
let prevSlash = false;
|
|
30
|
+
for (let i = 0; i < path.length; i++) {
|
|
31
|
+
const ch = path[i];
|
|
32
|
+
if (ch === "/") {
|
|
33
|
+
if (!prevSlash) {
|
|
34
|
+
result += ch;
|
|
35
|
+
}
|
|
36
|
+
prevSlash = true;
|
|
37
|
+
} else {
|
|
38
|
+
result += ch;
|
|
39
|
+
prevSlash = false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (result.length > 1 && result.endsWith("/")) {
|
|
43
|
+
result = result.slice(0, -1);
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
function getParentPath(path) {
|
|
48
|
+
const normalized = normalizePath(path);
|
|
49
|
+
if (normalized === "/") return "/";
|
|
50
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
51
|
+
return lastSlash <= 0 ? "/" : normalized.slice(0, lastSlash);
|
|
52
|
+
}
|
|
53
|
+
function joinPath(base, name) {
|
|
54
|
+
if (base === "/") return normalizePath("/" + name);
|
|
55
|
+
return normalizePath(base + "/" + name);
|
|
56
|
+
}
|
|
57
|
+
function getBaseName(path) {
|
|
58
|
+
const normalized = normalizePath(path);
|
|
59
|
+
if (normalized === "/") return "";
|
|
60
|
+
const lastSlash = normalized.lastIndexOf("/");
|
|
61
|
+
return normalized.slice(lastSlash + 1);
|
|
62
|
+
}
|
|
63
|
+
function isErrnoError(error) {
|
|
64
|
+
return typeof error === "object" && error !== null && "code" in error;
|
|
65
|
+
}
|
|
66
|
+
function mapError(error, path, context = "file") {
|
|
67
|
+
if (!isErrnoError(error)) {
|
|
68
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
69
|
+
}
|
|
70
|
+
switch (error.code) {
|
|
71
|
+
case "ENOENT":
|
|
72
|
+
return context === "directory" ? new workspace.DirectoryNotFoundError(path) : new workspace.FileNotFoundError(path);
|
|
73
|
+
case "EEXIST":
|
|
74
|
+
return new workspace.FileExistsError(path);
|
|
75
|
+
case "EISDIR":
|
|
76
|
+
return new workspace.IsDirectoryError(path);
|
|
77
|
+
case "ENOTDIR":
|
|
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
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function hasCode(error, code) {
|
|
89
|
+
return isErrnoError(error) && error.code === code;
|
|
90
|
+
}
|
|
91
|
+
var AgentFSFilesystem = class extends workspace.MastraFilesystem {
|
|
92
|
+
id;
|
|
93
|
+
name = "AgentFSFilesystem";
|
|
94
|
+
provider = "agentfs";
|
|
95
|
+
readOnly;
|
|
96
|
+
status = "pending";
|
|
97
|
+
// Display metadata
|
|
98
|
+
displayName;
|
|
99
|
+
icon;
|
|
100
|
+
description;
|
|
101
|
+
_agent = null;
|
|
102
|
+
_ownsAgent;
|
|
103
|
+
_agentId;
|
|
104
|
+
_path;
|
|
105
|
+
constructor(options) {
|
|
106
|
+
if (!options.agentId && !options.path && !options.agent) {
|
|
107
|
+
throw new Error("AgentFSFilesystem requires at least one of 'agentId', 'path', or 'agent'.");
|
|
108
|
+
}
|
|
109
|
+
super({ ...options, name: "AgentFSFilesystem" });
|
|
110
|
+
this.id = options.id ?? `agentfs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
111
|
+
this._agentId = options.agentId;
|
|
112
|
+
this._path = options.path ? resolveDbPath(options.path) : void 0;
|
|
113
|
+
this.readOnly = options.readOnly;
|
|
114
|
+
if (options.agent) {
|
|
115
|
+
this._agent = options.agent;
|
|
116
|
+
this._ownsAgent = false;
|
|
117
|
+
} else {
|
|
118
|
+
this._ownsAgent = true;
|
|
119
|
+
}
|
|
120
|
+
this.icon = options.icon ?? "database";
|
|
121
|
+
this.displayName = options.displayName ?? "AgentFS";
|
|
122
|
+
this.description = options.description;
|
|
123
|
+
}
|
|
124
|
+
/** The underlying AgentFS instance, or null if not yet initialized. */
|
|
125
|
+
get agent() {
|
|
126
|
+
return this._agent;
|
|
127
|
+
}
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
// Info
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
getInfo() {
|
|
132
|
+
return {
|
|
133
|
+
id: this.id,
|
|
134
|
+
name: this.name,
|
|
135
|
+
provider: this.provider,
|
|
136
|
+
status: this.status,
|
|
137
|
+
error: this.error,
|
|
138
|
+
readOnly: this.readOnly,
|
|
139
|
+
icon: this.icon,
|
|
140
|
+
metadata: {
|
|
141
|
+
...this._agentId && { agentId: this._agentId },
|
|
142
|
+
...this._path && { dbPath: this._path }
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
getInstructions() {
|
|
147
|
+
const label = this._agentId ? `agent "${this._agentId}"` : "database";
|
|
148
|
+
const access = this.readOnly ? "Read-only" : "Persistent";
|
|
149
|
+
return `AgentFS storage for ${label}. ${access} SQLite-backed filesystem \u2014 files are retained across sessions.`;
|
|
150
|
+
}
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// Lifecycle
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
async init() {
|
|
155
|
+
if (this._agent) return;
|
|
156
|
+
const openOptions = {};
|
|
157
|
+
if (this._agentId) openOptions.id = this._agentId;
|
|
158
|
+
if (this._path) {
|
|
159
|
+
openOptions.path = this._path;
|
|
160
|
+
fs.mkdirSync(nodePath__default.default.dirname(this._path), { recursive: true });
|
|
161
|
+
}
|
|
162
|
+
this._agent = await agentfsSdk.AgentFS.open(openOptions);
|
|
163
|
+
}
|
|
164
|
+
async destroy() {
|
|
165
|
+
if (this._agent && this._ownsAgent) {
|
|
166
|
+
await this._agent.close();
|
|
167
|
+
}
|
|
168
|
+
this._agent = null;
|
|
169
|
+
}
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
// Internal helpers
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
async getAgent() {
|
|
174
|
+
await this.ensureReady();
|
|
175
|
+
return this._agent;
|
|
176
|
+
}
|
|
177
|
+
assertWritable(operation) {
|
|
178
|
+
if (this.readOnly) {
|
|
179
|
+
throw new workspace.WorkspaceReadOnlyError(operation);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// File Operations
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
async readFile(path, options) {
|
|
186
|
+
const agent = await this.getAgent();
|
|
187
|
+
const normalized = normalizePath(path);
|
|
188
|
+
try {
|
|
189
|
+
if (options?.encoding) {
|
|
190
|
+
return await agent.fs.readFile(normalized, options.encoding);
|
|
191
|
+
}
|
|
192
|
+
return await agent.fs.readFile(normalized);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw mapError(error, normalized, "file");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async writeFile(path, content, options) {
|
|
198
|
+
this.assertWritable("writeFile");
|
|
199
|
+
const agent = await this.getAgent();
|
|
200
|
+
const normalized = normalizePath(path);
|
|
201
|
+
if (options?.recursive !== false) {
|
|
202
|
+
await this.mkdirRecursive(agent, getParentPath(normalized));
|
|
203
|
+
}
|
|
204
|
+
if (options?.overwrite === false) {
|
|
205
|
+
try {
|
|
206
|
+
await agent.fs.access(normalized);
|
|
207
|
+
throw new workspace.FileExistsError(normalized);
|
|
208
|
+
} catch (error) {
|
|
209
|
+
if (error instanceof workspace.FileExistsError) throw error;
|
|
210
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalized, "file");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
try {
|
|
214
|
+
const data = typeof content === "string" ? content : Buffer.from(content);
|
|
215
|
+
await agent.fs.writeFile(normalized, data);
|
|
216
|
+
} catch (error) {
|
|
217
|
+
throw mapError(error, normalized, "file");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async appendFile(path, content) {
|
|
221
|
+
this.assertWritable("appendFile");
|
|
222
|
+
let existing = Buffer.alloc(0);
|
|
223
|
+
try {
|
|
224
|
+
const current = await this.readFile(path);
|
|
225
|
+
existing = Buffer.isBuffer(current) ? Buffer.from(current) : Buffer.from(current);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
if (error instanceof workspace.FileNotFoundError) ; else {
|
|
228
|
+
throw error;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const appendBuffer = typeof content === "string" ? Buffer.from(content, "utf-8") : Buffer.from(content);
|
|
232
|
+
await this.writeFile(path, Buffer.concat([existing, appendBuffer]));
|
|
233
|
+
}
|
|
234
|
+
async deleteFile(path, options) {
|
|
235
|
+
this.assertWritable("deleteFile");
|
|
236
|
+
const agent = await this.getAgent();
|
|
237
|
+
const normalized = normalizePath(path);
|
|
238
|
+
try {
|
|
239
|
+
const st = await agent.fs.stat(normalized);
|
|
240
|
+
if (st.isDirectory()) {
|
|
241
|
+
throw new workspace.IsDirectoryError(normalized);
|
|
242
|
+
}
|
|
243
|
+
} catch (error) {
|
|
244
|
+
if (error instanceof workspace.IsDirectoryError) throw error;
|
|
245
|
+
if (hasCode(error, "ENOENT")) {
|
|
246
|
+
if (options?.force) return;
|
|
247
|
+
throw new workspace.FileNotFoundError(normalized);
|
|
248
|
+
}
|
|
249
|
+
throw mapError(error, normalized, "file");
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
await agent.fs.unlink(normalized);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
255
|
+
throw mapError(error, normalized, "file");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async copyFile(src, dest, options) {
|
|
259
|
+
this.assertWritable("copyFile");
|
|
260
|
+
const agent = await this.getAgent();
|
|
261
|
+
const normalizedSrc = normalizePath(src);
|
|
262
|
+
const normalizedDest = normalizePath(dest);
|
|
263
|
+
if (options?.overwrite === false) {
|
|
264
|
+
try {
|
|
265
|
+
await agent.fs.access(normalizedDest);
|
|
266
|
+
throw new workspace.FileExistsError(normalizedDest);
|
|
267
|
+
} catch (error) {
|
|
268
|
+
if (error instanceof workspace.FileExistsError) throw error;
|
|
269
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalizedDest, "file");
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const st = await agent.fs.stat(normalizedSrc);
|
|
274
|
+
if (st.isDirectory()) {
|
|
275
|
+
if (!options?.recursive) {
|
|
276
|
+
throw new workspace.IsDirectoryError(normalizedSrc);
|
|
277
|
+
}
|
|
278
|
+
await this.copyDirRecursive(agent, normalizedSrc, normalizedDest, options);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
await this.mkdirRecursive(agent, getParentPath(normalizedDest));
|
|
282
|
+
await agent.fs.copyFile(normalizedSrc, normalizedDest);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
if (error instanceof workspace.IsDirectoryError || error instanceof workspace.FileExistsError) throw error;
|
|
285
|
+
throw mapError(error, normalizedSrc, "file");
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async moveFile(src, dest, options) {
|
|
289
|
+
this.assertWritable("moveFile");
|
|
290
|
+
const agent = await this.getAgent();
|
|
291
|
+
const normalizedSrc = normalizePath(src);
|
|
292
|
+
const normalizedDest = normalizePath(dest);
|
|
293
|
+
if (options?.overwrite === false) {
|
|
294
|
+
try {
|
|
295
|
+
await agent.fs.access(normalizedDest);
|
|
296
|
+
throw new workspace.FileExistsError(normalizedDest);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
if (error instanceof workspace.FileExistsError) throw error;
|
|
299
|
+
if (!hasCode(error, "ENOENT")) throw mapError(error, normalizedDest, "file");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
await this.mkdirRecursive(agent, getParentPath(normalizedDest));
|
|
303
|
+
try {
|
|
304
|
+
await agent.fs.rename(normalizedSrc, normalizedDest);
|
|
305
|
+
} catch (error) {
|
|
306
|
+
throw mapError(error, normalizedSrc, "file");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// ---------------------------------------------------------------------------
|
|
310
|
+
// Directory Operations
|
|
311
|
+
// ---------------------------------------------------------------------------
|
|
312
|
+
async mkdir(path, options) {
|
|
313
|
+
this.assertWritable("mkdir");
|
|
314
|
+
const agent = await this.getAgent();
|
|
315
|
+
const normalized = normalizePath(path);
|
|
316
|
+
if (options?.recursive !== false) {
|
|
317
|
+
await this.mkdirRecursive(agent, normalized);
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
try {
|
|
321
|
+
await agent.fs.mkdir(normalized);
|
|
322
|
+
} catch (error) {
|
|
323
|
+
throw mapError(error, normalized, "directory");
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async rmdir(path, options) {
|
|
327
|
+
this.assertWritable("rmdir");
|
|
328
|
+
const agent = await this.getAgent();
|
|
329
|
+
const normalized = normalizePath(path);
|
|
330
|
+
if (options?.recursive) {
|
|
331
|
+
try {
|
|
332
|
+
await agent.fs.rm(normalized, { recursive: true });
|
|
333
|
+
} catch (error) {
|
|
334
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
335
|
+
throw mapError(error, normalized, "directory");
|
|
336
|
+
}
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
const entries = await agent.fs.readdir(normalized);
|
|
341
|
+
if (entries.length > 0) {
|
|
342
|
+
throw new workspace.DirectoryNotEmptyError(normalized);
|
|
343
|
+
}
|
|
344
|
+
await agent.fs.rmdir(normalized);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
if (error instanceof workspace.DirectoryNotEmptyError) throw error;
|
|
347
|
+
if (options?.force && hasCode(error, "ENOENT")) return;
|
|
348
|
+
throw mapError(error, normalized, "directory");
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
async readdir(path, options) {
|
|
352
|
+
const agent = await this.getAgent();
|
|
353
|
+
const normalized = normalizePath(path);
|
|
354
|
+
try {
|
|
355
|
+
const st = await agent.fs.stat(normalized);
|
|
356
|
+
if (!st.isDirectory()) {
|
|
357
|
+
throw new workspace.NotDirectoryError(normalized);
|
|
358
|
+
}
|
|
359
|
+
const dirEntries = await agent.fs.readdirPlus(normalized);
|
|
360
|
+
let entries = dirEntries.map((entry) => ({
|
|
361
|
+
name: entry.name,
|
|
362
|
+
type: entry.stats.isDirectory() ? "directory" : "file",
|
|
363
|
+
size: entry.stats.size
|
|
364
|
+
}));
|
|
365
|
+
if (options?.extension) {
|
|
366
|
+
const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];
|
|
367
|
+
entries = entries.filter((entry) => {
|
|
368
|
+
if (entry.type === "directory") return true;
|
|
369
|
+
return extensions.some((ext) => entry.name.endsWith(ext));
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
if (options?.recursive) {
|
|
373
|
+
const maxDepth = options.maxDepth ?? Infinity;
|
|
374
|
+
const subdirs = entries.filter((e) => e.type === "directory");
|
|
375
|
+
for (const dir of subdirs) {
|
|
376
|
+
if (maxDepth > 1) {
|
|
377
|
+
const subEntries = await this.readdir(joinPath(normalized, dir.name), {
|
|
378
|
+
...options,
|
|
379
|
+
maxDepth: maxDepth - 1
|
|
380
|
+
});
|
|
381
|
+
for (const sub of subEntries) {
|
|
382
|
+
entries.push({
|
|
383
|
+
...sub,
|
|
384
|
+
name: dir.name + "/" + sub.name
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return entries;
|
|
391
|
+
} catch (error) {
|
|
392
|
+
if (error instanceof workspace.NotDirectoryError || error instanceof workspace.DirectoryNotFoundError) {
|
|
393
|
+
throw error;
|
|
394
|
+
}
|
|
395
|
+
throw mapError(error, normalized, "directory");
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
// Path Operations
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
async exists(path) {
|
|
402
|
+
const agent = await this.getAgent();
|
|
403
|
+
const normalized = normalizePath(path);
|
|
404
|
+
try {
|
|
405
|
+
await agent.fs.access(normalized);
|
|
406
|
+
return true;
|
|
407
|
+
} catch {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
async stat(path) {
|
|
412
|
+
const agent = await this.getAgent();
|
|
413
|
+
const normalized = normalizePath(path);
|
|
414
|
+
try {
|
|
415
|
+
const st = await agent.fs.stat(normalized);
|
|
416
|
+
return {
|
|
417
|
+
name: getBaseName(normalized) || "",
|
|
418
|
+
path: normalized,
|
|
419
|
+
type: st.isDirectory() ? "directory" : "file",
|
|
420
|
+
size: st.size,
|
|
421
|
+
createdAt: new Date(st.ctime * 1e3),
|
|
422
|
+
modifiedAt: new Date(st.mtime * 1e3)
|
|
423
|
+
};
|
|
424
|
+
} catch (error) {
|
|
425
|
+
throw mapError(error, normalized, "file");
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
// ---------------------------------------------------------------------------
|
|
429
|
+
// Type checks
|
|
430
|
+
// ---------------------------------------------------------------------------
|
|
431
|
+
/**
|
|
432
|
+
* Check if the path points to a file.
|
|
433
|
+
* Returns `false` if the path doesn't exist.
|
|
434
|
+
*/
|
|
435
|
+
async isFile(path) {
|
|
436
|
+
try {
|
|
437
|
+
const st = await this.stat(path);
|
|
438
|
+
return st.type === "file";
|
|
439
|
+
} catch (error) {
|
|
440
|
+
if (error instanceof workspace.FileNotFoundError) return false;
|
|
441
|
+
throw error;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Check if the path points to a directory.
|
|
446
|
+
* Returns `false` if the path doesn't exist.
|
|
447
|
+
*/
|
|
448
|
+
async isDirectory(path) {
|
|
449
|
+
try {
|
|
450
|
+
const st = await this.stat(path);
|
|
451
|
+
return st.type === "directory";
|
|
452
|
+
} catch (error) {
|
|
453
|
+
if (error instanceof workspace.FileNotFoundError) return false;
|
|
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
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// src/provider.ts
|
|
506
|
+
var agentfsFilesystemProvider = {
|
|
507
|
+
id: "agentfs",
|
|
508
|
+
name: "AgentFS",
|
|
509
|
+
description: "Turso/SQLite-backed filesystem via AgentFS",
|
|
510
|
+
configSchema: {
|
|
511
|
+
type: "object",
|
|
512
|
+
properties: {
|
|
513
|
+
agentId: { type: "string", description: "Agent ID \u2014 creates database at .agentfs/<agentId>.db" },
|
|
514
|
+
path: { type: "string", description: "Explicit database file path (alternative to agentId)" },
|
|
515
|
+
readOnly: { type: "boolean", description: "Mount as read-only", default: false }
|
|
516
|
+
}
|
|
517
|
+
},
|
|
518
|
+
createFilesystem: (config) => new AgentFSFilesystem(config)
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
exports.AgentFSFilesystem = AgentFSFilesystem;
|
|
522
|
+
exports.agentfsFilesystemProvider = agentfsFilesystemProvider;
|
|
523
|
+
//# sourceMappingURL=index.cjs.map
|
|
524
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/filesystem/index.ts","../src/provider.ts"],"names":["os","nodePath","DirectoryNotFoundError","FileNotFoundError","FileExistsError","IsDirectoryError","NotDirectoryError","DirectoryNotEmptyError","PermissionError","MastraFilesystem","mkdirSync","AgentFS","WorkspaceReadOnlyError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * AgentFS Filesystem Provider\n *\n * Implements WorkspaceFilesystem backed by AgentFS (Turso/SQLite).\n * Follows the same pattern as S3Filesystem.\n */\n\nimport { mkdirSync } from 'node:fs';\nimport os from 'node:os';\nimport nodePath from 'node:path';\nimport type {\n FileContent,\n FileStat,\n FileEntry,\n ReadOptions,\n WriteOptions,\n ListOptions,\n RemoveOptions,\n CopyOptions,\n FilesystemIcon,\n FilesystemInfo,\n ProviderStatus,\n MastraFilesystemOptions,\n} from '@mastra/core/workspace';\nimport {\n MastraFilesystem,\n FileNotFoundError,\n FileExistsError,\n IsDirectoryError,\n NotDirectoryError,\n DirectoryNotFoundError,\n DirectoryNotEmptyError,\n PermissionError,\n WorkspaceReadOnlyError,\n} from '@mastra/core/workspace';\nimport { AgentFS } from 'agentfs-sdk';\n\n// ---------------------------------------------------------------------------\n// Database path resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Expand a leading `~` to the user's home directory.\n * Node.js path APIs don't handle tilde — only the shell does.\n */\nfunction expandTilde(p: string): string {\n if (p === '~') return os.homedir();\n if (p.startsWith('~/') || p.startsWith('~\\\\')) {\n return nodePath.join(os.homedir(), p.slice(2));\n }\n return p;\n}\n\n/**\n * Resolve a database path to an absolute path.\n * Expands tilde and resolves relative paths against cwd (at construction time).\n */\nfunction resolveDbPath(p: string): string {\n return nodePath.resolve(expandTilde(p));\n}\n\n// ---------------------------------------------------------------------------\n// Path utilities (POSIX-style with leading slash)\n// ---------------------------------------------------------------------------\n\nfunction normalizePath(input: string): string {\n // Treat \".\" and \"\" as root — consistent with how CompositeFilesystem\n // and the Studio UI use \".\" to mean \"filesystem root\".\n if (input === '' || input === '.') return '/';\n\n let path = input.startsWith('/') ? input : '/' + input;\n\n let result = '';\n let prevSlash = false;\n for (let i = 0; i < path.length; i++) {\n const ch = path[i];\n if (ch === '/') {\n if (!prevSlash) {\n result += ch;\n }\n prevSlash = true;\n } else {\n result += ch;\n prevSlash = false;\n }\n }\n\n if (result.length > 1 && result.endsWith('/')) {\n result = result.slice(0, -1);\n }\n\n return result;\n}\n\nfunction getParentPath(path: string): string {\n const normalized = normalizePath(path);\n if (normalized === '/') return '/';\n const lastSlash = normalized.lastIndexOf('/');\n return lastSlash <= 0 ? '/' : normalized.slice(0, lastSlash);\n}\n\nfunction joinPath(base: string, name: string): string {\n if (base === '/') return normalizePath('/' + name);\n return normalizePath(base + '/' + name);\n}\n\nfunction getBaseName(path: string): string {\n const normalized = normalizePath(path);\n if (normalized === '/') return '';\n const lastSlash = normalized.lastIndexOf('/');\n return normalized.slice(lastSlash + 1);\n}\n\n// ---------------------------------------------------------------------------\n// Error mapping (AgentFS errno → Mastra workspace errors)\n// ---------------------------------------------------------------------------\n\ninterface ErrnoError {\n code?: string;\n message?: string;\n}\n\nfunction isErrnoError(error: unknown): error is ErrnoError {\n return typeof error === 'object' && error !== null && 'code' in error;\n}\n\nfunction mapError(error: unknown, path: string, context: 'file' | 'directory' = 'file'): Error {\n if (!isErrnoError(error)) {\n return error instanceof Error ? error : new Error(String(error));\n }\n\n switch (error.code) {\n case 'ENOENT':\n return context === 'directory' ? new DirectoryNotFoundError(path) : new FileNotFoundError(path);\n case 'EEXIST':\n return new FileExistsError(path);\n case 'EISDIR':\n return new IsDirectoryError(path);\n case 'ENOTDIR':\n return new NotDirectoryError(path);\n case 'ENOTEMPTY':\n return new DirectoryNotEmptyError(path);\n case 'EPERM':\n case 'EACCES':\n return new PermissionError(path, 'access');\n default:\n return error instanceof Error ? error : new Error(String(error));\n }\n}\n\nfunction hasCode(error: unknown, code: string): boolean {\n return isErrnoError(error) && error.code === code;\n}\n\n// ---------------------------------------------------------------------------\n// AgentFS Filesystem\n// ---------------------------------------------------------------------------\n\n/**\n * AgentFS filesystem provider configuration.\n */\nexport interface AgentFSFilesystemOptions extends MastraFilesystemOptions {\n /** Unique identifier for this filesystem instance */\n id?: string;\n /** Agent ID — creates database at `.agentfs/<agentId>.db` */\n agentId?: string;\n /** Explicit database file path */\n path?: string;\n /** Pre-opened AgentFS instance (skips open/close — caller manages lifecycle) */\n agent?: AgentFS;\n /** Block write operations (default: false) */\n readOnly?: boolean;\n /** Human-friendly display name for the UI */\n displayName?: string;\n /** Icon identifier for the UI (default: 'database') */\n icon?: FilesystemIcon;\n /** Description shown in tooltips */\n description?: string;\n}\n\n/**\n * AgentFS filesystem implementation.\n *\n * Stores files in a Turso/SQLite database via the AgentFS SDK.\n *\n * @example Using agentId\n * ```typescript\n * import { AgentFSFilesystem } from '@mastra/agentfs';\n *\n * const fs = new AgentFSFilesystem({ agentId: 'my-agent' });\n * ```\n *\n * @example Using a pre-opened instance\n * ```typescript\n * import { AgentFS } from 'agentfs-sdk';\n * import { AgentFSFilesystem } from '@mastra/agentfs';\n *\n * const agent = await AgentFS.open({ id: 'my-agent' });\n * const fs = new AgentFSFilesystem({ agent });\n * ```\n */\nexport class AgentFSFilesystem extends MastraFilesystem {\n readonly id: string;\n readonly name = 'AgentFSFilesystem';\n readonly provider = 'agentfs';\n readonly readOnly?: boolean;\n\n status: ProviderStatus = 'pending';\n\n // Display metadata\n readonly displayName?: string;\n readonly icon: FilesystemIcon;\n readonly description?: string;\n\n private _agent: AgentFS | null = null;\n private readonly _ownsAgent: boolean;\n private readonly _agentId?: string;\n private readonly _path?: string;\n\n constructor(options: AgentFSFilesystemOptions) {\n if (!options.agentId && !options.path && !options.agent) {\n throw new Error(\"AgentFSFilesystem requires at least one of 'agentId', 'path', or 'agent'.\");\n }\n\n super({ ...options, name: 'AgentFSFilesystem' });\n this.id = options.id ?? `agentfs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;\n this._agentId = options.agentId;\n this._path = options.path ? resolveDbPath(options.path) : undefined;\n this.readOnly = options.readOnly;\n\n if (options.agent) {\n this._agent = options.agent;\n this._ownsAgent = false;\n } else {\n this._ownsAgent = true;\n }\n\n this.icon = options.icon ?? 'database';\n this.displayName = options.displayName ?? 'AgentFS';\n this.description = options.description;\n }\n\n /** The underlying AgentFS instance, or null if not yet initialized. */\n get agent(): AgentFS | null {\n return this._agent;\n }\n\n // ---------------------------------------------------------------------------\n // Info\n // ---------------------------------------------------------------------------\n\n getInfo(): FilesystemInfo<{\n agentId?: string;\n dbPath?: string;\n }> {\n return {\n id: this.id,\n name: this.name,\n provider: this.provider,\n status: this.status,\n error: this.error,\n readOnly: this.readOnly,\n icon: this.icon,\n metadata: {\n ...(this._agentId && { agentId: this._agentId }),\n ...(this._path && { dbPath: this._path }),\n },\n };\n }\n\n getInstructions(): string {\n const label = this._agentId ? `agent \"${this._agentId}\"` : 'database';\n const access = this.readOnly ? 'Read-only' : 'Persistent';\n return `AgentFS storage for ${label}. ${access} SQLite-backed filesystem — files are retained across sessions.`;\n }\n\n // ---------------------------------------------------------------------------\n // Lifecycle\n // ---------------------------------------------------------------------------\n\n async init(): Promise<void> {\n if (this._agent) return; // Pre-opened instance\n\n const openOptions: { id?: string; path?: string } = {};\n if (this._agentId) openOptions.id = this._agentId;\n if (this._path) {\n openOptions.path = this._path;\n // Ensure parent directory exists — the SDK only auto-creates `.agentfs/`\n // for the agentId-only case, not for explicit paths.\n mkdirSync(nodePath.dirname(this._path), { recursive: true });\n }\n\n this._agent = await AgentFS.open(openOptions);\n }\n\n async destroy(): Promise<void> {\n if (this._agent && this._ownsAgent) {\n await this._agent.close();\n }\n this._agent = null;\n }\n\n // ---------------------------------------------------------------------------\n // Internal helpers\n // ---------------------------------------------------------------------------\n\n private async getAgent(): Promise<AgentFS> {\n await this.ensureReady();\n return this._agent!;\n }\n\n private assertWritable(operation: string): void {\n if (this.readOnly) {\n throw new WorkspaceReadOnlyError(operation);\n }\n }\n\n // ---------------------------------------------------------------------------\n // File Operations\n // ---------------------------------------------------------------------------\n\n async readFile(path: string, options?: ReadOptions): Promise<string | Buffer> {\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n try {\n if (options?.encoding) {\n return await agent.fs.readFile(normalized, options.encoding);\n }\n return await agent.fs.readFile(normalized);\n } catch (error: unknown) {\n throw mapError(error, normalized, 'file');\n }\n }\n\n async writeFile(path: string, content: FileContent, options?: WriteOptions): Promise<void> {\n this.assertWritable('writeFile');\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n // Create parent directories (default behavior)\n if (options?.recursive !== false) {\n await this.mkdirRecursive(agent, getParentPath(normalized));\n }\n\n // Check overwrite\n if (options?.overwrite === false) {\n try {\n await agent.fs.access(normalized);\n throw new FileExistsError(normalized);\n } catch (error: unknown) {\n if (error instanceof FileExistsError) throw error;\n if (!hasCode(error, 'ENOENT')) throw mapError(error, normalized, 'file');\n }\n }\n\n try {\n const data = typeof content === 'string' ? content : Buffer.from(content);\n await agent.fs.writeFile(normalized, data);\n } catch (error: unknown) {\n throw mapError(error, normalized, 'file');\n }\n }\n\n async appendFile(path: string, content: FileContent): Promise<void> {\n this.assertWritable('appendFile');\n // AgentFS doesn't have native append — read + write (same pattern as S3Filesystem)\n let existing: Buffer = Buffer.alloc(0);\n try {\n const current = await this.readFile(path);\n existing = Buffer.isBuffer(current) ? Buffer.from(current) : Buffer.from(current);\n } catch (error) {\n if (error instanceof FileNotFoundError) {\n // File doesn't exist — start fresh\n } else {\n throw error;\n }\n }\n\n const appendBuffer = typeof content === 'string' ? Buffer.from(content, 'utf-8') : Buffer.from(content);\n await this.writeFile(path, Buffer.concat([existing, appendBuffer]));\n }\n\n async deleteFile(path: string, options?: RemoveOptions): Promise<void> {\n this.assertWritable('deleteFile');\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n // Check if it's a directory\n try {\n const st = await agent.fs.stat(normalized);\n if (st.isDirectory()) {\n throw new IsDirectoryError(normalized);\n }\n } catch (error: unknown) {\n if (error instanceof IsDirectoryError) throw error;\n if (hasCode(error, 'ENOENT')) {\n if (options?.force) return;\n throw new FileNotFoundError(normalized);\n }\n throw mapError(error, normalized, 'file');\n }\n\n try {\n await agent.fs.unlink(normalized);\n } catch (error: unknown) {\n if (options?.force && hasCode(error, 'ENOENT')) return;\n throw mapError(error, normalized, 'file');\n }\n }\n\n async copyFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n this.assertWritable('copyFile');\n const agent = await this.getAgent();\n const normalizedSrc = normalizePath(src);\n const normalizedDest = normalizePath(dest);\n\n if (options?.overwrite === false) {\n try {\n await agent.fs.access(normalizedDest);\n throw new FileExistsError(normalizedDest);\n } catch (error: unknown) {\n if (error instanceof FileExistsError) throw error;\n if (!hasCode(error, 'ENOENT')) throw mapError(error, normalizedDest, 'file');\n }\n }\n\n try {\n // Check if source is a directory\n const st = await agent.fs.stat(normalizedSrc);\n if (st.isDirectory()) {\n if (!options?.recursive) {\n throw new IsDirectoryError(normalizedSrc);\n }\n await this.copyDirRecursive(agent, normalizedSrc, normalizedDest, options);\n return;\n }\n\n // Ensure parent directory of dest exists\n await this.mkdirRecursive(agent, getParentPath(normalizedDest));\n await agent.fs.copyFile(normalizedSrc, normalizedDest);\n } catch (error: unknown) {\n if (error instanceof IsDirectoryError || error instanceof FileExistsError) throw error;\n throw mapError(error, normalizedSrc, 'file');\n }\n }\n\n async moveFile(src: string, dest: string, options?: CopyOptions): Promise<void> {\n this.assertWritable('moveFile');\n const agent = await this.getAgent();\n const normalizedSrc = normalizePath(src);\n const normalizedDest = normalizePath(dest);\n\n if (options?.overwrite === false) {\n try {\n await agent.fs.access(normalizedDest);\n throw new FileExistsError(normalizedDest);\n } catch (error: unknown) {\n if (error instanceof FileExistsError) throw error;\n if (!hasCode(error, 'ENOENT')) throw mapError(error, normalizedDest, 'file');\n }\n }\n\n // Ensure parent directory of dest exists\n await this.mkdirRecursive(agent, getParentPath(normalizedDest));\n\n try {\n await agent.fs.rename(normalizedSrc, normalizedDest);\n } catch (error: unknown) {\n throw mapError(error, normalizedSrc, 'file');\n }\n }\n\n // ---------------------------------------------------------------------------\n // Directory Operations\n // ---------------------------------------------------------------------------\n\n async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {\n this.assertWritable('mkdir');\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n // Default to recursive (matches LocalFilesystem behavior)\n if (options?.recursive !== false) {\n await this.mkdirRecursive(agent, normalized);\n return;\n }\n\n try {\n await agent.fs.mkdir(normalized);\n } catch (error: unknown) {\n throw mapError(error, normalized, 'directory');\n }\n }\n\n async rmdir(path: string, options?: RemoveOptions): Promise<void> {\n this.assertWritable('rmdir');\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n if (options?.recursive) {\n try {\n await agent.fs.rm(normalized, { recursive: true });\n } catch (error: unknown) {\n if (options?.force && hasCode(error, 'ENOENT')) return;\n throw mapError(error, normalized, 'directory');\n }\n return;\n }\n\n // Non-recursive: check if empty first\n try {\n const entries = await agent.fs.readdir(normalized);\n if (entries.length > 0) {\n throw new DirectoryNotEmptyError(normalized);\n }\n await agent.fs.rmdir(normalized);\n } catch (error: unknown) {\n if (error instanceof DirectoryNotEmptyError) throw error;\n if (options?.force && hasCode(error, 'ENOENT')) return;\n throw mapError(error, normalized, 'directory');\n }\n }\n\n async readdir(path: string, options?: ListOptions): Promise<FileEntry[]> {\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n try {\n // Verify it's a directory\n const st = await agent.fs.stat(normalized);\n if (!st.isDirectory()) {\n throw new NotDirectoryError(normalized);\n }\n\n const dirEntries = await agent.fs.readdirPlus(normalized);\n let entries: FileEntry[] = dirEntries.map(entry => ({\n name: entry.name,\n type: entry.stats.isDirectory() ? ('directory' as const) : ('file' as const),\n size: entry.stats.size,\n }));\n\n // Apply extension filter\n if (options?.extension) {\n const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];\n entries = entries.filter(entry => {\n if (entry.type === 'directory') return true;\n return extensions.some(ext => entry.name.endsWith(ext));\n });\n }\n\n // Recurse if requested\n if (options?.recursive) {\n const maxDepth = options.maxDepth ?? Infinity;\n const subdirs = entries.filter(e => e.type === 'directory');\n for (const dir of subdirs) {\n if (maxDepth > 1) {\n const subEntries = await this.readdir(joinPath(normalized, dir.name), {\n ...options,\n maxDepth: maxDepth - 1,\n });\n for (const sub of subEntries) {\n entries.push({\n ...sub,\n name: dir.name + '/' + sub.name,\n });\n }\n }\n }\n }\n\n return entries;\n } catch (error: unknown) {\n if (error instanceof NotDirectoryError || error instanceof DirectoryNotFoundError) {\n throw error;\n }\n throw mapError(error, normalized, 'directory');\n }\n }\n\n // ---------------------------------------------------------------------------\n // Path Operations\n // ---------------------------------------------------------------------------\n\n async exists(path: string): Promise<boolean> {\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n try {\n await agent.fs.access(normalized);\n return true;\n } catch {\n return false;\n }\n }\n\n async stat(path: string): Promise<FileStat> {\n const agent = await this.getAgent();\n const normalized = normalizePath(path);\n\n try {\n const st = await agent.fs.stat(normalized);\n return {\n name: getBaseName(normalized) || '',\n path: normalized,\n type: st.isDirectory() ? 'directory' : 'file',\n size: st.size,\n createdAt: new Date(st.ctime * 1000),\n modifiedAt: new Date(st.mtime * 1000),\n };\n } catch (error: unknown) {\n throw mapError(error, normalized, 'file');\n }\n }\n\n // ---------------------------------------------------------------------------\n // Type checks\n // ---------------------------------------------------------------------------\n\n /**\n * Check if the path points to a file.\n * Returns `false` if the path doesn't exist.\n */\n async isFile(path: string): Promise<boolean> {\n try {\n const st = await this.stat(path);\n return st.type === 'file';\n } catch (error) {\n if (error instanceof FileNotFoundError) return false;\n throw error;\n }\n }\n\n /**\n * Check if the path points to a directory.\n * Returns `false` if the path doesn't exist.\n */\n async isDirectory(path: string): Promise<boolean> {\n try {\n const st = await this.stat(path);\n return st.type === 'directory';\n } catch (error) {\n if (error instanceof FileNotFoundError) return false;\n throw error;\n }\n }\n\n // ---------------------------------------------------------------------------\n // Private helpers\n // ---------------------------------------------------------------------------\n\n /**\n * Recursively create directories, ignoring EEXIST errors.\n */\n private async mkdirRecursive(agent: AgentFS, path: string): Promise<void> {\n if (path === '/') return;\n\n const segments = path.split('/').filter(Boolean);\n let current = '';\n for (const segment of segments) {\n current += '/' + segment;\n try {\n await agent.fs.mkdir(current);\n } catch (error: unknown) {\n if (!hasCode(error, 'EEXIST')) {\n throw mapError(error, current, 'directory');\n }\n }\n }\n }\n\n /**\n * Recursively copy a directory tree.\n */\n private async copyDirRecursive(agent: AgentFS, src: string, dest: string, options?: CopyOptions): Promise<void> {\n await this.mkdirRecursive(agent, dest);\n\n const entries = await agent.fs.readdirPlus(src);\n for (const entry of entries) {\n const srcChild = joinPath(src, entry.name);\n const destChild = joinPath(dest, entry.name);\n\n if (entry.stats.isDirectory()) {\n await this.copyDirRecursive(agent, srcChild, destChild, options);\n } else {\n if (options?.overwrite === false) {\n try {\n await agent.fs.access(destChild);\n throw new FileExistsError(destChild);\n } catch (error: unknown) {\n if (error instanceof FileExistsError) throw error;\n if (!hasCode(error, 'ENOENT')) throw mapError(error, destChild, 'file');\n }\n }\n await agent.fs.copyFile(srcChild, destChild);\n }\n }\n }\n}\n","/**\n * AgentFS filesystem provider descriptor for MastraEditor.\n *\n * @example\n * ```typescript\n * import { agentfsFilesystemProvider } from '@mastra/agentfs';\n *\n * const editor = new MastraEditor({\n * filesystems: [agentfsFilesystemProvider],\n * });\n * ```\n */\nimport type { FilesystemProvider } from '@mastra/core/editor';\nimport { AgentFSFilesystem } from './filesystem';\nimport type { AgentFSFilesystemOptions } from './filesystem';\n\nexport const agentfsFilesystemProvider: FilesystemProvider<AgentFSFilesystemOptions> = {\n id: 'agentfs',\n name: 'AgentFS',\n description: 'Turso/SQLite-backed filesystem via AgentFS',\n configSchema: {\n type: 'object',\n properties: {\n agentId: { type: 'string', description: 'Agent ID — creates database at .agentfs/<agentId>.db' },\n path: { type: 'string', description: 'Explicit database file path (alternative to agentId)' },\n readOnly: { type: 'boolean', description: 'Mount as read-only', default: false },\n },\n },\n createFilesystem: config => new AgentFSFilesystem(config),\n};\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mastra/agentfs - AgentFS (Turso/SQLite-backed) Filesystem Provider
|
|
3
|
+
*
|
|
4
|
+
* A filesystem implementation backed by AgentFS, storing files in a
|
|
5
|
+
* Turso/SQLite database via the agentfs-sdk.
|
|
6
|
+
*/
|
|
7
|
+
export { AgentFSFilesystem, type AgentFSFilesystemOptions } from './filesystem/index.js';
|
|
8
|
+
export { agentfsFilesystemProvider } from './provider.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC"}
|