bazilion 0.0.0 → 0.1.1

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.
Files changed (265) hide show
  1. package/README.md +53 -152
  2. package/dist/cli.js +2730 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/daemon.js +6460 -0
  5. package/dist/daemon.js.map +1 -0
  6. package/dist/worker.js +2176 -0
  7. package/dist/worker.js.map +1 -0
  8. package/package.json +57 -28
  9. package/.understand-anything/.understandignore +0 -25
  10. package/.understand-anything/fingerprints.json +0 -14267
  11. package/.understand-anything/knowledge-graph.json +0 -18128
  12. package/.understand-anything/meta.json +0 -6
  13. package/CLAUDE.md +0 -164
  14. package/apps/cli/package.json +0 -21
  15. package/apps/cli/src/auth-file.ts +0 -18
  16. package/apps/cli/src/client.ts +0 -37
  17. package/apps/cli/src/columnize.ts +0 -32
  18. package/apps/cli/src/commands/agent.ts +0 -574
  19. package/apps/cli/src/commands/auth.ts +0 -110
  20. package/apps/cli/src/commands/backup.ts +0 -135
  21. package/apps/cli/src/commands/completion.ts +0 -155
  22. package/apps/cli/src/commands/config.ts +0 -95
  23. package/apps/cli/src/commands/doctor.ts +0 -131
  24. package/apps/cli/src/commands/group.ts +0 -132
  25. package/apps/cli/src/commands/inbox.ts +0 -82
  26. package/apps/cli/src/commands/login.ts +0 -73
  27. package/apps/cli/src/commands/memory.ts +0 -106
  28. package/apps/cli/src/commands/profile.ts +0 -259
  29. package/apps/cli/src/commands/provider.ts +0 -170
  30. package/apps/cli/src/commands/send.ts +0 -24
  31. package/apps/cli/src/commands/serve.ts +0 -89
  32. package/apps/cli/src/commands/skill.ts +0 -120
  33. package/apps/cli/src/commands/token.ts +0 -148
  34. package/apps/cli/src/commands/trigger.ts +0 -129
  35. package/apps/cli/src/commands/uninstall.ts +0 -156
  36. package/apps/cli/src/index.ts +0 -196
  37. package/apps/cli/src/paths.ts +0 -12
  38. package/apps/cli/test/agent.test.ts +0 -213
  39. package/apps/cli/test/backup.test.ts +0 -95
  40. package/apps/cli/test/chat.test.ts +0 -539
  41. package/apps/cli/test/columnize.test.ts +0 -29
  42. package/apps/cli/test/completion.test.ts +0 -45
  43. package/apps/cli/test/config-page.test.ts +0 -151
  44. package/apps/cli/test/group.test.ts +0 -74
  45. package/apps/cli/test/helpers.ts +0 -70
  46. package/apps/cli/test/inbox-autodeliver.test.ts +0 -143
  47. package/apps/cli/test/inbox.test.ts +0 -147
  48. package/apps/cli/test/memory.test.ts +0 -69
  49. package/apps/cli/test/profile.test.ts +0 -110
  50. package/apps/cli/test/send.test.ts +0 -30
  51. package/apps/cli/test/server-fixture.ts +0 -212
  52. package/apps/cli/test/session-head.test.ts +0 -45
  53. package/apps/cli/test/skill.test.ts +0 -128
  54. package/apps/cli/test/token.test.ts +0 -109
  55. package/apps/cli/test/trigger.test.ts +0 -245
  56. package/apps/cli/tsconfig.json +0 -4
  57. package/apps/daemon/package.json +0 -31
  58. package/apps/daemon/src/app.ts +0 -41
  59. package/apps/daemon/src/core/agent/archive.ts +0 -8
  60. package/apps/daemon/src/core/agent/delete.ts +0 -30
  61. package/apps/daemon/src/core/agent/resolve.ts +0 -31
  62. package/apps/daemon/src/core/agent/spawn.ts +0 -95
  63. package/apps/daemon/src/core/agent/unarchive.ts +0 -11
  64. package/apps/daemon/src/core/availableModels.ts +0 -58
  65. package/apps/daemon/src/core/db/client.ts +0 -113
  66. package/apps/daemon/src/core/db/migrate.ts +0 -41
  67. package/apps/daemon/src/core/db/migrations/0001_init.sql +0 -179
  68. package/apps/daemon/src/core/group/delete.ts +0 -21
  69. package/apps/daemon/src/core/group/register.ts +0 -68
  70. package/apps/daemon/src/core/index.ts +0 -71
  71. package/apps/daemon/src/core/paths.ts +0 -56
  72. package/apps/daemon/src/core/profile/create.ts +0 -78
  73. package/apps/daemon/src/core/profile/delete.ts +0 -26
  74. package/apps/daemon/src/core/profile/identity.ts +0 -70
  75. package/apps/daemon/src/core/profile/load.ts +0 -45
  76. package/apps/daemon/src/core/profile/seed.ts +0 -74
  77. package/apps/daemon/src/core/profile/templates.ts +0 -60
  78. package/apps/daemon/src/core/profile/update.ts +0 -57
  79. package/apps/daemon/src/core/profile/validate.ts +0 -9
  80. package/apps/daemon/src/core/repos/agents.ts +0 -202
  81. package/apps/daemon/src/core/repos/config.ts +0 -78
  82. package/apps/daemon/src/core/repos/groups.ts +0 -55
  83. package/apps/daemon/src/core/repos/messages.ts +0 -127
  84. package/apps/daemon/src/core/repos/profiles.ts +0 -83
  85. package/apps/daemon/src/core/repos/providerModels.ts +0 -58
  86. package/apps/daemon/src/core/repos/providerState.ts +0 -37
  87. package/apps/daemon/src/core/repos/secrets.ts +0 -145
  88. package/apps/daemon/src/core/repos/skillMeta.ts +0 -49
  89. package/apps/daemon/src/core/repos/triggers.ts +0 -101
  90. package/apps/daemon/src/core/repos/webTokens.ts +0 -87
  91. package/apps/daemon/src/core/secrets.ts +0 -65
  92. package/apps/daemon/src/core/services.ts +0 -264
  93. package/apps/daemon/src/core/skills/discover.ts +0 -28
  94. package/apps/daemon/src/core/skills/import.ts +0 -136
  95. package/apps/daemon/src/core/skills/parse.ts +0 -52
  96. package/apps/daemon/src/core/skills/resolve.ts +0 -50
  97. package/apps/daemon/src/index.ts +0 -45
  98. package/apps/daemon/src/lib/agent-cancel.ts +0 -48
  99. package/apps/daemon/src/lib/agent-id.ts +0 -13
  100. package/apps/daemon/src/lib/agent-turn.ts +0 -56
  101. package/apps/daemon/src/lib/api-key.ts +0 -56
  102. package/apps/daemon/src/lib/auth.ts +0 -41
  103. package/apps/daemon/src/lib/cron.ts +0 -93
  104. package/apps/daemon/src/lib/ctx.ts +0 -80
  105. package/apps/daemon/src/lib/messaging-host.ts +0 -34
  106. package/apps/daemon/src/lib/middleware-auth.ts +0 -52
  107. package/apps/daemon/src/lib/scheduler.ts +0 -294
  108. package/apps/daemon/src/routes/agents.ts +0 -772
  109. package/apps/daemon/src/routes/auth-login.ts +0 -193
  110. package/apps/daemon/src/routes/config.ts +0 -267
  111. package/apps/daemon/src/routes/groups.ts +0 -133
  112. package/apps/daemon/src/routes/messages.ts +0 -29
  113. package/apps/daemon/src/routes/misc.ts +0 -239
  114. package/apps/daemon/src/routes/profiles.ts +0 -197
  115. package/apps/daemon/src/routes/skills.ts +0 -123
  116. package/apps/daemon/src/routes/triggers.ts +0 -29
  117. package/apps/daemon/src/runtime/auth/openai-codex.ts +0 -121
  118. package/apps/daemon/src/runtime/auto-reply/heartbeat.ts +0 -31
  119. package/apps/daemon/src/runtime/index.ts +0 -77
  120. package/apps/daemon/src/runtime/memory/files.ts +0 -103
  121. package/apps/daemon/src/runtime/memory/qmd.ts +0 -152
  122. package/apps/daemon/src/runtime/memory/types.ts +0 -16
  123. package/apps/daemon/src/runtime/pi/events.ts +0 -173
  124. package/apps/daemon/src/runtime/pi/session.ts +0 -536
  125. package/apps/daemon/src/runtime/pi/tools.ts +0 -85
  126. package/apps/daemon/src/runtime/providers/catalog.ts +0 -145
  127. package/apps/daemon/src/runtime/providers/pi-adapter.ts +0 -272
  128. package/apps/daemon/src/runtime/providers/registry.ts +0 -374
  129. package/apps/daemon/src/runtime/providers/retry.ts +0 -176
  130. package/apps/daemon/src/runtime/providers/types.ts +0 -33
  131. package/apps/daemon/src/runtime/session/prompt.ts +0 -83
  132. package/apps/daemon/src/runtime/tools/bootstrap.ts +0 -22
  133. package/apps/daemon/src/runtime/tools/home.ts +0 -114
  134. package/apps/daemon/src/runtime/tools/memory.ts +0 -81
  135. package/apps/daemon/src/runtime/tools/messaging.ts +0 -127
  136. package/apps/daemon/src/runtime/tools/registry.ts +0 -29
  137. package/apps/daemon/src/runtime/tools/types.ts +0 -13
  138. package/apps/daemon/src/runtime/tools/web-extract.ts +0 -110
  139. package/apps/daemon/src/runtime/tools/web-ssrf.ts +0 -245
  140. package/apps/daemon/src/runtime/tools/web.ts +0 -273
  141. package/apps/daemon/src/runtime/worker/entry.ts +0 -221
  142. package/apps/daemon/src/runtime/worker/ipc-protocol.ts +0 -75
  143. package/apps/daemon/src/runtime/worker/spawn.ts +0 -249
  144. package/apps/daemon/test/core/agents.test.ts +0 -319
  145. package/apps/daemon/test/core/available-models.test.ts +0 -63
  146. package/apps/daemon/test/core/config.test.ts +0 -99
  147. package/apps/daemon/test/core/groups.test.ts +0 -63
  148. package/apps/daemon/test/core/helpers.ts +0 -50
  149. package/apps/daemon/test/core/identity.test.ts +0 -85
  150. package/apps/daemon/test/core/migrations.test.ts +0 -83
  151. package/apps/daemon/test/core/profiles.test.ts +0 -182
  152. package/apps/daemon/test/core/provider-models.test.ts +0 -57
  153. package/apps/daemon/test/core/provider-state.test.ts +0 -36
  154. package/apps/daemon/test/core/skill-meta.test.ts +0 -45
  155. package/apps/daemon/test/core/skills.test.ts +0 -271
  156. package/apps/daemon/test/core/triggers.test.ts +0 -182
  157. package/apps/daemon/test/core/web-tokens.test.ts +0 -79
  158. package/apps/daemon/test/cron.test.ts +0 -90
  159. package/apps/daemon/test/runtime/heartbeat.test.ts +0 -34
  160. package/apps/daemon/test/runtime/memory-qmd.test.ts +0 -97
  161. package/apps/daemon/test/runtime/memory.test.ts +0 -78
  162. package/apps/daemon/test/runtime/messaging.test.ts +0 -213
  163. package/apps/daemon/test/runtime/mock-server.ts +0 -65
  164. package/apps/daemon/test/runtime/openai-codex-auth.test.ts +0 -116
  165. package/apps/daemon/test/runtime/providers.test.ts +0 -306
  166. package/apps/daemon/test/runtime/retry.test.ts +0 -191
  167. package/apps/daemon/test/runtime/session-head.test.ts +0 -90
  168. package/apps/daemon/test/runtime/tools-home.test.ts +0 -102
  169. package/apps/daemon/test/runtime/tools-web.test.ts +0 -206
  170. package/apps/daemon/tsconfig.json +0 -4
  171. package/apps/mobile/README.md +0 -60
  172. package/apps/mobile/app/_layout.tsx +0 -58
  173. package/apps/mobile/app/agents/[id]/chat.tsx +0 -486
  174. package/apps/mobile/app/agents/[id]/index.tsx +0 -166
  175. package/apps/mobile/app/agents/index.tsx +0 -212
  176. package/apps/mobile/app/index.tsx +0 -21
  177. package/apps/mobile/app/pair.tsx +0 -226
  178. package/apps/mobile/app/settings.tsx +0 -419
  179. package/apps/mobile/app.json +0 -49
  180. package/apps/mobile/assets/adaptive-icon.png +0 -0
  181. package/apps/mobile/assets/favicon.png +0 -0
  182. package/apps/mobile/assets/icon.png +0 -0
  183. package/apps/mobile/assets/splash-icon.png +0 -0
  184. package/apps/mobile/babel.config.js +0 -6
  185. package/apps/mobile/metro.config.js +0 -28
  186. package/apps/mobile/package.json +0 -44
  187. package/apps/mobile/src/auth.ts +0 -66
  188. package/apps/mobile/src/pair-url.ts +0 -48
  189. package/apps/mobile/src/theme-context.tsx +0 -88
  190. package/apps/mobile/src/theme.ts +0 -135
  191. package/apps/mobile/test/pair-url.test.ts +0 -46
  192. package/apps/mobile/tsconfig.json +0 -23
  193. package/apps/web/components.json +0 -25
  194. package/apps/web/package.json +0 -39
  195. package/apps/web/public/baziu.svg +0 -8
  196. package/apps/web/src/components/AgentTabs.tsx +0 -45
  197. package/apps/web/src/components/BaziuLogo.tsx +0 -21
  198. package/apps/web/src/components/ChatPane.tsx +0 -1033
  199. package/apps/web/src/components/ConfigTabs.tsx +0 -29
  200. package/apps/web/src/components/CopyButton.tsx +0 -68
  201. package/apps/web/src/components/CreateGroupDialog.tsx +0 -127
  202. package/apps/web/src/components/FieldRow.tsx +0 -94
  203. package/apps/web/src/components/Footer.tsx +0 -10
  204. package/apps/web/src/components/PawIcon.tsx +0 -15
  205. package/apps/web/src/components/Sidebar.tsx +0 -287
  206. package/apps/web/src/components/SpawnDialog.tsx +0 -129
  207. package/apps/web/src/components/ThemeToggle.tsx +0 -75
  208. package/apps/web/src/components/TopNav.tsx +0 -34
  209. package/apps/web/src/components/ui/button.tsx +0 -67
  210. package/apps/web/src/components/ui/card.tsx +0 -103
  211. package/apps/web/src/components/ui/checkbox.tsx +0 -31
  212. package/apps/web/src/components/ui/dialog.tsx +0 -168
  213. package/apps/web/src/components/ui/input.tsx +0 -19
  214. package/apps/web/src/components/ui/label.tsx +0 -22
  215. package/apps/web/src/components/ui/radio-group.tsx +0 -44
  216. package/apps/web/src/components/ui/select.tsx +0 -192
  217. package/apps/web/src/components/ui/separator.tsx +0 -26
  218. package/apps/web/src/components/ui/table.tsx +0 -116
  219. package/apps/web/src/components/ui/tabs.tsx +0 -88
  220. package/apps/web/src/components/ui/textarea.tsx +0 -18
  221. package/apps/web/src/lib/auth.ts +0 -50
  222. package/apps/web/src/lib/daemon-client.ts +0 -34
  223. package/apps/web/src/lib/md.ts +0 -45
  224. package/apps/web/src/lib/utils.ts +0 -6
  225. package/apps/web/src/lib/wire-constants.ts +0 -27
  226. package/apps/web/src/routeTree.gen.ts +0 -408
  227. package/apps/web/src/router.tsx +0 -20
  228. package/apps/web/src/routes/__root.tsx +0 -123
  229. package/apps/web/src/routes/agents/$id/inbox.tsx +0 -207
  230. package/apps/web/src/routes/agents/$id/index.tsx +0 -527
  231. package/apps/web/src/routes/agents/$id/triggers.tsx +0 -239
  232. package/apps/web/src/routes/agents/index.tsx +0 -265
  233. package/apps/web/src/routes/api/$.ts +0 -88
  234. package/apps/web/src/routes/config/index.tsx +0 -315
  235. package/apps/web/src/routes/config/services.tsx +0 -49
  236. package/apps/web/src/routes/config/tokens.tsx +0 -192
  237. package/apps/web/src/routes/groups/$id/index.tsx +0 -153
  238. package/apps/web/src/routes/groups/$id/memory.tsx +0 -321
  239. package/apps/web/src/routes/groups/index.tsx +0 -191
  240. package/apps/web/src/routes/index.tsx +0 -133
  241. package/apps/web/src/routes/login.tsx +0 -63
  242. package/apps/web/src/routes/profiles/$id.tsx +0 -549
  243. package/apps/web/src/routes/profiles/index.tsx +0 -458
  244. package/apps/web/src/routes/skills/index.tsx +0 -297
  245. package/apps/web/src/routes/welcome.tsx +0 -61
  246. package/apps/web/src/styles.css +0 -449
  247. package/apps/web/tsconfig.json +0 -25
  248. package/apps/web/vite.config.ts +0 -25
  249. package/biome.json +0 -23
  250. package/docs/agent-engine.md +0 -219
  251. package/docs/architecture.md +0 -627
  252. package/docs/backlog/README.md +0 -42
  253. package/docs/backlog/draft/BAZ-001-a2a-federation-spike.md +0 -125
  254. package/docs/openclaw-reference.md +0 -210
  255. package/packages/api-types/package.json +0 -11
  256. package/packages/api-types/src/entities.ts +0 -146
  257. package/packages/api-types/src/events.ts +0 -55
  258. package/packages/api-types/src/index.ts +0 -488
  259. package/packages/api-types/src/memory.ts +0 -15
  260. package/packages/client/package.json +0 -13
  261. package/packages/client/src/index.ts +0 -117
  262. package/pnpm-workspace.yaml +0 -3
  263. package/tsconfig.base.json +0 -23
  264. package/tsconfig.json +0 -11
  265. package/vitest.config.ts +0 -22
