bazilion 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +5888 -0
  5. package/dist/daemon.js.map +1 -0
  6. package/dist/worker.js +1830 -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
@@ -1,6 +0,0 @@
1
- {
2
- "lastAnalyzedAt": "2026-05-22T09:05:00.000Z",
3
- "gitCommitHash": "663cf6bac528c56e62eb2f5d8e46d294f3f89090",
4
- "version": "1.0.0",
5
- "analyzedFiles": 250
6
- }
package/CLAUDE.md DELETED
@@ -1,164 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Dev commands
6
-
7
- Node 22.12+ required (for built-in `node:sqlite` + `.ts` ecosystem). pnpm 10+ as the package manager. Everything runs via `tsx`, which is pinned as a root dev-dep — no separate install.
8
-
9
- ```sh
10
- pnpm install
11
- pnpm test # vitest run across the whole tree
12
- pnpm typecheck # tsc --noEmit (excludes apps/web — see below)
13
- pnpm lint # biome check
14
- pnpm format # biome check --write
15
- ```
16
-
17
- Running a single test: `pnpm vitest run apps/daemon/test/core/agents.test.ts` (or `pnpm vitest -t 'pattern'`).
18
-
19
- Running the CLI locally (no build step — `tsx` executes `.ts` directly):
20
-
21
- ```sh
22
- pnpm tsx apps/cli/src/index.ts <subcommand>
23
- # e.g. pnpm tsx apps/cli/src/index.ts agent chat <uuid>
24
- # pnpm tsx apps/cli/src/index.ts serve # boots the daemon (web UI runs separately)
25
- ```
26
-
27
- `README.md` has the full user-facing quickstart (`bazilion serve` auto-bootstraps `~/.bazilion` on first run → start the web UI on :4322 → finish first-run setup on /config → spawn from the auto-seeded `default` profile).
28
-
29
- ## Architecture
30
-
31
- pnpm workspaces monorepo. **Four apps** (cli, daemon, web, mobile), **two packages** (api-types, client).
32
-
33
- The **daemon** (`apps/daemon`) is the single owner of `~/.bazilion` AND the LLM/tool stack. It's also the only place server-side code lives — there's no `@bazilion/core` or `@bazilion/runtime` package; that code is internal to the daemon under `apps/daemon/src/core/` (DB schema, repos, domain ops, paths, secrets, services, skills) and `apps/daemon/src/runtime/` (pi adapter, providers, memory, tools, worker, sessions). Every other process — CLI, web frontend SSR, mobile app, future browser SPA — talks to the daemon over HTTP. **Workers spawned per turn don't hold their own DB handle either** — they receive pre-resolved data on stdin and round-trip live messaging back to the daemon over Node IPC.
34
-
35
- Three invariants:
36
-
37
- 1. **Nothing outside `apps/daemon` imports daemon-internal code at runtime.** Clients talk to the daemon over HTTP via `@bazilion/client` + `@bazilion/api-types`. The CLI's tests are the one pragmatic exception: they reach into `apps/daemon/src/...` via relative imports for setup/inspection. No other consumer should follow that pattern.
38
- 2. **The daemon owns the DB, scheduler, agent-cancel registry, secrets table, and the bootstrap token in auth.json.** Other processes are stateless clients.
39
- 3. **The daemon self-bootstraps on first `bazilion serve`** — there is no `bazilion init` command. `apps/daemon/src/lib/ctx.ts:bootstrap()` runs idempotently at startup: creates `~/.bazilion/{profiles,agents,skills,groups,logs}`, opens the DB, runs migrations, and (if `auth.json` is missing) mints a bootstrap web_tokens row + writes the plaintext to `auth.json`.
40
-
41
- - **`packages/api-types`** — **hermetic** wire-shape package. Owns the canonical type definitions for everything that crosses the HTTP/IPC wire: entity shapes (`Agent`, `Group`, `Profile`, `Message`, `WebToken`, `AgentTrigger`, `ResolvedAgent`, `LoadedProfile`, `OpenAICodexStatus`, …) in `entities.ts`, chat/provider events (`ChatFrame`, `SessionEvent`, `ProviderMessage`, `ToolCall`, `ToolDef`) in `events.ts`, memory wire types in `memory.ts`, and request/response envelopes + `PROFILE_FILES` in `index.ts`. **Zero deps** — no node-only modules, no daemon code. The daemon imports its entity/wire types FROM here; that's what keeps `apps/web`, `apps/mobile`, and `@bazilion/client` from ever reaching Node-only code (`node:sqlite`, undici, pi-ai, the worker spawner).
42
- - **`packages/client`** — HTTP client for **cross-origin consumers that need explicit auth headers**: the CLI today, a future React Native / mobile app tomorrow. Exports `createClient({ serverUrl, token })`, `ApiClientError`, `BazilionClient`. Pure `fetch` + `TextDecoder` + NDJSON stream async generator — no `node:*` imports, no node-only deps. `token` is `string | (() => string | Promise<string>)` so rotating credentials (OAuth refresh, mobile keychain reads) plug in without rebuilding the client; the package builds `Authorization: Bearer <token>` + `Origin: <serverUrl>` headers internally. `apps/cli/src/client.ts` wraps it with the Node-specific `loadClientConfig()` (reads `~/.bazilion/auth.json` + `BAZILION_SERVER`/`BAZILION_TOKEN` env via the CLI's local `apps/cli/src/{paths,auth-file}.ts` helpers). **Not used by `apps/web` browser-side code**: the web UI hits its own server same-origin with relative URLs, so the `bz_token` cookie auto-attaches.
43
-
44
- ### Auth model
45
-
46
- One token table (`web_tokens`), one source of truth in the daemon. `apps/daemon/src/lib/auth.ts` exposes `isValidToken(t)` (queries `web_tokens` only — there's no separate bootstrap path) and `extractBearer(header)`; `apps/daemon/src/lib/middleware-auth.ts` is the Hono middleware that gates every route. The middleware reads `Authorization: Bearer <t>` first, falls back to the `bz_token` cookie (via `hono/cookie`) — whichever the client sent, the same `isValidToken` lookup decides. Public paths (`/api/login`, `/api/health`) skip auth; setup-open paths (`/api/config/*`, `/api/auth/*`) skip the first-run gate.
47
-
48
- The bootstrap token is the plaintext stored in `~/.bazilion/auth.json` — written there by the daemon's self-bootstrap on first `bazilion serve` (`apps/daemon/src/lib/ctx.ts:bootstrap()`) alongside its hash inserted into `web_tokens` (label `bootstrap`). Both the CLI (loopback bearer) and the daemon (PBKDF2 seed for the secrets table) read this file. **Do not allow revoking the bootstrap row**: `DELETE /api/tokens/:id` rejects (409) when the requested id matches the auth-token's hash, and the web UI hides the revoke button for that row. Otherwise the operator could lock themselves out.
49
-
50
- **SSR cookie-forward**: server fns inside `apps/web/src/lib/daemon-client.ts` read `bz_token` via `getCookie` from `@tanstack/react-start/server` and forward it as a bearer header when calling the daemon — user identity is preserved end-to-end, daemon audit logs always reflect the actual user. **`daemon-client.ts` is server-only**: any module that ends up in the client bundle must import constants from `apps/web/src/lib/wire-constants.ts` instead (Vite's import-protection rejects `@tanstack/react-start/server` in client code). Native clients (CLI, mobile) send bearer via `@bazilion/client`. Tokens are minted + revoked with `bazilion token create/list/revoke` → `POST|GET|DELETE /api/tokens`. When adding a new auth surface, extend `isValidToken` — don't bypass it.
51
-
52
- ### Mobile / LAN notes
53
-
54
- The daemon binds `127.0.0.1:4321` by default. `bazilion serve --host 0.0.0.0 [--port N]` exposes it on the LAN for a mobile client; the serve command prints a loud warning in that case because the API is admin-level and TLS is the user's responsibility (Tailscale handles it for personal networks; reverse-proxy with TLS for anything else). The web frontend's `vite.config.ts` reads `WEB_HOST`/`WEB_PORT` so it can move off 4322 if needed. Pairing: `bazilion token create <label> --qr` mints a token and emits a `bazilion://pair?server=<url>&token=<t>` URL plus a terminal QR code (via `qrcode-terminal`). The server URL is auto-detected from the first non-loopback IPv4 interface when the CLI's stored URL is loopback-only; `--server <url>` overrides detection (useful for Tailscale hostnames). No gateway/relay has been built — the mobile app is expected to speak to the daemon directly over LAN/Tailscale/VPN.
55
-
56
- ### apps/mobile
57
-
58
- Expo SDK 54 + Expo Router 6 (file-based), React 19, RN 0.81, new-architecture-enabled. URL scheme `bazilion://` for deep-link pairing. Structure:
59
- - `app/` — file-based routes. `_layout.tsx` wraps the stack; `index.tsx` is the auth gate (loads credentials from `expo-secure-store`, redirects to `/pair` or `/agents`); `pair.tsx` is the camera+manual-paste pairing flow; `agents/index.tsx` is a FlatList of agents (pull-to-refresh, 401→/pair auto-unpair, header-level unpair button); `agents/[id].tsx` is an agent detail stub where chat will land next.
60
- - `src/pair-url.ts` — pure TS parser for `bazilion://pair?server=…&token=…`. RN-free, unit-tested by root vitest (`apps/mobile/test/pair-url.test.ts`).
61
- - `src/auth.ts` — `expo-secure-store` wrapper (`loadCredentials` / `saveCredentials` / `clearCredentials` / `verifyCredentials`) and a `clientFor(creds)` factory returning `@bazilion/client`'s `BazilionClient`.
62
- - `metro.config.js` — sets `watchFolders`/`nodeModulesPaths` so Metro resolves workspace packages through pnpm's symlink layout.
63
- - Excluded from root `tsconfig.json`, `biome.json`. Run `pnpm --filter @bazilion/mobile typecheck` for mobile-only TS checks. Run `pnpm --filter @bazilion/mobile start` for the Expo dev server.
64
- - `@bazilion/api-types` is hermetic — entity types and wire shapes are defined inline (`entities.ts`, `events.ts`, `memory.ts`); it has no dep on the daemon. That's what keeps mobile's TS checker out of Node-only code. Metro itself never sees these imports at runtime (babel's TS transform strips `import type` / `export type`) — but do not add a *value* import from `@bazilion/daemon` (or any daemon-internal path) to the mobile tree, or the bundle will explode.
65
-
66
- - **`apps/cli`** — thin citty-based CLI. Every subcommand except `serve` talks to the daemon over HTTP via `@bazilion/client`. No direct DB access in the CLI's runtime path. The two filesystem-level commands are: `serve` (boots `apps/daemon` directly — the daemon then auto-bootstraps `~/.bazilion`); `uninstall` (two-tier teardown: data wipe vs. full — operates on the filesystem so it works even when the daemon isn't running). Local helpers `apps/cli/src/paths.ts` (`resolveCliPaths`) and `apps/cli/src/auth-file.ts` (`readAuthFile` + `AuthFile` type) duplicate just enough of the daemon's path/auth utilities for these filesystem-touching commands. The web UI runs separately during dev: `cd apps/web && pnpm dev`. Remote daemon is opt-in via `BAZILION_SERVER` + `BAZILION_TOKEN` env vars; otherwise the client reads `auth.json` and hits `http://127.0.0.1:4321`.
67
-
68
- - **`apps/daemon`** — Hono on `@hono/node-server`, binds `127.0.0.1:4321` by default (`HOST`/`PORT` env override). Owns all server-side code under one roof:
69
- - `src/index.ts` — entry: eagerly calls `getCtx()` so the bootstrap message + auth.json land before the port binds, then starts Hono.
70
- - `src/lib/` — daemon-only glue: `ctx.ts` (singleton + self-bootstrap), `middleware-auth.ts`, `auth.ts`, `agent-cancel.ts`, `agent-id.ts`, `agent-turn.ts`, `api-key.ts`, `cron.ts`, `messaging-host.ts`, `scheduler.ts`.
71
- - `src/routes/` — HTTP routes by resource family: `agents.ts` (CRUD + group + skills + triggers + messages + sessions + chat NDJSON + `/cancel`), `groups.ts` (CRUD + USER.md + per-group shared memory at `/api/groups/:slug/memory*`), `profiles.ts`, `skills.ts`, `triggers.ts`, `messages.ts`, `config.ts`, `auth-login.ts` (ChatGPT OAuth + `/providers/test` + `/login`), `misc.ts` (`/health`, `/backup`, `/tokens`).
72
- - `src/core/` — what used to be `packages/core`: SQLite schema + migrations (`db/`), repos (`repos/`), domain ops (`agent/`, `group/`, `profile/`, `skills/`), `paths.ts`, `secrets.ts`, `services.ts`, `availableModels.ts`. Barrel export at `src/core/index.ts`.
73
- - `src/runtime/` — what used to be `packages/runtime`: pi-coding-agent integration (`pi/`), provider adapters (`providers/`), memory backends (`memory/`), Bazilion-specific tools (`tools/`), per-turn worker subprocess (`worker/{entry,spawn,ipc-protocol}.ts`), heartbeat helpers (`auto-reply/`), OpenAI Codex OAuth (`auth/`). Barrel export at `src/runtime/index.ts`.
74
- - Auth + first-run middleware (`src/lib/middleware-auth.ts`) gates every route; public paths whitelisted inside the middleware. The daemon installs its own SIGINT/SIGTERM handlers and shuts the HTTP server gracefully.
75
- - **`apps/web`** — TanStack Start (React 19 + Vite 7) frontend, **daemon-only client**. The canonical end-user UI. File-based routes under `src/routes/`: `__root.tsx` (root layout + `beforeLoad` auth gate), `index.tsx`, `login.tsx`, `welcome.tsx`, `agents/{index,$id/{index,inbox,triggers}}.tsx`, `profiles/{index,$id}.tsx`, `groups/{index,$id/{index,memory}}.tsx`, `skills/index.tsx`, `config/{index,services,tokens}.tsx`, `api/$.ts` (catch-all proxy). Tailwind v4 (CSS-first) + shadcn/ui. SSR loaders use `apps/web/src/lib/daemon-client.ts` (server-only) inside `createServerFn` handlers; that helper reads the request's `bz_token` cookie and forwards it as `Authorization: Bearer …` to `http://127.0.0.1:4321` (overridable via `BAZILION_DAEMON`). Browser fetches hit relative `/api/*` URLs that pass through the catch-all reverse proxy (cookie→bearer translation, streaming-capable for chat NDJSON). The dev server binds `WEB_PORT` (default 4322) — pair with `bazilion serve` on 4321. **CLI/web parity is mandatory**: every HTTP endpoint must have both a CLI surface and a web UI surface. Chat markdown is rendered via `marked` + DOMPurify; styles for the `.md-content` class live in `apps/web/src/styles.css` (without them, Tailwind preflight strips list markers, header sizes, code styling, etc).
76
-
77
- ### SQLite driver
78
-
79
- `apps/daemon/src/core/db/client.ts` uses `node:sqlite` (Node 22+ built-in). `node:sqlite` has no callable `transaction()` wrapper, so the wrapper implements manual `BEGIN/COMMIT/ROLLBACK` in its `transaction()` method. Don't look for a `bun:sqlite` fallback — the project is Node-only.
80
-
81
- ### On-disk layout
82
-
83
- State lives in `~/.bazilion/` (overridable via `$BAZILION_HOME`):
84
-
85
- ```
86
- ~/.bazilion/
87
- bazilion.db # ALL DB state: entities + secrets + config (encrypted) + tokens
88
- auth.json # {token, remote?} — bootstrap bearer + optional CLI remote target
89
- groups/<slug>/ # collaboration root, mounted as cwd; may be a symlink (--link)
90
- memory/ # group-shared qmd index (.qmd-index.sqlite + markdown notes)
91
- ... project files / work product ...
92
- agents/<id>/ # agent's PRIVATE home — strictly outside the group tree
93
- SOUL.md / IDENTITY.md / AGENTS.md / TOOLS.md / HEARTBEAT.md / [BOOTSTRAP.md]
94
- sessions/<sessionId>.jsonl # pi's append-only transcript
95
- agent.json
96
- profiles/<id>/ # profile templates
97
- skills/<name>/SKILL.md # installed skills
98
- logs/
99
- ```
100
-
101
- Path resolution is centralized in `apps/daemon/src/core/paths.ts`. The `Paths` struct has `home`, `db`, `authFile`, `profilesDir`, `agentsDir`, `groupsDir`, `skillsDir`, `logsDir`, plus `agentDir(id)` / `groupDir(slug)` / `profileDir(id)` / `skillDir(name)` computed helpers. The CLI has its own minimal `apps/cli/src/paths.ts` (`resolveCliPaths` returns just `{home, authFile}`) for the filesystem-level commands (`uninstall`, `backup`, `login`, `token show-local`) — they don't need the full struct. **There is no longer a `configFile` field — `config.json` and `secrets.enc` were collapsed into the DB.** `bazilion uninstall` mirrors this layout as a two-tier teardown: data tier = DB + `profiles/` + `agents/` + `groups/`; full wipe adds `auth.json`, `logs/`, `skills/`. Symlinked groups (registered with `--link`) only have the slot under `~/.bazilion/groups/` removed; the symlink target is never touched.
102
-
103
- ### Group registration
104
-
105
- Groups always live at `~/.bazilion/groups/<slug>/`. The CLI (`bazilion group add <slug> [--link <target>]`) and the web `/groups` create form pass only the slug + optional name + optional link target; the daemon decides where the slot goes. `--link <abs-path>` materializes the slot as a symlink to an existing directory (the "agents working on my existing project tree" path); the target must exist and be a directory. Without `--link`, a fresh real directory is created. `groupRepo.get/list/insert(db, ..., paths)` derive `Group.path` from `paths.groupDir(id)` at read time — there is no `path` column anymore.
106
-
107
- ### Memory model
108
-
109
- Memory is **per-group**, shared across every agent in the group. The qmd backend lives at `<group.path>/memory/`; each turn's worker calls `qmdBackend(join(agent.group.path, 'memory'))`. The `memory_*` tool descriptions explicitly tell the LLM the store is shared and direct personal notes (persona quirks, preferences) to `home_write IDENTITY.md` instead. The schema's per-agent memory dir is gone — `spawnAgent` only creates `agents/<id>/sessions/`. External surfaces match the ownership: HTTP at `/api/groups/:slug/memory*`, web UI at `/groups/:slug/memory`, CLI at `bazilion memory <write|read|list|search|rm> <group-slug> ...`. There are no `/api/agents/:id/memory*` routes — clients always address the group.
110
-
111
- ### Worker subprocess + IPC
112
-
113
- Every chat turn runs in its own Node subprocess (`apps/daemon/src/runtime/worker/{entry,spawn,ipc-protocol}.ts`). The daemon's `apps/daemon/src/lib/agent-turn.ts:runAgentTurn`:
114
- 1. Resolves the agent + provider gate + merged secrets env in-process (the worker no longer holds a SQLite handle).
115
- 2. Pre-fetches the OAuth access token for `openai-codex` agents via `apps/daemon/src/lib/api-key.ts:resolveAgentApiKey` (env-key providers return `{}`).
116
- 3. Spawns the worker with `stdio: ['pipe', 'pipe', 'inherit', 'ipc']` — the IPC channel is what makes messaging tools work without a worker DB handle.
117
- 4. Sends `{agent, message, enabledProviders, apiKey?}` on stdin.
118
- 5. Line-parses NDJSON `ChatFrame`s from worker stdout and yields them.
119
- 6. Services worker `process.send({type:'rpc', method, args, id})` calls (the messaging-tool RPCs) by dispatching to `apps/daemon/src/lib/messaging-host.ts:createDbMessagingHost(db)` and replying with `child.send({type:'rpc-reply', id, ok, result|error})`.
120
-
121
- `SessionEvent` types: `user_message` / `assistant_message` / `assistant_delta` / `tool_call` / `tool_result` / `tool_error` / `error`. `ChatFrame` shapes: `{kind:'event', event}` / `{kind:'done', messages}` / `{kind:'fatal', error}`. **There is no `runId`, no `runs` table, no `events` table** — those were dropped along with the per-run audit metadata layer; pi's session JSONL files are the canonical transcript and the only persistent record of what an agent has said.
122
-
123
- Cancellation: keyed by **agentId** (not runId). The daemon's `apps/daemon/src/lib/agent-cancel.ts` registers an `AbortController` per active agent on each `runAgentTurn` start; `POST /api/agents/:id/cancel` aborts the controller, which SIGTERMs the worker (3 s grace → SIGKILL); the child's own SIGTERM handler aborts its internal controller so pi unwinds the provider fetch and emits an `error` event with `error: 'cancelled'` before exiting. CLI: `bazilion agent cancel <id>`. The worker also calls `process.disconnect()` in its `finally` so the IPC channel doesn't pin the event loop alive after the turn settles.
124
-
125
- See `docs/agent-engine.md` for the full turn-loop walkthrough.
126
-
127
- ### Providers
128
-
129
- Model strings are `provider:model` (e.g. `lmstudio:my-loaded-model`, `anthropic:claude-opus-4-6`, `gemini:gemini-2.0-flash-exp`, `openai-codex:gpt-5.3-codex`). `createProviderRegistry` + `loadProviderConfigFromEnv` in `apps/daemon/src/runtime/providers/registry.ts` resolve strings to `{ provider, model }`. Credentials come from env vars (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `LMSTUDIO_URL`/`LMSTUDIO_API_KEY`, `OLLAMA_URL`); plain API-key providers never touch the DB. The daemon's `mergeSecretsIntoEnv(db, authToken)` layers DB-stored secrets + plaintext config over `process.env` — this happens **server-side** per API request (chat, provider test, health) and again per worker spawn (the merged env is passed via `child_process.spawn`'s `env` option).
130
-
131
- **`openai-codex`** is the OAuth exception: credentials live as a JSON `{refresh, access, expires}` blob under the `OPENAI_CODEX_OAUTH` row of the `secrets` table. The provider registry's `apiKey` field is invoked as an async supplier so refreshes happen lazily on each chat() without rebuilding the cached Provider instance. Pass `{db, authToken}` as the second arg to `loadProviderConfigFromEnv(env, oauth?)` to enable it. For the worker subprocess specifically, `runAgentTurn` pre-fetches the initial access token via `resolveAgentApiKey` and passes it through `WorkerInput.apiKey` → `createBazilionSession({apiKey})`. The worker doesn't have a refresher wired — long turns that exceed the JWT lifetime fail; the daemon-side compact/context paths get full lazy refresh because they pass `withRefresher: true`.
132
-
133
- ### Secrets and config
134
-
135
- `secrets.enc` and `config.json` are gone. The DB has two tables:
136
-
137
- - **`secrets(key TEXT PK, envelope TEXT NOT NULL, updated_at INTEGER)`** — AES-256-GCM envelopes (salt+iv+tag+data hex JSON), one row per env-var-shaped key (`ANTHROPIC_API_KEY`, `OPENAI_CODEX_OAUTH`, …). Encryption key derived from `auth.json`'s `token` via PBKDF2-SHA256 100k. Same crypto as the previous file-based store; only the storage medium changed. Threat model is unchanged: anyone who can read both `bazilion.db` *and* `auth.json` can decrypt — the encryption guards against accidental exposure (cat'd dumps, screenshares), not against filesystem read.
138
- - **`config(key TEXT PK, value TEXT NOT NULL, updated_at INTEGER)`** — plaintext for env-var-shaped values that don't need confidentiality (server URLs, region slugs, project IDs). The `CONFIG_KEYS` allowlist (derived from `services.ts`) is enforced in `repos/config.ts` on writes.
139
-
140
- API in `apps/daemon/src/core/`: `openSecrets(db, password)` and `openConfig(db)` (ConfigStore + SecretsStore types). The daemon caches the auth token in `getCtx().authToken` so all routes can call `mergeSecretsIntoEnv(db, authToken)` without re-reading `auth.json`.
141
-
142
- ## Conventions
143
-
144
- - Biome formatter: single quotes, no semicolons, trailing commas, 2-space indent, 100-col width.
145
- - TS is strict with `noUncheckedIndexedAccess` and `verbatimModuleSyntax`. `.ts` extensions are required on all relative imports (`allowImportingTsExtensions: true`) — `tsx` and Vite both handle it.
146
- - `apps/web/` is excluded from the root `tsconfig.json` and from biome (it has its own Vite/TanStack-managed tooling). Run `pnpm --filter @bazilion/web typecheck` for web-only TS checks. The whole-tree `typecheck` intentionally skips it.
147
- - Migrations are numbered SQL files in `apps/daemon/src/core/db/migrations/`. The schema is consolidated into a single `0001_init.sql` (the project is alpha; we wiped the DB and collapsed the prior chain on every shape change rather than maintaining an ALTER chain). Add new migrations as new numbered files going forward; the runner is idempotent and runs from the daemon's self-bootstrap (`apps/daemon/src/lib/ctx.ts:bootstrap()`) on every startup. Existing installs pick new files up automatically.
148
-
149
- ## Already-shipped invariants (don't re-implement)
150
-
151
- - **Daemon = sole owner of `~/.bazilion`** — the worker subprocess delegates anything DB-backed (messaging tools, provider gate, agent resolution, secrets) back to the daemon over Node IPC + stdin. There is no per-worker SQLite handle.
152
- - **Groups = single filesystem root + USER.md + roster + shared memory.** One agent → one group. `groups.user_md` is a DB column (agents can't clobber it via `write`/`edit`). Groups always live under `~/.bazilion/groups/<slug>/` (real dir or symlink via `--link`).
153
- - **Memory is group-shared.** `qmdBackend(group.path/memory)` — every member writes to and reads from the same store. Personal notes go to `IDENTITY.md` via `home_write`.
154
- - **No runs/events tables, no stats CLI.** The runs/events audit layer was dropped in favor of pi's session JSONL files (which are the authoritative transcript). There is no `bazilion run list/show/cancel/prune` and no `bazilion stats`. Cancel is `bazilion agent cancel <id>` (keyed by agentId).
155
- - **Bootstrap auth lives in `auth.json`.** The daemon reads it once at startup (`getCtx().authToken`) and uses it as the PBKDF2 seed for the secrets table. The CLI reads it as its loopback bearer. The `bootstrap` row in `web_tokens` cannot be revoked — `DELETE /api/tokens/:id` rejects a hash match against the auth token.
156
- - **First-run gate** — `isSetupComplete(db)` returns true iff at least one enabled provider has ≥1 curated model. Web middleware redirects non-API routes to `/welcome` while the gate is closed; API routes return 409. Allowed prefixes during setup: `/welcome`, `/login`, `/config`, `/api/config`, `/api/auth`, `/api/health`, `/api/login`. Crossing the threshold triggers `ensureSetupSeeded(db, paths)` which creates the `default` profile (skillsMode: `'all'`) + `default` group (at `~/.bazilion/groups/default/`).
157
- - **Spawn-time skill override is gone.** Skills come from the profile only — `skillsMode: 'all'` attaches every installed skill at spawn, `'selected'` uses `profile_default_skills`. Per-agent tweaks happen post-spawn via `bazilion agent skill add/rm` (or the per-agent skills card on the detail page).
158
- - **Web client constants live in `apps/web/src/lib/wire-constants.ts`** (`DEFAULT_GROUP_ID`, `DEFAULT_PROFILE_ID`, `REASONING_LEVELS`). `apps/web/src/lib/daemon-client.ts` is server-only — Vite's import-protection rejects it from any client-bundled module.
159
- - **OpenClaw skill model: prompt-only.** Skills under `~/.bazilion/skills/<name>/` get their SKILL.md body injected into the system prompt of every agent they're attached to; helper scripts run via the agent's generic `bash` tool. No framework `entry:` extension, no trust gate.
160
- - **qmd memory backend** (`apps/daemon/src/runtime/memory/qmd.ts`) — wraps `@tobilu/qmd`'s `searchLex` (BM25) for all memory routes. One `.qmd-index.sqlite` per group. Hybrid/vector paths are intentionally not enabled (pulls `node-llama-cpp` and multi-GB GGUF models; excluded in `pnpm.onlyBuiltDependencies`).
161
- - **Heartbeats / cron triggers** (`agent_triggers` table; `apps/daemon/src/lib/scheduler.ts`) — in-process tick loop (default 5s, `BAZILION_SCHEDULER_TICK_MS`; disable with `BAZILION_SCHEDULER=off`) pinned to `globalThis[Symbol.for('bazilion.scheduler')]`. Interval kind uses `last_fired_at + every ≤ now` with `created_at` as baseline; cron kind parses 5-field expressions via `apps/daemon/src/lib/cron.ts`. Firing reuses `runAgentTurn`; `last_fired_at` is updated *before* the run kicks off so a restart mid-fire doesn't double-trigger. CLI: `bazilion trigger add|list|rm|enable|disable`.
162
- - **Inbox / messaging surfaces** — the `send_message` / `read_inbox` / `wait_for_reply` tools (`apps/daemon/src/runtime/tools/messaging.ts`) are wired with `MessagingHost` injection: in the daemon (compact/context routes) the host is `createDbMessagingHost(db)`; in the worker the host is `createIpcMessagingHost()` which proxies every method through Node IPC. Outside-the-loop surfaces: `GET /api/agents/:id/messages?unread=1` (list), `POST /api/agents/:id/messages` (now accepts `replyTo`), `GET|PATCH /api/messages/:id` (detail + mark-read). CLI: `bazilion inbox list <agent> [--unread]`, `inbox show <id>`, `inbox read <id>`. Web: `/agents/:id/inbox`.
163
- - **`web_fetch` hardening: Readability + markdown + cache + SSRF guard** — `@mozilla/readability` over `linkedom`, output as markdown (or text via `extract_mode`). SSRF guard at `apps/daemon/src/runtime/tools/web-ssrf.ts` blocks loopback/private/link-local + DNS rebinding (re-validates resolved IPs, pins them into undici's `Agent.connect.lookup`). 15-min in-memory LRU per `${mode}|${url}` (100-entry cap). UA spoofs desktop Safari. 20s default timeout, 3 max redirects.
164
- - **ChatGPT OAuth / `openai-codex` provider** — credentials in `secrets:OPENAI_CODEX_OAUTH`. CLI runs the loopback flow (port 1455) client-side and PUTs credentials to `/api/auth/openai`; web `/config` has a "Connect ChatGPT" card. `apps/daemon/src/lib/api-key.ts:resolveAgentApiKey` is the single helper every session-creating call site uses to pre-fetch the access token; for daemon-side sessions it also wires a refresher for mid-turn JWT swaps. Worker turns don't get the refresher today (they'd need a new IPC method).
@@ -1,21 +0,0 @@
1
- {
2
- "name": "@bazilion/cli",
3
- "version": "0.0.0",
4
- "private": true,
5
- "type": "module",
6
- "bin": {
7
- "bazilion": "./src/index.ts"
8
- },
9
- "dependencies": {
10
- "@bazilion/api-types": "workspace:*",
11
- "@bazilion/client": "workspace:*",
12
- "@mariozechner/pi-ai": "^0.69.0",
13
- "citty": "^0.1.6",
14
- "qrcode-terminal": "^0.12.0"
15
- },
16
- "devDependencies": {
17
- "@types/adm-zip": "^0.5.8",
18
- "@types/qrcode-terminal": "^0.12.2",
19
- "adm-zip": "^0.5.17"
20
- }
21
- }
@@ -1,18 +0,0 @@
1
- import { existsSync, readFileSync } from 'node:fs'
2
-
3
- export interface AuthFile {
4
- token: string
5
- remote?: { server: string; token: string } | null
6
- }
7
-
8
- export function readAuthFile(authFile: string): AuthFile {
9
- if (!existsSync(authFile)) {
10
- throw new Error(`${authFile} not found. Start the daemon with \`bazilion serve\` first.`)
11
- }
12
- const raw = readFileSync(authFile, 'utf8')
13
- const parsed = JSON.parse(raw) as Partial<AuthFile>
14
- if (typeof parsed.token !== 'string' || !parsed.token) {
15
- throw new Error(`${authFile} is missing the "token" field`)
16
- }
17
- return { token: parsed.token, remote: parsed.remote ?? null }
18
- }
@@ -1,37 +0,0 @@
1
- import { type BazilionClient, createClient as createPackageClient } from '@bazilion/client'
2
- import { readAuthFile } from './auth-file.ts'
3
- import { resolveCliPaths } from './paths.ts'
4
-
5
- export type { BazilionClient } from '@bazilion/client'
6
- export { ApiClientError } from '@bazilion/client'
7
-
8
- export interface ClientConfig {
9
- serverUrl: string
10
- token: string
11
- }
12
-
13
- export function loadClientConfig(): ClientConfig {
14
- const envUrl = process.env.BAZILION_SERVER
15
- const envToken = process.env.BAZILION_TOKEN
16
- if (envUrl && envToken) return { serverUrl: envUrl, token: envToken }
17
-
18
- const paths = resolveCliPaths()
19
- const auth = readAuthFile(paths.authFile)
20
- // `bazilion login` writes `remote`; when present it targets another host
21
- // (Tailscale, LAN). Env vars still win so CI / ad-hoc invocations can
22
- // override without editing auth.json.
23
- if (auth.remote?.server && auth.remote.token) {
24
- return {
25
- serverUrl: envUrl ?? auth.remote.server,
26
- token: auth.remote.token,
27
- }
28
- }
29
- return {
30
- serverUrl: envUrl ?? 'http://127.0.0.1:4321',
31
- token: auth.token,
32
- }
33
- }
34
-
35
- export function createClient(cfg: ClientConfig = loadClientConfig()): BazilionClient {
36
- return createPackageClient({ serverUrl: cfg.serverUrl, token: cfg.token })
37
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Render `rows` as space-aligned columns. All rows must have the same column
3
- * count; empty cells are treated as `""` for width purposes. Column spacing is
4
- * two spaces — wider than a tab, tighter than tabular CSV tooling expects.
5
- *
6
- * Used by list commands so `status` / `kind` / `name` columns don't jump when
7
- * one row is `idle` (4) and another is `archived` (8). Does not truncate —
8
- * long cells win the column width. Callers that want a bounded width should
9
- * slice before passing.
10
- */
11
- export function columnize(rows: string[][], gap = ' '): string[] {
12
- if (rows.length === 0) return []
13
- const colCount = rows[0]?.length ?? 0
14
- const widths: number[] = new Array<number>(colCount).fill(0)
15
- for (const row of rows) {
16
- for (let i = 0; i < colCount; i++) {
17
- const cell = row[i] ?? ''
18
- const prev = widths[i] ?? 0
19
- if (cell.length > prev) widths[i] = cell.length
20
- }
21
- }
22
- return rows.map((row) =>
23
- row
24
- .map((cell, i) => {
25
- // Don't pad the last column — trailing whitespace is pointless and
26
- // breaks `| wc`-style pipes.
27
- if (i === colCount - 1) return cell
28
- return (cell ?? '').padEnd(widths[i] ?? 0)
29
- })
30
- .join(gap),
31
- )
32
- }