agentinbox-cli 0.1.0-nightly.4 → 0.1.0-nightly.6
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/README.md +21 -0
- package/dist/cli.js +101 -24
- package/dist/cli.js.map +1 -1
- package/dist/content-BXblC_Qs.js +1162 -0
- package/dist/content-BXblC_Qs.js.map +1 -0
- package/dist/content-worker.js +28 -0
- package/dist/content-worker.js.map +1 -0
- package/dist/{instance-BnbMB2EK.js → instance-CgeL0q45.js} +28 -4
- package/dist/{instance-BnbMB2EK.js.map → instance-CgeL0q45.js.map} +1 -1
- package/dist/instance-CxS8D7b2.js +2 -0
- package/dist/{server-F3DTB7YC.js → server-CL0omdA2.js} +2655 -154
- package/dist/server-CL0omdA2.js.map +1 -0
- package/dist/service-cxr2FxwM.js +473 -0
- package/dist/service-cxr2FxwM.js.map +1 -0
- package/dist/{settings-DkA2sgzt.js → settings-BIuG-X7b.js} +12 -3
- package/dist/settings-BIuG-X7b.js.map +1 -0
- package/dist/settings-BK7h99j7.js +2 -0
- package/dist/skill-BJFn2bHK.js +2 -0
- package/dist/urls-Dp8pBGMU.js +2 -0
- package/dist/{urls-DmnonkJo.js → urls-U_LfYV61.js} +7 -2
- package/dist/urls-U_LfYV61.js.map +1 -0
- package/dist/web/assets/{_agentId-Cq2tty9r.js → _agentId-B1IT_oLM.js} +1 -1
- package/dist/web/assets/{_app-DU_bk7n8.js → _app-BZC_ezNd.js} +1 -1
- package/dist/web/assets/{_app-Cb1baRA0.js → _app-D899up8Q.js} +1 -1
- package/dist/web/assets/{_webhookId-B55gK0Lb.js → _webhookId-DL_FfpbN.js} +1 -1
- package/dist/web/assets/{account-status-C08BBEsU.js → account-status-B7xuoHdX.js} +1 -1
- package/dist/web/assets/{accounts-Bk1s8Uzv.js → accounts-BaWYdoXm.js} +1 -1
- package/dist/web/assets/{accounts-list-F-kO3jiT.js → accounts-list-SlLEx0Tj.js} +1 -1
- package/dist/web/assets/{agent-create-form-BxTkdezg.js → agent-create-form-xY4c5aKn.js} +1 -1
- package/dist/web/assets/{agents-CmbZ2lwf.js → agents-BeT2jhye.js} +1 -1
- package/dist/web/assets/{approvals-3DYaHsIJ.js → approvals-HoqCXgai.js} +1 -1
- package/dist/web/assets/{audit-CDXxi4Hk.js → audit-BKc-GvxS.js} +1 -1
- package/dist/web/assets/{audit-bits-D8AkB5ZU.js → audit-bits-D5T99qmp.js} +1 -1
- package/dist/web/assets/{chips-input-D_rUs_lc.js → chips-input-DnJH-tBN.js} +1 -1
- package/dist/web/assets/{common-Cc3JNp4n.js → common-ZVp8Iqy7.js} +1 -1
- package/dist/web/assets/{connect-host-BV4t499t.js → connect-host-DwjH0Vjz.js} +1 -1
- package/dist/web/assets/{data-table-CyhIs-ZM.js → data-table-Cgc2dZGL.js} +1 -1
- package/dist/web/assets/{dialog-Da2XSU3Y.js → dialog-CtguxvM9.js} +1 -1
- package/dist/web/assets/{event-row-BsPXPNKL.js → event-row-DeVjUVeT.js} +1 -1
- package/dist/web/assets/{events-eSr5JR5h.js → events-DLL46jV7.js} +1 -1
- package/dist/web/assets/{get-started-CGYjo7e7.js → get-started-6sT3RVnC.js} +1 -1
- package/dist/web/assets/{grants-BOBZxwBG.js → grants-CEtysWJ8.js} +1 -1
- package/dist/web/assets/{index-MbDFbrbR.js → index-DIE0uwO-.js} +2 -2
- package/dist/web/assets/index-akvt_1UI.css +2 -0
- package/dist/web/assets/{login-DTteGF6c.js → login-DM_C5rb-.js} +1 -1
- package/dist/web/assets/{mutations-C9NgE3M4.js → mutations-DE96cXwv.js} +1 -1
- package/dist/web/assets/{select-B7o4J-XI.js → select-BZaLwu6u.js} +1 -1
- package/dist/web/assets/{settings-CundYHSp.js → settings-ClkElIad.js} +1 -1
- package/dist/web/assets/{settings-form-BDGVJnAI.js → settings-form-BerjRzzv.js} +1 -1
- package/dist/web/assets/{setup-BHRb8np_.js → setup-DB0QQETq.js} +1 -1
- package/dist/web/assets/{sheet-CbWxq7yd.js → sheet-C_M4zCN1.js} +1 -1
- package/dist/web/assets/{tabs-ChnOxkjp.js → tabs-BGqmAVYU.js} +1 -1
- package/dist/web/assets/{test-connection-AUx4zhwY.js → test-connection-nxVAS0Wx.js} +1 -1
- package/dist/web/assets/{toggle-group-BjRrXeJH.js → toggle-group-CCiYTSds.js} +1 -1
- package/dist/web/assets/{useMutation-BGhPR1Vu.js → useMutation-BA5lpPGT.js} +1 -1
- package/dist/web/assets/{webhook-sheet-DQJqHwl0.js → webhook-sheet-GvYXTrKI.js} +1 -1
- package/dist/web/assets/{webhooks-DS8Xc6Gc.js → webhooks-CkT7bLVO.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/instance-BEEO0AHU.js +0 -2
- package/dist/server-F3DTB7YC.js.map +0 -1
- package/dist/service-lHEFbRJQ.js +0 -333
- package/dist/service-lHEFbRJQ.js.map +0 -1
- package/dist/settings-DkA2sgzt.js.map +0 -1
- package/dist/settings-DoPS659W.js +0 -2
- package/dist/skill-BWWtinsE.js +0 -2
- package/dist/urls-CNYhbeUQ.js +0 -2
- package/dist/urls-DmnonkJo.js.map +0 -1
- package/dist/web/assets/index-C0ZXKtiq.css +0 -2
package/README.md
CHANGED
|
@@ -224,6 +224,27 @@ Only one agentinbox runs per data directory; a second one refuses to start.
|
|
|
224
224
|
|
|
225
225
|
When a newer version is published, the console shows **Update available** with the exact command to run.
|
|
226
226
|
|
|
227
|
+
The unit runs the Node.js binary you installed it with. If you remove or replace that Node, run `service install` again.
|
|
228
|
+
If the service doesn't come up, `service install` rolls back and prints where to look (`systemctl --user status
|
|
229
|
+
agentinbox`, `journalctl --user -u agentinbox`). Over `su` or `sudo -u` there is often no systemd user session: log
|
|
230
|
+
in as that user directly, or enable lingering and set `XDG_RUNTIME_DIR=/run/user/$(id -u)` first.
|
|
231
|
+
|
|
232
|
+
A service that hasn't been claimed yet doesn't print its setup token to the journal. Get the link with
|
|
233
|
+
`npx agentinbox-cli reset-password --data <dir>`, or read the token from `<data>/setup-token`.
|
|
234
|
+
|
|
235
|
+
### With your own supervisor
|
|
236
|
+
|
|
237
|
+
On other systems, or to manage it yourself (Docker, runit, supervisord, pm2), install the command and run it in the
|
|
238
|
+
foreground:
|
|
239
|
+
|
|
240
|
+
```sh
|
|
241
|
+
npm i -g agentinbox-cli
|
|
242
|
+
agentinbox start --no-open --data /var/lib/agentinbox
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Use the installed `agentinbox` binary rather than `npx`: npx doesn't pass stop signals on, so agentinbox wouldn't shut
|
|
246
|
+
down cleanly.
|
|
247
|
+
|
|
227
248
|
### Behind a reverse proxy
|
|
228
249
|
|
|
229
250
|
agentinbox serves plain HTTP. To expose it beyond your network, put it behind a TLS-terminating proxy (Caddy, nginx,
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { join, resolve } from "node:path";
|
|
5
|
-
|
|
6
|
-
import
|
|
4
|
+
import { join, resolve, sep } from "node:path";
|
|
5
|
+
//#region server/node-check.ts
|
|
6
|
+
/** The oldest Node.js agentinbox runs on (node:sqlite unflagged, import.meta.dirname). Keep in sync with package.json engines. */
|
|
7
|
+
const MIN_NODE = "22.13.0";
|
|
8
|
+
/** An explanation when `version` (e.g. process.versions.node) is too old, else null. */
|
|
9
|
+
function nodeVersionError(version) {
|
|
10
|
+
const parse = (v) => v.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10) || 0);
|
|
11
|
+
const have = parse(version);
|
|
12
|
+
const need = parse(MIN_NODE);
|
|
13
|
+
for (let i = 0; i < 3; i++) {
|
|
14
|
+
if ((have[i] ?? 0) > need[i]) return null;
|
|
15
|
+
if ((have[i] ?? 0) < need[i]) return `agentinbox needs Node.js 22.13 or newer (you have ${version.replace(/^v?/, "v")}). Install a current Node.js from https://nodejs.org and try again.`;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const problem = nodeVersionError(process.versions.node);
|
|
20
|
+
if (problem) {
|
|
21
|
+
console.error(problem);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
7
25
|
//#region server/cli.ts
|
|
26
|
+
const { Command, InvalidArgumentError } = await import("commander");
|
|
27
|
+
const { default: pc } = await import("picocolors");
|
|
28
|
+
process.title = "agentinbox";
|
|
8
29
|
const emitWarning = process.emitWarning.bind(process);
|
|
9
30
|
process.emitWarning = ((warning, ...rest) => {
|
|
10
31
|
const message = typeof warning === "string" ? warning : warning.message;
|
|
@@ -40,8 +61,9 @@ const configInput = (o) => ({
|
|
|
40
61
|
dataDir: o.data
|
|
41
62
|
});
|
|
42
63
|
const program = new Command("agentinbox").description("Self-hosted Gmail broker for AI agents: MCP tools, webhooks, guardrails and a web console.").version(version, "-v, --version", "print the version").helpOption("-h, --help", "show help").addHelpText("after", "\nWithout installing: npx agentinbox-cli [command]. To install the command: npm i -g agentinbox-cli").showSuggestionAfterError();
|
|
43
|
-
withServerOptions(program.command("start", { isDefault: true }).description("run agentinbox in the foreground (default)")).option("--no-open", "don't open a browser on first run").option("--dev", "development: API only, the console runs on Vite (:5173)").action(async (o) => {
|
|
44
|
-
|
|
64
|
+
withServerOptions(program.command("start", { isDefault: true }).description("run agentinbox in the foreground (default)")).option("--no-open", "don't open a browser on first run").option("--dev", "development: API only, the console runs on Vite (:5173)").allowExcessArguments().action(async (o, cmd) => {
|
|
65
|
+
if (cmd.args.length) throw new Error(unknownCommand(cmd.args[0]));
|
|
66
|
+
const { runForeground } = await import("./server-CL0omdA2.js");
|
|
45
67
|
await runForeground({
|
|
46
68
|
...configInput(o),
|
|
47
69
|
dev: !!o.dev,
|
|
@@ -52,43 +74,43 @@ withServerOptions(program.command("start", { isDefault: true }).description("run
|
|
|
52
74
|
const service = program.command("service").description("run agentinbox as a background service (systemd / launchd)");
|
|
53
75
|
withServerOptions(service.command("install").description("install and start the service; re-run to update")).action(async (o) => {
|
|
54
76
|
const { loadConfig } = await import("./config-CIvgMqLx.js");
|
|
55
|
-
const { installService } = await import("./service-
|
|
77
|
+
const { installService } = await import("./service-cxr2FxwM.js");
|
|
56
78
|
await installService(loadConfig(configInput(o), version));
|
|
57
79
|
});
|
|
58
|
-
service.command("uninstall").description("stop and remove the service (keeps your data)").option("-d, --data <dir>", "data directory (default ~/.agentinbox, env AGENTINBOX_DATA)").action(async (o) => {
|
|
59
|
-
const {
|
|
60
|
-
|
|
61
|
-
uninstallService(loadConfig(configInput(o), version));
|
|
80
|
+
service.command("uninstall").description("stop and remove the service (keeps your data)").option("-d, --data <dir>", "data directory, if the installed service doesn't say (default ~/.agentinbox, env AGENTINBOX_DATA)").action(async (o) => {
|
|
81
|
+
const { uninstallService } = await import("./service-cxr2FxwM.js");
|
|
82
|
+
uninstallService({ dataDir: resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), ".agentinbox")) });
|
|
62
83
|
});
|
|
63
84
|
service.command("status").description("show service status").action(async () => {
|
|
64
|
-
const { serviceStatus } = await import("./service-
|
|
85
|
+
const { serviceStatus } = await import("./service-cxr2FxwM.js");
|
|
65
86
|
serviceStatus();
|
|
66
87
|
});
|
|
67
88
|
const skill = program.command("skill").description("the agentinbox agent skill (SKILL.md)");
|
|
68
89
|
skill.command("print").description("print SKILL.md to stdout").option("--url <url>", "agentinbox server URL to fill in (env AGENTINBOX_URL)").action(async (o) => {
|
|
69
|
-
const { renderSkill } = await import("./skill-
|
|
70
|
-
process.stdout.write(renderSkill(serverUrl(o.url)));
|
|
90
|
+
const { renderSkill } = await import("./skill-BJFn2bHK.js");
|
|
91
|
+
process.stdout.write(renderSkill(await serverUrl(o.url)));
|
|
71
92
|
});
|
|
72
|
-
skill.command("install").description("install SKILL.md for an agent (no running server needed)").option("-t, --target <target>", "claude, codex, agents, or a skills directory", "claude").option("--url <url>", "agentinbox server URL agents connect to (env AGENTINBOX_URL)").action(async (o) => {
|
|
73
|
-
const { renderSkill, skillPath, writeSkill } = await import("./skill-
|
|
74
|
-
|
|
93
|
+
skill.command("install").description("install SKILL.md for an agent (no running server needed)").option("-t, --target <target>", "claude, codex, agents, or a skills directory path", "claude").option("--url <url>", "agentinbox server URL agents connect to (env AGENTINBOX_URL)").action(async (o) => {
|
|
94
|
+
const { renderSkill, SKILL_TARGETS, skillPath, writeSkill } = await import("./skill-BJFn2bHK.js");
|
|
95
|
+
checkSkillTarget(o.target, Object.keys(SKILL_TARGETS));
|
|
96
|
+
const url = await serverUrl(o.url);
|
|
75
97
|
const path = skillPath(o.target);
|
|
76
98
|
writeSkill(path, renderSkill(url));
|
|
77
99
|
console.log(`Installed the agentinbox skill to ${pc.cyan(path)} (server ${url}).`);
|
|
78
100
|
if (!o.url && !process.env.AGENTINBOX_URL) console.log(pc.dim("Agents on other machines need the server's address: re-run with --url https://your-server."));
|
|
79
101
|
});
|
|
80
|
-
|
|
102
|
+
program.command("reset-password").description("remove the admin password and print a new setup link").option("-d, --data <dir>", "data directory (default ~/.agentinbox, env AGENTINBOX_DATA)").option("-p, --port <port>", "port of the running instance, used for the printed link", parsePort).option("--host <host>", "host of the running instance, used for the printed link").action(async (o) => {
|
|
81
103
|
const dataDir = resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), ".agentinbox"));
|
|
82
104
|
const dbPath = join(dataDir, "agentinbox.db");
|
|
83
105
|
if (!existsSync(dbPath)) throw new Error(`No agentinbox data in ${dataDir}. If agentinbox runs as a system service, run this with sudo; otherwise pass the data directory it uses with --data.`);
|
|
84
106
|
const { loadConfig } = await import("./config-CIvgMqLx.js");
|
|
85
107
|
const { Db } = await import("./db-CXhlUuVP.js");
|
|
86
108
|
const { createBus } = await import("./bus-OKIGut72.js");
|
|
87
|
-
const { SettingsStore } = await import("./settings-
|
|
109
|
+
const { SettingsStore } = await import("./settings-BK7h99j7.js");
|
|
88
110
|
const { AuditLog } = await import("./audit-Bf3TvAAN.js");
|
|
89
111
|
const { currentSetupToken, isClaimed, resetAdminPassword } = await import("./auth-X5SGuNNB.js");
|
|
90
|
-
const { runningInstance } = await import("./instance-
|
|
91
|
-
const { consoleUrls } = await import("./urls-
|
|
112
|
+
const { runningInstance } = await import("./instance-CxS8D7b2.js");
|
|
113
|
+
const { consoleUrls } = await import("./urls-Dp8pBGMU.js");
|
|
92
114
|
const running = runningInstance(dataDir);
|
|
93
115
|
const config = loadConfig({
|
|
94
116
|
dataDir,
|
|
@@ -116,9 +138,22 @@ withServerOptions(program.command("reset-password").description("remove the admi
|
|
|
116
138
|
db.close();
|
|
117
139
|
}
|
|
118
140
|
});
|
|
119
|
-
/**
|
|
120
|
-
|
|
121
|
-
|
|
141
|
+
/**
|
|
142
|
+
* The URL written into SKILL.md: --url, AGENTINBOX_URL, else the agentinbox running on this
|
|
143
|
+
* machine (its lock file), else http://localhost:8425.
|
|
144
|
+
*/
|
|
145
|
+
async function serverUrl(flag) {
|
|
146
|
+
let raw = flag ?? process.env.AGENTINBOX_URL;
|
|
147
|
+
if (!raw) {
|
|
148
|
+
const { runningInstance } = await import("./instance-CxS8D7b2.js");
|
|
149
|
+
const running = runningInstance(resolve(process.env.AGENTINBOX_DATA || join(homedir(), ".agentinbox")));
|
|
150
|
+
const host = running && ![
|
|
151
|
+
"0.0.0.0",
|
|
152
|
+
"::",
|
|
153
|
+
""
|
|
154
|
+
].includes(running.host) ? running.host : "localhost";
|
|
155
|
+
raw = `http://${host.includes(":") ? `[${host}]` : host}:${running?.port || process.env.PORT || 8425}`;
|
|
156
|
+
}
|
|
122
157
|
let url;
|
|
123
158
|
try {
|
|
124
159
|
url = new URL(raw);
|
|
@@ -128,6 +163,48 @@ function serverUrl(flag) {
|
|
|
128
163
|
if (url.protocol !== "http:" && url.protocol !== "https:") throw new Error("--url must start with http:// or https://");
|
|
129
164
|
return (url.origin + url.pathname).replace(/\/+$/, "");
|
|
130
165
|
}
|
|
166
|
+
/** A known agent name, or something that is clearly a path; typos like "claud" are refused. */
|
|
167
|
+
function checkSkillTarget(target, known) {
|
|
168
|
+
if (known.includes(target) || target.includes("/") || target.includes(sep) || target.startsWith(".") || isDir(target)) return;
|
|
169
|
+
const near = closest(target, known);
|
|
170
|
+
throw new Error(`Unknown skill target "${target}".${near ? ` Did you mean ${near}?` : ""} Use ${known.join(", ")}, or a directory path such as ./skills.`);
|
|
171
|
+
}
|
|
172
|
+
function isDir(path) {
|
|
173
|
+
try {
|
|
174
|
+
return statSync(path).isDirectory();
|
|
175
|
+
} catch {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function unknownCommand(name) {
|
|
180
|
+
const near = closest(name, [...program.commands.map((c) => c.name()), "help"]);
|
|
181
|
+
return `unknown command '${name}'${near ? `\n(Did you mean ${near}?)` : ""}\nRun agentinbox --help for the list of commands.`;
|
|
182
|
+
}
|
|
183
|
+
/** The candidate within edit distance 2 (or a prefix match), if any. */
|
|
184
|
+
function closest(word, candidates) {
|
|
185
|
+
const distance = (a, b) => {
|
|
186
|
+
const row = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
187
|
+
for (let i = 1; i <= a.length; i++) {
|
|
188
|
+
let prev = row[0];
|
|
189
|
+
row[0] = i;
|
|
190
|
+
for (let j = 1; j <= b.length; j++) {
|
|
191
|
+
const cur = row[j];
|
|
192
|
+
row[j] = Math.min(row[j] + 1, row[j - 1] + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
193
|
+
prev = cur;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return row[b.length];
|
|
197
|
+
};
|
|
198
|
+
let best = null;
|
|
199
|
+
for (const c of candidates) {
|
|
200
|
+
const d = c.startsWith(word) && word.length >= 3 ? 0 : distance(word.toLowerCase(), c);
|
|
201
|
+
if (d <= 2 && (!best || d < best.d)) best = {
|
|
202
|
+
name: c,
|
|
203
|
+
d
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
return best?.name ?? null;
|
|
207
|
+
}
|
|
131
208
|
try {
|
|
132
209
|
await program.parseAsync(process.argv);
|
|
133
210
|
} catch (err) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","names":[],"sources":["../server/cli.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { Command, InvalidArgumentError } from \"commander\";\nimport pc from \"picocolors\";\n\n// node:sqlite is stable enough for us but still warns on Node 22. This runs before any server\n// module loads: everything that touches node:sqlite is imported dynamically below.\nconst emitWarning = process.emitWarning.bind(process);\nprocess.emitWarning = ((warning: string | Error, ...rest: unknown[]) => {\n const message = typeof warning === \"string\" ? warning : warning.message;\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type;\n if ((type === \"ExperimentalWarning\" || (warning as Error).name === \"ExperimentalWarning\") && /SQLite/i.test(message)) return;\n return (emitWarning as (...args: unknown[]) => void)(warning, ...rest);\n}) as typeof process.emitWarning;\n\n/** package.json sits one level above both dist/cli.js and server/cli.ts. */\nfunction packageVersion(): string {\n try {\n return (JSON.parse(readFileSync(join(import.meta.dirname, \"..\", \"package.json\"), \"utf8\")) as { version: string }).version;\n } catch {\n return \"0.0.0\";\n }\n}\n\nconst version = packageVersion();\n\ninterface ServerFlags {\n port?: number;\n host?: string;\n data?: string;\n}\n\nconst validPort = (value: string) => /^\\d+$/.test(value) && Number(value) <= 65535;\n\nfunction parsePort(value: string): number {\n if (!validPort(value)) throw new InvalidArgumentError(\"Port must be a number from 0 to 65535.\");\n return Number(value);\n}\n\n/** --port, else a validated PORT env (a typo there would otherwise become NaN deep inside). */\nfunction portOption(flag: number | undefined): number | undefined {\n if (flag !== undefined) return flag;\n const env = process.env.PORT?.trim();\n if (!env) return undefined;\n if (!validPort(env)) throw new Error(`PORT=\"${process.env.PORT}\" is not a valid port. Use a number from 0 to 65535.`);\n return Number(env);\n}\n\nconst withServerOptions = (cmd: Command) =>\n cmd\n .option(\"-p, --port <port>\", \"port to listen on (default 8425, env PORT)\", parsePort)\n .option(\"--host <host>\", \"bind address (default 0.0.0.0, env HOST)\")\n .option(\"-d, --data <dir>\", \"data directory (default ~/.agentinbox, env AGENTINBOX_DATA)\");\n\nconst configInput = (o: ServerFlags) => ({ port: portOption(o.port), host: o.host, dataDir: o.data });\n\nconst program = new Command(\"agentinbox\")\n .description(\"Self-hosted Gmail broker for AI agents: MCP tools, webhooks, guardrails and a web console.\")\n .version(version, \"-v, --version\", \"print the version\")\n .helpOption(\"-h, --help\", \"show help\")\n .addHelpText(\"after\", \"\\nWithout installing: npx agentinbox-cli [command]. To install the command: npm i -g agentinbox-cli\")\n .showSuggestionAfterError();\n\nwithServerOptions(program.command(\"start\", { isDefault: true }).description(\"run agentinbox in the foreground (default)\"))\n .option(\"--no-open\", \"don't open a browser on first run\")\n .option(\"--dev\", \"development: API only, the console runs on Vite (:5173)\")\n .action(async (o: ServerFlags & { open: boolean; dev?: boolean }) => {\n const { runForeground } = await import(\"./server.ts\");\n await runForeground({ ...configInput(o), dev: !!o.dev, open: o.open, version });\n });\n\nconst service = program.command(\"service\").description(\"run agentinbox as a background service (systemd / launchd)\");\n\nwithServerOptions(service.command(\"install\").description(\"install and start the service; re-run to update\")).action(async (o: ServerFlags) => {\n const { loadConfig } = await import(\"./config.ts\");\n const { installService } = await import(\"./service.ts\");\n await installService(loadConfig(configInput(o), version));\n});\n\nservice\n .command(\"uninstall\")\n .description(\"stop and remove the service (keeps your data)\")\n .option(\"-d, --data <dir>\", \"data directory (default ~/.agentinbox, env AGENTINBOX_DATA)\")\n .action(async (o: ServerFlags) => {\n const { loadConfig } = await import(\"./config.ts\");\n const { uninstallService } = await import(\"./service.ts\");\n uninstallService(loadConfig(configInput(o), version));\n });\n\nservice\n .command(\"status\")\n .description(\"show service status\")\n .action(async () => {\n const { serviceStatus } = await import(\"./service.ts\");\n serviceStatus();\n });\n\nconst skill = program.command(\"skill\").description(\"the agentinbox agent skill (SKILL.md)\");\n\nskill\n .command(\"print\")\n .description(\"print SKILL.md to stdout\")\n .option(\"--url <url>\", \"agentinbox server URL to fill in (env AGENTINBOX_URL)\")\n .action(async (o: { url?: string }) => {\n const { renderSkill } = await import(\"./skill/index.ts\");\n process.stdout.write(renderSkill(serverUrl(o.url)));\n });\n\nskill\n .command(\"install\")\n .description(\"install SKILL.md for an agent (no running server needed)\")\n .option(\"-t, --target <target>\", \"claude, codex, agents, or a skills directory\", \"claude\")\n .option(\"--url <url>\", \"agentinbox server URL agents connect to (env AGENTINBOX_URL)\")\n .action(async (o: { target: string; url?: string }) => {\n const { renderSkill, skillPath, writeSkill } = await import(\"./skill/index.ts\");\n const url = serverUrl(o.url);\n const path = skillPath(o.target);\n writeSkill(path, renderSkill(url));\n console.log(`Installed the agentinbox skill to ${pc.cyan(path)} (server ${url}).`);\n if (!o.url && !process.env.AGENTINBOX_URL) {\n console.log(pc.dim(\"Agents on other machines need the server's address: re-run with --url https://your-server.\"));\n }\n });\n\nwithServerOptions(program.command(\"reset-password\").description(\"remove the admin password and print a new setup link\")).action(\n async (o: ServerFlags) => {\n // Never create a data directory or master key here: a wrong --data (or a service running as\n // another user) must not silently produce a fresh instance.\n const dataDir = resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), \".agentinbox\"));\n const dbPath = join(dataDir, \"agentinbox.db\");\n if (!existsSync(dbPath)) {\n throw new Error(\n `No agentinbox data in ${dataDir}. If agentinbox runs as a system service, run this with sudo; ` +\n \"otherwise pass the data directory it uses with --data.\",\n );\n }\n const { loadConfig } = await import(\"./config.ts\");\n const { Db } = await import(\"./db/index.ts\");\n const { createBus } = await import(\"./bus.ts\");\n const { SettingsStore } = await import(\"./settings.ts\");\n const { AuditLog } = await import(\"./audit.ts\");\n const { currentSetupToken, isClaimed, resetAdminPassword } = await import(\"./auth/index.ts\");\n const { runningInstance } = await import(\"./instance.ts\");\n const { consoleUrls } = await import(\"./urls.ts\");\n\n const running = runningInstance(dataDir);\n const config = loadConfig(\n { dataDir, port: portOption(o.port) ?? running?.port, host: o.host ?? (process.env.HOST || running?.host) },\n version,\n );\n const db = new Db(dbPath);\n try {\n const bus = createBus();\n const core = { config, db, settings: new SettingsStore(db, bus, config), audit: new AuditLog(db, bus) };\n const claimed = isClaimed(core);\n const token = claimed ? resetAdminPassword(core) : currentSetupToken(core)!;\n console.log(\n claimed\n ? \"\\n The admin password was removed and all console sessions were signed out.\\n Open this link to set a new password:\\n\"\n : \"\\n This instance hasn't been claimed yet, so there is no password to reset.\\n Open this link to claim it:\\n\",\n );\n const urls = consoleUrls(config.host, config.port);\n const publicUrl = core.settings.publicUrl();\n if (!urls.includes(publicUrl)) urls.push(publicUrl);\n for (const url of urls) console.log(` ${pc.cyan(`${url}/setup?token=${token}`)}`);\n console.log(pc.dim(`\\n ${running ? \"The running agentinbox picks this up immediately; no restart needed.\" : \"Start agentinbox to use it.\"}\\n`));\n } finally {\n db.close();\n }\n },\n);\n\n/** The URL written into SKILL.md: --url, AGENTINBOX_URL, or this machine's default. */\nfunction serverUrl(flag: string | undefined): string {\n const raw = flag ?? process.env.AGENTINBOX_URL ?? `http://localhost:${process.env.PORT || 8425}`;\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error(`Invalid --url \"${raw}\". Use a full URL such as https://mail.example.com.`);\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error(\"--url must start with http:// or https://\");\n return (url.origin + url.pathname).replace(/\\/+$/, \"\");\n}\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n console.error(pc.red(err instanceof Error ? err.message : String(err)));\n if (process.env.AGENTINBOX_DEBUG && err instanceof Error) console.error(err.stack);\n process.exit(1);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cli.js","names":[],"sources":["../server/node-check.ts","../server/cli.ts"],"sourcesContent":["/** The oldest Node.js agentinbox runs on (node:sqlite unflagged, import.meta.dirname). Keep in sync with package.json engines. */\nexport const MIN_NODE = \"22.13.0\";\n\n/** An explanation when `version` (e.g. process.versions.node) is too old, else null. */\nexport function nodeVersionError(version: string): string | null {\n const parse = (v: string) => v.replace(/^v/, \"\").split(\".\").map((n) => Number.parseInt(n, 10) || 0);\n const have = parse(version);\n const need = parse(MIN_NODE);\n for (let i = 0; i < 3; i++) {\n if ((have[i] ?? 0) > need[i]!) return null;\n if ((have[i] ?? 0) < need[i]!) return `agentinbox needs Node.js 22.13 or newer (you have ${version.replace(/^v?/, \"v\")}). Install a current Node.js from https://nodejs.org and try again.`;\n }\n return null;\n}\n\n// Runs on import, before anything that needs a newer Node is loaded.\nconst problem = nodeVersionError(process.versions.node);\nif (problem) {\n console.error(problem);\n process.exit(1);\n}\n","// Must stay the first import: exits with a clear message on a too-old Node.\nimport \"./node-check.ts\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve, sep } from \"node:path\";\nimport type { Command as CommandType } from \"commander\";\n\n// Loaded after the Node check (static imports are hoisted above it in the bundle).\nconst { Command, InvalidArgumentError } = await import(\"commander\");\nconst { default: pc } = await import(\"picocolors\");\n\nprocess.title = \"agentinbox\";\n\n// node:sqlite is stable enough for us but still warns on Node 22. This runs before any server\n// module loads: everything that touches node:sqlite is imported dynamically below.\nconst emitWarning = process.emitWarning.bind(process);\nprocess.emitWarning = ((warning: string | Error, ...rest: unknown[]) => {\n const message = typeof warning === \"string\" ? warning : warning.message;\n const type = typeof rest[0] === \"string\" ? rest[0] : (rest[0] as { type?: string } | undefined)?.type;\n if ((type === \"ExperimentalWarning\" || (warning as Error).name === \"ExperimentalWarning\") && /SQLite/i.test(message)) return;\n return (emitWarning as (...args: unknown[]) => void)(warning, ...rest);\n}) as typeof process.emitWarning;\n\n/** package.json sits one level above both dist/cli.js and server/cli.ts. */\nfunction packageVersion(): string {\n try {\n return (JSON.parse(readFileSync(join(import.meta.dirname, \"..\", \"package.json\"), \"utf8\")) as { version: string }).version;\n } catch {\n return \"0.0.0\";\n }\n}\n\nconst version = packageVersion();\n\ninterface ServerFlags {\n port?: number;\n host?: string;\n data?: string;\n}\n\nconst validPort = (value: string) => /^\\d+$/.test(value) && Number(value) <= 65535;\n\nfunction parsePort(value: string): number {\n if (!validPort(value)) throw new InvalidArgumentError(\"Port must be a number from 0 to 65535.\");\n return Number(value);\n}\n\n/** --port, else a validated PORT env (a typo there would otherwise become NaN deep inside). */\nfunction portOption(flag: number | undefined): number | undefined {\n if (flag !== undefined) return flag;\n const env = process.env.PORT?.trim();\n if (!env) return undefined;\n if (!validPort(env)) throw new Error(`PORT=\"${process.env.PORT}\" is not a valid port. Use a number from 0 to 65535.`);\n return Number(env);\n}\n\nconst withServerOptions = (cmd: CommandType) =>\n cmd\n .option(\"-p, --port <port>\", \"port to listen on (default 8425, env PORT)\", parsePort)\n .option(\"--host <host>\", \"bind address (default 0.0.0.0, env HOST)\")\n .option(\"-d, --data <dir>\", \"data directory (default ~/.agentinbox, env AGENTINBOX_DATA)\");\n\nconst configInput = (o: ServerFlags) => ({ port: portOption(o.port), host: o.host, dataDir: o.data });\n\nconst program = new Command(\"agentinbox\")\n .description(\"Self-hosted Gmail broker for AI agents: MCP tools, webhooks, guardrails and a web console.\")\n .version(version, \"-v, --version\", \"print the version\")\n .helpOption(\"-h, --help\", \"show help\")\n .addHelpText(\"after\", \"\\nWithout installing: npx agentinbox-cli [command]. To install the command: npm i -g agentinbox-cli\")\n .showSuggestionAfterError();\n\nwithServerOptions(program.command(\"start\", { isDefault: true }).description(\"run agentinbox in the foreground (default)\"))\n .option(\"--no-open\", \"don't open a browser on first run\")\n .option(\"--dev\", \"development: API only, the console runs on Vite (:5173)\")\n // `agentinbox typo` lands here as an extra argument: report it as the unknown command it is.\n .allowExcessArguments()\n .action(async (o: ServerFlags & { open: boolean; dev?: boolean }, cmd: CommandType) => {\n if (cmd.args.length) throw new Error(unknownCommand(cmd.args[0]!));\n const { runForeground } = await import(\"./server.ts\");\n await runForeground({ ...configInput(o), dev: !!o.dev, open: o.open, version });\n });\n\nconst service = program.command(\"service\").description(\"run agentinbox as a background service (systemd / launchd)\");\n\nwithServerOptions(service.command(\"install\").description(\"install and start the service; re-run to update\")).action(async (o: ServerFlags) => {\n const { loadConfig } = await import(\"./config.ts\");\n const { installService } = await import(\"./service.ts\");\n await installService(loadConfig(configInput(o), version));\n});\n\nservice\n .command(\"uninstall\")\n .description(\"stop and remove the service (keeps your data)\")\n .option(\"-d, --data <dir>\", \"data directory, if the installed service doesn't say (default ~/.agentinbox, env AGENTINBOX_DATA)\")\n .action(async (o: ServerFlags) => {\n const { uninstallService } = await import(\"./service.ts\");\n // No loadConfig: uninstalling must not create a data directory.\n uninstallService({ dataDir: resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), \".agentinbox\")) });\n });\n\nservice\n .command(\"status\")\n .description(\"show service status\")\n .action(async () => {\n const { serviceStatus } = await import(\"./service.ts\");\n serviceStatus();\n });\n\nconst skill = program.command(\"skill\").description(\"the agentinbox agent skill (SKILL.md)\");\n\nskill\n .command(\"print\")\n .description(\"print SKILL.md to stdout\")\n .option(\"--url <url>\", \"agentinbox server URL to fill in (env AGENTINBOX_URL)\")\n .action(async (o: { url?: string }) => {\n const { renderSkill } = await import(\"./skill/index.ts\");\n process.stdout.write(renderSkill(await serverUrl(o.url)));\n });\n\nskill\n .command(\"install\")\n .description(\"install SKILL.md for an agent (no running server needed)\")\n .option(\"-t, --target <target>\", \"claude, codex, agents, or a skills directory path\", \"claude\")\n .option(\"--url <url>\", \"agentinbox server URL agents connect to (env AGENTINBOX_URL)\")\n .action(async (o: { target: string; url?: string }) => {\n const { renderSkill, SKILL_TARGETS, skillPath, writeSkill } = await import(\"./skill/index.ts\");\n checkSkillTarget(o.target, Object.keys(SKILL_TARGETS));\n const url = await serverUrl(o.url);\n const path = skillPath(o.target);\n writeSkill(path, renderSkill(url));\n console.log(`Installed the agentinbox skill to ${pc.cyan(path)} (server ${url}).`);\n if (!o.url && !process.env.AGENTINBOX_URL) {\n console.log(pc.dim(\"Agents on other machines need the server's address: re-run with --url https://your-server.\"));\n }\n });\n\nprogram\n .command(\"reset-password\")\n .description(\"remove the admin password and print a new setup link\")\n .option(\"-d, --data <dir>\", \"data directory (default ~/.agentinbox, env AGENTINBOX_DATA)\")\n .option(\"-p, --port <port>\", \"port of the running instance, used for the printed link\", parsePort)\n .option(\"--host <host>\", \"host of the running instance, used for the printed link\")\n .action(\n async (o: ServerFlags) => {\n // Never create a data directory or master key here: a wrong --data (or a service running as\n // another user) must not silently produce a fresh instance.\n const dataDir = resolve(o.data ?? process.env.AGENTINBOX_DATA ?? join(homedir(), \".agentinbox\"));\n const dbPath = join(dataDir, \"agentinbox.db\");\n if (!existsSync(dbPath)) {\n throw new Error(\n `No agentinbox data in ${dataDir}. If agentinbox runs as a system service, run this with sudo; ` +\n \"otherwise pass the data directory it uses with --data.\",\n );\n }\n const { loadConfig } = await import(\"./config.ts\");\n const { Db } = await import(\"./db/index.ts\");\n const { createBus } = await import(\"./bus.ts\");\n const { SettingsStore } = await import(\"./settings.ts\");\n const { AuditLog } = await import(\"./audit.ts\");\n const { currentSetupToken, isClaimed, resetAdminPassword } = await import(\"./auth/index.ts\");\n const { runningInstance } = await import(\"./instance.ts\");\n const { consoleUrls } = await import(\"./urls.ts\");\n\n const running = runningInstance(dataDir);\n const config = loadConfig(\n { dataDir, port: portOption(o.port) ?? running?.port, host: o.host ?? (process.env.HOST || running?.host) },\n version,\n );\n const db = new Db(dbPath);\n try {\n const bus = createBus();\n const core = { config, db, settings: new SettingsStore(db, bus, config), audit: new AuditLog(db, bus) };\n const claimed = isClaimed(core);\n const token = claimed ? resetAdminPassword(core) : currentSetupToken(core)!;\n console.log(\n claimed\n ? \"\\n The admin password was removed and all console sessions were signed out.\\n Open this link to set a new password:\\n\"\n : \"\\n This instance hasn't been claimed yet, so there is no password to reset.\\n Open this link to claim it:\\n\",\n );\n const urls = consoleUrls(config.host, config.port);\n const publicUrl = core.settings.publicUrl();\n if (!urls.includes(publicUrl)) urls.push(publicUrl);\n for (const url of urls) console.log(` ${pc.cyan(`${url}/setup?token=${token}`)}`);\n console.log(pc.dim(`\\n ${running ? \"The running agentinbox picks this up immediately; no restart needed.\" : \"Start agentinbox to use it.\"}\\n`));\n } finally {\n db.close();\n }\n },\n);\n\n/**\n * The URL written into SKILL.md: --url, AGENTINBOX_URL, else the agentinbox running on this\n * machine (its lock file), else http://localhost:8425.\n */\nasync function serverUrl(flag: string | undefined): Promise<string> {\n let raw = flag ?? process.env.AGENTINBOX_URL;\n if (!raw) {\n const { runningInstance } = await import(\"./instance.ts\");\n const running = runningInstance(resolve(process.env.AGENTINBOX_DATA || join(homedir(), \".agentinbox\")));\n const host = running && ![\"0.0.0.0\", \"::\", \"\"].includes(running.host) ? running.host : \"localhost\";\n raw = `http://${host.includes(\":\") ? `[${host}]` : host}:${running?.port || process.env.PORT || 8425}`;\n }\n let url: URL;\n try {\n url = new URL(raw);\n } catch {\n throw new Error(`Invalid --url \"${raw}\". Use a full URL such as https://mail.example.com.`);\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") throw new Error(\"--url must start with http:// or https://\");\n return (url.origin + url.pathname).replace(/\\/+$/, \"\");\n}\n\n/** A known agent name, or something that is clearly a path; typos like \"claud\" are refused. */\nfunction checkSkillTarget(target: string, known: string[]): void {\n if (known.includes(target) || target.includes(\"/\") || target.includes(sep) || target.startsWith(\".\") || isDir(target)) return;\n const near = closest(target, known);\n throw new Error(\n `Unknown skill target \"${target}\".${near ? ` Did you mean ${near}?` : \"\"} Use ${known.join(\", \")}, or a directory path such as ./skills.`,\n );\n}\n\nfunction isDir(path: string): boolean {\n try {\n return statSync(path).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction unknownCommand(name: string): string {\n const near = closest(name, [...program.commands.map((c) => c.name()), \"help\"]);\n return `unknown command '${name}'${near ? `\\n(Did you mean ${near}?)` : \"\"}\\nRun agentinbox --help for the list of commands.`;\n}\n\n/** The candidate within edit distance 2 (or a prefix match), if any. */\nfunction closest(word: string, candidates: string[]): string | null {\n const distance = (a: string, b: string) => {\n const row = Array.from({ length: b.length + 1 }, (_, j) => j);\n for (let i = 1; i <= a.length; i++) {\n let prev = row[0]!;\n row[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const cur = row[j]!;\n row[j] = Math.min(row[j]! + 1, row[j - 1]! + 1, prev + (a[i - 1] === b[j - 1] ? 0 : 1));\n prev = cur;\n }\n }\n return row[b.length]!;\n };\n let best: { name: string; d: number } | null = null;\n for (const c of candidates) {\n const d = c.startsWith(word) && word.length >= 3 ? 0 : distance(word.toLowerCase(), c);\n if (d <= 2 && (!best || d < best.d)) best = { name: c, d };\n }\n return best?.name ?? null;\n}\n\ntry {\n await program.parseAsync(process.argv);\n} catch (err) {\n console.error(pc.red(err instanceof Error ? err.message : String(err)));\n if (process.env.AGENTINBOX_DEBUG && err instanceof Error) console.error(err.stack);\n process.exit(1);\n}\n"],"mappings":"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"}
|