package/dist/cli.js ADDED
@@ -0,0 +1,2730 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { defineCommand as defineCommand19, runCommand, showUsage } from "citty";
5
+
6
+ // package.json
7
+ var package_default = {
8
+ name: "bazilion",
9
+ version: "0.1.1",
10
+ description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/groups/skills, and run the local daemon.",
11
+ license: "MIT",
12
+ repository: {
13
+ type: "git",
14
+ url: "git+https://github.com/rullopat/bazilion.git",
15
+ directory: "apps/cli"
16
+ },
17
+ homepage: "https://bazilion.com",
18
+ bugs: {
19
+ url: "https://github.com/rullopat/bazilion/issues"
20
+ },
21
+ keywords: [
22
+ "agent",
23
+ "agents",
24
+ "ai",
25
+ "cli",
26
+ "daemon",
27
+ "llm",
28
+ "local-first",
29
+ "multi-agent",
30
+ "openclaw",
31
+ "skills"
32
+ ],
33
+ type: "module",
34
+ bin: {
35
+ bazilion: "./dist/cli.js"
36
+ },
37
+ files: [
38
+ "dist",
39
+ "README.md",
40
+ "LICENSE"
41
+ ],
42
+ scripts: {
43
+ build: "tsup"
44
+ },
45
+ engines: {
46
+ node: ">=24.0.0"
47
+ },
48
+ publishConfig: {
49
+ access: "public"
50
+ },
51
+ dependencies: {
52
+ "@earendil-works/pi-agent-core": "^0.75.4",
53
+ "@earendil-works/pi-ai": "^0.75.4",
54
+ "@earendil-works/pi-coding-agent": "^0.75.4",
55
+ "@hono/node-server": "^2.0.3",
56
+ "@mozilla/readability": "^0.6.0",
57
+ "@tobilu/qmd": "^2.5.2",
58
+ "adm-zip": "^0.5.17",
59
+ citty: "^0.2.2",
60
+ hono: "^4.12.22",
61
+ linkedom: "^0.18.12",
62
+ "qrcode-terminal": "^0.12.0",
63
+ typebox: "^1.1.38",
64
+ undici: "^8.3.0",
65
+ yaml: "^2.9.0"
66
+ },
67
+ devDependencies: {
68
+ "@bazilion/api-types": "workspace:*",
69
+ "@bazilion/client": "workspace:*",
70
+ "@types/adm-zip": "^0.5.8",
71
+ "@types/qrcode-terminal": "^0.12.2"
72
+ }
73
+ };
74
+
75
+ // ../../packages/client/src/index.ts
76
+ var ApiClientError = class extends Error {
77
+ status;
78
+ body;
79
+ constructor(status, body) {
80
+ super(`${status}: ${body.error}`);
81
+ this.status = status;
82
+ this.body = body;
83
+ }
84
+ };
85
+ async function resolveToken(src) {
86
+ return typeof src === "function" ? await src() : src;
87
+ }
88
+ function createClient(cfg) {
89
+ async function authHeaders() {
90
+ const token = await resolveToken(cfg.token);
91
+ return {
92
+ authorization: `Bearer ${token}`,
93
+ // Astro 6 enabled `security.checkOrigin` by default for server mode:
94
+ // any state-changing request without an `Origin` matching the server
95
+ // host is rejected with 403. Browsers set this automatically; `fetch`
96
+ // in Node / React Native does not. Stamping the server's own URL is
97
+ // always valid for a legitimate client.
98
+ origin: cfg.serverUrl
99
+ };
100
+ }
101
+ async function request(method, path, body) {
102
+ const headers = { ...await authHeaders() };
103
+ if (body !== void 0) headers["content-type"] = "application/json";
104
+ const res = await fetch(`${cfg.serverUrl}${path}`, {
105
+ method,
106
+ headers,
107
+ body: body !== void 0 ? JSON.stringify(body) : void 0
108
+ });
109
+ if (!res.ok) {
110
+ const err = await res.json().catch(() => ({ error: res.statusText }));
111
+ throw new ApiClientError(res.status, err);
112
+ }
113
+ if (res.status === 204) return void 0;
114
+ return await res.json();
115
+ }
116
+ async function postMultipart(path, form) {
117
+ const res = await fetch(`${cfg.serverUrl}${path}`, {
118
+ method: "POST",
119
+ headers: { ...await authHeaders() },
120
+ body: form
121
+ });
122
+ if (!res.ok) {
123
+ const err = await res.json().catch(() => ({ error: res.statusText }));
124
+ throw new ApiClientError(res.status, err);
125
+ }
126
+ if (res.status === 204) return void 0;
127
+ return await res.json();
128
+ }
129
+ async function* stream(method, path, body) {
130
+ const headers = { ...await authHeaders() };
131
+ if (body !== void 0) headers["content-type"] = "application/json";
132
+ const res = await fetch(`${cfg.serverUrl}${path}`, {
133
+ method,
134
+ headers,
135
+ body: body !== void 0 ? JSON.stringify(body) : void 0
136
+ });
137
+ if (!res.ok || !res.body) {
138
+ const err = await res.json().catch(() => ({ error: res.statusText }));
139
+ throw new ApiClientError(res.status, err);
140
+ }
141
+ const reader = res.body.getReader();
142
+ const decoder = new TextDecoder();
143
+ let buffer = "";
144
+ while (true) {
145
+ const { done, value } = await reader.read();
146
+ if (done) break;
147
+ buffer += decoder.decode(value, { stream: true });
148
+ const lines = buffer.split("\n");
149
+ buffer = lines.pop() ?? "";
150
+ for (const line of lines) {
151
+ if (line.trim()) yield JSON.parse(line);
152
+ }
153
+ }
154
+ if (buffer.trim()) yield JSON.parse(buffer);
155
+ }
156
+ return {
157
+ get: (p) => request("GET", p),
158
+ post: (p, b) => request("POST", p, b),
159
+ postMultipart,
160
+ put: (p, b) => request("PUT", p, b),
161
+ patch: (p, b) => request("PATCH", p, b),
162
+ del: (p) => request("DELETE", p),
163
+ stream
164
+ };
165
+ }
166
+
167
+ // src/auth-file.ts
168
+ import { existsSync, readFileSync } from "fs";
169
+ function readAuthFile(authFile) {
170
+ if (!existsSync(authFile)) {
171
+ throw new Error(`${authFile} not found. Start the daemon with \`bazilion serve\` first.`);
172
+ }
173
+ const raw = readFileSync(authFile, "utf8");
174
+ const parsed = JSON.parse(raw);
175
+ if (typeof parsed.token !== "string" || !parsed.token) {
176
+ throw new Error(`${authFile} is missing the "token" field`);
177
+ }
178
+ return { token: parsed.token, remote: parsed.remote ?? null };
179
+ }
180
+
181
+ // src/paths.ts
182
+ import { homedir } from "os";
183
+ import { join } from "path";
184
+ function resolveCliPaths(home) {
185
+ const root = home ?? process.env.BAZILION_HOME ?? join(homedir(), ".bazilion");
186
+ return { home: root, authFile: join(root, "auth.json") };
187
+ }
188
+
189
+ // src/client.ts
190
+ function loadClientConfig() {
191
+ const envUrl = process.env.BAZILION_SERVER;
192
+ const envToken = process.env.BAZILION_TOKEN;
193
+ if (envUrl && envToken) return { serverUrl: envUrl, token: envToken };
194
+ const paths = resolveCliPaths();
195
+ const auth = readAuthFile(paths.authFile);
196
+ if (auth.remote?.server && auth.remote.token) {
197
+ return {
198
+ serverUrl: envUrl ?? auth.remote.server,
199
+ token: auth.remote.token
200
+ };
201
+ }
202
+ return {
203
+ serverUrl: envUrl ?? "http://127.0.0.1:4321",
204
+ token: auth.token
205
+ };
206
+ }
207
+ function createClient2(cfg = loadClientConfig()) {
208
+ return createClient({ serverUrl: cfg.serverUrl, token: cfg.token });
209
+ }
210
+
211
+ // src/commands/agent.ts
212
+ import { stdin, stdout } from "process";
213
+ import { createInterface } from "readline/promises";
214
+ import { defineCommand } from "citty";
215
+
216
+ // src/columnize.ts
217
+ function columnize(rows, gap = " ") {
218
+ if (rows.length === 0) return [];
219
+ const colCount = rows[0]?.length ?? 0;
220
+ const widths = new Array(colCount).fill(0);
221
+ for (const row of rows) {
222
+ for (let i = 0; i < colCount; i++) {
223
+ const cell = row[i] ?? "";
224
+ const prev = widths[i] ?? 0;
225
+ if (cell.length > prev) widths[i] = cell.length;
226
+ }
227
+ }
228
+ return rows.map(
229
+ (row) => row.map((cell, i) => {
230
+ if (i === colCount - 1) return cell;
231
+ return (cell ?? "").padEnd(widths[i] ?? 0);
232
+ }).join(gap)
233
+ );
234
+ }
235
+
236
+ // src/commands/agent.ts
237
+ var spawnCmd = defineCommand({
238
+ meta: { name: "spawn", description: "Spawn an agent from a profile into a group" },
239
+ args: {
240
+ profile: { type: "string", required: true, description: "Profile id" },
241
+ name: { type: "string", description: "Agent name (defaults to profile name)" },
242
+ group: {
243
+ type: "string",
244
+ description: "Group to join (defaults to 'default')"
245
+ },
246
+ model: { type: "string", description: "Override profile default model" },
247
+ reasoning: {
248
+ type: "string",
249
+ description: "Reasoning level: off|minimal|low|medium|high|xhigh (default: medium)"
250
+ }
251
+ },
252
+ async run({ args }) {
253
+ const client = createClient2();
254
+ const body = {
255
+ profileId: args.profile,
256
+ name: args.name,
257
+ model: args.model,
258
+ reasoningLevel: args.reasoning,
259
+ groupId: args.group
260
+ };
261
+ const agent = await client.post("/api/agents", body);
262
+ console.log(`spawned agent ${agent.id} (${agent.name})`);
263
+ console.log(`dir: ${agent.dir}`);
264
+ }
265
+ });
266
+ var editCmd = defineCommand({
267
+ meta: {
268
+ name: "edit",
269
+ description: "Edit agent settings (name, model override, reasoning level)"
270
+ },
271
+ args: {
272
+ id: { type: "positional", required: true, description: "Agent id or prefix" },
273
+ name: { type: "string", description: "Rename the agent" },
274
+ model: { type: "string", description: 'Set model override (use --model "" to clear)' },
275
+ reasoning: {
276
+ type: "string",
277
+ description: "Reasoning level: off|minimal|low|medium|high|xhigh"
278
+ }
279
+ },
280
+ async run({ args }) {
281
+ if (args.name === void 0 && args.model === void 0 && args.reasoning === void 0) {
282
+ console.error("agent edit: specify at least one of --name, --model, or --reasoning");
283
+ process.exit(2);
284
+ }
285
+ const client = createClient2();
286
+ const body = {};
287
+ if (args.name !== void 0) body.name = args.name;
288
+ if (args.model !== void 0) {
289
+ body.modelOverride = args.model === "" ? null : args.model;
290
+ }
291
+ if (args.reasoning !== void 0) body.reasoningLevel = args.reasoning;
292
+ const agent = await client.patch(`/api/agents/${args.id}`, body);
293
+ console.log(`updated agent ${agent.id} (${agent.name})`);
294
+ }
295
+ });
296
+ var listCmd = defineCommand({
297
+ meta: { name: "list", description: "List agents" },
298
+ args: {
299
+ all: { type: "boolean", description: "Include archived agents" },
300
+ long: { type: "boolean", alias: "l", description: "Show profile + full UUID columns" }
301
+ },
302
+ async run({ args }) {
303
+ const client = createClient2();
304
+ const q = args.all ? "?includeArchived=true" : "";
305
+ const list = await client.get(`/api/agents${q}`);
306
+ if (list.length === 0) {
307
+ console.log("(no agents)");
308
+ return;
309
+ }
310
+ const rows = list.map(
311
+ (a) => args.long ? [a.id, a.status, a.name, a.profileId] : (
312
+ // Short UUID prefix — all CLI commands accept 4+ char prefixes now.
313
+ [a.id.slice(0, 8), a.status, a.name]
314
+ )
315
+ );
316
+ for (const line of columnize(rows)) console.log(line);
317
+ }
318
+ });
319
+ var showCmd = defineCommand({
320
+ meta: { name: "show", description: "Show agent details" },
321
+ args: {
322
+ id: { type: "positional", required: true }
323
+ },
324
+ async run({ args }) {
325
+ const client = createClient2();
326
+ const r = await client.get(`/api/agents/${args.id}`);
327
+ console.log(`# ${r.agent.id}`);
328
+ console.log(`name: ${r.agent.name}`);
329
+ console.log(`status: ${r.agent.status}`);
330
+ console.log(`profile: ${r.profile.id}`);
331
+ console.log(`model: ${r.model}`);
332
+ console.log(`dir: ${r.agent.dir}`);
333
+ console.log(`group: ${r.group.id} ${r.group.path}`);
334
+ console.log("skills:");
335
+ if (r.skills.length === 0) {
336
+ console.log(" (none)");
337
+ } else {
338
+ for (const s of r.skills) console.log(` ${s}`);
339
+ }
340
+ }
341
+ });
342
+ var archiveCmd = defineCommand({
343
+ meta: { name: "archive", description: "Archive an agent" },
344
+ args: {
345
+ id: { type: "positional", required: true }
346
+ },
347
+ async run({ args }) {
348
+ const client = createClient2();
349
+ await client.post(`/api/agents/${args.id}/archive`);
350
+ console.log(`archived agent ${args.id}`);
351
+ }
352
+ });
353
+ var unarchiveCmd = defineCommand({
354
+ meta: { name: "unarchive", description: "Restore an archived agent to idle" },
355
+ args: {
356
+ id: { type: "positional", required: true }
357
+ },
358
+ async run({ args }) {
359
+ const client = createClient2();
360
+ await client.post(`/api/agents/${args.id}/unarchive`);
361
+ console.log(`unarchived agent ${args.id}`);
362
+ }
363
+ });
364
+ var deleteCmd = defineCommand({
365
+ meta: { name: "delete", description: "Permanently delete an agent and its data" },
366
+ args: {
367
+ id: { type: "positional", required: true }
368
+ },
369
+ async run({ args }) {
370
+ const client = createClient2();
371
+ await client.del(`/api/agents/${args.id}`);
372
+ console.log(`deleted agent ${args.id}`);
373
+ }
374
+ });
375
+ function printEvent(e, state) {
376
+ switch (e.type) {
377
+ case "assistant_delta":
378
+ process.stdout.write(e.delta);
379
+ state.inDeltaStream = true;
380
+ break;
381
+ case "assistant_message":
382
+ if (state.inDeltaStream) {
383
+ process.stdout.write("\n");
384
+ state.inDeltaStream = false;
385
+ } else {
386
+ console.log(e.text);
387
+ }
388
+ break;
389
+ case "tool_call":
390
+ if (state.inDeltaStream) {
391
+ process.stdout.write("\n");
392
+ state.inDeltaStream = false;
393
+ }
394
+ console.log(` [tool: ${e.name} ${e.arguments}]`);
395
+ break;
396
+ case "tool_result":
397
+ console.log(` [result: ${e.result.split("\n")[0]?.slice(0, 100)}]`);
398
+ break;
399
+ case "tool_error":
400
+ console.log(` [tool error: ${e.name} \u2014 ${e.error}]`);
401
+ break;
402
+ case "error":
403
+ if (state.inDeltaStream) {
404
+ process.stdout.write("\n");
405
+ state.inDeltaStream = false;
406
+ }
407
+ console.log(` [error: ${e.error}]`);
408
+ break;
409
+ }
410
+ }
411
+ async function streamTurn(client, agentId, message) {
412
+ const state = { inDeltaStream: false };
413
+ for await (const frame of client.stream("POST", `/api/agents/${agentId}/chat`, {
414
+ message
415
+ })) {
416
+ if (frame.kind === "event") {
417
+ if (frame.event.type !== "user_message") printEvent(frame.event, state);
418
+ } else if (frame.kind === "fatal") {
419
+ if (state.inDeltaStream) process.stdout.write("\n");
420
+ throw new Error(frame.error);
421
+ }
422
+ }
423
+ }
424
+ var chatCmd = defineCommand({
425
+ meta: { name: "chat", description: "Chat with an agent" },
426
+ args: {
427
+ id: { type: "positional", required: true },
428
+ message: {
429
+ type: "string",
430
+ description: "Send a single message and exit (one-shot mode)"
431
+ }
432
+ },
433
+ async run({ args }) {
434
+ const client = createClient2();
435
+ const resolved = await client.get(`/api/agents/${args.id}`);
436
+ if (args.message) {
437
+ await streamTurn(client, resolved.agent.id, args.message);
438
+ return;
439
+ }
440
+ console.log(`chatting with ${resolved.agent.name} (${resolved.model})`);
441
+ console.log("(type /exit to quit)");
442
+ const rl = createInterface({ input: stdin, output: stdout });
443
+ rl.setPrompt("> ");
444
+ rl.prompt();
445
+ for await (const line of rl) {
446
+ const trimmed = line.trim();
447
+ if (trimmed === "/exit" || trimmed === "/quit") break;
448
+ if (!trimmed) {
449
+ rl.prompt();
450
+ continue;
451
+ }
452
+ try {
453
+ await streamTurn(client, resolved.agent.id, trimmed);
454
+ } catch (err) {
455
+ console.error(`error: ${err.message}`);
456
+ }
457
+ rl.prompt();
458
+ }
459
+ rl.close();
460
+ }
461
+ });
462
+ var chatResetCmd = defineCommand({
463
+ meta: { name: "chat-reset", description: "Reset an agent's chat history to empty" },
464
+ args: {
465
+ id: { type: "positional", required: true },
466
+ force: { type: "boolean", description: "Skip the y/N prompt" }
467
+ },
468
+ async run({ args }) {
469
+ if (!args.force) {
470
+ process.stdout.write(`reset all chat history for ${args.id}? [y/N] `);
471
+ const answer = await new Promise((resolve3) => {
472
+ process.stdin.once("data", (d) => resolve3(String(d).trim().toLowerCase()));
473
+ });
474
+ if (answer !== "y" && answer !== "yes") {
475
+ console.log("aborted");
476
+ return;
477
+ }
478
+ }
479
+ const client = createClient2();
480
+ await client.post(`/api/agents/${args.id}/chat/reset`);
481
+ console.log(`reset chat history for ${args.id}`);
482
+ }
483
+ });
484
+ var chatTrimCmd = defineCommand({
485
+ meta: {
486
+ name: "chat-trim",
487
+ description: "Keep the first N messages of an agent's chat history; drop the rest"
488
+ },
489
+ args: {
490
+ id: { type: "positional", required: true },
491
+ keep: { type: "string", required: true, description: "Number of leading messages to keep" }
492
+ },
493
+ async run({ args }) {
494
+ const n = Number(args.keep);
495
+ if (!Number.isFinite(n) || n < 0 || !Number.isInteger(n)) {
496
+ throw new Error("--keep must be a non-negative integer");
497
+ }
498
+ const client = createClient2();
499
+ const body = { keepCount: n };
500
+ const res = await client.post(
501
+ `/api/agents/${args.id}/chat/truncate`,
502
+ body
503
+ );
504
+ console.log(
505
+ `trimmed: ${res.before} \u2192 ${res.after} messages (${res.before - res.after} dropped)`
506
+ );
507
+ }
508
+ });
509
+ function formatBytes(n) {
510
+ if (n < 1024) return `${n} B`;
511
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KiB`;
512
+ return `${(n / (1024 * 1024)).toFixed(2)} MiB`;
513
+ }
514
+ var chatContextCmd = defineCommand({
515
+ meta: {
516
+ name: "chat-context",
517
+ description: "Break down what consumes the agent's context window"
518
+ },
519
+ args: {
520
+ id: { type: "positional", required: true },
521
+ detail: {
522
+ type: "boolean",
523
+ description: "Include every tool/skill entry instead of the top 30"
524
+ },
525
+ json: { type: "boolean", description: "Emit raw JSON instead of a human report" }
526
+ },
527
+ async run({ args }) {
528
+ const client = createClient2();
529
+ const query = args.detail || args.json ? "?detail=1" : "";
530
+ const ctx = await client.get(`/api/agents/${args.id}/chat/context${query}`);
531
+ if (args.json) {
532
+ console.log(JSON.stringify(ctx, null, 2));
533
+ return;
534
+ }
535
+ const fmt = (chars, tokens) => `${chars.toLocaleString()} chars (~${tokens.toLocaleString()} tok)`;
536
+ console.log(`\u{1F9E0} context for ${ctx.agentId}`);
537
+ console.log(`model: ${ctx.model}`);
538
+ console.log("");
539
+ console.log("## system prompt");
540
+ console.log(` total: ${fmt(ctx.systemPrompt.chars, ctx.systemPrompt.tokens)}`);
541
+ if (ctx.systemPrompt.files.length > 0) {
542
+ console.log(" profile files:");
543
+ for (const f of ctx.systemPrompt.files) {
544
+ console.log(` - ${f.name}: ${fmt(f.chars, f.tokens)}`);
545
+ }
546
+ }
547
+ if (ctx.systemPrompt.skillsListChars > 0) {
548
+ console.log(` skills line: ${ctx.systemPrompt.skillsListChars.toLocaleString()} chars`);
549
+ }
550
+ if (ctx.systemPrompt.groupListChars > 0) {
551
+ console.log(` group block: ${ctx.systemPrompt.groupListChars.toLocaleString()} chars`);
552
+ }
553
+ if (ctx.systemPrompt.userMdChars > 0) {
554
+ console.log(` user_md block: ${ctx.systemPrompt.userMdChars.toLocaleString()} chars`);
555
+ }
556
+ console.log(` memory hint: ${ctx.systemPrompt.memoryHintChars.toLocaleString()} chars`);
557
+ console.log("");
558
+ console.log("## tools");
559
+ console.log(` count: ${ctx.tools.count}`);
560
+ console.log(
561
+ ` schemas (JSON): ${ctx.tools.schemaChars.toLocaleString()} chars (~${estimate(ctx.tools.schemaChars).toLocaleString()} tok)`
562
+ );
563
+ console.log(` list text: ${ctx.tools.listChars.toLocaleString()} chars`);
564
+ if (ctx.tools.entries.length > 0) {
565
+ console.log(" top tools by schema size:");
566
+ for (const t of ctx.tools.entries) {
567
+ const params = t.paramCount != null ? ` (${t.paramCount} params)` : "";
568
+ console.log(` - ${t.name}: ${t.schemaChars.toLocaleString()} chars${params}`);
569
+ }
570
+ }
571
+ console.log("");
572
+ if (ctx.skills.count > 0) {
573
+ console.log("## skills");
574
+ console.log(` count: ${ctx.skills.count}`);
575
+ for (const s of ctx.skills.entries) {
576
+ console.log(` - ${s.name}: ${s.blockChars.toLocaleString()} chars`);
577
+ }
578
+ console.log("");
579
+ }
580
+ console.log("## group");
581
+ console.log(` - ${ctx.group.id} (${ctx.group.name}): ${ctx.group.path}`);
582
+ if (ctx.group.userMdChars > 0) {
583
+ console.log(` user_md: ${ctx.group.userMdChars.toLocaleString()} chars`);
584
+ }
585
+ console.log("");
586
+ console.log("## history");
587
+ console.log(` messages: ${ctx.history.messageEntries}`);
588
+ console.log(` compactions: ${ctx.history.compactionEntries}`);
589
+ console.log(` total: ${fmt(ctx.history.chars, ctx.history.tokensEstimate)}`);
590
+ console.log(` bytes: ${formatBytes(ctx.history.bytes)}`);
591
+ console.log("");
592
+ console.log(`TOTAL: ${fmt(ctx.totals.chars, ctx.totals.tokens)}`);
593
+ }
594
+ });
595
+ function estimate(chars) {
596
+ return Math.ceil(Math.max(0, chars) / 4);
597
+ }
598
+ var chatCompactCmd = defineCommand({
599
+ meta: {
600
+ name: "chat-compact",
601
+ description: "Summarize the head of an agent's chat log, preserving the tail verbatim"
602
+ },
603
+ args: {
604
+ id: { type: "positional", required: true },
605
+ "keep-tail": {
606
+ type: "string",
607
+ description: "Message entries to keep verbatim after the summary (default 10)"
608
+ },
609
+ instructions: {
610
+ type: "string",
611
+ description: "Optional extra guidance prepended to the summarizer prompt"
612
+ },
613
+ force: { type: "boolean", description: "Skip the y/N prompt" }
614
+ },
615
+ async run({ args }) {
616
+ if (!args.force) {
617
+ process.stdout.write(
618
+ `compact chat history for ${args.id}? head turns become a summary; tail is preserved. [y/N] `
619
+ );
620
+ const answer = await new Promise((resolve3) => {
621
+ process.stdin.once("data", (d) => resolve3(String(d).trim().toLowerCase()));
622
+ });
623
+ if (answer !== "y" && answer !== "yes") {
624
+ console.log("aborted");
625
+ return;
626
+ }
627
+ }
628
+ const keepTailNum = args["keep-tail"] ? Number(args["keep-tail"]) : void 0;
629
+ if (keepTailNum !== void 0 && (!Number.isFinite(keepTailNum) || keepTailNum < 0)) {
630
+ console.error("--keep-tail must be a non-negative integer");
631
+ process.exitCode = 1;
632
+ return;
633
+ }
634
+ const body = {};
635
+ if (keepTailNum !== void 0) body.keepTail = Math.floor(keepTailNum);
636
+ if (args.instructions) body.customInstructions = args.instructions;
637
+ const client = createClient2();
638
+ const res = await client.post(`/api/agents/${args.id}/chat/compact`, body);
639
+ console.log(
640
+ `compacted: ${res.before} \u2192 ${res.after} entries (${res.summarized} summarized, ${res.keptTail} tail kept verbatim)`
641
+ );
642
+ console.log(
643
+ `tokens: ~${res.tokensBefore.toLocaleString()} \u2192 ~${res.tokensAfter.toLocaleString()}`
644
+ );
645
+ console.log("");
646
+ console.log("summary:");
647
+ console.log(res.summary);
648
+ }
649
+ });
650
+ var skillAddCmd = defineCommand({
651
+ meta: { name: "add", description: "Attach a skill to an agent" },
652
+ args: {
653
+ agent: { type: "positional", required: true },
654
+ skill: { type: "positional", required: true }
655
+ },
656
+ async run({ args }) {
657
+ const client = createClient2();
658
+ const body = { skill: args.skill };
659
+ await client.post(`/api/agents/${args.agent}/skills`, body);
660
+ console.log(`attached skill ${args.skill} to ${args.agent}`);
661
+ }
662
+ });
663
+ var skillRmCmd = defineCommand({
664
+ meta: { name: "rm", description: "Detach a skill from an agent" },
665
+ args: {
666
+ agent: { type: "positional", required: true },
667
+ skill: { type: "positional", required: true }
668
+ },
669
+ async run({ args }) {
670
+ const client = createClient2();
671
+ await client.del(`/api/agents/${args.agent}/skills/${encodeURIComponent(args.skill)}`);
672
+ console.log(`detached skill ${args.skill} from ${args.agent}`);
673
+ }
674
+ });
675
+ var skillCmd = defineCommand({
676
+ meta: { name: "skill", description: "Attach/detach skills on an agent" },
677
+ subCommands: {
678
+ add: skillAddCmd,
679
+ rm: skillRmCmd
680
+ }
681
+ });
682
+ var moveCmd = defineCommand({
683
+ meta: { name: "move", description: "Move an agent to a different group" },
684
+ args: {
685
+ agent: { type: "positional", required: true },
686
+ group: { type: "positional", required: true }
687
+ },
688
+ async run({ args }) {
689
+ const client = createClient2();
690
+ const body = { groupId: args.group };
691
+ await client.patch(`/api/agents/${args.agent}/group`, body);
692
+ console.log(`moved ${args.agent} to group ${args.group}`);
693
+ }
694
+ });
695
+ var sessionHeadCmd = defineCommand({
696
+ meta: {
697
+ name: "session-head",
698
+ description: "Print the agent's current session file head (for stale-tab checks)"
699
+ },
700
+ args: {
701
+ id: { type: "positional", required: true },
702
+ json: { type: "boolean", description: "Emit raw JSON instead of a human line" }
703
+ },
704
+ async run({ args }) {
705
+ const client = createClient2();
706
+ const head = await client.get(`/api/agents/${args.id}/sessions/head`);
707
+ if (args.json) {
708
+ console.log(JSON.stringify(head));
709
+ return;
710
+ }
711
+ console.log(head.file ? `${head.file} (${head.size} bytes)` : "(no session yet)");
712
+ }
713
+ });
714
+ var cancelCmd = defineCommand({
715
+ meta: { name: "cancel", description: "Abort the agent's currently-running turn" },
716
+ args: {
717
+ id: { type: "positional", required: true }
718
+ },
719
+ async run({ args }) {
720
+ const client = createClient2();
721
+ await client.post(`/api/agents/${args.id}/cancel`);
722
+ console.log(`cancelled active turn for ${args.id}`);
723
+ }
724
+ });
725
+ var agentCommand = defineCommand({
726
+ meta: { name: "agent", description: "Manage agent instances" },
727
+ subCommands: {
728
+ spawn: spawnCmd,
729
+ list: listCmd,
730
+ show: showCmd,
731
+ edit: editCmd,
732
+ archive: archiveCmd,
733
+ unarchive: unarchiveCmd,
734
+ delete: deleteCmd,
735
+ chat: chatCmd,
736
+ "chat-reset": chatResetCmd,
737
+ "chat-trim": chatTrimCmd,
738
+ "chat-context": chatContextCmd,
739
+ "chat-compact": chatCompactCmd,
740
+ cancel: cancelCmd,
741
+ skill: skillCmd,
742
+ move: moveCmd,
743
+ "session-head": sessionHeadCmd
744
+ }
745
+ });
746
+
747
+ // src/commands/auth.ts
748
+ import { loginOpenAICodex } from "@earendil-works/pi-ai/oauth";
749
+ import { defineCommand as defineCommand2 } from "citty";
750
+ function formatExpiry(ms) {
751
+ if (!ms) return "(unknown)";
752
+ const d = new Date(ms);
753
+ return d.toISOString().replace(/\.\d+Z$/, "Z");
754
+ }
755
+ var openaiLoginCmd = defineCommand2({
756
+ meta: {
757
+ name: "login",
758
+ description: "Connect your ChatGPT account via OAuth (browser sign-in)"
759
+ },
760
+ async run() {
761
+ const client = createClient2();
762
+ console.log("opening your browser for OpenAI sign-in...");
763
+ console.log("(if it doesn't open automatically, paste the URL shown below)");
764
+ const creds = await loginOpenAICodex({
765
+ onAuth: ({ url }) => {
766
+ console.log("");
767
+ console.log(` \u2192 ${url}`);
768
+ console.log("");
769
+ },
770
+ onPrompt: async (prompt) => {
771
+ process.stdout.write(`${prompt.message}: `);
772
+ return new Promise((resolve3) => {
773
+ process.stdin.once("data", (d) => resolve3(String(d).trim()));
774
+ });
775
+ },
776
+ onProgress: (msg) => {
777
+ console.log(` ${msg}`);
778
+ }
779
+ });
780
+ const status = await client.put("/api/auth/openai", {
781
+ refresh: creds.refresh,
782
+ access: creds.access,
783
+ expires: creds.expires
784
+ });
785
+ console.log("");
786
+ console.log("connected \u2713");
787
+ if (status.accountId) console.log(`account: ${status.accountId}`);
788
+ console.log(`access token expires: ${formatExpiry(status.expiresAt)}`);
789
+ console.log("");
790
+ console.log(`enable the 'openai-codex' provider on /config and add at least one model`);
791
+ console.log("(e.g. gpt-5.1-codex-max, gpt-5.2, gpt-5.3-codex) to start using it.");
792
+ }
793
+ });
794
+ var openaiLogoutCmd = defineCommand2({
795
+ meta: {
796
+ name: "logout",
797
+ description: "Forget the stored ChatGPT OAuth credentials"
798
+ },
799
+ async run() {
800
+ const client = createClient2();
801
+ await client.del("/api/auth/openai");
802
+ console.log("disconnected ChatGPT OAuth credentials");
803
+ }
804
+ });
805
+ var openaiStatusCmd = defineCommand2({
806
+ meta: {
807
+ name: "status",
808
+ description: "Show ChatGPT OAuth connection status"
809
+ },
810
+ async run() {
811
+ const client = createClient2();
812
+ const status = await client.get("/api/auth/openai");
813
+ if (!status.connected) {
814
+ console.log("not connected \u2014 run `bazilion auth openai login`");
815
+ return;
816
+ }
817
+ console.log("connected \u2713");
818
+ if (status.accountId) console.log(`account: ${status.accountId}`);
819
+ console.log(`access token expires: ${formatExpiry(status.expiresAt)}`);
820
+ }
821
+ });
822
+ var openaiCmd = defineCommand2({
823
+ meta: {
824
+ name: "openai",
825
+ description: "Manage ChatGPT (OAuth) authentication"
826
+ },
827
+ subCommands: {
828
+ login: openaiLoginCmd,
829
+ logout: openaiLogoutCmd,
830
+ status: openaiStatusCmd
831
+ }
832
+ });
833
+ var authCommand = defineCommand2({
834
+ meta: {
835
+ name: "auth",
836
+ description: "OAuth-based provider authentication (ChatGPT account, etc.)"
837
+ },
838
+ subCommands: {
839
+ openai: openaiCmd
840
+ }
841
+ });
842
+
843
+ // src/commands/backup.ts
844
+ import { spawn } from "child_process";
845
+ import { createWriteStream, existsSync as existsSync2, mkdirSync, readdirSync, rmSync } from "fs";
846
+ import { resolve } from "path";
847
+ import { Readable } from "stream";
848
+ import { pipeline } from "stream/promises";
849
+ import { defineCommand as defineCommand3 } from "citty";
850
+ var createCmd = defineCommand3({
851
+ meta: { name: "create", description: "Download a tar.gz backup of ~/.bazilion from the server" },
852
+ args: {
853
+ output: {
854
+ type: "positional",
855
+ required: false,
856
+ description: "Output file path (default: ./bazilion-backup-YYYY-MM-DD.tar.gz)"
857
+ }
858
+ },
859
+ async run({ args }) {
860
+ const cfg = loadClientConfig();
861
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
862
+ const outAbs = resolve(args.output ?? `bazilion-backup-${date}.tar.gz`);
863
+ console.log(`downloading backup \u2192 ${outAbs}`);
864
+ const res = await fetch(`${cfg.serverUrl}/api/backup`, {
865
+ headers: { authorization: `Bearer ${cfg.token}`, origin: cfg.serverUrl }
866
+ });
867
+ if (!res.ok || !res.body) {
868
+ let err = res.statusText;
869
+ try {
870
+ const body = await res.json();
871
+ err = body.error ?? err;
872
+ } catch {
873
+ }
874
+ throw new Error(`backup failed: ${err}`);
875
+ }
876
+ await pipeline(Readable.fromWeb(res.body), createWriteStream(outAbs));
877
+ console.log("done");
878
+ }
879
+ });
880
+ async function probeServerRunning(port) {
881
+ try {
882
+ const ctrl = new AbortController();
883
+ const timer = setTimeout(() => ctrl.abort(), 500);
884
+ const res = await fetch(`http://127.0.0.1:${port}/login`, { signal: ctrl.signal });
885
+ clearTimeout(timer);
886
+ return res.status >= 200 && res.status < 600;
887
+ } catch {
888
+ return false;
889
+ }
890
+ }
891
+ var restoreCmd = defineCommand3({
892
+ meta: {
893
+ name: "restore",
894
+ description: "Extract a backup tar.gz into ~/.bazilion (offline; server must be stopped)"
895
+ },
896
+ args: {
897
+ file: {
898
+ type: "positional",
899
+ required: true,
900
+ description: "Path to tar.gz backup file"
901
+ },
902
+ home: { type: "string", description: "Override BAZILION_HOME" },
903
+ force: {
904
+ type: "boolean",
905
+ description: "Overwrite existing non-empty home (destroys existing data)"
906
+ }
907
+ },
908
+ async run({ args }) {
909
+ const file = resolve(args.file);
910
+ if (!existsSync2(file)) throw new Error(`backup file not found: ${file}`);
911
+ const paths = resolveCliPaths(args.home);
912
+ const targetHome = paths.home;
913
+ const defaultHome = !args.home && !process.env.BAZILION_HOME;
914
+ if (defaultHome && !args.force && await probeServerRunning(4321)) {
915
+ throw new Error(
916
+ "bazilion server appears to be running on :4321 \u2014 stop it first (DB corruption risk), or pass --force to override."
917
+ );
918
+ }
919
+ if (existsSync2(targetHome)) {
920
+ const entries = readdirSync(targetHome);
921
+ if (entries.length > 0) {
922
+ if (!args.force) {
923
+ throw new Error(
924
+ `${targetHome} is not empty. Pass --force to overwrite (destroys existing data).`
925
+ );
926
+ }
927
+ rmSync(targetHome, { recursive: true, force: true });
928
+ }
929
+ }
930
+ mkdirSync(targetHome, { recursive: true });
931
+ console.log(`extracting ${file} \u2192 ${targetHome}`);
932
+ await new Promise((res, rej) => {
933
+ const proc = spawn("tar", ["-xzf", file, "-C", targetHome], { stdio: "inherit" });
934
+ proc.on("error", rej);
935
+ proc.on("exit", (code) => {
936
+ if (code === 0) res();
937
+ else rej(new Error(`tar exited with code ${code}`));
938
+ });
939
+ });
940
+ console.log(`restored to ${targetHome}`);
941
+ console.log("start the server with: bazilion serve (migrations apply automatically)");
942
+ }
943
+ });
944
+ var backupCommand = defineCommand3({
945
+ meta: { name: "backup", description: "Create or restore a ~/.bazilion tar.gz backup" },
946
+ subCommands: {
947
+ create: createCmd,
948
+ restore: restoreCmd
949
+ }
950
+ // `bazilion backup` with no positional falls through to citty's subcommand
951
+ // prompt ("No command specified"). The previous default (auto-download to
952
+ // cwd) double-fired when a subcommand was used because citty runs parent's
953
+ // `run` after the subcommand completes — explicit `create` / `restore` is
954
+ // the supported form now.
955
+ });
956
+
957
+ // src/commands/completion.ts
958
+ import { defineCommand as defineCommand4 } from "citty";
959
+ async function walk(cmd, path, out) {
960
+ const subsRaw = cmd.subCommands ?? {};
961
+ const subNames = Object.keys(subsRaw);
962
+ const flags = flagsOf(cmd.args ?? {});
963
+ out.push({ path, subs: subNames, flags });
964
+ for (const name of subNames) {
965
+ const v = subsRaw[name];
966
+ const sub = await Promise.resolve(v);
967
+ await walk(sub, [...path, name], out);
968
+ }
969
+ }
970
+ function flagsOf(args) {
971
+ const out = [];
972
+ for (const [name, def] of Object.entries(args)) {
973
+ if (def.type === "positional") continue;
974
+ out.push(`--${name}`);
975
+ const aliases = Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : [];
976
+ for (const a of aliases) out.push(a.length === 1 ? `-${a}` : `--${a}`);
977
+ }
978
+ return out;
979
+ }
980
+ function bashScript(flat) {
981
+ const cases = flat.map((f) => {
982
+ const key = f.path.length === 0 ? '""' : JSON.stringify(f.path.join(" "));
983
+ const words = [...f.subs, ...f.flags].join(" ");
984
+ return ` ${key})
985
+ COMPREPLY=($(compgen -W ${JSON.stringify(words)} -- "$cur"))
986
+ ;;`;
987
+ }).join("\n");
988
+ return `# bazilion bash completion. Install with:
989
+ # source <(bazilion completion bash)
990
+ # or append to ~/.bashrc / ~/.bash_profile.
991
+ _bazilion_completion() {
992
+ local cur prev cword
993
+ COMPREPLY=()
994
+ cur="\${COMP_WORDS[COMP_CWORD]}"
995
+ cword=$COMP_CWORD
996
+ # Build the current subcommand path by walking words[1..cword-1], skipping
997
+ # flags and their values. We don't try to parse flag arity \u2014 treating every
998
+ # flag as standalone is a good-enough approximation for completion.
999
+ local cmd=""
1000
+ local i
1001
+ for ((i=1; i<cword; i++)); do
1002
+ local w="\${COMP_WORDS[i]}"
1003
+ [[ "$w" == -* ]] && continue
1004
+ cmd+="\${cmd:+ }$w"
1005
+ done
1006
+ case "$cmd" in
1007
+ ${cases}
1008
+ *)
1009
+ COMPREPLY=()
1010
+ ;;
1011
+ esac
1012
+ }
1013
+ complete -F _bazilion_completion bazilion
1014
+ `;
1015
+ }
1016
+ function zshScript(flat) {
1017
+ const bash = bashScript(flat);
1018
+ return `# bazilion zsh completion. Install with:
1019
+ # source <(bazilion completion zsh)
1020
+ # If you don't already have bashcompinit loaded, this does it for you.
1021
+ autoload -U +X compinit && compinit
1022
+ autoload -U +X bashcompinit && bashcompinit
1023
+ ${bash}`;
1024
+ }
1025
+ function fishScript(flat) {
1026
+ const lines = [
1027
+ "# bazilion fish completion. Install with:",
1028
+ "# bazilion completion fish | source",
1029
+ "# or write it to ~/.config/fish/completions/bazilion.fish",
1030
+ "",
1031
+ "complete -c bazilion -f"
1032
+ ];
1033
+ for (const f of flat) {
1034
+ if (f.path.length === 0) {
1035
+ for (const s of f.subs) lines.push(`complete -c bazilion -n '__fish_use_subcommand' -a ${s}`);
1036
+ for (const fl of f.flags) {
1037
+ const long = fl.startsWith("--") ? fl.slice(2) : "";
1038
+ const short = !fl.startsWith("--") ? fl.slice(1) : "";
1039
+ const parts = ["complete -c bazilion -n '__fish_use_subcommand'"];
1040
+ if (short) parts.push(`-s ${short}`);
1041
+ if (long) parts.push(`-l ${long}`);
1042
+ lines.push(parts.join(" "));
1043
+ }
1044
+ } else {
1045
+ const guard = f.path.map((p) => `__fish_seen_subcommand_from ${p}`).join("; and ");
1046
+ for (const s of f.subs) {
1047
+ lines.push(`complete -c bazilion -n '${guard}' -a ${s}`);
1048
+ }
1049
+ for (const fl of f.flags) {
1050
+ const long = fl.startsWith("--") ? fl.slice(2) : "";
1051
+ const short = !fl.startsWith("--") ? fl.slice(1) : "";
1052
+ const parts = [`complete -c bazilion -n '${guard}'`];
1053
+ if (short) parts.push(`-s ${short}`);
1054
+ if (long) parts.push(`-l ${long}`);
1055
+ lines.push(parts.join(" "));
1056
+ }
1057
+ }
1058
+ }
1059
+ return `${lines.join("\n")}
1060
+ `;
1061
+ }
1062
+ function completionCommand(main2) {
1063
+ return defineCommand4({
1064
+ meta: {
1065
+ name: "completion",
1066
+ description: "Print a shell completion script (bash, zsh, or fish)"
1067
+ },
1068
+ args: {
1069
+ shell: {
1070
+ type: "positional",
1071
+ required: true,
1072
+ description: "bash | zsh | fish"
1073
+ }
1074
+ },
1075
+ async run({ args }) {
1076
+ const flat = [];
1077
+ await walk(main2, [], flat);
1078
+ const shell = String(args.shell).toLowerCase();
1079
+ if (shell === "bash") console.log(bashScript(flat));
1080
+ else if (shell === "zsh") console.log(zshScript(flat));
1081
+ else if (shell === "fish") console.log(fishScript(flat));
1082
+ else throw new Error(`unsupported shell: ${args.shell} (want bash | zsh | fish)`);
1083
+ }
1084
+ });
1085
+ }
1086
+
1087
+ // src/commands/config.ts
1088
+ import { defineCommand as defineCommand5 } from "citty";
1089
+ function displayValue(f) {
1090
+ if (!f.set) return "(unset)";
1091
+ if (f.kind === "secret") return f.preview ?? "(set)";
1092
+ return f.value ?? "(set)";
1093
+ }
1094
+ var listCmd2 = defineCommand5({
1095
+ meta: {
1096
+ name: "list",
1097
+ description: "List every configurable field (credentials + URLs) across all services"
1098
+ },
1099
+ async run() {
1100
+ const client = createClient2();
1101
+ const { providers } = await client.get("/api/config/providers");
1102
+ const { services } = await client.get("/api/config/services");
1103
+ const all = [...providers, ...services];
1104
+ const rows = [];
1105
+ for (const svc of all) {
1106
+ for (const f of svc.fields) {
1107
+ rows.push([svc.id, f.envVar, f.kind, displayValue(f)]);
1108
+ }
1109
+ }
1110
+ if (rows.length === 0) {
1111
+ console.log("(no fields registered)");
1112
+ return;
1113
+ }
1114
+ for (const line of columnize(rows)) console.log(line);
1115
+ }
1116
+ });
1117
+ var setCmd = defineCommand5({
1118
+ meta: {
1119
+ name: "set",
1120
+ description: "Set a configurable field (auto-routes to secrets or plaintext store)"
1121
+ },
1122
+ args: {
1123
+ envVar: {
1124
+ type: "positional",
1125
+ required: true,
1126
+ description: "Env var name (e.g. ANTHROPIC_API_KEY, LMSTUDIO_URL)"
1127
+ },
1128
+ value: {
1129
+ type: "positional",
1130
+ required: true,
1131
+ description: "New value (empty string clears the field)"
1132
+ }
1133
+ },
1134
+ async run({ args }) {
1135
+ const client = createClient2();
1136
+ const body = { value: args.value };
1137
+ const state = await client.put(
1138
+ `/api/config/fields/${encodeURIComponent(args.envVar)}`,
1139
+ body
1140
+ );
1141
+ console.log(`${state.envVar} (${state.kind}): ${displayValue(state)}`);
1142
+ }
1143
+ });
1144
+ var rmCmd = defineCommand5({
1145
+ meta: { name: "rm", description: "Remove a configurable field value" },
1146
+ args: {
1147
+ envVar: { type: "positional", required: true, description: "Env var name to clear" }
1148
+ },
1149
+ async run({ args }) {
1150
+ const client = createClient2();
1151
+ await client.del(`/api/config/fields/${encodeURIComponent(args.envVar)}`);
1152
+ console.log(`removed ${args.envVar}`);
1153
+ }
1154
+ });
1155
+ var configCommand = defineCommand5({
1156
+ meta: {
1157
+ name: "config",
1158
+ description: "Manage service configuration \u2014 credentials (encrypted) and URLs/IDs (plaintext), unified under one CLI"
1159
+ },
1160
+ subCommands: {
1161
+ list: listCmd2,
1162
+ set: setCmd,
1163
+ rm: rmCmd
1164
+ }
1165
+ });
1166
+
1167
+ // src/commands/doctor.ts
1168
+ import { defineCommand as defineCommand6 } from "citty";
1169
+ var doctorCommand = defineCommand6({
1170
+ meta: { name: "doctor", description: "Diagnose your bazilion install" },
1171
+ async run() {
1172
+ const client = createClient2();
1173
+ const r = await client.get("/api/health");
1174
+ function check(label, condition, hint) {
1175
+ const mark = condition ? "\u2713" : "\u2717";
1176
+ const tail = !condition && hint ? ` \u2014 ${hint}` : "";
1177
+ console.log(` ${mark} ${label}${tail}`);
1178
+ }
1179
+ console.log(`bazilion home: ${r.home}`);
1180
+ console.log();
1181
+ console.log("paths");
1182
+ check("home dir exists", r.paths.home);
1183
+ check("database exists", r.paths.db, "run: bazilion serve (auto-bootstraps on first run)");
1184
+ check("auth.json exists", r.paths.auth, "run: bazilion serve (auto-bootstraps on first run)");
1185
+ check("profiles dir exists", r.paths.profiles);
1186
+ check("agents dir exists", r.paths.agents);
1187
+ check("skills dir exists", r.paths.skills);
1188
+ if (r.database) {
1189
+ console.log();
1190
+ console.log("database");
1191
+ if (r.database.ok) {
1192
+ console.log(` ${r.database.profiles} profile(s)`);
1193
+ console.log(
1194
+ ` ${r.database.activeAgents} active agent(s) (${r.database.totalAgents} total)`
1195
+ );
1196
+ console.log(` ${r.database.groups} group(s)`);
1197
+ } else {
1198
+ check("open database", false, r.database.error);
1199
+ }
1200
+ }
1201
+ console.log();
1202
+ console.log("skills library");
1203
+ console.log(` ${r.skills.installed} skill(s) installed`);
1204
+ if (r.skills.parseErrors > 0) {
1205
+ check("all skills parse", false, `${r.skills.parseErrors} skill(s) have errors`);
1206
+ }
1207
+ console.log();
1208
+ console.log("providers (at least one needed for chat)");
1209
+ if (r.providers.configured.length === 0) {
1210
+ console.log(" - no cloud providers configured");
1211
+ console.log(" (set e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY)");
1212
+ } else {
1213
+ for (const name of r.providers.configured) {
1214
+ console.log(` \u2713 ${name}`);
1215
+ }
1216
+ }
1217
+ console.log(
1218
+ ` \u2713 lmstudio: ${r.providers.lmstudio.baseURL}${r.providers.lmstudio.hasKey ? " (api key set)" : ""}`
1219
+ );
1220
+ console.log(` \u2713 ollama: ${r.providers.ollama.baseURL}`);
1221
+ console.log();
1222
+ console.log("web search (at least one needed for web_search tool)");
1223
+ if (r.webSearch.bravePreview) {
1224
+ console.log(` \u2713 Brave Search (BRAVE_API_KEY set, ${r.webSearch.bravePreview})`);
1225
+ } else {
1226
+ console.log(" - Brave Search (set BRAVE_API_KEY \u2014 free at https://brave.com/search/api/)");
1227
+ }
1228
+ if (r.webSearch.searxngUrl) {
1229
+ console.log(` \u2713 SearXNG: ${r.webSearch.searxngUrl}`);
1230
+ } else {
1231
+ console.log(" - SearXNG (set SEARXNG_URL if you self-host one)");
1232
+ }
1233
+ if (!r.webSearch.bravePreview && !r.webSearch.searxngUrl) {
1234
+ console.log(" \u26A0 no search backend \u2014 web_search will error until one is configured");
1235
+ }
1236
+ console.log();
1237
+ console.log("openclaw integration");
1238
+ if (r.openclaw.exists) {
1239
+ console.log(` \u2713 ${r.openclaw.path} found`);
1240
+ console.log(" try: bazilion skill import --from openclaw");
1241
+ } else {
1242
+ console.log(` - ${r.openclaw.path} not found (fine if you don't use OpenClaw)`);
1243
+ }
1244
+ console.log();
1245
+ console.log("background jobs");
1246
+ console.log(
1247
+ ` ${r.scheduler.enabled ? "\u2713" : "-"} scheduler${r.scheduler.enabled ? ` (tick ${r.scheduler.tickMs}ms)` : " (BAZILION_SCHEDULER=off)"}`
1248
+ );
1249
+ console.log();
1250
+ console.log("operational counts");
1251
+ console.log(` ${r.triggers.active} active trigger(s), ${r.triggers.disabled} disabled`);
1252
+ console.log(` ${r.tokens.active} active web token(s)`);
1253
+ const anyCloudProvider = r.providers.configured.length > 0;
1254
+ const hasProfiles = (r.database?.ok ? r.database.profiles : 0) > 0;
1255
+ const hasAgents = (r.database?.ok ? r.database.totalAgents : 0) > 0;
1256
+ console.log();
1257
+ if (!r.ok) {
1258
+ console.log("issues found \u2717");
1259
+ process.exit(1);
1260
+ }
1261
+ if (!hasProfiles || !hasAgents) {
1262
+ console.log("install is healthy, but not yet ready to run \u26A0");
1263
+ const todo = [];
1264
+ if (!anyCloudProvider) {
1265
+ todo.push(" - set a cloud api key (ANTHROPIC_API_KEY / OPENAI_API_KEY / GEMINI_API_KEY)");
1266
+ todo.push(" or make sure LMStudio / Ollama is running locally");
1267
+ }
1268
+ if (!hasProfiles) todo.push(" - create a profile: bazilion profile create <id> --model \u2026");
1269
+ if (!hasAgents) todo.push(" - spawn an agent: bazilion agent spawn --profile <id>");
1270
+ for (const line of todo) console.log(line);
1271
+ } else {
1272
+ console.log("all good \u2713");
1273
+ }
1274
+ }
1275
+ });
1276
+
1277
+ // src/commands/group.ts
1278
+ import { readFileSync as readFileSync2 } from "fs";
1279
+ import { stdin as stdin2 } from "process";
1280
+ import { defineCommand as defineCommand7 } from "citty";
1281
+ var addCmd = defineCommand7({
1282
+ meta: {
1283
+ name: "add",
1284
+ description: "Register a group at ~/.bazilion/groups/<slug>/ (use --link to point at an existing tree)"
1285
+ },
1286
+ args: {
1287
+ id: { type: "positional", required: true, description: "Group slug" },
1288
+ name: { type: "string", description: "Display name (defaults to slug)" },
1289
+ link: {
1290
+ type: "string",
1291
+ description: "Absolute path of an existing directory; the group slot becomes a symlink to it"
1292
+ }
1293
+ },
1294
+ async run({ args }) {
1295
+ const client = createClient2();
1296
+ const body = {
1297
+ id: args.id,
1298
+ ...args.name ? { name: args.name } : {},
1299
+ ...args.link ? { link: args.link } : {}
1300
+ };
1301
+ const g = await client.post("/api/groups", body);
1302
+ console.log(`registered group ${g.id} at ${g.path}`);
1303
+ }
1304
+ });
1305
+ var listCmd3 = defineCommand7({
1306
+ meta: { name: "list", description: "List groups" },
1307
+ async run() {
1308
+ const client = createClient2();
1309
+ const list = await client.get("/api/groups");
1310
+ if (list.length === 0) {
1311
+ console.log("(no groups)");
1312
+ return;
1313
+ }
1314
+ const rows = list.map((g) => [g.id, g.path]);
1315
+ for (const line of columnize(rows)) console.log(line);
1316
+ }
1317
+ });
1318
+ var rmCmd2 = defineCommand7({
1319
+ meta: { name: "rm", description: "Remove a group registration" },
1320
+ args: {
1321
+ id: { type: "positional", required: true }
1322
+ },
1323
+ async run({ args }) {
1324
+ const client = createClient2();
1325
+ await client.del(`/api/groups/${args.id}`);
1326
+ console.log(`removed group ${args.id}`);
1327
+ }
1328
+ });
1329
+ async function readStdin() {
1330
+ const chunks = [];
1331
+ for await (const chunk of stdin2) chunks.push(chunk);
1332
+ return Buffer.concat(chunks).toString("utf8");
1333
+ }
1334
+ var userMdShowCmd = defineCommand7({
1335
+ meta: { name: "show", description: "Print the group's USER.md" },
1336
+ args: { id: { type: "positional", required: true } },
1337
+ async run({ args }) {
1338
+ const client = createClient2();
1339
+ const g = await client.get(`/api/groups/${args.id}`);
1340
+ process.stdout.write(g.userMd);
1341
+ if (g.userMd && !g.userMd.endsWith("\n")) process.stdout.write("\n");
1342
+ }
1343
+ });
1344
+ var userMdSetCmd = defineCommand7({
1345
+ meta: {
1346
+ name: "set",
1347
+ description: "Replace the group's USER.md (from --file, --from-stdin, or inline text)"
1348
+ },
1349
+ args: {
1350
+ id: { type: "positional", required: true },
1351
+ file: { type: "string", description: "Read content from a file path" },
1352
+ "from-stdin": { type: "boolean", description: "Read content from stdin" },
1353
+ text: { type: "string", description: "Inline content" }
1354
+ },
1355
+ async run({ args }) {
1356
+ let content;
1357
+ if (args["from-stdin"]) content = await readStdin();
1358
+ else if (args.file) content = readFileSync2(args.file, "utf8");
1359
+ else if (args.text !== void 0) content = args.text;
1360
+ else {
1361
+ console.error("group user-md set: provide --file, --from-stdin, or --text");
1362
+ process.exit(2);
1363
+ }
1364
+ const client = createClient2();
1365
+ const body = { userMd: content };
1366
+ await client.put(`/api/groups/${args.id}/user-md`, body);
1367
+ console.log(`updated USER.md for group ${args.id} (${content.length} bytes)`);
1368
+ }
1369
+ });
1370
+ var userMdClearCmd = defineCommand7({
1371
+ meta: { name: "clear", description: "Clear the group's USER.md to empty" },
1372
+ args: { id: { type: "positional", required: true } },
1373
+ async run({ args }) {
1374
+ const client = createClient2();
1375
+ const body = { userMd: "" };
1376
+ await client.put(`/api/groups/${args.id}/user-md`, body);
1377
+ console.log(`cleared USER.md for group ${args.id}`);
1378
+ }
1379
+ });
1380
+ var userMdCmd = defineCommand7({
1381
+ meta: { name: "user-md", description: "View or edit a group's USER.md" },
1382
+ subCommands: {
1383
+ show: userMdShowCmd,
1384
+ set: userMdSetCmd,
1385
+ clear: userMdClearCmd
1386
+ }
1387
+ });
1388
+ var groupCommand = defineCommand7({
1389
+ meta: { name: "group", description: "Manage groups (collaboration contexts)" },
1390
+ subCommands: {
1391
+ add: addCmd,
1392
+ list: listCmd3,
1393
+ rm: rmCmd2,
1394
+ "user-md": userMdCmd
1395
+ }
1396
+ });
1397
+
1398
+ // src/commands/inbox.ts
1399
+ import { defineCommand as defineCommand8 } from "citty";
1400
+ function decodeText(payload) {
1401
+ try {
1402
+ const obj = JSON.parse(payload);
1403
+ if (typeof obj.text === "string") return obj.text;
1404
+ } catch {
1405
+ }
1406
+ return payload;
1407
+ }
1408
+ function messageRow(m) {
1409
+ const when = new Date(m.createdAt).toISOString();
1410
+ const state = m.readAt ? "read" : "NEW";
1411
+ const text = decodeText(m.payload);
1412
+ const preview = text.length > 60 ? `${text.slice(0, 60)}\u2026` : text;
1413
+ return [m.id, state, when, `from:${m.fromAgentId.slice(0, 8)}`, `"${preview}"`];
1414
+ }
1415
+ var listCmd4 = defineCommand8({
1416
+ meta: { name: "list", description: "List messages in an agent inbox" },
1417
+ args: {
1418
+ agent: { type: "positional", required: true, description: "Recipient agent id" },
1419
+ unread: { type: "boolean", description: "Only show unread messages" }
1420
+ },
1421
+ async run({ args }) {
1422
+ const client = createClient2();
1423
+ const qs = args.unread ? "?unread=1" : "";
1424
+ const { messages } = await client.get(
1425
+ `/api/agents/${args.agent}/messages${qs}`
1426
+ );
1427
+ if (messages.length === 0) {
1428
+ console.log(args.unread ? "(no unread messages)" : "(inbox empty)");
1429
+ return;
1430
+ }
1431
+ for (const line of columnize(messages.map(messageRow))) console.log(line);
1432
+ }
1433
+ });
1434
+ var showCmd2 = defineCommand8({
1435
+ meta: { name: "show", description: "Show a single message in full" },
1436
+ args: {
1437
+ id: { type: "positional", required: true, description: "Message id" }
1438
+ },
1439
+ async run({ args }) {
1440
+ const client = createClient2();
1441
+ const m = await client.get(`/api/messages/${args.id}`);
1442
+ const when = new Date(m.createdAt).toISOString();
1443
+ const read = m.readAt ? new Date(m.readAt).toISOString() : "(unread)";
1444
+ console.log(`id: ${m.id}`);
1445
+ console.log(`from: ${m.fromAgentId}`);
1446
+ console.log(`to: ${m.toAgentId}`);
1447
+ console.log(`created: ${when}`);
1448
+ console.log(`read: ${read}`);
1449
+ if (m.replyTo) console.log(`reply_to: ${m.replyTo}`);
1450
+ console.log("");
1451
+ console.log(decodeText(m.payload));
1452
+ }
1453
+ });
1454
+ var readCmd = defineCommand8({
1455
+ meta: { name: "read", description: "Mark a message as read" },
1456
+ args: {
1457
+ id: { type: "positional", required: true, description: "Message id" }
1458
+ },
1459
+ async run({ args }) {
1460
+ const client = createClient2();
1461
+ await client.patch(`/api/messages/${args.id}`, { read: true });
1462
+ console.log(`marked read: ${args.id}`);
1463
+ }
1464
+ });
1465
+ var inboxCommand = defineCommand8({
1466
+ meta: { name: "inbox", description: "Inspect agent inboxes" },
1467
+ subCommands: {
1468
+ list: listCmd4,
1469
+ show: showCmd2,
1470
+ read: readCmd
1471
+ }
1472
+ });
1473
+
1474
+ // src/commands/login.ts
1475
+ import { existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync } from "fs";
1476
+ import { defineCommand as defineCommand9 } from "citty";
1477
+ function normalizeServer(raw) {
1478
+ let url;
1479
+ try {
1480
+ url = new URL(raw);
1481
+ } catch {
1482
+ throw new Error(`invalid --server URL: ${raw}`);
1483
+ }
1484
+ if (!/^https?:$/.test(url.protocol)) {
1485
+ throw new Error(`--server must be http(s), got ${url.protocol}`);
1486
+ }
1487
+ return `${url.origin}${url.pathname.replace(/\/$/, "")}`;
1488
+ }
1489
+ async function verifyToken(server, token) {
1490
+ const res = await fetch(`${server}/api/health`, {
1491
+ headers: { authorization: `Bearer ${token}`, origin: server }
1492
+ });
1493
+ if (res.status === 401) throw new Error("server rejected token (401)");
1494
+ if (!res.ok) throw new Error(`server returned ${res.status} from /api/health`);
1495
+ }
1496
+ var loginCommand = defineCommand9({
1497
+ meta: {
1498
+ name: "login",
1499
+ description: "Save a remote bazilion server + token pair to auth.json"
1500
+ },
1501
+ args: {
1502
+ server: { type: "string", description: "Remote server URL (http[s]://...)" },
1503
+ token: { type: "string", description: "Token issued by `bazilion token create`" },
1504
+ skipVerify: { type: "boolean", description: "Don't probe /api/health before saving" },
1505
+ clear: { type: "boolean", description: "Remove the stored remote instead of setting one" }
1506
+ },
1507
+ async run({ args }) {
1508
+ const paths = resolveCliPaths();
1509
+ if (!existsSync3(paths.authFile)) {
1510
+ throw new Error(
1511
+ `${paths.authFile} not found. Start the daemon with "bazilion serve" first \u2014 login stores the remote there.`
1512
+ );
1513
+ }
1514
+ const auth = JSON.parse(readFileSync3(paths.authFile, "utf8"));
1515
+ if (args.clear) {
1516
+ if (!auth.remote) {
1517
+ console.log("no remote stored \u2014 nothing to clear");
1518
+ return;
1519
+ }
1520
+ delete auth.remote;
1521
+ writeFileSync(paths.authFile, `${JSON.stringify(auth, null, 2)}
1522
+ `, { mode: 384 });
1523
+ console.log("cleared stored remote; CLI will fall back to the local daemon");
1524
+ return;
1525
+ }
1526
+ if (!args.server || !args.token) {
1527
+ throw new Error(
1528
+ "--server and --token are required (or pass --clear to remove the stored remote)"
1529
+ );
1530
+ }
1531
+ const server = normalizeServer(args.server);
1532
+ if (!args.skipVerify) {
1533
+ await verifyToken(server, args.token);
1534
+ }
1535
+ auth.remote = { server, token: args.token };
1536
+ writeFileSync(paths.authFile, `${JSON.stringify(auth, null, 2)}
1537
+ `, { mode: 384 });
1538
+ console.log(`saved remote: ${server}`);
1539
+ console.log("CLI will now target this server unless BAZILION_SERVER is set in the env.");
1540
+ }
1541
+ });
1542
+
1543
+ // src/commands/memory.ts
1544
+ import { defineCommand as defineCommand10 } from "citty";
1545
+ function encodeKey(key) {
1546
+ return key.split("/").map(encodeURIComponent).join("/");
1547
+ }
1548
+ var writeCmd = defineCommand10({
1549
+ meta: { name: "write", description: "Write an entry into a group's shared memory" },
1550
+ args: {
1551
+ group: { type: "positional", required: true, description: "Group slug" },
1552
+ key: { type: "positional", required: true, description: "Memory key (path under memory/)" },
1553
+ content: { type: "positional", required: true, description: "Content to write" }
1554
+ },
1555
+ async run({ args }) {
1556
+ const client = createClient2();
1557
+ const entry2 = await client.put(
1558
+ `/api/groups/${args.group}/memory/${encodeKey(args.key)}`,
1559
+ { content: args.content }
1560
+ );
1561
+ console.log(`wrote ${entry2.key} (${entry2.content.length} bytes)`);
1562
+ }
1563
+ });
1564
+ var readCmd2 = defineCommand10({
1565
+ meta: { name: "read", description: "Read an entry from a group's shared memory" },
1566
+ args: {
1567
+ group: { type: "positional", required: true, description: "Group slug" },
1568
+ key: { type: "positional", required: true }
1569
+ },
1570
+ async run({ args }) {
1571
+ const client = createClient2();
1572
+ const entry2 = await client.get(
1573
+ `/api/groups/${args.group}/memory/${encodeKey(args.key)}`
1574
+ );
1575
+ console.log(entry2.content);
1576
+ }
1577
+ });
1578
+ var searchCmd = defineCommand10({
1579
+ meta: { name: "search", description: "Search a group's shared memory" },
1580
+ args: {
1581
+ group: { type: "positional", required: true, description: "Group slug" },
1582
+ query: { type: "positional", required: true },
1583
+ limit: { type: "string", description: "Max results (default 10)" }
1584
+ },
1585
+ async run({ args }) {
1586
+ const client = createClient2();
1587
+ const limit = args.limit ? Number.parseInt(args.limit, 10) : 10;
1588
+ const params = new URLSearchParams({ q: args.query, limit: String(limit) });
1589
+ const hits = await client.get(`/api/groups/${args.group}/memory/search?${params}`);
1590
+ if (hits.length === 0) {
1591
+ console.log("(no matches)");
1592
+ return;
1593
+ }
1594
+ for (const h of hits) {
1595
+ console.log(`${h.key} ${h.snippet.replaceAll("\n", " ")}`);
1596
+ }
1597
+ }
1598
+ });
1599
+ var listCmd5 = defineCommand10({
1600
+ meta: { name: "list", description: "List all entries in a group's shared memory" },
1601
+ args: {
1602
+ group: { type: "positional", required: true, description: "Group slug" }
1603
+ },
1604
+ async run({ args }) {
1605
+ const client = createClient2();
1606
+ const all = await client.get(`/api/groups/${args.group}/memory`);
1607
+ if (all.length === 0) {
1608
+ console.log("(no memory entries)");
1609
+ return;
1610
+ }
1611
+ for (const e of all) {
1612
+ console.log(`${e.key} ${e.content.length}b`);
1613
+ }
1614
+ }
1615
+ });
1616
+ var rmCmd3 = defineCommand10({
1617
+ meta: { name: "rm", description: "Remove an entry from a group's shared memory" },
1618
+ args: {
1619
+ group: { type: "positional", required: true, description: "Group slug" },
1620
+ key: { type: "positional", required: true }
1621
+ },
1622
+ async run({ args }) {
1623
+ const client = createClient2();
1624
+ await client.del(`/api/groups/${args.group}/memory/${encodeKey(args.key)}`);
1625
+ console.log(`removed ${args.key}`);
1626
+ }
1627
+ });
1628
+ var memoryCommand = defineCommand10({
1629
+ meta: {
1630
+ name: "memory",
1631
+ description: "Manage a group's shared memory (BM25-indexed markdown notes)"
1632
+ },
1633
+ subCommands: {
1634
+ write: writeCmd,
1635
+ read: readCmd2,
1636
+ search: searchCmd,
1637
+ list: listCmd5,
1638
+ rm: rmCmd3
1639
+ }
1640
+ });
1641
+
1642
+ // src/commands/profile.ts
1643
+ import { spawn as spawn2 } from "child_process";
1644
+ import { randomBytes } from "crypto";
1645
+ import { readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
1646
+ import { tmpdir } from "os";
1647
+ import { join as join2 } from "path";
1648
+
1649
+ // ../../packages/api-types/src/index.ts
1650
+ var PROFILE_FILES = [
1651
+ "profile.json",
1652
+ "SOUL.md",
1653
+ "IDENTITY.md",
1654
+ "BOOTSTRAP.md",
1655
+ "AGENTS.md",
1656
+ "TOOLS.md",
1657
+ "HEARTBEAT.md"
1658
+ ];
1659
+
1660
+ // src/commands/profile.ts
1661
+ import { defineCommand as defineCommand11 } from "citty";
1662
+ function splitCsv(v) {
1663
+ if (!v) return void 0;
1664
+ const out = v.split(",").map((s) => s.trim()).filter(Boolean);
1665
+ return out.length > 0 ? out : void 0;
1666
+ }
1667
+ function parseSkillsMode(v) {
1668
+ if (v === void 0) return void 0;
1669
+ if (v === "all" || v === "selected") return v;
1670
+ throw new Error(`--skills-mode must be 'all' or 'selected', got '${v}'`);
1671
+ }
1672
+ var createCmd2 = defineCommand11({
1673
+ meta: { name: "create", description: "Create a new profile" },
1674
+ args: {
1675
+ id: { type: "positional", required: true, description: "Profile slug" },
1676
+ name: { type: "string", description: "Display name (defaults to slug)" },
1677
+ model: {
1678
+ type: "string",
1679
+ required: true,
1680
+ description: "Default model, e.g. anthropic:claude-opus-4-6"
1681
+ },
1682
+ "skills-mode": {
1683
+ type: "string",
1684
+ description: "'all' (attach every discovered skill) or 'selected' (default)"
1685
+ },
1686
+ skills: {
1687
+ type: "string",
1688
+ description: "Default skills, comma-separated (skills-mode=selected)"
1689
+ },
1690
+ "soul-file": {
1691
+ type: "string",
1692
+ description: "Path to custom SOUL.md content (defaults to the built-in template)"
1693
+ },
1694
+ "identity-file": {
1695
+ type: "string",
1696
+ description: "Path to custom IDENTITY.md content (defaults to the built-in template)"
1697
+ },
1698
+ "bootstrap-file": {
1699
+ type: "string",
1700
+ description: "Path to custom BOOTSTRAP.md content (defaults to the built-in template)"
1701
+ },
1702
+ "skip-bootstrap": {
1703
+ type: "boolean",
1704
+ description: "Skip the bootstrap file entirely (no first-run intro)"
1705
+ },
1706
+ "agents-file": {
1707
+ type: "string",
1708
+ description: "Path to AGENTS.md content (optional; omit to skip)"
1709
+ },
1710
+ "tools-file": {
1711
+ type: "string",
1712
+ description: "Path to TOOLS.md content (optional; omit to skip)"
1713
+ },
1714
+ "heartbeat-file": {
1715
+ type: "string",
1716
+ description: "Path to HEARTBEAT.md content (optional; omit to skip)"
1717
+ }
1718
+ },
1719
+ async run({ args }) {
1720
+ const skillsMode = parseSkillsMode(args["skills-mode"]);
1721
+ const readTemplate = (path) => path ? readFileSync4(path, "utf8") : void 0;
1722
+ const body = {
1723
+ id: args.id,
1724
+ name: args.name,
1725
+ defaultModel: args.model,
1726
+ skillsMode,
1727
+ defaultSkills: splitCsv(args.skills),
1728
+ soul: readTemplate(args["soul-file"]),
1729
+ identity: readTemplate(args["identity-file"]),
1730
+ bootstrap: args["skip-bootstrap"] ? null : readTemplate(args["bootstrap-file"]) ?? void 0,
1731
+ agents: readTemplate(args["agents-file"]),
1732
+ tools: readTemplate(args["tools-file"]),
1733
+ heartbeat: readTemplate(args["heartbeat-file"])
1734
+ };
1735
+ const client = createClient2();
1736
+ const profile = await client.post("/api/profiles", body);
1737
+ console.log(`created profile ${profile.id} at ${profile.dir}`);
1738
+ }
1739
+ });
1740
+ var listCmd6 = defineCommand11({
1741
+ meta: { name: "list", description: "List profiles" },
1742
+ async run() {
1743
+ const client = createClient2();
1744
+ const list = await client.get("/api/profiles");
1745
+ if (list.length === 0) {
1746
+ console.log("(no profiles)");
1747
+ return;
1748
+ }
1749
+ const rows = list.map((p) => [p.id, p.defaultModel, p.name]);
1750
+ for (const line of columnize(rows)) console.log(line);
1751
+ }
1752
+ });
1753
+ var showCmd3 = defineCommand11({
1754
+ meta: { name: "show", description: "Show profile details" },
1755
+ args: {
1756
+ id: { type: "positional", required: true }
1757
+ },
1758
+ async run({ args }) {
1759
+ const client = createClient2();
1760
+ const loaded = await client.get(`/api/profiles/${args.id}`);
1761
+ console.log(`# ${loaded.profile.id}`);
1762
+ console.log(`name: ${loaded.profile.name}`);
1763
+ console.log(`dir: ${loaded.profile.dir}`);
1764
+ console.log(`default model: ${loaded.profile.defaultModel}`);
1765
+ console.log(`skills mode: ${loaded.profile.skillsMode}`);
1766
+ console.log(
1767
+ `default skills: ${loaded.defaultSkills.length === 0 ? "(none)" : loaded.defaultSkills.join(", ")}`
1768
+ );
1769
+ console.log(`bootstrap: ${loaded.files.bootstrap !== null ? "yes" : "no"}`);
1770
+ console.log(`agents: ${loaded.files.agents !== null ? "yes" : "no"}`);
1771
+ console.log(`tools: ${loaded.files.tools !== null ? "yes" : "no"}`);
1772
+ console.log(`heartbeat: ${loaded.files.heartbeat !== null ? "yes" : "no"}`);
1773
+ if (loaded.identity) {
1774
+ const fields = Object.entries(loaded.identity).filter(([, v]) => typeof v === "string" && v.length > 0).map(([k, v]) => `${k}=${v}`).join(", ");
1775
+ if (fields) console.log(`identity: ${fields}`);
1776
+ }
1777
+ }
1778
+ });
1779
+ var editCmd2 = defineCommand11({
1780
+ meta: { name: "edit", description: "Open a profile file in $EDITOR" },
1781
+ args: {
1782
+ id: { type: "positional", required: true },
1783
+ file: {
1784
+ type: "string",
1785
+ default: "profile.json",
1786
+ description: `File: ${PROFILE_FILES.join(", ")}`
1787
+ }
1788
+ },
1789
+ async run({ args }) {
1790
+ if (!PROFILE_FILES.includes(args.file)) {
1791
+ throw new Error(`unsupported file: ${args.file}. Allowed: ${PROFILE_FILES.join(", ")}`);
1792
+ }
1793
+ const file = args.file;
1794
+ const client = createClient2();
1795
+ const { content } = await client.get(
1796
+ `/api/profiles/${args.id}/files/${file}`
1797
+ );
1798
+ const tmpPath = join2(tmpdir(), `bazilion-${args.id}-${file}-${randomBytes(4).toString("hex")}`);
1799
+ writeFileSync2(tmpPath, content);
1800
+ try {
1801
+ const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
1802
+ const code = await new Promise((resolve3, reject) => {
1803
+ const child = spawn2(editor, [tmpPath], { stdio: "inherit" });
1804
+ child.on("error", reject);
1805
+ child.on("close", (c) => resolve3(c ?? 0));
1806
+ });
1807
+ if (code !== 0) throw new Error(`editor exited with code ${code}`);
1808
+ const updated = readFileSync4(tmpPath, "utf8");
1809
+ if (updated === content) {
1810
+ console.log("(no changes)");
1811
+ return;
1812
+ }
1813
+ const body = { content: updated };
1814
+ await client.put(`/api/profiles/${args.id}/files/${file}`, body);
1815
+ console.log(`saved ${file}`);
1816
+ } finally {
1817
+ try {
1818
+ rmSync2(tmpPath, { force: true });
1819
+ } catch {
1820
+ }
1821
+ }
1822
+ }
1823
+ });
1824
+ var updateCmd = defineCommand11({
1825
+ meta: {
1826
+ name: "update",
1827
+ description: "Update profile settings (name, model, skills-mode, skills)"
1828
+ },
1829
+ args: {
1830
+ id: { type: "positional", required: true },
1831
+ name: { type: "string", description: "New display name" },
1832
+ model: { type: "string", description: "New default model" },
1833
+ "skills-mode": {
1834
+ type: "string",
1835
+ description: "Switch to 'all' or 'selected'"
1836
+ },
1837
+ skills: { type: "string", description: "Replacement default skills, comma-separated" }
1838
+ },
1839
+ async run({ args }) {
1840
+ const body = {};
1841
+ if (args.name !== void 0) body.name = args.name;
1842
+ if (args.model !== void 0) body.defaultModel = args.model;
1843
+ const mode = parseSkillsMode(args["skills-mode"]);
1844
+ if (mode !== void 0) body.skillsMode = mode;
1845
+ if (args.skills !== void 0) {
1846
+ body.defaultSkills = args.skills.split(",").map((s) => s.trim()).filter(Boolean);
1847
+ }
1848
+ if (Object.keys(body).length === 0) {
1849
+ throw new Error(
1850
+ "nothing to update \u2014 pass at least one of --name/--model/--skills-mode/--skills"
1851
+ );
1852
+ }
1853
+ const client = createClient2();
1854
+ const profile = await client.patch(`/api/profiles/${args.id}`, body);
1855
+ console.log(`updated profile ${profile.id}`);
1856
+ }
1857
+ });
1858
+ var deleteCmd2 = defineCommand11({
1859
+ meta: { name: "delete", description: "Permanently delete a profile and its files" },
1860
+ args: {
1861
+ id: { type: "positional", required: true }
1862
+ },
1863
+ async run({ args }) {
1864
+ const client = createClient2();
1865
+ await client.del(`/api/profiles/${args.id}`);
1866
+ console.log(`deleted profile ${args.id}`);
1867
+ }
1868
+ });
1869
+ var profileCommand = defineCommand11({
1870
+ meta: { name: "profile", description: "Manage profiles" },
1871
+ subCommands: {
1872
+ create: createCmd2,
1873
+ list: listCmd6,
1874
+ show: showCmd3,
1875
+ edit: editCmd2,
1876
+ update: updateCmd,
1877
+ delete: deleteCmd2
1878
+ }
1879
+ });
1880
+
1881
+ // src/commands/provider.ts
1882
+ import { defineCommand as defineCommand12 } from "citty";
1883
+ var listCmd7 = defineCommand12({
1884
+ meta: {
1885
+ name: "list",
1886
+ description: "List all providers with enabled/disabled state and curated model counts"
1887
+ },
1888
+ args: {
1889
+ enabled: { type: "boolean", description: "Show only enabled providers" }
1890
+ },
1891
+ async run({ args }) {
1892
+ const client = createClient2();
1893
+ const { providers } = await client.get("/api/config/providers");
1894
+ const filtered = args.enabled ? providers.filter((p) => p.enabled) : providers;
1895
+ if (filtered.length === 0) {
1896
+ console.log("(no providers to show)");
1897
+ return;
1898
+ }
1899
+ const rows = filtered.map((p) => [
1900
+ p.id,
1901
+ p.enabled ? "enabled" : "disabled",
1902
+ `${p.curated.length} curated`,
1903
+ `${p.catalog.length} catalog`,
1904
+ p.enabled ? "" : `(set ${p.envHint})`
1905
+ ]);
1906
+ for (const line of columnize(rows)) console.log(line);
1907
+ }
1908
+ });
1909
+ var modelsCmd = defineCommand12({
1910
+ meta: {
1911
+ name: "models",
1912
+ description: "Show curated + catalog + live models for one provider"
1913
+ },
1914
+ args: {
1915
+ name: { type: "positional", required: true, description: "Provider name" }
1916
+ },
1917
+ async run({ args }) {
1918
+ const client = createClient2();
1919
+ const { providers } = await client.get("/api/config/providers");
1920
+ const p = providers.find((x) => x.id === args.name);
1921
+ if (!p) {
1922
+ console.error(`unknown provider: ${args.name}`);
1923
+ process.exit(1);
1924
+ }
1925
+ console.log(`# ${p.id} (${p.enabled ? "enabled" : "disabled"})`);
1926
+ if (!p.enabled) console.log(` (set ${p.envHint} to enable)`);
1927
+ console.log("\n## curated");
1928
+ if (p.curated.length === 0) console.log(" (none \u2014 use `provider models-set` to pin some)");
1929
+ else for (const m of p.curated) console.log(` ${m}`);
1930
+ console.log("\n## catalog (from pi-ai)");
1931
+ if (p.catalog.length === 0) console.log(" (empty)");
1932
+ else for (const m of p.catalog) console.log(` ${m}`);
1933
+ if (p.live) {
1934
+ console.log("\n## live (from upstream /v1/models)");
1935
+ if (p.live.error) console.log(` (error: ${p.live.error})`);
1936
+ else if (p.live.models.length === 0) console.log(" (empty)");
1937
+ else for (const m of p.live.models) console.log(` ${m}`);
1938
+ }
1939
+ }
1940
+ });
1941
+ var modelsSetCmd = defineCommand12({
1942
+ meta: {
1943
+ name: "models-set",
1944
+ description: "Replace the curated model list for a provider (comma-separated)"
1945
+ },
1946
+ args: {
1947
+ name: { type: "positional", required: true, description: "Provider name" },
1948
+ models: {
1949
+ type: "positional",
1950
+ required: true,
1951
+ description: "Comma-separated model list (empty string clears the list)"
1952
+ }
1953
+ },
1954
+ async run({ args }) {
1955
+ const client = createClient2();
1956
+ const models = args.models.split(",").map((s) => s.trim()).filter(Boolean);
1957
+ const body = { models };
1958
+ const saved = await client.put(
1959
+ `/api/config/providers/${encodeURIComponent(args.name)}/models`,
1960
+ body
1961
+ );
1962
+ console.log(`saved ${saved.models.length} curated model(s) for ${args.name}`);
1963
+ for (const m of saved.models) console.log(` ${m}`);
1964
+ }
1965
+ });
1966
+ var enableCmd = defineCommand12({
1967
+ meta: { name: "enable", description: "Toggle a provider on so agents can use it" },
1968
+ args: {
1969
+ name: { type: "positional", required: true, description: "Provider id (e.g. anthropic)" }
1970
+ },
1971
+ async run({ args }) {
1972
+ const client = createClient2();
1973
+ const res = await client.put(
1974
+ `/api/config/providers/${encodeURIComponent(args.name)}/enabled`,
1975
+ { enabled: true }
1976
+ );
1977
+ console.log(`${res.name}: enabled`);
1978
+ }
1979
+ });
1980
+ var disableCmd = defineCommand12({
1981
+ meta: {
1982
+ name: "disable",
1983
+ description: "Toggle a provider off \u2014 agents will refuse its model strings"
1984
+ },
1985
+ args: {
1986
+ name: { type: "positional", required: true, description: "Provider id" }
1987
+ },
1988
+ async run({ args }) {
1989
+ const client = createClient2();
1990
+ const res = await client.put(
1991
+ `/api/config/providers/${encodeURIComponent(args.name)}/enabled`,
1992
+ { enabled: false }
1993
+ );
1994
+ console.log(`${res.name}: disabled`);
1995
+ }
1996
+ });
1997
+ var testCmd = defineCommand12({
1998
+ meta: { name: "test", description: "Send a single chat to a model and print the reply" },
1999
+ args: {
2000
+ model: {
2001
+ type: "positional",
2002
+ required: true,
2003
+ description: "Model string, e.g. anthropic:claude-opus-4-6"
2004
+ },
2005
+ message: { type: "string", description: 'Message text (default "say hi briefly")' }
2006
+ },
2007
+ async run({ args }) {
2008
+ const client = createClient2();
2009
+ const body = { model: args.model, message: args.message };
2010
+ console.log(`-> ${args.model}: ${args.message ?? "say hi briefly"}`);
2011
+ const res = await client.post("/api/providers/test", body);
2012
+ console.log(`<- ${res.content}`);
2013
+ if (res.usage) {
2014
+ console.log(`(${res.usage.promptTokens} in, ${res.usage.completionTokens} out)`);
2015
+ }
2016
+ }
2017
+ });
2018
+ var providerCommand = defineCommand12({
2019
+ meta: { name: "provider", description: "Manage and test LLM providers" },
2020
+ subCommands: {
2021
+ list: listCmd7,
2022
+ enable: enableCmd,
2023
+ disable: disableCmd,
2024
+ models: modelsCmd,
2025
+ "models-set": modelsSetCmd,
2026
+ test: testCmd
2027
+ }
2028
+ });
2029
+
2030
+ // src/commands/send.ts
2031
+ import { defineCommand as defineCommand13 } from "citty";
2032
+ var sendCommand = defineCommand13({
2033
+ meta: {
2034
+ name: "send",
2035
+ description: "Send a message from one agent to another"
2036
+ },
2037
+ args: {
2038
+ from: { type: "positional", required: true, description: "Sender agent id" },
2039
+ to: { type: "positional", required: true, description: "Recipient agent id" },
2040
+ message: { type: "positional", required: true, description: "Message text" }
2041
+ },
2042
+ async run({ args }) {
2043
+ const client = createClient2();
2044
+ const body = {
2045
+ from: args.from,
2046
+ payload: { text: args.message }
2047
+ };
2048
+ const msg = await client.post(`/api/agents/${args.to}/messages`, body);
2049
+ console.log(`sent message ${msg.id}`);
2050
+ }
2051
+ });
2052
+
2053
+ // src/commands/serve.ts
2054
+ import { spawn as spawn3 } from "child_process";
2055
+ import { existsSync as existsSync4 } from "fs";
2056
+ import { join as join3 } from "path";
2057
+ import { defineCommand as defineCommand14 } from "citty";
2058
+ var bundledDaemonEntry = join3(import.meta.dirname, "daemon.js");
2059
+ var sourceDaemonEntry = join3(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
2060
+ var daemonEntry = existsSync4(bundledDaemonEntry) ? bundledDaemonEntry : sourceDaemonEntry;
2061
+ var serveCommand = defineCommand14({
2062
+ meta: {
2063
+ name: "serve",
2064
+ description: "Start the bazilion daemon (HTTP API)"
2065
+ },
2066
+ args: {
2067
+ port: { type: "string", description: "Port (default 4321)" },
2068
+ host: {
2069
+ type: "string",
2070
+ description: "Host (default 127.0.0.1). Put a TLS proxy in front before binding 0.0.0.0"
2071
+ }
2072
+ },
2073
+ async run({ args }) {
2074
+ if (!existsSync4(daemonEntry)) {
2075
+ throw new Error(
2076
+ `bazilion daemon not found at ${daemonEntry}. Are you running from a development checkout?`
2077
+ );
2078
+ }
2079
+ const env = { ...process.env };
2080
+ if (args.port) env.PORT = args.port;
2081
+ if (args.host) env.HOST = args.host;
2082
+ const host = args.host ?? "127.0.0.1";
2083
+ const port = args.port ?? "4321";
2084
+ if (host !== "127.0.0.1" && host !== "localhost" && host !== "::1") {
2085
+ console.error("");
2086
+ console.error(`\u26A0 binding to ${host} \u2014 the daemon is now reachable beyond loopback.`);
2087
+ console.error(" anyone on this network who has a valid token can reach every API.");
2088
+ console.error(" put a TLS proxy in front for untrusted networks.");
2089
+ console.error("");
2090
+ }
2091
+ console.log(`starting bazilion daemon at http://${host}:${port}`);
2092
+ console.log("(web UI runs separately: cd apps/web && pnpm dev)");
2093
+ const nodeArgs = daemonEntry.endsWith(".ts") ? ["--import", "tsx/esm", daemonEntry] : [daemonEntry];
2094
+ const proc = spawn3("node", nodeArgs, {
2095
+ env,
2096
+ stdio: "inherit"
2097
+ });
2098
+ let signalled = false;
2099
+ const onSigterm = () => {
2100
+ signalled = true;
2101
+ try {
2102
+ proc.kill("SIGTERM");
2103
+ } catch {
2104
+ }
2105
+ };
2106
+ process.on("SIGINT", () => {
2107
+ signalled = true;
2108
+ });
2109
+ process.on("SIGTERM", onSigterm);
2110
+ await new Promise((resolve3, reject) => {
2111
+ proc.on("error", (err) => reject(err));
2112
+ proc.on("close", (code) => {
2113
+ if (signalled) {
2114
+ process.exitCode = 0;
2115
+ resolve3();
2116
+ } else if (code === 0 || code === null) {
2117
+ resolve3();
2118
+ } else {
2119
+ process.exitCode = code;
2120
+ resolve3();
2121
+ }
2122
+ });
2123
+ });
2124
+ }
2125
+ });
2126
+
2127
+ // src/commands/skill.ts
2128
+ import { existsSync as existsSync5, readFileSync as readFileSync5, statSync } from "fs";
2129
+ import { basename, resolve as resolve2 } from "path";
2130
+ import { defineCommand as defineCommand15 } from "citty";
2131
+ var listCmd8 = defineCommand15({
2132
+ meta: { name: "list", description: "List installed skills (or those attached to an agent)" },
2133
+ args: {
2134
+ agent: { type: "string", description: "Filter to skills attached to this agent" }
2135
+ },
2136
+ async run({ args }) {
2137
+ const client = createClient2();
2138
+ if (args.agent) {
2139
+ const set = await client.get(`/api/agents/${args.agent}/skills`);
2140
+ if (set.resolved.length === 0 && set.missing.length === 0) {
2141
+ console.log("(no skills attached to this agent)");
2142
+ return;
2143
+ }
2144
+ const rows2 = set.resolved.map((s) => [s.name, s.description]);
2145
+ for (const line of columnize(rows2)) console.log(line);
2146
+ for (const m of set.missing) {
2147
+ console.log(`(missing: ${m.name} \u2014 ${m.reason})`);
2148
+ }
2149
+ return;
2150
+ }
2151
+ const skills = await client.get("/api/skills");
2152
+ if (skills.length === 0) {
2153
+ console.log('(no skills installed; use "bazilion skill import" to add some)');
2154
+ return;
2155
+ }
2156
+ const rows = skills.map((s) => [
2157
+ s.name,
2158
+ s.parseError ? `(parse error: ${s.parseError})` : s.description
2159
+ ]);
2160
+ for (const line of columnize(rows)) console.log(line);
2161
+ }
2162
+ });
2163
+ var importCmd = defineCommand15({
2164
+ meta: {
2165
+ name: "import",
2166
+ description: "Import skills from openclaw, a directory, or a local .zip archive"
2167
+ },
2168
+ args: {
2169
+ from: {
2170
+ type: "string",
2171
+ required: true,
2172
+ description: 'Source: "openclaw", a filesystem path on the server, or a local .zip file to upload'
2173
+ },
2174
+ force: { type: "boolean", description: "Overwrite existing skills" }
2175
+ },
2176
+ async run({ args }) {
2177
+ const client = createClient2();
2178
+ const absFrom = resolve2(args.from);
2179
+ const isLocalZip = args.from.toLowerCase().endsWith(".zip") && existsSync5(absFrom) && statSync(absFrom).isFile();
2180
+ let result;
2181
+ if (isLocalZip) {
2182
+ const bytes = readFileSync5(absFrom);
2183
+ const file = new File([bytes], basename(absFrom), { type: "application/zip" });
2184
+ const fd = new FormData();
2185
+ fd.set("file", file);
2186
+ if (args.force) fd.set("force", "true");
2187
+ result = await client.postMultipart("/api/skills/import", fd);
2188
+ } else {
2189
+ const body = {
2190
+ source: args.from,
2191
+ force: args.force
2192
+ };
2193
+ result = await client.post("/api/skills/import", body);
2194
+ }
2195
+ if (result.imported.length === 0 && result.skipped.length === 0) {
2196
+ console.log("(nothing to import)");
2197
+ return;
2198
+ }
2199
+ for (const name of result.imported) {
2200
+ console.log(`imported ${name}`);
2201
+ }
2202
+ for (const s of result.skipped) {
2203
+ console.log(`skipped ${s.name}: ${s.reason}`);
2204
+ }
2205
+ }
2206
+ });
2207
+ var rmCmd4 = defineCommand15({
2208
+ meta: { name: "rm", description: "Remove an installed skill" },
2209
+ args: {
2210
+ name: { type: "positional", required: true }
2211
+ },
2212
+ async run({ args }) {
2213
+ const client = createClient2();
2214
+ await client.del(`/api/skills/${encodeURIComponent(args.name)}`);
2215
+ console.log(`removed skill ${args.name}`);
2216
+ }
2217
+ });
2218
+ var skillCommand = defineCommand15({
2219
+ meta: { name: "skill", description: "Manage the skill library" },
2220
+ subCommands: {
2221
+ list: listCmd8,
2222
+ import: importCmd,
2223
+ rm: rmCmd4
2224
+ }
2225
+ });
2226
+
2227
+ // src/commands/token.ts
2228
+ import { networkInterfaces } from "os";
2229
+ import { defineCommand as defineCommand16 } from "citty";
2230
+ import qrcode from "qrcode-terminal";
2231
+ function tokenRow(t) {
2232
+ const last = t.lastUsedAt ? new Date(t.lastUsedAt).toISOString() : "(never)";
2233
+ const state = t.revokedAt ? "revoked" : "active";
2234
+ return [t.id, state, t.label, `last: ${last}`];
2235
+ }
2236
+ function detectLanOrigin(port) {
2237
+ const candidates = [];
2238
+ for (const ifs of Object.values(networkInterfaces())) {
2239
+ for (const i of ifs ?? []) {
2240
+ if (i.family === "IPv4" && !i.internal) candidates.push(i.address);
2241
+ }
2242
+ }
2243
+ const [first, ...rest] = candidates;
2244
+ if (!first) return null;
2245
+ const origin = `http://${first}:${port}`;
2246
+ return rest.length > 0 ? { origin, warning: `multiple LAN IPs found (${candidates.join(", ")}) \u2014 using ${first}` } : { origin };
2247
+ }
2248
+ function resolveQrServer(override) {
2249
+ if (override) return override.replace(/\/$/, "");
2250
+ const cfg = loadClientConfig();
2251
+ const current = new URL(cfg.serverUrl);
2252
+ const isLoopback = current.hostname === "127.0.0.1" || current.hostname === "localhost" || current.hostname === "::1";
2253
+ if (!isLoopback) return cfg.serverUrl.replace(/\/$/, "");
2254
+ const detected = detectLanOrigin(current.port || "4321");
2255
+ if (!detected) {
2256
+ throw new Error(
2257
+ "server URL is loopback-only and no LAN interface was found. Pass --server http://<host>:<port> so the mobile client knows where to connect."
2258
+ );
2259
+ }
2260
+ if (detected.warning) console.warn(`\u26A0 ${detected.warning}`);
2261
+ return detected.origin;
2262
+ }
2263
+ var createCmd3 = defineCommand16({
2264
+ meta: { name: "create", description: "Mint a new web token (shown once)" },
2265
+ args: {
2266
+ label: { type: "positional", required: true, description: "Human-readable label" },
2267
+ qr: {
2268
+ type: "boolean",
2269
+ description: "Also render a pairing QR code for mobile clients (bazilion://pair?...)"
2270
+ },
2271
+ server: {
2272
+ type: "string",
2273
+ description: "Server URL to embed in the pairing QR (default: detect LAN IP; ignored without --qr)"
2274
+ }
2275
+ },
2276
+ async run({ args }) {
2277
+ const client = createClient2();
2278
+ const body = { label: args.label };
2279
+ const res = await client.post("/api/tokens", body);
2280
+ console.log(`id: ${res.meta.id}`);
2281
+ console.log(`label: ${res.meta.label}`);
2282
+ console.log(`token: ${res.token}`);
2283
+ console.log("");
2284
+ console.log("store the token now \u2014 it is not recoverable later.");
2285
+ if (!args.qr) return;
2286
+ const serverUrl = resolveQrServer(args.server);
2287
+ const pairUrl = `bazilion://pair?server=${encodeURIComponent(serverUrl)}&token=${encodeURIComponent(res.token)}`;
2288
+ console.log("");
2289
+ console.log(`pairing URL: ${pairUrl}`);
2290
+ console.log("");
2291
+ qrcode.generate(pairUrl, { small: true }, (qr) => console.log(qr));
2292
+ }
2293
+ });
2294
+ var listCmd9 = defineCommand16({
2295
+ meta: { name: "list", description: "List web tokens" },
2296
+ args: {
2297
+ all: { type: "boolean", description: "Include revoked tokens" }
2298
+ },
2299
+ async run({ args }) {
2300
+ const client = createClient2();
2301
+ const qs = args.all ? "?includeRevoked=1" : "";
2302
+ const { tokens } = await client.get(`/api/tokens${qs}`);
2303
+ if (tokens.length === 0) {
2304
+ console.log("(no tokens)");
2305
+ return;
2306
+ }
2307
+ for (const line of columnize(tokens.map(tokenRow))) console.log(line);
2308
+ }
2309
+ });
2310
+ var showLocalCmd = defineCommand16({
2311
+ meta: {
2312
+ name: "show-local",
2313
+ description: "Print the bootstrap web token stored in ~/.bazilion/auth.json"
2314
+ },
2315
+ run() {
2316
+ const paths = resolveCliPaths();
2317
+ console.log(readAuthFile(paths.authFile).token);
2318
+ }
2319
+ });
2320
+ var revokeCmd = defineCommand16({
2321
+ meta: { name: "revoke", description: "Revoke a web token" },
2322
+ args: {
2323
+ id: { type: "positional", required: true }
2324
+ },
2325
+ async run({ args }) {
2326
+ const client = createClient2();
2327
+ await client.del(`/api/tokens/${args.id}`);
2328
+ console.log(`revoked token ${args.id}`);
2329
+ }
2330
+ });
2331
+ var tokenCommand = defineCommand16({
2332
+ meta: { name: "token", description: "Manage web tokens for API/CLI clients" },
2333
+ subCommands: {
2334
+ create: createCmd3,
2335
+ list: listCmd9,
2336
+ revoke: revokeCmd,
2337
+ "show-local": showLocalCmd
2338
+ }
2339
+ });
2340
+
2341
+ // src/commands/trigger.ts
2342
+ import { defineCommand as defineCommand17 } from "citty";
2343
+ var addCmd2 = defineCommand17({
2344
+ meta: { name: "add", description: "Add a heartbeat / cron trigger to an agent" },
2345
+ args: {
2346
+ agent: { type: "positional", required: true },
2347
+ every: {
2348
+ type: "string",
2349
+ description: "Interval in seconds (e.g. --every 300 = every 5 minutes)"
2350
+ },
2351
+ cron: {
2352
+ type: "string",
2353
+ description: "Cron expression (5 fields: minute hour dom month dow)"
2354
+ },
2355
+ message: {
2356
+ type: "string",
2357
+ required: true,
2358
+ description: "Message to inject when the trigger fires"
2359
+ },
2360
+ disabled: { type: "boolean", description: "Create in disabled state" }
2361
+ },
2362
+ async run({ args }) {
2363
+ if (!args.every === !args.cron) {
2364
+ throw new Error('specify exactly one of --every <seconds> or --cron "<expr>"');
2365
+ }
2366
+ const client = createClient2();
2367
+ const body = args.every ? {
2368
+ kind: "interval",
2369
+ intervalSec: Number(args.every),
2370
+ message: args.message,
2371
+ enabled: !args.disabled
2372
+ } : {
2373
+ kind: "cron",
2374
+ cronExpr: args.cron,
2375
+ message: args.message,
2376
+ enabled: !args.disabled
2377
+ };
2378
+ const res = await client.post(`/api/agents/${args.agent}/triggers`, body);
2379
+ const t = res.trigger;
2380
+ const spec = t.kind === "interval" ? `every ${t.intervalSec}s` : `cron "${t.cronExpr}"`;
2381
+ console.log(`${t.id} ${spec} ${t.enabled ? "enabled" : "disabled"}`);
2382
+ }
2383
+ });
2384
+ function triggerRow(t) {
2385
+ const spec = t.kind === "interval" ? `every ${t.intervalSec}s` : `cron "${t.cronExpr}"`;
2386
+ const last = t.lastFiredAt ? new Date(t.lastFiredAt).toISOString() : "(never)";
2387
+ const state = t.enabled ? "enabled" : "disabled";
2388
+ const msgPreview = t.message.length > 60 ? `${t.message.slice(0, 60)}\u2026` : t.message;
2389
+ return [t.id, state, spec, `last: ${last}`, `"${msgPreview}"`];
2390
+ }
2391
+ var listCmd10 = defineCommand17({
2392
+ meta: { name: "list", description: "List triggers for an agent" },
2393
+ args: {
2394
+ agent: { type: "positional", required: true }
2395
+ },
2396
+ async run({ args }) {
2397
+ const client = createClient2();
2398
+ const { triggers } = await client.get(
2399
+ `/api/agents/${args.agent}/triggers`
2400
+ );
2401
+ if (triggers.length === 0) {
2402
+ console.log("(no triggers)");
2403
+ return;
2404
+ }
2405
+ for (const line of columnize(triggers.map(triggerRow))) console.log(line);
2406
+ }
2407
+ });
2408
+ var rmCmd5 = defineCommand17({
2409
+ meta: { name: "rm", description: "Delete a trigger" },
2410
+ args: {
2411
+ id: { type: "positional", required: true }
2412
+ },
2413
+ async run({ args }) {
2414
+ const client = createClient2();
2415
+ await client.del(`/api/triggers/${args.id}`);
2416
+ console.log(`removed trigger ${args.id}`);
2417
+ }
2418
+ });
2419
+ var enableCmd2 = defineCommand17({
2420
+ meta: { name: "enable", description: "Enable a trigger" },
2421
+ args: {
2422
+ id: { type: "positional", required: true }
2423
+ },
2424
+ async run({ args }) {
2425
+ const client = createClient2();
2426
+ const body = { enabled: true };
2427
+ await client.patch(`/api/triggers/${args.id}`, body);
2428
+ console.log(`enabled trigger ${args.id}`);
2429
+ }
2430
+ });
2431
+ var disableCmd2 = defineCommand17({
2432
+ meta: { name: "disable", description: "Disable a trigger" },
2433
+ args: {
2434
+ id: { type: "positional", required: true }
2435
+ },
2436
+ async run({ args }) {
2437
+ const client = createClient2();
2438
+ const body = { enabled: false };
2439
+ await client.patch(`/api/triggers/${args.id}`, body);
2440
+ console.log(`disabled trigger ${args.id}`);
2441
+ }
2442
+ });
2443
+ var triggerCommand = defineCommand17({
2444
+ meta: { name: "trigger", description: "Manage agent heartbeats / cron triggers" },
2445
+ subCommands: {
2446
+ add: addCmd2,
2447
+ list: listCmd10,
2448
+ rm: rmCmd5,
2449
+ enable: enableCmd2,
2450
+ disable: disableCmd2
2451
+ }
2452
+ });
2453
+
2454
+ // src/commands/uninstall.ts
2455
+ import { existsSync as existsSync6, readdirSync as readdirSync2, rmSync as rmSync3 } from "fs";
2456
+ import { join as join4 } from "path";
2457
+ import { defineCommand as defineCommand18 } from "citty";
2458
+ function makeLineReader() {
2459
+ let buffer = "";
2460
+ let ended = false;
2461
+ const queue = [];
2462
+ const tryDeliver = () => {
2463
+ while (queue.length > 0) {
2464
+ const nlIdx = buffer.indexOf("\n");
2465
+ if (nlIdx === -1) {
2466
+ if (ended) {
2467
+ const resolve3 = queue.shift();
2468
+ resolve3?.(buffer);
2469
+ buffer = "";
2470
+ } else {
2471
+ return;
2472
+ }
2473
+ } else {
2474
+ const line = buffer.slice(0, nlIdx);
2475
+ buffer = buffer.slice(nlIdx + 1);
2476
+ const resolve3 = queue.shift();
2477
+ resolve3?.(line);
2478
+ }
2479
+ }
2480
+ };
2481
+ process.stdin.setEncoding("utf8");
2482
+ process.stdin.on("data", (chunk) => {
2483
+ buffer += chunk;
2484
+ tryDeliver();
2485
+ });
2486
+ process.stdin.on("end", () => {
2487
+ ended = true;
2488
+ tryDeliver();
2489
+ });
2490
+ return () => new Promise((resolve3) => {
2491
+ queue.push(resolve3);
2492
+ tryDeliver();
2493
+ });
2494
+ }
2495
+ async function askYes(readLine, prompt) {
2496
+ process.stdout.write(`${prompt} [y/N] `);
2497
+ const answer = (await readLine()).trim().toLowerCase();
2498
+ return answer === "y" || answer === "yes";
2499
+ }
2500
+ function removePath(p) {
2501
+ if (!existsSync6(p)) return false;
2502
+ rmSync3(p, { recursive: true, force: true });
2503
+ return true;
2504
+ }
2505
+ var uninstallCommand = defineCommand18({
2506
+ meta: {
2507
+ name: "uninstall",
2508
+ description: "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"
2509
+ },
2510
+ args: {
2511
+ home: { type: "string", description: "Override BAZILION_HOME" },
2512
+ yes: {
2513
+ type: "boolean",
2514
+ description: "Skip confirmations (data tier only unless --all is set)"
2515
+ },
2516
+ all: {
2517
+ type: "boolean",
2518
+ description: "Also remove configs, logs, and skills (full wipe)"
2519
+ }
2520
+ },
2521
+ async run({ args }) {
2522
+ const paths = resolveCliPaths(args.home);
2523
+ const dbFile = join4(paths.home, "bazilion.db");
2524
+ const profilesDir = join4(paths.home, "profiles");
2525
+ const agentsDir = join4(paths.home, "agents");
2526
+ const groupsDir = join4(paths.home, "groups");
2527
+ const skillsDir = join4(paths.home, "skills");
2528
+ const logsDir = join4(paths.home, "logs");
2529
+ if (!existsSync6(paths.home)) {
2530
+ console.log(`nothing to remove: ${paths.home} does not exist`);
2531
+ return;
2532
+ }
2533
+ console.log(`about to uninstall bazilion at ${paths.home}`);
2534
+ console.log("");
2535
+ const dataTargets = [
2536
+ dbFile,
2537
+ `${dbFile}-wal`,
2538
+ `${dbFile}-shm`,
2539
+ profilesDir,
2540
+ agentsDir,
2541
+ groupsDir
2542
+ ];
2543
+ const needsPrompt = !args.yes;
2544
+ const readLine = needsPrompt ? makeLineReader() : null;
2545
+ const wipeData = args.yes || await askYes(
2546
+ readLine,
2547
+ "remove DB + agent / profile / workspace data?"
2548
+ );
2549
+ if (!wipeData) {
2550
+ console.log("aborted");
2551
+ process.stdin.pause();
2552
+ return;
2553
+ }
2554
+ const wipeAll = args.all || (args.yes ? false : await askYes(
2555
+ readLine,
2556
+ "also remove configs, logs, and skills? (full wipe of ~/.bazilion)"
2557
+ ));
2558
+ process.stdin.pause();
2559
+ for (const p of dataTargets) {
2560
+ if (removePath(p)) console.log(`removed ${p}`);
2561
+ }
2562
+ if (wipeAll) {
2563
+ const configTargets = [paths.authFile, logsDir, skillsDir];
2564
+ for (const p of configTargets) {
2565
+ if (removePath(p)) console.log(`removed ${p}`);
2566
+ }
2567
+ if (readdirSync2(paths.home).length === 0) {
2568
+ rmSync3(paths.home, { recursive: true, force: true });
2569
+ console.log(`removed ${paths.home}`);
2570
+ } else {
2571
+ console.log(`${paths.home} still has unmanaged files; left in place`);
2572
+ }
2573
+ } else {
2574
+ console.log("");
2575
+ console.log("kept: auth.json, logs/, skills/");
2576
+ console.log(`re-run 'bazilion serve' to recreate the DB when you're ready.`);
2577
+ }
2578
+ }
2579
+ });
2580
+
2581
+ // src/index.ts
2582
+ var VERSION = package_default.version;
2583
+ var main = defineCommand19({
2584
+ meta: {
2585
+ name: "bazilion",
2586
+ version: VERSION,
2587
+ description: "Multi-agent runtime"
2588
+ },
2589
+ subCommands: {
2590
+ login: loginCommand,
2591
+ profile: profileCommand,
2592
+ group: groupCommand,
2593
+ agent: agentCommand,
2594
+ skill: skillCommand,
2595
+ memory: memoryCommand,
2596
+ provider: providerCommand,
2597
+ send: sendCommand,
2598
+ inbox: inboxCommand,
2599
+ config: configCommand,
2600
+ serve: serveCommand,
2601
+ doctor: doctorCommand,
2602
+ backup: backupCommand,
2603
+ trigger: triggerCommand,
2604
+ token: tokenCommand,
2605
+ auth: authCommand,
2606
+ uninstall: uninstallCommand
2607
+ }
2608
+ });
2609
+ main.subCommands.completion = completionCommand(main);
2610
+ async function resolveSubCommand(cmd, rawArgs, parent) {
2611
+ const subs = cmd.subCommands;
2612
+ if (subs && Object.keys(subs).length > 0) {
2613
+ const idx = rawArgs.findIndex((a) => !a.startsWith("-"));
2614
+ const name = idx >= 0 ? rawArgs[idx] : void 0;
2615
+ if (name && subs[name]) {
2616
+ return resolveSubCommand(subs[name], rawArgs.slice(idx + 1), cmd);
2617
+ }
2618
+ }
2619
+ return [cmd, parent];
2620
+ }
2621
+ function printError(err) {
2622
+ if (err instanceof ApiClientError) {
2623
+ console.error(`error: ${err.body.error}`);
2624
+ if (err.status === 401) {
2625
+ console.error(' hint: token mismatch. Check ~/.bazilion/auth.json "token"');
2626
+ console.error(' or re-run "bazilion login" for a remote server.');
2627
+ } else if (err.status === 403) {
2628
+ console.error(" hint: request was rejected by the server. If you hit this from a");
2629
+ console.error(" fresh CLI build, check that BAZILION_SERVER matches the");
2630
+ console.error(" server origin exactly (scheme + host + port).");
2631
+ }
2632
+ return;
2633
+ }
2634
+ const msg = err instanceof Error ? err.message : String(err);
2635
+ console.error(`error: ${msg}`);
2636
+ const cause = err instanceof Error ? err.cause : void 0;
2637
+ const code = cause?.code;
2638
+ if (code === "ECONNREFUSED" || /ECONNREFUSED/.test(msg)) {
2639
+ console.error(' hint: the bazilion server is not running. Start it with "bazilion serve"');
2640
+ console.error(" or point BAZILION_SERVER at a running instance.");
2641
+ } else if (code === "ENOTFOUND" || /ENOTFOUND/.test(msg)) {
2642
+ console.error(" hint: host not found. Check BAZILION_SERVER / ~/.bazilion/auth.json.");
2643
+ }
2644
+ }
2645
+ function printTopLevelHelp() {
2646
+ console.log(`Multi-agent runtime (bazilion v${VERSION})`);
2647
+ console.log("");
2648
+ console.log("USAGE bazilion <command> [args]");
2649
+ console.log("");
2650
+ const groups = [
2651
+ {
2652
+ title: "setup",
2653
+ items: [
2654
+ ["serve", "Start the bazilion daemon (auto-bootstraps ~/.bazilion on first run)"],
2655
+ ["doctor", "Diagnose your bazilion install"],
2656
+ ["uninstall", "Wipe bazilion state from ~/.bazilion (or BAZILION_HOME)"]
2657
+ ]
2658
+ },
2659
+ {
2660
+ title: "catalog",
2661
+ items: [
2662
+ ["profile", "Manage profiles (templates agents are spawned from)"],
2663
+ ["group", "Manage groups (collaboration context \u2014 filesystem root + USER.md + roster)"],
2664
+ ["skill", "Manage the skill library"],
2665
+ ["provider", "Manage and test LLM providers"],
2666
+ ["config", "Manage service config (credentials + URLs/IDs)"],
2667
+ ["auth", "OAuth provider sign-in (ChatGPT account, \u2026)"]
2668
+ ]
2669
+ },
2670
+ {
2671
+ title: "agents",
2672
+ items: [
2673
+ ["agent", "Spawn, list, chat, archive agents"],
2674
+ ["memory", "Read/write a group's shared memory"],
2675
+ ["send", "Send a message from one agent to another"],
2676
+ ["inbox", "Inspect agent inboxes"],
2677
+ ["trigger", "Manage agent heartbeats / cron triggers"]
2678
+ ]
2679
+ },
2680
+ {
2681
+ title: "ops",
2682
+ items: [["backup", "Download a tar.gz backup of ~/.bazilion"]]
2683
+ },
2684
+ {
2685
+ title: "remote",
2686
+ items: [
2687
+ ["login", "Save a remote bazilion server + token pair to auth.json"],
2688
+ ["token", "Manage web tokens for API/CLI clients"]
2689
+ ]
2690
+ },
2691
+ {
2692
+ title: "shell",
2693
+ items: [["completion", "Print shell completion script (bash | zsh | fish)"]]
2694
+ }
2695
+ ];
2696
+ const nameWidth = 12;
2697
+ for (const g of groups) {
2698
+ console.log(` ${g.title}`);
2699
+ for (const [name, desc] of g.items) {
2700
+ console.log(` ${name.padEnd(nameWidth)}${desc}`);
2701
+ }
2702
+ console.log("");
2703
+ }
2704
+ console.log("Use `bazilion <command> --help` for more information about a command.");
2705
+ }
2706
+ async function entry() {
2707
+ const rawArgs = process.argv.slice(2);
2708
+ try {
2709
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
2710
+ const firstPositional = rawArgs.find((a) => !a.startsWith("-"));
2711
+ if (!firstPositional) {
2712
+ printTopLevelHelp();
2713
+ process.exit(0);
2714
+ }
2715
+ const [target, parent] = await resolveSubCommand(main, rawArgs);
2716
+ await showUsage(target, parent);
2717
+ process.exit(0);
2718
+ }
2719
+ if (rawArgs.length === 1 && (rawArgs[0] === "--version" || rawArgs[0] === "-v")) {
2720
+ console.log(VERSION);
2721
+ return;
2722
+ }
2723
+ await runCommand(main, { rawArgs });
2724
+ } catch (err) {
2725
+ printError(err);
2726
+ process.exit(1);
2727
+ }
2728
+ }
2729
+ entry();
2730
+ //# sourceMappingURL=cli.js.map