@burdenoff/vibe-agent 2.1.1 → 2.2.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/dist/app-6mmbmske.js +1166 -0
- package/dist/app-6mmbmske.js.map +19 -0
- package/dist/cli.js +152 -2036
- package/dist/cli.js.map +6 -28
- package/dist/index-05qfwz8r.js +122 -0
- package/dist/index-05qfwz8r.js.map +10 -0
- package/dist/index-30p492yv.js +294 -0
- package/dist/index-30p492yv.js.map +13 -0
- package/dist/index-3v78e2cn.js +373 -0
- package/dist/index-3v78e2cn.js.map +11 -0
- package/dist/index-41m1exz7.js +269 -0
- package/dist/index-41m1exz7.js.map +13 -0
- package/dist/index-88ym10cs.js +194 -0
- package/dist/index-88ym10cs.js.map +10 -0
- package/dist/index-9tgyd3ep.js +513 -0
- package/dist/index-9tgyd3ep.js.map +19 -0
- package/dist/index-a9g7hbj9.js +229 -0
- package/dist/index-a9g7hbj9.js.map +13 -0
- package/dist/index-atjhkm74.js +149 -0
- package/dist/index-atjhkm74.js.map +10 -0
- package/dist/index-c7zy3n33.js +167 -0
- package/dist/index-c7zy3n33.js.map +13 -0
- package/dist/index-hefqxwht.js +270 -0
- package/dist/index-hefqxwht.js.map +13 -0
- package/dist/index-k9hb0b93.js +280 -0
- package/dist/index-k9hb0b93.js.map +13 -0
- package/dist/index-npmvh1x9.js +385 -0
- package/dist/index-npmvh1x9.js.map +13 -0
- package/dist/index-q4ytrfx7.js +286 -0
- package/dist/index-q4ytrfx7.js.map +13 -0
- package/dist/index-qthbtg9n.js +302 -0
- package/dist/index-qthbtg9n.js.map +13 -0
- package/dist/index-rdm6e3rr.js +587 -0
- package/dist/index-rdm6e3rr.js.map +13 -0
- package/dist/index-wdtxbebz.js +339 -0
- package/dist/index-wdtxbebz.js.map +13 -0
- package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3201
- package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
- package/dist/index-xmeskdnb.js +292 -0
- package/dist/index-xmeskdnb.js.map +11 -0
- package/dist/index-xn4tarcd.js +287 -0
- package/dist/index-xn4tarcd.js.map +13 -0
- package/dist/index.js +9 -6
- package/dist/index.js.map +2 -2
- package/dist/{package-hb6db316.js → package-ywexp6sg.js} +3 -3
- package/dist/{package-hb6db316.js.map → package-ywexp6sg.js.map} +1 -1
- package/dist/plugin-system-v7a7xnhk.js +475 -0
- package/dist/plugin-system-v7a7xnhk.js.map +10 -0
- package/package.json +1 -1
- package/dist/index-t06ktmx9.js +0 -216
- package/dist/index-t06ktmx9.js.map +0 -11
- package/dist/plugin-system-bg1pzjj9.js +0 -450
- package/dist/plugin-system-bg1pzjj9.js.map +0 -11
|
@@ -0,0 +1,385 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
Elysia,
|
|
4
|
+
t
|
|
5
|
+
} from "./index-wr0mkm57.js";
|
|
6
|
+
import {
|
|
7
|
+
apiPost,
|
|
8
|
+
fail,
|
|
9
|
+
formatBytes,
|
|
10
|
+
formatTable,
|
|
11
|
+
getAgentUrl,
|
|
12
|
+
header,
|
|
13
|
+
info,
|
|
14
|
+
success
|
|
15
|
+
} from "./index-xmeskdnb.js";
|
|
16
|
+
import"./index-g8dczzvv.js";
|
|
17
|
+
|
|
18
|
+
// src/plugins/file/routes.ts
|
|
19
|
+
import { promises as fs } from "fs";
|
|
20
|
+
import nodePath from "path";
|
|
21
|
+
var SENSITIVE_PATTERNS = [
|
|
22
|
+
/\.env$/,
|
|
23
|
+
/\.pem$/,
|
|
24
|
+
/\.key$/,
|
|
25
|
+
/id_rsa/,
|
|
26
|
+
/\.ssh\//,
|
|
27
|
+
/\.git\/config$/,
|
|
28
|
+
/\.npmrc$/
|
|
29
|
+
];
|
|
30
|
+
var PROTECTED_PATHS = ["/", "/etc", "/usr", "/bin", "/sbin", "/var", "/opt"];
|
|
31
|
+
function validatePath(filePath) {
|
|
32
|
+
const normalized = nodePath.normalize(filePath);
|
|
33
|
+
if (normalized.includes("..")) {
|
|
34
|
+
return {
|
|
35
|
+
valid: false,
|
|
36
|
+
normalized,
|
|
37
|
+
error: "Directory traversal not allowed"
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
return { valid: true, normalized };
|
|
41
|
+
}
|
|
42
|
+
function isSensitiveFile(filePath) {
|
|
43
|
+
return SENSITIVE_PATTERNS.some((p) => p.test(filePath));
|
|
44
|
+
}
|
|
45
|
+
function isProtectedPath(filePath) {
|
|
46
|
+
return PROTECTED_PATHS.includes(filePath) || PROTECTED_PATHS.some((p) => filePath.startsWith(p + "/"));
|
|
47
|
+
}
|
|
48
|
+
function createRoutes(_deps) {
|
|
49
|
+
return new Elysia().post("/read", async ({ body, set }) => {
|
|
50
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
51
|
+
if (!valid) {
|
|
52
|
+
set.status = 403;
|
|
53
|
+
return { error };
|
|
54
|
+
}
|
|
55
|
+
if (isSensitiveFile(normalized)) {
|
|
56
|
+
set.status = 403;
|
|
57
|
+
return { error: "Access to sensitive files not allowed" };
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const content = await fs.readFile(normalized, "utf-8");
|
|
61
|
+
return { content, path: normalized, size: content.length };
|
|
62
|
+
} catch (err) {
|
|
63
|
+
const nodeErr = err;
|
|
64
|
+
if (nodeErr.code === "ENOENT") {
|
|
65
|
+
set.status = 404;
|
|
66
|
+
return { error: "File not found" };
|
|
67
|
+
}
|
|
68
|
+
if (nodeErr.code === "EACCES") {
|
|
69
|
+
set.status = 403;
|
|
70
|
+
return { error: "Permission denied" };
|
|
71
|
+
}
|
|
72
|
+
set.status = 500;
|
|
73
|
+
return { error: "Failed to read file", details: String(err) };
|
|
74
|
+
}
|
|
75
|
+
}, {
|
|
76
|
+
body: t.Object({
|
|
77
|
+
path: t.String(),
|
|
78
|
+
projectId: t.Optional(t.String())
|
|
79
|
+
})
|
|
80
|
+
}).post("/write", async ({ body, set }) => {
|
|
81
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
82
|
+
if (!valid) {
|
|
83
|
+
set.status = 403;
|
|
84
|
+
return { error };
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
const dir = nodePath.dirname(normalized);
|
|
88
|
+
await fs.mkdir(dir, { recursive: true });
|
|
89
|
+
await fs.writeFile(normalized, body.content, "utf-8");
|
|
90
|
+
const stats = await fs.stat(normalized);
|
|
91
|
+
return { success: true, path: normalized, size: stats.size };
|
|
92
|
+
} catch (err) {
|
|
93
|
+
const nodeErr = err;
|
|
94
|
+
if (nodeErr.code === "EACCES") {
|
|
95
|
+
set.status = 403;
|
|
96
|
+
return { error: "Permission denied" };
|
|
97
|
+
}
|
|
98
|
+
set.status = 500;
|
|
99
|
+
return { error: "Failed to write file", details: String(err) };
|
|
100
|
+
}
|
|
101
|
+
}, {
|
|
102
|
+
body: t.Object({
|
|
103
|
+
path: t.String(),
|
|
104
|
+
content: t.String(),
|
|
105
|
+
projectId: t.Optional(t.String())
|
|
106
|
+
})
|
|
107
|
+
}).post("/list", async ({ body, set }) => {
|
|
108
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
109
|
+
if (!valid) {
|
|
110
|
+
set.status = 403;
|
|
111
|
+
return { error };
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const entries = await fs.readdir(normalized, {
|
|
115
|
+
withFileTypes: true
|
|
116
|
+
});
|
|
117
|
+
const files = await Promise.all(entries.map(async (entry) => {
|
|
118
|
+
const fullPath = nodePath.join(normalized, entry.name);
|
|
119
|
+
let stats;
|
|
120
|
+
try {
|
|
121
|
+
stats = await fs.stat(fullPath);
|
|
122
|
+
} catch {
|
|
123
|
+
stats = null;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
name: entry.name,
|
|
127
|
+
path: fullPath,
|
|
128
|
+
type: entry.isDirectory() ? "directory" : entry.isFile() ? "file" : entry.isSymbolicLink() ? "symlink" : "other",
|
|
129
|
+
size: stats?.size || 0,
|
|
130
|
+
modified: stats?.mtime || null,
|
|
131
|
+
permissions: stats?.mode || null
|
|
132
|
+
};
|
|
133
|
+
}));
|
|
134
|
+
files.sort((a, b) => {
|
|
135
|
+
if (a.type === "directory" && b.type !== "directory")
|
|
136
|
+
return -1;
|
|
137
|
+
if (a.type !== "directory" && b.type === "directory")
|
|
138
|
+
return 1;
|
|
139
|
+
return a.name.localeCompare(b.name);
|
|
140
|
+
});
|
|
141
|
+
return { path: normalized, files, count: files.length };
|
|
142
|
+
} catch (err) {
|
|
143
|
+
const nodeErr = err;
|
|
144
|
+
if (nodeErr.code === "ENOENT") {
|
|
145
|
+
set.status = 404;
|
|
146
|
+
return { error: "Directory not found" };
|
|
147
|
+
}
|
|
148
|
+
if (nodeErr.code === "ENOTDIR") {
|
|
149
|
+
set.status = 400;
|
|
150
|
+
return { error: "Path is not a directory" };
|
|
151
|
+
}
|
|
152
|
+
if (nodeErr.code === "EACCES") {
|
|
153
|
+
set.status = 403;
|
|
154
|
+
return { error: "Permission denied" };
|
|
155
|
+
}
|
|
156
|
+
set.status = 500;
|
|
157
|
+
return { error: "Failed to list directory", details: String(err) };
|
|
158
|
+
}
|
|
159
|
+
}, {
|
|
160
|
+
body: t.Object({
|
|
161
|
+
path: t.String(),
|
|
162
|
+
projectId: t.Optional(t.String())
|
|
163
|
+
})
|
|
164
|
+
}).post("/exists", async ({ body, set }) => {
|
|
165
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
166
|
+
if (!valid) {
|
|
167
|
+
set.status = 403;
|
|
168
|
+
return { error };
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const stats = await fs.stat(normalized);
|
|
172
|
+
return {
|
|
173
|
+
exists: true,
|
|
174
|
+
path: normalized,
|
|
175
|
+
type: stats.isDirectory() ? "directory" : stats.isFile() ? "file" : "other",
|
|
176
|
+
size: stats.size,
|
|
177
|
+
modified: stats.mtime
|
|
178
|
+
};
|
|
179
|
+
} catch (err) {
|
|
180
|
+
const nodeErr = err;
|
|
181
|
+
if (nodeErr.code === "ENOENT") {
|
|
182
|
+
return { exists: false, path: normalized };
|
|
183
|
+
}
|
|
184
|
+
set.status = 500;
|
|
185
|
+
return { error: "Failed to check path", details: String(err) };
|
|
186
|
+
}
|
|
187
|
+
}, {
|
|
188
|
+
body: t.Object({
|
|
189
|
+
path: t.String()
|
|
190
|
+
})
|
|
191
|
+
}).post("/delete", async ({ body, set }) => {
|
|
192
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
193
|
+
if (!valid) {
|
|
194
|
+
set.status = 403;
|
|
195
|
+
return { error };
|
|
196
|
+
}
|
|
197
|
+
if (isProtectedPath(normalized)) {
|
|
198
|
+
set.status = 403;
|
|
199
|
+
return { error: "Cannot delete system directories" };
|
|
200
|
+
}
|
|
201
|
+
try {
|
|
202
|
+
const stats = await fs.stat(normalized);
|
|
203
|
+
if (stats.isDirectory()) {
|
|
204
|
+
await fs.rm(normalized, { recursive: true, force: true });
|
|
205
|
+
} else {
|
|
206
|
+
await fs.unlink(normalized);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
success: true,
|
|
210
|
+
path: normalized
|
|
211
|
+
};
|
|
212
|
+
} catch (err) {
|
|
213
|
+
const nodeErr = err;
|
|
214
|
+
if (nodeErr.code === "ENOENT") {
|
|
215
|
+
set.status = 404;
|
|
216
|
+
return { error: "Path not found" };
|
|
217
|
+
}
|
|
218
|
+
if (nodeErr.code === "EACCES") {
|
|
219
|
+
set.status = 403;
|
|
220
|
+
return { error: "Permission denied" };
|
|
221
|
+
}
|
|
222
|
+
set.status = 500;
|
|
223
|
+
return { error: "Failed to delete path", details: String(err) };
|
|
224
|
+
}
|
|
225
|
+
}, {
|
|
226
|
+
body: t.Object({
|
|
227
|
+
path: t.String()
|
|
228
|
+
})
|
|
229
|
+
}).post("/readme", async ({ body, set }) => {
|
|
230
|
+
const { valid, normalized, error } = validatePath(body.path);
|
|
231
|
+
if (!valid) {
|
|
232
|
+
set.status = 403;
|
|
233
|
+
return { error };
|
|
234
|
+
}
|
|
235
|
+
const readmeVariants = [
|
|
236
|
+
"README.md",
|
|
237
|
+
"readme.md",
|
|
238
|
+
"README.MD",
|
|
239
|
+
"README",
|
|
240
|
+
"readme",
|
|
241
|
+
"README.txt",
|
|
242
|
+
"readme.txt",
|
|
243
|
+
"README.rst",
|
|
244
|
+
"readme.rst"
|
|
245
|
+
];
|
|
246
|
+
for (const variant of readmeVariants) {
|
|
247
|
+
try {
|
|
248
|
+
const readmePath = nodePath.join(normalized, variant);
|
|
249
|
+
const content = await fs.readFile(readmePath, "utf-8");
|
|
250
|
+
return {
|
|
251
|
+
content,
|
|
252
|
+
path: readmePath,
|
|
253
|
+
variant,
|
|
254
|
+
size: content.length
|
|
255
|
+
};
|
|
256
|
+
} catch {}
|
|
257
|
+
}
|
|
258
|
+
set.status = 404;
|
|
259
|
+
return { error: "No README file found" };
|
|
260
|
+
}, {
|
|
261
|
+
body: t.Object({
|
|
262
|
+
path: t.String()
|
|
263
|
+
})
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/cli/commands/file.cmd.ts
|
|
268
|
+
var DEFAULT_AGENT_URL = "http://localhost:3005";
|
|
269
|
+
function register(program) {
|
|
270
|
+
const cmd = program.command("file").description("File system operations via agent");
|
|
271
|
+
cmd.command("read").description("Read a file").requiredOption("--path <path>", "File path to read").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
272
|
+
try {
|
|
273
|
+
const url = getAgentUrl(options);
|
|
274
|
+
const result = await apiPost(url, "/api/files/read", {
|
|
275
|
+
path: options.path
|
|
276
|
+
});
|
|
277
|
+
if (result?.content !== undefined) {
|
|
278
|
+
console.log(result.content);
|
|
279
|
+
} else {
|
|
280
|
+
info("File is empty or has no content.");
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
fail(err.message);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
cmd.command("write").description("Write content to a file").requiredOption("--path <path>", "File path to write").requiredOption("--content <content>", "Content to write").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
287
|
+
try {
|
|
288
|
+
const url = getAgentUrl(options);
|
|
289
|
+
await apiPost(url, "/api/files/write", {
|
|
290
|
+
path: options.path,
|
|
291
|
+
content: options.content
|
|
292
|
+
});
|
|
293
|
+
success(`File written: ${options.path}`);
|
|
294
|
+
} catch (err) {
|
|
295
|
+
fail(err.message);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
cmd.command("list").description("List files in a directory").requiredOption("--path <path>", "Directory path").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
299
|
+
try {
|
|
300
|
+
const url = getAgentUrl(options);
|
|
301
|
+
const result = await apiPost(url, "/api/files/list", {
|
|
302
|
+
path: options.path
|
|
303
|
+
});
|
|
304
|
+
const files = result?.files || result;
|
|
305
|
+
if (!files || Array.isArray(files) && files.length === 0) {
|
|
306
|
+
info("Directory is empty.");
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
header(`Files in ${options.path}`);
|
|
310
|
+
formatTable((Array.isArray(files) ? files : []).map((f) => ({
|
|
311
|
+
Name: f.name || f.filename || "-",
|
|
312
|
+
Type: f.type || (f.isDirectory ? "directory" : "file"),
|
|
313
|
+
Size: f.size !== undefined ? formatBytes(f.size) : "-"
|
|
314
|
+
})));
|
|
315
|
+
} catch (err) {
|
|
316
|
+
fail(err.message);
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
cmd.command("exists").description("Check if a file exists").requiredOption("--path <path>", "File path to check").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
320
|
+
try {
|
|
321
|
+
const url = getAgentUrl(options);
|
|
322
|
+
const result = await apiPost(url, "/api/files/exists", {
|
|
323
|
+
path: options.path
|
|
324
|
+
});
|
|
325
|
+
if (result?.exists) {
|
|
326
|
+
success(`File exists: ${options.path}`);
|
|
327
|
+
} else {
|
|
328
|
+
info(`File does not exist: ${options.path}`);
|
|
329
|
+
}
|
|
330
|
+
} catch (err) {
|
|
331
|
+
fail(err.message);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
cmd.command("delete").description("Delete a file").requiredOption("--path <path>", "File path to delete").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
335
|
+
try {
|
|
336
|
+
const url = getAgentUrl(options);
|
|
337
|
+
await apiPost(url, "/api/files/delete", {
|
|
338
|
+
path: options.path
|
|
339
|
+
});
|
|
340
|
+
success(`File deleted: ${options.path}`);
|
|
341
|
+
} catch (err) {
|
|
342
|
+
fail(err.message);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
cmd.command("readme").description("Read the README file from a directory").requiredOption("--path <path>", "Directory path").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
|
|
346
|
+
try {
|
|
347
|
+
const url = getAgentUrl(options);
|
|
348
|
+
const result = await apiPost(url, "/api/files/readme", {
|
|
349
|
+
path: options.path
|
|
350
|
+
});
|
|
351
|
+
if (result?.content) {
|
|
352
|
+
console.log(result.content);
|
|
353
|
+
} else {
|
|
354
|
+
info("No README found in the specified directory.");
|
|
355
|
+
}
|
|
356
|
+
} catch (err) {
|
|
357
|
+
fail(err.message);
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/plugins/file/commands.ts
|
|
363
|
+
function registerCommands(program, _hostServices) {
|
|
364
|
+
register(program);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// src/plugins/file/index.ts
|
|
368
|
+
var vibePlugin = {
|
|
369
|
+
name: "file",
|
|
370
|
+
version: "2.2.0",
|
|
371
|
+
description: "File system operations with security checks",
|
|
372
|
+
tags: ["backend", "cli"],
|
|
373
|
+
cliCommand: "file",
|
|
374
|
+
apiPrefix: "/api/files",
|
|
375
|
+
createRoutes: (deps) => createRoutes(deps),
|
|
376
|
+
onCliSetup: async (program, hostServices) => {
|
|
377
|
+
registerCommands(program, hostServices);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
export {
|
|
381
|
+
vibePlugin
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
//# debugId=EBEB983AE70EABB664756E2164756E21
|
|
385
|
+
//# sourceMappingURL=index-npmvh1x9.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/plugins/file/routes.ts", "../src/cli/commands/file.cmd.ts", "../src/plugins/file/commands.ts", "../src/plugins/file/index.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * File Plugin — Routes\n *\n * File system operations with security checks (path traversal, sensitive file blocking).\n *\n * Endpoints:\n * POST /read — Read file content\n * POST /write — Write file content\n * POST /list — List directory contents\n * POST /exists — Check if path exists\n * POST /delete — Delete file or directory\n * POST /readme — Read README file from a project\n */\n\nimport { Elysia, t } from \"elysia\";\nimport { promises as fs } from \"node:fs\";\nimport nodePath from \"node:path\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\n\n// ── Security Helpers ────────────────────────────────────────────────────\n\nconst SENSITIVE_PATTERNS = [\n /\\.env$/,\n /\\.pem$/,\n /\\.key$/,\n /id_rsa/,\n /\\.ssh\\//,\n /\\.git\\/config$/,\n /\\.npmrc$/,\n];\n\nconst PROTECTED_PATHS = [\"/\", \"/etc\", \"/usr\", \"/bin\", \"/sbin\", \"/var\", \"/opt\"];\n\nfunction validatePath(filePath: string): {\n valid: boolean;\n normalized: string;\n error?: string;\n} {\n const normalized = nodePath.normalize(filePath);\n\n if (normalized.includes(\"..\")) {\n return {\n valid: false,\n normalized,\n error: \"Directory traversal not allowed\",\n };\n }\n\n return { valid: true, normalized };\n}\n\nfunction isSensitiveFile(filePath: string): boolean {\n return SENSITIVE_PATTERNS.some((p) => p.test(filePath));\n}\n\nfunction isProtectedPath(filePath: string): boolean {\n return (\n PROTECTED_PATHS.includes(filePath) ||\n PROTECTED_PATHS.some((p) => filePath.startsWith(p + \"/\"))\n );\n}\n\n// ── Routes ──────────────────────────────────────────────────────────────\n\nexport function createRoutes(_deps: PluginRouteDeps) {\n return (\n new Elysia()\n // Read file\n .post(\n \"/read\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n if (isSensitiveFile(normalized)) {\n set.status = 403;\n return { error: \"Access to sensitive files not allowed\" };\n }\n\n try {\n const content = await fs.readFile(normalized, \"utf-8\");\n return { content, path: normalized, size: content.length };\n } catch (err) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === \"ENOENT\") {\n set.status = 404;\n return { error: \"File not found\" };\n }\n if (nodeErr.code === \"EACCES\") {\n set.status = 403;\n return { error: \"Permission denied\" };\n }\n set.status = 500;\n return { error: \"Failed to read file\", details: String(err) };\n }\n },\n {\n body: t.Object({\n path: t.String(),\n projectId: t.Optional(t.String()),\n }),\n },\n )\n\n // Write file\n .post(\n \"/write\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n try {\n const dir = nodePath.dirname(normalized);\n await fs.mkdir(dir, { recursive: true });\n await fs.writeFile(normalized, body.content, \"utf-8\");\n const stats = await fs.stat(normalized);\n return { success: true, path: normalized, size: stats.size };\n } catch (err) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === \"EACCES\") {\n set.status = 403;\n return { error: \"Permission denied\" };\n }\n set.status = 500;\n return { error: \"Failed to write file\", details: String(err) };\n }\n },\n {\n body: t.Object({\n path: t.String(),\n content: t.String(),\n projectId: t.Optional(t.String()),\n }),\n },\n )\n\n // List directory\n .post(\n \"/list\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n try {\n const entries = await fs.readdir(normalized, {\n withFileTypes: true,\n });\n\n const files = await Promise.all(\n entries.map(async (entry) => {\n const fullPath = nodePath.join(normalized, entry.name);\n let stats;\n try {\n stats = await fs.stat(fullPath);\n } catch {\n stats = null;\n }\n\n return {\n name: entry.name,\n path: fullPath,\n type: entry.isDirectory()\n ? \"directory\"\n : entry.isFile()\n ? \"file\"\n : entry.isSymbolicLink()\n ? \"symlink\"\n : \"other\",\n size: stats?.size || 0,\n modified: stats?.mtime || null,\n permissions: stats?.mode || null,\n };\n }),\n );\n\n // Sort: directories first, then files alphabetically\n files.sort((a, b) => {\n if (a.type === \"directory\" && b.type !== \"directory\") return -1;\n if (a.type !== \"directory\" && b.type === \"directory\") return 1;\n return a.name.localeCompare(b.name);\n });\n\n return { path: normalized, files, count: files.length };\n } catch (err) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === \"ENOENT\") {\n set.status = 404;\n return { error: \"Directory not found\" };\n }\n if (nodeErr.code === \"ENOTDIR\") {\n set.status = 400;\n return { error: \"Path is not a directory\" };\n }\n if (nodeErr.code === \"EACCES\") {\n set.status = 403;\n return { error: \"Permission denied\" };\n }\n set.status = 500;\n return { error: \"Failed to list directory\", details: String(err) };\n }\n },\n {\n body: t.Object({\n path: t.String(),\n projectId: t.Optional(t.String()),\n }),\n },\n )\n\n // Check if path exists\n .post(\n \"/exists\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n try {\n const stats = await fs.stat(normalized);\n return {\n exists: true,\n path: normalized,\n type: stats.isDirectory()\n ? \"directory\"\n : stats.isFile()\n ? \"file\"\n : \"other\",\n size: stats.size,\n modified: stats.mtime,\n };\n } catch (err) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === \"ENOENT\") {\n return { exists: false, path: normalized };\n }\n set.status = 500;\n return { error: \"Failed to check path\", details: String(err) };\n }\n },\n {\n body: t.Object({\n path: t.String(),\n }),\n },\n )\n\n // Delete file or directory\n .post(\n \"/delete\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n if (isProtectedPath(normalized)) {\n set.status = 403;\n return { error: \"Cannot delete system directories\" };\n }\n\n try {\n const stats = await fs.stat(normalized);\n if (stats.isDirectory()) {\n await fs.rm(normalized, { recursive: true, force: true });\n } else {\n await fs.unlink(normalized);\n }\n return {\n success: true,\n path: normalized,\n };\n } catch (err) {\n const nodeErr = err as NodeJS.ErrnoException;\n if (nodeErr.code === \"ENOENT\") {\n set.status = 404;\n return { error: \"Path not found\" };\n }\n if (nodeErr.code === \"EACCES\") {\n set.status = 403;\n return { error: \"Permission denied\" };\n }\n set.status = 500;\n return { error: \"Failed to delete path\", details: String(err) };\n }\n },\n {\n body: t.Object({\n path: t.String(),\n }),\n },\n )\n\n // Read README file\n .post(\n \"/readme\",\n async ({ body, set }) => {\n const { valid, normalized, error } = validatePath(body.path);\n if (!valid) {\n set.status = 403;\n return { error };\n }\n\n const readmeVariants = [\n \"README.md\",\n \"readme.md\",\n \"README.MD\",\n \"README\",\n \"readme\",\n \"README.txt\",\n \"readme.txt\",\n \"README.rst\",\n \"readme.rst\",\n ];\n\n for (const variant of readmeVariants) {\n try {\n const readmePath = nodePath.join(normalized, variant);\n const content = await fs.readFile(readmePath, \"utf-8\");\n return {\n content,\n path: readmePath,\n variant,\n size: content.length,\n };\n } catch {\n /* next variant */\n }\n }\n\n set.status = 404;\n return { error: \"No README file found\" };\n },\n {\n body: t.Object({\n path: t.String(),\n }),\n },\n )\n );\n}\n",
|
|
6
|
+
"import { Command } from \"commander\";\nimport {\n getAgentUrl,\n apiPost,\n fail,\n success,\n info,\n header,\n kv,\n blank,\n formatTable,\n formatBytes,\n} from \"../utils/index.js\";\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\nexport function register(program: Command): void {\n const cmd = program\n .command(\"file\")\n .description(\"File system operations via agent\");\n\n // file read\n cmd\n .command(\"read\")\n .description(\"Read a file\")\n .requiredOption(\"--path <path>\", \"File path to read\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const result = await apiPost<any>(url, \"/api/files/read\", {\n path: options.path,\n });\n if (result?.content !== undefined) {\n console.log(result.content);\n } else {\n info(\"File is empty or has no content.\");\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // file write\n cmd\n .command(\"write\")\n .description(\"Write content to a file\")\n .requiredOption(\"--path <path>\", \"File path to write\")\n .requiredOption(\"--content <content>\", \"Content to write\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiPost<any>(url, \"/api/files/write\", {\n path: options.path,\n content: options.content,\n });\n success(`File written: ${options.path}`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // file list\n cmd\n .command(\"list\")\n .description(\"List files in a directory\")\n .requiredOption(\"--path <path>\", \"Directory path\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const result = await apiPost<any>(url, \"/api/files/list\", {\n path: options.path,\n });\n const files = result?.files || result;\n if (!files || (Array.isArray(files) && files.length === 0)) {\n info(\"Directory is empty.\");\n return;\n }\n header(`Files in ${options.path}`);\n formatTable(\n (Array.isArray(files) ? files : []).map((f: any) => ({\n Name: f.name || f.filename || \"-\",\n Type: f.type || (f.isDirectory ? \"directory\" : \"file\"),\n Size: f.size !== undefined ? formatBytes(f.size) : \"-\",\n })),\n );\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // file exists\n cmd\n .command(\"exists\")\n .description(\"Check if a file exists\")\n .requiredOption(\"--path <path>\", \"File path to check\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const result = await apiPost<any>(url, \"/api/files/exists\", {\n path: options.path,\n });\n if (result?.exists) {\n success(`File exists: ${options.path}`);\n } else {\n info(`File does not exist: ${options.path}`);\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // file delete\n cmd\n .command(\"delete\")\n .description(\"Delete a file\")\n .requiredOption(\"--path <path>\", \"File path to delete\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiPost<any>(url, \"/api/files/delete\", {\n path: options.path,\n });\n success(`File deleted: ${options.path}`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // file readme\n cmd\n .command(\"readme\")\n .description(\"Read the README file from a directory\")\n .requiredOption(\"--path <path>\", \"Directory path\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const result = await apiPost<any>(url, \"/api/files/readme\", {\n path: options.path,\n });\n if (result?.content) {\n console.log(result.content);\n } else {\n info(\"No README found in the specified directory.\");\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n}\n",
|
|
7
|
+
"import type { Command } from \"commander\";\nimport type { HostServices } from \"../../core/plugin-system.js\";\nimport { register as registerFile } from \"../../cli/commands/file.cmd.js\";\n\nexport function registerCommands(\n program: Command,\n _hostServices: HostServices,\n): void {\n registerFile(program);\n}\n",
|
|
8
|
+
"import type { VibePlugin } from \"../../core/plugin-system.js\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\nimport { createRoutes } from \"./routes.js\";\nimport { registerCommands } from \"./commands.js\";\n\nexport const vibePlugin: VibePlugin = {\n name: \"file\",\n version: \"2.2.0\",\n description: \"File system operations with security checks\",\n tags: [\"backend\", \"cli\"],\n cliCommand: \"file\",\n apiPrefix: \"/api/files\",\n createRoutes: (deps: PluginRouteDeps) => createRoutes(deps),\n onCliSetup: async (program, hostServices) => {\n registerCommands(program, hostServices);\n },\n};\n"
|
|
9
|
+
],
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "EBEB983AE70EABB664756E2164756E21",
|
|
12
|
+
"names": []
|
|
13
|
+
}
|