@aigne/afs-cli 1.11.0-beta.5 → 1.11.0-beta.7
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/cli.cjs +25 -328
- package/dist/cli.d.cts +2 -1
- package/dist/cli.d.mts +2 -1
- package/dist/cli.mjs +26 -328
- package/dist/cli.mjs.map +1 -1
- package/dist/config/afs-loader.cjs +123 -0
- package/dist/config/afs-loader.d.cts +14 -0
- package/dist/config/afs-loader.d.cts.map +1 -0
- package/dist/config/afs-loader.d.mts +14 -0
- package/dist/config/afs-loader.d.mts.map +1 -0
- package/dist/config/afs-loader.mjs +122 -0
- package/dist/config/afs-loader.mjs.map +1 -0
- package/dist/config/loader.cjs +14 -3
- package/dist/config/loader.mjs +14 -3
- package/dist/config/loader.mjs.map +1 -1
- package/dist/{commands/mount.cjs → config/mount-commands.cjs} +13 -49
- package/dist/config/mount-commands.d.cts +20 -0
- package/dist/config/mount-commands.d.cts.map +1 -0
- package/dist/config/mount-commands.d.mts +20 -0
- package/dist/config/mount-commands.d.mts.map +1 -0
- package/dist/{commands/mount.mjs → config/mount-commands.mjs} +14 -49
- package/dist/config/mount-commands.mjs.map +1 -0
- package/dist/config/schema.cjs +9 -1
- package/dist/config/schema.mjs +9 -1
- package/dist/config/schema.mjs.map +1 -1
- package/dist/core/commands/delete.cjs +41 -0
- package/dist/core/commands/delete.d.cts +18 -0
- package/dist/core/commands/delete.d.cts.map +1 -0
- package/dist/core/commands/delete.d.mts +18 -0
- package/dist/core/commands/delete.d.mts.map +1 -0
- package/dist/core/commands/delete.mjs +42 -0
- package/dist/core/commands/delete.mjs.map +1 -0
- package/dist/core/commands/exec.cjs +95 -0
- package/dist/core/commands/exec.d.cts +26 -0
- package/dist/core/commands/exec.d.cts.map +1 -0
- package/dist/core/commands/exec.d.mts +26 -0
- package/dist/core/commands/exec.d.mts.map +1 -0
- package/dist/core/commands/exec.mjs +96 -0
- package/dist/core/commands/exec.mjs.map +1 -0
- package/dist/core/commands/explain.cjs +254 -0
- package/dist/core/commands/explain.d.cts +25 -0
- package/dist/core/commands/explain.d.cts.map +1 -0
- package/dist/core/commands/explain.d.mts +25 -0
- package/dist/core/commands/explain.d.mts.map +1 -0
- package/dist/core/commands/explain.mjs +255 -0
- package/dist/core/commands/explain.mjs.map +1 -0
- package/dist/core/commands/explore.cjs +30 -0
- package/dist/core/commands/explore.d.mts +2 -0
- package/dist/core/commands/explore.mjs +31 -0
- package/dist/core/commands/explore.mjs.map +1 -0
- package/dist/core/commands/index.cjs +36 -0
- package/dist/core/commands/index.d.cts +21 -0
- package/dist/core/commands/index.d.cts.map +1 -0
- package/dist/core/commands/index.d.mts +24 -0
- package/dist/core/commands/index.d.mts.map +1 -0
- package/dist/core/commands/index.mjs +37 -0
- package/dist/core/commands/index.mjs.map +1 -0
- package/dist/core/commands/ls.cjs +57 -0
- package/dist/core/commands/ls.d.cts +21 -0
- package/dist/core/commands/ls.d.cts.map +1 -0
- package/dist/core/commands/ls.d.mts +21 -0
- package/dist/core/commands/ls.d.mts.map +1 -0
- package/dist/core/commands/ls.mjs +58 -0
- package/dist/core/commands/ls.mjs.map +1 -0
- package/dist/core/commands/mount.cjs +139 -0
- package/dist/core/commands/mount.d.cts +33 -0
- package/dist/core/commands/mount.d.cts.map +1 -0
- package/dist/core/commands/mount.d.mts +33 -0
- package/dist/core/commands/mount.d.mts.map +1 -0
- package/dist/core/commands/mount.mjs +140 -0
- package/dist/core/commands/mount.mjs.map +1 -0
- package/dist/core/commands/read.cjs +48 -0
- package/dist/core/commands/read.d.cts +17 -0
- package/dist/core/commands/read.d.cts.map +1 -0
- package/dist/core/commands/read.d.mts +17 -0
- package/dist/core/commands/read.d.mts.map +1 -0
- package/dist/core/commands/read.mjs +49 -0
- package/dist/core/commands/read.mjs.map +1 -0
- package/dist/core/commands/search.cjs +40 -0
- package/dist/core/commands/search.d.mts +2 -0
- package/dist/core/commands/search.mjs +41 -0
- package/dist/core/commands/search.mjs.map +1 -0
- package/dist/core/commands/serve.cjs +242 -0
- package/dist/core/commands/serve.d.mts +2 -0
- package/dist/core/commands/serve.mjs +242 -0
- package/dist/core/commands/serve.mjs.map +1 -0
- package/dist/core/commands/stat.cjs +53 -0
- package/dist/core/commands/stat.d.cts +17 -0
- package/dist/core/commands/stat.d.cts.map +1 -0
- package/dist/core/commands/stat.d.mts +17 -0
- package/dist/core/commands/stat.d.mts.map +1 -0
- package/dist/core/commands/stat.mjs +54 -0
- package/dist/core/commands/stat.mjs.map +1 -0
- package/dist/core/commands/types.cjs +13 -0
- package/dist/core/commands/types.d.cts +54 -0
- package/dist/core/commands/types.d.cts.map +1 -0
- package/dist/core/commands/types.d.mts +54 -0
- package/dist/core/commands/types.d.mts.map +1 -0
- package/dist/core/commands/types.mjs +14 -0
- package/dist/core/commands/types.mjs.map +1 -0
- package/dist/core/commands/write.cjs +70 -0
- package/dist/core/commands/write.d.cts +20 -0
- package/dist/core/commands/write.d.cts.map +1 -0
- package/dist/core/commands/write.d.mts +20 -0
- package/dist/core/commands/write.d.mts.map +1 -0
- package/dist/core/commands/write.mjs +71 -0
- package/dist/core/commands/write.mjs.map +1 -0
- package/dist/core/executor/index.cjs +196 -0
- package/dist/core/executor/index.d.cts +77 -0
- package/dist/core/executor/index.d.cts.map +1 -0
- package/dist/core/executor/index.d.mts +77 -0
- package/dist/core/executor/index.d.mts.map +1 -0
- package/dist/core/executor/index.mjs +195 -0
- package/dist/core/executor/index.mjs.map +1 -0
- package/dist/core/formatters/delete.cjs +37 -0
- package/dist/core/formatters/delete.d.cts +18 -0
- package/dist/core/formatters/delete.d.cts.map +1 -0
- package/dist/core/formatters/delete.d.mts +18 -0
- package/dist/core/formatters/delete.d.mts.map +1 -0
- package/dist/core/formatters/delete.mjs +37 -0
- package/dist/core/formatters/delete.mjs.map +1 -0
- package/dist/core/formatters/exec.cjs +60 -0
- package/dist/core/formatters/exec.d.cts +18 -0
- package/dist/core/formatters/exec.d.cts.map +1 -0
- package/dist/core/formatters/exec.d.mts +18 -0
- package/dist/core/formatters/exec.d.mts.map +1 -0
- package/dist/core/formatters/exec.mjs +60 -0
- package/dist/core/formatters/exec.mjs.map +1 -0
- package/dist/core/formatters/explain.cjs +97 -0
- package/dist/core/formatters/explain.d.cts +11 -0
- package/dist/core/formatters/explain.d.cts.map +1 -0
- package/dist/core/formatters/explain.d.mts +11 -0
- package/dist/core/formatters/explain.d.mts.map +1 -0
- package/dist/core/formatters/explain.mjs +96 -0
- package/dist/core/formatters/explain.mjs.map +1 -0
- package/dist/core/formatters/index.d.mts +9 -0
- package/dist/core/formatters/ls.cjs +179 -0
- package/dist/core/formatters/ls.d.cts +20 -0
- package/dist/core/formatters/ls.d.cts.map +1 -0
- package/dist/core/formatters/ls.d.mts +20 -0
- package/dist/core/formatters/ls.d.mts.map +1 -0
- package/dist/core/formatters/ls.mjs +179 -0
- package/dist/core/formatters/ls.mjs.map +1 -0
- package/dist/core/formatters/mount.cjs +55 -0
- package/dist/core/formatters/mount.d.cts +15 -0
- package/dist/core/formatters/mount.d.cts.map +1 -0
- package/dist/core/formatters/mount.d.mts +15 -0
- package/dist/core/formatters/mount.d.mts.map +1 -0
- package/dist/core/formatters/mount.mjs +55 -0
- package/dist/core/formatters/mount.mjs.map +1 -0
- package/dist/core/formatters/read.cjs +100 -0
- package/dist/core/formatters/read.d.cts +22 -0
- package/dist/core/formatters/read.d.cts.map +1 -0
- package/dist/core/formatters/read.d.mts +22 -0
- package/dist/core/formatters/read.d.mts.map +1 -0
- package/dist/core/formatters/read.mjs +100 -0
- package/dist/core/formatters/read.mjs.map +1 -0
- package/dist/core/formatters/search.cjs +44 -0
- package/dist/core/formatters/search.d.mts +1 -0
- package/dist/core/formatters/search.mjs +44 -0
- package/dist/core/formatters/search.mjs.map +1 -0
- package/dist/core/formatters/stat.cjs +155 -0
- package/dist/core/formatters/stat.d.cts +15 -0
- package/dist/core/formatters/stat.d.cts.map +1 -0
- package/dist/core/formatters/stat.d.mts +15 -0
- package/dist/core/formatters/stat.d.mts.map +1 -0
- package/dist/core/formatters/stat.mjs +155 -0
- package/dist/core/formatters/stat.mjs.map +1 -0
- package/dist/core/formatters/write.cjs +51 -0
- package/dist/core/formatters/write.d.cts +22 -0
- package/dist/core/formatters/write.d.cts.map +1 -0
- package/dist/core/formatters/write.d.mts +22 -0
- package/dist/core/formatters/write.d.mts.map +1 -0
- package/dist/core/formatters/write.mjs +51 -0
- package/dist/core/formatters/write.mjs.map +1 -0
- package/dist/core/helpers/exec-args.cjs +142 -0
- package/dist/core/helpers/exec-args.d.cts +46 -0
- package/dist/core/helpers/exec-args.d.cts.map +1 -0
- package/dist/core/helpers/exec-args.d.mts +46 -0
- package/dist/core/helpers/exec-args.d.mts.map +1 -0
- package/dist/core/helpers/exec-args.mjs +139 -0
- package/dist/core/helpers/exec-args.mjs.map +1 -0
- package/dist/core/helpers/stdin.cjs +41 -0
- package/dist/core/helpers/stdin.d.cts +15 -0
- package/dist/core/helpers/stdin.d.cts.map +1 -0
- package/dist/core/helpers/stdin.d.mts +15 -0
- package/dist/core/helpers/stdin.d.mts.map +1 -0
- package/dist/core/helpers/stdin.mjs +41 -0
- package/dist/core/helpers/stdin.mjs.map +1 -0
- package/dist/core/index.cjs +49 -0
- package/dist/core/index.d.cts +24 -0
- package/dist/core/index.d.mts +25 -0
- package/dist/core/index.mjs +24 -0
- package/dist/core/path-utils.cjs +1 -0
- package/dist/core/path-utils.mjs +3 -0
- package/dist/core/types.d.cts +24 -0
- package/dist/core/types.d.cts.map +1 -0
- package/dist/core/types.d.mts +24 -0
- package/dist/core/types.d.mts.map +1 -0
- package/dist/errors.cjs +0 -11
- package/dist/errors.mjs +1 -11
- package/dist/errors.mjs.map +1 -1
- package/dist/explorer/actions.cjs +113 -48
- package/dist/explorer/actions.mjs +113 -48
- package/dist/explorer/actions.mjs.map +1 -1
- package/dist/explorer/components/dialog.cjs +287 -10
- package/dist/explorer/components/dialog.mjs +287 -10
- package/dist/explorer/components/dialog.mjs.map +1 -1
- package/dist/explorer/components/file-list.mjs.map +1 -1
- package/dist/explorer/components/metadata-panel.cjs +121 -24
- package/dist/explorer/components/metadata-panel.mjs +121 -24
- package/dist/explorer/components/metadata-panel.mjs.map +1 -1
- package/dist/explorer/screen.cjs +72 -21
- package/dist/explorer/screen.d.cts +23 -0
- package/dist/explorer/screen.d.cts.map +1 -0
- package/dist/explorer/screen.d.mts +23 -0
- package/dist/explorer/screen.d.mts.map +1 -0
- package/dist/explorer/screen.mjs +73 -22
- package/dist/explorer/screen.mjs.map +1 -1
- package/dist/explorer/theme.cjs +4 -2
- package/dist/explorer/theme.mjs +4 -2
- package/dist/explorer/theme.mjs.map +1 -1
- package/dist/index.cjs +7 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.mts +4 -1
- package/dist/index.mjs +4 -1
- package/dist/mcp/http-transport.cjs +68 -0
- package/dist/mcp/http-transport.mjs +68 -0
- package/dist/mcp/http-transport.mjs.map +1 -0
- package/dist/mcp/prompts.cjs +48 -0
- package/dist/mcp/prompts.mjs +48 -0
- package/dist/mcp/prompts.mjs.map +1 -0
- package/dist/mcp/resources.cjs +25 -0
- package/dist/mcp/resources.mjs +25 -0
- package/dist/mcp/resources.mjs.map +1 -0
- package/dist/mcp/server.cjs +30 -0
- package/dist/mcp/server.mjs +30 -0
- package/dist/mcp/server.mjs.map +1 -0
- package/dist/mcp/tools.cjs +196 -0
- package/dist/mcp/tools.mjs +196 -0
- package/dist/mcp/tools.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts +10 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/index.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.cts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts +46 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/types.d.mts.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.cjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs +902 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/dist/urlpattern.mjs.map +1 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.cjs +6 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs +8 -0
- package/dist/node_modules/.pnpm/urlpattern-polyfill@10.1.0/node_modules/urlpattern-polyfill/index.mjs.map +1 -0
- package/dist/path-utils.cjs +2 -1
- package/dist/path-utils.d.cts +50 -0
- package/dist/path-utils.d.cts.map +1 -0
- package/dist/path-utils.d.mts +50 -0
- package/dist/path-utils.d.mts.map +1 -0
- package/dist/path-utils.mjs +1 -1
- package/dist/repl.cjs +485 -0
- package/dist/repl.d.cts +15 -0
- package/dist/repl.d.cts.map +1 -0
- package/dist/repl.d.mts +16 -0
- package/dist/repl.d.mts.map +1 -0
- package/dist/repl.mjs +485 -0
- package/dist/repl.mjs.map +1 -0
- package/dist/serve.cjs +146 -0
- package/dist/serve.d.cts +41 -0
- package/dist/serve.d.cts.map +1 -0
- package/dist/serve.d.mts +41 -0
- package/dist/serve.d.mts.map +1 -0
- package/dist/serve.mjs +146 -0
- package/dist/serve.mjs.map +1 -0
- package/dist/ui/header.cjs +1 -49
- package/dist/ui/header.mjs +1 -47
- package/dist/ui/header.mjs.map +1 -1
- package/dist/ui/index.cjs +2 -11
- package/dist/ui/index.mjs +2 -8
- package/dist/ui/index.mjs.map +1 -1
- package/dist/ui/terminal.cjs +1 -10
- package/dist/ui/terminal.mjs +1 -8
- package/dist/ui/terminal.mjs.map +1 -1
- package/package.json +32 -9
- package/dist/commands/exec.cjs +0 -46
- package/dist/commands/exec.mjs +0 -45
- package/dist/commands/exec.mjs.map +0 -1
- package/dist/commands/explain.cjs +0 -244
- package/dist/commands/explain.mjs +0 -242
- package/dist/commands/explain.mjs.map +0 -1
- package/dist/commands/index.cjs +0 -8
- package/dist/commands/index.mjs +0 -10
- package/dist/commands/ls.cjs +0 -143
- package/dist/commands/ls.mjs +0 -143
- package/dist/commands/ls.mjs.map +0 -1
- package/dist/commands/mount.mjs.map +0 -1
- package/dist/commands/read.cjs +0 -65
- package/dist/commands/read.mjs +0 -64
- package/dist/commands/read.mjs.map +0 -1
- package/dist/commands/serve.cjs +0 -144
- package/dist/commands/serve.mjs +0 -143
- package/dist/commands/serve.mjs.map +0 -1
- package/dist/commands/stat.cjs +0 -113
- package/dist/commands/stat.mjs +0 -112
- package/dist/commands/stat.mjs.map +0 -1
- package/dist/commands/write.cjs +0 -52
- package/dist/commands/write.mjs +0 -51
- package/dist/commands/write.mjs.map +0 -1
- package/dist/config/provider-factory.cjs +0 -93
- package/dist/config/provider-factory.mjs +0 -94
- package/dist/config/provider-factory.mjs.map +0 -1
- package/dist/config/uri-parser.cjs +0 -92
- package/dist/config/uri-parser.mjs +0 -92
- package/dist/config/uri-parser.mjs.map +0 -1
- package/dist/runtime.cjs +0 -96
- package/dist/runtime.mjs +0 -96
- package/dist/runtime.mjs.map +0 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_index = require('../../ui/index.cjs');
|
|
3
|
+
const require_loader = require('../../config/loader.cjs');
|
|
4
|
+
const require_types = require('./types.cjs');
|
|
5
|
+
let node_http = require("node:http");
|
|
6
|
+
let _aigne_afs_http = require("@aigne/afs-http");
|
|
7
|
+
|
|
8
|
+
//#region src/core/commands/serve.ts
|
|
9
|
+
/**
|
|
10
|
+
* Create an AFSModule wrapper around AFS
|
|
11
|
+
*/
|
|
12
|
+
function createAFSModule(afs, readonly) {
|
|
13
|
+
return {
|
|
14
|
+
name: "afs-server",
|
|
15
|
+
accessMode: readonly ? "readonly" : "readwrite",
|
|
16
|
+
async list(path, options) {
|
|
17
|
+
return afs.list(path, options);
|
|
18
|
+
},
|
|
19
|
+
async read(path, options) {
|
|
20
|
+
return afs.read(path, options);
|
|
21
|
+
},
|
|
22
|
+
async write(path, content, options) {
|
|
23
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
24
|
+
return afs.write(path, content, options);
|
|
25
|
+
},
|
|
26
|
+
async delete(path, options) {
|
|
27
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
28
|
+
return afs.delete(path, options);
|
|
29
|
+
},
|
|
30
|
+
async search(path, query, options) {
|
|
31
|
+
return afs.search(path, query, options);
|
|
32
|
+
},
|
|
33
|
+
async stat(path, options) {
|
|
34
|
+
return afs.stat(path, options);
|
|
35
|
+
},
|
|
36
|
+
async explain(path, options) {
|
|
37
|
+
return afs.explain(path, options);
|
|
38
|
+
},
|
|
39
|
+
async exec(path, args, options) {
|
|
40
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
41
|
+
return afs.exec(path, args, options);
|
|
42
|
+
},
|
|
43
|
+
async rename(oldPath, newPath, options) {
|
|
44
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
45
|
+
return afs.rename(oldPath, newPath, options);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Format serve result for output
|
|
51
|
+
*/
|
|
52
|
+
function formatServeOutput(result) {
|
|
53
|
+
const lines = [];
|
|
54
|
+
lines.push(require_index.colors.green("AFS HTTP Server starting..."));
|
|
55
|
+
lines.push(require_index.colors.bold("Mounted providers:"));
|
|
56
|
+
for (const mount of result.mounts) lines.push(` ${require_index.colors.cyan(mount.path.padEnd(20))} ${require_index.colors.dim(mount.provider)}`);
|
|
57
|
+
lines.push("");
|
|
58
|
+
lines.push(`${require_index.colors.dim("Listening on:")} ${require_index.colors.brightCyan(result.url)}`);
|
|
59
|
+
lines.push(require_index.colors.dim("Press Ctrl+C to stop"));
|
|
60
|
+
return lines.join("\n");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create serve command
|
|
64
|
+
*/
|
|
65
|
+
function createServeCommand(options) {
|
|
66
|
+
return {
|
|
67
|
+
command: "serve",
|
|
68
|
+
describe: "Start AFS server (HTTP or MCP)",
|
|
69
|
+
builder: {
|
|
70
|
+
host: {
|
|
71
|
+
type: "string",
|
|
72
|
+
default: "localhost",
|
|
73
|
+
description: "Host to bind"
|
|
74
|
+
},
|
|
75
|
+
port: {
|
|
76
|
+
type: "number",
|
|
77
|
+
default: 3e3,
|
|
78
|
+
description: "Port to listen on"
|
|
79
|
+
},
|
|
80
|
+
path: {
|
|
81
|
+
type: "string",
|
|
82
|
+
default: "/afs",
|
|
83
|
+
description: "Base path for API"
|
|
84
|
+
},
|
|
85
|
+
readonly: {
|
|
86
|
+
type: "boolean",
|
|
87
|
+
default: false,
|
|
88
|
+
description: "Read-only mode"
|
|
89
|
+
},
|
|
90
|
+
cors: {
|
|
91
|
+
type: "boolean",
|
|
92
|
+
default: false,
|
|
93
|
+
description: "Enable CORS"
|
|
94
|
+
},
|
|
95
|
+
transport: {
|
|
96
|
+
type: "string",
|
|
97
|
+
default: "http",
|
|
98
|
+
choices: [
|
|
99
|
+
"http",
|
|
100
|
+
"mcp-stdio",
|
|
101
|
+
"mcp-http"
|
|
102
|
+
],
|
|
103
|
+
description: "Transport: http (default), mcp-stdio, or mcp-http"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
handler: async (argv) => {
|
|
107
|
+
const config = await new require_loader.ConfigLoader().load(process.cwd());
|
|
108
|
+
const serveConfig = config.serve ?? {};
|
|
109
|
+
const host = argv.host ?? serveConfig.host ?? "localhost";
|
|
110
|
+
const port = argv.port ?? serveConfig.port ?? 3e3;
|
|
111
|
+
const basePath = argv.path ?? serveConfig.path ?? "/afs";
|
|
112
|
+
const readonly = argv.readonly ?? serveConfig.readonly ?? false;
|
|
113
|
+
const cors = argv.cors ?? serveConfig.cors ?? false;
|
|
114
|
+
const maxBodySize = serveConfig.max_body_size ?? 10 * 1024 * 1024;
|
|
115
|
+
const token = serveConfig.token;
|
|
116
|
+
const mounts = config.mounts.map((m) => ({
|
|
117
|
+
path: m.path,
|
|
118
|
+
provider: m.uri
|
|
119
|
+
}));
|
|
120
|
+
const afs = await require_types.resolveAFS(options);
|
|
121
|
+
if (argv.transport === "mcp-stdio") {
|
|
122
|
+
const { createAFSMcpServer } = await Promise.resolve().then(() => require("../../mcp/server.cjs"));
|
|
123
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
124
|
+
const { server: mcpServer } = createAFSMcpServer({ afs });
|
|
125
|
+
const transport = new StdioServerTransport();
|
|
126
|
+
await mcpServer.connect(transport);
|
|
127
|
+
await new Promise((resolve) => {
|
|
128
|
+
process.on("SIGINT", async () => {
|
|
129
|
+
await mcpServer.close();
|
|
130
|
+
resolve();
|
|
131
|
+
});
|
|
132
|
+
process.on("SIGTERM", async () => {
|
|
133
|
+
await mcpServer.close();
|
|
134
|
+
resolve();
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
if (argv.transport === "mcp-http") {
|
|
140
|
+
const { createAFSMcpServer } = await Promise.resolve().then(() => require("../../mcp/server.cjs"));
|
|
141
|
+
const { startMcpHttpServer } = await Promise.resolve().then(() => require("../../mcp/http-transport.cjs"));
|
|
142
|
+
const { server: mcpServer } = createAFSMcpServer({ afs });
|
|
143
|
+
await startMcpHttpServer({
|
|
144
|
+
mcpServer,
|
|
145
|
+
host,
|
|
146
|
+
port,
|
|
147
|
+
cors
|
|
148
|
+
});
|
|
149
|
+
await new Promise((resolve) => {
|
|
150
|
+
process.on("SIGINT", async () => {
|
|
151
|
+
await mcpServer.close();
|
|
152
|
+
resolve();
|
|
153
|
+
});
|
|
154
|
+
process.on("SIGTERM", async () => {
|
|
155
|
+
await mcpServer.close();
|
|
156
|
+
resolve();
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const handler = (0, _aigne_afs_http.createAFSHttpHandler)({
|
|
162
|
+
module: createAFSModule(afs, readonly),
|
|
163
|
+
maxBodySize,
|
|
164
|
+
token
|
|
165
|
+
});
|
|
166
|
+
const server = (0, node_http.createServer)(async (req, res) => {
|
|
167
|
+
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
168
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
169
|
+
console.error(`${timestamp} ${req.method} ${url.pathname}`);
|
|
170
|
+
if (cors) {
|
|
171
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
172
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
173
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
174
|
+
if (req.method === "OPTIONS") {
|
|
175
|
+
res.writeHead(204);
|
|
176
|
+
res.end();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (!url.pathname.startsWith(basePath)) {
|
|
181
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
182
|
+
res.end(JSON.stringify({
|
|
183
|
+
code: 1,
|
|
184
|
+
error: "Not found"
|
|
185
|
+
}));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
const headers = new Headers();
|
|
189
|
+
for (const [key, value] of Object.entries(req.headers)) if (value) headers.append(key, Array.isArray(value) ? value.join(", ") : value);
|
|
190
|
+
const chunks = [];
|
|
191
|
+
for await (const chunk of req) chunks.push(chunk);
|
|
192
|
+
const body = Buffer.concat(chunks);
|
|
193
|
+
const request = new Request(`http://${req.headers.host}${req.url}`, {
|
|
194
|
+
method: req.method,
|
|
195
|
+
headers,
|
|
196
|
+
body: body.length > 0 ? body : void 0
|
|
197
|
+
});
|
|
198
|
+
try {
|
|
199
|
+
const response = await handler(request);
|
|
200
|
+
res.writeHead(response.status, { "Content-Type": response.headers.get("Content-Type") || "application/json" });
|
|
201
|
+
const responseBody = await response.text();
|
|
202
|
+
res.end(responseBody);
|
|
203
|
+
console.error(`${timestamp} ${req.method} ${url.pathname} status=${response.status}`);
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error(`Error handling request:`, error);
|
|
206
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
207
|
+
res.end(JSON.stringify({
|
|
208
|
+
code: 5,
|
|
209
|
+
error: "Internal server error"
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
await new Promise((resolve, reject) => {
|
|
214
|
+
server.listen(port, host, () => {
|
|
215
|
+
resolve();
|
|
216
|
+
});
|
|
217
|
+
server.on("error", reject);
|
|
218
|
+
});
|
|
219
|
+
const shutdown = () => {
|
|
220
|
+
console.error("\nShutting down server...");
|
|
221
|
+
server.close(() => {
|
|
222
|
+
process.exit(0);
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
process.on("SIGINT", shutdown);
|
|
226
|
+
process.on("SIGTERM", shutdown);
|
|
227
|
+
const result = {
|
|
228
|
+
success: true,
|
|
229
|
+
host,
|
|
230
|
+
port,
|
|
231
|
+
path: basePath,
|
|
232
|
+
url: `http://${host}:${port}${basePath}`,
|
|
233
|
+
mounts
|
|
234
|
+
};
|
|
235
|
+
console.log(formatServeOutput(result));
|
|
236
|
+
await new Promise(() => {});
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
//#endregion
|
|
242
|
+
exports.createServeCommand = createServeCommand;
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { colors } from "../../ui/index.mjs";
|
|
2
|
+
import { ConfigLoader } from "../../config/loader.mjs";
|
|
3
|
+
import { resolveAFS } from "./types.mjs";
|
|
4
|
+
import { createServer } from "node:http";
|
|
5
|
+
import { createAFSHttpHandler } from "@aigne/afs-http";
|
|
6
|
+
|
|
7
|
+
//#region src/core/commands/serve.ts
|
|
8
|
+
/**
|
|
9
|
+
* Create an AFSModule wrapper around AFS
|
|
10
|
+
*/
|
|
11
|
+
function createAFSModule(afs, readonly) {
|
|
12
|
+
return {
|
|
13
|
+
name: "afs-server",
|
|
14
|
+
accessMode: readonly ? "readonly" : "readwrite",
|
|
15
|
+
async list(path, options) {
|
|
16
|
+
return afs.list(path, options);
|
|
17
|
+
},
|
|
18
|
+
async read(path, options) {
|
|
19
|
+
return afs.read(path, options);
|
|
20
|
+
},
|
|
21
|
+
async write(path, content, options) {
|
|
22
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
23
|
+
return afs.write(path, content, options);
|
|
24
|
+
},
|
|
25
|
+
async delete(path, options) {
|
|
26
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
27
|
+
return afs.delete(path, options);
|
|
28
|
+
},
|
|
29
|
+
async search(path, query, options) {
|
|
30
|
+
return afs.search(path, query, options);
|
|
31
|
+
},
|
|
32
|
+
async stat(path, options) {
|
|
33
|
+
return afs.stat(path, options);
|
|
34
|
+
},
|
|
35
|
+
async explain(path, options) {
|
|
36
|
+
return afs.explain(path, options);
|
|
37
|
+
},
|
|
38
|
+
async exec(path, args, options) {
|
|
39
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
40
|
+
return afs.exec(path, args, options);
|
|
41
|
+
},
|
|
42
|
+
async rename(oldPath, newPath, options) {
|
|
43
|
+
if (readonly) throw new Error("Server is in readonly mode");
|
|
44
|
+
return afs.rename(oldPath, newPath, options);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Format serve result for output
|
|
50
|
+
*/
|
|
51
|
+
function formatServeOutput(result) {
|
|
52
|
+
const lines = [];
|
|
53
|
+
lines.push(colors.green("AFS HTTP Server starting..."));
|
|
54
|
+
lines.push(colors.bold("Mounted providers:"));
|
|
55
|
+
for (const mount of result.mounts) lines.push(` ${colors.cyan(mount.path.padEnd(20))} ${colors.dim(mount.provider)}`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
lines.push(`${colors.dim("Listening on:")} ${colors.brightCyan(result.url)}`);
|
|
58
|
+
lines.push(colors.dim("Press Ctrl+C to stop"));
|
|
59
|
+
return lines.join("\n");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create serve command
|
|
63
|
+
*/
|
|
64
|
+
function createServeCommand(options) {
|
|
65
|
+
return {
|
|
66
|
+
command: "serve",
|
|
67
|
+
describe: "Start AFS server (HTTP or MCP)",
|
|
68
|
+
builder: {
|
|
69
|
+
host: {
|
|
70
|
+
type: "string",
|
|
71
|
+
default: "localhost",
|
|
72
|
+
description: "Host to bind"
|
|
73
|
+
},
|
|
74
|
+
port: {
|
|
75
|
+
type: "number",
|
|
76
|
+
default: 3e3,
|
|
77
|
+
description: "Port to listen on"
|
|
78
|
+
},
|
|
79
|
+
path: {
|
|
80
|
+
type: "string",
|
|
81
|
+
default: "/afs",
|
|
82
|
+
description: "Base path for API"
|
|
83
|
+
},
|
|
84
|
+
readonly: {
|
|
85
|
+
type: "boolean",
|
|
86
|
+
default: false,
|
|
87
|
+
description: "Read-only mode"
|
|
88
|
+
},
|
|
89
|
+
cors: {
|
|
90
|
+
type: "boolean",
|
|
91
|
+
default: false,
|
|
92
|
+
description: "Enable CORS"
|
|
93
|
+
},
|
|
94
|
+
transport: {
|
|
95
|
+
type: "string",
|
|
96
|
+
default: "http",
|
|
97
|
+
choices: [
|
|
98
|
+
"http",
|
|
99
|
+
"mcp-stdio",
|
|
100
|
+
"mcp-http"
|
|
101
|
+
],
|
|
102
|
+
description: "Transport: http (default), mcp-stdio, or mcp-http"
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
handler: async (argv) => {
|
|
106
|
+
const config = await new ConfigLoader().load(process.cwd());
|
|
107
|
+
const serveConfig = config.serve ?? {};
|
|
108
|
+
const host = argv.host ?? serveConfig.host ?? "localhost";
|
|
109
|
+
const port = argv.port ?? serveConfig.port ?? 3e3;
|
|
110
|
+
const basePath = argv.path ?? serveConfig.path ?? "/afs";
|
|
111
|
+
const readonly = argv.readonly ?? serveConfig.readonly ?? false;
|
|
112
|
+
const cors = argv.cors ?? serveConfig.cors ?? false;
|
|
113
|
+
const maxBodySize = serveConfig.max_body_size ?? 10 * 1024 * 1024;
|
|
114
|
+
const token = serveConfig.token;
|
|
115
|
+
const mounts = config.mounts.map((m) => ({
|
|
116
|
+
path: m.path,
|
|
117
|
+
provider: m.uri
|
|
118
|
+
}));
|
|
119
|
+
const afs = await resolveAFS(options);
|
|
120
|
+
if (argv.transport === "mcp-stdio") {
|
|
121
|
+
const { createAFSMcpServer } = await import("../../mcp/server.mjs");
|
|
122
|
+
const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
|
|
123
|
+
const { server: mcpServer } = createAFSMcpServer({ afs });
|
|
124
|
+
const transport = new StdioServerTransport();
|
|
125
|
+
await mcpServer.connect(transport);
|
|
126
|
+
await new Promise((resolve) => {
|
|
127
|
+
process.on("SIGINT", async () => {
|
|
128
|
+
await mcpServer.close();
|
|
129
|
+
resolve();
|
|
130
|
+
});
|
|
131
|
+
process.on("SIGTERM", async () => {
|
|
132
|
+
await mcpServer.close();
|
|
133
|
+
resolve();
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (argv.transport === "mcp-http") {
|
|
139
|
+
const { createAFSMcpServer } = await import("../../mcp/server.mjs");
|
|
140
|
+
const { startMcpHttpServer } = await import("../../mcp/http-transport.mjs");
|
|
141
|
+
const { server: mcpServer } = createAFSMcpServer({ afs });
|
|
142
|
+
await startMcpHttpServer({
|
|
143
|
+
mcpServer,
|
|
144
|
+
host,
|
|
145
|
+
port,
|
|
146
|
+
cors
|
|
147
|
+
});
|
|
148
|
+
await new Promise((resolve) => {
|
|
149
|
+
process.on("SIGINT", async () => {
|
|
150
|
+
await mcpServer.close();
|
|
151
|
+
resolve();
|
|
152
|
+
});
|
|
153
|
+
process.on("SIGTERM", async () => {
|
|
154
|
+
await mcpServer.close();
|
|
155
|
+
resolve();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const handler = createAFSHttpHandler({
|
|
161
|
+
module: createAFSModule(afs, readonly),
|
|
162
|
+
maxBodySize,
|
|
163
|
+
token
|
|
164
|
+
});
|
|
165
|
+
const server = createServer(async (req, res) => {
|
|
166
|
+
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
167
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
168
|
+
console.error(`${timestamp} ${req.method} ${url.pathname}`);
|
|
169
|
+
if (cors) {
|
|
170
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
171
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
|
|
172
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
|
173
|
+
if (req.method === "OPTIONS") {
|
|
174
|
+
res.writeHead(204);
|
|
175
|
+
res.end();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (!url.pathname.startsWith(basePath)) {
|
|
180
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
181
|
+
res.end(JSON.stringify({
|
|
182
|
+
code: 1,
|
|
183
|
+
error: "Not found"
|
|
184
|
+
}));
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const headers = new Headers();
|
|
188
|
+
for (const [key, value] of Object.entries(req.headers)) if (value) headers.append(key, Array.isArray(value) ? value.join(", ") : value);
|
|
189
|
+
const chunks = [];
|
|
190
|
+
for await (const chunk of req) chunks.push(chunk);
|
|
191
|
+
const body = Buffer.concat(chunks);
|
|
192
|
+
const request = new Request(`http://${req.headers.host}${req.url}`, {
|
|
193
|
+
method: req.method,
|
|
194
|
+
headers,
|
|
195
|
+
body: body.length > 0 ? body : void 0
|
|
196
|
+
});
|
|
197
|
+
try {
|
|
198
|
+
const response = await handler(request);
|
|
199
|
+
res.writeHead(response.status, { "Content-Type": response.headers.get("Content-Type") || "application/json" });
|
|
200
|
+
const responseBody = await response.text();
|
|
201
|
+
res.end(responseBody);
|
|
202
|
+
console.error(`${timestamp} ${req.method} ${url.pathname} status=${response.status}`);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error(`Error handling request:`, error);
|
|
205
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
206
|
+
res.end(JSON.stringify({
|
|
207
|
+
code: 5,
|
|
208
|
+
error: "Internal server error"
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
await new Promise((resolve, reject) => {
|
|
213
|
+
server.listen(port, host, () => {
|
|
214
|
+
resolve();
|
|
215
|
+
});
|
|
216
|
+
server.on("error", reject);
|
|
217
|
+
});
|
|
218
|
+
const shutdown = () => {
|
|
219
|
+
console.error("\nShutting down server...");
|
|
220
|
+
server.close(() => {
|
|
221
|
+
process.exit(0);
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
process.on("SIGINT", shutdown);
|
|
225
|
+
process.on("SIGTERM", shutdown);
|
|
226
|
+
const result = {
|
|
227
|
+
success: true,
|
|
228
|
+
host,
|
|
229
|
+
port,
|
|
230
|
+
path: basePath,
|
|
231
|
+
url: `http://${host}:${port}${basePath}`,
|
|
232
|
+
mounts
|
|
233
|
+
};
|
|
234
|
+
console.log(formatServeOutput(result));
|
|
235
|
+
await new Promise(() => {});
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
//#endregion
|
|
241
|
+
export { createServeCommand };
|
|
242
|
+
//# sourceMappingURL=serve.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.mjs","names":[],"sources":["../../../src/core/commands/serve.ts"],"sourcesContent":["/**\n * AFS Serve Command\n *\n * Starts an HTTP server to expose AFS providers over HTTP transport\n */\n\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { createServer } from \"node:http\";\nimport type { AFS, AFSModule } from \"@aigne/afs\";\nimport { createAFSHttpHandler } from \"@aigne/afs-http\";\nimport type { CommandModule } from \"yargs\";\nimport { ConfigLoader } from \"../../config/loader.js\";\nimport type { MountConfig, ServeConfig } from \"../../config/schema.js\";\nimport { colors } from \"../../ui/index.js\";\nimport { type CommandFactoryOptions, resolveAFS } from \"./types.js\";\n\nexport interface ServeArgs {\n host: string;\n port: number;\n path: string;\n readonly: boolean;\n cors: boolean;\n transport: \"http\" | \"mcp-stdio\" | \"mcp-http\";\n}\n\nexport interface ServeResult {\n success: boolean;\n host: string;\n port: number;\n path: string;\n url: string;\n mounts: Array<{ path: string; provider: string }>;\n}\n\n/**\n * Create an AFSModule wrapper around AFS\n */\nfunction createAFSModule(afs: AFS, readonly: boolean): AFSModule {\n return {\n name: \"afs-server\",\n accessMode: readonly ? \"readonly\" : \"readwrite\",\n async list(path, options) {\n return afs.list(path, options);\n },\n async read(path, options) {\n return afs.read(path, options);\n },\n async write(path, content, options) {\n if (readonly) {\n throw new Error(\"Server is in readonly mode\");\n }\n return afs.write(path, content, options);\n },\n async delete(path, options) {\n if (readonly) {\n throw new Error(\"Server is in readonly mode\");\n }\n return afs.delete(path, options);\n },\n async search(path, query, options) {\n return afs.search(path, query, options);\n },\n async stat(path, options) {\n return afs.stat(path, options);\n },\n async explain(path, options) {\n return afs.explain(path, options);\n },\n async exec(path, args, options) {\n if (readonly) {\n throw new Error(\"Server is in readonly mode\");\n }\n return afs.exec(path, args, options);\n },\n async rename(oldPath, newPath, options) {\n if (readonly) {\n throw new Error(\"Server is in readonly mode\");\n }\n return afs.rename(oldPath, newPath, options);\n },\n };\n}\n\n/**\n * Format serve result for output\n */\nexport function formatServeOutput(result: ServeResult): string {\n const lines: string[] = [];\n\n lines.push(colors.green(\"AFS HTTP Server starting...\"));\n lines.push(colors.bold(\"Mounted providers:\"));\n\n for (const mount of result.mounts) {\n lines.push(` ${colors.cyan(mount.path.padEnd(20))} ${colors.dim(mount.provider)}`);\n }\n\n lines.push(\"\");\n lines.push(`${colors.dim(\"Listening on:\")} ${colors.brightCyan(result.url)}`);\n lines.push(colors.dim(\"Press Ctrl+C to stop\"));\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Create serve command\n */\nexport function createServeCommand(\n options: CommandFactoryOptions,\n): CommandModule<unknown, ServeArgs> {\n return {\n command: \"serve\",\n describe: \"Start AFS server (HTTP or MCP)\",\n builder: {\n host: { type: \"string\", default: \"localhost\", description: \"Host to bind\" },\n port: { type: \"number\", default: 3000, description: \"Port to listen on\" },\n path: { type: \"string\", default: \"/afs\", description: \"Base path for API\" },\n readonly: { type: \"boolean\", default: false, description: \"Read-only mode\" },\n cors: { type: \"boolean\", default: false, description: \"Enable CORS\" },\n transport: {\n type: \"string\",\n default: \"http\",\n choices: [\"http\", \"mcp-stdio\", \"mcp-http\"],\n description: \"Transport: http (default), mcp-stdio, or mcp-http\",\n },\n },\n handler: async (argv) => {\n // Load config for serve defaults and mount info\n const configLoader = new ConfigLoader();\n const config = await configLoader.load(process.cwd());\n\n const serveConfig: Partial<ServeConfig> = config.serve ?? {};\n\n // Merge: command line > config file > defaults\n const host = argv.host ?? serveConfig.host ?? \"localhost\";\n const port = argv.port ?? serveConfig.port ?? 3000;\n const basePath = argv.path ?? serveConfig.path ?? \"/afs\";\n const readonly = argv.readonly ?? serveConfig.readonly ?? false;\n const cors = argv.cors ?? serveConfig.cors ?? false;\n const maxBodySize = serveConfig.max_body_size ?? 10 * 1024 * 1024;\n const token = serveConfig.token;\n\n const mounts: Array<{ path: string; provider: string }> = config.mounts.map(\n (m: MountConfig) => ({\n path: m.path,\n provider: m.uri,\n }),\n );\n\n // Create AFS instance\n const afs = await resolveAFS(options);\n\n // Dispatch based on transport mode\n if (argv.transport === \"mcp-stdio\") {\n const { createAFSMcpServer } = await import(\"../../mcp/server.js\");\n const { StdioServerTransport } = await import(\"@modelcontextprotocol/sdk/server/stdio.js\");\n const { server: mcpServer } = createAFSMcpServer({ afs });\n const transport = new StdioServerTransport();\n await mcpServer.connect(transport);\n // Block until server closes\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", async () => {\n await mcpServer.close();\n resolve();\n });\n process.on(\"SIGTERM\", async () => {\n await mcpServer.close();\n resolve();\n });\n });\n return;\n }\n\n if (argv.transport === \"mcp-http\") {\n const { createAFSMcpServer } = await import(\"../../mcp/server.js\");\n const { startMcpHttpServer } = await import(\"../../mcp/http-transport.js\");\n const { server: mcpServer } = createAFSMcpServer({ afs });\n await startMcpHttpServer({\n mcpServer,\n host,\n port,\n cors,\n });\n // Block until server closes\n await new Promise<void>((resolve) => {\n process.on(\"SIGINT\", async () => {\n await mcpServer.close();\n resolve();\n });\n process.on(\"SIGTERM\", async () => {\n await mcpServer.close();\n resolve();\n });\n });\n return;\n }\n\n // Default: HTTP transport (existing behavior)\n const module = createAFSModule(afs, readonly);\n\n // Create HTTP handler\n const handler = createAFSHttpHandler({\n module,\n maxBodySize,\n token,\n });\n\n // Create HTTP server with path routing\n const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n const url = new URL(req.url || \"/\", `http://${req.headers.host}`);\n\n // Log request\n const timestamp = new Date().toISOString();\n console.error(`${timestamp} ${req.method} ${url.pathname}`);\n\n // CORS support\n if (cors) {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET, POST, PUT, DELETE, OPTIONS\");\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\");\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204);\n res.end();\n return;\n }\n }\n\n // Check if request is for our base path\n if (!url.pathname.startsWith(basePath)) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ code: 1, error: \"Not found\" }));\n return;\n }\n\n // Convert Node.js request to Web Standard Request\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n headers.append(key, Array.isArray(value) ? value.join(\", \") : value);\n }\n }\n\n // Collect request body\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk);\n }\n const body = Buffer.concat(chunks);\n\n const request = new Request(`http://${req.headers.host}${req.url}`, {\n method: req.method,\n headers,\n body: body.length > 0 ? body : undefined,\n });\n\n try {\n // Call handler\n const response = await handler(request);\n\n // Copy response to Node.js response\n res.writeHead(response.status, {\n \"Content-Type\": response.headers.get(\"Content-Type\") || \"application/json\",\n });\n\n const responseBody = await response.text();\n res.end(responseBody);\n\n // Log response\n console.error(`${timestamp} ${req.method} ${url.pathname} status=${response.status}`);\n } catch (error) {\n console.error(`Error handling request:`, error);\n res.writeHead(500, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ code: 5, error: \"Internal server error\" }));\n }\n });\n\n // Start server\n await new Promise<void>((resolve, reject) => {\n server.listen(port, host, () => {\n resolve();\n });\n server.on(\"error\", reject);\n });\n\n // Handle graceful shutdown\n const shutdown = () => {\n console.error(\"\\nShutting down server...\");\n server.close(() => {\n process.exit(0);\n });\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n const url = `http://${host}:${port}${basePath}`;\n\n const result: ServeResult = {\n success: true,\n host,\n port,\n path: basePath,\n url,\n mounts,\n };\n\n console.log(formatServeOutput(result));\n\n // Keep running\n await new Promise(() => {});\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const require_stat = require('../formatters/stat.cjs');
|
|
2
|
+
const require_path_utils = require('../../path-utils.cjs');
|
|
3
|
+
require('../path-utils.cjs');
|
|
4
|
+
const require_types = require('./types.cjs');
|
|
5
|
+
const require_errors = require('../../errors.cjs');
|
|
6
|
+
|
|
7
|
+
//#region src/core/commands/stat.ts
|
|
8
|
+
/**
|
|
9
|
+
* Create stat command factory
|
|
10
|
+
*/
|
|
11
|
+
function createStatCommand(options) {
|
|
12
|
+
return {
|
|
13
|
+
command: "stat <path>",
|
|
14
|
+
describe: "Get file or directory info",
|
|
15
|
+
builder: { path: {
|
|
16
|
+
type: "string",
|
|
17
|
+
demandOption: true,
|
|
18
|
+
description: "Path to stat"
|
|
19
|
+
} },
|
|
20
|
+
handler: async (argv) => {
|
|
21
|
+
const afs = await require_types.resolveAFS(options);
|
|
22
|
+
const canonicalPath = require_path_utils.cliPathToCanonical(argv.path);
|
|
23
|
+
let result;
|
|
24
|
+
try {
|
|
25
|
+
result = await afs.stat(canonicalPath);
|
|
26
|
+
} catch {}
|
|
27
|
+
if (!result) try {
|
|
28
|
+
const entry = (await afs.read(canonicalPath)).data;
|
|
29
|
+
if (entry) result = { data: {
|
|
30
|
+
...entry,
|
|
31
|
+
meta: entry.meta ?? {}
|
|
32
|
+
} };
|
|
33
|
+
} catch {}
|
|
34
|
+
if (result?.data) result.data.path = argv.path;
|
|
35
|
+
const notFound = !result?.data;
|
|
36
|
+
options.onResult({
|
|
37
|
+
command: "stat",
|
|
38
|
+
result: result ?? {
|
|
39
|
+
data: void 0,
|
|
40
|
+
message: `No data found for path: ${argv.path}`
|
|
41
|
+
},
|
|
42
|
+
format: require_stat.formatStatOutput,
|
|
43
|
+
...notFound && { error: {
|
|
44
|
+
code: require_errors.ExitCode.NOT_FOUND,
|
|
45
|
+
message: `No data found for path: ${argv.path}`
|
|
46
|
+
} }
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
exports.createStatCommand = createStatCommand;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommandFactoryOptions } from "./types.cjs";
|
|
2
|
+
import { CommandModule } from "yargs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/commands/stat.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Stat command arguments
|
|
7
|
+
*/
|
|
8
|
+
interface StatArgs {
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create stat command factory
|
|
13
|
+
*/
|
|
14
|
+
declare function createStatCommand(options: CommandFactoryOptions): CommandModule<unknown, StatArgs>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { StatArgs, createStatCommand };
|
|
17
|
+
//# sourceMappingURL=stat.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat.d.cts","names":[],"sources":["../../../src/core/commands/stat.ts"],"mappings":";;;;;AAwBA;;UAPiB,QAAA;EACf,IAAA;AAAA;;;;iBAMc,iBAAA,CACd,OAAA,EAAS,qBAAA,GACR,aAAA,UAAuB,QAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommandFactoryOptions } from "./types.mjs";
|
|
2
|
+
import { CommandModule } from "yargs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/commands/stat.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Stat command arguments
|
|
7
|
+
*/
|
|
8
|
+
interface StatArgs {
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create stat command factory
|
|
13
|
+
*/
|
|
14
|
+
declare function createStatCommand(options: CommandFactoryOptions): CommandModule<unknown, StatArgs>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { StatArgs, createStatCommand };
|
|
17
|
+
//# sourceMappingURL=stat.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat.d.mts","names":[],"sources":["../../../src/core/commands/stat.ts"],"mappings":";;;;;AAwBA;;UAPiB,QAAA;EACf,IAAA;AAAA;;;;iBAMc,iBAAA,CACd,OAAA,EAAS,qBAAA,GACR,aAAA,UAAuB,QAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { formatStatOutput } from "../formatters/stat.mjs";
|
|
2
|
+
import { cliPathToCanonical } from "../../path-utils.mjs";
|
|
3
|
+
import "../path-utils.mjs";
|
|
4
|
+
import { resolveAFS } from "./types.mjs";
|
|
5
|
+
import { ExitCode } from "../../errors.mjs";
|
|
6
|
+
|
|
7
|
+
//#region src/core/commands/stat.ts
|
|
8
|
+
/**
|
|
9
|
+
* Create stat command factory
|
|
10
|
+
*/
|
|
11
|
+
function createStatCommand(options) {
|
|
12
|
+
return {
|
|
13
|
+
command: "stat <path>",
|
|
14
|
+
describe: "Get file or directory info",
|
|
15
|
+
builder: { path: {
|
|
16
|
+
type: "string",
|
|
17
|
+
demandOption: true,
|
|
18
|
+
description: "Path to stat"
|
|
19
|
+
} },
|
|
20
|
+
handler: async (argv) => {
|
|
21
|
+
const afs = await resolveAFS(options);
|
|
22
|
+
const canonicalPath = cliPathToCanonical(argv.path);
|
|
23
|
+
let result;
|
|
24
|
+
try {
|
|
25
|
+
result = await afs.stat(canonicalPath);
|
|
26
|
+
} catch {}
|
|
27
|
+
if (!result) try {
|
|
28
|
+
const entry = (await afs.read(canonicalPath)).data;
|
|
29
|
+
if (entry) result = { data: {
|
|
30
|
+
...entry,
|
|
31
|
+
meta: entry.meta ?? {}
|
|
32
|
+
} };
|
|
33
|
+
} catch {}
|
|
34
|
+
if (result?.data) result.data.path = argv.path;
|
|
35
|
+
const notFound = !result?.data;
|
|
36
|
+
options.onResult({
|
|
37
|
+
command: "stat",
|
|
38
|
+
result: result ?? {
|
|
39
|
+
data: void 0,
|
|
40
|
+
message: `No data found for path: ${argv.path}`
|
|
41
|
+
},
|
|
42
|
+
format: formatStatOutput,
|
|
43
|
+
...notFound && { error: {
|
|
44
|
+
code: ExitCode.NOT_FOUND,
|
|
45
|
+
message: `No data found for path: ${argv.path}`
|
|
46
|
+
} }
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { createStatCommand };
|
|
54
|
+
//# sourceMappingURL=stat.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat.mjs","names":[],"sources":["../../../src/core/commands/stat.ts"],"sourcesContent":["/**\n * stat Command - Core Implementation\n *\n * Gets file/node statistics. Accepts AFS instance directly.\n * Returns AFSStatResult directly (no custom type).\n */\n\nimport type { AFSStatResult } from \"@aigne/afs\";\nimport type { CommandModule } from \"yargs\";\nimport { ExitCode } from \"../../errors.js\";\nimport { formatStatOutput } from \"../formatters/index.js\";\nimport { cliPathToCanonical } from \"../path-utils.js\";\nimport { type CommandFactoryOptions, resolveAFS } from \"./types.js\";\n\n/**\n * Stat command arguments\n */\nexport interface StatArgs {\n path: string;\n}\n\n/**\n * Create stat command factory\n */\nexport function createStatCommand(\n options: CommandFactoryOptions,\n): CommandModule<unknown, StatArgs> {\n return {\n command: \"stat <path>\",\n describe: \"Get file or directory info\",\n builder: {\n path: {\n type: \"string\",\n demandOption: true,\n description: \"Path to stat\",\n },\n },\n handler: async (argv) => {\n const afs = await resolveAFS(options);\n const canonicalPath = cliPathToCanonical(argv.path);\n let result: AFSStatResult | undefined;\n try {\n result = await afs.stat(canonicalPath);\n } catch {}\n\n if (!result) {\n // Fallback: Use read to get detailed metadata\n try {\n const entry = (await afs.read(canonicalPath)).data;\n if (entry) {\n result = { data: { ...entry, meta: entry.meta ?? {} } };\n }\n } catch {}\n }\n\n // Use the original CLI path for display (UX-friendly, e.g. /fs instead of $afs/fs)\n if (result?.data) {\n result.data.path = argv.path;\n }\n\n const notFound = !result?.data;\n options.onResult({\n command: \"stat\",\n result: result ?? { data: undefined, message: `No data found for path: ${argv.path}` },\n format: formatStatOutput,\n ...(notFound && {\n error: {\n code: ExitCode.NOT_FOUND,\n message: `No data found for path: ${argv.path}`,\n },\n }),\n });\n },\n };\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAgB,kBACd,SACkC;AAClC,QAAO;EACL,SAAS;EACT,UAAU;EACV,SAAS,EACP,MAAM;GACJ,MAAM;GACN,cAAc;GACd,aAAa;GACd,EACF;EACD,SAAS,OAAO,SAAS;GACvB,MAAM,MAAM,MAAM,WAAW,QAAQ;GACrC,MAAM,gBAAgB,mBAAmB,KAAK,KAAK;GACnD,IAAI;AACJ,OAAI;AACF,aAAS,MAAM,IAAI,KAAK,cAAc;WAChC;AAER,OAAI,CAAC,OAEH,KAAI;IACF,MAAM,SAAS,MAAM,IAAI,KAAK,cAAc,EAAE;AAC9C,QAAI,MACF,UAAS,EAAE,MAAM;KAAE,GAAG;KAAO,MAAM,MAAM,QAAQ,EAAE;KAAE,EAAE;WAEnD;AAIV,OAAI,QAAQ,KACV,QAAO,KAAK,OAAO,KAAK;GAG1B,MAAM,WAAW,CAAC,QAAQ;AAC1B,WAAQ,SAAS;IACf,SAAS;IACT,QAAQ,UAAU;KAAE,MAAM;KAAW,SAAS,2BAA2B,KAAK;KAAQ;IACtF,QAAQ;IACR,GAAI,YAAY,EACd,OAAO;KACL,MAAM,SAAS;KACf,SAAS,2BAA2B,KAAK;KAC1C,EACF;IACF,CAAC;;EAEL"}
|