@aigne/afs-cli 1.11.0-beta.11 → 1.11.0-beta.12
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 +3 -2
- package/dist/cli.mjs +3 -2
- package/dist/cli.mjs.map +1 -1
- package/dist/config/afs-loader.cjs +64 -315
- package/dist/config/afs-loader.d.cts.map +1 -1
- package/dist/config/afs-loader.d.mts +2 -1
- package/dist/config/afs-loader.d.mts.map +1 -1
- package/dist/config/afs-loader.mjs +59 -310
- package/dist/config/afs-loader.mjs.map +1 -1
- package/dist/config/credential-helpers.cjs +291 -0
- package/dist/config/credential-helpers.d.mts +2 -0
- package/dist/config/credential-helpers.mjs +288 -0
- package/dist/config/credential-helpers.mjs.map +1 -0
- package/dist/config/loader.cjs +3 -1
- package/dist/config/loader.mjs +3 -2
- package/dist/config/loader.mjs.map +1 -1
- package/dist/config/program-install.cjs +276 -0
- package/dist/config/program-install.d.mts +1 -0
- package/dist/config/program-install.mjs +273 -0
- package/dist/config/program-install.mjs.map +1 -0
- package/dist/core/commands/connect.cjs +53 -0
- package/dist/core/commands/connect.d.mts +2 -0
- package/dist/core/commands/connect.mjs +55 -0
- package/dist/core/commands/connect.mjs.map +1 -0
- package/dist/core/commands/daemon.cjs +207 -0
- package/dist/core/commands/daemon.d.mts +2 -0
- package/dist/core/commands/daemon.mjs +208 -0
- package/dist/core/commands/daemon.mjs.map +1 -0
- package/dist/core/commands/explain.cjs +3 -1
- package/dist/core/commands/explain.mjs +3 -1
- package/dist/core/commands/explain.mjs.map +1 -1
- package/dist/core/commands/explore.cjs +47 -12
- package/dist/core/commands/explore.mjs +47 -12
- package/dist/core/commands/explore.mjs.map +1 -1
- package/dist/core/commands/gen-agent-md.cjs +126 -0
- package/dist/core/commands/gen-agent-md.d.mts +2 -0
- package/dist/core/commands/gen-agent-md.mjs +125 -0
- package/dist/core/commands/gen-agent-md.mjs.map +1 -0
- package/dist/core/commands/index.cjs +13 -1
- package/dist/core/commands/index.d.cts.map +1 -1
- package/dist/core/commands/index.d.mts +6 -0
- package/dist/core/commands/index.d.mts.map +1 -1
- package/dist/core/commands/index.mjs +13 -1
- package/dist/core/commands/index.mjs.map +1 -1
- package/dist/core/commands/install.cjs +91 -0
- package/dist/core/commands/install.d.mts +2 -0
- package/dist/core/commands/install.mjs +92 -0
- package/dist/core/commands/install.mjs.map +1 -0
- package/dist/core/commands/ls.cjs +14 -2
- package/dist/core/commands/ls.d.cts +2 -0
- package/dist/core/commands/ls.d.cts.map +1 -1
- package/dist/core/commands/ls.d.mts +2 -0
- package/dist/core/commands/ls.d.mts.map +1 -1
- package/dist/core/commands/ls.mjs +14 -2
- package/dist/core/commands/ls.mjs.map +1 -1
- package/dist/core/commands/mcp-bridge.cjs +201 -0
- package/dist/core/commands/mcp-bridge.d.mts +2 -0
- package/dist/core/commands/mcp-bridge.mjs +201 -0
- package/dist/core/commands/mcp-bridge.mjs.map +1 -0
- package/dist/core/commands/read.cjs +20 -7
- package/dist/core/commands/read.d.cts +2 -0
- package/dist/core/commands/read.d.cts.map +1 -1
- package/dist/core/commands/read.d.mts +2 -0
- package/dist/core/commands/read.d.mts.map +1 -1
- package/dist/core/commands/read.mjs +20 -7
- package/dist/core/commands/read.mjs.map +1 -1
- package/dist/core/commands/search.cjs +5 -1
- package/dist/core/commands/search.mjs +5 -1
- package/dist/core/commands/search.mjs.map +1 -1
- package/dist/core/commands/stat.mjs.map +1 -1
- package/dist/core/commands/types.d.cts +2 -0
- package/dist/core/commands/types.d.cts.map +1 -1
- package/dist/core/commands/types.d.mts +2 -0
- package/dist/core/commands/types.d.mts.map +1 -1
- package/dist/core/commands/types.mjs.map +1 -1
- package/dist/core/commands/vault.cjs +289 -0
- package/dist/core/commands/vault.d.mts +2 -0
- package/dist/core/commands/vault.mjs +289 -0
- package/dist/core/commands/vault.mjs.map +1 -0
- package/dist/core/commands/write.cjs +19 -6
- package/dist/core/commands/write.d.cts +2 -1
- package/dist/core/commands/write.d.cts.map +1 -1
- package/dist/core/commands/write.d.mts +2 -1
- package/dist/core/commands/write.d.mts.map +1 -1
- package/dist/core/commands/write.mjs +19 -6
- package/dist/core/commands/write.mjs.map +1 -1
- package/dist/core/executor/index.cjs +95 -19
- package/dist/core/executor/index.d.cts +4 -0
- package/dist/core/executor/index.d.cts.map +1 -1
- package/dist/core/executor/index.d.mts +4 -0
- package/dist/core/executor/index.d.mts.map +1 -1
- package/dist/core/executor/index.mjs +95 -19
- package/dist/core/executor/index.mjs.map +1 -1
- package/dist/core/formatters/index.d.mts +1 -0
- package/dist/core/formatters/install.cjs +21 -0
- package/dist/core/formatters/install.d.mts +1 -0
- package/dist/core/formatters/install.mjs +19 -0
- package/dist/core/formatters/install.mjs.map +1 -0
- package/dist/core/formatters/vault.cjs +36 -0
- package/dist/core/formatters/vault.mjs +32 -0
- package/dist/core/formatters/vault.mjs.map +1 -0
- package/dist/credential/index.d.mts +2 -1
- package/dist/credential/mcp-auth-context.cjs +21 -5
- package/dist/credential/mcp-auth-context.mjs +21 -5
- package/dist/credential/mcp-auth-context.mjs.map +1 -1
- package/dist/credential/resolver.cjs +7 -2
- package/dist/credential/resolver.mjs +7 -2
- package/dist/credential/resolver.mjs.map +1 -1
- package/dist/credential/vault-store.d.mts +1 -0
- package/dist/daemon/config-manager.cjs +279 -0
- package/dist/daemon/config-manager.mjs +279 -0
- package/dist/daemon/config-manager.mjs.map +1 -0
- package/dist/daemon/manager.cjs +164 -0
- package/dist/daemon/manager.mjs +157 -0
- package/dist/daemon/manager.mjs.map +1 -0
- package/dist/daemon/server.cjs +220 -0
- package/dist/daemon/server.mjs +220 -0
- package/dist/daemon/server.mjs.map +1 -0
- package/dist/mcp/http-transport.cjs +14 -1
- package/dist/mcp/http-transport.mjs +14 -1
- package/dist/mcp/http-transport.mjs.map +1 -1
- package/dist/mcp/server.cjs +4 -2
- package/dist/mcp/server.mjs +4 -2
- package/dist/mcp/server.mjs.map +1 -1
- package/dist/mcp/tools.cjs +62 -12
- package/dist/mcp/tools.mjs +62 -12
- package/dist/mcp/tools.mjs.map +1 -1
- package/dist/program/daemon-integration.cjs +46 -0
- package/dist/program/daemon-integration.mjs +45 -0
- package/dist/program/daemon-integration.mjs.map +1 -0
- package/dist/program/program-manager.cjs +162 -0
- package/dist/program/program-manager.mjs +162 -0
- package/dist/program/program-manager.mjs.map +1 -0
- package/dist/program/trigger-scanner.cjs +148 -0
- package/dist/program/trigger-scanner.mjs +148 -0
- package/dist/program/trigger-scanner.mjs.map +1 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +11 -0
- package/dist/providers/vault/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs.map +1 -0
- package/dist/providers/vault/dist/encrypted-file.cjs +158 -0
- package/dist/providers/vault/dist/encrypted-file.mjs +153 -0
- package/dist/providers/vault/dist/encrypted-file.mjs.map +1 -0
- package/dist/providers/vault/dist/index.cjs +405 -0
- package/dist/providers/vault/dist/index.mjs +400 -0
- package/dist/providers/vault/dist/index.mjs.map +1 -0
- package/dist/providers/vault/dist/key-resolver.cjs +181 -0
- package/dist/providers/vault/dist/key-resolver.mjs +180 -0
- package/dist/providers/vault/dist/key-resolver.mjs.map +1 -0
- package/dist/repl.cjs +105 -14
- package/dist/repl.d.cts.map +1 -1
- package/dist/repl.d.mts.map +1 -1
- package/dist/repl.mjs +105 -14
- package/dist/repl.mjs.map +1 -1
- package/package.json +29 -22
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const require_index = require('../../ui/index.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/core/commands/connect.ts
|
|
4
|
+
/** No-op formatter for lifecycle commands that manage their own output. */
|
|
5
|
+
const noopFormat = () => "";
|
|
6
|
+
function createConnectCommand(options) {
|
|
7
|
+
return {
|
|
8
|
+
command: "connect",
|
|
9
|
+
describe: "Start service and open web explorer",
|
|
10
|
+
builder: { port: {
|
|
11
|
+
type: "number",
|
|
12
|
+
default: 4900,
|
|
13
|
+
description: "Port for service"
|
|
14
|
+
} },
|
|
15
|
+
handler: async (argv) => {
|
|
16
|
+
const { getDaemonStatus, spawnDaemon } = await Promise.resolve().then(() => require("../../daemon/manager.cjs"));
|
|
17
|
+
let info = await getDaemonStatus();
|
|
18
|
+
if (info) console.log(`${require_index.colors.green("Service already running")} on port ${info.port}`);
|
|
19
|
+
else {
|
|
20
|
+
console.log(require_index.colors.dim("Starting AFS service..."));
|
|
21
|
+
try {
|
|
22
|
+
info = await spawnDaemon(argv.port);
|
|
23
|
+
console.log(require_index.colors.green("AFS Service started"));
|
|
24
|
+
console.log(` ${require_index.colors.dim("PID:")} ${info.pid}`);
|
|
25
|
+
console.log(` ${require_index.colors.dim("Port:")} ${info.port}`);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
console.error(require_index.colors.red(`Failed to start service: ${err.message}`));
|
|
28
|
+
options.onResult({
|
|
29
|
+
command: "connect",
|
|
30
|
+
result: null,
|
|
31
|
+
format: noopFormat
|
|
32
|
+
});
|
|
33
|
+
process.exitCode = 1;
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
console.log(` ${require_index.colors.dim("URL:")} ${require_index.colors.brightCyan(info.url)}`);
|
|
38
|
+
openBrowser(info.url);
|
|
39
|
+
options.onResult({
|
|
40
|
+
command: "connect",
|
|
41
|
+
result: null,
|
|
42
|
+
format: noopFormat
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function openBrowser(url) {
|
|
48
|
+
const { exec } = require("node:child_process");
|
|
49
|
+
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"} ${url}`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
exports.createConnectCommand = createConnectCommand;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { __require } from "../../_virtual/rolldown_runtime.mjs";
|
|
2
|
+
import { colors } from "../../ui/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/core/commands/connect.ts
|
|
5
|
+
/** No-op formatter for lifecycle commands that manage their own output. */
|
|
6
|
+
const noopFormat = () => "";
|
|
7
|
+
function createConnectCommand(options) {
|
|
8
|
+
return {
|
|
9
|
+
command: "connect",
|
|
10
|
+
describe: "Start service and open web explorer",
|
|
11
|
+
builder: { port: {
|
|
12
|
+
type: "number",
|
|
13
|
+
default: 4900,
|
|
14
|
+
description: "Port for service"
|
|
15
|
+
} },
|
|
16
|
+
handler: async (argv) => {
|
|
17
|
+
const { getDaemonStatus, spawnDaemon } = await import("../../daemon/manager.mjs");
|
|
18
|
+
let info = await getDaemonStatus();
|
|
19
|
+
if (info) console.log(`${colors.green("Service already running")} on port ${info.port}`);
|
|
20
|
+
else {
|
|
21
|
+
console.log(colors.dim("Starting AFS service..."));
|
|
22
|
+
try {
|
|
23
|
+
info = await spawnDaemon(argv.port);
|
|
24
|
+
console.log(colors.green("AFS Service started"));
|
|
25
|
+
console.log(` ${colors.dim("PID:")} ${info.pid}`);
|
|
26
|
+
console.log(` ${colors.dim("Port:")} ${info.port}`);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.error(colors.red(`Failed to start service: ${err.message}`));
|
|
29
|
+
options.onResult({
|
|
30
|
+
command: "connect",
|
|
31
|
+
result: null,
|
|
32
|
+
format: noopFormat
|
|
33
|
+
});
|
|
34
|
+
process.exitCode = 1;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
console.log(` ${colors.dim("URL:")} ${colors.brightCyan(info.url)}`);
|
|
39
|
+
openBrowser(info.url);
|
|
40
|
+
options.onResult({
|
|
41
|
+
command: "connect",
|
|
42
|
+
result: null,
|
|
43
|
+
format: noopFormat
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function openBrowser(url) {
|
|
49
|
+
const { exec } = __require("node:child_process");
|
|
50
|
+
exec(`${process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open"} ${url}`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
export { createConnectCommand };
|
|
55
|
+
//# sourceMappingURL=connect.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.mjs","names":[],"sources":["../../../src/core/commands/connect.ts"],"sourcesContent":["/**\n * AFS Connect Command\n *\n * One-command experience: starts service (if not running) + opens browser + exits.\n * This is the primary user entry point.\n */\n\nimport type { CommandModule } from \"yargs\";\nimport { colors } from \"../../ui/index.js\";\nimport type { CommandFactoryOptions } from \"./types.js\";\n\nexport interface ConnectArgs {\n port: number;\n}\n\n/** No-op formatter for lifecycle commands that manage their own output. */\nconst noopFormat = () => \"\";\n\nexport function createConnectCommand(\n options: CommandFactoryOptions,\n): CommandModule<unknown, ConnectArgs> {\n return {\n command: \"connect\",\n describe: \"Start service and open web explorer\",\n builder: {\n port: {\n type: \"number\",\n default: 4900,\n description: \"Port for service\",\n },\n },\n handler: async (argv) => {\n const { getDaemonStatus, spawnDaemon } = await import(\"../../daemon/manager.js\");\n\n let info = await getDaemonStatus();\n\n if (info) {\n console.log(`${colors.green(\"Service already running\")} on port ${info.port}`);\n } else {\n console.log(colors.dim(\"Starting AFS service...\"));\n try {\n info = await spawnDaemon(argv.port);\n console.log(colors.green(\"AFS Service started\"));\n console.log(` ${colors.dim(\"PID:\")} ${info.pid}`);\n console.log(` ${colors.dim(\"Port:\")} ${info.port}`);\n } catch (err) {\n console.error(colors.red(`Failed to start service: ${(err as Error).message}`));\n options.onResult({ command: \"connect\", result: null, format: noopFormat });\n process.exitCode = 1;\n return;\n }\n }\n\n console.log(` ${colors.dim(\"URL:\")} ${colors.brightCyan(info.url)}`);\n openBrowser(info.url);\n\n // Signal executor that command ran (output already printed above)\n options.onResult({ command: \"connect\", result: null, format: noopFormat });\n },\n };\n}\n\nfunction openBrowser(url: string): void {\n const { exec } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n const cmd =\n process.platform === \"darwin\" ? \"open\" : process.platform === \"win32\" ? \"start\" : \"xdg-open\";\n exec(`${cmd} ${url}`);\n}\n"],"mappings":";;;;;AAgBA,MAAM,mBAAmB;AAEzB,SAAgB,qBACd,SACqC;AACrC,QAAO;EACL,SAAS;EACT,UAAU;EACV,SAAS,EACP,MAAM;GACJ,MAAM;GACN,SAAS;GACT,aAAa;GACd,EACF;EACD,SAAS,OAAO,SAAS;GACvB,MAAM,EAAE,iBAAiB,gBAAgB,MAAM,OAAO;GAEtD,IAAI,OAAO,MAAM,iBAAiB;AAElC,OAAI,KACF,SAAQ,IAAI,GAAG,OAAO,MAAM,0BAA0B,CAAC,WAAW,KAAK,OAAO;QACzE;AACL,YAAQ,IAAI,OAAO,IAAI,0BAA0B,CAAC;AAClD,QAAI;AACF,YAAO,MAAM,YAAY,KAAK,KAAK;AACnC,aAAQ,IAAI,OAAO,MAAM,sBAAsB,CAAC;AAChD,aAAQ,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;AACnD,aAAQ,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,GAAG,KAAK,OAAO;aAC7C,KAAK;AACZ,aAAQ,MAAM,OAAO,IAAI,4BAA6B,IAAc,UAAU,CAAC;AAC/E,aAAQ,SAAS;MAAE,SAAS;MAAW,QAAQ;MAAM,QAAQ;MAAY,CAAC;AAC1E,aAAQ,WAAW;AACnB;;;AAIJ,WAAQ,IAAI,KAAK,OAAO,IAAI,OAAO,CAAC,IAAI,OAAO,WAAW,KAAK,IAAI,GAAG;AACtE,eAAY,KAAK,IAAI;AAGrB,WAAQ,SAAS;IAAE,SAAS;IAAW,QAAQ;IAAM,QAAQ;IAAY,CAAC;;EAE7E;;AAGH,SAAS,YAAY,KAAmB;CACtC,MAAM,EAAE,mBAAiB,qBAAqB;AAG9C,MAAK,GADH,QAAQ,aAAa,WAAW,SAAS,QAAQ,aAAa,UAAU,UAAU,WACxE,GAAG,MAAM"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
const require_index = require('../../ui/index.cjs');
|
|
2
|
+
|
|
3
|
+
//#region src/core/commands/daemon.ts
|
|
4
|
+
/** No-op formatter for lifecycle commands that manage their own output. */
|
|
5
|
+
const noopFormat = () => "";
|
|
6
|
+
/** Print endpoint table for a running service. */
|
|
7
|
+
function printEndpoints(url) {
|
|
8
|
+
console.log("");
|
|
9
|
+
console.log(` ${require_index.colors.dim("Endpoints:")}`);
|
|
10
|
+
console.log(` ${require_index.colors.brightCyan(`${url}/`)}${require_index.colors.dim(" Explorer UI")}`);
|
|
11
|
+
console.log(` ${require_index.colors.brightCyan(`${url}/ws`)}${require_index.colors.dim(" WebSocket JSON-RPC")}`);
|
|
12
|
+
console.log(` ${require_index.colors.brightCyan(`${url}/afs/*`)}${require_index.colors.dim(" REST API")}`);
|
|
13
|
+
console.log(` ${require_index.colors.brightCyan(`${url}/mcp`)}${require_index.colors.dim(" MCP Streamable HTTP")}`);
|
|
14
|
+
}
|
|
15
|
+
function createServiceCommand(options) {
|
|
16
|
+
return {
|
|
17
|
+
command: "service <action>",
|
|
18
|
+
describe: "Manage AFS background service",
|
|
19
|
+
builder: (yargs) => yargs.positional("action", {
|
|
20
|
+
type: "string",
|
|
21
|
+
choices: [
|
|
22
|
+
"start",
|
|
23
|
+
"stop",
|
|
24
|
+
"status",
|
|
25
|
+
"restart"
|
|
26
|
+
],
|
|
27
|
+
description: "Service action"
|
|
28
|
+
}).option("port", {
|
|
29
|
+
type: "number",
|
|
30
|
+
default: 4900,
|
|
31
|
+
description: "Port for service"
|
|
32
|
+
}).option("cwd", {
|
|
33
|
+
type: "string",
|
|
34
|
+
hidden: true,
|
|
35
|
+
description: "Working directory (used by _run)"
|
|
36
|
+
}),
|
|
37
|
+
handler: async (argv) => {
|
|
38
|
+
const action = argv.action;
|
|
39
|
+
const { getDaemonStatus, stopDaemon, spawnDaemon, getLogFile } = await Promise.resolve().then(() => require("../../daemon/manager.cjs"));
|
|
40
|
+
switch (action) {
|
|
41
|
+
case "start": {
|
|
42
|
+
const existing = await getDaemonStatus();
|
|
43
|
+
if (existing) {
|
|
44
|
+
console.log(`${require_index.colors.yellow("Service already running")} (PID ${existing.pid}, port ${existing.port})`);
|
|
45
|
+
printEndpoints(existing.url);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(require_index.colors.dim("Starting AFS service..."));
|
|
49
|
+
try {
|
|
50
|
+
const info = await spawnDaemon(argv.port);
|
|
51
|
+
console.log(require_index.colors.green("AFS Service started"));
|
|
52
|
+
console.log(` ${require_index.colors.dim("PID:")} ${info.pid}`);
|
|
53
|
+
console.log(` ${require_index.colors.dim("Port:")} ${info.port}`);
|
|
54
|
+
console.log(` ${require_index.colors.dim("Log:")} ${getLogFile()}`);
|
|
55
|
+
printEndpoints(info.url);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error(require_index.colors.red(`Failed to start service: ${err.message}`));
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "_run": {
|
|
63
|
+
const logTs = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
64
|
+
process.on("uncaughtException", (err) => {
|
|
65
|
+
console.error(`[${logTs()}] FATAL uncaughtException: ${err.stack || err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
68
|
+
process.on("unhandledRejection", (reason) => {
|
|
69
|
+
const msg = reason instanceof Error ? reason.stack || reason.message : String(reason);
|
|
70
|
+
console.error(`[${logTs()}] FATAL unhandledRejection: ${msg}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
const { homedir } = await import("node:os");
|
|
74
|
+
const cwd = argv.cwd ?? homedir();
|
|
75
|
+
const { createAFS } = await Promise.resolve().then(() => require("../../config/afs-loader.cjs"));
|
|
76
|
+
const { startDaemonServer } = await Promise.resolve().then(() => require("../../daemon/server.cjs"));
|
|
77
|
+
const { DaemonConfigManager } = await Promise.resolve().then(() => require("../../daemon/config-manager.cjs"));
|
|
78
|
+
const { writePidFile, writePortFile, ensureDaemonDir, cleanPidFiles } = await Promise.resolve().then(() => require("../../daemon/manager.cjs"));
|
|
79
|
+
const { createCredentialStore } = await Promise.resolve().then(() => require("../../credential/store.cjs"));
|
|
80
|
+
const { afs, failures, configMountPaths, registry } = await createAFS(cwd, { credentialStore: createCredentialStore() });
|
|
81
|
+
if (failures.length > 0) {
|
|
82
|
+
console.warn(`[${logTs()}] ${failures.length} provider(s) failed to mount:`);
|
|
83
|
+
for (const f of failures) console.warn(` ${f.path}: ${f.reason}`);
|
|
84
|
+
}
|
|
85
|
+
const configManager = new DaemonConfigManager({
|
|
86
|
+
cwd,
|
|
87
|
+
afs,
|
|
88
|
+
registry,
|
|
89
|
+
configMountPaths,
|
|
90
|
+
failures: failures.map((f) => ({
|
|
91
|
+
path: f.path,
|
|
92
|
+
uri: "",
|
|
93
|
+
reason: f.reason
|
|
94
|
+
})),
|
|
95
|
+
onConfigChanged: (added, removed) => {
|
|
96
|
+
if (serverInfo?.server) serverInfo.server.broadcast("configReloaded", {
|
|
97
|
+
added,
|
|
98
|
+
removed
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
configManager.startWatching();
|
|
103
|
+
const { ProgramManager } = await Promise.resolve().then(() => require("../../program/program-manager.cjs"));
|
|
104
|
+
const { scanProgramTriggers } = await Promise.resolve().then(() => require("../../program/trigger-scanner.cjs"));
|
|
105
|
+
const { listInstalledPrograms, getUserConfigDir } = await Promise.resolve().then(() => require("../../config/program-install.cjs"));
|
|
106
|
+
const userConfigDir = getUserConfigDir();
|
|
107
|
+
const programManager = new ProgramManager({
|
|
108
|
+
globalAFS: afs,
|
|
109
|
+
createProvider: afs.createProviderFromMount,
|
|
110
|
+
listPrograms: async () => {
|
|
111
|
+
return (await listInstalledPrograms({ userConfigDir })).map((p) => ({
|
|
112
|
+
id: p.id,
|
|
113
|
+
installPath: p.installPath,
|
|
114
|
+
mountPath: p.mountPath
|
|
115
|
+
}));
|
|
116
|
+
},
|
|
117
|
+
scanTriggers: async (programDir) => {
|
|
118
|
+
let compile = null;
|
|
119
|
+
try {
|
|
120
|
+
compile = (await import("@aigne/ash")).compileSource;
|
|
121
|
+
} catch {}
|
|
122
|
+
return scanProgramTriggers(programDir, compile);
|
|
123
|
+
},
|
|
124
|
+
dataDir: (programId) => `/.data/${programId}`
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
await programManager.activateAll();
|
|
128
|
+
const activated = programManager.getActivatedPrograms();
|
|
129
|
+
if (activated.length > 0) console.log(`[${logTs()}] Activated ${activated.length} program(s): ${activated.join(", ")}`);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.warn(`[${logTs()}] Program activation failed: ${err instanceof Error ? err.message : err}`);
|
|
132
|
+
}
|
|
133
|
+
let serverInfo;
|
|
134
|
+
serverInfo = await startDaemonServer({
|
|
135
|
+
afs,
|
|
136
|
+
port: argv.port,
|
|
137
|
+
configManager,
|
|
138
|
+
programManager
|
|
139
|
+
});
|
|
140
|
+
await ensureDaemonDir();
|
|
141
|
+
await writePidFile(process.pid);
|
|
142
|
+
await writePortFile(serverInfo.port);
|
|
143
|
+
const mounts = afs.getMounts();
|
|
144
|
+
console.log(`[${logTs()}] AFS Service started`);
|
|
145
|
+
console.log(`PID: ${process.pid}, Port: ${serverInfo.port}`);
|
|
146
|
+
console.log(`MCP: ${serverInfo.mcpUrl}`);
|
|
147
|
+
for (const m of mounts) console.log(` ${m.path} → ${m.module.name}`);
|
|
148
|
+
let shuttingDown = false;
|
|
149
|
+
const shutdown = async () => {
|
|
150
|
+
if (shuttingDown) return;
|
|
151
|
+
shuttingDown = true;
|
|
152
|
+
console.log(`[${logTs()}] Shutting down service...`);
|
|
153
|
+
try {
|
|
154
|
+
await programManager.deactivateAll();
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.warn(`[${logTs()}] Program deactivation error: ${err instanceof Error ? err.message : err}`);
|
|
157
|
+
}
|
|
158
|
+
configManager.stopWatching();
|
|
159
|
+
serverInfo?.stop();
|
|
160
|
+
await cleanPidFiles();
|
|
161
|
+
process.exit(0);
|
|
162
|
+
};
|
|
163
|
+
process.on("SIGINT", shutdown);
|
|
164
|
+
process.on("SIGTERM", shutdown);
|
|
165
|
+
await new Promise(() => {});
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case "stop":
|
|
169
|
+
if (await stopDaemon()) console.log(require_index.colors.green("Service stopped"));
|
|
170
|
+
else console.log(require_index.colors.yellow("No running service found"));
|
|
171
|
+
break;
|
|
172
|
+
case "status": {
|
|
173
|
+
const info = await getDaemonStatus();
|
|
174
|
+
if (info) {
|
|
175
|
+
console.log(require_index.colors.green("Service is running"));
|
|
176
|
+
console.log(` PID: ${info.pid}`);
|
|
177
|
+
console.log(` Port: ${info.port}`);
|
|
178
|
+
printEndpoints(info.url);
|
|
179
|
+
} else console.log(require_index.colors.dim("Service is not running"));
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "restart":
|
|
183
|
+
if (await stopDaemon()) console.log(require_index.colors.dim("Stopped existing service, restarting..."));
|
|
184
|
+
console.log(require_index.colors.dim("Starting AFS service..."));
|
|
185
|
+
try {
|
|
186
|
+
const info = await spawnDaemon(argv.port);
|
|
187
|
+
console.log(require_index.colors.green("AFS Service restarted"));
|
|
188
|
+
console.log(` ${require_index.colors.dim("PID:")} ${info.pid}`);
|
|
189
|
+
console.log(` ${require_index.colors.dim("Port:")} ${info.port}`);
|
|
190
|
+
printEndpoints(info.url);
|
|
191
|
+
} catch (err) {
|
|
192
|
+
console.error(require_index.colors.red(`Failed to restart service: ${err.message}`));
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
options.onResult({
|
|
198
|
+
command: "service",
|
|
199
|
+
result: null,
|
|
200
|
+
format: noopFormat
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
//#endregion
|
|
207
|
+
exports.createServiceCommand = createServiceCommand;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { colors } from "../../ui/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/core/commands/daemon.ts
|
|
4
|
+
/** No-op formatter for lifecycle commands that manage their own output. */
|
|
5
|
+
const noopFormat = () => "";
|
|
6
|
+
/** Print endpoint table for a running service. */
|
|
7
|
+
function printEndpoints(url) {
|
|
8
|
+
console.log("");
|
|
9
|
+
console.log(` ${colors.dim("Endpoints:")}`);
|
|
10
|
+
console.log(` ${colors.brightCyan(`${url}/`)}${colors.dim(" Explorer UI")}`);
|
|
11
|
+
console.log(` ${colors.brightCyan(`${url}/ws`)}${colors.dim(" WebSocket JSON-RPC")}`);
|
|
12
|
+
console.log(` ${colors.brightCyan(`${url}/afs/*`)}${colors.dim(" REST API")}`);
|
|
13
|
+
console.log(` ${colors.brightCyan(`${url}/mcp`)}${colors.dim(" MCP Streamable HTTP")}`);
|
|
14
|
+
}
|
|
15
|
+
function createServiceCommand(options) {
|
|
16
|
+
return {
|
|
17
|
+
command: "service <action>",
|
|
18
|
+
describe: "Manage AFS background service",
|
|
19
|
+
builder: (yargs) => yargs.positional("action", {
|
|
20
|
+
type: "string",
|
|
21
|
+
choices: [
|
|
22
|
+
"start",
|
|
23
|
+
"stop",
|
|
24
|
+
"status",
|
|
25
|
+
"restart"
|
|
26
|
+
],
|
|
27
|
+
description: "Service action"
|
|
28
|
+
}).option("port", {
|
|
29
|
+
type: "number",
|
|
30
|
+
default: 4900,
|
|
31
|
+
description: "Port for service"
|
|
32
|
+
}).option("cwd", {
|
|
33
|
+
type: "string",
|
|
34
|
+
hidden: true,
|
|
35
|
+
description: "Working directory (used by _run)"
|
|
36
|
+
}),
|
|
37
|
+
handler: async (argv) => {
|
|
38
|
+
const action = argv.action;
|
|
39
|
+
const { getDaemonStatus, stopDaemon, spawnDaemon, getLogFile } = await import("../../daemon/manager.mjs");
|
|
40
|
+
switch (action) {
|
|
41
|
+
case "start": {
|
|
42
|
+
const existing = await getDaemonStatus();
|
|
43
|
+
if (existing) {
|
|
44
|
+
console.log(`${colors.yellow("Service already running")} (PID ${existing.pid}, port ${existing.port})`);
|
|
45
|
+
printEndpoints(existing.url);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
console.log(colors.dim("Starting AFS service..."));
|
|
49
|
+
try {
|
|
50
|
+
const info = await spawnDaemon(argv.port);
|
|
51
|
+
console.log(colors.green("AFS Service started"));
|
|
52
|
+
console.log(` ${colors.dim("PID:")} ${info.pid}`);
|
|
53
|
+
console.log(` ${colors.dim("Port:")} ${info.port}`);
|
|
54
|
+
console.log(` ${colors.dim("Log:")} ${getLogFile()}`);
|
|
55
|
+
printEndpoints(info.url);
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error(colors.red(`Failed to start service: ${err.message}`));
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case "_run": {
|
|
63
|
+
const logTs = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
64
|
+
process.on("uncaughtException", (err) => {
|
|
65
|
+
console.error(`[${logTs()}] FATAL uncaughtException: ${err.stack || err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
68
|
+
process.on("unhandledRejection", (reason) => {
|
|
69
|
+
const msg = reason instanceof Error ? reason.stack || reason.message : String(reason);
|
|
70
|
+
console.error(`[${logTs()}] FATAL unhandledRejection: ${msg}`);
|
|
71
|
+
process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
const { homedir } = await import("node:os");
|
|
74
|
+
const cwd = argv.cwd ?? homedir();
|
|
75
|
+
const { createAFS } = await import("../../config/afs-loader.mjs");
|
|
76
|
+
const { startDaemonServer } = await import("../../daemon/server.mjs");
|
|
77
|
+
const { DaemonConfigManager } = await import("../../daemon/config-manager.mjs");
|
|
78
|
+
const { writePidFile, writePortFile, ensureDaemonDir, cleanPidFiles } = await import("../../daemon/manager.mjs");
|
|
79
|
+
const { createCredentialStore } = await import("../../credential/store.mjs");
|
|
80
|
+
const { afs, failures, configMountPaths, registry } = await createAFS(cwd, { credentialStore: createCredentialStore() });
|
|
81
|
+
if (failures.length > 0) {
|
|
82
|
+
console.warn(`[${logTs()}] ${failures.length} provider(s) failed to mount:`);
|
|
83
|
+
for (const f of failures) console.warn(` ${f.path}: ${f.reason}`);
|
|
84
|
+
}
|
|
85
|
+
const configManager = new DaemonConfigManager({
|
|
86
|
+
cwd,
|
|
87
|
+
afs,
|
|
88
|
+
registry,
|
|
89
|
+
configMountPaths,
|
|
90
|
+
failures: failures.map((f) => ({
|
|
91
|
+
path: f.path,
|
|
92
|
+
uri: "",
|
|
93
|
+
reason: f.reason
|
|
94
|
+
})),
|
|
95
|
+
onConfigChanged: (added, removed) => {
|
|
96
|
+
if (serverInfo?.server) serverInfo.server.broadcast("configReloaded", {
|
|
97
|
+
added,
|
|
98
|
+
removed
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
configManager.startWatching();
|
|
103
|
+
const { ProgramManager } = await import("../../program/program-manager.mjs");
|
|
104
|
+
const { scanProgramTriggers } = await import("../../program/trigger-scanner.mjs");
|
|
105
|
+
const { listInstalledPrograms, getUserConfigDir } = await import("../../config/program-install.mjs");
|
|
106
|
+
const userConfigDir = getUserConfigDir();
|
|
107
|
+
const programManager = new ProgramManager({
|
|
108
|
+
globalAFS: afs,
|
|
109
|
+
createProvider: afs.createProviderFromMount,
|
|
110
|
+
listPrograms: async () => {
|
|
111
|
+
return (await listInstalledPrograms({ userConfigDir })).map((p) => ({
|
|
112
|
+
id: p.id,
|
|
113
|
+
installPath: p.installPath,
|
|
114
|
+
mountPath: p.mountPath
|
|
115
|
+
}));
|
|
116
|
+
},
|
|
117
|
+
scanTriggers: async (programDir) => {
|
|
118
|
+
let compile = null;
|
|
119
|
+
try {
|
|
120
|
+
compile = (await import("@aigne/ash")).compileSource;
|
|
121
|
+
} catch {}
|
|
122
|
+
return scanProgramTriggers(programDir, compile);
|
|
123
|
+
},
|
|
124
|
+
dataDir: (programId) => `/.data/${programId}`
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
await programManager.activateAll();
|
|
128
|
+
const activated = programManager.getActivatedPrograms();
|
|
129
|
+
if (activated.length > 0) console.log(`[${logTs()}] Activated ${activated.length} program(s): ${activated.join(", ")}`);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
console.warn(`[${logTs()}] Program activation failed: ${err instanceof Error ? err.message : err}`);
|
|
132
|
+
}
|
|
133
|
+
let serverInfo;
|
|
134
|
+
serverInfo = await startDaemonServer({
|
|
135
|
+
afs,
|
|
136
|
+
port: argv.port,
|
|
137
|
+
configManager,
|
|
138
|
+
programManager
|
|
139
|
+
});
|
|
140
|
+
await ensureDaemonDir();
|
|
141
|
+
await writePidFile(process.pid);
|
|
142
|
+
await writePortFile(serverInfo.port);
|
|
143
|
+
const mounts = afs.getMounts();
|
|
144
|
+
console.log(`[${logTs()}] AFS Service started`);
|
|
145
|
+
console.log(`PID: ${process.pid}, Port: ${serverInfo.port}`);
|
|
146
|
+
console.log(`MCP: ${serverInfo.mcpUrl}`);
|
|
147
|
+
for (const m of mounts) console.log(` ${m.path} → ${m.module.name}`);
|
|
148
|
+
let shuttingDown = false;
|
|
149
|
+
const shutdown = async () => {
|
|
150
|
+
if (shuttingDown) return;
|
|
151
|
+
shuttingDown = true;
|
|
152
|
+
console.log(`[${logTs()}] Shutting down service...`);
|
|
153
|
+
try {
|
|
154
|
+
await programManager.deactivateAll();
|
|
155
|
+
} catch (err) {
|
|
156
|
+
console.warn(`[${logTs()}] Program deactivation error: ${err instanceof Error ? err.message : err}`);
|
|
157
|
+
}
|
|
158
|
+
configManager.stopWatching();
|
|
159
|
+
serverInfo?.stop();
|
|
160
|
+
await cleanPidFiles();
|
|
161
|
+
process.exit(0);
|
|
162
|
+
};
|
|
163
|
+
process.on("SIGINT", shutdown);
|
|
164
|
+
process.on("SIGTERM", shutdown);
|
|
165
|
+
await new Promise(() => {});
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case "stop":
|
|
169
|
+
if (await stopDaemon()) console.log(colors.green("Service stopped"));
|
|
170
|
+
else console.log(colors.yellow("No running service found"));
|
|
171
|
+
break;
|
|
172
|
+
case "status": {
|
|
173
|
+
const info = await getDaemonStatus();
|
|
174
|
+
if (info) {
|
|
175
|
+
console.log(colors.green("Service is running"));
|
|
176
|
+
console.log(` PID: ${info.pid}`);
|
|
177
|
+
console.log(` Port: ${info.port}`);
|
|
178
|
+
printEndpoints(info.url);
|
|
179
|
+
} else console.log(colors.dim("Service is not running"));
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
case "restart":
|
|
183
|
+
if (await stopDaemon()) console.log(colors.dim("Stopped existing service, restarting..."));
|
|
184
|
+
console.log(colors.dim("Starting AFS service..."));
|
|
185
|
+
try {
|
|
186
|
+
const info = await spawnDaemon(argv.port);
|
|
187
|
+
console.log(colors.green("AFS Service restarted"));
|
|
188
|
+
console.log(` ${colors.dim("PID:")} ${info.pid}`);
|
|
189
|
+
console.log(` ${colors.dim("Port:")} ${info.port}`);
|
|
190
|
+
printEndpoints(info.url);
|
|
191
|
+
} catch (err) {
|
|
192
|
+
console.error(colors.red(`Failed to restart service: ${err.message}`));
|
|
193
|
+
process.exitCode = 1;
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
options.onResult({
|
|
198
|
+
command: "service",
|
|
199
|
+
result: null,
|
|
200
|
+
format: noopFormat
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
//#endregion
|
|
207
|
+
export { createServiceCommand };
|
|
208
|
+
//# sourceMappingURL=daemon.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"daemon.mjs","names":[],"sources":["../../../src/core/commands/daemon.ts"],"sourcesContent":["/**\n * AFS Service Command\n *\n * Manages the AFS background service process.\n * Subcommands: start, stop, status, restart, _run (hidden)\n *\n * File is named daemon.ts for historical reasons; the user-facing command is \"service\".\n */\n\nimport type { CommandModule } from \"yargs\";\nimport { colors } from \"../../ui/index.js\";\nimport type { CommandFactoryOptions } from \"./types.js\";\n\nexport interface ServiceArgs {\n port: number;\n cwd?: string;\n}\n\n/** No-op formatter for lifecycle commands that manage their own output. */\nconst noopFormat = () => \"\";\n\n/** Print endpoint table for a running service. */\nfunction printEndpoints(url: string): void {\n console.log(\"\");\n console.log(` ${colors.dim(\"Endpoints:\")}`);\n console.log(` ${colors.brightCyan(`${url}/`)}${colors.dim(\" Explorer UI\")}`);\n console.log(` ${colors.brightCyan(`${url}/ws`)}${colors.dim(\" WebSocket JSON-RPC\")}`);\n console.log(` ${colors.brightCyan(`${url}/afs/*`)}${colors.dim(\" REST API\")}`);\n console.log(` ${colors.brightCyan(`${url}/mcp`)}${colors.dim(\" MCP Streamable HTTP\")}`);\n}\n\nexport function createServiceCommand(\n options: CommandFactoryOptions,\n): CommandModule<unknown, ServiceArgs> {\n return {\n command: \"service <action>\",\n describe: \"Manage AFS background service\",\n builder: (yargs) =>\n yargs\n .positional(\"action\", {\n type: \"string\",\n choices: [\"start\", \"stop\", \"status\", \"restart\"],\n description: \"Service action\",\n })\n .option(\"port\", {\n type: \"number\",\n default: 4900,\n description: \"Port for service\",\n })\n .option(\"cwd\", {\n type: \"string\",\n hidden: true,\n description: \"Working directory (used by _run)\",\n }) as any,\n handler: async (argv) => {\n const action = (argv as any).action as string;\n const { getDaemonStatus, stopDaemon, spawnDaemon, getLogFile } = await import(\n \"../../daemon/manager.js\"\n );\n\n switch (action) {\n case \"start\": {\n const existing = await getDaemonStatus();\n if (existing) {\n console.log(\n `${colors.yellow(\"Service already running\")} (PID ${existing.pid}, port ${existing.port})`,\n );\n printEndpoints(existing.url);\n return;\n }\n\n console.log(colors.dim(\"Starting AFS service...\"));\n\n try {\n const info = await spawnDaemon(argv.port);\n console.log(colors.green(\"AFS Service started\"));\n console.log(` ${colors.dim(\"PID:\")} ${info.pid}`);\n console.log(` ${colors.dim(\"Port:\")} ${info.port}`);\n console.log(` ${colors.dim(\"Log:\")} ${getLogFile()}`);\n printEndpoints(info.url);\n } catch (err) {\n console.error(colors.red(`Failed to start service: ${(err as Error).message}`));\n process.exitCode = 1;\n }\n break;\n }\n\n case \"_run\": {\n // Hidden subcommand — the actual service process (runs in detached child)\n\n // Install crash handlers immediately — before any async work.\n // Without these, uncaught errors kill the process with no trace in the log.\n const logTs = () => new Date().toISOString();\n process.on(\"uncaughtException\", (err) => {\n console.error(`[${logTs()}] FATAL uncaughtException: ${err.stack || err.message}`);\n process.exit(1);\n });\n process.on(\"unhandledRejection\", (reason) => {\n const msg = reason instanceof Error ? reason.stack || reason.message : String(reason);\n console.error(`[${logTs()}] FATAL unhandledRejection: ${msg}`);\n process.exit(1);\n });\n\n // Always use home directory for config discovery — daemon serves a\n // global AFS instance, independent of which directory it was started from.\n const { homedir } = await import(\"node:os\");\n const cwd = argv.cwd ?? homedir();\n const { createAFS } = await import(\"../../config/afs-loader.js\");\n const { startDaemonServer } = await import(\"../../daemon/server.js\");\n const { DaemonConfigManager } = await import(\"../../daemon/config-manager.js\");\n const { writePidFile, writePortFile, ensureDaemonDir, cleanPidFiles } = await import(\n \"../../daemon/manager.js\"\n );\n const { createCredentialStore } = await import(\"../../credential/store.js\");\n\n const { afs, failures, configMountPaths, registry } = await createAFS(cwd, {\n credentialStore: createCredentialStore(),\n // No authContext — daemon is non-interactive, relies on stored credentials\n });\n\n if (failures.length > 0) {\n console.warn(`[${logTs()}] ${failures.length} provider(s) failed to mount:`);\n for (const f of failures) {\n console.warn(` ${f.path}: ${f.reason}`);\n }\n }\n\n const configManager = new DaemonConfigManager({\n cwd,\n afs,\n registry,\n configMountPaths,\n failures: failures.map((f) => ({ path: f.path, uri: \"\", reason: f.reason })),\n onConfigChanged: (added, removed) => {\n if (serverInfo?.server) {\n serverInfo.server.broadcast(\"configReloaded\", { added, removed });\n }\n },\n });\n configManager.startWatching();\n\n // Initialize ProgramManager for program activation\n const { ProgramManager } = await import(\"../../program/program-manager.js\");\n const { scanProgramTriggers } = await import(\"../../program/trigger-scanner.js\");\n const { listInstalledPrograms, getUserConfigDir } = await import(\n \"../../config/program-install.js\"\n );\n\n const userConfigDir = getUserConfigDir();\n const programManager = new ProgramManager({\n globalAFS: afs,\n createProvider: afs.createProviderFromMount,\n listPrograms: async () => {\n const programs = await listInstalledPrograms({ userConfigDir });\n return programs.map((p) => ({\n id: p.id,\n installPath: p.installPath,\n mountPath: p.mountPath,\n }));\n },\n scanTriggers: async (programDir: string) => {\n let compile = null;\n try {\n // Dynamic import — @aigne/ash is an optional peer dependency\n const ashModule = \"@aigne/ash\";\n const mod = await import(/* webpackIgnore: true */ ashModule);\n compile = mod.compileSource;\n } catch {\n // @aigne/ash not available — use regex fallback\n }\n return scanProgramTriggers(programDir, compile);\n },\n dataDir: (programId: string) => `/.data/${programId}`,\n });\n\n // Activate all programs (best-effort — failures don't block daemon startup)\n try {\n await programManager.activateAll();\n const activated = programManager.getActivatedPrograms();\n if (activated.length > 0) {\n console.log(\n `[${logTs()}] Activated ${activated.length} program(s): ${activated.join(\", \")}`,\n );\n }\n } catch (err) {\n console.warn(\n `[${logTs()}] Program activation failed: ${err instanceof Error ? err.message : err}`,\n );\n }\n\n let serverInfo: Awaited<ReturnType<typeof startDaemonServer>> | undefined;\n serverInfo = await startDaemonServer({\n afs,\n port: argv.port,\n configManager,\n programManager,\n });\n\n // Write PID and port files so parent (and status/stop) can find us\n await ensureDaemonDir();\n await writePidFile(process.pid);\n await writePortFile(serverInfo.port);\n\n const mounts = afs.getMounts();\n console.log(`[${logTs()}] AFS Service started`);\n console.log(`PID: ${process.pid}, Port: ${serverInfo.port}`);\n console.log(`MCP: ${serverInfo.mcpUrl}`);\n for (const m of mounts) {\n console.log(` ${m.path} → ${m.module.name}`);\n }\n\n // Graceful shutdown\n let shuttingDown = false;\n const shutdown = async () => {\n if (shuttingDown) return;\n shuttingDown = true;\n console.log(`[${logTs()}] Shutting down service...`);\n try {\n await programManager.deactivateAll();\n } catch (err) {\n console.warn(\n `[${logTs()}] Program deactivation error: ${err instanceof Error ? err.message : err}`,\n );\n }\n configManager.stopWatching();\n serverInfo?.stop();\n await cleanPidFiles();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n\n // Keep running\n await new Promise(() => {});\n break;\n }\n\n case \"stop\": {\n const stopped = await stopDaemon();\n if (stopped) {\n console.log(colors.green(\"Service stopped\"));\n } else {\n console.log(colors.yellow(\"No running service found\"));\n }\n break;\n }\n\n case \"status\": {\n const info = await getDaemonStatus();\n if (info) {\n console.log(colors.green(\"Service is running\"));\n console.log(` PID: ${info.pid}`);\n console.log(` Port: ${info.port}`);\n printEndpoints(info.url);\n } else {\n console.log(colors.dim(\"Service is not running\"));\n }\n break;\n }\n\n case \"restart\": {\n const wasRunning = await stopDaemon();\n if (wasRunning) {\n console.log(colors.dim(\"Stopped existing service, restarting...\"));\n }\n\n console.log(colors.dim(\"Starting AFS service...\"));\n try {\n const info = await spawnDaemon(argv.port);\n console.log(colors.green(\"AFS Service restarted\"));\n console.log(` ${colors.dim(\"PID:\")} ${info.pid}`);\n console.log(` ${colors.dim(\"Port:\")} ${info.port}`);\n printEndpoints(info.url);\n } catch (err) {\n console.error(colors.red(`Failed to restart service: ${(err as Error).message}`));\n process.exitCode = 1;\n }\n break;\n }\n }\n\n // Signal executor that command ran (output already printed above)\n options.onResult({ command: \"service\", result: null, format: noopFormat });\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -165,7 +165,9 @@ async function explainMounts(cwd, afs) {
|
|
|
165
165
|
explanation: `Runtime mounts (mounted via API):\n\n${listResult.data.map((entry) => ` ${entry.path} (runtime mount)`).join("\n")}`,
|
|
166
166
|
examples: listResult.data.slice(0, 3).map((entry) => `afs ls ${entry.path}`)
|
|
167
167
|
};
|
|
168
|
-
} catch {
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.debug("[explain] mount enumeration failed:", err);
|
|
170
|
+
}
|
|
169
171
|
return {
|
|
170
172
|
topic: "Mounts",
|
|
171
173
|
explanation: `No mounts configured.
|
|
@@ -165,7 +165,9 @@ async function explainMounts(cwd, afs) {
|
|
|
165
165
|
explanation: `Runtime mounts (mounted via API):\n\n${listResult.data.map((entry) => ` ${entry.path} (runtime mount)`).join("\n")}`,
|
|
166
166
|
examples: listResult.data.slice(0, 3).map((entry) => `afs ls ${entry.path}`)
|
|
167
167
|
};
|
|
168
|
-
} catch {
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.debug("[explain] mount enumeration failed:", err);
|
|
170
|
+
}
|
|
169
171
|
return {
|
|
170
172
|
topic: "Mounts",
|
|
171
173
|
explanation: `No mounts configured.
|