@aigne/afs-fs 1.11.0-beta.2
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 +26 -0
- package/README.md +337 -0
- package/dist/_virtual/rolldown_runtime.cjs +29 -0
- package/dist/index.cjs +360 -0
- package/dist/index.d.cts +98 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +98 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +359 -0
- package/dist/index.mjs.map +1 -0
- package/dist/utils/ripgrep.cjs +85 -0
- package/dist/utils/ripgrep.mjs +85 -0
- package/dist/utils/ripgrep.mjs.map +1 -0
- package/package.json +58 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_ripgrep = require('./utils/ripgrep.cjs');
|
|
3
|
+
let node_fs_promises = require("node:fs/promises");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
let _aigne_afs_utils_zod = require("@aigne/afs/utils/zod");
|
|
6
|
+
let ignore = require("ignore");
|
|
7
|
+
ignore = require_rolldown_runtime.__toESM(ignore);
|
|
8
|
+
let minimatch = require("minimatch");
|
|
9
|
+
let zod = require("zod");
|
|
10
|
+
|
|
11
|
+
//#region src/index.ts
|
|
12
|
+
const LIST_MAX_LIMIT = 1e3;
|
|
13
|
+
const afsFSOptionsSchema = (0, _aigne_afs_utils_zod.camelize)(zod.z.object({
|
|
14
|
+
name: (0, _aigne_afs_utils_zod.optionalize)(zod.z.string()),
|
|
15
|
+
localPath: zod.z.string().describe("The path to the local directory to mount"),
|
|
16
|
+
description: (0, _aigne_afs_utils_zod.optionalize)(zod.z.string().describe("A description of the mounted directory")),
|
|
17
|
+
ignore: (0, _aigne_afs_utils_zod.optionalize)(zod.z.array(zod.z.string())),
|
|
18
|
+
accessMode: (0, _aigne_afs_utils_zod.optionalize)(zod.z.enum(["readonly", "readwrite"]).describe("Access mode for this module")),
|
|
19
|
+
agentSkills: (0, _aigne_afs_utils_zod.optionalize)(zod.z.boolean().describe("Enable automatic agent skill scanning for this module"))
|
|
20
|
+
}));
|
|
21
|
+
var AFSFS = class AFSFS {
|
|
22
|
+
static schema() {
|
|
23
|
+
return afsFSOptionsSchema;
|
|
24
|
+
}
|
|
25
|
+
static async load({ filepath, parsed }) {
|
|
26
|
+
return new AFSFS({
|
|
27
|
+
...await AFSFS.schema().parseAsync(parsed),
|
|
28
|
+
cwd: (0, node_path.dirname)(filepath)
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
constructor(options) {
|
|
32
|
+
this.options = options;
|
|
33
|
+
(0, _aigne_afs_utils_zod.zodParse)(afsFSOptionsSchema, options);
|
|
34
|
+
let localPath;
|
|
35
|
+
if (options.localPath === ".") localPath = process.cwd();
|
|
36
|
+
else {
|
|
37
|
+
localPath = options.localPath.replaceAll("${CWD}", process.cwd());
|
|
38
|
+
if (localPath.startsWith("~/")) localPath = (0, node_path.join)(process.env.HOME || "", localPath.slice(2));
|
|
39
|
+
if (!(0, node_path.isAbsolute)(localPath)) localPath = (0, node_path.join)(options.cwd || process.cwd(), localPath);
|
|
40
|
+
}
|
|
41
|
+
this.name = options.name || (0, node_path.basename)(localPath) || "fs";
|
|
42
|
+
this.description = options.description;
|
|
43
|
+
this.agentSkills = options.agentSkills;
|
|
44
|
+
this.accessMode = options.accessMode ?? (options.agentSkills ? "readonly" : "readwrite");
|
|
45
|
+
this.options.localPath = localPath;
|
|
46
|
+
}
|
|
47
|
+
name;
|
|
48
|
+
description;
|
|
49
|
+
accessMode;
|
|
50
|
+
agentSkills;
|
|
51
|
+
get localPathExists() {
|
|
52
|
+
return (0, node_fs_promises.stat)(this.options.localPath).then(() => true).catch(() => false);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Detect MIME type based on file extension
|
|
56
|
+
*/
|
|
57
|
+
getMimeType(filePath) {
|
|
58
|
+
return {
|
|
59
|
+
png: "image/png",
|
|
60
|
+
jpg: "image/jpeg",
|
|
61
|
+
jpeg: "image/jpeg",
|
|
62
|
+
gif: "image/gif",
|
|
63
|
+
bmp: "image/bmp",
|
|
64
|
+
webp: "image/webp",
|
|
65
|
+
svg: "image/svg+xml",
|
|
66
|
+
ico: "image/x-icon",
|
|
67
|
+
pdf: "application/pdf",
|
|
68
|
+
txt: "text/plain",
|
|
69
|
+
md: "text/markdown",
|
|
70
|
+
js: "text/javascript",
|
|
71
|
+
ts: "text/typescript",
|
|
72
|
+
json: "application/json",
|
|
73
|
+
html: "text/html",
|
|
74
|
+
css: "text/css",
|
|
75
|
+
xml: "text/xml"
|
|
76
|
+
}[(0, node_path.basename)(filePath).split(".").pop()?.toLowerCase() || ""] || "application/octet-stream";
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if file is likely binary based on extension
|
|
80
|
+
*/
|
|
81
|
+
isBinaryFile(filePath) {
|
|
82
|
+
const ext = (0, node_path.basename)(filePath).split(".").pop()?.toLowerCase();
|
|
83
|
+
return [
|
|
84
|
+
"png",
|
|
85
|
+
"jpg",
|
|
86
|
+
"jpeg",
|
|
87
|
+
"gif",
|
|
88
|
+
"bmp",
|
|
89
|
+
"webp",
|
|
90
|
+
"ico",
|
|
91
|
+
"pdf",
|
|
92
|
+
"zip",
|
|
93
|
+
"tar",
|
|
94
|
+
"gz",
|
|
95
|
+
"exe",
|
|
96
|
+
"dll",
|
|
97
|
+
"so",
|
|
98
|
+
"dylib",
|
|
99
|
+
"wasm"
|
|
100
|
+
].includes(ext || "");
|
|
101
|
+
}
|
|
102
|
+
async symlinkToPhysical(path) {
|
|
103
|
+
if (await this.localPathExists) await (0, node_fs_promises.symlink)(this.options.localPath, path);
|
|
104
|
+
}
|
|
105
|
+
async list(path, options) {
|
|
106
|
+
path = (0, node_path.join)("/", path);
|
|
107
|
+
const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);
|
|
108
|
+
const maxChildren = typeof options?.maxChildren === "number" ? options.maxChildren : Number.MAX_SAFE_INTEGER;
|
|
109
|
+
const maxDepth = options?.maxDepth ?? 1;
|
|
110
|
+
const disableGitignore = options?.disableGitignore ?? false;
|
|
111
|
+
const pattern = options?.pattern;
|
|
112
|
+
const basePath = (0, node_path.join)(this.options.localPath, path);
|
|
113
|
+
const mountRoot = this.options.localPath;
|
|
114
|
+
if (typeof maxChildren === "number" && maxChildren <= 0) throw new Error(`Invalid maxChildren: ${maxChildren}. Must be positive.`);
|
|
115
|
+
const entries = [];
|
|
116
|
+
const queue = [];
|
|
117
|
+
queue.push({
|
|
118
|
+
fullPath: basePath,
|
|
119
|
+
relativePath: path || "/",
|
|
120
|
+
depth: 0,
|
|
121
|
+
gitignored: false
|
|
122
|
+
});
|
|
123
|
+
while (true) {
|
|
124
|
+
const item = queue.shift();
|
|
125
|
+
if (!item) break;
|
|
126
|
+
const { fullPath, relativePath, depth, gitignored } = item;
|
|
127
|
+
const stats = await (0, node_fs_promises.stat)(fullPath);
|
|
128
|
+
const isDirectory = stats.isDirectory();
|
|
129
|
+
let childItemsWithStatus;
|
|
130
|
+
if (isDirectory && !gitignored) {
|
|
131
|
+
const items = (await (0, node_fs_promises.readdir)(fullPath)).sort();
|
|
132
|
+
let ig = null;
|
|
133
|
+
let ignoreBase = mountRoot;
|
|
134
|
+
if (!disableGitignore) {
|
|
135
|
+
const result = await this.loadIgnoreRules(fullPath, mountRoot);
|
|
136
|
+
ig = result?.ig || null;
|
|
137
|
+
ignoreBase = result?.ignoreBase || mountRoot;
|
|
138
|
+
}
|
|
139
|
+
childItemsWithStatus = items.map((childName) => {
|
|
140
|
+
if (!ig) return {
|
|
141
|
+
name: childName,
|
|
142
|
+
gitignored: false
|
|
143
|
+
};
|
|
144
|
+
const itemFullPath = (0, node_path.join)(fullPath, childName);
|
|
145
|
+
const itemRelativePath = (0, node_path.relative)(ignoreBase, itemFullPath);
|
|
146
|
+
return {
|
|
147
|
+
name: childName,
|
|
148
|
+
gitignored: ig.ignores(itemRelativePath) || ig.ignores(`${itemRelativePath}/`)
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const metadata = {
|
|
153
|
+
childrenCount: childItemsWithStatus?.length,
|
|
154
|
+
type: isDirectory ? "directory" : "file",
|
|
155
|
+
size: stats.size,
|
|
156
|
+
gitignored: gitignored || void 0
|
|
157
|
+
};
|
|
158
|
+
if (!isDirectory) metadata.mimeType = this.getMimeType(fullPath);
|
|
159
|
+
const entry = {
|
|
160
|
+
id: relativePath,
|
|
161
|
+
path: relativePath,
|
|
162
|
+
createdAt: stats.birthtime,
|
|
163
|
+
updatedAt: stats.mtime,
|
|
164
|
+
metadata
|
|
165
|
+
};
|
|
166
|
+
if (!pattern || (0, minimatch.minimatch)(relativePath, pattern, { matchBase: true })) entries.push(entry);
|
|
167
|
+
if (entries.length >= limit) {
|
|
168
|
+
if (isDirectory && entry.metadata) entry.metadata.childrenTruncated = true;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
if (isDirectory && depth < maxDepth && childItemsWithStatus) {
|
|
172
|
+
const itemsToProcess = childItemsWithStatus.length > maxChildren ? childItemsWithStatus.slice(0, maxChildren) : childItemsWithStatus;
|
|
173
|
+
if (itemsToProcess.length < childItemsWithStatus.length && entry.metadata) entry.metadata.childrenTruncated = true;
|
|
174
|
+
for (const child of itemsToProcess) queue.push({
|
|
175
|
+
fullPath: (0, node_path.join)(fullPath, child.name),
|
|
176
|
+
relativePath: (0, node_path.join)(relativePath, child.name),
|
|
177
|
+
depth: depth + 1,
|
|
178
|
+
gitignored: child.gitignored
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return { data: entries };
|
|
183
|
+
}
|
|
184
|
+
async read(path, _options) {
|
|
185
|
+
try {
|
|
186
|
+
const fullPath = (0, node_path.join)(this.options.localPath, path);
|
|
187
|
+
const stats = await (0, node_fs_promises.stat)(fullPath);
|
|
188
|
+
let content;
|
|
189
|
+
const metadata = {
|
|
190
|
+
type: stats.isDirectory() ? "directory" : "file",
|
|
191
|
+
size: stats.size
|
|
192
|
+
};
|
|
193
|
+
if (stats.isFile()) {
|
|
194
|
+
const mimeType = this.getMimeType(fullPath);
|
|
195
|
+
const isBinary = this.isBinaryFile(fullPath);
|
|
196
|
+
metadata.mimeType = mimeType;
|
|
197
|
+
if (isBinary) {
|
|
198
|
+
content = (await (0, node_fs_promises.readFile)(fullPath)).toString("base64");
|
|
199
|
+
metadata.contentType = "base64";
|
|
200
|
+
} else content = await (0, node_fs_promises.readFile)(fullPath, "utf8");
|
|
201
|
+
}
|
|
202
|
+
return { data: {
|
|
203
|
+
id: path,
|
|
204
|
+
path,
|
|
205
|
+
createdAt: stats.birthtime,
|
|
206
|
+
updatedAt: stats.mtime,
|
|
207
|
+
content,
|
|
208
|
+
metadata
|
|
209
|
+
} };
|
|
210
|
+
} catch (error) {
|
|
211
|
+
return {
|
|
212
|
+
data: void 0,
|
|
213
|
+
message: error.message
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async write(path, entry, options) {
|
|
218
|
+
const fullPath = (0, node_path.join)(this.options.localPath, path);
|
|
219
|
+
const append = options?.append ?? false;
|
|
220
|
+
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(fullPath), { recursive: true });
|
|
221
|
+
if (entry.content !== void 0) {
|
|
222
|
+
let contentToWrite;
|
|
223
|
+
if (typeof entry.content === "string") contentToWrite = entry.content;
|
|
224
|
+
else contentToWrite = JSON.stringify(entry.content, null, 2);
|
|
225
|
+
await (0, node_fs_promises.writeFile)(fullPath, contentToWrite, {
|
|
226
|
+
encoding: "utf8",
|
|
227
|
+
flag: append ? "a" : "w"
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
const stats = await (0, node_fs_promises.stat)(fullPath);
|
|
231
|
+
return { data: {
|
|
232
|
+
id: path,
|
|
233
|
+
path,
|
|
234
|
+
createdAt: stats.birthtime,
|
|
235
|
+
updatedAt: stats.mtime,
|
|
236
|
+
content: entry.content,
|
|
237
|
+
summary: entry.summary,
|
|
238
|
+
metadata: {
|
|
239
|
+
...entry.metadata,
|
|
240
|
+
type: stats.isDirectory() ? "directory" : "file",
|
|
241
|
+
size: stats.size
|
|
242
|
+
},
|
|
243
|
+
userId: entry.userId,
|
|
244
|
+
sessionId: entry.sessionId,
|
|
245
|
+
linkTo: entry.linkTo
|
|
246
|
+
} };
|
|
247
|
+
}
|
|
248
|
+
async delete(path, options) {
|
|
249
|
+
const fullPath = (0, node_path.join)(this.options.localPath, path);
|
|
250
|
+
const recursive = options?.recursive ?? false;
|
|
251
|
+
if ((await (0, node_fs_promises.stat)(fullPath)).isDirectory() && !recursive) throw new Error(`Cannot delete directory '${path}' without recursive option. Set recursive: true to delete directories.`);
|
|
252
|
+
await (0, node_fs_promises.rm)(fullPath, {
|
|
253
|
+
recursive,
|
|
254
|
+
force: true
|
|
255
|
+
});
|
|
256
|
+
return { message: `Successfully deleted: ${path}` };
|
|
257
|
+
}
|
|
258
|
+
async rename(oldPath, newPath, options) {
|
|
259
|
+
const oldFullPath = (0, node_path.join)(this.options.localPath, oldPath);
|
|
260
|
+
const newFullPath = (0, node_path.join)(this.options.localPath, newPath);
|
|
261
|
+
const overwrite = options?.overwrite ?? false;
|
|
262
|
+
await (0, node_fs_promises.stat)(oldFullPath);
|
|
263
|
+
try {
|
|
264
|
+
await (0, node_fs_promises.stat)(newFullPath);
|
|
265
|
+
if (!overwrite) throw new Error(`Destination '${newPath}' already exists. Set overwrite: true to replace it.`);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
if (error.code !== "ENOENT") throw error;
|
|
268
|
+
}
|
|
269
|
+
await (0, node_fs_promises.mkdir)((0, node_path.dirname)(newFullPath), { recursive: true });
|
|
270
|
+
await (0, node_fs_promises.rename)(oldFullPath, newFullPath);
|
|
271
|
+
return { message: `Successfully renamed '${oldPath}' to '${newPath}'` };
|
|
272
|
+
}
|
|
273
|
+
async search(path, query, options) {
|
|
274
|
+
const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);
|
|
275
|
+
const basePath = (0, node_path.join)(this.options.localPath, path);
|
|
276
|
+
const matches = await require_ripgrep.searchWithRipgrep(basePath, query, options);
|
|
277
|
+
const entries = [];
|
|
278
|
+
const processedFiles = /* @__PURE__ */ new Set();
|
|
279
|
+
let hasMoreFiles = false;
|
|
280
|
+
for (const match of matches) if (match.type === "match" && match.data.path) {
|
|
281
|
+
const absolutePath = match.data.path.text;
|
|
282
|
+
const itemRelativePath = (0, node_path.join)(path, (0, node_path.relative)(basePath, absolutePath));
|
|
283
|
+
if (processedFiles.has(itemRelativePath)) continue;
|
|
284
|
+
processedFiles.add(itemRelativePath);
|
|
285
|
+
const stats = await (0, node_fs_promises.stat)(absolutePath);
|
|
286
|
+
const entry = {
|
|
287
|
+
id: itemRelativePath,
|
|
288
|
+
path: itemRelativePath,
|
|
289
|
+
createdAt: stats.birthtime,
|
|
290
|
+
updatedAt: stats.mtime,
|
|
291
|
+
summary: match.data.lines?.text,
|
|
292
|
+
metadata: {
|
|
293
|
+
type: "file",
|
|
294
|
+
size: stats.size
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
entries.push(entry);
|
|
298
|
+
if (entries.length >= limit) {
|
|
299
|
+
hasMoreFiles = true;
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
data: entries,
|
|
305
|
+
message: hasMoreFiles ? `Results truncated to limit ${limit}` : void 0
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Load gitignore rules from mountRoot down to checkPath.
|
|
310
|
+
* Accumulates rules from parent to child for proper inheritance.
|
|
311
|
+
* Stops at .git boundaries (submodules are independent repos).
|
|
312
|
+
* @param checkPath - The directory whose files we're checking
|
|
313
|
+
* @param mountRoot - The mounted local filesystem root (stop point for walking up)
|
|
314
|
+
* @returns An object with ignore instance and the base path for matching
|
|
315
|
+
*/
|
|
316
|
+
async loadIgnoreRules(checkPath, mountRoot) {
|
|
317
|
+
const ig = (0, ignore.default)();
|
|
318
|
+
const dirsToCheck = [];
|
|
319
|
+
let currentPath = checkPath;
|
|
320
|
+
let gitBoundary = null;
|
|
321
|
+
while (true) {
|
|
322
|
+
dirsToCheck.unshift(currentPath);
|
|
323
|
+
if (gitBoundary === null) try {
|
|
324
|
+
await (0, node_fs_promises.stat)((0, node_path.join)(currentPath, ".git"));
|
|
325
|
+
gitBoundary = currentPath;
|
|
326
|
+
} catch {}
|
|
327
|
+
if (currentPath === mountRoot) break;
|
|
328
|
+
const parentPath = (0, node_path.dirname)(currentPath);
|
|
329
|
+
if (!currentPath.startsWith(mountRoot) || parentPath === currentPath) break;
|
|
330
|
+
currentPath = parentPath;
|
|
331
|
+
}
|
|
332
|
+
const effectiveStart = gitBoundary || mountRoot;
|
|
333
|
+
const filteredDirs = dirsToCheck.filter((dir) => dir >= effectiveStart);
|
|
334
|
+
for (const dirPath of filteredDirs) try {
|
|
335
|
+
const gitignoreContent = await (0, node_fs_promises.readFile)((0, node_path.join)(dirPath, ".gitignore"), "utf8");
|
|
336
|
+
const effectiveBase = gitBoundary && dirPath >= gitBoundary ? gitBoundary : mountRoot;
|
|
337
|
+
if (dirPath !== effectiveBase) {
|
|
338
|
+
const prefix = (0, node_path.relative)(effectiveBase, dirPath);
|
|
339
|
+
const prefixedLines = gitignoreContent.split("\n").map((line) => {
|
|
340
|
+
const trimmed = line.trim();
|
|
341
|
+
if (!trimmed || trimmed.startsWith("#")) return line;
|
|
342
|
+
if (trimmed.startsWith("!")) return line;
|
|
343
|
+
if (trimmed.startsWith("/")) return `/${prefix}${trimmed}`;
|
|
344
|
+
if (trimmed.includes("/")) return `${prefix}/${trimmed}`;
|
|
345
|
+
return `${prefix}/**/${trimmed}`;
|
|
346
|
+
});
|
|
347
|
+
ig.add(prefixedLines.join("\n"));
|
|
348
|
+
} else ig.add(gitignoreContent);
|
|
349
|
+
} catch {}
|
|
350
|
+
ig.add(".git");
|
|
351
|
+
ig.add(this.options.ignore || []);
|
|
352
|
+
return {
|
|
353
|
+
ig,
|
|
354
|
+
ignoreBase: effectiveStart
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
//#endregion
|
|
360
|
+
exports.AFSFS = AFSFS;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { AFSAccessMode, AFSDeleteOptions, AFSDeleteResult, AFSListOptions, AFSListResult, AFSModule, AFSModuleLoadParams, AFSReadOptions, AFSReadResult, AFSRenameOptions, AFSSearchOptions, AFSSearchResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
interface AFSFSOptions {
|
|
6
|
+
name?: string;
|
|
7
|
+
localPath: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
ignore?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Access mode for this module.
|
|
12
|
+
* - "readonly": Only read operations are allowed
|
|
13
|
+
* - "readwrite": All operations are allowed (default, unless agentSkills is enabled)
|
|
14
|
+
* @default "readwrite" (or "readonly" when agentSkills is true)
|
|
15
|
+
*/
|
|
16
|
+
accessMode?: AFSAccessMode;
|
|
17
|
+
/**
|
|
18
|
+
* Enable automatic agent skill scanning for this module.
|
|
19
|
+
* When enabled, defaults accessMode to "readonly" if not explicitly set.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
agentSkills?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare class AFSFS implements AFSModule {
|
|
25
|
+
options: AFSFSOptions & {
|
|
26
|
+
cwd?: string;
|
|
27
|
+
};
|
|
28
|
+
static schema(): z.ZodEffects<z.ZodObject<{
|
|
29
|
+
name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
|
|
30
|
+
localPath: z.ZodString;
|
|
31
|
+
description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
|
|
32
|
+
ignore: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
|
|
33
|
+
accessMode: z.ZodType<"readonly" | "readwrite" | undefined, z.ZodTypeDef, "readonly" | "readwrite" | undefined>;
|
|
34
|
+
agentSkills: z.ZodType<boolean | undefined, z.ZodTypeDef, boolean | undefined>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
localPath: string;
|
|
37
|
+
name?: string | undefined;
|
|
38
|
+
description?: string | undefined;
|
|
39
|
+
ignore?: string[] | undefined;
|
|
40
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
41
|
+
agentSkills?: boolean | undefined;
|
|
42
|
+
}, {
|
|
43
|
+
localPath: string;
|
|
44
|
+
name?: string | undefined;
|
|
45
|
+
description?: string | undefined;
|
|
46
|
+
ignore?: string[] | undefined;
|
|
47
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
48
|
+
agentSkills?: boolean | undefined;
|
|
49
|
+
}>, {
|
|
50
|
+
localPath: string;
|
|
51
|
+
name?: string | undefined;
|
|
52
|
+
description?: string | undefined;
|
|
53
|
+
ignore?: string[] | undefined;
|
|
54
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
55
|
+
agentSkills?: boolean | undefined;
|
|
56
|
+
}, any>;
|
|
57
|
+
static load({
|
|
58
|
+
filepath,
|
|
59
|
+
parsed
|
|
60
|
+
}: AFSModuleLoadParams): Promise<AFSFS>;
|
|
61
|
+
constructor(options: AFSFSOptions & {
|
|
62
|
+
cwd?: string;
|
|
63
|
+
});
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
accessMode: AFSAccessMode;
|
|
67
|
+
agentSkills?: boolean;
|
|
68
|
+
private get localPathExists();
|
|
69
|
+
/**
|
|
70
|
+
* Detect MIME type based on file extension
|
|
71
|
+
*/
|
|
72
|
+
private getMimeType;
|
|
73
|
+
/**
|
|
74
|
+
* Check if file is likely binary based on extension
|
|
75
|
+
*/
|
|
76
|
+
private isBinaryFile;
|
|
77
|
+
symlinkToPhysical(path: string): Promise<void>;
|
|
78
|
+
list(path: string, options?: AFSListOptions): Promise<AFSListResult>;
|
|
79
|
+
read(path: string, _options?: AFSReadOptions): Promise<AFSReadResult>;
|
|
80
|
+
write(path: string, entry: AFSWriteEntryPayload, options?: AFSWriteOptions): Promise<AFSWriteResult>;
|
|
81
|
+
delete(path: string, options?: AFSDeleteOptions): Promise<AFSDeleteResult>;
|
|
82
|
+
rename(oldPath: string, newPath: string, options?: AFSRenameOptions): Promise<{
|
|
83
|
+
message?: string;
|
|
84
|
+
}>;
|
|
85
|
+
search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult>;
|
|
86
|
+
/**
|
|
87
|
+
* Load gitignore rules from mountRoot down to checkPath.
|
|
88
|
+
* Accumulates rules from parent to child for proper inheritance.
|
|
89
|
+
* Stops at .git boundaries (submodules are independent repos).
|
|
90
|
+
* @param checkPath - The directory whose files we're checking
|
|
91
|
+
* @param mountRoot - The mounted local filesystem root (stop point for walking up)
|
|
92
|
+
* @returns An object with ignore instance and the base path for matching
|
|
93
|
+
*/
|
|
94
|
+
private loadIgnoreRules;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { AFSFS, AFSFSOptions };
|
|
98
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;;;UA6BiB,YAAA;EAAA,IAAA;EAAA,SAAA;EAAA,WAAA;EAAA,MAAA;EAAA;AAmCjB;;;;;EAnCiB,UAAA,GAWF,aAAA;EAAA;AAwBf;;;;EAxBe,WAAA;AAAA;AAAA,cAwBF,KAAA,YAAiB,SAAA;EAAA,OAAA,EAWA,YAAA;IAAA,GAAA;EAAA;EAAA,OAAA,OAAA,GAVf,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;IAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAI2B,mBAAA,GAAmB,OAAA,CAAA,KAAA;EAAA,YAAA,OAAA,EAM/B,YAAA;IAAA,GAAA;EAAA;EAAA,IAAA;EAAA,WAAA;EAAA,UAAA,EA2BhB,aAAA;EAAA,WAAA;EAAA,YAAA,gBAAA;EAAA;;;EAAA,QAAA,WAAA;EAAA;;;EAAA,QAAA,YAAA;EAAA,kBAAA,IAAA,WAkE2B,OAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GAMJ,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,KAAA,IAAA,UAAA,QAAA,GA8IxB,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,MAAA,IAAA,UAAA,KAAA,EAkDpD,oBAAA,EAAA,OAAA,GACG,eAAA,GACT,OAAA,CAAQ,cAAA;EAAA,OAAA,IAAA,UAAA,OAAA,GA6C0B,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,OAAA,OAAA,UAAA,OAAA,UAAA,OAAA,GAoBpD,gBAAA,GACT,OAAA;IAAA,OAAA;EAAA;EAAA,OAAA,IAAA,UAAA,KAAA,UAAA,OAAA,GAiCiD,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA;;;;;;;;EAAA,QAAA,eAAA;AAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AFSAccessMode, AFSDeleteOptions, AFSDeleteResult, AFSListOptions, AFSListResult, AFSModule, AFSModuleLoadParams, AFSReadOptions, AFSReadResult, AFSRenameOptions, AFSSearchOptions, AFSSearchResult, AFSWriteEntryPayload, AFSWriteOptions, AFSWriteResult } from "@aigne/afs";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
interface AFSFSOptions {
|
|
6
|
+
name?: string;
|
|
7
|
+
localPath: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
ignore?: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Access mode for this module.
|
|
12
|
+
* - "readonly": Only read operations are allowed
|
|
13
|
+
* - "readwrite": All operations are allowed (default, unless agentSkills is enabled)
|
|
14
|
+
* @default "readwrite" (or "readonly" when agentSkills is true)
|
|
15
|
+
*/
|
|
16
|
+
accessMode?: AFSAccessMode;
|
|
17
|
+
/**
|
|
18
|
+
* Enable automatic agent skill scanning for this module.
|
|
19
|
+
* When enabled, defaults accessMode to "readonly" if not explicitly set.
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
agentSkills?: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare class AFSFS implements AFSModule {
|
|
25
|
+
options: AFSFSOptions & {
|
|
26
|
+
cwd?: string;
|
|
27
|
+
};
|
|
28
|
+
static schema(): z.ZodEffects<z.ZodObject<{
|
|
29
|
+
name: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
|
|
30
|
+
localPath: z.ZodString;
|
|
31
|
+
description: z.ZodType<string | undefined, z.ZodTypeDef, string | undefined>;
|
|
32
|
+
ignore: z.ZodType<string[] | undefined, z.ZodTypeDef, string[] | undefined>;
|
|
33
|
+
accessMode: z.ZodType<"readonly" | "readwrite" | undefined, z.ZodTypeDef, "readonly" | "readwrite" | undefined>;
|
|
34
|
+
agentSkills: z.ZodType<boolean | undefined, z.ZodTypeDef, boolean | undefined>;
|
|
35
|
+
}, "strip", z.ZodTypeAny, {
|
|
36
|
+
localPath: string;
|
|
37
|
+
name?: string | undefined;
|
|
38
|
+
description?: string | undefined;
|
|
39
|
+
ignore?: string[] | undefined;
|
|
40
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
41
|
+
agentSkills?: boolean | undefined;
|
|
42
|
+
}, {
|
|
43
|
+
localPath: string;
|
|
44
|
+
name?: string | undefined;
|
|
45
|
+
description?: string | undefined;
|
|
46
|
+
ignore?: string[] | undefined;
|
|
47
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
48
|
+
agentSkills?: boolean | undefined;
|
|
49
|
+
}>, {
|
|
50
|
+
localPath: string;
|
|
51
|
+
name?: string | undefined;
|
|
52
|
+
description?: string | undefined;
|
|
53
|
+
ignore?: string[] | undefined;
|
|
54
|
+
accessMode?: "readonly" | "readwrite" | undefined;
|
|
55
|
+
agentSkills?: boolean | undefined;
|
|
56
|
+
}, any>;
|
|
57
|
+
static load({
|
|
58
|
+
filepath,
|
|
59
|
+
parsed
|
|
60
|
+
}: AFSModuleLoadParams): Promise<AFSFS>;
|
|
61
|
+
constructor(options: AFSFSOptions & {
|
|
62
|
+
cwd?: string;
|
|
63
|
+
});
|
|
64
|
+
name: string;
|
|
65
|
+
description?: string;
|
|
66
|
+
accessMode: AFSAccessMode;
|
|
67
|
+
agentSkills?: boolean;
|
|
68
|
+
private get localPathExists();
|
|
69
|
+
/**
|
|
70
|
+
* Detect MIME type based on file extension
|
|
71
|
+
*/
|
|
72
|
+
private getMimeType;
|
|
73
|
+
/**
|
|
74
|
+
* Check if file is likely binary based on extension
|
|
75
|
+
*/
|
|
76
|
+
private isBinaryFile;
|
|
77
|
+
symlinkToPhysical(path: string): Promise<void>;
|
|
78
|
+
list(path: string, options?: AFSListOptions): Promise<AFSListResult>;
|
|
79
|
+
read(path: string, _options?: AFSReadOptions): Promise<AFSReadResult>;
|
|
80
|
+
write(path: string, entry: AFSWriteEntryPayload, options?: AFSWriteOptions): Promise<AFSWriteResult>;
|
|
81
|
+
delete(path: string, options?: AFSDeleteOptions): Promise<AFSDeleteResult>;
|
|
82
|
+
rename(oldPath: string, newPath: string, options?: AFSRenameOptions): Promise<{
|
|
83
|
+
message?: string;
|
|
84
|
+
}>;
|
|
85
|
+
search(path: string, query: string, options?: AFSSearchOptions): Promise<AFSSearchResult>;
|
|
86
|
+
/**
|
|
87
|
+
* Load gitignore rules from mountRoot down to checkPath.
|
|
88
|
+
* Accumulates rules from parent to child for proper inheritance.
|
|
89
|
+
* Stops at .git boundaries (submodules are independent repos).
|
|
90
|
+
* @param checkPath - The directory whose files we're checking
|
|
91
|
+
* @param mountRoot - The mounted local filesystem root (stop point for walking up)
|
|
92
|
+
* @returns An object with ignore instance and the base path for matching
|
|
93
|
+
*/
|
|
94
|
+
private loadIgnoreRules;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
export { AFSFS, AFSFSOptions };
|
|
98
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;;;UA6BiB,YAAA;EAAA,IAAA;EAAA,SAAA;EAAA,WAAA;EAAA,MAAA;EAAA;AAmCjB;;;;;EAnCiB,UAAA,GAWF,aAAA;EAAA;AAwBf;;;;EAxBe,WAAA;AAAA;AAAA,cAwBF,KAAA,YAAiB,SAAA;EAAA,OAAA,EAWA,YAAA;IAAA,GAAA;EAAA;EAAA,OAAA,OAAA,GAVf,CAAA,CAAA,UAAA,CAAA,CAAA,CAAA,SAAA;IAAA,IAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAI2B,mBAAA,GAAmB,OAAA,CAAA,KAAA;EAAA,YAAA,OAAA,EAM/B,YAAA;IAAA,GAAA;EAAA;EAAA,IAAA;EAAA,WAAA;EAAA,UAAA,EA2BhB,aAAA;EAAA,WAAA;EAAA,YAAA,gBAAA;EAAA;;;EAAA,QAAA,WAAA;EAAA;;;EAAA,QAAA,YAAA;EAAA,kBAAA,IAAA,WAkE2B,OAAA;EAAA,KAAA,IAAA,UAAA,OAAA,GAMJ,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,KAAA,IAAA,UAAA,QAAA,GA8IxB,cAAA,GAAiB,OAAA,CAAQ,aAAA;EAAA,MAAA,IAAA,UAAA,KAAA,EAkDpD,oBAAA,EAAA,OAAA,GACG,eAAA,GACT,OAAA,CAAQ,cAAA;EAAA,OAAA,IAAA,UAAA,OAAA,GA6C0B,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA,OAAA,OAAA,UAAA,OAAA,UAAA,OAAA,GAoBpD,gBAAA,GACT,OAAA;IAAA,OAAA;EAAA;EAAA,OAAA,IAAA,UAAA,KAAA,UAAA,OAAA,GAiCiD,gBAAA,GAAmB,OAAA,CAAQ,eAAA;EAAA;;;;;;;;EAAA,QAAA,eAAA;AAAA"}
|