bazilion 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/cli.js +811 -250
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +4778 -1461
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +21 -0
- package/dist/web/client/assets/{ProductionTeamPolicyEditor-CSL3W7XM.js → ProductionTeamPolicyEditor-DdpYInwV.js} +1 -1
- package/dist/web/client/assets/{ProfileCommunicationEditor-CwU0QkmE.js → ProfileCommunicationEditor-BcSf2Hao.js} +1 -1
- package/dist/web/client/assets/{TeamTabs-C1Hakkff.js → TeamTabs-Bk89JfN7.js} +1 -1
- package/dist/web/client/assets/{TemplatesTabs-klEydJ8-.js → TemplatesTabs-CyDVzrOl.js} +1 -1
- package/dist/web/client/assets/{_id-CnVq-rED.js → _id-CAJTTnee.js} +1 -1
- package/dist/web/client/assets/{_id-wkjjWLz0.js → _id-CN6jPaBu.js} +1 -1
- package/dist/web/client/assets/{_id-BOC7ioJu.js → _id-DGwJqqDc.js} +1 -1
- package/dist/web/client/assets/{_id-e4u7dmBb.js → _id-DWTMH7Eb.js} +1 -1
- package/dist/web/client/assets/{activity-uqhwzmiy.js → activity-DK_M0-bn.js} +1 -1
- package/dist/web/client/assets/{agents-B2usE-L_.js → agents-B-i5pASm.js} +1 -1
- package/dist/web/client/assets/{agents-FaQtkAWs.js → agents-n8U7qNxw.js} +1 -1
- package/dist/web/client/assets/{approvals-DqLE6ttw.js → approvals-CmVxCy0Z.js} +1 -1
- package/dist/web/client/assets/{attention-CkGozYnJ.js → attention-F0lUQCWE.js} +1 -1
- package/dist/web/client/assets/chevron-down-OndG7r1U.js +1 -0
- package/dist/web/client/assets/config-DuApZ9xS.js +3 -0
- package/dist/web/client/assets/{context-ZWqx3uiC.js → context-C1sMnW6K.js} +1 -1
- package/dist/web/client/assets/dm-sans-latin-400-normal-BwCSEQnW.woff +0 -0
- package/dist/web/client/assets/dm-sans-latin-400-normal-CW0RaeGs.woff2 +0 -0
- package/dist/web/client/assets/dm-sans-latin-500-normal-B9HHJjqV.woff2 +0 -0
- package/dist/web/client/assets/dm-sans-latin-500-normal-Dr3UlScf.woff +0 -0
- package/dist/web/client/assets/dm-sans-latin-600-normal-Aqo67rzb.woff2 +0 -0
- package/dist/web/client/assets/dm-sans-latin-600-normal-BmdmIIQ2.woff +0 -0
- package/dist/web/client/assets/dm-sans-latin-700-normal-CUSSCpQX.woff +0 -0
- package/dist/web/client/assets/dm-sans-latin-700-normal-DvUfVpUG.woff2 +0 -0
- package/dist/web/client/assets/dm-serif-display-latin-400-normal-C5_t9oOD.woff2 +0 -0
- package/dist/web/client/assets/dm-serif-display-latin-400-normal-_kVFYEpx.woff +0 -0
- package/dist/web/client/assets/{inbox-BoIvl9ZF.js → inbox-D2NypLee.js} +1 -1
- package/dist/web/client/assets/{index-nb2MV8X1.js → index-B3vdrEEg.js} +4 -4
- package/dist/web/client/assets/index-Cofc7zhl.css +1 -0
- package/dist/web/client/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/web/client/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/web/client/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/web/client/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/web/client/assets/{learning-6_oYn1l7.js → learning-zYDCfVxT.js} +1 -1
- package/dist/web/client/assets/{login-DM1ytxQL.js → login-B1Un51Zx.js} +1 -1
- package/dist/web/client/assets/{mcp-CetZbyUh.js → mcp-DSVmJBdv.js} +1 -1
- package/dist/web/client/assets/{members-DdqWtwZd.js → members-Pl7hXJcN.js} +1 -1
- package/dist/web/client/assets/{memory-FNrxFHmC.js → memory-Co3BEaAq.js} +1 -1
- package/dist/web/client/assets/plus-Dor-_wmL.js +1 -0
- package/dist/web/client/assets/{policy-BKPejYRI.js → policy-CHM95pMU.js} +1 -1
- package/dist/web/client/assets/{routes-CH1ZTTo-.js → routes-D29qjwG0.js} +1 -1
- package/dist/web/client/assets/{services-zk9SqN06.js → services-CCQ_6YWQ.js} +1 -1
- package/dist/web/client/assets/{skills-tXDpomHW.js → skills-3xAIvzvP.js} +1 -1
- package/dist/web/client/assets/styles-D6RPN7RK.css +2 -0
- package/dist/web/client/assets/{teams-BZYjekBN.js → teams-Dm_huGxn.js} +1 -1
- package/dist/web/client/assets/{teams-D1c8zlxs.js → teams-UGLyjHYj.js} +1 -1
- package/dist/web/client/assets/telegram-3KvrJVO6.js +1 -0
- package/dist/web/client/assets/tokens-DUSFmV5_.js +1 -0
- package/dist/web/client/assets/{triggers-D8R-5guA.js → triggers-DlQ2KF1h.js} +1 -1
- package/dist/web/client/assets/{welcome-CuK0shDJ.js → welcome-DkP8qzK1.js} +1 -1
- package/dist/web/server/assets/{_id-CwyGjJeP.js → _id-BENqNBfK.js} +4 -4
- package/dist/web/server/assets/{_id-D3Ap7zZA.js → _id-BFELaMIN.js} +1 -1
- package/dist/web/server/assets/{_id-LrvXU4Nr.js → _id-BQ2zoMiR.js} +1 -1
- package/dist/web/server/assets/{_id-D27T85mU.js → _id-BZWunvy7.js} +4 -4
- package/dist/web/server/assets/{_id-BHYLL8M-.js → _id-BreRHYV2.js} +1 -1
- package/dist/web/server/assets/{_id-C3HY4lWg.js → _id-CPIXIqyO.js} +1 -1
- package/dist/web/server/assets/{_id-FcHdSocl.js → _id-CvYqVJPU.js} +4 -4
- package/dist/web/server/assets/{_id-DinTp_7X.js → _id-DkrNqqTw.js} +3 -3
- package/dist/web/server/assets/{_id-IzadFZV9.js → _id-DvlDkk04.js} +4 -4
- package/dist/web/server/assets/{_id-BhOB8Umi.js → _id-DxCnEFpm.js} +4 -4
- package/dist/web/server/assets/{_id-tB47Vsfp.js → _id-HMy7jM3P.js} +3 -3
- package/dist/web/server/assets/{_id-Dj1yZ3zJ.js → _id-xTD_6ApX.js} +4 -4
- package/dist/web/server/assets/{_tanstack-start-manifest_v-fLsYERQ-.js → _tanstack-start-manifest_v-COkJjXt_.js} +50 -49
- package/dist/web/server/assets/{activity-DohitgwW.js → activity-9VP6QDTH.js} +3 -3
- package/dist/web/server/assets/{activity-BCI4mfNS.js → activity-B6N1T_5N.js} +1 -1
- package/dist/web/server/assets/{activity-D9SMqBhy.js → activity-BazZNfvf.js} +3 -3
- package/dist/web/server/assets/{agents-BY74v7fM.js → agents-BJAv919x.js} +3 -3
- package/dist/web/server/assets/{agents-C9xlWK0Z.js → agents-BpSeOA30.js} +4 -4
- package/dist/web/server/assets/{agents-BvttypqB.js → agents-DY630p6x.js} +3 -3
- package/dist/web/server/assets/{agents-DZuFEj0D.js → agents-DfoLnTyD.js} +1 -1
- package/dist/web/server/assets/{agents-BPKOshR5.js → agents-DjyQk94u.js} +4 -4
- package/dist/web/server/assets/{agents-CgZMHj80.js → agents-wSYNPuyK.js} +1 -1
- package/dist/web/server/assets/{approvals-DCaVw1Mz.js → approvals-BYajNOdE.js} +1 -1
- package/dist/web/server/assets/{approvals-BGU-XGIO.js → approvals-BYi84gwl.js} +3 -3
- package/dist/web/server/assets/{approvals-CWcFHlor.js → approvals-BkUGmYU9.js} +3 -3
- package/dist/web/server/assets/{attention-BxkTf337.js → attention-Bw_wiiqI.js} +3 -3
- package/dist/web/server/assets/{attention-CM-Ks1N9.js → attention-UhqPK_Ro.js} +3 -3
- package/dist/web/server/assets/{attention-w21GQIGH.js → attention-Z3bGuxOD.js} +1 -1
- package/dist/web/server/assets/{auth-byfSx6Ja.js → auth-7BHTH-KS.js} +5 -5
- package/dist/web/server/assets/{config-BDCJdtj2.js → config-BMiajTZP.js} +10 -5
- package/dist/web/server/assets/{config-D2LAsud2.js → config-DGzM28F_.js} +211 -27
- package/dist/web/server/assets/{config-TeIoyYYc.js → config-wYtIhkRm.js} +3 -3
- package/dist/web/server/assets/context-BkDDwbby.js +12 -0
- package/dist/web/server/assets/context-DMc0KyHh.js +12 -0
- package/dist/web/server/assets/{context-DrkrIWun.js → context-poimKI7w.js} +1 -1
- package/dist/web/server/assets/{createServerRpc-pU-IQV2Y.js → createServerRpc-B7Yr1K8i.js} +1 -1
- package/dist/web/server/assets/{createSsrRpc-DFsIAfFd.js → createSsrRpc-6LHNEsSK.js} +1 -1
- package/dist/web/server/assets/{daemon-client-2NRMzlTr.js → daemon-client-CI5NHwNC.js} +16 -4
- package/dist/web/server/assets/{inbox-ZvDNAjaM.js → inbox-0iiSg-Y1.js} +4 -4
- package/dist/web/server/assets/{inbox-BLUzA5sQ.js → inbox-DTTfSuGU.js} +1 -1
- package/dist/web/server/assets/{inbox-CzlKT9Wg.js → inbox-Dv55rGYq.js} +4 -4
- package/dist/web/server/assets/{learning-8zav4pIT.js → learning-C2upa1CE.js} +4 -4
- package/dist/web/server/assets/{learning-B7PBkvER.js → learning-DpyLNVe8.js} +4 -4
- package/dist/web/server/assets/{learning-Cq7K2heb.js → learning-fG8316uc.js} +1 -1
- package/dist/web/server/assets/{login-Bx5LEyGP.js → login-CrFVVUaE.js} +1 -1
- package/dist/web/server/assets/{login-CmWvxfTK.js → login-D_GDeTrB.js} +7 -7
- package/dist/web/server/assets/{mcp-DIWTogHM.js → mcp-BQtp2T87.js} +3 -3
- package/dist/web/server/assets/{mcp-2pwT9HU8.js → mcp-BvnvlVFd.js} +3 -3
- package/dist/web/server/assets/{mcp-BJjLIdP0.js → mcp-DlgXUcAS.js} +1 -1
- package/dist/web/server/assets/members-BP3UTqu1.js +12 -0
- package/dist/web/server/assets/{members-CCv17cjQ.js → members-CteHKPSF.js} +1 -1
- package/dist/web/server/assets/members-DXu2oAS_.js +12 -0
- package/dist/web/server/assets/{memory-Dngc13Nw.js → memory-BqV-Afy1.js} +4 -4
- package/dist/web/server/assets/{memory-a8Kz57Kh.js → memory-C6fX_FKI.js} +1 -1
- package/dist/web/server/assets/{memory-pZ4pZT7p.js → memory-Iq2M0-Yc.js} +4 -4
- package/dist/web/server/assets/{policy-Bb-vEgqg.js → policy-18fdTFO4.js} +3 -3
- package/dist/web/server/assets/{policy-BcGELcc9.js → policy-Bg6u-rTq.js} +1 -1
- package/dist/web/server/assets/{policy-C30AeFIb.js → policy-D7kj3Cy7.js} +3 -3
- package/dist/web/server/assets/public-origin-xV0lm0Ty.js +25 -0
- package/dist/web/server/assets/{router-CQuj7553.js → router-D-6TzLRZ.js} +168 -65
- package/dist/web/server/assets/{routes-BrA-U_Hm.js → routes-CNRzy79H.js} +4 -4
- package/dist/web/server/assets/{routes-B6cMLIPk.js → routes-CiPfEldd.js} +1 -1
- package/dist/web/server/assets/{routes-C19CMLZt.js → routes-D933ngZS.js} +4 -4
- package/dist/web/server/assets/{services-B9yBWDX0.js → services-DJRA1A0-.js} +1 -1
- package/dist/web/server/assets/{services-wG8I06oS.js → services-DozuJtzX.js} +3 -3
- package/dist/web/server/assets/{services-C4szdhPx.js → services-OB4LAr2A.js} +3 -3
- package/dist/web/server/assets/{skills-BZdqiDig.js → skills-Babb9jsQ.js} +1 -1
- package/dist/web/server/assets/{skills-C-UgkuCW.js → skills-D5DQL8bM.js} +3 -3
- package/dist/web/server/assets/{skills-a9VSWHWq.js → skills-DfGSJTCB.js} +3 -3
- package/dist/web/server/assets/start-uKQNK6if.js +70 -0
- package/dist/web/server/assets/{teams-CpQ0YgWf.js → teams-Bk6ZT0MD.js} +1 -1
- package/dist/web/server/assets/{teams-jBtvnk59.js → teams-Cc2Czynq.js} +1 -1
- package/dist/web/server/assets/{teams-DqfrEoH6.js → teams-DPnAX4wD.js} +4 -4
- package/dist/web/server/assets/{teams-DEpQR2QA.js → teams-DqC4wZxu.js} +3 -3
- package/dist/web/server/assets/{teams-OIkHuxy1.js → teams-Dz6ZEMRo.js} +3 -3
- package/dist/web/server/assets/{teams-MjqgsmC3.js → teams-be05ci17.js} +3 -3
- package/dist/web/server/assets/{telegram-DNgCWebD.js → telegram-1AWL6lFw.js} +3 -3
- package/dist/web/server/assets/{telegram-CBF8SJzB.js → telegram-DUbDIVGX.js} +122 -3
- package/dist/web/server/assets/{telegram-XwyKSEtj.js → telegram-J4T0XhwQ.js} +3 -3
- package/dist/web/server/assets/{tokens-yyTSfBSN.js → tokens-CJM_0NDa.js} +126 -22
- package/dist/web/server/assets/{tokens-BnwFbV7T.js → tokens-DO5BzNOn.js} +4 -4
- package/dist/web/server/assets/tokens-DjM8GsgS.js +19 -0
- package/dist/web/server/assets/{triggers-CSNNzRIi.js → triggers-B87fycBl.js} +1 -1
- package/dist/web/server/assets/{triggers-BZPl5CHs.js → triggers-BdBx-HwR.js} +4 -4
- package/dist/web/server/assets/{triggers-D79NoSXk.js → triggers-Nezfw-Bd.js} +4 -4
- package/dist/web/server/assets/{welcome-IYHGurWx.js → welcome-DDB11L5j.js} +2 -2
- package/dist/web/server/server.js +30 -30
- package/dist/web-server.js +4 -0
- package/dist/web-server.js.map +1 -1
- package/dist/worker.js +1982 -537
- package/dist/worker.js.map +1 -1
- package/package.json +7 -6
- package/dist/web/client/assets/chevron-down-CJk0zGNT.js +0 -1
- package/dist/web/client/assets/config-xrXoDEWM.js +0 -3
- package/dist/web/client/assets/plus-C3GroITC.js +0 -1
- package/dist/web/client/assets/styles-DMltY3su.css +0 -2
- package/dist/web/client/assets/telegram-DCe1CWMt.js +0 -1
- package/dist/web/client/assets/tokens-DAPjRS0N.js +0 -1
- package/dist/web/server/assets/context-B-XDf6Ym.js +0 -12
- package/dist/web/server/assets/context-BXGo5Vfi.js +0 -12
- package/dist/web/server/assets/members-CW5aBe81.js +0 -12
- package/dist/web/server/assets/members-VdPwD6CE.js +0 -12
- package/dist/web/server/assets/start-WH8WzTL_.js +0 -4
- package/dist/web/server/assets/tokens-DPDMSN5O.js +0 -12
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { defineCommand as
|
|
4
|
+
import { defineCommand as defineCommand28, runCommand, showUsage } from "citty";
|
|
5
5
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "bazilion",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.13.0",
|
|
10
10
|
description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/teams/skills, and run the local daemon.",
|
|
11
11
|
license: "MIT",
|
|
12
12
|
repository: {
|
|
@@ -49,15 +49,16 @@ var package_default = {
|
|
|
49
49
|
access: "public"
|
|
50
50
|
},
|
|
51
51
|
dependencies: {
|
|
52
|
-
"@earendil-works/pi-agent-core": "0.
|
|
53
|
-
"@earendil-works/pi-ai": "0.
|
|
54
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
52
|
+
"@earendil-works/pi-agent-core": "0.84.3",
|
|
53
|
+
"@earendil-works/pi-ai": "0.84.3",
|
|
54
|
+
"@earendil-works/pi-coding-agent": "0.84.3",
|
|
55
55
|
"@hono/node-server": "^2.0.6",
|
|
56
56
|
"@mozilla/readability": "^0.6.0",
|
|
57
57
|
"@playwright/browser-chromium": "^1.61.0",
|
|
58
58
|
"@tanstack/react-router": "1.170.16",
|
|
59
59
|
"@tobilu/qmd": "^2.5.3",
|
|
60
60
|
"adm-zip": "^0.5.17",
|
|
61
|
+
"age-encryption": "0.3.0",
|
|
61
62
|
citty: "^0.2.2",
|
|
62
63
|
dompurify: "^3.4.11",
|
|
63
64
|
grammy: "^1.44.0",
|
|
@@ -96,15 +97,17 @@ async function resolveToken(src) {
|
|
|
96
97
|
}
|
|
97
98
|
function createClient(cfg) {
|
|
98
99
|
async function authHeaders() {
|
|
99
|
-
const token = await resolveToken(cfg.token);
|
|
100
|
+
const token = cfg.token === null ? null : await resolveToken(cfg.token);
|
|
101
|
+
const extra = typeof cfg.headers === "function" ? await cfg.headers() : cfg.headers ?? {};
|
|
100
102
|
return {
|
|
101
|
-
authorization: `Bearer ${token}
|
|
103
|
+
...token ? { authorization: `Bearer ${token}` } : {},
|
|
102
104
|
// Astro 6 enabled `security.checkOrigin` by default for server mode:
|
|
103
105
|
// any state-changing request without an `Origin` matching the server
|
|
104
106
|
// host is rejected with 403. Browsers set this automatically; `fetch`
|
|
105
107
|
// in Node / React Native does not. Stamping the server's own URL is
|
|
106
108
|
// always valid for a legitimate client.
|
|
107
|
-
origin: cfg.serverUrl
|
|
109
|
+
origin: cfg.serverUrl,
|
|
110
|
+
...extra
|
|
108
111
|
};
|
|
109
112
|
}
|
|
110
113
|
async function request(method, path, body) {
|
|
@@ -229,15 +232,15 @@ function columnize(rows, gap = " ") {
|
|
|
229
232
|
if (rows.length === 0) return [];
|
|
230
233
|
const colCount = rows[0]?.length ?? 0;
|
|
231
234
|
const widths = new Array(colCount).fill(0);
|
|
232
|
-
for (const
|
|
235
|
+
for (const row2 of rows) {
|
|
233
236
|
for (let i = 0; i < colCount; i++) {
|
|
234
|
-
const cell =
|
|
237
|
+
const cell = row2[i] ?? "";
|
|
235
238
|
const prev = widths[i] ?? 0;
|
|
236
239
|
if (cell.length > prev) widths[i] = cell.length;
|
|
237
240
|
}
|
|
238
241
|
}
|
|
239
242
|
return rows.map(
|
|
240
|
-
(
|
|
243
|
+
(row2) => row2.map((cell, i) => {
|
|
241
244
|
if (i === colCount - 1) return cell;
|
|
242
245
|
return (cell ?? "").padEnd(widths[i] ?? 0);
|
|
243
246
|
}).join(gap)
|
|
@@ -1339,7 +1342,7 @@ var attentionCommand = defineCommand3({
|
|
|
1339
1342
|
});
|
|
1340
1343
|
|
|
1341
1344
|
// src/commands/auth.ts
|
|
1342
|
-
import {
|
|
1345
|
+
import { openaiCodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
|
|
1343
1346
|
import { defineCommand as defineCommand4 } from "citty";
|
|
1344
1347
|
function formatExpiry(ms) {
|
|
1345
1348
|
if (!ms) return "(unknown)";
|
|
@@ -1355,20 +1358,28 @@ var openaiLoginCmd = defineCommand4({
|
|
|
1355
1358
|
const client = createClient2();
|
|
1356
1359
|
console.log("opening your browser for OpenAI sign-in...");
|
|
1357
1360
|
console.log("(if it doesn't open automatically, paste the URL shown below)");
|
|
1358
|
-
const
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1361
|
+
const oauth = openaiCodexProvider().auth.oauth;
|
|
1362
|
+
if (!oauth) throw new Error("Pi openai-codex provider does not expose OAuth");
|
|
1363
|
+
const loginController = new AbortController();
|
|
1364
|
+
const creds = await oauth.login({
|
|
1365
|
+
signal: loginController.signal,
|
|
1366
|
+
notify: (event) => {
|
|
1367
|
+
if (event.type === "auth_url") {
|
|
1368
|
+
console.log("");
|
|
1369
|
+
console.log(` \u2192 ${event.url}`);
|
|
1370
|
+
console.log("");
|
|
1371
|
+
} else if (event.type === "progress" || event.type === "info") {
|
|
1372
|
+
console.log(` ${event.message}`);
|
|
1373
|
+
} else if (event.type === "device_code") {
|
|
1374
|
+
console.log(` open ${event.verificationUri} and enter ${event.userCode}`);
|
|
1375
|
+
}
|
|
1363
1376
|
},
|
|
1364
|
-
|
|
1377
|
+
prompt: async (prompt) => {
|
|
1378
|
+
if (prompt.type === "select") return prompt.options[0]?.id ?? "";
|
|
1365
1379
|
process.stdout.write(`${prompt.message}: `);
|
|
1366
1380
|
return new Promise((resolve4) => {
|
|
1367
1381
|
process.stdin.once("data", (d) => resolve4(String(d).trim()));
|
|
1368
1382
|
});
|
|
1369
|
-
},
|
|
1370
|
-
onProgress: (msg) => {
|
|
1371
|
-
console.log(` ${msg}`);
|
|
1372
1383
|
}
|
|
1373
1384
|
});
|
|
1374
1385
|
const status = await client.put("/api/auth/openai", {
|
|
@@ -1438,11 +1449,20 @@ var authCommand = defineCommand4({
|
|
|
1438
1449
|
});
|
|
1439
1450
|
|
|
1440
1451
|
// src/commands/backup.ts
|
|
1441
|
-
import {
|
|
1452
|
+
import {
|
|
1453
|
+
createCipheriv,
|
|
1454
|
+
createDecipheriv,
|
|
1455
|
+
createHash as createHash3,
|
|
1456
|
+
pbkdf2Sync,
|
|
1457
|
+
randomBytes,
|
|
1458
|
+
randomUUID as randomUUID2
|
|
1459
|
+
} from "crypto";
|
|
1442
1460
|
import {
|
|
1443
1461
|
chmodSync as chmodSync2,
|
|
1444
1462
|
closeSync as closeSync2,
|
|
1445
1463
|
copyFileSync,
|
|
1464
|
+
cpSync,
|
|
1465
|
+
createReadStream,
|
|
1446
1466
|
createWriteStream,
|
|
1447
1467
|
existsSync as existsSync2,
|
|
1448
1468
|
fsyncSync as fsyncSync2,
|
|
@@ -1452,21 +1472,24 @@ import {
|
|
|
1452
1472
|
openSync as openSync2,
|
|
1453
1473
|
readdirSync,
|
|
1454
1474
|
readFileSync as readFileSync4,
|
|
1475
|
+
readSync,
|
|
1455
1476
|
renameSync as renameSync2,
|
|
1456
|
-
rmSync as rmSync2
|
|
1477
|
+
rmSync as rmSync2,
|
|
1478
|
+
writeFileSync as writeFileSync2
|
|
1457
1479
|
} from "fs";
|
|
1458
1480
|
import { tmpdir } from "os";
|
|
1459
1481
|
import { basename as basename3, dirname as dirname2, isAbsolute, parse, posix, relative, resolve as resolve2 } from "path";
|
|
1460
|
-
import { DatabaseSync } from "node:sqlite";
|
|
1482
|
+
import { DatabaseSync, backup as sqliteBackup } from "node:sqlite";
|
|
1461
1483
|
import { Readable } from "stream";
|
|
1462
1484
|
import { pipeline } from "stream/promises";
|
|
1485
|
+
import { Decrypter, Encrypter } from "age-encryption";
|
|
1463
1486
|
import { defineCommand as defineCommand5 } from "citty";
|
|
1464
1487
|
import { extract, list as list3 } from "tar";
|
|
1465
1488
|
|
|
1466
1489
|
// src/backup-schema.ts
|
|
1467
1490
|
import { createHash } from "crypto";
|
|
1468
1491
|
var CANONICAL_MIGRATION = "0001_init";
|
|
1469
|
-
var CANONICAL_SCHEMA_HASH = "
|
|
1492
|
+
var CANONICAL_SCHEMA_HASH = "4bde209eb0bf9851bf1f01fc96263f165a1799c81e720ddea463169a0d6c0d51";
|
|
1470
1493
|
var CANONICAL_OBJECTS = [
|
|
1471
1494
|
["index", "agent_triggers_agent"],
|
|
1472
1495
|
["index", "agent_triggers_enabled"],
|
|
@@ -1491,6 +1514,8 @@ var CANONICAL_OBJECTS = [
|
|
|
1491
1514
|
["index", "trigger_dispatches_claimable"],
|
|
1492
1515
|
["index", "trigger_dispatches_trigger_time"],
|
|
1493
1516
|
["index", "web_tokens_active"],
|
|
1517
|
+
["index", "web_sessions_active"],
|
|
1518
|
+
["index", "web_sessions_device"],
|
|
1494
1519
|
["table", "agent_skills"],
|
|
1495
1520
|
["table", "agent_loop_break_events"],
|
|
1496
1521
|
["table", "agent_lesson_proposals"],
|
|
@@ -1525,9 +1550,11 @@ var CANONICAL_OBJECTS = [
|
|
|
1525
1550
|
["table", "team_templates"],
|
|
1526
1551
|
["table", "teams"],
|
|
1527
1552
|
["table", "telegram_allowed_users"],
|
|
1553
|
+
["table", "telegram_pairing_challenge"],
|
|
1528
1554
|
["table", "template_instantiations"],
|
|
1529
1555
|
["table", "trigger_dispatches"],
|
|
1530
1556
|
["table", "web_tokens"],
|
|
1557
|
+
["table", "web_sessions"],
|
|
1531
1558
|
["trigger", "create_team_policy"],
|
|
1532
1559
|
["trigger", "prevent_detached_team_policy_delete"],
|
|
1533
1560
|
["trigger", "validate_source_binding_insert"],
|
|
@@ -1543,7 +1570,7 @@ function assertCanonicalBackupSchema(db) {
|
|
|
1543
1570
|
const migrations = db.prepare("SELECT version FROM schema_migrations ORDER BY version").all();
|
|
1544
1571
|
if (migrations.length !== 1 || migrations[0]?.version !== CANONICAL_MIGRATION) {
|
|
1545
1572
|
throw new Error(
|
|
1546
|
-
`schema_migrations must contain exactly ${CANONICAL_MIGRATION}; found ` + (migrations.map((
|
|
1573
|
+
`schema_migrations must contain exactly ${CANONICAL_MIGRATION}; found ` + (migrations.map((row2) => row2.version).join(", ") || "none")
|
|
1547
1574
|
);
|
|
1548
1575
|
}
|
|
1549
1576
|
const rows = db.prepare(
|
|
@@ -1551,20 +1578,20 @@ function assertCanonicalBackupSchema(db) {
|
|
|
1551
1578
|
FROM sqlite_schema
|
|
1552
1579
|
WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite_%'`
|
|
1553
1580
|
).all();
|
|
1554
|
-
const byKey = new Map(rows.map((
|
|
1581
|
+
const byKey = new Map(rows.map((row2) => [`${row2.type}\0${row2.name}`, row2]));
|
|
1555
1582
|
const canonicalKeys = new Set(CANONICAL_OBJECTS.map(([type, name]) => `${type}\0${name}`));
|
|
1556
|
-
for (const
|
|
1557
|
-
if (!canonicalKeys.has(`${
|
|
1558
|
-
throw new Error(`unexpected schema ${
|
|
1583
|
+
for (const row2 of rows) {
|
|
1584
|
+
if (!canonicalKeys.has(`${row2.type}\0${row2.name}`)) {
|
|
1585
|
+
throw new Error(`unexpected schema ${row2.type} is not canonical: ${row2.name}`);
|
|
1559
1586
|
}
|
|
1560
1587
|
}
|
|
1561
1588
|
const canonicalRows = [];
|
|
1562
1589
|
for (const [type, name] of CANONICAL_OBJECTS) {
|
|
1563
|
-
const
|
|
1564
|
-
if (!
|
|
1565
|
-
canonicalRows.push(
|
|
1590
|
+
const row2 = byKey.get(`${type}\0${name}`);
|
|
1591
|
+
if (!row2) throw new Error(`required canonical schema ${type} is missing: ${name}`);
|
|
1592
|
+
canonicalRows.push(row2);
|
|
1566
1593
|
}
|
|
1567
|
-
const payload = canonicalRows.map((
|
|
1594
|
+
const payload = canonicalRows.map((row2) => [row2.type, row2.name, row2.tbl_name, normalizeSql(row2.sql)].join("\0")).join("\n");
|
|
1568
1595
|
const actualHash = createHash("sha256").update(payload).digest("hex");
|
|
1569
1596
|
if (actualHash !== CANONICAL_SCHEMA_HASH) {
|
|
1570
1597
|
throw new Error(
|
|
@@ -1880,18 +1907,34 @@ async function acquireHomeRestoreLock(home) {
|
|
|
1880
1907
|
|
|
1881
1908
|
// src/commands/backup.ts
|
|
1882
1909
|
var createCmd = defineCommand5({
|
|
1883
|
-
meta: { name: "create", description: "
|
|
1910
|
+
meta: { name: "create", description: "Create a client-side encrypted backup of ~/.bazilion" },
|
|
1884
1911
|
args: {
|
|
1885
1912
|
output: {
|
|
1886
1913
|
type: "positional",
|
|
1887
1914
|
required: false,
|
|
1888
|
-
description: "Output
|
|
1915
|
+
description: "Output path (default: .tar.gz.age with --recipient, otherwise .tar.gz)"
|
|
1916
|
+
},
|
|
1917
|
+
recipient: {
|
|
1918
|
+
type: "string",
|
|
1919
|
+
description: "age recipient (age1\u2026 or age1pq1\u2026); encrypts before writing output"
|
|
1920
|
+
},
|
|
1921
|
+
plaintext: {
|
|
1922
|
+
type: "boolean",
|
|
1923
|
+
description: "Explicitly permit a sensitive unencrypted .tar.gz backup"
|
|
1889
1924
|
}
|
|
1890
1925
|
},
|
|
1891
1926
|
async run({ args }) {
|
|
1927
|
+
if (args.recipient && args.plaintext) {
|
|
1928
|
+
throw new Error("--recipient and --plaintext are mutually exclusive");
|
|
1929
|
+
}
|
|
1930
|
+
if (!args.recipient && !args.plaintext) {
|
|
1931
|
+
throw new Error("choose --recipient <age1\u2026> for encryption or explicitly pass --plaintext");
|
|
1932
|
+
}
|
|
1892
1933
|
const cfg = loadClientConfig();
|
|
1893
1934
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1894
|
-
const
|
|
1935
|
+
const defaultSuffix = args.recipient ? ".tar.gz.age" : ".tar.gz";
|
|
1936
|
+
const outAbs = resolve2(args.output ?? `bazilion-backup-${date}${defaultSuffix}`);
|
|
1937
|
+
if (existsSync2(outAbs)) throw new Error(`refusing to overwrite existing backup: ${outAbs}`);
|
|
1895
1938
|
const configuredHome = resolve2(resolveCliPaths().home);
|
|
1896
1939
|
const outputFromHome = relative(configuredHome, outAbs);
|
|
1897
1940
|
if (!outputFromHome || !outputFromHome.startsWith("..") && !isAbsolute(outputFromHome)) {
|
|
@@ -1899,7 +1942,10 @@ var createCmd = defineCommand5({
|
|
|
1899
1942
|
`backup output must be outside BAZILION_HOME (${configuredHome}) to avoid nesting backups`
|
|
1900
1943
|
);
|
|
1901
1944
|
}
|
|
1902
|
-
|
|
1945
|
+
if (!args.recipient) {
|
|
1946
|
+
console.warn("warning: creating a plaintext backup containing all Bazilion credentials");
|
|
1947
|
+
}
|
|
1948
|
+
console.log(`${args.recipient ? "encrypting" : "downloading"} backup \u2192 ${outAbs}`);
|
|
1903
1949
|
const res = await fetch(`${cfg.serverUrl}/api/backup`, {
|
|
1904
1950
|
headers: { authorization: `Bearer ${cfg.token}`, origin: cfg.serverUrl }
|
|
1905
1951
|
});
|
|
@@ -1915,11 +1961,25 @@ var createCmd = defineCommand5({
|
|
|
1915
1961
|
const downloadDir = mkdtempSync(resolve2(tmpdir(), "bazilion-download-"));
|
|
1916
1962
|
const partial = resolve2(downloadDir, "backup.tar.gz");
|
|
1917
1963
|
try {
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1964
|
+
if (args.recipient) {
|
|
1965
|
+
const [encryptSource, validateSource] = res.body.tee();
|
|
1966
|
+
const encrypter = new Encrypter();
|
|
1967
|
+
encrypter.addRecipient(args.recipient);
|
|
1968
|
+
const encrypted = await encrypter.encrypt(encryptSource);
|
|
1969
|
+
await Promise.all([
|
|
1970
|
+
pipeline(
|
|
1971
|
+
Readable.fromWeb(encrypted),
|
|
1972
|
+
createWriteStream(partial, { flags: "wx", mode: 384 })
|
|
1973
|
+
),
|
|
1974
|
+
validateArchiveReadable(Readable.fromWeb(validateSource))
|
|
1975
|
+
]);
|
|
1976
|
+
} else {
|
|
1977
|
+
await pipeline(
|
|
1978
|
+
Readable.fromWeb(res.body),
|
|
1979
|
+
createWriteStream(partial, { flags: "wx", mode: 384 })
|
|
1980
|
+
);
|
|
1981
|
+
}
|
|
1982
|
+
if (!args.recipient) await validateArchive(partial);
|
|
1923
1983
|
try {
|
|
1924
1984
|
renameSync2(partial, outAbs);
|
|
1925
1985
|
} catch (error) {
|
|
@@ -2049,6 +2109,27 @@ async function validateArchive(file) {
|
|
|
2049
2109
|
entries.push({ path, type: entry2.type, linkpath: entry2.linkpath });
|
|
2050
2110
|
}
|
|
2051
2111
|
});
|
|
2112
|
+
return validateArchiveEntries(entries);
|
|
2113
|
+
}
|
|
2114
|
+
async function validateArchiveReadable(stream) {
|
|
2115
|
+
const entries = [];
|
|
2116
|
+
const parser = list3({
|
|
2117
|
+
strict: true,
|
|
2118
|
+
onentry(entry2) {
|
|
2119
|
+
if (entry2.meta) return;
|
|
2120
|
+
const path = normalizeArchivePath(entry2.path);
|
|
2121
|
+
if (!path) return;
|
|
2122
|
+
if (!EXTRACTABLE_ENTRY_TYPES.has(entry2.type)) {
|
|
2123
|
+
throw new Error(`backup contains unsupported ${entry2.type} entry: ${path}`);
|
|
2124
|
+
}
|
|
2125
|
+
if (entry2.type === "SymbolicLink") validateArchiveSymbolicLink(path, entry2.linkpath);
|
|
2126
|
+
entries.push({ path, type: entry2.type, linkpath: entry2.linkpath });
|
|
2127
|
+
}
|
|
2128
|
+
});
|
|
2129
|
+
await pipeline(stream, parser);
|
|
2130
|
+
return validateArchiveEntries(entries);
|
|
2131
|
+
}
|
|
2132
|
+
function validateArchiveEntries(entries) {
|
|
2052
2133
|
const byPath = /* @__PURE__ */ new Map();
|
|
2053
2134
|
for (const entry2 of entries) {
|
|
2054
2135
|
if (byPath.has(entry2.path)) throw new Error(`backup contains a duplicate path: ${entry2.path}`);
|
|
@@ -2107,7 +2188,7 @@ function validateDatabase(path, authToken) {
|
|
|
2107
2188
|
db = new DatabaseSync(path, { readOnly: true });
|
|
2108
2189
|
const integrity = db.prepare("PRAGMA integrity_check").all();
|
|
2109
2190
|
if (integrity.length !== 1 || integrity[0]?.integrity_check !== "ok") {
|
|
2110
|
-
const detail = integrity.map((
|
|
2191
|
+
const detail = integrity.map((row2) => row2.integrity_check).join("; ") || "no result";
|
|
2111
2192
|
throw new Error(`integrity_check failed: ${detail}`);
|
|
2112
2193
|
}
|
|
2113
2194
|
const foreignKeyErrors = db.prepare("PRAGMA foreign_key_check").all();
|
|
@@ -2118,7 +2199,7 @@ function validateDatabase(path, authToken) {
|
|
|
2118
2199
|
const tokenHash = createHash3("sha256").update(authToken).digest("hex");
|
|
2119
2200
|
const activeBootstrap = db.prepare(
|
|
2120
2201
|
`SELECT 1 FROM web_tokens
|
|
2121
|
-
WHERE token_hash = ? AND
|
|
2202
|
+
WHERE token_hash = ? AND kind = 'bootstrap' AND revoked_at IS NULL
|
|
2122
2203
|
LIMIT 1`
|
|
2123
2204
|
).get(tokenHash);
|
|
2124
2205
|
if (!activeBootstrap) {
|
|
@@ -2181,8 +2262,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2181
2262
|
const collection = table;
|
|
2182
2263
|
const stagedRoot = resolve2(payload, collection);
|
|
2183
2264
|
const targetRoot = resolve2(targetHome, collection);
|
|
2184
|
-
for (const
|
|
2185
|
-
const id = validateEntityId(
|
|
2265
|
+
for (const row2 of rows) {
|
|
2266
|
+
const id = validateEntityId(row2.id, idPattern, `${table} row`);
|
|
2186
2267
|
const rowLabel = `${table} row ${JSON.stringify(id)}`;
|
|
2187
2268
|
const stagedDir = containedChildDirectory(stagedRoot, id, rowLabel);
|
|
2188
2269
|
requireExtractedDirectory(stagedDir, rowLabel);
|
|
@@ -2194,8 +2275,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2194
2275
|
}
|
|
2195
2276
|
}
|
|
2196
2277
|
const stagedTeamsRoot = resolve2(payload, "teams");
|
|
2197
|
-
for (const
|
|
2198
|
-
const id = validateEntityId(
|
|
2278
|
+
for (const row2 of teams) {
|
|
2279
|
+
const id = validateEntityId(row2.id, SLUG_ID, "teams row");
|
|
2199
2280
|
const rowLabel = `teams row ${JSON.stringify(id)}`;
|
|
2200
2281
|
requireExtractedTeamSlot(containedChildDirectory(stagedTeamsRoot, id, rowLabel), rowLabel);
|
|
2201
2282
|
}
|
|
@@ -2216,8 +2297,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2216
2297
|
const readProfile = db.prepare("SELECT dir FROM profiles WHERE id = ?");
|
|
2217
2298
|
const readAgent = db.prepare("SELECT dir FROM agents WHERE id = ?");
|
|
2218
2299
|
for (const rewrite of rewrites) {
|
|
2219
|
-
const
|
|
2220
|
-
if (
|
|
2300
|
+
const row2 = rewrite.table === "profiles" ? readProfile.get(rewrite.id) : readAgent.get(rewrite.id);
|
|
2301
|
+
if (row2?.dir !== rewrite.dir) {
|
|
2221
2302
|
throw new Error(
|
|
2222
2303
|
`could not verify rebased ${rewrite.table} row ${JSON.stringify(rewrite.id)}`
|
|
2223
2304
|
);
|
|
@@ -2255,6 +2336,14 @@ function removeRebuildableQmdIndexes(payload) {
|
|
|
2255
2336
|
}
|
|
2256
2337
|
}
|
|
2257
2338
|
}
|
|
2339
|
+
function revokeRestoredBrowserSessions(database) {
|
|
2340
|
+
const db = new DatabaseSync(database);
|
|
2341
|
+
try {
|
|
2342
|
+
db.prepare("UPDATE web_sessions SET revoked_at = ? WHERE revoked_at IS NULL").run(Date.now());
|
|
2343
|
+
} finally {
|
|
2344
|
+
db.close();
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2258
2347
|
function installValidatedPayload(payload, targetHome, staging, lifecycle, operations = { rename: renameSync2 }) {
|
|
2259
2348
|
const previous = resolve2(staging, "previous-home");
|
|
2260
2349
|
const hadPrevious = existsSync2(targetHome);
|
|
@@ -2368,6 +2457,37 @@ function fsyncDirectory(path) {
|
|
|
2368
2457
|
if (fd !== null) closeSync2(fd);
|
|
2369
2458
|
}
|
|
2370
2459
|
}
|
|
2460
|
+
function fsyncFile(path) {
|
|
2461
|
+
const fd = openSync2(path, "r");
|
|
2462
|
+
try {
|
|
2463
|
+
fsyncSync2(fd);
|
|
2464
|
+
} finally {
|
|
2465
|
+
closeSync2(fd);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
var AGE_HEADER = Buffer.from("age-encryption.org/v1\n", "ascii");
|
|
2469
|
+
function isAgeEncrypted(path) {
|
|
2470
|
+
const fd = openSync2(path, "r");
|
|
2471
|
+
try {
|
|
2472
|
+
const header = Buffer.alloc(AGE_HEADER.length);
|
|
2473
|
+
return readSync(fd, header, 0, header.length, 0) === header.length && header.equals(AGE_HEADER);
|
|
2474
|
+
} finally {
|
|
2475
|
+
closeSync2(fd);
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
function readAgeIdentity(rawPath) {
|
|
2479
|
+
const path = resolve2(rawPath);
|
|
2480
|
+
const entry2 = lstatSync2(path);
|
|
2481
|
+
if (!entry2.isFile()) throw new Error(`age identity is not a regular file: ${path}`);
|
|
2482
|
+
if (process.platform !== "win32" && (entry2.mode & 63) !== 0) {
|
|
2483
|
+
throw new Error(`age identity must be owner-only (chmod 600): ${path}`);
|
|
2484
|
+
}
|
|
2485
|
+
const identities = readFileSync4(path, "utf8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
2486
|
+
if (identities.length !== 1 || !identities[0]?.startsWith("AGE-SECRET-KEY-")) {
|
|
2487
|
+
throw new Error("age identity file must contain exactly one supported AGE-SECRET-KEY entry");
|
|
2488
|
+
}
|
|
2489
|
+
return identities[0];
|
|
2490
|
+
}
|
|
2371
2491
|
var restoreCmd = defineCommand5({
|
|
2372
2492
|
meta: {
|
|
2373
2493
|
name: "restore",
|
|
@@ -2383,6 +2503,10 @@ var restoreCmd = defineCommand5({
|
|
|
2383
2503
|
force: {
|
|
2384
2504
|
type: "boolean",
|
|
2385
2505
|
description: "Overwrite existing non-empty home (destroys existing data)"
|
|
2506
|
+
},
|
|
2507
|
+
identity: {
|
|
2508
|
+
type: "string",
|
|
2509
|
+
description: "Path to an age identity file required for encrypted backups"
|
|
2386
2510
|
}
|
|
2387
2511
|
},
|
|
2388
2512
|
async run({ args }) {
|
|
@@ -2423,7 +2547,36 @@ var restoreCmd = defineCommand5({
|
|
|
2423
2547
|
const payload = resolve2(staging, "payload");
|
|
2424
2548
|
let preserveStaging = false;
|
|
2425
2549
|
try {
|
|
2426
|
-
|
|
2550
|
+
if (isAgeEncrypted(file)) {
|
|
2551
|
+
if (!args.identity) {
|
|
2552
|
+
throw new Error("encrypted backup requires --identity <owner-only age identity file>");
|
|
2553
|
+
}
|
|
2554
|
+
const identity = readAgeIdentity(args.identity);
|
|
2555
|
+
const decrypter = new Decrypter();
|
|
2556
|
+
decrypter.addIdentity(identity);
|
|
2557
|
+
let decrypted;
|
|
2558
|
+
try {
|
|
2559
|
+
decrypted = await decrypter.decrypt(
|
|
2560
|
+
Readable.toWeb(createReadStream(file))
|
|
2561
|
+
);
|
|
2562
|
+
} catch {
|
|
2563
|
+
throw new Error("backup decryption failed: wrong identity or invalid encrypted header");
|
|
2564
|
+
}
|
|
2565
|
+
try {
|
|
2566
|
+
await pipeline(
|
|
2567
|
+
Readable.fromWeb(decrypted),
|
|
2568
|
+
createWriteStream(stagedArchive, { flags: "wx", mode: 384 })
|
|
2569
|
+
);
|
|
2570
|
+
} catch {
|
|
2571
|
+
throw new Error("backup decryption failed: ciphertext is truncated or modified");
|
|
2572
|
+
}
|
|
2573
|
+
} else {
|
|
2574
|
+
if (args.identity) {
|
|
2575
|
+
throw new Error("encrypted-only restore requested, but the backup is plaintext");
|
|
2576
|
+
}
|
|
2577
|
+
copyFileSync(file, stagedArchive);
|
|
2578
|
+
chmodSync2(stagedArchive, 384);
|
|
2579
|
+
}
|
|
2427
2580
|
await validateArchive(stagedArchive);
|
|
2428
2581
|
mkdirSync2(payload);
|
|
2429
2582
|
await extract({
|
|
@@ -2445,6 +2598,7 @@ var restoreCmd = defineCommand5({
|
|
|
2445
2598
|
const authToken = validateAuthFile(authFile);
|
|
2446
2599
|
validateDatabase(database, authToken);
|
|
2447
2600
|
rebaseRestoredHomeDirectories(database, payload, targetHome);
|
|
2601
|
+
revokeRestoredBrowserSessions(database);
|
|
2448
2602
|
validateDatabase(database, authToken);
|
|
2449
2603
|
removeRebuildableQmdIndexes(payload);
|
|
2450
2604
|
console.log(`installing validated backup ${file} \u2192 ${targetHome}`);
|
|
@@ -2475,11 +2629,200 @@ var restoreCmd = defineCommand5({
|
|
|
2475
2629
|
console.log("start the server with: bazilion serve (migrations apply automatically)");
|
|
2476
2630
|
}
|
|
2477
2631
|
});
|
|
2632
|
+
function decryptSecretEnvelope(raw, password) {
|
|
2633
|
+
const envelope = JSON.parse(raw);
|
|
2634
|
+
const key = pbkdf2Sync(password, Buffer.from(envelope.salt, "hex"), 1e5, 32, "sha256");
|
|
2635
|
+
const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(envelope.iv, "hex"));
|
|
2636
|
+
decipher.setAuthTag(Buffer.from(envelope.tag, "hex"));
|
|
2637
|
+
return Buffer.concat([
|
|
2638
|
+
decipher.update(Buffer.from(envelope.data, "hex")),
|
|
2639
|
+
decipher.final()
|
|
2640
|
+
]).toString("utf8");
|
|
2641
|
+
}
|
|
2642
|
+
function encryptSecretEnvelope(value, password) {
|
|
2643
|
+
const salt = randomBytes(16);
|
|
2644
|
+
const key = pbkdf2Sync(password, salt, 1e5, 32, "sha256");
|
|
2645
|
+
const iv = randomBytes(12);
|
|
2646
|
+
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
2647
|
+
const data = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
|
|
2648
|
+
return JSON.stringify({
|
|
2649
|
+
salt: salt.toString("hex"),
|
|
2650
|
+
iv: iv.toString("hex"),
|
|
2651
|
+
tag: cipher.getAuthTag().toString("hex"),
|
|
2652
|
+
data: data.toString("hex")
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
function credentialInventory(home) {
|
|
2656
|
+
const authFile = resolve2(home, "auth.json");
|
|
2657
|
+
const database = resolve2(home, "bazilion.db");
|
|
2658
|
+
const token = validateAuthFile(authFile);
|
|
2659
|
+
validateDatabase(database, token);
|
|
2660
|
+
const db = new DatabaseSync(database, { readOnly: true });
|
|
2661
|
+
try {
|
|
2662
|
+
const activeTokens = db.prepare(
|
|
2663
|
+
"SELECT COUNT(*) AS count FROM web_tokens WHERE revoked_at IS NULL AND kind = 'device' AND expires_at > ?"
|
|
2664
|
+
).get(Date.now());
|
|
2665
|
+
const secretKeys = db.prepare("SELECT key FROM secrets ORDER BY key").all().map((row2) => row2.key);
|
|
2666
|
+
return { bootstrap: true, activeTokens: activeTokens.count, secretKeys };
|
|
2667
|
+
} finally {
|
|
2668
|
+
db.close();
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
var inventoryCmd = defineCommand5({
|
|
2672
|
+
meta: { name: "inventory", description: "List credential classes captured by a backup/home" },
|
|
2673
|
+
args: { home: { type: "string", description: "Override BAZILION_HOME" } },
|
|
2674
|
+
run({ args }) {
|
|
2675
|
+
const home = resolve2(resolveCliPaths(args.home).home);
|
|
2676
|
+
const inventory = credentialInventory(home);
|
|
2677
|
+
console.log("credential classes present (values are never shown):");
|
|
2678
|
+
console.log(` bootstrap token: ${inventory.bootstrap ? "present" : "missing"}`);
|
|
2679
|
+
console.log(` active device/web/mobile tokens: ${inventory.activeTokens}`);
|
|
2680
|
+
for (const key of inventory.secretKeys) console.log(` stored secret: ${key}`);
|
|
2681
|
+
}
|
|
2682
|
+
});
|
|
2683
|
+
var recoveryGuideCmd = defineCommand5({
|
|
2684
|
+
meta: { name: "recovery-guide", description: "Print the credential-exposure recovery checklist" },
|
|
2685
|
+
run() {
|
|
2686
|
+
console.log("Bazilion credential exposure recovery:");
|
|
2687
|
+
console.log("1. Stop the Bazilion daemon and preserve the suspected archive for investigation.");
|
|
2688
|
+
console.log(
|
|
2689
|
+
"2. Run `bazilion backup inventory`, then `bazilion backup rotate-bootstrap --yes`."
|
|
2690
|
+
);
|
|
2691
|
+
console.log("3. Regenerate the Telegram bot token with BotFather and save the replacement.");
|
|
2692
|
+
console.log(
|
|
2693
|
+
"4. Disconnect/revoke the affected OpenAI session or grant, then authenticate again."
|
|
2694
|
+
);
|
|
2695
|
+
console.log("5. Rotate every provider or MCP credential named by the inventory.");
|
|
2696
|
+
console.log("6. Create and verify a fresh recipient-encrypted backup after external rotation.");
|
|
2697
|
+
console.log(
|
|
2698
|
+
"Local bootstrap rotation does not revoke copied Telegram/OpenAI/provider credentials."
|
|
2699
|
+
);
|
|
2700
|
+
}
|
|
2701
|
+
});
|
|
2702
|
+
var rotateBootstrapCmd = defineCommand5({
|
|
2703
|
+
meta: {
|
|
2704
|
+
name: "rotate-bootstrap",
|
|
2705
|
+
description: "Offline crash-safe bootstrap rotation; revokes every other local token"
|
|
2706
|
+
},
|
|
2707
|
+
args: {
|
|
2708
|
+
home: { type: "string", description: "Override BAZILION_HOME" },
|
|
2709
|
+
yes: { type: "boolean", required: true, description: "Confirm token revocation and home swap" }
|
|
2710
|
+
},
|
|
2711
|
+
async run({ args }) {
|
|
2712
|
+
if (!args.yes) throw new Error("--yes is required");
|
|
2713
|
+
const paths = resolveCliPaths(args.home);
|
|
2714
|
+
const targetHome = resolve2(paths.home);
|
|
2715
|
+
if (targetHome === parse(targetHome).root) {
|
|
2716
|
+
throw new Error(`refusing to rotate filesystem root: ${targetHome}`);
|
|
2717
|
+
}
|
|
2718
|
+
const lock = await acquireHomeRestoreLock(targetHome);
|
|
2719
|
+
const parent = dirname2(targetHome);
|
|
2720
|
+
const staging = mkdtempSync(resolve2(parent, ".bazilion-rotate-"));
|
|
2721
|
+
const payload = resolve2(staging, "payload");
|
|
2722
|
+
let preserveStaging = false;
|
|
2723
|
+
try {
|
|
2724
|
+
for (const serverUrl of configuredLoopbackUrls()) {
|
|
2725
|
+
if (await probeServerRunning(serverUrl)) {
|
|
2726
|
+
throw new Error(`bazilion server appears to be running at ${serverUrl} \u2014 stop it first.`);
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
const oldAuth = JSON.parse(readFileSync4(paths.authFile, "utf8"));
|
|
2730
|
+
if (typeof oldAuth.token !== "string" || !oldAuth.token) {
|
|
2731
|
+
throw new Error("auth.json is missing the bootstrap token");
|
|
2732
|
+
}
|
|
2733
|
+
validateDatabase(resolve2(targetHome, "bazilion.db"), oldAuth.token);
|
|
2734
|
+
cpSync(targetHome, payload, {
|
|
2735
|
+
recursive: true,
|
|
2736
|
+
dereference: false,
|
|
2737
|
+
verbatimSymlinks: true,
|
|
2738
|
+
preserveTimestamps: true
|
|
2739
|
+
});
|
|
2740
|
+
const stagedDb = resolve2(payload, "bazilion.db");
|
|
2741
|
+
rmSync2(stagedDb, { force: true });
|
|
2742
|
+
const sourceDb = new DatabaseSync(resolve2(targetHome, "bazilion.db"), { readOnly: true });
|
|
2743
|
+
try {
|
|
2744
|
+
await sqliteBackup(sourceDb, stagedDb);
|
|
2745
|
+
} finally {
|
|
2746
|
+
sourceDb.close();
|
|
2747
|
+
}
|
|
2748
|
+
for (const suffix of ["-wal", "-shm", "-journal"])
|
|
2749
|
+
rmSync2(`${stagedDb}${suffix}`, { force: true });
|
|
2750
|
+
const newToken = randomBytes(24).toString("hex");
|
|
2751
|
+
const db = new DatabaseSync(stagedDb);
|
|
2752
|
+
try {
|
|
2753
|
+
db.exec("PRAGMA foreign_keys = ON; BEGIN IMMEDIATE");
|
|
2754
|
+
try {
|
|
2755
|
+
const rows = db.prepare("SELECT key, envelope FROM secrets ORDER BY key").all();
|
|
2756
|
+
const updateSecret = db.prepare(
|
|
2757
|
+
"UPDATE secrets SET envelope = ?, updated_at = ? WHERE key = ?"
|
|
2758
|
+
);
|
|
2759
|
+
for (const row2 of rows) {
|
|
2760
|
+
let value;
|
|
2761
|
+
try {
|
|
2762
|
+
value = decryptSecretEnvelope(row2.envelope, oldAuth.token);
|
|
2763
|
+
} catch {
|
|
2764
|
+
throw new Error(`stored secret is unreadable and rotation was aborted: ${row2.key}`);
|
|
2765
|
+
}
|
|
2766
|
+
updateSecret.run(encryptSecretEnvelope(value, newToken), Date.now(), row2.key);
|
|
2767
|
+
}
|
|
2768
|
+
const oldHash = createHash3("sha256").update(oldAuth.token).digest("hex");
|
|
2769
|
+
const newHash = createHash3("sha256").update(newToken).digest("hex");
|
|
2770
|
+
const bootstrap = db.prepare(
|
|
2771
|
+
"UPDATE web_tokens SET token_hash = ?, last_used_at = NULL, revoked_at = NULL WHERE token_hash = ? AND kind = 'bootstrap' AND revoked_at IS NULL"
|
|
2772
|
+
).run(newHash, oldHash);
|
|
2773
|
+
if (bootstrap.changes !== 1) throw new Error("active bootstrap token row was not unique");
|
|
2774
|
+
const revokedAt = Date.now();
|
|
2775
|
+
db.prepare(
|
|
2776
|
+
"UPDATE web_tokens SET revoked_at = ? WHERE kind != 'bootstrap' AND revoked_at IS NULL"
|
|
2777
|
+
).run(revokedAt);
|
|
2778
|
+
db.prepare("UPDATE web_sessions SET revoked_at = ? WHERE revoked_at IS NULL").run(
|
|
2779
|
+
revokedAt
|
|
2780
|
+
);
|
|
2781
|
+
db.exec("COMMIT");
|
|
2782
|
+
} catch (error) {
|
|
2783
|
+
db.exec("ROLLBACK");
|
|
2784
|
+
throw error;
|
|
2785
|
+
}
|
|
2786
|
+
} finally {
|
|
2787
|
+
db.close();
|
|
2788
|
+
}
|
|
2789
|
+
const stagedAuth = resolve2(payload, "auth.json");
|
|
2790
|
+
const authPartial = resolve2(payload, `.auth.json.${randomUUID2()}.installing`);
|
|
2791
|
+
writeFileSync2(authPartial, `${JSON.stringify({ ...oldAuth, token: newToken }, null, 2)}
|
|
2792
|
+
`, {
|
|
2793
|
+
mode: 384,
|
|
2794
|
+
flag: "wx"
|
|
2795
|
+
});
|
|
2796
|
+
renameSync2(authPartial, stagedAuth);
|
|
2797
|
+
chmodSync2(stagedAuth, 384);
|
|
2798
|
+
validateDatabase(stagedDb, newToken);
|
|
2799
|
+
const verification = credentialInventory(payload);
|
|
2800
|
+
if (!verification.bootstrap) throw new Error("rotated credential inventory is invalid");
|
|
2801
|
+
fsyncFile(stagedDb);
|
|
2802
|
+
fsyncFile(stagedAuth);
|
|
2803
|
+
fsyncDirectory(payload);
|
|
2804
|
+
try {
|
|
2805
|
+
installValidatedPayload(payload, targetHome, staging, lock);
|
|
2806
|
+
} catch (error) {
|
|
2807
|
+
if (error instanceof RestoreRecoveryRequiredError) preserveStaging = true;
|
|
2808
|
+
throw error;
|
|
2809
|
+
}
|
|
2810
|
+
console.log("bootstrap token rotated; all non-bootstrap Bazilion tokens were revoked");
|
|
2811
|
+
console.log("external Telegram, OpenAI, provider, and MCP credentials were not revoked");
|
|
2812
|
+
} finally {
|
|
2813
|
+
if (!preserveStaging) rmSync2(staging, { recursive: true, force: true });
|
|
2814
|
+
lock.release();
|
|
2815
|
+
}
|
|
2816
|
+
}
|
|
2817
|
+
});
|
|
2478
2818
|
var backupCommand = defineCommand5({
|
|
2479
|
-
meta: { name: "backup", description: "
|
|
2819
|
+
meta: { name: "backup", description: "Encrypted backup, restore, and credential recovery" },
|
|
2480
2820
|
subCommands: {
|
|
2481
2821
|
create: createCmd,
|
|
2482
|
-
restore: restoreCmd
|
|
2822
|
+
restore: restoreCmd,
|
|
2823
|
+
inventory: inventoryCmd,
|
|
2824
|
+
"recovery-guide": recoveryGuideCmd,
|
|
2825
|
+
"rotate-bootstrap": rotateBootstrapCmd
|
|
2483
2826
|
}
|
|
2484
2827
|
// `bazilion backup` with no positional falls through to citty's subcommand
|
|
2485
2828
|
// prompt ("No command specified"). The previous default (auto-download to
|
|
@@ -2921,7 +3264,7 @@ var doctorCommand = defineCommand9({
|
|
|
2921
3264
|
meta: { name: "doctor", description: "Diagnose your bazilion install" },
|
|
2922
3265
|
async run() {
|
|
2923
3266
|
const client = createClient2();
|
|
2924
|
-
const r = await client.get("/api/health");
|
|
3267
|
+
const r = await client.get("/api/health/details");
|
|
2925
3268
|
function check(label, condition, hint) {
|
|
2926
3269
|
const mark = condition ? "\u2713" : "\u2717";
|
|
2927
3270
|
const tail = !condition && hint ? ` \u2014 ${hint}` : "";
|
|
@@ -2966,22 +3309,24 @@ var doctorCommand = defineCommand9({
|
|
|
2966
3309
|
}
|
|
2967
3310
|
}
|
|
2968
3311
|
console.log(
|
|
2969
|
-
` \u2713 lmstudio: ${r.providers.lmstudio.
|
|
3312
|
+
` \u2713 lmstudio: ${r.providers.lmstudio.customEndpointConfigured ? "custom endpoint configured" : "default local endpoint"}${r.providers.lmstudio.keyConfigured ? " (API key configured)" : ""}`
|
|
3313
|
+
);
|
|
3314
|
+
console.log(
|
|
3315
|
+
` \u2713 ollama: ${r.providers.ollama.customEndpointConfigured ? "custom endpoint configured" : "default local endpoint"}`
|
|
2970
3316
|
);
|
|
2971
|
-
console.log(` \u2713 ollama: ${r.providers.ollama.baseURL}`);
|
|
2972
3317
|
console.log();
|
|
2973
3318
|
console.log("web search (at least one needed for web_search tool)");
|
|
2974
|
-
if (r.webSearch.
|
|
2975
|
-
console.log(
|
|
3319
|
+
if (r.webSearch.braveConfigured) {
|
|
3320
|
+
console.log(" \u2713 Brave Search configured");
|
|
2976
3321
|
} else {
|
|
2977
3322
|
console.log(" - Brave Search (set BRAVE_API_KEY \u2014 free at https://brave.com/search/api/)");
|
|
2978
3323
|
}
|
|
2979
|
-
if (r.webSearch.
|
|
2980
|
-
console.log(
|
|
3324
|
+
if (r.webSearch.searxngConfigured) {
|
|
3325
|
+
console.log(" \u2713 SearXNG configured");
|
|
2981
3326
|
} else {
|
|
2982
3327
|
console.log(" - SearXNG (set SEARXNG_URL if you self-host one)");
|
|
2983
3328
|
}
|
|
2984
|
-
if (!r.webSearch.
|
|
3329
|
+
if (!r.webSearch.braveConfigured && !r.webSearch.searxngConfigured) {
|
|
2985
3330
|
console.log(" \u26A0 no search backend \u2014 web_search will error until one is configured");
|
|
2986
3331
|
}
|
|
2987
3332
|
console.log();
|
|
@@ -2998,35 +3343,7 @@ var doctorCommand = defineCommand9({
|
|
|
2998
3343
|
` ${r.scheduler.enabled ? "\u2713" : "-"} scheduler${r.scheduler.enabled ? ` (tick ${r.scheduler.tickMs}ms)` : " (BAZILION_SCHEDULER=off)"}`
|
|
2999
3344
|
);
|
|
3000
3345
|
console.log();
|
|
3001
|
-
console.log(
|
|
3002
|
-
if (!r.shellSecurity.ok) {
|
|
3003
|
-
check("valid shell-security configuration", false, r.shellSecurity.error);
|
|
3004
|
-
} else {
|
|
3005
|
-
if (r.shellSecurity.approvalMode === "dangerous") {
|
|
3006
|
-
console.log(" - dangerous-command approval enabled");
|
|
3007
|
-
console.log(
|
|
3008
|
-
" web and TTY CLI turns can allow once; background and non-TTY turns auto-deny"
|
|
3009
|
-
);
|
|
3010
|
-
} else {
|
|
3011
|
-
console.log(" - dangerous-command approval off");
|
|
3012
|
-
console.log(" set BAZILION_BASH_APPROVAL=dangerous to opt in");
|
|
3013
|
-
}
|
|
3014
|
-
if (r.shellSecurity.sandboxMode === "docker") {
|
|
3015
|
-
console.log(` - Docker sandbox configured (${r.shellSecurity.sandboxImage})`);
|
|
3016
|
-
console.log(
|
|
3017
|
-
" workspace-only writable mount \xB7 bounded inputs/skills/memory read-only \xB7 network disabled"
|
|
3018
|
-
);
|
|
3019
|
-
console.log(" host coding tools hidden");
|
|
3020
|
-
console.log(
|
|
3021
|
-
" policy syntax is valid; Docker and image availability are checked on execution"
|
|
3022
|
-
);
|
|
3023
|
-
console.log(" commands fail closed if either is unavailable");
|
|
3024
|
-
} else {
|
|
3025
|
-
console.log(" - sandbox off (agent shell and coding tools run on the host)");
|
|
3026
|
-
console.log(" approval is a host-execution tripwire, not a filesystem sandbox");
|
|
3027
|
-
console.log(" set BAZILION_BASH_SANDBOX=docker to opt in");
|
|
3028
|
-
}
|
|
3029
|
-
}
|
|
3346
|
+
for (const line of executionSecurityDoctorLines(r)) console.log(line);
|
|
3030
3347
|
console.log();
|
|
3031
3348
|
console.log("operational counts");
|
|
3032
3349
|
console.log(` ${r.triggers.active} active trigger(s), ${r.triggers.disabled} disabled`);
|
|
@@ -3035,7 +3352,7 @@ var doctorCommand = defineCommand9({
|
|
|
3035
3352
|
const hasProfiles = (r.database?.ok ? r.database.profiles : 0) > 0;
|
|
3036
3353
|
const hasAgents = (r.database?.ok ? r.database.totalAgents : 0) > 0;
|
|
3037
3354
|
console.log();
|
|
3038
|
-
if (
|
|
3355
|
+
if (doctorHasIssues(r)) {
|
|
3039
3356
|
console.log("issues found \u2717");
|
|
3040
3357
|
process.exit(1);
|
|
3041
3358
|
}
|
|
@@ -3057,9 +3374,150 @@ var doctorCommand = defineCommand9({
|
|
|
3057
3374
|
}
|
|
3058
3375
|
}
|
|
3059
3376
|
});
|
|
3377
|
+
function executionSecurityDoctorLines(report) {
|
|
3378
|
+
const configured = report.executionSecurity.configuredOperatorHttp;
|
|
3379
|
+
const protectedTurns = report.executionSecurity.protectedUnattendedTurns;
|
|
3380
|
+
const lines = ["configured operator HTTP (legacy \xB7 unprotected)"];
|
|
3381
|
+
if (!report.shellSecurity.ok) {
|
|
3382
|
+
lines.push(checkLine("valid shell-security configuration", false, report.shellSecurity.error));
|
|
3383
|
+
} else {
|
|
3384
|
+
if (report.shellSecurity.approvalMode === "dangerous") {
|
|
3385
|
+
lines.push(
|
|
3386
|
+
" - dangerous-command approval enabled",
|
|
3387
|
+
" web and TTY CLI turns can allow once; non-interactive operator requests auto-deny"
|
|
3388
|
+
);
|
|
3389
|
+
} else {
|
|
3390
|
+
lines.push(
|
|
3391
|
+
" - dangerous-command approval off",
|
|
3392
|
+
" set BAZILION_BASH_APPROVAL=dangerous to opt in"
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
if (report.shellSecurity.sandboxMode === "docker") {
|
|
3396
|
+
lines.push(
|
|
3397
|
+
` - coding surface: Docker only (${report.shellSecurity.sandboxImage})`,
|
|
3398
|
+
" workspace-only writable mount \xB7 bounded inputs/skills/memory read-only \xB7 network disabled",
|
|
3399
|
+
" host coding tools hidden",
|
|
3400
|
+
" policy syntax is valid; Docker and image availability are checked on execution",
|
|
3401
|
+
" commands fail closed if either is unavailable"
|
|
3402
|
+
);
|
|
3403
|
+
} else {
|
|
3404
|
+
lines.push(
|
|
3405
|
+
" - coding surface: host tools",
|
|
3406
|
+
" approval is a host-execution tripwire, not a filesystem sandbox",
|
|
3407
|
+
" set BAZILION_BASH_SANDBOX=docker to opt in"
|
|
3408
|
+
);
|
|
3409
|
+
}
|
|
3410
|
+
}
|
|
3411
|
+
lines.push(` - browser: ${configured.browser}`, ` - MCP: ${configured.mcp}`, "");
|
|
3412
|
+
lines.push(
|
|
3413
|
+
"protected unattended turns baseline (Telegram, schedules, inbox, approvals)",
|
|
3414
|
+
checkLine("protected base runtime ready", protectedTurns.baseRuntimeReady),
|
|
3415
|
+
" - coding surface: Docker only",
|
|
3416
|
+
checkLine(
|
|
3417
|
+
`Docker ready (${protectedTurns.docker.image})`,
|
|
3418
|
+
protectedTurns.docker.ready,
|
|
3419
|
+
protectedTurns.docker.reason ?? void 0
|
|
3420
|
+
),
|
|
3421
|
+
checkLine("OpenAI Codex enabled", protectedTurns.openaiCodex.enabled),
|
|
3422
|
+
checkLine("ChatGPT connected", protectedTurns.openaiCodex.connected),
|
|
3423
|
+
` - OpenAI access: ${openAIAccessStatus(protectedTurns.openaiCodex)}`,
|
|
3424
|
+
checkLine("OpenAI Codex baseline eligible", protectedTurns.openaiCodex.baselineEligible),
|
|
3425
|
+
` \u2713 browser: ${protectedTurns.browser}`,
|
|
3426
|
+
` \u2713 MCP: ${protectedTurns.mcp}`,
|
|
3427
|
+
" - every turn separately validates its selected normal/review model, bound OAuth refresh, and mounts/paths"
|
|
3428
|
+
);
|
|
3429
|
+
if (protectedTurns.remediation) {
|
|
3430
|
+
lines.push(` remediation: ${protectedTurns.remediation}`);
|
|
3431
|
+
}
|
|
3432
|
+
return lines;
|
|
3433
|
+
}
|
|
3434
|
+
function doctorHasIssues(report) {
|
|
3435
|
+
return !report.ok || !report.protectedWorkBaselineReady;
|
|
3436
|
+
}
|
|
3437
|
+
function openAIAccessStatus(status) {
|
|
3438
|
+
if (status.accessCurrent) return "current";
|
|
3439
|
+
if (status.refreshOnNextTurn) return "refresh on next turn";
|
|
3440
|
+
return "unavailable";
|
|
3441
|
+
}
|
|
3442
|
+
function checkLine(label, condition, hint) {
|
|
3443
|
+
const mark = condition ? "\u2713" : "\u2717";
|
|
3444
|
+
const tail = !condition && hint ? ` \u2014 ${hint}` : "";
|
|
3445
|
+
return ` ${mark} ${label}${tail}`;
|
|
3446
|
+
}
|
|
3060
3447
|
|
|
3061
|
-
// src/commands/
|
|
3448
|
+
// src/commands/gateway.ts
|
|
3449
|
+
import { execFile } from "child_process";
|
|
3450
|
+
import { promisify } from "util";
|
|
3062
3451
|
import { defineCommand as defineCommand10 } from "citty";
|
|
3452
|
+
var execFileAsync = promisify(execFile);
|
|
3453
|
+
function exactHttpsOrigin(raw) {
|
|
3454
|
+
if (!raw) throw new Error("BAZILION_PUBLIC_ORIGIN is required");
|
|
3455
|
+
const url = new URL(raw);
|
|
3456
|
+
if (url.protocol !== "https:" || url.username || url.password || url.pathname !== "/" || url.search || url.hash || url.origin !== raw.replace(/\/$/, "")) {
|
|
3457
|
+
throw new Error("BAZILION_PUBLIC_ORIGIN must be an exact HTTPS origin");
|
|
3458
|
+
}
|
|
3459
|
+
return url;
|
|
3460
|
+
}
|
|
3461
|
+
function listenerIsLoopback(output, port) {
|
|
3462
|
+
const suffix = `:${port}`;
|
|
3463
|
+
const listeners = output.split("\n").filter((line) => line.trim()).filter((line) => line.split(/\s+/).some((field) => field.endsWith(suffix)));
|
|
3464
|
+
return listeners.length > 0 && listeners.every((line) => /(?:127\.0\.0\.1|\[?::1\]?):\d+/.test(line));
|
|
3465
|
+
}
|
|
3466
|
+
function hasFunnel(value) {
|
|
3467
|
+
if (Array.isArray(value)) return value.some(hasFunnel);
|
|
3468
|
+
if (!value || typeof value !== "object") return false;
|
|
3469
|
+
return Object.entries(value).some(
|
|
3470
|
+
([key, nested]) => /funnel/i.test(key) && nested !== false && nested !== null || hasFunnel(nested)
|
|
3471
|
+
);
|
|
3472
|
+
}
|
|
3473
|
+
var preflightCmd = defineCommand10({
|
|
3474
|
+
meta: { name: "preflight", description: "Read-only private Tailscale gateway safety check" },
|
|
3475
|
+
async run() {
|
|
3476
|
+
const publicOrigin = exactHttpsOrigin(process.env.BAZILION_PUBLIC_ORIGIN);
|
|
3477
|
+
const daemonPort = Number(process.env.PORT ?? 4321);
|
|
3478
|
+
const webPort = Number(process.env.WEB_PORT ?? 4322);
|
|
3479
|
+
const { stdout: listeners } = await execFileAsync("ss", ["-ltnH"], { timeout: 5e3 });
|
|
3480
|
+
if (!listenerIsLoopback(listeners, daemonPort)) {
|
|
3481
|
+
throw new Error(`daemon port ${daemonPort} is not listening exclusively on loopback`);
|
|
3482
|
+
}
|
|
3483
|
+
if (!listenerIsLoopback(listeners, webPort)) {
|
|
3484
|
+
throw new Error(`web port ${webPort} is not listening exclusively on loopback`);
|
|
3485
|
+
}
|
|
3486
|
+
let serveStatus;
|
|
3487
|
+
try {
|
|
3488
|
+
const { stdout: stdout2 } = await execFileAsync("tailscale", ["serve", "status", "--json"], {
|
|
3489
|
+
timeout: 1e4,
|
|
3490
|
+
maxBuffer: 1024 * 1024
|
|
3491
|
+
});
|
|
3492
|
+
serveStatus = JSON.parse(stdout2);
|
|
3493
|
+
} catch {
|
|
3494
|
+
throw new Error("could not obtain unambiguous `tailscale serve status --json` evidence");
|
|
3495
|
+
}
|
|
3496
|
+
if (hasFunnel(serveStatus))
|
|
3497
|
+
throw new Error("Tailscale Funnel is enabled; private Serve is required");
|
|
3498
|
+
const serialized = JSON.stringify(serveStatus);
|
|
3499
|
+
if (!serialized.includes(`127.0.0.1:${webPort}`) && !serialized.includes(`localhost:${webPort}`)) {
|
|
3500
|
+
throw new Error(`Tailscale Serve does not clearly target the loopback web port ${webPort}`);
|
|
3501
|
+
}
|
|
3502
|
+
const health = await createClient2().get("/api/health/details");
|
|
3503
|
+
if (!health.protectedWorkBaselineReady) {
|
|
3504
|
+
throw new Error("BAZ-027 protected-turn baseline is not ready");
|
|
3505
|
+
}
|
|
3506
|
+
console.log("private gateway preflight passed");
|
|
3507
|
+
console.log(`public origin: ${publicOrigin.origin}`);
|
|
3508
|
+
console.log(`daemon: loopback:${daemonPort}`);
|
|
3509
|
+
console.log(`web: loopback:${webPort}`);
|
|
3510
|
+
console.log("Tailscale: private Serve target present; Funnel absent");
|
|
3511
|
+
console.log("hosted Agent turns: protected baseline ready");
|
|
3512
|
+
}
|
|
3513
|
+
});
|
|
3514
|
+
var gatewayCommand = defineCommand10({
|
|
3515
|
+
meta: { name: "gateway", description: "Inspect the private web gateway posture" },
|
|
3516
|
+
subCommands: { preflight: preflightCmd }
|
|
3517
|
+
});
|
|
3518
|
+
|
|
3519
|
+
// src/commands/inbox.ts
|
|
3520
|
+
import { defineCommand as defineCommand11 } from "citty";
|
|
3063
3521
|
function decodeText(payload) {
|
|
3064
3522
|
try {
|
|
3065
3523
|
const obj = JSON.parse(payload);
|
|
@@ -3075,7 +3533,7 @@ function messageRow(m) {
|
|
|
3075
3533
|
const preview = text2.length > 60 ? `${text2.slice(0, 60)}\u2026` : text2;
|
|
3076
3534
|
return [m.id, state, when, `from:${m.fromAgentId.slice(0, 8)}`, `"${preview}"`];
|
|
3077
3535
|
}
|
|
3078
|
-
var listCmd3 =
|
|
3536
|
+
var listCmd3 = defineCommand11({
|
|
3079
3537
|
meta: { name: "list", description: "List messages in an agent inbox" },
|
|
3080
3538
|
args: {
|
|
3081
3539
|
agent: { type: "positional", required: true, description: "Recipient agent id" },
|
|
@@ -3094,7 +3552,7 @@ var listCmd3 = defineCommand10({
|
|
|
3094
3552
|
for (const line of columnize(messages.map(messageRow))) console.log(line);
|
|
3095
3553
|
}
|
|
3096
3554
|
});
|
|
3097
|
-
var showCmd2 =
|
|
3555
|
+
var showCmd2 = defineCommand11({
|
|
3098
3556
|
meta: { name: "show", description: "Show a single message in full" },
|
|
3099
3557
|
args: {
|
|
3100
3558
|
id: { type: "positional", required: true, description: "Message id" }
|
|
@@ -3114,7 +3572,7 @@ var showCmd2 = defineCommand10({
|
|
|
3114
3572
|
console.log(decodeText(m.payload));
|
|
3115
3573
|
}
|
|
3116
3574
|
});
|
|
3117
|
-
var readCmd =
|
|
3575
|
+
var readCmd = defineCommand11({
|
|
3118
3576
|
meta: { name: "read", description: "Mark a message as read" },
|
|
3119
3577
|
args: {
|
|
3120
3578
|
id: { type: "positional", required: true, description: "Message id" }
|
|
@@ -3125,7 +3583,7 @@ var readCmd = defineCommand10({
|
|
|
3125
3583
|
console.log(`marked read: ${args.id}`);
|
|
3126
3584
|
}
|
|
3127
3585
|
});
|
|
3128
|
-
var loopBreaksCmd =
|
|
3586
|
+
var loopBreaksCmd = defineCommand11({
|
|
3129
3587
|
meta: { name: "loop-breaks", description: "List stopped agent-message chains" },
|
|
3130
3588
|
args: {
|
|
3131
3589
|
agent: { type: "positional", required: true, description: "Agent id" },
|
|
@@ -3153,7 +3611,7 @@ var loopBreaksCmd = defineCommand10({
|
|
|
3153
3611
|
console.log(line);
|
|
3154
3612
|
}
|
|
3155
3613
|
});
|
|
3156
|
-
var inboxCommand =
|
|
3614
|
+
var inboxCommand = defineCommand11({
|
|
3157
3615
|
meta: { name: "inbox", description: "Inspect agent inboxes" },
|
|
3158
3616
|
subCommands: {
|
|
3159
3617
|
list: listCmd3,
|
|
@@ -3164,8 +3622,8 @@ var inboxCommand = defineCommand10({
|
|
|
3164
3622
|
});
|
|
3165
3623
|
|
|
3166
3624
|
// src/commands/login.ts
|
|
3167
|
-
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as
|
|
3168
|
-
import { defineCommand as
|
|
3625
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
3626
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
3169
3627
|
function normalizeServer(raw) {
|
|
3170
3628
|
let url;
|
|
3171
3629
|
try {
|
|
@@ -3179,13 +3637,17 @@ function normalizeServer(raw) {
|
|
|
3179
3637
|
return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
|
|
3180
3638
|
}
|
|
3181
3639
|
async function verifyToken(server, token) {
|
|
3182
|
-
const res = await fetch(`${server}/api/
|
|
3640
|
+
const res = await fetch(`${server}/api/auth/whoami`, {
|
|
3183
3641
|
headers: { authorization: `Bearer ${token}`, origin: server }
|
|
3184
3642
|
});
|
|
3185
3643
|
if (res.status === 401) throw new Error("server rejected token (401)");
|
|
3186
|
-
if (!res.ok) throw new Error(`server returned ${res.status} from /api/
|
|
3644
|
+
if (!res.ok) throw new Error(`server returned ${res.status} from /api/auth/whoami`);
|
|
3645
|
+
const owner = await res.json();
|
|
3646
|
+
if (owner.publicOrigin && owner.publicOrigin !== new URL(server).origin) {
|
|
3647
|
+
throw new Error("server canonical private origin does not match --server");
|
|
3648
|
+
}
|
|
3187
3649
|
}
|
|
3188
|
-
var loginCommand =
|
|
3650
|
+
var loginCommand = defineCommand12({
|
|
3189
3651
|
meta: {
|
|
3190
3652
|
name: "login",
|
|
3191
3653
|
description: "Save a remote bazilion server + token pair to auth.json"
|
|
@@ -3193,7 +3655,7 @@ var loginCommand = defineCommand11({
|
|
|
3193
3655
|
args: {
|
|
3194
3656
|
server: { type: "string", description: "Remote server URL (http[s]://...)" },
|
|
3195
3657
|
token: { type: "string", description: "Token issued by `bazilion token create`" },
|
|
3196
|
-
skipVerify: { type: "boolean", description: "Don't
|
|
3658
|
+
skipVerify: { type: "boolean", description: "Don't verify /api/auth/whoami before saving" },
|
|
3197
3659
|
clear: { type: "boolean", description: "Remove the stored remote instead of setting one" }
|
|
3198
3660
|
},
|
|
3199
3661
|
async run({ args }) {
|
|
@@ -3210,7 +3672,7 @@ var loginCommand = defineCommand11({
|
|
|
3210
3672
|
return;
|
|
3211
3673
|
}
|
|
3212
3674
|
delete auth.remote;
|
|
3213
|
-
|
|
3675
|
+
writeFileSync3(paths.authFile, `${JSON.stringify(auth, null, 2)}
|
|
3214
3676
|
`, { mode: 384 });
|
|
3215
3677
|
console.log("cleared stored remote; CLI will fall back to the local daemon");
|
|
3216
3678
|
return;
|
|
@@ -3225,7 +3687,7 @@ var loginCommand = defineCommand11({
|
|
|
3225
3687
|
await verifyToken(server, args.token);
|
|
3226
3688
|
}
|
|
3227
3689
|
auth.remote = { server, token: args.token };
|
|
3228
|
-
|
|
3690
|
+
writeFileSync3(paths.authFile, `${JSON.stringify(auth, null, 2)}
|
|
3229
3691
|
`, { mode: 384 });
|
|
3230
3692
|
console.log(`saved remote: ${server}`);
|
|
3231
3693
|
console.log("CLI will now target this server unless BAZILION_SERVER is set in the env.");
|
|
@@ -3233,7 +3695,7 @@ var loginCommand = defineCommand11({
|
|
|
3233
3695
|
});
|
|
3234
3696
|
|
|
3235
3697
|
// src/commands/mcp.ts
|
|
3236
|
-
import { defineCommand as
|
|
3698
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
3237
3699
|
function serverRow(s) {
|
|
3238
3700
|
const where = s.transport === "stdio" ? `${s.command} ${s.args.join(" ")}`.trim() : s.url ?? "";
|
|
3239
3701
|
return [
|
|
@@ -3245,7 +3707,7 @@ function serverRow(s) {
|
|
|
3245
3707
|
where
|
|
3246
3708
|
];
|
|
3247
3709
|
}
|
|
3248
|
-
var addCmd =
|
|
3710
|
+
var addCmd = defineCommand13({
|
|
3249
3711
|
meta: { name: "add", description: "Register an MCP server" },
|
|
3250
3712
|
args: {
|
|
3251
3713
|
name: { type: "positional", required: true, description: "Unique name ([a-zA-Z0-9_])" },
|
|
@@ -3272,7 +3734,7 @@ var addCmd = defineCommand12({
|
|
|
3272
3734
|
console.log(`${server.id} ${server.name} ${server.transport}`);
|
|
3273
3735
|
}
|
|
3274
3736
|
});
|
|
3275
|
-
var listCmd4 =
|
|
3737
|
+
var listCmd4 = defineCommand13({
|
|
3276
3738
|
meta: { name: "list", description: "List MCP servers" },
|
|
3277
3739
|
async run() {
|
|
3278
3740
|
const client = createClient2();
|
|
@@ -3284,7 +3746,7 @@ var listCmd4 = defineCommand12({
|
|
|
3284
3746
|
for (const line of columnize(servers.map(serverRow))) console.log(line);
|
|
3285
3747
|
}
|
|
3286
3748
|
});
|
|
3287
|
-
var showCmd3 =
|
|
3749
|
+
var showCmd3 = defineCommand13({
|
|
3288
3750
|
meta: { name: "show", description: "Show one MCP server" },
|
|
3289
3751
|
args: { id: { type: "positional", required: true } },
|
|
3290
3752
|
async run({ args }) {
|
|
@@ -3293,7 +3755,7 @@ var showCmd3 = defineCommand12({
|
|
|
3293
3755
|
console.log(JSON.stringify(server, null, 2));
|
|
3294
3756
|
}
|
|
3295
3757
|
});
|
|
3296
|
-
var rmCmd2 =
|
|
3758
|
+
var rmCmd2 = defineCommand13({
|
|
3297
3759
|
meta: { name: "rm", description: "Delete an MCP server" },
|
|
3298
3760
|
args: { id: { type: "positional", required: true } },
|
|
3299
3761
|
async run({ args }) {
|
|
@@ -3302,7 +3764,7 @@ var rmCmd2 = defineCommand12({
|
|
|
3302
3764
|
console.log(`removed MCP server ${args.id}`);
|
|
3303
3765
|
}
|
|
3304
3766
|
});
|
|
3305
|
-
var enableCmd =
|
|
3767
|
+
var enableCmd = defineCommand13({
|
|
3306
3768
|
meta: { name: "enable", description: "Enable an MCP server" },
|
|
3307
3769
|
args: { id: { type: "positional", required: true } },
|
|
3308
3770
|
async run({ args }) {
|
|
@@ -3311,7 +3773,7 @@ var enableCmd = defineCommand12({
|
|
|
3311
3773
|
console.log(`enabled MCP server ${args.id}`);
|
|
3312
3774
|
}
|
|
3313
3775
|
});
|
|
3314
|
-
var disableCmd =
|
|
3776
|
+
var disableCmd = defineCommand13({
|
|
3315
3777
|
meta: { name: "disable", description: "Disable an MCP server" },
|
|
3316
3778
|
args: { id: { type: "positional", required: true } },
|
|
3317
3779
|
async run({ args }) {
|
|
@@ -3320,7 +3782,7 @@ var disableCmd = defineCommand12({
|
|
|
3320
3782
|
console.log(`disabled MCP server ${args.id}`);
|
|
3321
3783
|
}
|
|
3322
3784
|
});
|
|
3323
|
-
var testCmd =
|
|
3785
|
+
var testCmd = defineCommand13({
|
|
3324
3786
|
meta: { name: "test", description: "Connect to a server and list its tools" },
|
|
3325
3787
|
args: { id: { type: "positional", required: true } },
|
|
3326
3788
|
async run({ args }) {
|
|
@@ -3338,7 +3800,7 @@ var testCmd = defineCommand12({
|
|
|
3338
3800
|
for (const t of tools) console.log(` ${t.name} ${t.description}`);
|
|
3339
3801
|
}
|
|
3340
3802
|
});
|
|
3341
|
-
var mcpCommand =
|
|
3803
|
+
var mcpCommand = defineCommand13({
|
|
3342
3804
|
meta: { name: "mcp", description: "Manage MCP servers" },
|
|
3343
3805
|
subCommands: {
|
|
3344
3806
|
add: addCmd,
|
|
@@ -3352,11 +3814,11 @@ var mcpCommand = defineCommand12({
|
|
|
3352
3814
|
});
|
|
3353
3815
|
|
|
3354
3816
|
// src/commands/memory.ts
|
|
3355
|
-
import { defineCommand as
|
|
3817
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
3356
3818
|
function encodeKey(key) {
|
|
3357
3819
|
return key.split("/").map(encodeURIComponent).join("/");
|
|
3358
3820
|
}
|
|
3359
|
-
var writeCmd =
|
|
3821
|
+
var writeCmd = defineCommand14({
|
|
3360
3822
|
meta: { name: "write", description: "Write an entry into a team's shared memory" },
|
|
3361
3823
|
args: {
|
|
3362
3824
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3372,7 +3834,7 @@ var writeCmd = defineCommand13({
|
|
|
3372
3834
|
console.log(`wrote ${entry2.key} (${entry2.content.length} bytes)`);
|
|
3373
3835
|
}
|
|
3374
3836
|
});
|
|
3375
|
-
var readCmd2 =
|
|
3837
|
+
var readCmd2 = defineCommand14({
|
|
3376
3838
|
meta: { name: "read", description: "Read an entry from a team's shared memory" },
|
|
3377
3839
|
args: {
|
|
3378
3840
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3386,7 +3848,7 @@ var readCmd2 = defineCommand13({
|
|
|
3386
3848
|
console.log(entry2.content);
|
|
3387
3849
|
}
|
|
3388
3850
|
});
|
|
3389
|
-
var searchCmd =
|
|
3851
|
+
var searchCmd = defineCommand14({
|
|
3390
3852
|
meta: { name: "search", description: "Search a team's shared memory" },
|
|
3391
3853
|
args: {
|
|
3392
3854
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3407,7 +3869,7 @@ var searchCmd = defineCommand13({
|
|
|
3407
3869
|
}
|
|
3408
3870
|
}
|
|
3409
3871
|
});
|
|
3410
|
-
var listCmd5 =
|
|
3872
|
+
var listCmd5 = defineCommand14({
|
|
3411
3873
|
meta: { name: "list", description: "List all entries in a team's shared memory" },
|
|
3412
3874
|
args: {
|
|
3413
3875
|
team: { type: "positional", required: true, description: "Team slug" }
|
|
@@ -3424,7 +3886,7 @@ var listCmd5 = defineCommand13({
|
|
|
3424
3886
|
}
|
|
3425
3887
|
}
|
|
3426
3888
|
});
|
|
3427
|
-
var rmCmd3 =
|
|
3889
|
+
var rmCmd3 = defineCommand14({
|
|
3428
3890
|
meta: { name: "rm", description: "Remove an entry from a team's shared memory" },
|
|
3429
3891
|
args: {
|
|
3430
3892
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3436,7 +3898,7 @@ var rmCmd3 = defineCommand13({
|
|
|
3436
3898
|
console.log(`removed ${args.key}`);
|
|
3437
3899
|
}
|
|
3438
3900
|
});
|
|
3439
|
-
var memoryCommand =
|
|
3901
|
+
var memoryCommand = defineCommand14({
|
|
3440
3902
|
meta: {
|
|
3441
3903
|
name: "memory",
|
|
3442
3904
|
description: "Manage a team's shared memory (BM25-indexed markdown notes)"
|
|
@@ -3452,8 +3914,8 @@ var memoryCommand = defineCommand13({
|
|
|
3452
3914
|
|
|
3453
3915
|
// src/commands/profile.ts
|
|
3454
3916
|
import { spawn as spawn2 } from "child_process";
|
|
3455
|
-
import { randomBytes } from "crypto";
|
|
3456
|
-
import { readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as
|
|
3917
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
3918
|
+
import { readFileSync as readFileSync6, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
3457
3919
|
import { tmpdir as tmpdir2 } from "os";
|
|
3458
3920
|
import { join as join4 } from "path";
|
|
3459
3921
|
|
|
@@ -3468,7 +3930,7 @@ var PROFILE_FILES = [
|
|
|
3468
3930
|
];
|
|
3469
3931
|
|
|
3470
3932
|
// src/commands/profile.ts
|
|
3471
|
-
import { defineCommand as
|
|
3933
|
+
import { defineCommand as defineCommand15 } from "citty";
|
|
3472
3934
|
function splitCsv(v) {
|
|
3473
3935
|
if (!v) return void 0;
|
|
3474
3936
|
const out = v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -3479,7 +3941,7 @@ function parseSkillsMode(v) {
|
|
|
3479
3941
|
if (v === "all" || v === "selected") return v;
|
|
3480
3942
|
throw new Error(`--skills-mode must be 'all' or 'selected', got '${v}'`);
|
|
3481
3943
|
}
|
|
3482
|
-
var createCmd2 =
|
|
3944
|
+
var createCmd2 = defineCommand15({
|
|
3483
3945
|
meta: { name: "create", description: "Create a new profile" },
|
|
3484
3946
|
args: {
|
|
3485
3947
|
id: { type: "positional", required: true, description: "Profile slug" },
|
|
@@ -3542,7 +4004,7 @@ var createCmd2 = defineCommand14({
|
|
|
3542
4004
|
console.log(`created profile ${profile.id} at ${profile.dir}`);
|
|
3543
4005
|
}
|
|
3544
4006
|
});
|
|
3545
|
-
var listCmd6 =
|
|
4007
|
+
var listCmd6 = defineCommand15({
|
|
3546
4008
|
meta: { name: "list", description: "List profiles" },
|
|
3547
4009
|
async run() {
|
|
3548
4010
|
const client = createClient2();
|
|
@@ -3555,7 +4017,7 @@ var listCmd6 = defineCommand14({
|
|
|
3555
4017
|
for (const line of columnize(rows)) console.log(line);
|
|
3556
4018
|
}
|
|
3557
4019
|
});
|
|
3558
|
-
var showCmd4 =
|
|
4020
|
+
var showCmd4 = defineCommand15({
|
|
3559
4021
|
meta: { name: "show", description: "Show profile details" },
|
|
3560
4022
|
args: {
|
|
3561
4023
|
id: { type: "positional", required: true }
|
|
@@ -3580,7 +4042,7 @@ var showCmd4 = defineCommand14({
|
|
|
3580
4042
|
}
|
|
3581
4043
|
}
|
|
3582
4044
|
});
|
|
3583
|
-
var editCmd2 =
|
|
4045
|
+
var editCmd2 = defineCommand15({
|
|
3584
4046
|
meta: { name: "edit", description: "Open a profile file in $EDITOR" },
|
|
3585
4047
|
args: {
|
|
3586
4048
|
id: { type: "positional", required: true },
|
|
@@ -3599,8 +4061,8 @@ var editCmd2 = defineCommand14({
|
|
|
3599
4061
|
const { content } = await client.get(
|
|
3600
4062
|
`/api/profiles/${args.id}/files/${file}`
|
|
3601
4063
|
);
|
|
3602
|
-
const tmpPath = join4(tmpdir2(), `bazilion-${args.id}-${file}-${
|
|
3603
|
-
|
|
4064
|
+
const tmpPath = join4(tmpdir2(), `bazilion-${args.id}-${file}-${randomBytes2(4).toString("hex")}`);
|
|
4065
|
+
writeFileSync4(tmpPath, content);
|
|
3604
4066
|
try {
|
|
3605
4067
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
3606
4068
|
const code = await new Promise((resolve4, reject) => {
|
|
@@ -3625,7 +4087,7 @@ var editCmd2 = defineCommand14({
|
|
|
3625
4087
|
}
|
|
3626
4088
|
}
|
|
3627
4089
|
});
|
|
3628
|
-
var updateCmd =
|
|
4090
|
+
var updateCmd = defineCommand15({
|
|
3629
4091
|
meta: {
|
|
3630
4092
|
name: "update",
|
|
3631
4093
|
description: "Update profile settings (name, model, skills-mode, skills)"
|
|
@@ -3659,7 +4121,7 @@ var updateCmd = defineCommand14({
|
|
|
3659
4121
|
console.log(`updated profile ${profile.id}`);
|
|
3660
4122
|
}
|
|
3661
4123
|
});
|
|
3662
|
-
var deleteCmd2 =
|
|
4124
|
+
var deleteCmd2 = defineCommand15({
|
|
3663
4125
|
meta: { name: "delete", description: "Permanently delete a profile and its files" },
|
|
3664
4126
|
args: {
|
|
3665
4127
|
id: { type: "positional", required: true }
|
|
@@ -3670,7 +4132,7 @@ var deleteCmd2 = defineCommand14({
|
|
|
3670
4132
|
console.log(`deleted profile ${args.id}`);
|
|
3671
4133
|
}
|
|
3672
4134
|
});
|
|
3673
|
-
var profileCommand =
|
|
4135
|
+
var profileCommand = defineCommand15({
|
|
3674
4136
|
meta: { name: "profile", description: "Manage profiles" },
|
|
3675
4137
|
subCommands: {
|
|
3676
4138
|
create: createCmd2,
|
|
@@ -3683,8 +4145,8 @@ var profileCommand = defineCommand14({
|
|
|
3683
4145
|
});
|
|
3684
4146
|
|
|
3685
4147
|
// src/commands/provider.ts
|
|
3686
|
-
import { defineCommand as
|
|
3687
|
-
var listCmd7 =
|
|
4148
|
+
import { defineCommand as defineCommand16 } from "citty";
|
|
4149
|
+
var listCmd7 = defineCommand16({
|
|
3688
4150
|
meta: {
|
|
3689
4151
|
name: "list",
|
|
3690
4152
|
description: "List all providers with enabled/disabled state and curated model counts"
|
|
@@ -3710,7 +4172,7 @@ var listCmd7 = defineCommand15({
|
|
|
3710
4172
|
for (const line of columnize(rows)) console.log(line);
|
|
3711
4173
|
}
|
|
3712
4174
|
});
|
|
3713
|
-
var modelsCmd =
|
|
4175
|
+
var modelsCmd = defineCommand16({
|
|
3714
4176
|
meta: {
|
|
3715
4177
|
name: "models",
|
|
3716
4178
|
description: "Show curated + catalog + live models for one provider"
|
|
@@ -3742,7 +4204,7 @@ var modelsCmd = defineCommand15({
|
|
|
3742
4204
|
}
|
|
3743
4205
|
}
|
|
3744
4206
|
});
|
|
3745
|
-
var modelsSetCmd =
|
|
4207
|
+
var modelsSetCmd = defineCommand16({
|
|
3746
4208
|
meta: {
|
|
3747
4209
|
name: "models-set",
|
|
3748
4210
|
description: "Replace the curated model list for a provider (comma-separated)"
|
|
@@ -3767,7 +4229,7 @@ var modelsSetCmd = defineCommand15({
|
|
|
3767
4229
|
for (const m of saved.models) console.log(` ${m}`);
|
|
3768
4230
|
}
|
|
3769
4231
|
});
|
|
3770
|
-
var enableCmd2 =
|
|
4232
|
+
var enableCmd2 = defineCommand16({
|
|
3771
4233
|
meta: { name: "enable", description: "Toggle a provider on so agents can use it" },
|
|
3772
4234
|
args: {
|
|
3773
4235
|
name: { type: "positional", required: true, description: "Provider id (e.g. anthropic)" }
|
|
@@ -3781,7 +4243,7 @@ var enableCmd2 = defineCommand15({
|
|
|
3781
4243
|
console.log(`${res.name}: enabled`);
|
|
3782
4244
|
}
|
|
3783
4245
|
});
|
|
3784
|
-
var disableCmd2 =
|
|
4246
|
+
var disableCmd2 = defineCommand16({
|
|
3785
4247
|
meta: {
|
|
3786
4248
|
name: "disable",
|
|
3787
4249
|
description: "Toggle a provider off \u2014 agents will refuse its model strings"
|
|
@@ -3798,7 +4260,7 @@ var disableCmd2 = defineCommand15({
|
|
|
3798
4260
|
console.log(`${res.name}: disabled`);
|
|
3799
4261
|
}
|
|
3800
4262
|
});
|
|
3801
|
-
var testCmd2 =
|
|
4263
|
+
var testCmd2 = defineCommand16({
|
|
3802
4264
|
meta: { name: "test", description: "Send a single chat to a model and print the reply" },
|
|
3803
4265
|
args: {
|
|
3804
4266
|
model: {
|
|
@@ -3819,7 +4281,7 @@ var testCmd2 = defineCommand15({
|
|
|
3819
4281
|
}
|
|
3820
4282
|
}
|
|
3821
4283
|
});
|
|
3822
|
-
var providerCommand =
|
|
4284
|
+
var providerCommand = defineCommand16({
|
|
3823
4285
|
meta: { name: "provider", description: "Manage and test LLM providers" },
|
|
3824
4286
|
subCommands: {
|
|
3825
4287
|
list: listCmd7,
|
|
@@ -3832,8 +4294,8 @@ var providerCommand = defineCommand15({
|
|
|
3832
4294
|
});
|
|
3833
4295
|
|
|
3834
4296
|
// src/commands/send.ts
|
|
3835
|
-
import { defineCommand as
|
|
3836
|
-
var sendCommand =
|
|
4297
|
+
import { defineCommand as defineCommand17 } from "citty";
|
|
4298
|
+
var sendCommand = defineCommand17({
|
|
3837
4299
|
meta: {
|
|
3838
4300
|
name: "send",
|
|
3839
4301
|
description: "Send a message from one agent to another"
|
|
@@ -3867,11 +4329,11 @@ var sendCommand = defineCommand16({
|
|
|
3867
4329
|
import { spawn as spawn3 } from "child_process";
|
|
3868
4330
|
import { existsSync as existsSync5 } from "fs";
|
|
3869
4331
|
import { join as join5 } from "path";
|
|
3870
|
-
import { defineCommand as
|
|
4332
|
+
import { defineCommand as defineCommand18 } from "citty";
|
|
3871
4333
|
var bundledDaemonEntry2 = join5(import.meta.dirname, "daemon.js");
|
|
3872
4334
|
var sourceDaemonEntry2 = join5(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
|
|
3873
4335
|
var daemonEntry2 = existsSync5(bundledDaemonEntry2) ? bundledDaemonEntry2 : sourceDaemonEntry2;
|
|
3874
|
-
var serveCommand =
|
|
4336
|
+
var serveCommand = defineCommand18({
|
|
3875
4337
|
meta: {
|
|
3876
4338
|
name: "serve",
|
|
3877
4339
|
description: "Start the bazilion daemon (HTTP API)"
|
|
@@ -3937,17 +4399,54 @@ var serveCommand = defineCommand17({
|
|
|
3937
4399
|
}
|
|
3938
4400
|
});
|
|
3939
4401
|
|
|
4402
|
+
// src/commands/session.ts
|
|
4403
|
+
import { defineCommand as defineCommand19 } from "citty";
|
|
4404
|
+
function row(session) {
|
|
4405
|
+
const state = session.revokedAt ? "revoked" : session.absoluteExpiresAt <= Date.now() || session.idleExpiresAt <= Date.now() ? "expired" : "active";
|
|
4406
|
+
return [
|
|
4407
|
+
session.id,
|
|
4408
|
+
state,
|
|
4409
|
+
session.current ? "current" : "",
|
|
4410
|
+
session.deviceLabel,
|
|
4411
|
+
`idle: ${new Date(session.idleExpiresAt).toISOString()}`,
|
|
4412
|
+
`absolute: ${new Date(session.absoluteExpiresAt).toISOString()}`
|
|
4413
|
+
];
|
|
4414
|
+
}
|
|
4415
|
+
var listCmd8 = defineCommand19({
|
|
4416
|
+
meta: { name: "list", description: "List browser sessions" },
|
|
4417
|
+
async run() {
|
|
4418
|
+
const { sessions } = await createClient2().get("/api/sessions");
|
|
4419
|
+
if (sessions.length === 0) {
|
|
4420
|
+
console.log("(no active browser sessions)");
|
|
4421
|
+
return;
|
|
4422
|
+
}
|
|
4423
|
+
for (const line of columnize(sessions.map(row))) console.log(line);
|
|
4424
|
+
}
|
|
4425
|
+
});
|
|
4426
|
+
var revokeCmd = defineCommand19({
|
|
4427
|
+
meta: { name: "revoke", description: "Revoke one browser session" },
|
|
4428
|
+
args: { id: { type: "positional", required: true } },
|
|
4429
|
+
async run({ args }) {
|
|
4430
|
+
await createClient2().del(`/api/sessions/${encodeURIComponent(args.id)}`);
|
|
4431
|
+
console.log(`revoked browser session ${args.id}`);
|
|
4432
|
+
}
|
|
4433
|
+
});
|
|
4434
|
+
var sessionCommand = defineCommand19({
|
|
4435
|
+
meta: { name: "session", description: "Manage browser sessions" },
|
|
4436
|
+
subCommands: { list: listCmd8, revoke: revokeCmd }
|
|
4437
|
+
});
|
|
4438
|
+
|
|
3940
4439
|
// src/commands/skill.ts
|
|
3941
4440
|
import { existsSync as existsSync6, readFileSync as readFileSync7, statSync } from "fs";
|
|
3942
4441
|
import { basename as basename4, resolve as resolve3 } from "path";
|
|
3943
|
-
import { defineCommand as
|
|
4442
|
+
import { defineCommand as defineCommand20 } from "citty";
|
|
3944
4443
|
function printFindings(findings, prefix = " ") {
|
|
3945
4444
|
for (const f of findings) {
|
|
3946
4445
|
const line = f.line ? ` line ${f.line}` : "";
|
|
3947
4446
|
console.log(`${prefix}${f.severity}: ${f.code}${line} - ${f.message}`);
|
|
3948
4447
|
}
|
|
3949
4448
|
}
|
|
3950
|
-
var
|
|
4449
|
+
var listCmd9 = defineCommand20({
|
|
3951
4450
|
meta: { name: "list", description: "List installed skills (or those attached to an agent)" },
|
|
3952
4451
|
args: {
|
|
3953
4452
|
agent: { type: "string", description: "Filter to skills attached to this agent" }
|
|
@@ -3988,7 +4487,7 @@ var listCmd8 = defineCommand18({
|
|
|
3988
4487
|
}
|
|
3989
4488
|
}
|
|
3990
4489
|
});
|
|
3991
|
-
var importCmd =
|
|
4490
|
+
var importCmd = defineCommand20({
|
|
3992
4491
|
meta: {
|
|
3993
4492
|
name: "import",
|
|
3994
4493
|
description: "Import skills from openclaw, a directory, or a local .zip archive"
|
|
@@ -4057,7 +4556,7 @@ var importCmd = defineCommand18({
|
|
|
4057
4556
|
}
|
|
4058
4557
|
}
|
|
4059
4558
|
});
|
|
4060
|
-
var rmCmd4 =
|
|
4559
|
+
var rmCmd4 = defineCommand20({
|
|
4061
4560
|
meta: { name: "rm", description: "Remove an installed skill" },
|
|
4062
4561
|
args: {
|
|
4063
4562
|
name: { type: "positional", required: true }
|
|
@@ -4068,10 +4567,10 @@ var rmCmd4 = defineCommand18({
|
|
|
4068
4567
|
console.log(`removed skill ${args.name}`);
|
|
4069
4568
|
}
|
|
4070
4569
|
});
|
|
4071
|
-
var skillCommand =
|
|
4570
|
+
var skillCommand = defineCommand20({
|
|
4072
4571
|
meta: { name: "skill", description: "Manage the skill library" },
|
|
4073
4572
|
subCommands: {
|
|
4074
|
-
list:
|
|
4573
|
+
list: listCmd9,
|
|
4075
4574
|
import: importCmd,
|
|
4076
4575
|
rm: rmCmd4
|
|
4077
4576
|
}
|
|
@@ -4080,11 +4579,11 @@ var skillCommand = defineCommand18({
|
|
|
4080
4579
|
// src/commands/team.ts
|
|
4081
4580
|
import { readFileSync as readFileSync9 } from "fs";
|
|
4082
4581
|
import { stdin as stdin2 } from "process";
|
|
4083
|
-
import { defineCommand as
|
|
4582
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
4084
4583
|
|
|
4085
4584
|
// src/commands/team-policy.ts
|
|
4086
4585
|
import { readFileSync as readFileSync8 } from "fs";
|
|
4087
|
-
import { defineCommand as
|
|
4586
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
4088
4587
|
|
|
4089
4588
|
// src/team-interchange.ts
|
|
4090
4589
|
var TEAM_POLICY_INTERCHANGE_VERSION = 1;
|
|
@@ -4332,7 +4831,7 @@ function printPolicy(detail) {
|
|
|
4332
4831
|
console.log(line);
|
|
4333
4832
|
}
|
|
4334
4833
|
}
|
|
4335
|
-
var show2 =
|
|
4834
|
+
var show2 = defineCommand21({
|
|
4336
4835
|
meta: { name: "show", description: "Show the one effective live policy for a Team" },
|
|
4337
4836
|
args: {
|
|
4338
4837
|
team: { type: "positional", required: true },
|
|
@@ -4346,7 +4845,7 @@ var show2 = defineCommand19({
|
|
|
4346
4845
|
else printPolicy(detail);
|
|
4347
4846
|
}
|
|
4348
4847
|
});
|
|
4349
|
-
var exportCommand =
|
|
4848
|
+
var exportCommand = defineCommand21({
|
|
4350
4849
|
meta: { name: "export", description: "Export a revisioned Team policy document" },
|
|
4351
4850
|
args: { team: { type: "positional", required: true } },
|
|
4352
4851
|
async run({ args }) {
|
|
@@ -4370,7 +4869,7 @@ function printEdgeDiff(current, edges) {
|
|
|
4370
4869
|
for (const value of diff2.added) console.log(` + ${value}`);
|
|
4371
4870
|
for (const value of diff2.removed) console.log(` - ${value}`);
|
|
4372
4871
|
}
|
|
4373
|
-
var importCommand =
|
|
4872
|
+
var importCommand = defineCommand21({
|
|
4374
4873
|
meta: {
|
|
4375
4874
|
name: "import",
|
|
4376
4875
|
description: "Validate, diff, and explicitly replace a Team policy"
|
|
@@ -4425,7 +4924,7 @@ var importCommand = defineCommand19({
|
|
|
4425
4924
|
console.log(`updated Team ${args.team} policy to revision ${updated.teamPolicy.revision}`);
|
|
4426
4925
|
}
|
|
4427
4926
|
});
|
|
4428
|
-
var diff =
|
|
4927
|
+
var diff = defineCommand21({
|
|
4429
4928
|
meta: { name: "diff", description: "Compare live policy with its retained baseline source" },
|
|
4430
4929
|
args: {
|
|
4431
4930
|
team: { type: "positional", required: true },
|
|
@@ -4449,7 +4948,7 @@ var diff = defineCommand19({
|
|
|
4449
4948
|
);
|
|
4450
4949
|
}
|
|
4451
4950
|
});
|
|
4452
|
-
var evaluate =
|
|
4951
|
+
var evaluate = defineCommand21({
|
|
4453
4952
|
meta: {
|
|
4454
4953
|
name: "evaluate",
|
|
4455
4954
|
description: "Evaluate a communication path without sending or recording a block"
|
|
@@ -4480,7 +4979,7 @@ var evaluate = defineCommand19({
|
|
|
4480
4979
|
);
|
|
4481
4980
|
}
|
|
4482
4981
|
});
|
|
4483
|
-
var blocks =
|
|
4982
|
+
var blocks = defineCommand21({
|
|
4484
4983
|
meta: { name: "blocks", description: "List paginated durable communication denials" },
|
|
4485
4984
|
args: {
|
|
4486
4985
|
team: { type: "positional", required: true },
|
|
@@ -4529,7 +5028,7 @@ var blocks = defineCommand19({
|
|
|
4529
5028
|
if (page.nextCursor) console.log(`next cursor: ${page.nextCursor}`);
|
|
4530
5029
|
}
|
|
4531
5030
|
});
|
|
4532
|
-
var teamPolicyCommand =
|
|
5031
|
+
var teamPolicyCommand = defineCommand21({
|
|
4533
5032
|
meta: { name: "policy", description: "Inspect and manage the Team-owned live policy" },
|
|
4534
5033
|
subCommands: {
|
|
4535
5034
|
show: show2,
|
|
@@ -4542,7 +5041,7 @@ var teamPolicyCommand = defineCommand19({
|
|
|
4542
5041
|
});
|
|
4543
5042
|
|
|
4544
5043
|
// src/commands/team.ts
|
|
4545
|
-
var addCmd2 =
|
|
5044
|
+
var addCmd2 = defineCommand22({
|
|
4546
5045
|
meta: {
|
|
4547
5046
|
name: "add",
|
|
4548
5047
|
description: "Register a team at ~/.bazilion/teams/<slug>/ (use --link to point at an existing tree)"
|
|
@@ -4566,7 +5065,7 @@ var addCmd2 = defineCommand20({
|
|
|
4566
5065
|
console.log(`registered team ${g.id} at ${g.path}`);
|
|
4567
5066
|
}
|
|
4568
5067
|
});
|
|
4569
|
-
var
|
|
5068
|
+
var listCmd10 = defineCommand22({
|
|
4570
5069
|
meta: { name: "list", description: "List teams" },
|
|
4571
5070
|
async run() {
|
|
4572
5071
|
const client = createClient2();
|
|
@@ -4579,7 +5078,7 @@ var listCmd9 = defineCommand20({
|
|
|
4579
5078
|
for (const line of columnize(rows)) console.log(line);
|
|
4580
5079
|
}
|
|
4581
5080
|
});
|
|
4582
|
-
var rmCmd5 =
|
|
5081
|
+
var rmCmd5 = defineCommand22({
|
|
4583
5082
|
meta: { name: "rm", description: "Remove a team registration" },
|
|
4584
5083
|
args: {
|
|
4585
5084
|
id: { type: "positional", required: true }
|
|
@@ -4600,7 +5099,7 @@ async function readStdin() {
|
|
|
4600
5099
|
for await (const chunk of stdin2) chunks.push(chunk);
|
|
4601
5100
|
return Buffer.concat(chunks).toString("utf8");
|
|
4602
5101
|
}
|
|
4603
|
-
var userMdShowCmd =
|
|
5102
|
+
var userMdShowCmd = defineCommand22({
|
|
4604
5103
|
meta: { name: "show", description: "Print the team's USER.md" },
|
|
4605
5104
|
args: { id: { type: "positional", required: true } },
|
|
4606
5105
|
async run({ args }) {
|
|
@@ -4610,7 +5109,7 @@ var userMdShowCmd = defineCommand20({
|
|
|
4610
5109
|
if (g.userMd && !g.userMd.endsWith("\n")) process.stdout.write("\n");
|
|
4611
5110
|
}
|
|
4612
5111
|
});
|
|
4613
|
-
var userMdSetCmd =
|
|
5112
|
+
var userMdSetCmd = defineCommand22({
|
|
4614
5113
|
meta: {
|
|
4615
5114
|
name: "set",
|
|
4616
5115
|
description: "Replace the team's USER.md (from --file, --from-stdin, or inline text)"
|
|
@@ -4636,7 +5135,7 @@ var userMdSetCmd = defineCommand20({
|
|
|
4636
5135
|
console.log(`updated USER.md for team ${args.id} (${content.length} bytes)`);
|
|
4637
5136
|
}
|
|
4638
5137
|
});
|
|
4639
|
-
var userMdClearCmd =
|
|
5138
|
+
var userMdClearCmd = defineCommand22({
|
|
4640
5139
|
meta: { name: "clear", description: "Clear the team's USER.md to empty" },
|
|
4641
5140
|
args: { id: { type: "positional", required: true } },
|
|
4642
5141
|
async run({ args }) {
|
|
@@ -4646,7 +5145,7 @@ var userMdClearCmd = defineCommand20({
|
|
|
4646
5145
|
console.log(`cleared USER.md for team ${args.id}`);
|
|
4647
5146
|
}
|
|
4648
5147
|
});
|
|
4649
|
-
var userMdCmd =
|
|
5148
|
+
var userMdCmd = defineCommand22({
|
|
4650
5149
|
meta: { name: "user-md", description: "View or edit a team's USER.md" },
|
|
4651
5150
|
subCommands: {
|
|
4652
5151
|
show: userMdShowCmd,
|
|
@@ -4654,7 +5153,7 @@ var userMdCmd = defineCommand20({
|
|
|
4654
5153
|
clear: userMdClearCmd
|
|
4655
5154
|
}
|
|
4656
5155
|
});
|
|
4657
|
-
var topicFormatShowCmd =
|
|
5156
|
+
var topicFormatShowCmd = defineCommand22({
|
|
4658
5157
|
meta: { name: "show", description: "Print the team's Telegram topic-name template" },
|
|
4659
5158
|
args: { id: { type: "positional", required: true } },
|
|
4660
5159
|
async run({ args }) {
|
|
@@ -4663,7 +5162,7 @@ var topicFormatShowCmd = defineCommand20({
|
|
|
4663
5162
|
console.log(g.telegramTopicNameFormat ?? "(default naming)");
|
|
4664
5163
|
}
|
|
4665
5164
|
});
|
|
4666
|
-
var topicFormatSetCmd =
|
|
5165
|
+
var topicFormatSetCmd = defineCommand22({
|
|
4667
5166
|
meta: {
|
|
4668
5167
|
name: "set",
|
|
4669
5168
|
description: "Set the topic-name template. Tokens: {agent.name} {team.name} {team.slug} (must include {agent.name})"
|
|
@@ -4683,7 +5182,7 @@ var topicFormatSetCmd = defineCommand20({
|
|
|
4683
5182
|
console.log(`set topic-name template for team ${args.id}: ${g.telegramTopicNameFormat}`);
|
|
4684
5183
|
}
|
|
4685
5184
|
});
|
|
4686
|
-
var topicFormatClearCmd =
|
|
5185
|
+
var topicFormatClearCmd = defineCommand22({
|
|
4687
5186
|
meta: { name: "clear", description: "Clear the template (revert to built-in naming)" },
|
|
4688
5187
|
args: { id: { type: "positional", required: true } },
|
|
4689
5188
|
async run({ args }) {
|
|
@@ -4693,7 +5192,7 @@ var topicFormatClearCmd = defineCommand20({
|
|
|
4693
5192
|
console.log(`cleared topic-name template for team ${args.id}`);
|
|
4694
5193
|
}
|
|
4695
5194
|
});
|
|
4696
|
-
var topicFormatCmd =
|
|
5195
|
+
var topicFormatCmd = defineCommand22({
|
|
4697
5196
|
meta: {
|
|
4698
5197
|
name: "topic-format",
|
|
4699
5198
|
description: "View or edit a team's Telegram forum-topic name template"
|
|
@@ -4704,11 +5203,11 @@ var topicFormatCmd = defineCommand20({
|
|
|
4704
5203
|
clear: topicFormatClearCmd
|
|
4705
5204
|
}
|
|
4706
5205
|
});
|
|
4707
|
-
var teamCommand =
|
|
5206
|
+
var teamCommand = defineCommand22({
|
|
4708
5207
|
meta: { name: "team", description: "Manage teams (collaboration contexts)" },
|
|
4709
5208
|
subCommands: {
|
|
4710
5209
|
add: addCmd2,
|
|
4711
|
-
list:
|
|
5210
|
+
list: listCmd10,
|
|
4712
5211
|
rm: rmCmd5,
|
|
4713
5212
|
"user-md": userMdCmd,
|
|
4714
5213
|
"topic-format": topicFormatCmd,
|
|
@@ -4718,7 +5217,7 @@ var teamCommand = defineCommand20({
|
|
|
4718
5217
|
|
|
4719
5218
|
// src/commands/team-template.ts
|
|
4720
5219
|
import { readFileSync as readFileSync10 } from "fs";
|
|
4721
|
-
import { defineCommand as
|
|
5220
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
4722
5221
|
function jsonFile(path) {
|
|
4723
5222
|
try {
|
|
4724
5223
|
return JSON.parse(readFileSync10(path, "utf8"));
|
|
@@ -4746,7 +5245,7 @@ function printTeam(detail) {
|
|
|
4746
5245
|
console.log(line);
|
|
4747
5246
|
}
|
|
4748
5247
|
}
|
|
4749
|
-
var list4 =
|
|
5248
|
+
var list4 = defineCommand23({
|
|
4750
5249
|
meta: { name: "list", description: "List canonical Team templates" },
|
|
4751
5250
|
args: { json: { type: "boolean", description: "Emit stable JSON" } },
|
|
4752
5251
|
async run({ args }) {
|
|
@@ -4755,12 +5254,12 @@ var list4 = defineCommand21({
|
|
|
4755
5254
|
if (!rows.length) return console.log("(no Team templates)");
|
|
4756
5255
|
for (const line of columnize([
|
|
4757
5256
|
["id", "revision", "slots", "name"],
|
|
4758
|
-
...rows.map((
|
|
5257
|
+
...rows.map((row2) => [row2.id, String(row2.currentRevision), String(row2.slotCount), row2.name])
|
|
4759
5258
|
]))
|
|
4760
5259
|
console.log(line);
|
|
4761
5260
|
}
|
|
4762
5261
|
});
|
|
4763
|
-
var show3 =
|
|
5262
|
+
var show3 = defineCommand23({
|
|
4764
5263
|
meta: { name: "show", description: "Show a canonical Team template" },
|
|
4765
5264
|
args: {
|
|
4766
5265
|
id: { type: "positional", required: true },
|
|
@@ -4774,7 +5273,7 @@ var show3 = defineCommand21({
|
|
|
4774
5273
|
else printTeam(detail);
|
|
4775
5274
|
}
|
|
4776
5275
|
});
|
|
4777
|
-
var exportCommand2 =
|
|
5276
|
+
var exportCommand2 = defineCommand23({
|
|
4778
5277
|
meta: {
|
|
4779
5278
|
name: "export",
|
|
4780
5279
|
description: "Export a portable versioned Team-template document to stdout"
|
|
@@ -4814,7 +5313,7 @@ function printImportDiff(current, document) {
|
|
|
4814
5313
|
for (const value of diff2.added) console.log(` + ${value}`);
|
|
4815
5314
|
for (const value of diff2.removed) console.log(` - ${value}`);
|
|
4816
5315
|
}
|
|
4817
|
-
var importCommand2 =
|
|
5316
|
+
var importCommand2 = defineCommand23({
|
|
4818
5317
|
meta: {
|
|
4819
5318
|
name: "import",
|
|
4820
5319
|
description: "Validate, diff, and explicitly apply a portable Team-template document"
|
|
@@ -4895,7 +5394,7 @@ var importCommand2 = defineCommand21({
|
|
|
4895
5394
|
);
|
|
4896
5395
|
}
|
|
4897
5396
|
});
|
|
4898
|
-
var teamTemplateCommand =
|
|
5397
|
+
var teamTemplateCommand = defineCommand23({
|
|
4899
5398
|
meta: {
|
|
4900
5399
|
name: "team-template",
|
|
4901
5400
|
description: "Inspect and exchange canonical Team templates"
|
|
@@ -4904,8 +5403,8 @@ var teamTemplateCommand = defineCommand21({
|
|
|
4904
5403
|
});
|
|
4905
5404
|
|
|
4906
5405
|
// src/commands/telegram.ts
|
|
4907
|
-
import { defineCommand as
|
|
4908
|
-
var setCmd2 =
|
|
5406
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
5407
|
+
var setCmd2 = defineCommand24({
|
|
4909
5408
|
meta: {
|
|
4910
5409
|
name: "set",
|
|
4911
5410
|
description: "Save bot token + supergroup chat ID (paired write)"
|
|
@@ -4923,7 +5422,7 @@ var setCmd2 = defineCommand22({
|
|
|
4923
5422
|
console.log(`saved \xB7 token ${state.botTokenPreview} \xB7 chat ${state.chatId}`);
|
|
4924
5423
|
}
|
|
4925
5424
|
});
|
|
4926
|
-
var clearCmd =
|
|
5425
|
+
var clearCmd = defineCommand24({
|
|
4927
5426
|
meta: {
|
|
4928
5427
|
name: "clear",
|
|
4929
5428
|
description: "Remove stored bot token + chat ID"
|
|
@@ -4934,7 +5433,7 @@ var clearCmd = defineCommand22({
|
|
|
4934
5433
|
console.log("cleared");
|
|
4935
5434
|
}
|
|
4936
5435
|
});
|
|
4937
|
-
var showCmd5 =
|
|
5436
|
+
var showCmd5 = defineCommand24({
|
|
4938
5437
|
meta: {
|
|
4939
5438
|
name: "show",
|
|
4940
5439
|
description: "Show what credentials are stored (token is masked)"
|
|
@@ -4955,7 +5454,7 @@ var showCmd5 = defineCommand22({
|
|
|
4955
5454
|
}
|
|
4956
5455
|
}
|
|
4957
5456
|
});
|
|
4958
|
-
var reconnectCmd =
|
|
5457
|
+
var reconnectCmd = defineCommand24({
|
|
4959
5458
|
meta: {
|
|
4960
5459
|
name: "reconnect",
|
|
4961
5460
|
description: "Apply a pending supergroup chat-id migration + re-activate the bot"
|
|
@@ -4966,7 +5465,7 @@ var reconnectCmd = defineCommand22({
|
|
|
4966
5465
|
console.log(`reconnected \xB7 chat ${state.chatId}`);
|
|
4967
5466
|
}
|
|
4968
5467
|
});
|
|
4969
|
-
var configCmd =
|
|
5468
|
+
var configCmd = defineCommand24({
|
|
4970
5469
|
meta: {
|
|
4971
5470
|
name: "config",
|
|
4972
5471
|
description: "Manage Telegram credentials (bot token + chat ID)"
|
|
@@ -4977,7 +5476,7 @@ var configCmd = defineCommand22({
|
|
|
4977
5476
|
show: showCmd5
|
|
4978
5477
|
}
|
|
4979
5478
|
});
|
|
4980
|
-
var healthCmd =
|
|
5479
|
+
var healthCmd = defineCommand24({
|
|
4981
5480
|
meta: {
|
|
4982
5481
|
name: "health",
|
|
4983
5482
|
description: "Run the four-step preflight against the Telegram Bot API"
|
|
@@ -5007,11 +5506,16 @@ var healthCmd = defineCommand22({
|
|
|
5007
5506
|
console.log(line(p.isForum, "forum topics enabled", String(p.isForum)));
|
|
5008
5507
|
console.log(line(p.hasManageTopics, "can_manage_topics", String(p.hasManageTopics)));
|
|
5009
5508
|
console.log(line(p.privacyModeOff, "Privacy Mode is OFF", String(p.privacyModeOff)));
|
|
5010
|
-
|
|
5509
|
+
console.log(line(p.chatIsPrivate, "supergroup is private", String(p.chatIsPrivate)));
|
|
5510
|
+
console.log(line(p.memberCount === 2, "one owner + bot", String(p.memberCount ?? "unknown")));
|
|
5511
|
+
if (p.ownerPresent !== null) {
|
|
5512
|
+
console.log(line(p.ownerPresent, "paired owner is present", String(p.ownerPresent)));
|
|
5513
|
+
}
|
|
5514
|
+
const allOk = p.botUsername.length > 0 && p.chatTitle.length > 0 && p.isForum && p.hasManageTopics && p.privacyModeOff && p.chatIsPrivate && p.memberCount === 2 && p.ownerPresent !== false;
|
|
5011
5515
|
if (!allOk) process.exitCode = 1;
|
|
5012
5516
|
}
|
|
5013
5517
|
});
|
|
5014
|
-
var botStatusCmd =
|
|
5518
|
+
var botStatusCmd = defineCommand24({
|
|
5015
5519
|
meta: {
|
|
5016
5520
|
name: "status",
|
|
5017
5521
|
description: "Show polling state of the live bot"
|
|
@@ -5036,7 +5540,7 @@ var botStatusCmd = defineCommand22({
|
|
|
5036
5540
|
if (!p.running) process.exitCode = 1;
|
|
5037
5541
|
}
|
|
5038
5542
|
});
|
|
5039
|
-
var botRestartCmd =
|
|
5543
|
+
var botRestartCmd = defineCommand24({
|
|
5040
5544
|
meta: {
|
|
5041
5545
|
name: "restart",
|
|
5042
5546
|
description: "Force-restart the bot (tears down + brings up from current creds)"
|
|
@@ -5047,7 +5551,7 @@ var botRestartCmd = defineCommand22({
|
|
|
5047
5551
|
console.log("restart requested");
|
|
5048
5552
|
}
|
|
5049
5553
|
});
|
|
5050
|
-
var botCmd =
|
|
5554
|
+
var botCmd = defineCommand24({
|
|
5051
5555
|
meta: {
|
|
5052
5556
|
name: "bot",
|
|
5053
5557
|
description: "Inspect / control the live polling bot"
|
|
@@ -5057,7 +5561,7 @@ var botCmd = defineCommand22({
|
|
|
5057
5561
|
restart: botRestartCmd
|
|
5058
5562
|
}
|
|
5059
5563
|
});
|
|
5060
|
-
var bindCmd =
|
|
5564
|
+
var bindCmd = defineCommand24({
|
|
5061
5565
|
meta: {
|
|
5062
5566
|
name: "bind",
|
|
5063
5567
|
description: "Create a Telegram topic for an agent (manual fallback for /talk)"
|
|
@@ -5075,7 +5579,7 @@ var bindCmd = defineCommand22({
|
|
|
5075
5579
|
console.log(` ${result.deepLink}`);
|
|
5076
5580
|
}
|
|
5077
5581
|
});
|
|
5078
|
-
var unbindCmd =
|
|
5582
|
+
var unbindCmd = defineCommand24({
|
|
5079
5583
|
meta: {
|
|
5080
5584
|
name: "unbind",
|
|
5081
5585
|
description: "Clear an agent's Telegram topic binding (topic stays in Telegram as orphan)"
|
|
@@ -5089,7 +5593,7 @@ var unbindCmd = defineCommand22({
|
|
|
5089
5593
|
console.log(`unbound agent ${args.agent}`);
|
|
5090
5594
|
}
|
|
5091
5595
|
});
|
|
5092
|
-
var listBindingsCmd =
|
|
5596
|
+
var listBindingsCmd = defineCommand24({
|
|
5093
5597
|
meta: {
|
|
5094
5598
|
name: "list",
|
|
5095
5599
|
description: "List agents and their Telegram topic bindings"
|
|
@@ -5117,24 +5621,23 @@ var listBindingsCmd = defineCommand22({
|
|
|
5117
5621
|
}
|
|
5118
5622
|
}
|
|
5119
5623
|
});
|
|
5120
|
-
var allowCmd =
|
|
5624
|
+
var allowCmd = defineCommand24({
|
|
5121
5625
|
meta: { name: "allow", description: "Add a Telegram user id to the allowlist" },
|
|
5122
5626
|
args: {
|
|
5123
5627
|
userId: { type: "positional", required: true, description: "Numeric Telegram user id" },
|
|
5124
|
-
label: { type: "string", description: "Optional human label" }
|
|
5125
|
-
owner: { type: "boolean", description: "Grant owner role (can manage the allowlist)" }
|
|
5628
|
+
label: { type: "string", description: "Optional human label" }
|
|
5126
5629
|
},
|
|
5127
5630
|
async run({ args }) {
|
|
5128
5631
|
const client = createClient2();
|
|
5129
5632
|
const u = await client.post("/api/config/telegram/acl", {
|
|
5130
5633
|
userId: Number(args.userId),
|
|
5131
5634
|
label: args.label ?? null,
|
|
5132
|
-
role:
|
|
5635
|
+
role: "member"
|
|
5133
5636
|
});
|
|
5134
5637
|
console.log(`allowed ${u.userId} (${u.role})`);
|
|
5135
5638
|
}
|
|
5136
5639
|
});
|
|
5137
|
-
var denyCmd =
|
|
5640
|
+
var denyCmd = defineCommand24({
|
|
5138
5641
|
meta: { name: "deny", description: "Remove a Telegram user id from the allowlist" },
|
|
5139
5642
|
args: { userId: { type: "positional", required: true } },
|
|
5140
5643
|
async run({ args }) {
|
|
@@ -5143,13 +5646,13 @@ var denyCmd = defineCommand22({
|
|
|
5143
5646
|
console.log(`removed ${args.userId}`);
|
|
5144
5647
|
}
|
|
5145
5648
|
});
|
|
5146
|
-
var allowedCmd =
|
|
5649
|
+
var allowedCmd = defineCommand24({
|
|
5147
5650
|
meta: { name: "allowed", description: "List allowlisted Telegram users" },
|
|
5148
5651
|
async run() {
|
|
5149
5652
|
const client = createClient2();
|
|
5150
5653
|
const users = await client.get("/api/config/telegram/acl");
|
|
5151
5654
|
if (users.length === 0) {
|
|
5152
|
-
console.log("(allowlist empty \u2014
|
|
5655
|
+
console.log("(allowlist empty \u2014 unpaired and closed)");
|
|
5153
5656
|
return;
|
|
5154
5657
|
}
|
|
5155
5658
|
for (const u of users) {
|
|
@@ -5158,7 +5661,56 @@ var allowedCmd = defineCommand22({
|
|
|
5158
5661
|
}
|
|
5159
5662
|
}
|
|
5160
5663
|
});
|
|
5161
|
-
var
|
|
5664
|
+
var pairingCreateCmd = defineCommand24({
|
|
5665
|
+
meta: { name: "create", description: "Generate a one-time Telegram owner pairing code" },
|
|
5666
|
+
async run() {
|
|
5667
|
+
const result = await createClient2().post(
|
|
5668
|
+
"/api/config/telegram/pairing/challenge"
|
|
5669
|
+
);
|
|
5670
|
+
console.log(`pairing code: ${result.code}`);
|
|
5671
|
+
console.log(`expires: ${new Date(result.expiresAt).toISOString()}`);
|
|
5672
|
+
console.log("send `/pair <code>` in the configured \u2699 bazilion service topic");
|
|
5673
|
+
}
|
|
5674
|
+
});
|
|
5675
|
+
var pairingStatusCmd = defineCommand24({
|
|
5676
|
+
meta: { name: "status", description: "Show Telegram owner pairing status" },
|
|
5677
|
+
async run() {
|
|
5678
|
+
const result = await createClient2().get("/api/config/telegram/pairing");
|
|
5679
|
+
console.log(`paired: ${result.paired}`);
|
|
5680
|
+
console.log(`owner: ${result.ownerUserId ?? "(none)"}`);
|
|
5681
|
+
console.log(`challenge active: ${result.challengeActive}`);
|
|
5682
|
+
if (result.challengeExpiresAt)
|
|
5683
|
+
console.log(`expires: ${new Date(result.challengeExpiresAt).toISOString()}`);
|
|
5684
|
+
}
|
|
5685
|
+
});
|
|
5686
|
+
var pairingCancelCmd = defineCommand24({
|
|
5687
|
+
meta: { name: "cancel", description: "Cancel the active Telegram pairing code" },
|
|
5688
|
+
async run() {
|
|
5689
|
+
await createClient2().del("/api/config/telegram/pairing/challenge");
|
|
5690
|
+
console.log("pairing challenge cancelled");
|
|
5691
|
+
}
|
|
5692
|
+
});
|
|
5693
|
+
var pairingResetCmd = defineCommand24({
|
|
5694
|
+
meta: { name: "reset", description: "Revoke the Telegram owner and require re-pairing" },
|
|
5695
|
+
args: {
|
|
5696
|
+
yes: { type: "boolean", description: "Confirm destructive owner reset", required: true }
|
|
5697
|
+
},
|
|
5698
|
+
async run({ args }) {
|
|
5699
|
+
if (!args.yes) throw new Error("--yes is required");
|
|
5700
|
+
await createClient2().post("/api/config/telegram/pairing/reset", { confirm: true });
|
|
5701
|
+
console.log("Telegram owner reset; ingress is closed until re-paired");
|
|
5702
|
+
}
|
|
5703
|
+
});
|
|
5704
|
+
var pairingCmd = defineCommand24({
|
|
5705
|
+
meta: { name: "pairing", description: "Manage single-owner Telegram pairing" },
|
|
5706
|
+
subCommands: {
|
|
5707
|
+
create: pairingCreateCmd,
|
|
5708
|
+
status: pairingStatusCmd,
|
|
5709
|
+
cancel: pairingCancelCmd,
|
|
5710
|
+
reset: pairingResetCmd
|
|
5711
|
+
}
|
|
5712
|
+
});
|
|
5713
|
+
var telegramCommand = defineCommand24({
|
|
5162
5714
|
meta: {
|
|
5163
5715
|
name: "telegram",
|
|
5164
5716
|
description: "Telegram integration: credentials, health, bot lifecycle, bindings, access"
|
|
@@ -5173,47 +5725,42 @@ var telegramCommand = defineCommand22({
|
|
|
5173
5725
|
list: listBindingsCmd,
|
|
5174
5726
|
allow: allowCmd,
|
|
5175
5727
|
deny: denyCmd,
|
|
5176
|
-
allowed: allowedCmd
|
|
5728
|
+
allowed: allowedCmd,
|
|
5729
|
+
pairing: pairingCmd
|
|
5177
5730
|
}
|
|
5178
5731
|
});
|
|
5179
5732
|
|
|
5180
5733
|
// src/commands/token.ts
|
|
5181
|
-
import {
|
|
5182
|
-
import { defineCommand as defineCommand23 } from "citty";
|
|
5734
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
5183
5735
|
import qrcode from "qrcode-terminal";
|
|
5184
5736
|
function tokenRow(t) {
|
|
5185
5737
|
const last = t.lastUsedAt ? new Date(t.lastUsedAt).toISOString() : "(never)";
|
|
5186
|
-
const
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
const candidates = [];
|
|
5191
|
-
for (const ifs of Object.values(networkInterfaces())) {
|
|
5192
|
-
for (const i of ifs ?? []) {
|
|
5193
|
-
if (i.family === "IPv4" && !i.internal) candidates.push(i.address);
|
|
5194
|
-
}
|
|
5195
|
-
}
|
|
5196
|
-
const [first, ...rest] = candidates;
|
|
5197
|
-
if (!first) return null;
|
|
5198
|
-
const origin = `http://${first}:${port}`;
|
|
5199
|
-
return rest.length > 0 ? { origin, warning: `multiple LAN IPs found (${candidates.join(", ")}) \u2014 using ${first}` } : { origin };
|
|
5738
|
+
const expired = t.expiresAt !== null && t.expiresAt <= Date.now();
|
|
5739
|
+
const state = t.revokedAt ? "revoked" : expired ? "expired" : "active";
|
|
5740
|
+
const expires = t.expiresAt ? new Date(t.expiresAt).toISOString() : "(never)";
|
|
5741
|
+
return [t.id, t.kind, state, t.label, `expires: ${expires}`, `last: ${last}`];
|
|
5200
5742
|
}
|
|
5201
5743
|
function resolveQrServer(override) {
|
|
5202
|
-
|
|
5744
|
+
const raw = override ?? loadClientConfig().serverUrl;
|
|
5745
|
+
const url = new URL(raw);
|
|
5746
|
+
const loopback = ["127.0.0.1", "localhost", "[::1]", "::1"].includes(url.hostname);
|
|
5747
|
+
if (url.protocol !== "https:" && !(url.protocol === "http:" && loopback)) {
|
|
5748
|
+
throw new Error("pairing server must use HTTPS (HTTP is allowed only for loopback development)");
|
|
5749
|
+
}
|
|
5750
|
+
if (url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
|
|
5751
|
+
throw new Error(
|
|
5752
|
+
"pairing server must be an exact origin without credentials, path, query, or fragment"
|
|
5753
|
+
);
|
|
5754
|
+
}
|
|
5203
5755
|
const cfg = loadClientConfig();
|
|
5204
|
-
|
|
5205
|
-
const isLoopback = current.hostname === "127.0.0.1" || current.hostname === "localhost" || current.hostname === "::1";
|
|
5206
|
-
if (!isLoopback) return cfg.serverUrl.replace(/\/$/, "");
|
|
5207
|
-
const detected = detectLanOrigin(current.port || "4321");
|
|
5208
|
-
if (!detected) {
|
|
5756
|
+
if (loopback && !override && new URL(cfg.serverUrl).hostname === url.hostname) {
|
|
5209
5757
|
throw new Error(
|
|
5210
|
-
"server URL is loopback-only
|
|
5758
|
+
"server URL is loopback-only. Pass --server https://<private-tailnet-host> for mobile pairing."
|
|
5211
5759
|
);
|
|
5212
5760
|
}
|
|
5213
|
-
|
|
5214
|
-
return detected.origin;
|
|
5761
|
+
return url.origin;
|
|
5215
5762
|
}
|
|
5216
|
-
var createCmd3 =
|
|
5763
|
+
var createCmd3 = defineCommand25({
|
|
5217
5764
|
meta: { name: "create", description: "Mint a new web token (shown once)" },
|
|
5218
5765
|
args: {
|
|
5219
5766
|
label: { type: "positional", required: true, description: "Human-readable label" },
|
|
@@ -5224,14 +5771,26 @@ var createCmd3 = defineCommand23({
|
|
|
5224
5771
|
server: {
|
|
5225
5772
|
type: "string",
|
|
5226
5773
|
description: "Server URL to embed in the pairing QR (default: detect LAN IP; ignored without --qr)"
|
|
5774
|
+
},
|
|
5775
|
+
expiresDays: {
|
|
5776
|
+
type: "string",
|
|
5777
|
+
description: "Device lifetime in days (default 90, maximum 365)"
|
|
5227
5778
|
}
|
|
5228
5779
|
},
|
|
5229
5780
|
async run({ args }) {
|
|
5230
5781
|
const client = createClient2();
|
|
5231
|
-
const
|
|
5782
|
+
const expiresInDays = args.expiresDays === void 0 ? void 0 : Number(args.expiresDays);
|
|
5783
|
+
if (expiresInDays !== void 0 && !Number.isInteger(expiresInDays)) {
|
|
5784
|
+
throw new Error("--expires-days must be an integer");
|
|
5785
|
+
}
|
|
5786
|
+
const body = { label: args.label, expiresInDays };
|
|
5232
5787
|
const res = await client.post("/api/tokens", body);
|
|
5233
5788
|
console.log(`id: ${res.meta.id}`);
|
|
5234
5789
|
console.log(`label: ${res.meta.label}`);
|
|
5790
|
+
console.log(`kind: ${res.meta.kind}`);
|
|
5791
|
+
console.log(
|
|
5792
|
+
`expires: ${res.meta.expiresAt ? new Date(res.meta.expiresAt).toISOString() : "(never)"}`
|
|
5793
|
+
);
|
|
5235
5794
|
console.log(`token: ${res.token}`);
|
|
5236
5795
|
console.log("");
|
|
5237
5796
|
console.log("store the token now \u2014 it is not recoverable later.");
|
|
@@ -5244,7 +5803,7 @@ var createCmd3 = defineCommand23({
|
|
|
5244
5803
|
qrcode.generate(pairUrl, { small: true }, (qr) => console.log(qr));
|
|
5245
5804
|
}
|
|
5246
5805
|
});
|
|
5247
|
-
var
|
|
5806
|
+
var listCmd11 = defineCommand25({
|
|
5248
5807
|
meta: { name: "list", description: "List web tokens" },
|
|
5249
5808
|
args: {
|
|
5250
5809
|
all: { type: "boolean", description: "Include revoked tokens" }
|
|
@@ -5260,7 +5819,7 @@ var listCmd10 = defineCommand23({
|
|
|
5260
5819
|
for (const line of columnize(tokens.map(tokenRow))) console.log(line);
|
|
5261
5820
|
}
|
|
5262
5821
|
});
|
|
5263
|
-
var showLocalCmd =
|
|
5822
|
+
var showLocalCmd = defineCommand25({
|
|
5264
5823
|
meta: {
|
|
5265
5824
|
name: "show-local",
|
|
5266
5825
|
description: "Print the bootstrap web token stored in ~/.bazilion/auth.json"
|
|
@@ -5270,7 +5829,7 @@ var showLocalCmd = defineCommand23({
|
|
|
5270
5829
|
console.log(readAuthFile(paths.authFile).token);
|
|
5271
5830
|
}
|
|
5272
5831
|
});
|
|
5273
|
-
var
|
|
5832
|
+
var revokeCmd2 = defineCommand25({
|
|
5274
5833
|
meta: { name: "revoke", description: "Revoke a web token" },
|
|
5275
5834
|
args: {
|
|
5276
5835
|
id: { type: "positional", required: true }
|
|
@@ -5281,19 +5840,19 @@ var revokeCmd = defineCommand23({
|
|
|
5281
5840
|
console.log(`revoked token ${args.id}`);
|
|
5282
5841
|
}
|
|
5283
5842
|
});
|
|
5284
|
-
var tokenCommand =
|
|
5843
|
+
var tokenCommand = defineCommand25({
|
|
5285
5844
|
meta: { name: "token", description: "Manage web tokens for API/CLI clients" },
|
|
5286
5845
|
subCommands: {
|
|
5287
5846
|
create: createCmd3,
|
|
5288
|
-
list:
|
|
5289
|
-
revoke:
|
|
5847
|
+
list: listCmd11,
|
|
5848
|
+
revoke: revokeCmd2,
|
|
5290
5849
|
"show-local": showLocalCmd
|
|
5291
5850
|
}
|
|
5292
5851
|
});
|
|
5293
5852
|
|
|
5294
5853
|
// src/commands/trigger.ts
|
|
5295
|
-
import { defineCommand as
|
|
5296
|
-
var addCmd3 =
|
|
5854
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
5855
|
+
var addCmd3 = defineCommand26({
|
|
5297
5856
|
meta: { name: "add", description: "Add an interval / cron trigger to an agent" },
|
|
5298
5857
|
args: {
|
|
5299
5858
|
agent: { type: "positional", required: true },
|
|
@@ -5341,7 +5900,7 @@ function triggerRow(t) {
|
|
|
5341
5900
|
const msgPreview = t.message.length > 60 ? `${t.message.slice(0, 60)}\u2026` : t.message;
|
|
5342
5901
|
return [t.id, state, spec, `last: ${last}`, `"${msgPreview}"`];
|
|
5343
5902
|
}
|
|
5344
|
-
var
|
|
5903
|
+
var listCmd12 = defineCommand26({
|
|
5345
5904
|
meta: { name: "list", description: "List triggers for an agent" },
|
|
5346
5905
|
args: {
|
|
5347
5906
|
agent: { type: "positional", required: true }
|
|
@@ -5358,7 +5917,7 @@ var listCmd11 = defineCommand24({
|
|
|
5358
5917
|
for (const line of columnize(triggers.map(triggerRow))) console.log(line);
|
|
5359
5918
|
}
|
|
5360
5919
|
});
|
|
5361
|
-
var rmCmd6 =
|
|
5920
|
+
var rmCmd6 = defineCommand26({
|
|
5362
5921
|
meta: { name: "rm", description: "Delete a trigger" },
|
|
5363
5922
|
args: {
|
|
5364
5923
|
id: { type: "positional", required: true }
|
|
@@ -5369,7 +5928,7 @@ var rmCmd6 = defineCommand24({
|
|
|
5369
5928
|
console.log(`removed trigger ${args.id}`);
|
|
5370
5929
|
}
|
|
5371
5930
|
});
|
|
5372
|
-
var enableCmd3 =
|
|
5931
|
+
var enableCmd3 = defineCommand26({
|
|
5373
5932
|
meta: { name: "enable", description: "Enable a trigger" },
|
|
5374
5933
|
args: {
|
|
5375
5934
|
id: { type: "positional", required: true }
|
|
@@ -5381,7 +5940,7 @@ var enableCmd3 = defineCommand24({
|
|
|
5381
5940
|
console.log(`enabled trigger ${args.id}`);
|
|
5382
5941
|
}
|
|
5383
5942
|
});
|
|
5384
|
-
var disableCmd3 =
|
|
5943
|
+
var disableCmd3 = defineCommand26({
|
|
5385
5944
|
meta: { name: "disable", description: "Disable a trigger" },
|
|
5386
5945
|
args: {
|
|
5387
5946
|
id: { type: "positional", required: true }
|
|
@@ -5393,7 +5952,7 @@ var disableCmd3 = defineCommand24({
|
|
|
5393
5952
|
console.log(`disabled trigger ${args.id}`);
|
|
5394
5953
|
}
|
|
5395
5954
|
});
|
|
5396
|
-
var historyCmd =
|
|
5955
|
+
var historyCmd = defineCommand26({
|
|
5397
5956
|
meta: { name: "history", description: "Show recent dispatches for a trigger" },
|
|
5398
5957
|
args: {
|
|
5399
5958
|
id: { type: "positional", required: true },
|
|
@@ -5421,11 +5980,11 @@ var historyCmd = defineCommand24({
|
|
|
5421
5980
|
for (const line of columnize(rows)) console.log(line);
|
|
5422
5981
|
}
|
|
5423
5982
|
});
|
|
5424
|
-
var triggerCommand =
|
|
5983
|
+
var triggerCommand = defineCommand26({
|
|
5425
5984
|
meta: { name: "trigger", description: "Manage scheduled agent triggers" },
|
|
5426
5985
|
subCommands: {
|
|
5427
5986
|
add: addCmd3,
|
|
5428
|
-
list:
|
|
5987
|
+
list: listCmd12,
|
|
5429
5988
|
rm: rmCmd6,
|
|
5430
5989
|
enable: enableCmd3,
|
|
5431
5990
|
disable: disableCmd3,
|
|
@@ -5436,7 +5995,7 @@ var triggerCommand = defineCommand24({
|
|
|
5436
5995
|
// src/commands/uninstall.ts
|
|
5437
5996
|
import { existsSync as existsSync7, readdirSync as readdirSync2, rmSync as rmSync4 } from "fs";
|
|
5438
5997
|
import { join as join6 } from "path";
|
|
5439
|
-
import { defineCommand as
|
|
5998
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
5440
5999
|
function makeLineReader() {
|
|
5441
6000
|
let buffer = "";
|
|
5442
6001
|
let ended = false;
|
|
@@ -5484,7 +6043,7 @@ function removePath(p) {
|
|
|
5484
6043
|
rmSync4(p, { recursive: true, force: true });
|
|
5485
6044
|
return true;
|
|
5486
6045
|
}
|
|
5487
|
-
var uninstallCommand =
|
|
6046
|
+
var uninstallCommand = defineCommand27({
|
|
5488
6047
|
meta: {
|
|
5489
6048
|
name: "uninstall",
|
|
5490
6049
|
description: "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"
|
|
@@ -5555,7 +6114,7 @@ var uninstallCommand = defineCommand25({
|
|
|
5555
6114
|
|
|
5556
6115
|
// src/index.ts
|
|
5557
6116
|
var VERSION = package_default.version;
|
|
5558
|
-
var main =
|
|
6117
|
+
var main = defineCommand28({
|
|
5559
6118
|
meta: {
|
|
5560
6119
|
name: "bazilion",
|
|
5561
6120
|
version: VERSION,
|
|
@@ -5574,11 +6133,13 @@ var main = defineCommand26({
|
|
|
5574
6133
|
mcp: mcpCommand,
|
|
5575
6134
|
provider: providerCommand,
|
|
5576
6135
|
send: sendCommand,
|
|
6136
|
+
session: sessionCommand,
|
|
5577
6137
|
inbox: inboxCommand,
|
|
5578
6138
|
config: configCommand,
|
|
5579
6139
|
serve: serveCommand,
|
|
5580
6140
|
dashboard: dashboardCommand,
|
|
5581
6141
|
doctor: doctorCommand,
|
|
6142
|
+
gateway: gatewayCommand,
|
|
5582
6143
|
backup: backupCommand,
|
|
5583
6144
|
trigger: triggerCommand,
|
|
5584
6145
|
token: tokenCommand,
|
|
@@ -5678,7 +6239,7 @@ function printTopLevelHelp() {
|
|
|
5678
6239
|
},
|
|
5679
6240
|
{
|
|
5680
6241
|
title: "ops",
|
|
5681
|
-
items: [["backup", "
|
|
6242
|
+
items: [["backup", "Encrypted backup, restore, and credential recovery"]]
|
|
5682
6243
|
},
|
|
5683
6244
|
{
|
|
5684
6245
|
title: "remote",
|