bazilion 0.12.2 → 0.14.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 +2 -2
- package/dist/cli.js +795 -240
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +4555 -1280
- package/dist/daemon.js.map +1 -1
- package/dist/migrations/0001_init.sql +21 -0
- package/dist/web/client/assets/AgentTabs-BcmmwYJc.js +1 -0
- package/dist/web/client/assets/ConfigPage-BCLp-FUC.js +1 -0
- package/dist/web/client/assets/ConfirmDialog-CyL9A20V.js +1 -0
- package/dist/web/client/assets/FieldRow-D6REbYUa.js +1 -0
- package/dist/web/client/assets/Page-NV96O47A.js +1 -0
- package/dist/web/client/assets/ProductionTeamPolicyEditor-DBKnOezm.js +7 -0
- package/dist/web/client/assets/{ProfileCommunicationEditor-C43HvUe-.js → ProfileCommunicationEditor-4RK2laqO.js} +1 -1
- package/dist/web/client/assets/SectionTabs-4kCQXuFY.js +1 -0
- package/dist/web/client/assets/TeamTabs-CdtNEqt4.js +1 -0
- package/dist/web/client/assets/{TemplatesTabs-6Jd_xQj7.js → TemplatesTabs-CZyss2Y0.js} +1 -1
- package/dist/web/client/assets/UnsavedChangesGuard-CEoK-ZcN.js +1 -0
- package/dist/web/client/assets/_id-4ZS-w_Aj.js +1 -0
- package/dist/web/client/assets/{_id-AOAT0H_5.js → _id-DIqtdQij.js} +1 -1
- package/dist/web/client/assets/_id-DbcC2E7F.js +1 -0
- package/dist/web/client/assets/_id-f_r5M0p3.js +1 -0
- package/dist/web/client/assets/activity-CB9Ufth-.js +1 -0
- package/dist/web/client/assets/agents-D-JGXVg9.js +1 -0
- package/dist/web/client/assets/agents-DS2XafoA.js +1 -0
- package/dist/web/client/assets/approvals-Cke_mrJv.js +1 -0
- package/dist/web/client/assets/attention-PYwRM2wC.js +1 -0
- package/dist/web/client/assets/chevron-right-BG4OeFRQ.js +1 -0
- package/dist/web/client/assets/config-DF9Gqmfa.js +3 -0
- 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-Bn1GbUsJ.js → inbox-DC_HdOfI.js} +1 -1
- package/dist/web/client/assets/index-Cofc7zhl.css +1 -0
- package/dist/web/client/assets/index-Cp6UHWr2.js +52 -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-BfrQ4YZY.js +1 -0
- package/dist/web/client/assets/login-D4n3AcBR.js +1 -0
- package/dist/web/client/assets/mcp-CnjQc_JJ.js +1 -0
- package/dist/web/client/assets/members-wxsVTJdW.js +1 -0
- package/dist/web/client/assets/memory-Du60O3pE.js +1 -0
- package/dist/web/client/assets/{policy-DaijITy7.js → policy-BOfnkJsL.js} +1 -1
- package/dist/web/client/assets/{preload-helper-mNuBjNXU.js → preload-helper-bztXdkDj.js} +1 -1
- package/dist/web/client/assets/routes-B9CuhzUW.js +1 -0
- package/dist/web/client/assets/services-DyvqJqM2.js +1 -0
- package/dist/web/client/assets/skills-DQo7ioW7.js +1 -0
- package/dist/web/client/assets/styles-B5vcgXln.css +2 -0
- package/dist/web/client/assets/{teams-D92R9Pb7.js → teams-DPggy97H.js} +1 -1
- package/dist/web/client/assets/teams-DdawcfNR.js +1 -0
- package/dist/web/client/assets/telegram-DcTeDpP5.js +1 -0
- package/dist/web/client/assets/tokens-CIEKwZXc.js +1 -0
- package/dist/web/client/assets/triggers-Bc2RrUPm.js +1 -0
- package/dist/web/client/assets/utils-B6KiDbIe.js +1 -0
- package/dist/web/client/assets/welcome-DlhNXUIa.js +1 -0
- package/dist/web/client/assets/wire-constants-BzdHSc6A.js +74 -0
- package/dist/web/client/assets/x-DAXGIe_Q.js +1 -0
- package/dist/web/server/assets/{AgentTabs-aXdsiiMp.js → AgentTabs-Dq8hDM2Q.js} +9 -2
- package/dist/web/server/assets/{ChatPane-Ba5wTsVk.js → ChatPane-CgSe7tsy.js} +81 -43
- package/dist/web/server/assets/{ConfigPage-BKlh5vOU.js → ConfigPage-CiQ-gxmJ.js} +3 -2
- package/dist/web/server/assets/ConfirmDialog-C-MPYYSU.js +99 -0
- package/dist/web/server/assets/FieldRow-DCOF07kl.js +160 -0
- package/dist/web/server/assets/{Page-LENulSXY.js → Page-Bz-ydB8j.js} +4 -10
- package/dist/web/server/assets/{ProductionTeamPolicyEditor-Y4mzFFvR.js → ProductionTeamPolicyEditor-DQSdP7Yx.js} +140 -123
- package/dist/web/server/assets/{SectionTabs-BJTPr5nU.js → SectionTabs-B2Yw81XN.js} +2 -2
- package/dist/web/server/assets/{Sidebar-DsRVCszF.js → Sidebar-DKyk7oIo.js} +563 -283
- package/dist/web/server/assets/{TeamTabs-zZzbP1t_.js → TeamTabs-Co3n2exj.js} +2 -6
- package/dist/web/server/assets/{TemplatesTabs-CcRxZhJe.js → TemplatesTabs-B0fA361R.js} +1 -1
- package/dist/web/server/assets/UnsavedChangesGuard-CiStXyBI.js +40 -0
- package/dist/web/server/assets/{_id-Dj1yZ3zJ.js → _id-BAA9KJBU.js} +4 -4
- package/dist/web/server/assets/{_id-LrvXU4Nr.js → _id-BM5m2FLT.js} +4 -4
- package/dist/web/server/assets/{_id-CwyGjJeP.js → _id-BYKpT2Tu.js} +4 -5
- package/dist/web/server/assets/{_id-BHYLL8M-.js → _id-BeKhPKw3.js} +350 -185
- package/dist/web/server/assets/{_id-C3HY4lWg.js → _id-BqWTB8Wl.js} +188 -86
- package/dist/web/server/assets/{_id-DinTp_7X.js → _id-BwvCtzlD.js} +3 -3
- package/dist/web/server/assets/{_id-D27T85mU.js → _id-DYU6uIBx.js} +4 -5
- 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-D3Ap7zZA.js → _id-ndxFHx0t.js} +75 -71
- package/dist/web/server/assets/{_id-FcHdSocl.js → _id-sNu5aXZt.js} +5 -4
- package/dist/web/server/assets/{_tanstack-start-manifest_v-BGDBdnUs.js → _tanstack-start-manifest_v-C-OiOZeM.js} +118 -94
- package/dist/web/server/assets/{activity-DohitgwW.js → activity-9VP6QDTH.js} +3 -3
- package/dist/web/server/assets/{activity-BCI4mfNS.js → activity-BWv1goK6.js} +3 -3
- package/dist/web/server/assets/{activity-D9SMqBhy.js → activity-LjpblbDL.js} +3 -3
- package/dist/web/server/assets/{agents-C9xlWK0Z.js → agents-BDFGrU3o.js} +4 -4
- package/dist/web/server/assets/{agents-BY74v7fM.js → agents-BJAv919x.js} +3 -3
- package/dist/web/server/assets/{agents-BvttypqB.js → agents-CJk4pxKu.js} +3 -3
- package/dist/web/server/assets/{agents-CgZMHj80.js → agents-CYw1xHoY.js} +138 -16
- package/dist/web/server/assets/{agents-DZuFEj0D.js → agents-DfNKc_Q7.js} +52 -8
- package/dist/web/server/assets/{agents-BPKOshR5.js → agents-DjyQk94u.js} +4 -4
- package/dist/web/server/assets/{approvals-CWcFHlor.js → approvals-7JOoBchn.js} +3 -3
- package/dist/web/server/assets/{approvals-BGU-XGIO.js → approvals-BYi84gwl.js} +3 -3
- package/dist/web/server/assets/{approvals-DCaVw1Mz.js → approvals-Bz123liE.js} +59 -21
- package/dist/web/server/assets/{attention-BxkTf337.js → attention-B35JvhOL.js} +3 -3
- package/dist/web/server/assets/{attention-w21GQIGH.js → attention-C1pPWSXw.js} +3 -3
- package/dist/web/server/assets/{attention-CM-Ks1N9.js → attention-UhqPK_Ro.js} +3 -3
- 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-1w2GiJUn.js → config-BlMkHStx.js} +3 -3
- package/dist/web/server/assets/config-ExacOzHX.js +958 -0
- 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-CzlKT9Wg.js → inbox-Dv55rGYq.js} +4 -4
- package/dist/web/server/assets/{inbox-BLUzA5sQ.js → inbox-RweGCV3D.js} +3 -3
- package/dist/web/server/assets/{inbox-ZvDNAjaM.js → inbox-cu3jLzNP.js} +4 -4
- package/dist/web/server/assets/{learning-B7PBkvER.js → learning-BaKM6qaw.js} +4 -4
- package/dist/web/server/assets/{learning-8zav4pIT.js → learning-C2upa1CE.js} +4 -4
- package/dist/web/server/assets/{learning-Cq7K2heb.js → learning-CbtNlqYo.js} +76 -23
- package/dist/web/server/assets/{login-CmWvxfTK.js → login-BNj3U6ok.js} +22 -12
- package/dist/web/server/assets/{login-Bx5LEyGP.js → login-Be8eP4Jp.js} +2 -2
- package/dist/web/server/assets/{mcp-DIWTogHM.js → mcp-B0goWO8Q.js} +3 -3
- package/dist/web/server/assets/{mcp-2pwT9HU8.js → mcp-BvnvlVFd.js} +3 -3
- package/dist/web/server/assets/mcp-CiBs8unU.js +332 -0
- package/dist/web/server/assets/members-BP3UTqu1.js +12 -0
- package/dist/web/server/assets/members-DHYTVgwb.js +100 -0
- package/dist/web/server/assets/members-DiYtr-zm.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-CkXUgf5s.js} +150 -48
- package/dist/web/server/assets/{memory-pZ4pZT7p.js → memory-DTFEmfF3.js} +4 -4
- package/dist/web/server/assets/{policy-Bb-vEgqg.js → policy-18fdTFO4.js} +3 -3
- package/dist/web/server/assets/{policy-C30AeFIb.js → policy-BddK4xom.js} +3 -3
- package/dist/web/server/assets/{policy-BcGELcc9.js → policy-Bvvav8fh.js} +4 -4
- package/dist/web/server/assets/public-origin-xV0lm0Ty.js +25 -0
- package/dist/web/server/assets/router-pjH2t8Rl.js +813 -0
- package/dist/web/server/assets/{routes-B6cMLIPk.js → routes-BgHisAxH.js} +22 -5
- package/dist/web/server/assets/{routes-BrA-U_Hm.js → routes-COtkyZG1.js} +5 -5
- package/dist/web/server/assets/{routes-C19CMLZt.js → routes-DAU2g7Uz.js} +4 -4
- package/dist/web/server/assets/services-ClyGBU7W.js +83 -0
- package/dist/web/server/assets/{services-C4szdhPx.js → services-DgoU1udp.js} +3 -3
- package/dist/web/server/assets/{services-wG8I06oS.js → services-DozuJtzX.js} +3 -3
- package/dist/web/server/assets/{skills-BZdqiDig.js → skills-CYih9TJw.js} +47 -6
- package/dist/web/server/assets/{skills-a9VSWHWq.js → skills-DfGSJTCB.js} +3 -3
- package/dist/web/server/assets/{skills-C-UgkuCW.js → skills-Dw3cI3si.js} +3 -3
- package/dist/web/server/assets/start-D4Wq9iTa.js +70 -0
- package/dist/web/server/assets/{teams-OIkHuxy1.js → teams-BJuoNOTB.js} +3 -3
- package/dist/web/server/assets/{teams-CpQ0YgWf.js → teams-DF3RViAg.js} +3 -3
- package/dist/web/server/assets/{teams-DEpQR2QA.js → teams-DFnuc660.js} +3 -3
- package/dist/web/server/assets/{teams-DqfrEoH6.js → teams-DPnAX4wD.js} +4 -4
- package/dist/web/server/assets/{teams-jBtvnk59.js → teams-TV6nbEN_.js} +101 -10
- 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-XwyKSEtj.js → telegram-DbOFpTFm.js} +3 -3
- package/dist/web/server/assets/{telegram-CBF8SJzB.js → telegram-Dj4Wwhd6.js} +262 -43
- package/dist/web/server/assets/tokens-DDwtO15P.js +359 -0
- package/dist/web/server/assets/tokens-DjM8GsgS.js +19 -0
- package/dist/web/server/assets/{tokens-BnwFbV7T.js → tokens-_2hptHP6.js} +4 -4
- package/dist/web/server/assets/{triggers-BZPl5CHs.js → triggers-BvjYNmmY.js} +4 -4
- package/dist/web/server/assets/triggers-CHk9O3rU.js +367 -0
- package/dist/web/server/assets/{triggers-D79NoSXk.js → triggers-Nezfw-Bd.js} +4 -4
- package/dist/web/server/assets/utils-C_uf36nf.js +8 -0
- package/dist/web/server/assets/{welcome-DDB11L5j.js → welcome-B8nchXdF.js} +9 -8
- package/dist/web/server/server.js +29 -33
- package/dist/web-server.js +4 -0
- package/dist/web-server.js.map +1 -1
- package/dist/worker.js +1744 -362
- package/dist/worker.js.map +1 -1
- package/package.json +7 -6
- package/dist/web/client/assets/AgentTabs-R6gSjIj3.js +0 -1
- package/dist/web/client/assets/ConfigPage-BCwfgyjD.js +0 -1
- package/dist/web/client/assets/FieldRow-avAFLgYW.js +0 -1
- package/dist/web/client/assets/Page-CwNuDhWz.js +0 -1
- package/dist/web/client/assets/ProductionTeamPolicyEditor-CsWpTsy6.js +0 -7
- package/dist/web/client/assets/SectionTabs-DZzy01az.js +0 -1
- package/dist/web/client/assets/TeamTabs-DvqWieCq.js +0 -1
- package/dist/web/client/assets/_id-BUuz7Drv.js +0 -1
- package/dist/web/client/assets/_id-BegmVRmT.js +0 -1
- package/dist/web/client/assets/_id-BrA4Crh_.js +0 -1
- package/dist/web/client/assets/activity-n0Fw9_w3.js +0 -1
- package/dist/web/client/assets/agents-B33VQtbl.js +0 -1
- package/dist/web/client/assets/agents-C50pdxp7.js +0 -1
- package/dist/web/client/assets/approvals-DVW0hX8h.js +0 -1
- package/dist/web/client/assets/attention-B2490jcN.js +0 -1
- package/dist/web/client/assets/chevron-down-B0aNNOyn.js +0 -1
- package/dist/web/client/assets/config-CMMxxeX2.js +0 -3
- package/dist/web/client/assets/context-DcFzsfZ3.js +0 -1
- package/dist/web/client/assets/index-3nrK5iFr.js +0 -12
- package/dist/web/client/assets/learning-BUX1MFu2.js +0 -1
- package/dist/web/client/assets/login-CMWpGDKv.js +0 -1
- package/dist/web/client/assets/mcp-lZV08dqc.js +0 -1
- package/dist/web/client/assets/members-DAeaY2Cy.js +0 -1
- package/dist/web/client/assets/memory-HmMWxxdF.js +0 -1
- package/dist/web/client/assets/plus-CPzRJg1V.js +0 -1
- package/dist/web/client/assets/routes-BNk270AM.js +0 -1
- package/dist/web/client/assets/services-DtrpJrdo.js +0 -1
- package/dist/web/client/assets/skills-Cv93A3P3.js +0 -1
- package/dist/web/client/assets/styles-DMltY3su.css +0 -2
- package/dist/web/client/assets/teams-CCFnSNKi.js +0 -1
- package/dist/web/client/assets/telegram-BF1vdgDB.js +0 -1
- package/dist/web/client/assets/tokens-BXj6hWW-.js +0 -1
- package/dist/web/client/assets/triggers-NT24i4hZ.js +0 -1
- package/dist/web/client/assets/welcome-D0cy68eZ.js +0 -1
- package/dist/web/client/assets/wire-constants-BhVKOCQa.js +0 -74
- package/dist/web/server/assets/FieldRow-B4eTegH9.js +0 -94
- package/dist/web/server/assets/config-BmixCpz-.js +0 -372
- 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/context-DrkrIWun.js +0 -47
- package/dist/web/server/assets/mcp-BJjLIdP0.js +0 -261
- package/dist/web/server/assets/members-CCv17cjQ.js +0 -46
- 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/router-CIVjTgNp.js +0 -537
- package/dist/web/server/assets/services-B9yBWDX0.js +0 -79
- package/dist/web/server/assets/start-WH8WzTL_.js +0 -4
- package/dist/web/server/assets/tokens-DPDMSN5O.js +0 -12
- package/dist/web/server/assets/tokens-yyTSfBSN.js +0 -186
- package/dist/web/server/assets/triggers-CSNNzRIi.js +0 -216
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.14.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)
|
|
@@ -1357,7 +1360,9 @@ var openaiLoginCmd = defineCommand4({
|
|
|
1357
1360
|
console.log("(if it doesn't open automatically, paste the URL shown below)");
|
|
1358
1361
|
const oauth = openaiCodexProvider().auth.oauth;
|
|
1359
1362
|
if (!oauth) throw new Error("Pi openai-codex provider does not expose OAuth");
|
|
1363
|
+
const loginController = new AbortController();
|
|
1360
1364
|
const creds = await oauth.login({
|
|
1365
|
+
signal: loginController.signal,
|
|
1361
1366
|
notify: (event) => {
|
|
1362
1367
|
if (event.type === "auth_url") {
|
|
1363
1368
|
console.log("");
|
|
@@ -1444,11 +1449,20 @@ var authCommand = defineCommand4({
|
|
|
1444
1449
|
});
|
|
1445
1450
|
|
|
1446
1451
|
// src/commands/backup.ts
|
|
1447
|
-
import {
|
|
1452
|
+
import {
|
|
1453
|
+
createCipheriv,
|
|
1454
|
+
createDecipheriv,
|
|
1455
|
+
createHash as createHash3,
|
|
1456
|
+
pbkdf2Sync,
|
|
1457
|
+
randomBytes,
|
|
1458
|
+
randomUUID as randomUUID2
|
|
1459
|
+
} from "crypto";
|
|
1448
1460
|
import {
|
|
1449
1461
|
chmodSync as chmodSync2,
|
|
1450
1462
|
closeSync as closeSync2,
|
|
1451
1463
|
copyFileSync,
|
|
1464
|
+
cpSync,
|
|
1465
|
+
createReadStream,
|
|
1452
1466
|
createWriteStream,
|
|
1453
1467
|
existsSync as existsSync2,
|
|
1454
1468
|
fsyncSync as fsyncSync2,
|
|
@@ -1458,21 +1472,24 @@ import {
|
|
|
1458
1472
|
openSync as openSync2,
|
|
1459
1473
|
readdirSync,
|
|
1460
1474
|
readFileSync as readFileSync4,
|
|
1475
|
+
readSync,
|
|
1461
1476
|
renameSync as renameSync2,
|
|
1462
|
-
rmSync as rmSync2
|
|
1477
|
+
rmSync as rmSync2,
|
|
1478
|
+
writeFileSync as writeFileSync2
|
|
1463
1479
|
} from "fs";
|
|
1464
1480
|
import { tmpdir } from "os";
|
|
1465
1481
|
import { basename as basename3, dirname as dirname2, isAbsolute, parse, posix, relative, resolve as resolve2 } from "path";
|
|
1466
|
-
import { DatabaseSync } from "node:sqlite";
|
|
1482
|
+
import { DatabaseSync, backup as sqliteBackup } from "node:sqlite";
|
|
1467
1483
|
import { Readable } from "stream";
|
|
1468
1484
|
import { pipeline } from "stream/promises";
|
|
1485
|
+
import { Decrypter, Encrypter } from "age-encryption";
|
|
1469
1486
|
import { defineCommand as defineCommand5 } from "citty";
|
|
1470
1487
|
import { extract, list as list3 } from "tar";
|
|
1471
1488
|
|
|
1472
1489
|
// src/backup-schema.ts
|
|
1473
1490
|
import { createHash } from "crypto";
|
|
1474
1491
|
var CANONICAL_MIGRATION = "0001_init";
|
|
1475
|
-
var CANONICAL_SCHEMA_HASH = "
|
|
1492
|
+
var CANONICAL_SCHEMA_HASH = "4bde209eb0bf9851bf1f01fc96263f165a1799c81e720ddea463169a0d6c0d51";
|
|
1476
1493
|
var CANONICAL_OBJECTS = [
|
|
1477
1494
|
["index", "agent_triggers_agent"],
|
|
1478
1495
|
["index", "agent_triggers_enabled"],
|
|
@@ -1497,6 +1514,8 @@ var CANONICAL_OBJECTS = [
|
|
|
1497
1514
|
["index", "trigger_dispatches_claimable"],
|
|
1498
1515
|
["index", "trigger_dispatches_trigger_time"],
|
|
1499
1516
|
["index", "web_tokens_active"],
|
|
1517
|
+
["index", "web_sessions_active"],
|
|
1518
|
+
["index", "web_sessions_device"],
|
|
1500
1519
|
["table", "agent_skills"],
|
|
1501
1520
|
["table", "agent_loop_break_events"],
|
|
1502
1521
|
["table", "agent_lesson_proposals"],
|
|
@@ -1531,9 +1550,11 @@ var CANONICAL_OBJECTS = [
|
|
|
1531
1550
|
["table", "team_templates"],
|
|
1532
1551
|
["table", "teams"],
|
|
1533
1552
|
["table", "telegram_allowed_users"],
|
|
1553
|
+
["table", "telegram_pairing_challenge"],
|
|
1534
1554
|
["table", "template_instantiations"],
|
|
1535
1555
|
["table", "trigger_dispatches"],
|
|
1536
1556
|
["table", "web_tokens"],
|
|
1557
|
+
["table", "web_sessions"],
|
|
1537
1558
|
["trigger", "create_team_policy"],
|
|
1538
1559
|
["trigger", "prevent_detached_team_policy_delete"],
|
|
1539
1560
|
["trigger", "validate_source_binding_insert"],
|
|
@@ -1549,7 +1570,7 @@ function assertCanonicalBackupSchema(db) {
|
|
|
1549
1570
|
const migrations = db.prepare("SELECT version FROM schema_migrations ORDER BY version").all();
|
|
1550
1571
|
if (migrations.length !== 1 || migrations[0]?.version !== CANONICAL_MIGRATION) {
|
|
1551
1572
|
throw new Error(
|
|
1552
|
-
`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")
|
|
1553
1574
|
);
|
|
1554
1575
|
}
|
|
1555
1576
|
const rows = db.prepare(
|
|
@@ -1557,20 +1578,20 @@ function assertCanonicalBackupSchema(db) {
|
|
|
1557
1578
|
FROM sqlite_schema
|
|
1558
1579
|
WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite_%'`
|
|
1559
1580
|
).all();
|
|
1560
|
-
const byKey = new Map(rows.map((
|
|
1581
|
+
const byKey = new Map(rows.map((row2) => [`${row2.type}\0${row2.name}`, row2]));
|
|
1561
1582
|
const canonicalKeys = new Set(CANONICAL_OBJECTS.map(([type, name]) => `${type}\0${name}`));
|
|
1562
|
-
for (const
|
|
1563
|
-
if (!canonicalKeys.has(`${
|
|
1564
|
-
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}`);
|
|
1565
1586
|
}
|
|
1566
1587
|
}
|
|
1567
1588
|
const canonicalRows = [];
|
|
1568
1589
|
for (const [type, name] of CANONICAL_OBJECTS) {
|
|
1569
|
-
const
|
|
1570
|
-
if (!
|
|
1571
|
-
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);
|
|
1572
1593
|
}
|
|
1573
|
-
const payload = canonicalRows.map((
|
|
1594
|
+
const payload = canonicalRows.map((row2) => [row2.type, row2.name, row2.tbl_name, normalizeSql(row2.sql)].join("\0")).join("\n");
|
|
1574
1595
|
const actualHash = createHash("sha256").update(payload).digest("hex");
|
|
1575
1596
|
if (actualHash !== CANONICAL_SCHEMA_HASH) {
|
|
1576
1597
|
throw new Error(
|
|
@@ -1886,18 +1907,34 @@ async function acquireHomeRestoreLock(home) {
|
|
|
1886
1907
|
|
|
1887
1908
|
// src/commands/backup.ts
|
|
1888
1909
|
var createCmd = defineCommand5({
|
|
1889
|
-
meta: { name: "create", description: "
|
|
1910
|
+
meta: { name: "create", description: "Create a client-side encrypted backup of ~/.bazilion" },
|
|
1890
1911
|
args: {
|
|
1891
1912
|
output: {
|
|
1892
1913
|
type: "positional",
|
|
1893
1914
|
required: false,
|
|
1894
|
-
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"
|
|
1895
1924
|
}
|
|
1896
1925
|
},
|
|
1897
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
|
+
}
|
|
1898
1933
|
const cfg = loadClientConfig();
|
|
1899
1934
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
1900
|
-
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}`);
|
|
1901
1938
|
const configuredHome = resolve2(resolveCliPaths().home);
|
|
1902
1939
|
const outputFromHome = relative(configuredHome, outAbs);
|
|
1903
1940
|
if (!outputFromHome || !outputFromHome.startsWith("..") && !isAbsolute(outputFromHome)) {
|
|
@@ -1905,7 +1942,10 @@ var createCmd = defineCommand5({
|
|
|
1905
1942
|
`backup output must be outside BAZILION_HOME (${configuredHome}) to avoid nesting backups`
|
|
1906
1943
|
);
|
|
1907
1944
|
}
|
|
1908
|
-
|
|
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}`);
|
|
1909
1949
|
const res = await fetch(`${cfg.serverUrl}/api/backup`, {
|
|
1910
1950
|
headers: { authorization: `Bearer ${cfg.token}`, origin: cfg.serverUrl }
|
|
1911
1951
|
});
|
|
@@ -1921,11 +1961,25 @@ var createCmd = defineCommand5({
|
|
|
1921
1961
|
const downloadDir = mkdtempSync(resolve2(tmpdir(), "bazilion-download-"));
|
|
1922
1962
|
const partial = resolve2(downloadDir, "backup.tar.gz");
|
|
1923
1963
|
try {
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
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);
|
|
1929
1983
|
try {
|
|
1930
1984
|
renameSync2(partial, outAbs);
|
|
1931
1985
|
} catch (error) {
|
|
@@ -2055,6 +2109,27 @@ async function validateArchive(file) {
|
|
|
2055
2109
|
entries.push({ path, type: entry2.type, linkpath: entry2.linkpath });
|
|
2056
2110
|
}
|
|
2057
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) {
|
|
2058
2133
|
const byPath = /* @__PURE__ */ new Map();
|
|
2059
2134
|
for (const entry2 of entries) {
|
|
2060
2135
|
if (byPath.has(entry2.path)) throw new Error(`backup contains a duplicate path: ${entry2.path}`);
|
|
@@ -2113,7 +2188,7 @@ function validateDatabase(path, authToken) {
|
|
|
2113
2188
|
db = new DatabaseSync(path, { readOnly: true });
|
|
2114
2189
|
const integrity = db.prepare("PRAGMA integrity_check").all();
|
|
2115
2190
|
if (integrity.length !== 1 || integrity[0]?.integrity_check !== "ok") {
|
|
2116
|
-
const detail = integrity.map((
|
|
2191
|
+
const detail = integrity.map((row2) => row2.integrity_check).join("; ") || "no result";
|
|
2117
2192
|
throw new Error(`integrity_check failed: ${detail}`);
|
|
2118
2193
|
}
|
|
2119
2194
|
const foreignKeyErrors = db.prepare("PRAGMA foreign_key_check").all();
|
|
@@ -2124,7 +2199,7 @@ function validateDatabase(path, authToken) {
|
|
|
2124
2199
|
const tokenHash = createHash3("sha256").update(authToken).digest("hex");
|
|
2125
2200
|
const activeBootstrap = db.prepare(
|
|
2126
2201
|
`SELECT 1 FROM web_tokens
|
|
2127
|
-
WHERE token_hash = ? AND
|
|
2202
|
+
WHERE token_hash = ? AND kind = 'bootstrap' AND revoked_at IS NULL
|
|
2128
2203
|
LIMIT 1`
|
|
2129
2204
|
).get(tokenHash);
|
|
2130
2205
|
if (!activeBootstrap) {
|
|
@@ -2187,8 +2262,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2187
2262
|
const collection = table;
|
|
2188
2263
|
const stagedRoot = resolve2(payload, collection);
|
|
2189
2264
|
const targetRoot = resolve2(targetHome, collection);
|
|
2190
|
-
for (const
|
|
2191
|
-
const id = validateEntityId(
|
|
2265
|
+
for (const row2 of rows) {
|
|
2266
|
+
const id = validateEntityId(row2.id, idPattern, `${table} row`);
|
|
2192
2267
|
const rowLabel = `${table} row ${JSON.stringify(id)}`;
|
|
2193
2268
|
const stagedDir = containedChildDirectory(stagedRoot, id, rowLabel);
|
|
2194
2269
|
requireExtractedDirectory(stagedDir, rowLabel);
|
|
@@ -2200,8 +2275,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2200
2275
|
}
|
|
2201
2276
|
}
|
|
2202
2277
|
const stagedTeamsRoot = resolve2(payload, "teams");
|
|
2203
|
-
for (const
|
|
2204
|
-
const id = validateEntityId(
|
|
2278
|
+
for (const row2 of teams) {
|
|
2279
|
+
const id = validateEntityId(row2.id, SLUG_ID, "teams row");
|
|
2205
2280
|
const rowLabel = `teams row ${JSON.stringify(id)}`;
|
|
2206
2281
|
requireExtractedTeamSlot(containedChildDirectory(stagedTeamsRoot, id, rowLabel), rowLabel);
|
|
2207
2282
|
}
|
|
@@ -2222,8 +2297,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
|
|
|
2222
2297
|
const readProfile = db.prepare("SELECT dir FROM profiles WHERE id = ?");
|
|
2223
2298
|
const readAgent = db.prepare("SELECT dir FROM agents WHERE id = ?");
|
|
2224
2299
|
for (const rewrite of rewrites) {
|
|
2225
|
-
const
|
|
2226
|
-
if (
|
|
2300
|
+
const row2 = rewrite.table === "profiles" ? readProfile.get(rewrite.id) : readAgent.get(rewrite.id);
|
|
2301
|
+
if (row2?.dir !== rewrite.dir) {
|
|
2227
2302
|
throw new Error(
|
|
2228
2303
|
`could not verify rebased ${rewrite.table} row ${JSON.stringify(rewrite.id)}`
|
|
2229
2304
|
);
|
|
@@ -2261,6 +2336,14 @@ function removeRebuildableQmdIndexes(payload) {
|
|
|
2261
2336
|
}
|
|
2262
2337
|
}
|
|
2263
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
|
+
}
|
|
2264
2347
|
function installValidatedPayload(payload, targetHome, staging, lifecycle, operations = { rename: renameSync2 }) {
|
|
2265
2348
|
const previous = resolve2(staging, "previous-home");
|
|
2266
2349
|
const hadPrevious = existsSync2(targetHome);
|
|
@@ -2374,6 +2457,37 @@ function fsyncDirectory(path) {
|
|
|
2374
2457
|
if (fd !== null) closeSync2(fd);
|
|
2375
2458
|
}
|
|
2376
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
|
+
}
|
|
2377
2491
|
var restoreCmd = defineCommand5({
|
|
2378
2492
|
meta: {
|
|
2379
2493
|
name: "restore",
|
|
@@ -2389,6 +2503,10 @@ var restoreCmd = defineCommand5({
|
|
|
2389
2503
|
force: {
|
|
2390
2504
|
type: "boolean",
|
|
2391
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"
|
|
2392
2510
|
}
|
|
2393
2511
|
},
|
|
2394
2512
|
async run({ args }) {
|
|
@@ -2429,7 +2547,36 @@ var restoreCmd = defineCommand5({
|
|
|
2429
2547
|
const payload = resolve2(staging, "payload");
|
|
2430
2548
|
let preserveStaging = false;
|
|
2431
2549
|
try {
|
|
2432
|
-
|
|
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
|
+
}
|
|
2433
2580
|
await validateArchive(stagedArchive);
|
|
2434
2581
|
mkdirSync2(payload);
|
|
2435
2582
|
await extract({
|
|
@@ -2451,6 +2598,7 @@ var restoreCmd = defineCommand5({
|
|
|
2451
2598
|
const authToken = validateAuthFile(authFile);
|
|
2452
2599
|
validateDatabase(database, authToken);
|
|
2453
2600
|
rebaseRestoredHomeDirectories(database, payload, targetHome);
|
|
2601
|
+
revokeRestoredBrowserSessions(database);
|
|
2454
2602
|
validateDatabase(database, authToken);
|
|
2455
2603
|
removeRebuildableQmdIndexes(payload);
|
|
2456
2604
|
console.log(`installing validated backup ${file} \u2192 ${targetHome}`);
|
|
@@ -2481,11 +2629,200 @@ var restoreCmd = defineCommand5({
|
|
|
2481
2629
|
console.log("start the server with: bazilion serve (migrations apply automatically)");
|
|
2482
2630
|
}
|
|
2483
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
|
+
});
|
|
2484
2818
|
var backupCommand = defineCommand5({
|
|
2485
|
-
meta: { name: "backup", description: "
|
|
2819
|
+
meta: { name: "backup", description: "Encrypted backup, restore, and credential recovery" },
|
|
2486
2820
|
subCommands: {
|
|
2487
2821
|
create: createCmd,
|
|
2488
|
-
restore: restoreCmd
|
|
2822
|
+
restore: restoreCmd,
|
|
2823
|
+
inventory: inventoryCmd,
|
|
2824
|
+
"recovery-guide": recoveryGuideCmd,
|
|
2825
|
+
"rotate-bootstrap": rotateBootstrapCmd
|
|
2489
2826
|
}
|
|
2490
2827
|
// `bazilion backup` with no positional falls through to citty's subcommand
|
|
2491
2828
|
// prompt ("No command specified"). The previous default (auto-download to
|
|
@@ -2927,7 +3264,7 @@ var doctorCommand = defineCommand9({
|
|
|
2927
3264
|
meta: { name: "doctor", description: "Diagnose your bazilion install" },
|
|
2928
3265
|
async run() {
|
|
2929
3266
|
const client = createClient2();
|
|
2930
|
-
const r = await client.get("/api/health");
|
|
3267
|
+
const r = await client.get("/api/health/details");
|
|
2931
3268
|
function check(label, condition, hint) {
|
|
2932
3269
|
const mark = condition ? "\u2713" : "\u2717";
|
|
2933
3270
|
const tail = !condition && hint ? ` \u2014 ${hint}` : "";
|
|
@@ -2972,22 +3309,24 @@ var doctorCommand = defineCommand9({
|
|
|
2972
3309
|
}
|
|
2973
3310
|
}
|
|
2974
3311
|
console.log(
|
|
2975
|
-
` \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"}`
|
|
2976
3316
|
);
|
|
2977
|
-
console.log(` \u2713 ollama: ${r.providers.ollama.baseURL}`);
|
|
2978
3317
|
console.log();
|
|
2979
3318
|
console.log("web search (at least one needed for web_search tool)");
|
|
2980
|
-
if (r.webSearch.
|
|
2981
|
-
console.log(
|
|
3319
|
+
if (r.webSearch.braveConfigured) {
|
|
3320
|
+
console.log(" \u2713 Brave Search configured");
|
|
2982
3321
|
} else {
|
|
2983
3322
|
console.log(" - Brave Search (set BRAVE_API_KEY \u2014 free at https://brave.com/search/api/)");
|
|
2984
3323
|
}
|
|
2985
|
-
if (r.webSearch.
|
|
2986
|
-
console.log(
|
|
3324
|
+
if (r.webSearch.searxngConfigured) {
|
|
3325
|
+
console.log(" \u2713 SearXNG configured");
|
|
2987
3326
|
} else {
|
|
2988
3327
|
console.log(" - SearXNG (set SEARXNG_URL if you self-host one)");
|
|
2989
3328
|
}
|
|
2990
|
-
if (!r.webSearch.
|
|
3329
|
+
if (!r.webSearch.braveConfigured && !r.webSearch.searxngConfigured) {
|
|
2991
3330
|
console.log(" \u26A0 no search backend \u2014 web_search will error until one is configured");
|
|
2992
3331
|
}
|
|
2993
3332
|
console.log();
|
|
@@ -3004,35 +3343,7 @@ var doctorCommand = defineCommand9({
|
|
|
3004
3343
|
` ${r.scheduler.enabled ? "\u2713" : "-"} scheduler${r.scheduler.enabled ? ` (tick ${r.scheduler.tickMs}ms)` : " (BAZILION_SCHEDULER=off)"}`
|
|
3005
3344
|
);
|
|
3006
3345
|
console.log();
|
|
3007
|
-
console.log(
|
|
3008
|
-
if (!r.shellSecurity.ok) {
|
|
3009
|
-
check("valid shell-security configuration", false, r.shellSecurity.error);
|
|
3010
|
-
} else {
|
|
3011
|
-
if (r.shellSecurity.approvalMode === "dangerous") {
|
|
3012
|
-
console.log(" - dangerous-command approval enabled");
|
|
3013
|
-
console.log(
|
|
3014
|
-
" web and TTY CLI turns can allow once; background and non-TTY turns auto-deny"
|
|
3015
|
-
);
|
|
3016
|
-
} else {
|
|
3017
|
-
console.log(" - dangerous-command approval off");
|
|
3018
|
-
console.log(" set BAZILION_BASH_APPROVAL=dangerous to opt in");
|
|
3019
|
-
}
|
|
3020
|
-
if (r.shellSecurity.sandboxMode === "docker") {
|
|
3021
|
-
console.log(` - Docker sandbox configured (${r.shellSecurity.sandboxImage})`);
|
|
3022
|
-
console.log(
|
|
3023
|
-
" workspace-only writable mount \xB7 bounded inputs/skills/memory read-only \xB7 network disabled"
|
|
3024
|
-
);
|
|
3025
|
-
console.log(" host coding tools hidden");
|
|
3026
|
-
console.log(
|
|
3027
|
-
" policy syntax is valid; Docker and image availability are checked on execution"
|
|
3028
|
-
);
|
|
3029
|
-
console.log(" commands fail closed if either is unavailable");
|
|
3030
|
-
} else {
|
|
3031
|
-
console.log(" - sandbox off (agent shell and coding tools run on the host)");
|
|
3032
|
-
console.log(" approval is a host-execution tripwire, not a filesystem sandbox");
|
|
3033
|
-
console.log(" set BAZILION_BASH_SANDBOX=docker to opt in");
|
|
3034
|
-
}
|
|
3035
|
-
}
|
|
3346
|
+
for (const line of executionSecurityDoctorLines(r)) console.log(line);
|
|
3036
3347
|
console.log();
|
|
3037
3348
|
console.log("operational counts");
|
|
3038
3349
|
console.log(` ${r.triggers.active} active trigger(s), ${r.triggers.disabled} disabled`);
|
|
@@ -3041,7 +3352,7 @@ var doctorCommand = defineCommand9({
|
|
|
3041
3352
|
const hasProfiles = (r.database?.ok ? r.database.profiles : 0) > 0;
|
|
3042
3353
|
const hasAgents = (r.database?.ok ? r.database.totalAgents : 0) > 0;
|
|
3043
3354
|
console.log();
|
|
3044
|
-
if (
|
|
3355
|
+
if (doctorHasIssues(r)) {
|
|
3045
3356
|
console.log("issues found \u2717");
|
|
3046
3357
|
process.exit(1);
|
|
3047
3358
|
}
|
|
@@ -3063,9 +3374,150 @@ var doctorCommand = defineCommand9({
|
|
|
3063
3374
|
}
|
|
3064
3375
|
}
|
|
3065
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
|
+
}
|
|
3066
3447
|
|
|
3067
|
-
// src/commands/
|
|
3448
|
+
// src/commands/gateway.ts
|
|
3449
|
+
import { execFile } from "child_process";
|
|
3450
|
+
import { promisify } from "util";
|
|
3068
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";
|
|
3069
3521
|
function decodeText(payload) {
|
|
3070
3522
|
try {
|
|
3071
3523
|
const obj = JSON.parse(payload);
|
|
@@ -3081,7 +3533,7 @@ function messageRow(m) {
|
|
|
3081
3533
|
const preview = text2.length > 60 ? `${text2.slice(0, 60)}\u2026` : text2;
|
|
3082
3534
|
return [m.id, state, when, `from:${m.fromAgentId.slice(0, 8)}`, `"${preview}"`];
|
|
3083
3535
|
}
|
|
3084
|
-
var listCmd3 =
|
|
3536
|
+
var listCmd3 = defineCommand11({
|
|
3085
3537
|
meta: { name: "list", description: "List messages in an agent inbox" },
|
|
3086
3538
|
args: {
|
|
3087
3539
|
agent: { type: "positional", required: true, description: "Recipient agent id" },
|
|
@@ -3100,7 +3552,7 @@ var listCmd3 = defineCommand10({
|
|
|
3100
3552
|
for (const line of columnize(messages.map(messageRow))) console.log(line);
|
|
3101
3553
|
}
|
|
3102
3554
|
});
|
|
3103
|
-
var showCmd2 =
|
|
3555
|
+
var showCmd2 = defineCommand11({
|
|
3104
3556
|
meta: { name: "show", description: "Show a single message in full" },
|
|
3105
3557
|
args: {
|
|
3106
3558
|
id: { type: "positional", required: true, description: "Message id" }
|
|
@@ -3120,7 +3572,7 @@ var showCmd2 = defineCommand10({
|
|
|
3120
3572
|
console.log(decodeText(m.payload));
|
|
3121
3573
|
}
|
|
3122
3574
|
});
|
|
3123
|
-
var readCmd =
|
|
3575
|
+
var readCmd = defineCommand11({
|
|
3124
3576
|
meta: { name: "read", description: "Mark a message as read" },
|
|
3125
3577
|
args: {
|
|
3126
3578
|
id: { type: "positional", required: true, description: "Message id" }
|
|
@@ -3131,7 +3583,7 @@ var readCmd = defineCommand10({
|
|
|
3131
3583
|
console.log(`marked read: ${args.id}`);
|
|
3132
3584
|
}
|
|
3133
3585
|
});
|
|
3134
|
-
var loopBreaksCmd =
|
|
3586
|
+
var loopBreaksCmd = defineCommand11({
|
|
3135
3587
|
meta: { name: "loop-breaks", description: "List stopped agent-message chains" },
|
|
3136
3588
|
args: {
|
|
3137
3589
|
agent: { type: "positional", required: true, description: "Agent id" },
|
|
@@ -3159,7 +3611,7 @@ var loopBreaksCmd = defineCommand10({
|
|
|
3159
3611
|
console.log(line);
|
|
3160
3612
|
}
|
|
3161
3613
|
});
|
|
3162
|
-
var inboxCommand =
|
|
3614
|
+
var inboxCommand = defineCommand11({
|
|
3163
3615
|
meta: { name: "inbox", description: "Inspect agent inboxes" },
|
|
3164
3616
|
subCommands: {
|
|
3165
3617
|
list: listCmd3,
|
|
@@ -3170,8 +3622,8 @@ var inboxCommand = defineCommand10({
|
|
|
3170
3622
|
});
|
|
3171
3623
|
|
|
3172
3624
|
// src/commands/login.ts
|
|
3173
|
-
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as
|
|
3174
|
-
import { defineCommand as
|
|
3625
|
+
import { existsSync as existsSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
3626
|
+
import { defineCommand as defineCommand12 } from "citty";
|
|
3175
3627
|
function normalizeServer(raw) {
|
|
3176
3628
|
let url;
|
|
3177
3629
|
try {
|
|
@@ -3185,13 +3637,17 @@ function normalizeServer(raw) {
|
|
|
3185
3637
|
return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
|
|
3186
3638
|
}
|
|
3187
3639
|
async function verifyToken(server, token) {
|
|
3188
|
-
const res = await fetch(`${server}/api/
|
|
3640
|
+
const res = await fetch(`${server}/api/auth/whoami`, {
|
|
3189
3641
|
headers: { authorization: `Bearer ${token}`, origin: server }
|
|
3190
3642
|
});
|
|
3191
3643
|
if (res.status === 401) throw new Error("server rejected token (401)");
|
|
3192
|
-
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
|
+
}
|
|
3193
3649
|
}
|
|
3194
|
-
var loginCommand =
|
|
3650
|
+
var loginCommand = defineCommand12({
|
|
3195
3651
|
meta: {
|
|
3196
3652
|
name: "login",
|
|
3197
3653
|
description: "Save a remote bazilion server + token pair to auth.json"
|
|
@@ -3199,7 +3655,7 @@ var loginCommand = defineCommand11({
|
|
|
3199
3655
|
args: {
|
|
3200
3656
|
server: { type: "string", description: "Remote server URL (http[s]://...)" },
|
|
3201
3657
|
token: { type: "string", description: "Token issued by `bazilion token create`" },
|
|
3202
|
-
skipVerify: { type: "boolean", description: "Don't
|
|
3658
|
+
skipVerify: { type: "boolean", description: "Don't verify /api/auth/whoami before saving" },
|
|
3203
3659
|
clear: { type: "boolean", description: "Remove the stored remote instead of setting one" }
|
|
3204
3660
|
},
|
|
3205
3661
|
async run({ args }) {
|
|
@@ -3216,7 +3672,7 @@ var loginCommand = defineCommand11({
|
|
|
3216
3672
|
return;
|
|
3217
3673
|
}
|
|
3218
3674
|
delete auth.remote;
|
|
3219
|
-
|
|
3675
|
+
writeFileSync3(paths.authFile, `${JSON.stringify(auth, null, 2)}
|
|
3220
3676
|
`, { mode: 384 });
|
|
3221
3677
|
console.log("cleared stored remote; CLI will fall back to the local daemon");
|
|
3222
3678
|
return;
|
|
@@ -3231,7 +3687,7 @@ var loginCommand = defineCommand11({
|
|
|
3231
3687
|
await verifyToken(server, args.token);
|
|
3232
3688
|
}
|
|
3233
3689
|
auth.remote = { server, token: args.token };
|
|
3234
|
-
|
|
3690
|
+
writeFileSync3(paths.authFile, `${JSON.stringify(auth, null, 2)}
|
|
3235
3691
|
`, { mode: 384 });
|
|
3236
3692
|
console.log(`saved remote: ${server}`);
|
|
3237
3693
|
console.log("CLI will now target this server unless BAZILION_SERVER is set in the env.");
|
|
@@ -3239,7 +3695,7 @@ var loginCommand = defineCommand11({
|
|
|
3239
3695
|
});
|
|
3240
3696
|
|
|
3241
3697
|
// src/commands/mcp.ts
|
|
3242
|
-
import { defineCommand as
|
|
3698
|
+
import { defineCommand as defineCommand13 } from "citty";
|
|
3243
3699
|
function serverRow(s) {
|
|
3244
3700
|
const where = s.transport === "stdio" ? `${s.command} ${s.args.join(" ")}`.trim() : s.url ?? "";
|
|
3245
3701
|
return [
|
|
@@ -3251,7 +3707,7 @@ function serverRow(s) {
|
|
|
3251
3707
|
where
|
|
3252
3708
|
];
|
|
3253
3709
|
}
|
|
3254
|
-
var addCmd =
|
|
3710
|
+
var addCmd = defineCommand13({
|
|
3255
3711
|
meta: { name: "add", description: "Register an MCP server" },
|
|
3256
3712
|
args: {
|
|
3257
3713
|
name: { type: "positional", required: true, description: "Unique name ([a-zA-Z0-9_])" },
|
|
@@ -3278,7 +3734,7 @@ var addCmd = defineCommand12({
|
|
|
3278
3734
|
console.log(`${server.id} ${server.name} ${server.transport}`);
|
|
3279
3735
|
}
|
|
3280
3736
|
});
|
|
3281
|
-
var listCmd4 =
|
|
3737
|
+
var listCmd4 = defineCommand13({
|
|
3282
3738
|
meta: { name: "list", description: "List MCP servers" },
|
|
3283
3739
|
async run() {
|
|
3284
3740
|
const client = createClient2();
|
|
@@ -3290,7 +3746,7 @@ var listCmd4 = defineCommand12({
|
|
|
3290
3746
|
for (const line of columnize(servers.map(serverRow))) console.log(line);
|
|
3291
3747
|
}
|
|
3292
3748
|
});
|
|
3293
|
-
var showCmd3 =
|
|
3749
|
+
var showCmd3 = defineCommand13({
|
|
3294
3750
|
meta: { name: "show", description: "Show one MCP server" },
|
|
3295
3751
|
args: { id: { type: "positional", required: true } },
|
|
3296
3752
|
async run({ args }) {
|
|
@@ -3299,7 +3755,7 @@ var showCmd3 = defineCommand12({
|
|
|
3299
3755
|
console.log(JSON.stringify(server, null, 2));
|
|
3300
3756
|
}
|
|
3301
3757
|
});
|
|
3302
|
-
var rmCmd2 =
|
|
3758
|
+
var rmCmd2 = defineCommand13({
|
|
3303
3759
|
meta: { name: "rm", description: "Delete an MCP server" },
|
|
3304
3760
|
args: { id: { type: "positional", required: true } },
|
|
3305
3761
|
async run({ args }) {
|
|
@@ -3308,7 +3764,7 @@ var rmCmd2 = defineCommand12({
|
|
|
3308
3764
|
console.log(`removed MCP server ${args.id}`);
|
|
3309
3765
|
}
|
|
3310
3766
|
});
|
|
3311
|
-
var enableCmd =
|
|
3767
|
+
var enableCmd = defineCommand13({
|
|
3312
3768
|
meta: { name: "enable", description: "Enable an MCP server" },
|
|
3313
3769
|
args: { id: { type: "positional", required: true } },
|
|
3314
3770
|
async run({ args }) {
|
|
@@ -3317,7 +3773,7 @@ var enableCmd = defineCommand12({
|
|
|
3317
3773
|
console.log(`enabled MCP server ${args.id}`);
|
|
3318
3774
|
}
|
|
3319
3775
|
});
|
|
3320
|
-
var disableCmd =
|
|
3776
|
+
var disableCmd = defineCommand13({
|
|
3321
3777
|
meta: { name: "disable", description: "Disable an MCP server" },
|
|
3322
3778
|
args: { id: { type: "positional", required: true } },
|
|
3323
3779
|
async run({ args }) {
|
|
@@ -3326,7 +3782,7 @@ var disableCmd = defineCommand12({
|
|
|
3326
3782
|
console.log(`disabled MCP server ${args.id}`);
|
|
3327
3783
|
}
|
|
3328
3784
|
});
|
|
3329
|
-
var testCmd =
|
|
3785
|
+
var testCmd = defineCommand13({
|
|
3330
3786
|
meta: { name: "test", description: "Connect to a server and list its tools" },
|
|
3331
3787
|
args: { id: { type: "positional", required: true } },
|
|
3332
3788
|
async run({ args }) {
|
|
@@ -3344,7 +3800,7 @@ var testCmd = defineCommand12({
|
|
|
3344
3800
|
for (const t of tools) console.log(` ${t.name} ${t.description}`);
|
|
3345
3801
|
}
|
|
3346
3802
|
});
|
|
3347
|
-
var mcpCommand =
|
|
3803
|
+
var mcpCommand = defineCommand13({
|
|
3348
3804
|
meta: { name: "mcp", description: "Manage MCP servers" },
|
|
3349
3805
|
subCommands: {
|
|
3350
3806
|
add: addCmd,
|
|
@@ -3358,11 +3814,11 @@ var mcpCommand = defineCommand12({
|
|
|
3358
3814
|
});
|
|
3359
3815
|
|
|
3360
3816
|
// src/commands/memory.ts
|
|
3361
|
-
import { defineCommand as
|
|
3817
|
+
import { defineCommand as defineCommand14 } from "citty";
|
|
3362
3818
|
function encodeKey(key) {
|
|
3363
3819
|
return key.split("/").map(encodeURIComponent).join("/");
|
|
3364
3820
|
}
|
|
3365
|
-
var writeCmd =
|
|
3821
|
+
var writeCmd = defineCommand14({
|
|
3366
3822
|
meta: { name: "write", description: "Write an entry into a team's shared memory" },
|
|
3367
3823
|
args: {
|
|
3368
3824
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3378,7 +3834,7 @@ var writeCmd = defineCommand13({
|
|
|
3378
3834
|
console.log(`wrote ${entry2.key} (${entry2.content.length} bytes)`);
|
|
3379
3835
|
}
|
|
3380
3836
|
});
|
|
3381
|
-
var readCmd2 =
|
|
3837
|
+
var readCmd2 = defineCommand14({
|
|
3382
3838
|
meta: { name: "read", description: "Read an entry from a team's shared memory" },
|
|
3383
3839
|
args: {
|
|
3384
3840
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3392,7 +3848,7 @@ var readCmd2 = defineCommand13({
|
|
|
3392
3848
|
console.log(entry2.content);
|
|
3393
3849
|
}
|
|
3394
3850
|
});
|
|
3395
|
-
var searchCmd =
|
|
3851
|
+
var searchCmd = defineCommand14({
|
|
3396
3852
|
meta: { name: "search", description: "Search a team's shared memory" },
|
|
3397
3853
|
args: {
|
|
3398
3854
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3413,7 +3869,7 @@ var searchCmd = defineCommand13({
|
|
|
3413
3869
|
}
|
|
3414
3870
|
}
|
|
3415
3871
|
});
|
|
3416
|
-
var listCmd5 =
|
|
3872
|
+
var listCmd5 = defineCommand14({
|
|
3417
3873
|
meta: { name: "list", description: "List all entries in a team's shared memory" },
|
|
3418
3874
|
args: {
|
|
3419
3875
|
team: { type: "positional", required: true, description: "Team slug" }
|
|
@@ -3430,7 +3886,7 @@ var listCmd5 = defineCommand13({
|
|
|
3430
3886
|
}
|
|
3431
3887
|
}
|
|
3432
3888
|
});
|
|
3433
|
-
var rmCmd3 =
|
|
3889
|
+
var rmCmd3 = defineCommand14({
|
|
3434
3890
|
meta: { name: "rm", description: "Remove an entry from a team's shared memory" },
|
|
3435
3891
|
args: {
|
|
3436
3892
|
team: { type: "positional", required: true, description: "Team slug" },
|
|
@@ -3442,7 +3898,7 @@ var rmCmd3 = defineCommand13({
|
|
|
3442
3898
|
console.log(`removed ${args.key}`);
|
|
3443
3899
|
}
|
|
3444
3900
|
});
|
|
3445
|
-
var memoryCommand =
|
|
3901
|
+
var memoryCommand = defineCommand14({
|
|
3446
3902
|
meta: {
|
|
3447
3903
|
name: "memory",
|
|
3448
3904
|
description: "Manage a team's shared memory (BM25-indexed markdown notes)"
|
|
@@ -3458,8 +3914,8 @@ var memoryCommand = defineCommand13({
|
|
|
3458
3914
|
|
|
3459
3915
|
// src/commands/profile.ts
|
|
3460
3916
|
import { spawn as spawn2 } from "child_process";
|
|
3461
|
-
import { randomBytes } from "crypto";
|
|
3462
|
-
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";
|
|
3463
3919
|
import { tmpdir as tmpdir2 } from "os";
|
|
3464
3920
|
import { join as join4 } from "path";
|
|
3465
3921
|
|
|
@@ -3474,7 +3930,7 @@ var PROFILE_FILES = [
|
|
|
3474
3930
|
];
|
|
3475
3931
|
|
|
3476
3932
|
// src/commands/profile.ts
|
|
3477
|
-
import { defineCommand as
|
|
3933
|
+
import { defineCommand as defineCommand15 } from "citty";
|
|
3478
3934
|
function splitCsv(v) {
|
|
3479
3935
|
if (!v) return void 0;
|
|
3480
3936
|
const out = v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -3485,7 +3941,7 @@ function parseSkillsMode(v) {
|
|
|
3485
3941
|
if (v === "all" || v === "selected") return v;
|
|
3486
3942
|
throw new Error(`--skills-mode must be 'all' or 'selected', got '${v}'`);
|
|
3487
3943
|
}
|
|
3488
|
-
var createCmd2 =
|
|
3944
|
+
var createCmd2 = defineCommand15({
|
|
3489
3945
|
meta: { name: "create", description: "Create a new profile" },
|
|
3490
3946
|
args: {
|
|
3491
3947
|
id: { type: "positional", required: true, description: "Profile slug" },
|
|
@@ -3548,7 +4004,7 @@ var createCmd2 = defineCommand14({
|
|
|
3548
4004
|
console.log(`created profile ${profile.id} at ${profile.dir}`);
|
|
3549
4005
|
}
|
|
3550
4006
|
});
|
|
3551
|
-
var listCmd6 =
|
|
4007
|
+
var listCmd6 = defineCommand15({
|
|
3552
4008
|
meta: { name: "list", description: "List profiles" },
|
|
3553
4009
|
async run() {
|
|
3554
4010
|
const client = createClient2();
|
|
@@ -3561,7 +4017,7 @@ var listCmd6 = defineCommand14({
|
|
|
3561
4017
|
for (const line of columnize(rows)) console.log(line);
|
|
3562
4018
|
}
|
|
3563
4019
|
});
|
|
3564
|
-
var showCmd4 =
|
|
4020
|
+
var showCmd4 = defineCommand15({
|
|
3565
4021
|
meta: { name: "show", description: "Show profile details" },
|
|
3566
4022
|
args: {
|
|
3567
4023
|
id: { type: "positional", required: true }
|
|
@@ -3586,7 +4042,7 @@ var showCmd4 = defineCommand14({
|
|
|
3586
4042
|
}
|
|
3587
4043
|
}
|
|
3588
4044
|
});
|
|
3589
|
-
var editCmd2 =
|
|
4045
|
+
var editCmd2 = defineCommand15({
|
|
3590
4046
|
meta: { name: "edit", description: "Open a profile file in $EDITOR" },
|
|
3591
4047
|
args: {
|
|
3592
4048
|
id: { type: "positional", required: true },
|
|
@@ -3605,8 +4061,8 @@ var editCmd2 = defineCommand14({
|
|
|
3605
4061
|
const { content } = await client.get(
|
|
3606
4062
|
`/api/profiles/${args.id}/files/${file}`
|
|
3607
4063
|
);
|
|
3608
|
-
const tmpPath = join4(tmpdir2(), `bazilion-${args.id}-${file}-${
|
|
3609
|
-
|
|
4064
|
+
const tmpPath = join4(tmpdir2(), `bazilion-${args.id}-${file}-${randomBytes2(4).toString("hex")}`);
|
|
4065
|
+
writeFileSync4(tmpPath, content);
|
|
3610
4066
|
try {
|
|
3611
4067
|
const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
|
|
3612
4068
|
const code = await new Promise((resolve4, reject) => {
|
|
@@ -3631,7 +4087,7 @@ var editCmd2 = defineCommand14({
|
|
|
3631
4087
|
}
|
|
3632
4088
|
}
|
|
3633
4089
|
});
|
|
3634
|
-
var updateCmd =
|
|
4090
|
+
var updateCmd = defineCommand15({
|
|
3635
4091
|
meta: {
|
|
3636
4092
|
name: "update",
|
|
3637
4093
|
description: "Update profile settings (name, model, skills-mode, skills)"
|
|
@@ -3665,7 +4121,7 @@ var updateCmd = defineCommand14({
|
|
|
3665
4121
|
console.log(`updated profile ${profile.id}`);
|
|
3666
4122
|
}
|
|
3667
4123
|
});
|
|
3668
|
-
var deleteCmd2 =
|
|
4124
|
+
var deleteCmd2 = defineCommand15({
|
|
3669
4125
|
meta: { name: "delete", description: "Permanently delete a profile and its files" },
|
|
3670
4126
|
args: {
|
|
3671
4127
|
id: { type: "positional", required: true }
|
|
@@ -3676,7 +4132,7 @@ var deleteCmd2 = defineCommand14({
|
|
|
3676
4132
|
console.log(`deleted profile ${args.id}`);
|
|
3677
4133
|
}
|
|
3678
4134
|
});
|
|
3679
|
-
var profileCommand =
|
|
4135
|
+
var profileCommand = defineCommand15({
|
|
3680
4136
|
meta: { name: "profile", description: "Manage profiles" },
|
|
3681
4137
|
subCommands: {
|
|
3682
4138
|
create: createCmd2,
|
|
@@ -3689,8 +4145,8 @@ var profileCommand = defineCommand14({
|
|
|
3689
4145
|
});
|
|
3690
4146
|
|
|
3691
4147
|
// src/commands/provider.ts
|
|
3692
|
-
import { defineCommand as
|
|
3693
|
-
var listCmd7 =
|
|
4148
|
+
import { defineCommand as defineCommand16 } from "citty";
|
|
4149
|
+
var listCmd7 = defineCommand16({
|
|
3694
4150
|
meta: {
|
|
3695
4151
|
name: "list",
|
|
3696
4152
|
description: "List all providers with enabled/disabled state and curated model counts"
|
|
@@ -3716,7 +4172,7 @@ var listCmd7 = defineCommand15({
|
|
|
3716
4172
|
for (const line of columnize(rows)) console.log(line);
|
|
3717
4173
|
}
|
|
3718
4174
|
});
|
|
3719
|
-
var modelsCmd =
|
|
4175
|
+
var modelsCmd = defineCommand16({
|
|
3720
4176
|
meta: {
|
|
3721
4177
|
name: "models",
|
|
3722
4178
|
description: "Show curated + catalog + live models for one provider"
|
|
@@ -3748,7 +4204,7 @@ var modelsCmd = defineCommand15({
|
|
|
3748
4204
|
}
|
|
3749
4205
|
}
|
|
3750
4206
|
});
|
|
3751
|
-
var modelsSetCmd =
|
|
4207
|
+
var modelsSetCmd = defineCommand16({
|
|
3752
4208
|
meta: {
|
|
3753
4209
|
name: "models-set",
|
|
3754
4210
|
description: "Replace the curated model list for a provider (comma-separated)"
|
|
@@ -3773,7 +4229,7 @@ var modelsSetCmd = defineCommand15({
|
|
|
3773
4229
|
for (const m of saved.models) console.log(` ${m}`);
|
|
3774
4230
|
}
|
|
3775
4231
|
});
|
|
3776
|
-
var enableCmd2 =
|
|
4232
|
+
var enableCmd2 = defineCommand16({
|
|
3777
4233
|
meta: { name: "enable", description: "Toggle a provider on so agents can use it" },
|
|
3778
4234
|
args: {
|
|
3779
4235
|
name: { type: "positional", required: true, description: "Provider id (e.g. anthropic)" }
|
|
@@ -3787,7 +4243,7 @@ var enableCmd2 = defineCommand15({
|
|
|
3787
4243
|
console.log(`${res.name}: enabled`);
|
|
3788
4244
|
}
|
|
3789
4245
|
});
|
|
3790
|
-
var disableCmd2 =
|
|
4246
|
+
var disableCmd2 = defineCommand16({
|
|
3791
4247
|
meta: {
|
|
3792
4248
|
name: "disable",
|
|
3793
4249
|
description: "Toggle a provider off \u2014 agents will refuse its model strings"
|
|
@@ -3804,7 +4260,7 @@ var disableCmd2 = defineCommand15({
|
|
|
3804
4260
|
console.log(`${res.name}: disabled`);
|
|
3805
4261
|
}
|
|
3806
4262
|
});
|
|
3807
|
-
var testCmd2 =
|
|
4263
|
+
var testCmd2 = defineCommand16({
|
|
3808
4264
|
meta: { name: "test", description: "Send a single chat to a model and print the reply" },
|
|
3809
4265
|
args: {
|
|
3810
4266
|
model: {
|
|
@@ -3825,7 +4281,7 @@ var testCmd2 = defineCommand15({
|
|
|
3825
4281
|
}
|
|
3826
4282
|
}
|
|
3827
4283
|
});
|
|
3828
|
-
var providerCommand =
|
|
4284
|
+
var providerCommand = defineCommand16({
|
|
3829
4285
|
meta: { name: "provider", description: "Manage and test LLM providers" },
|
|
3830
4286
|
subCommands: {
|
|
3831
4287
|
list: listCmd7,
|
|
@@ -3838,8 +4294,8 @@ var providerCommand = defineCommand15({
|
|
|
3838
4294
|
});
|
|
3839
4295
|
|
|
3840
4296
|
// src/commands/send.ts
|
|
3841
|
-
import { defineCommand as
|
|
3842
|
-
var sendCommand =
|
|
4297
|
+
import { defineCommand as defineCommand17 } from "citty";
|
|
4298
|
+
var sendCommand = defineCommand17({
|
|
3843
4299
|
meta: {
|
|
3844
4300
|
name: "send",
|
|
3845
4301
|
description: "Send a message from one agent to another"
|
|
@@ -3873,11 +4329,11 @@ var sendCommand = defineCommand16({
|
|
|
3873
4329
|
import { spawn as spawn3 } from "child_process";
|
|
3874
4330
|
import { existsSync as existsSync5 } from "fs";
|
|
3875
4331
|
import { join as join5 } from "path";
|
|
3876
|
-
import { defineCommand as
|
|
4332
|
+
import { defineCommand as defineCommand18 } from "citty";
|
|
3877
4333
|
var bundledDaemonEntry2 = join5(import.meta.dirname, "daemon.js");
|
|
3878
4334
|
var sourceDaemonEntry2 = join5(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
|
|
3879
4335
|
var daemonEntry2 = existsSync5(bundledDaemonEntry2) ? bundledDaemonEntry2 : sourceDaemonEntry2;
|
|
3880
|
-
var serveCommand =
|
|
4336
|
+
var serveCommand = defineCommand18({
|
|
3881
4337
|
meta: {
|
|
3882
4338
|
name: "serve",
|
|
3883
4339
|
description: "Start the bazilion daemon (HTTP API)"
|
|
@@ -3943,17 +4399,54 @@ var serveCommand = defineCommand17({
|
|
|
3943
4399
|
}
|
|
3944
4400
|
});
|
|
3945
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
|
+
|
|
3946
4439
|
// src/commands/skill.ts
|
|
3947
4440
|
import { existsSync as existsSync6, readFileSync as readFileSync7, statSync } from "fs";
|
|
3948
4441
|
import { basename as basename4, resolve as resolve3 } from "path";
|
|
3949
|
-
import { defineCommand as
|
|
4442
|
+
import { defineCommand as defineCommand20 } from "citty";
|
|
3950
4443
|
function printFindings(findings, prefix = " ") {
|
|
3951
4444
|
for (const f of findings) {
|
|
3952
4445
|
const line = f.line ? ` line ${f.line}` : "";
|
|
3953
4446
|
console.log(`${prefix}${f.severity}: ${f.code}${line} - ${f.message}`);
|
|
3954
4447
|
}
|
|
3955
4448
|
}
|
|
3956
|
-
var
|
|
4449
|
+
var listCmd9 = defineCommand20({
|
|
3957
4450
|
meta: { name: "list", description: "List installed skills (or those attached to an agent)" },
|
|
3958
4451
|
args: {
|
|
3959
4452
|
agent: { type: "string", description: "Filter to skills attached to this agent" }
|
|
@@ -3994,7 +4487,7 @@ var listCmd8 = defineCommand18({
|
|
|
3994
4487
|
}
|
|
3995
4488
|
}
|
|
3996
4489
|
});
|
|
3997
|
-
var importCmd =
|
|
4490
|
+
var importCmd = defineCommand20({
|
|
3998
4491
|
meta: {
|
|
3999
4492
|
name: "import",
|
|
4000
4493
|
description: "Import skills from openclaw, a directory, or a local .zip archive"
|
|
@@ -4063,7 +4556,7 @@ var importCmd = defineCommand18({
|
|
|
4063
4556
|
}
|
|
4064
4557
|
}
|
|
4065
4558
|
});
|
|
4066
|
-
var rmCmd4 =
|
|
4559
|
+
var rmCmd4 = defineCommand20({
|
|
4067
4560
|
meta: { name: "rm", description: "Remove an installed skill" },
|
|
4068
4561
|
args: {
|
|
4069
4562
|
name: { type: "positional", required: true }
|
|
@@ -4074,10 +4567,10 @@ var rmCmd4 = defineCommand18({
|
|
|
4074
4567
|
console.log(`removed skill ${args.name}`);
|
|
4075
4568
|
}
|
|
4076
4569
|
});
|
|
4077
|
-
var skillCommand =
|
|
4570
|
+
var skillCommand = defineCommand20({
|
|
4078
4571
|
meta: { name: "skill", description: "Manage the skill library" },
|
|
4079
4572
|
subCommands: {
|
|
4080
|
-
list:
|
|
4573
|
+
list: listCmd9,
|
|
4081
4574
|
import: importCmd,
|
|
4082
4575
|
rm: rmCmd4
|
|
4083
4576
|
}
|
|
@@ -4086,11 +4579,11 @@ var skillCommand = defineCommand18({
|
|
|
4086
4579
|
// src/commands/team.ts
|
|
4087
4580
|
import { readFileSync as readFileSync9 } from "fs";
|
|
4088
4581
|
import { stdin as stdin2 } from "process";
|
|
4089
|
-
import { defineCommand as
|
|
4582
|
+
import { defineCommand as defineCommand22 } from "citty";
|
|
4090
4583
|
|
|
4091
4584
|
// src/commands/team-policy.ts
|
|
4092
4585
|
import { readFileSync as readFileSync8 } from "fs";
|
|
4093
|
-
import { defineCommand as
|
|
4586
|
+
import { defineCommand as defineCommand21 } from "citty";
|
|
4094
4587
|
|
|
4095
4588
|
// src/team-interchange.ts
|
|
4096
4589
|
var TEAM_POLICY_INTERCHANGE_VERSION = 1;
|
|
@@ -4338,7 +4831,7 @@ function printPolicy(detail) {
|
|
|
4338
4831
|
console.log(line);
|
|
4339
4832
|
}
|
|
4340
4833
|
}
|
|
4341
|
-
var show2 =
|
|
4834
|
+
var show2 = defineCommand21({
|
|
4342
4835
|
meta: { name: "show", description: "Show the one effective live policy for a Team" },
|
|
4343
4836
|
args: {
|
|
4344
4837
|
team: { type: "positional", required: true },
|
|
@@ -4352,7 +4845,7 @@ var show2 = defineCommand19({
|
|
|
4352
4845
|
else printPolicy(detail);
|
|
4353
4846
|
}
|
|
4354
4847
|
});
|
|
4355
|
-
var exportCommand =
|
|
4848
|
+
var exportCommand = defineCommand21({
|
|
4356
4849
|
meta: { name: "export", description: "Export a revisioned Team policy document" },
|
|
4357
4850
|
args: { team: { type: "positional", required: true } },
|
|
4358
4851
|
async run({ args }) {
|
|
@@ -4376,7 +4869,7 @@ function printEdgeDiff(current, edges) {
|
|
|
4376
4869
|
for (const value of diff2.added) console.log(` + ${value}`);
|
|
4377
4870
|
for (const value of diff2.removed) console.log(` - ${value}`);
|
|
4378
4871
|
}
|
|
4379
|
-
var importCommand =
|
|
4872
|
+
var importCommand = defineCommand21({
|
|
4380
4873
|
meta: {
|
|
4381
4874
|
name: "import",
|
|
4382
4875
|
description: "Validate, diff, and explicitly replace a Team policy"
|
|
@@ -4431,7 +4924,7 @@ var importCommand = defineCommand19({
|
|
|
4431
4924
|
console.log(`updated Team ${args.team} policy to revision ${updated.teamPolicy.revision}`);
|
|
4432
4925
|
}
|
|
4433
4926
|
});
|
|
4434
|
-
var diff =
|
|
4927
|
+
var diff = defineCommand21({
|
|
4435
4928
|
meta: { name: "diff", description: "Compare live policy with its retained baseline source" },
|
|
4436
4929
|
args: {
|
|
4437
4930
|
team: { type: "positional", required: true },
|
|
@@ -4455,7 +4948,7 @@ var diff = defineCommand19({
|
|
|
4455
4948
|
);
|
|
4456
4949
|
}
|
|
4457
4950
|
});
|
|
4458
|
-
var evaluate =
|
|
4951
|
+
var evaluate = defineCommand21({
|
|
4459
4952
|
meta: {
|
|
4460
4953
|
name: "evaluate",
|
|
4461
4954
|
description: "Evaluate a communication path without sending or recording a block"
|
|
@@ -4486,7 +4979,7 @@ var evaluate = defineCommand19({
|
|
|
4486
4979
|
);
|
|
4487
4980
|
}
|
|
4488
4981
|
});
|
|
4489
|
-
var blocks =
|
|
4982
|
+
var blocks = defineCommand21({
|
|
4490
4983
|
meta: { name: "blocks", description: "List paginated durable communication denials" },
|
|
4491
4984
|
args: {
|
|
4492
4985
|
team: { type: "positional", required: true },
|
|
@@ -4535,7 +5028,7 @@ var blocks = defineCommand19({
|
|
|
4535
5028
|
if (page.nextCursor) console.log(`next cursor: ${page.nextCursor}`);
|
|
4536
5029
|
}
|
|
4537
5030
|
});
|
|
4538
|
-
var teamPolicyCommand =
|
|
5031
|
+
var teamPolicyCommand = defineCommand21({
|
|
4539
5032
|
meta: { name: "policy", description: "Inspect and manage the Team-owned live policy" },
|
|
4540
5033
|
subCommands: {
|
|
4541
5034
|
show: show2,
|
|
@@ -4548,7 +5041,7 @@ var teamPolicyCommand = defineCommand19({
|
|
|
4548
5041
|
});
|
|
4549
5042
|
|
|
4550
5043
|
// src/commands/team.ts
|
|
4551
|
-
var addCmd2 =
|
|
5044
|
+
var addCmd2 = defineCommand22({
|
|
4552
5045
|
meta: {
|
|
4553
5046
|
name: "add",
|
|
4554
5047
|
description: "Register a team at ~/.bazilion/teams/<slug>/ (use --link to point at an existing tree)"
|
|
@@ -4572,7 +5065,7 @@ var addCmd2 = defineCommand20({
|
|
|
4572
5065
|
console.log(`registered team ${g.id} at ${g.path}`);
|
|
4573
5066
|
}
|
|
4574
5067
|
});
|
|
4575
|
-
var
|
|
5068
|
+
var listCmd10 = defineCommand22({
|
|
4576
5069
|
meta: { name: "list", description: "List teams" },
|
|
4577
5070
|
async run() {
|
|
4578
5071
|
const client = createClient2();
|
|
@@ -4585,7 +5078,7 @@ var listCmd9 = defineCommand20({
|
|
|
4585
5078
|
for (const line of columnize(rows)) console.log(line);
|
|
4586
5079
|
}
|
|
4587
5080
|
});
|
|
4588
|
-
var rmCmd5 =
|
|
5081
|
+
var rmCmd5 = defineCommand22({
|
|
4589
5082
|
meta: { name: "rm", description: "Remove a team registration" },
|
|
4590
5083
|
args: {
|
|
4591
5084
|
id: { type: "positional", required: true }
|
|
@@ -4606,7 +5099,7 @@ async function readStdin() {
|
|
|
4606
5099
|
for await (const chunk of stdin2) chunks.push(chunk);
|
|
4607
5100
|
return Buffer.concat(chunks).toString("utf8");
|
|
4608
5101
|
}
|
|
4609
|
-
var userMdShowCmd =
|
|
5102
|
+
var userMdShowCmd = defineCommand22({
|
|
4610
5103
|
meta: { name: "show", description: "Print the team's USER.md" },
|
|
4611
5104
|
args: { id: { type: "positional", required: true } },
|
|
4612
5105
|
async run({ args }) {
|
|
@@ -4616,7 +5109,7 @@ var userMdShowCmd = defineCommand20({
|
|
|
4616
5109
|
if (g.userMd && !g.userMd.endsWith("\n")) process.stdout.write("\n");
|
|
4617
5110
|
}
|
|
4618
5111
|
});
|
|
4619
|
-
var userMdSetCmd =
|
|
5112
|
+
var userMdSetCmd = defineCommand22({
|
|
4620
5113
|
meta: {
|
|
4621
5114
|
name: "set",
|
|
4622
5115
|
description: "Replace the team's USER.md (from --file, --from-stdin, or inline text)"
|
|
@@ -4642,7 +5135,7 @@ var userMdSetCmd = defineCommand20({
|
|
|
4642
5135
|
console.log(`updated USER.md for team ${args.id} (${content.length} bytes)`);
|
|
4643
5136
|
}
|
|
4644
5137
|
});
|
|
4645
|
-
var userMdClearCmd =
|
|
5138
|
+
var userMdClearCmd = defineCommand22({
|
|
4646
5139
|
meta: { name: "clear", description: "Clear the team's USER.md to empty" },
|
|
4647
5140
|
args: { id: { type: "positional", required: true } },
|
|
4648
5141
|
async run({ args }) {
|
|
@@ -4652,7 +5145,7 @@ var userMdClearCmd = defineCommand20({
|
|
|
4652
5145
|
console.log(`cleared USER.md for team ${args.id}`);
|
|
4653
5146
|
}
|
|
4654
5147
|
});
|
|
4655
|
-
var userMdCmd =
|
|
5148
|
+
var userMdCmd = defineCommand22({
|
|
4656
5149
|
meta: { name: "user-md", description: "View or edit a team's USER.md" },
|
|
4657
5150
|
subCommands: {
|
|
4658
5151
|
show: userMdShowCmd,
|
|
@@ -4660,7 +5153,7 @@ var userMdCmd = defineCommand20({
|
|
|
4660
5153
|
clear: userMdClearCmd
|
|
4661
5154
|
}
|
|
4662
5155
|
});
|
|
4663
|
-
var topicFormatShowCmd =
|
|
5156
|
+
var topicFormatShowCmd = defineCommand22({
|
|
4664
5157
|
meta: { name: "show", description: "Print the team's Telegram topic-name template" },
|
|
4665
5158
|
args: { id: { type: "positional", required: true } },
|
|
4666
5159
|
async run({ args }) {
|
|
@@ -4669,7 +5162,7 @@ var topicFormatShowCmd = defineCommand20({
|
|
|
4669
5162
|
console.log(g.telegramTopicNameFormat ?? "(default naming)");
|
|
4670
5163
|
}
|
|
4671
5164
|
});
|
|
4672
|
-
var topicFormatSetCmd =
|
|
5165
|
+
var topicFormatSetCmd = defineCommand22({
|
|
4673
5166
|
meta: {
|
|
4674
5167
|
name: "set",
|
|
4675
5168
|
description: "Set the topic-name template. Tokens: {agent.name} {team.name} {team.slug} (must include {agent.name})"
|
|
@@ -4689,7 +5182,7 @@ var topicFormatSetCmd = defineCommand20({
|
|
|
4689
5182
|
console.log(`set topic-name template for team ${args.id}: ${g.telegramTopicNameFormat}`);
|
|
4690
5183
|
}
|
|
4691
5184
|
});
|
|
4692
|
-
var topicFormatClearCmd =
|
|
5185
|
+
var topicFormatClearCmd = defineCommand22({
|
|
4693
5186
|
meta: { name: "clear", description: "Clear the template (revert to built-in naming)" },
|
|
4694
5187
|
args: { id: { type: "positional", required: true } },
|
|
4695
5188
|
async run({ args }) {
|
|
@@ -4699,7 +5192,7 @@ var topicFormatClearCmd = defineCommand20({
|
|
|
4699
5192
|
console.log(`cleared topic-name template for team ${args.id}`);
|
|
4700
5193
|
}
|
|
4701
5194
|
});
|
|
4702
|
-
var topicFormatCmd =
|
|
5195
|
+
var topicFormatCmd = defineCommand22({
|
|
4703
5196
|
meta: {
|
|
4704
5197
|
name: "topic-format",
|
|
4705
5198
|
description: "View or edit a team's Telegram forum-topic name template"
|
|
@@ -4710,11 +5203,11 @@ var topicFormatCmd = defineCommand20({
|
|
|
4710
5203
|
clear: topicFormatClearCmd
|
|
4711
5204
|
}
|
|
4712
5205
|
});
|
|
4713
|
-
var teamCommand =
|
|
5206
|
+
var teamCommand = defineCommand22({
|
|
4714
5207
|
meta: { name: "team", description: "Manage teams (collaboration contexts)" },
|
|
4715
5208
|
subCommands: {
|
|
4716
5209
|
add: addCmd2,
|
|
4717
|
-
list:
|
|
5210
|
+
list: listCmd10,
|
|
4718
5211
|
rm: rmCmd5,
|
|
4719
5212
|
"user-md": userMdCmd,
|
|
4720
5213
|
"topic-format": topicFormatCmd,
|
|
@@ -4724,7 +5217,7 @@ var teamCommand = defineCommand20({
|
|
|
4724
5217
|
|
|
4725
5218
|
// src/commands/team-template.ts
|
|
4726
5219
|
import { readFileSync as readFileSync10 } from "fs";
|
|
4727
|
-
import { defineCommand as
|
|
5220
|
+
import { defineCommand as defineCommand23 } from "citty";
|
|
4728
5221
|
function jsonFile(path) {
|
|
4729
5222
|
try {
|
|
4730
5223
|
return JSON.parse(readFileSync10(path, "utf8"));
|
|
@@ -4752,7 +5245,7 @@ function printTeam(detail) {
|
|
|
4752
5245
|
console.log(line);
|
|
4753
5246
|
}
|
|
4754
5247
|
}
|
|
4755
|
-
var list4 =
|
|
5248
|
+
var list4 = defineCommand23({
|
|
4756
5249
|
meta: { name: "list", description: "List canonical Team templates" },
|
|
4757
5250
|
args: { json: { type: "boolean", description: "Emit stable JSON" } },
|
|
4758
5251
|
async run({ args }) {
|
|
@@ -4761,12 +5254,12 @@ var list4 = defineCommand21({
|
|
|
4761
5254
|
if (!rows.length) return console.log("(no Team templates)");
|
|
4762
5255
|
for (const line of columnize([
|
|
4763
5256
|
["id", "revision", "slots", "name"],
|
|
4764
|
-
...rows.map((
|
|
5257
|
+
...rows.map((row2) => [row2.id, String(row2.currentRevision), String(row2.slotCount), row2.name])
|
|
4765
5258
|
]))
|
|
4766
5259
|
console.log(line);
|
|
4767
5260
|
}
|
|
4768
5261
|
});
|
|
4769
|
-
var show3 =
|
|
5262
|
+
var show3 = defineCommand23({
|
|
4770
5263
|
meta: { name: "show", description: "Show a canonical Team template" },
|
|
4771
5264
|
args: {
|
|
4772
5265
|
id: { type: "positional", required: true },
|
|
@@ -4780,7 +5273,7 @@ var show3 = defineCommand21({
|
|
|
4780
5273
|
else printTeam(detail);
|
|
4781
5274
|
}
|
|
4782
5275
|
});
|
|
4783
|
-
var exportCommand2 =
|
|
5276
|
+
var exportCommand2 = defineCommand23({
|
|
4784
5277
|
meta: {
|
|
4785
5278
|
name: "export",
|
|
4786
5279
|
description: "Export a portable versioned Team-template document to stdout"
|
|
@@ -4820,7 +5313,7 @@ function printImportDiff(current, document) {
|
|
|
4820
5313
|
for (const value of diff2.added) console.log(` + ${value}`);
|
|
4821
5314
|
for (const value of diff2.removed) console.log(` - ${value}`);
|
|
4822
5315
|
}
|
|
4823
|
-
var importCommand2 =
|
|
5316
|
+
var importCommand2 = defineCommand23({
|
|
4824
5317
|
meta: {
|
|
4825
5318
|
name: "import",
|
|
4826
5319
|
description: "Validate, diff, and explicitly apply a portable Team-template document"
|
|
@@ -4901,7 +5394,7 @@ var importCommand2 = defineCommand21({
|
|
|
4901
5394
|
);
|
|
4902
5395
|
}
|
|
4903
5396
|
});
|
|
4904
|
-
var teamTemplateCommand =
|
|
5397
|
+
var teamTemplateCommand = defineCommand23({
|
|
4905
5398
|
meta: {
|
|
4906
5399
|
name: "team-template",
|
|
4907
5400
|
description: "Inspect and exchange canonical Team templates"
|
|
@@ -4910,8 +5403,8 @@ var teamTemplateCommand = defineCommand21({
|
|
|
4910
5403
|
});
|
|
4911
5404
|
|
|
4912
5405
|
// src/commands/telegram.ts
|
|
4913
|
-
import { defineCommand as
|
|
4914
|
-
var setCmd2 =
|
|
5406
|
+
import { defineCommand as defineCommand24 } from "citty";
|
|
5407
|
+
var setCmd2 = defineCommand24({
|
|
4915
5408
|
meta: {
|
|
4916
5409
|
name: "set",
|
|
4917
5410
|
description: "Save bot token + supergroup chat ID (paired write)"
|
|
@@ -4929,7 +5422,7 @@ var setCmd2 = defineCommand22({
|
|
|
4929
5422
|
console.log(`saved \xB7 token ${state.botTokenPreview} \xB7 chat ${state.chatId}`);
|
|
4930
5423
|
}
|
|
4931
5424
|
});
|
|
4932
|
-
var clearCmd =
|
|
5425
|
+
var clearCmd = defineCommand24({
|
|
4933
5426
|
meta: {
|
|
4934
5427
|
name: "clear",
|
|
4935
5428
|
description: "Remove stored bot token + chat ID"
|
|
@@ -4940,7 +5433,7 @@ var clearCmd = defineCommand22({
|
|
|
4940
5433
|
console.log("cleared");
|
|
4941
5434
|
}
|
|
4942
5435
|
});
|
|
4943
|
-
var showCmd5 =
|
|
5436
|
+
var showCmd5 = defineCommand24({
|
|
4944
5437
|
meta: {
|
|
4945
5438
|
name: "show",
|
|
4946
5439
|
description: "Show what credentials are stored (token is masked)"
|
|
@@ -4961,7 +5454,7 @@ var showCmd5 = defineCommand22({
|
|
|
4961
5454
|
}
|
|
4962
5455
|
}
|
|
4963
5456
|
});
|
|
4964
|
-
var reconnectCmd =
|
|
5457
|
+
var reconnectCmd = defineCommand24({
|
|
4965
5458
|
meta: {
|
|
4966
5459
|
name: "reconnect",
|
|
4967
5460
|
description: "Apply a pending supergroup chat-id migration + re-activate the bot"
|
|
@@ -4972,7 +5465,7 @@ var reconnectCmd = defineCommand22({
|
|
|
4972
5465
|
console.log(`reconnected \xB7 chat ${state.chatId}`);
|
|
4973
5466
|
}
|
|
4974
5467
|
});
|
|
4975
|
-
var configCmd =
|
|
5468
|
+
var configCmd = defineCommand24({
|
|
4976
5469
|
meta: {
|
|
4977
5470
|
name: "config",
|
|
4978
5471
|
description: "Manage Telegram credentials (bot token + chat ID)"
|
|
@@ -4983,7 +5476,7 @@ var configCmd = defineCommand22({
|
|
|
4983
5476
|
show: showCmd5
|
|
4984
5477
|
}
|
|
4985
5478
|
});
|
|
4986
|
-
var healthCmd =
|
|
5479
|
+
var healthCmd = defineCommand24({
|
|
4987
5480
|
meta: {
|
|
4988
5481
|
name: "health",
|
|
4989
5482
|
description: "Run the four-step preflight against the Telegram Bot API"
|
|
@@ -5013,11 +5506,16 @@ var healthCmd = defineCommand22({
|
|
|
5013
5506
|
console.log(line(p.isForum, "forum topics enabled", String(p.isForum)));
|
|
5014
5507
|
console.log(line(p.hasManageTopics, "can_manage_topics", String(p.hasManageTopics)));
|
|
5015
5508
|
console.log(line(p.privacyModeOff, "Privacy Mode is OFF", String(p.privacyModeOff)));
|
|
5016
|
-
|
|
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;
|
|
5017
5515
|
if (!allOk) process.exitCode = 1;
|
|
5018
5516
|
}
|
|
5019
5517
|
});
|
|
5020
|
-
var botStatusCmd =
|
|
5518
|
+
var botStatusCmd = defineCommand24({
|
|
5021
5519
|
meta: {
|
|
5022
5520
|
name: "status",
|
|
5023
5521
|
description: "Show polling state of the live bot"
|
|
@@ -5042,7 +5540,7 @@ var botStatusCmd = defineCommand22({
|
|
|
5042
5540
|
if (!p.running) process.exitCode = 1;
|
|
5043
5541
|
}
|
|
5044
5542
|
});
|
|
5045
|
-
var botRestartCmd =
|
|
5543
|
+
var botRestartCmd = defineCommand24({
|
|
5046
5544
|
meta: {
|
|
5047
5545
|
name: "restart",
|
|
5048
5546
|
description: "Force-restart the bot (tears down + brings up from current creds)"
|
|
@@ -5053,7 +5551,7 @@ var botRestartCmd = defineCommand22({
|
|
|
5053
5551
|
console.log("restart requested");
|
|
5054
5552
|
}
|
|
5055
5553
|
});
|
|
5056
|
-
var botCmd =
|
|
5554
|
+
var botCmd = defineCommand24({
|
|
5057
5555
|
meta: {
|
|
5058
5556
|
name: "bot",
|
|
5059
5557
|
description: "Inspect / control the live polling bot"
|
|
@@ -5063,7 +5561,7 @@ var botCmd = defineCommand22({
|
|
|
5063
5561
|
restart: botRestartCmd
|
|
5064
5562
|
}
|
|
5065
5563
|
});
|
|
5066
|
-
var bindCmd =
|
|
5564
|
+
var bindCmd = defineCommand24({
|
|
5067
5565
|
meta: {
|
|
5068
5566
|
name: "bind",
|
|
5069
5567
|
description: "Create a Telegram topic for an agent (manual fallback for /talk)"
|
|
@@ -5081,7 +5579,7 @@ var bindCmd = defineCommand22({
|
|
|
5081
5579
|
console.log(` ${result.deepLink}`);
|
|
5082
5580
|
}
|
|
5083
5581
|
});
|
|
5084
|
-
var unbindCmd =
|
|
5582
|
+
var unbindCmd = defineCommand24({
|
|
5085
5583
|
meta: {
|
|
5086
5584
|
name: "unbind",
|
|
5087
5585
|
description: "Clear an agent's Telegram topic binding (topic stays in Telegram as orphan)"
|
|
@@ -5095,7 +5593,7 @@ var unbindCmd = defineCommand22({
|
|
|
5095
5593
|
console.log(`unbound agent ${args.agent}`);
|
|
5096
5594
|
}
|
|
5097
5595
|
});
|
|
5098
|
-
var listBindingsCmd =
|
|
5596
|
+
var listBindingsCmd = defineCommand24({
|
|
5099
5597
|
meta: {
|
|
5100
5598
|
name: "list",
|
|
5101
5599
|
description: "List agents and their Telegram topic bindings"
|
|
@@ -5123,24 +5621,23 @@ var listBindingsCmd = defineCommand22({
|
|
|
5123
5621
|
}
|
|
5124
5622
|
}
|
|
5125
5623
|
});
|
|
5126
|
-
var allowCmd =
|
|
5624
|
+
var allowCmd = defineCommand24({
|
|
5127
5625
|
meta: { name: "allow", description: "Add a Telegram user id to the allowlist" },
|
|
5128
5626
|
args: {
|
|
5129
5627
|
userId: { type: "positional", required: true, description: "Numeric Telegram user id" },
|
|
5130
|
-
label: { type: "string", description: "Optional human label" }
|
|
5131
|
-
owner: { type: "boolean", description: "Grant owner role (can manage the allowlist)" }
|
|
5628
|
+
label: { type: "string", description: "Optional human label" }
|
|
5132
5629
|
},
|
|
5133
5630
|
async run({ args }) {
|
|
5134
5631
|
const client = createClient2();
|
|
5135
5632
|
const u = await client.post("/api/config/telegram/acl", {
|
|
5136
5633
|
userId: Number(args.userId),
|
|
5137
5634
|
label: args.label ?? null,
|
|
5138
|
-
role:
|
|
5635
|
+
role: "member"
|
|
5139
5636
|
});
|
|
5140
5637
|
console.log(`allowed ${u.userId} (${u.role})`);
|
|
5141
5638
|
}
|
|
5142
5639
|
});
|
|
5143
|
-
var denyCmd =
|
|
5640
|
+
var denyCmd = defineCommand24({
|
|
5144
5641
|
meta: { name: "deny", description: "Remove a Telegram user id from the allowlist" },
|
|
5145
5642
|
args: { userId: { type: "positional", required: true } },
|
|
5146
5643
|
async run({ args }) {
|
|
@@ -5149,13 +5646,13 @@ var denyCmd = defineCommand22({
|
|
|
5149
5646
|
console.log(`removed ${args.userId}`);
|
|
5150
5647
|
}
|
|
5151
5648
|
});
|
|
5152
|
-
var allowedCmd =
|
|
5649
|
+
var allowedCmd = defineCommand24({
|
|
5153
5650
|
meta: { name: "allowed", description: "List allowlisted Telegram users" },
|
|
5154
5651
|
async run() {
|
|
5155
5652
|
const client = createClient2();
|
|
5156
5653
|
const users = await client.get("/api/config/telegram/acl");
|
|
5157
5654
|
if (users.length === 0) {
|
|
5158
|
-
console.log("(allowlist empty \u2014
|
|
5655
|
+
console.log("(allowlist empty \u2014 unpaired and closed)");
|
|
5159
5656
|
return;
|
|
5160
5657
|
}
|
|
5161
5658
|
for (const u of users) {
|
|
@@ -5164,7 +5661,56 @@ var allowedCmd = defineCommand22({
|
|
|
5164
5661
|
}
|
|
5165
5662
|
}
|
|
5166
5663
|
});
|
|
5167
|
-
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({
|
|
5168
5714
|
meta: {
|
|
5169
5715
|
name: "telegram",
|
|
5170
5716
|
description: "Telegram integration: credentials, health, bot lifecycle, bindings, access"
|
|
@@ -5179,47 +5725,42 @@ var telegramCommand = defineCommand22({
|
|
|
5179
5725
|
list: listBindingsCmd,
|
|
5180
5726
|
allow: allowCmd,
|
|
5181
5727
|
deny: denyCmd,
|
|
5182
|
-
allowed: allowedCmd
|
|
5728
|
+
allowed: allowedCmd,
|
|
5729
|
+
pairing: pairingCmd
|
|
5183
5730
|
}
|
|
5184
5731
|
});
|
|
5185
5732
|
|
|
5186
5733
|
// src/commands/token.ts
|
|
5187
|
-
import {
|
|
5188
|
-
import { defineCommand as defineCommand23 } from "citty";
|
|
5734
|
+
import { defineCommand as defineCommand25 } from "citty";
|
|
5189
5735
|
import qrcode from "qrcode-terminal";
|
|
5190
5736
|
function tokenRow(t) {
|
|
5191
5737
|
const last = t.lastUsedAt ? new Date(t.lastUsedAt).toISOString() : "(never)";
|
|
5192
|
-
const
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
const candidates = [];
|
|
5197
|
-
for (const ifs of Object.values(networkInterfaces())) {
|
|
5198
|
-
for (const i of ifs ?? []) {
|
|
5199
|
-
if (i.family === "IPv4" && !i.internal) candidates.push(i.address);
|
|
5200
|
-
}
|
|
5201
|
-
}
|
|
5202
|
-
const [first, ...rest] = candidates;
|
|
5203
|
-
if (!first) return null;
|
|
5204
|
-
const origin = `http://${first}:${port}`;
|
|
5205
|
-
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}`];
|
|
5206
5742
|
}
|
|
5207
5743
|
function resolveQrServer(override) {
|
|
5208
|
-
|
|
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
|
+
}
|
|
5209
5755
|
const cfg = loadClientConfig();
|
|
5210
|
-
|
|
5211
|
-
const isLoopback = current.hostname === "127.0.0.1" || current.hostname === "localhost" || current.hostname === "::1";
|
|
5212
|
-
if (!isLoopback) return cfg.serverUrl.replace(/\/$/, "");
|
|
5213
|
-
const detected = detectLanOrigin(current.port || "4321");
|
|
5214
|
-
if (!detected) {
|
|
5756
|
+
if (loopback && !override && new URL(cfg.serverUrl).hostname === url.hostname) {
|
|
5215
5757
|
throw new Error(
|
|
5216
|
-
"server URL is loopback-only
|
|
5758
|
+
"server URL is loopback-only. Pass --server https://<private-tailnet-host> for mobile pairing."
|
|
5217
5759
|
);
|
|
5218
5760
|
}
|
|
5219
|
-
|
|
5220
|
-
return detected.origin;
|
|
5761
|
+
return url.origin;
|
|
5221
5762
|
}
|
|
5222
|
-
var createCmd3 =
|
|
5763
|
+
var createCmd3 = defineCommand25({
|
|
5223
5764
|
meta: { name: "create", description: "Mint a new web token (shown once)" },
|
|
5224
5765
|
args: {
|
|
5225
5766
|
label: { type: "positional", required: true, description: "Human-readable label" },
|
|
@@ -5230,14 +5771,26 @@ var createCmd3 = defineCommand23({
|
|
|
5230
5771
|
server: {
|
|
5231
5772
|
type: "string",
|
|
5232
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)"
|
|
5233
5778
|
}
|
|
5234
5779
|
},
|
|
5235
5780
|
async run({ args }) {
|
|
5236
5781
|
const client = createClient2();
|
|
5237
|
-
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 };
|
|
5238
5787
|
const res = await client.post("/api/tokens", body);
|
|
5239
5788
|
console.log(`id: ${res.meta.id}`);
|
|
5240
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
|
+
);
|
|
5241
5794
|
console.log(`token: ${res.token}`);
|
|
5242
5795
|
console.log("");
|
|
5243
5796
|
console.log("store the token now \u2014 it is not recoverable later.");
|
|
@@ -5250,7 +5803,7 @@ var createCmd3 = defineCommand23({
|
|
|
5250
5803
|
qrcode.generate(pairUrl, { small: true }, (qr) => console.log(qr));
|
|
5251
5804
|
}
|
|
5252
5805
|
});
|
|
5253
|
-
var
|
|
5806
|
+
var listCmd11 = defineCommand25({
|
|
5254
5807
|
meta: { name: "list", description: "List web tokens" },
|
|
5255
5808
|
args: {
|
|
5256
5809
|
all: { type: "boolean", description: "Include revoked tokens" }
|
|
@@ -5266,7 +5819,7 @@ var listCmd10 = defineCommand23({
|
|
|
5266
5819
|
for (const line of columnize(tokens.map(tokenRow))) console.log(line);
|
|
5267
5820
|
}
|
|
5268
5821
|
});
|
|
5269
|
-
var showLocalCmd =
|
|
5822
|
+
var showLocalCmd = defineCommand25({
|
|
5270
5823
|
meta: {
|
|
5271
5824
|
name: "show-local",
|
|
5272
5825
|
description: "Print the bootstrap web token stored in ~/.bazilion/auth.json"
|
|
@@ -5276,7 +5829,7 @@ var showLocalCmd = defineCommand23({
|
|
|
5276
5829
|
console.log(readAuthFile(paths.authFile).token);
|
|
5277
5830
|
}
|
|
5278
5831
|
});
|
|
5279
|
-
var
|
|
5832
|
+
var revokeCmd2 = defineCommand25({
|
|
5280
5833
|
meta: { name: "revoke", description: "Revoke a web token" },
|
|
5281
5834
|
args: {
|
|
5282
5835
|
id: { type: "positional", required: true }
|
|
@@ -5287,19 +5840,19 @@ var revokeCmd = defineCommand23({
|
|
|
5287
5840
|
console.log(`revoked token ${args.id}`);
|
|
5288
5841
|
}
|
|
5289
5842
|
});
|
|
5290
|
-
var tokenCommand =
|
|
5843
|
+
var tokenCommand = defineCommand25({
|
|
5291
5844
|
meta: { name: "token", description: "Manage web tokens for API/CLI clients" },
|
|
5292
5845
|
subCommands: {
|
|
5293
5846
|
create: createCmd3,
|
|
5294
|
-
list:
|
|
5295
|
-
revoke:
|
|
5847
|
+
list: listCmd11,
|
|
5848
|
+
revoke: revokeCmd2,
|
|
5296
5849
|
"show-local": showLocalCmd
|
|
5297
5850
|
}
|
|
5298
5851
|
});
|
|
5299
5852
|
|
|
5300
5853
|
// src/commands/trigger.ts
|
|
5301
|
-
import { defineCommand as
|
|
5302
|
-
var addCmd3 =
|
|
5854
|
+
import { defineCommand as defineCommand26 } from "citty";
|
|
5855
|
+
var addCmd3 = defineCommand26({
|
|
5303
5856
|
meta: { name: "add", description: "Add an interval / cron trigger to an agent" },
|
|
5304
5857
|
args: {
|
|
5305
5858
|
agent: { type: "positional", required: true },
|
|
@@ -5347,7 +5900,7 @@ function triggerRow(t) {
|
|
|
5347
5900
|
const msgPreview = t.message.length > 60 ? `${t.message.slice(0, 60)}\u2026` : t.message;
|
|
5348
5901
|
return [t.id, state, spec, `last: ${last}`, `"${msgPreview}"`];
|
|
5349
5902
|
}
|
|
5350
|
-
var
|
|
5903
|
+
var listCmd12 = defineCommand26({
|
|
5351
5904
|
meta: { name: "list", description: "List triggers for an agent" },
|
|
5352
5905
|
args: {
|
|
5353
5906
|
agent: { type: "positional", required: true }
|
|
@@ -5364,7 +5917,7 @@ var listCmd11 = defineCommand24({
|
|
|
5364
5917
|
for (const line of columnize(triggers.map(triggerRow))) console.log(line);
|
|
5365
5918
|
}
|
|
5366
5919
|
});
|
|
5367
|
-
var rmCmd6 =
|
|
5920
|
+
var rmCmd6 = defineCommand26({
|
|
5368
5921
|
meta: { name: "rm", description: "Delete a trigger" },
|
|
5369
5922
|
args: {
|
|
5370
5923
|
id: { type: "positional", required: true }
|
|
@@ -5375,7 +5928,7 @@ var rmCmd6 = defineCommand24({
|
|
|
5375
5928
|
console.log(`removed trigger ${args.id}`);
|
|
5376
5929
|
}
|
|
5377
5930
|
});
|
|
5378
|
-
var enableCmd3 =
|
|
5931
|
+
var enableCmd3 = defineCommand26({
|
|
5379
5932
|
meta: { name: "enable", description: "Enable a trigger" },
|
|
5380
5933
|
args: {
|
|
5381
5934
|
id: { type: "positional", required: true }
|
|
@@ -5387,7 +5940,7 @@ var enableCmd3 = defineCommand24({
|
|
|
5387
5940
|
console.log(`enabled trigger ${args.id}`);
|
|
5388
5941
|
}
|
|
5389
5942
|
});
|
|
5390
|
-
var disableCmd3 =
|
|
5943
|
+
var disableCmd3 = defineCommand26({
|
|
5391
5944
|
meta: { name: "disable", description: "Disable a trigger" },
|
|
5392
5945
|
args: {
|
|
5393
5946
|
id: { type: "positional", required: true }
|
|
@@ -5399,7 +5952,7 @@ var disableCmd3 = defineCommand24({
|
|
|
5399
5952
|
console.log(`disabled trigger ${args.id}`);
|
|
5400
5953
|
}
|
|
5401
5954
|
});
|
|
5402
|
-
var historyCmd =
|
|
5955
|
+
var historyCmd = defineCommand26({
|
|
5403
5956
|
meta: { name: "history", description: "Show recent dispatches for a trigger" },
|
|
5404
5957
|
args: {
|
|
5405
5958
|
id: { type: "positional", required: true },
|
|
@@ -5427,11 +5980,11 @@ var historyCmd = defineCommand24({
|
|
|
5427
5980
|
for (const line of columnize(rows)) console.log(line);
|
|
5428
5981
|
}
|
|
5429
5982
|
});
|
|
5430
|
-
var triggerCommand =
|
|
5983
|
+
var triggerCommand = defineCommand26({
|
|
5431
5984
|
meta: { name: "trigger", description: "Manage scheduled agent triggers" },
|
|
5432
5985
|
subCommands: {
|
|
5433
5986
|
add: addCmd3,
|
|
5434
|
-
list:
|
|
5987
|
+
list: listCmd12,
|
|
5435
5988
|
rm: rmCmd6,
|
|
5436
5989
|
enable: enableCmd3,
|
|
5437
5990
|
disable: disableCmd3,
|
|
@@ -5442,7 +5995,7 @@ var triggerCommand = defineCommand24({
|
|
|
5442
5995
|
// src/commands/uninstall.ts
|
|
5443
5996
|
import { existsSync as existsSync7, readdirSync as readdirSync2, rmSync as rmSync4 } from "fs";
|
|
5444
5997
|
import { join as join6 } from "path";
|
|
5445
|
-
import { defineCommand as
|
|
5998
|
+
import { defineCommand as defineCommand27 } from "citty";
|
|
5446
5999
|
function makeLineReader() {
|
|
5447
6000
|
let buffer = "";
|
|
5448
6001
|
let ended = false;
|
|
@@ -5490,7 +6043,7 @@ function removePath(p) {
|
|
|
5490
6043
|
rmSync4(p, { recursive: true, force: true });
|
|
5491
6044
|
return true;
|
|
5492
6045
|
}
|
|
5493
|
-
var uninstallCommand =
|
|
6046
|
+
var uninstallCommand = defineCommand27({
|
|
5494
6047
|
meta: {
|
|
5495
6048
|
name: "uninstall",
|
|
5496
6049
|
description: "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"
|
|
@@ -5561,7 +6114,7 @@ var uninstallCommand = defineCommand25({
|
|
|
5561
6114
|
|
|
5562
6115
|
// src/index.ts
|
|
5563
6116
|
var VERSION = package_default.version;
|
|
5564
|
-
var main =
|
|
6117
|
+
var main = defineCommand28({
|
|
5565
6118
|
meta: {
|
|
5566
6119
|
name: "bazilion",
|
|
5567
6120
|
version: VERSION,
|
|
@@ -5580,11 +6133,13 @@ var main = defineCommand26({
|
|
|
5580
6133
|
mcp: mcpCommand,
|
|
5581
6134
|
provider: providerCommand,
|
|
5582
6135
|
send: sendCommand,
|
|
6136
|
+
session: sessionCommand,
|
|
5583
6137
|
inbox: inboxCommand,
|
|
5584
6138
|
config: configCommand,
|
|
5585
6139
|
serve: serveCommand,
|
|
5586
6140
|
dashboard: dashboardCommand,
|
|
5587
6141
|
doctor: doctorCommand,
|
|
6142
|
+
gateway: gatewayCommand,
|
|
5588
6143
|
backup: backupCommand,
|
|
5589
6144
|
trigger: triggerCommand,
|
|
5590
6145
|
token: tokenCommand,
|
|
@@ -5684,7 +6239,7 @@ function printTopLevelHelp() {
|
|
|
5684
6239
|
},
|
|
5685
6240
|
{
|
|
5686
6241
|
title: "ops",
|
|
5687
|
-
items: [["backup", "
|
|
6242
|
+
items: [["backup", "Encrypted backup, restore, and credential recovery"]]
|
|
5688
6243
|
},
|
|
5689
6244
|
{
|
|
5690
6245
|
title: "remote",
|