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.
- package/README.md +53 -152
- package/dist/cli.js +2730 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon.js +5888 -0
- package/dist/daemon.js.map +1 -0
- package/dist/worker.js +1830 -0
- package/dist/worker.js.map +1 -0
- package/package.json +57 -28
- package/.understand-anything/.understandignore +0 -25
- package/.understand-anything/fingerprints.json +0 -14267
- package/.understand-anything/knowledge-graph.json +0 -18128
- package/.understand-anything/meta.json +0 -6
- package/CLAUDE.md +0 -164
- package/apps/cli/package.json +0 -21
- package/apps/cli/src/auth-file.ts +0 -18
- package/apps/cli/src/client.ts +0 -37
- package/apps/cli/src/columnize.ts +0 -32
- package/apps/cli/src/commands/agent.ts +0 -574
- package/apps/cli/src/commands/auth.ts +0 -110
- package/apps/cli/src/commands/backup.ts +0 -135
- package/apps/cli/src/commands/completion.ts +0 -155
- package/apps/cli/src/commands/config.ts +0 -95
- package/apps/cli/src/commands/doctor.ts +0 -131
- package/apps/cli/src/commands/group.ts +0 -132
- package/apps/cli/src/commands/inbox.ts +0 -82
- package/apps/cli/src/commands/login.ts +0 -73
- package/apps/cli/src/commands/memory.ts +0 -106
- package/apps/cli/src/commands/profile.ts +0 -259
- package/apps/cli/src/commands/provider.ts +0 -170
- package/apps/cli/src/commands/send.ts +0 -24
- package/apps/cli/src/commands/serve.ts +0 -89
- package/apps/cli/src/commands/skill.ts +0 -120
- package/apps/cli/src/commands/token.ts +0 -148
- package/apps/cli/src/commands/trigger.ts +0 -129
- package/apps/cli/src/commands/uninstall.ts +0 -156
- package/apps/cli/src/index.ts +0 -196
- package/apps/cli/src/paths.ts +0 -12
- package/apps/cli/test/agent.test.ts +0 -213
- package/apps/cli/test/backup.test.ts +0 -95
- package/apps/cli/test/chat.test.ts +0 -539
- package/apps/cli/test/columnize.test.ts +0 -29
- package/apps/cli/test/completion.test.ts +0 -45
- package/apps/cli/test/config-page.test.ts +0 -151
- package/apps/cli/test/group.test.ts +0 -74
- package/apps/cli/test/helpers.ts +0 -70
- package/apps/cli/test/inbox-autodeliver.test.ts +0 -143
- package/apps/cli/test/inbox.test.ts +0 -147
- package/apps/cli/test/memory.test.ts +0 -69
- package/apps/cli/test/profile.test.ts +0 -110
- package/apps/cli/test/send.test.ts +0 -30
- package/apps/cli/test/server-fixture.ts +0 -212
- package/apps/cli/test/session-head.test.ts +0 -45
- package/apps/cli/test/skill.test.ts +0 -128
- package/apps/cli/test/token.test.ts +0 -109
- package/apps/cli/test/trigger.test.ts +0 -245
- package/apps/cli/tsconfig.json +0 -4
- package/apps/daemon/package.json +0 -31
- package/apps/daemon/src/app.ts +0 -41
- package/apps/daemon/src/core/agent/archive.ts +0 -8
- package/apps/daemon/src/core/agent/delete.ts +0 -30
- package/apps/daemon/src/core/agent/resolve.ts +0 -31
- package/apps/daemon/src/core/agent/spawn.ts +0 -95
- package/apps/daemon/src/core/agent/unarchive.ts +0 -11
- package/apps/daemon/src/core/availableModels.ts +0 -58
- package/apps/daemon/src/core/db/client.ts +0 -113
- package/apps/daemon/src/core/db/migrate.ts +0 -41
- package/apps/daemon/src/core/db/migrations/0001_init.sql +0 -179
- package/apps/daemon/src/core/group/delete.ts +0 -21
- package/apps/daemon/src/core/group/register.ts +0 -68
- package/apps/daemon/src/core/index.ts +0 -71
- package/apps/daemon/src/core/paths.ts +0 -56
- package/apps/daemon/src/core/profile/create.ts +0 -78
- package/apps/daemon/src/core/profile/delete.ts +0 -26
- package/apps/daemon/src/core/profile/identity.ts +0 -70
- package/apps/daemon/src/core/profile/load.ts +0 -45
- package/apps/daemon/src/core/profile/seed.ts +0 -74
- package/apps/daemon/src/core/profile/templates.ts +0 -60
- package/apps/daemon/src/core/profile/update.ts +0 -57
- package/apps/daemon/src/core/profile/validate.ts +0 -9
- package/apps/daemon/src/core/repos/agents.ts +0 -202
- package/apps/daemon/src/core/repos/config.ts +0 -78
- package/apps/daemon/src/core/repos/groups.ts +0 -55
- package/apps/daemon/src/core/repos/messages.ts +0 -127
- package/apps/daemon/src/core/repos/profiles.ts +0 -83
- package/apps/daemon/src/core/repos/providerModels.ts +0 -58
- package/apps/daemon/src/core/repos/providerState.ts +0 -37
- package/apps/daemon/src/core/repos/secrets.ts +0 -145
- package/apps/daemon/src/core/repos/skillMeta.ts +0 -49
- package/apps/daemon/src/core/repos/triggers.ts +0 -101
- package/apps/daemon/src/core/repos/webTokens.ts +0 -87
- package/apps/daemon/src/core/secrets.ts +0 -65
- package/apps/daemon/src/core/services.ts +0 -264
- package/apps/daemon/src/core/skills/discover.ts +0 -28
- package/apps/daemon/src/core/skills/import.ts +0 -136
- package/apps/daemon/src/core/skills/parse.ts +0 -52
- package/apps/daemon/src/core/skills/resolve.ts +0 -50
- package/apps/daemon/src/index.ts +0 -45
- package/apps/daemon/src/lib/agent-cancel.ts +0 -48
- package/apps/daemon/src/lib/agent-id.ts +0 -13
- package/apps/daemon/src/lib/agent-turn.ts +0 -56
- package/apps/daemon/src/lib/api-key.ts +0 -56
- package/apps/daemon/src/lib/auth.ts +0 -41
- package/apps/daemon/src/lib/cron.ts +0 -93
- package/apps/daemon/src/lib/ctx.ts +0 -80
- package/apps/daemon/src/lib/messaging-host.ts +0 -34
- package/apps/daemon/src/lib/middleware-auth.ts +0 -52
- package/apps/daemon/src/lib/scheduler.ts +0 -294
- package/apps/daemon/src/routes/agents.ts +0 -772
- package/apps/daemon/src/routes/auth-login.ts +0 -193
- package/apps/daemon/src/routes/config.ts +0 -267
- package/apps/daemon/src/routes/groups.ts +0 -133
- package/apps/daemon/src/routes/messages.ts +0 -29
- package/apps/daemon/src/routes/misc.ts +0 -239
- package/apps/daemon/src/routes/profiles.ts +0 -197
- package/apps/daemon/src/routes/skills.ts +0 -123
- package/apps/daemon/src/routes/triggers.ts +0 -29
- package/apps/daemon/src/runtime/auth/openai-codex.ts +0 -121
- package/apps/daemon/src/runtime/auto-reply/heartbeat.ts +0 -31
- package/apps/daemon/src/runtime/index.ts +0 -77
- package/apps/daemon/src/runtime/memory/files.ts +0 -103
- package/apps/daemon/src/runtime/memory/qmd.ts +0 -152
- package/apps/daemon/src/runtime/memory/types.ts +0 -16
- package/apps/daemon/src/runtime/pi/events.ts +0 -173
- package/apps/daemon/src/runtime/pi/session.ts +0 -536
- package/apps/daemon/src/runtime/pi/tools.ts +0 -85
- package/apps/daemon/src/runtime/providers/catalog.ts +0 -145
- package/apps/daemon/src/runtime/providers/pi-adapter.ts +0 -272
- package/apps/daemon/src/runtime/providers/registry.ts +0 -374
- package/apps/daemon/src/runtime/providers/retry.ts +0 -176
- package/apps/daemon/src/runtime/providers/types.ts +0 -33
- package/apps/daemon/src/runtime/session/prompt.ts +0 -83
- package/apps/daemon/src/runtime/tools/bootstrap.ts +0 -22
- package/apps/daemon/src/runtime/tools/home.ts +0 -114
- package/apps/daemon/src/runtime/tools/memory.ts +0 -81
- package/apps/daemon/src/runtime/tools/messaging.ts +0 -127
- package/apps/daemon/src/runtime/tools/registry.ts +0 -29
- package/apps/daemon/src/runtime/tools/types.ts +0 -13
- package/apps/daemon/src/runtime/tools/web-extract.ts +0 -110
- package/apps/daemon/src/runtime/tools/web-ssrf.ts +0 -245
- package/apps/daemon/src/runtime/tools/web.ts +0 -273
- package/apps/daemon/src/runtime/worker/entry.ts +0 -221
- package/apps/daemon/src/runtime/worker/ipc-protocol.ts +0 -75
- package/apps/daemon/src/runtime/worker/spawn.ts +0 -249
- package/apps/daemon/test/core/agents.test.ts +0 -319
- package/apps/daemon/test/core/available-models.test.ts +0 -63
- package/apps/daemon/test/core/config.test.ts +0 -99
- package/apps/daemon/test/core/groups.test.ts +0 -63
- package/apps/daemon/test/core/helpers.ts +0 -50
- package/apps/daemon/test/core/identity.test.ts +0 -85
- package/apps/daemon/test/core/migrations.test.ts +0 -83
- package/apps/daemon/test/core/profiles.test.ts +0 -182
- package/apps/daemon/test/core/provider-models.test.ts +0 -57
- package/apps/daemon/test/core/provider-state.test.ts +0 -36
- package/apps/daemon/test/core/skill-meta.test.ts +0 -45
- package/apps/daemon/test/core/skills.test.ts +0 -271
- package/apps/daemon/test/core/triggers.test.ts +0 -182
- package/apps/daemon/test/core/web-tokens.test.ts +0 -79
- package/apps/daemon/test/cron.test.ts +0 -90
- package/apps/daemon/test/runtime/heartbeat.test.ts +0 -34
- package/apps/daemon/test/runtime/memory-qmd.test.ts +0 -97
- package/apps/daemon/test/runtime/memory.test.ts +0 -78
- package/apps/daemon/test/runtime/messaging.test.ts +0 -213
- package/apps/daemon/test/runtime/mock-server.ts +0 -65
- package/apps/daemon/test/runtime/openai-codex-auth.test.ts +0 -116
- package/apps/daemon/test/runtime/providers.test.ts +0 -306
- package/apps/daemon/test/runtime/retry.test.ts +0 -191
- package/apps/daemon/test/runtime/session-head.test.ts +0 -90
- package/apps/daemon/test/runtime/tools-home.test.ts +0 -102
- package/apps/daemon/test/runtime/tools-web.test.ts +0 -206
- package/apps/daemon/tsconfig.json +0 -4
- package/apps/mobile/README.md +0 -60
- package/apps/mobile/app/_layout.tsx +0 -58
- package/apps/mobile/app/agents/[id]/chat.tsx +0 -486
- package/apps/mobile/app/agents/[id]/index.tsx +0 -166
- package/apps/mobile/app/agents/index.tsx +0 -212
- package/apps/mobile/app/index.tsx +0 -21
- package/apps/mobile/app/pair.tsx +0 -226
- package/apps/mobile/app/settings.tsx +0 -419
- package/apps/mobile/app.json +0 -49
- package/apps/mobile/assets/adaptive-icon.png +0 -0
- package/apps/mobile/assets/favicon.png +0 -0
- package/apps/mobile/assets/icon.png +0 -0
- package/apps/mobile/assets/splash-icon.png +0 -0
- package/apps/mobile/babel.config.js +0 -6
- package/apps/mobile/metro.config.js +0 -28
- package/apps/mobile/package.json +0 -44
- package/apps/mobile/src/auth.ts +0 -66
- package/apps/mobile/src/pair-url.ts +0 -48
- package/apps/mobile/src/theme-context.tsx +0 -88
- package/apps/mobile/src/theme.ts +0 -135
- package/apps/mobile/test/pair-url.test.ts +0 -46
- package/apps/mobile/tsconfig.json +0 -23
- package/apps/web/components.json +0 -25
- package/apps/web/package.json +0 -39
- package/apps/web/public/baziu.svg +0 -8
- package/apps/web/src/components/AgentTabs.tsx +0 -45
- package/apps/web/src/components/BaziuLogo.tsx +0 -21
- package/apps/web/src/components/ChatPane.tsx +0 -1033
- package/apps/web/src/components/ConfigTabs.tsx +0 -29
- package/apps/web/src/components/CopyButton.tsx +0 -68
- package/apps/web/src/components/CreateGroupDialog.tsx +0 -127
- package/apps/web/src/components/FieldRow.tsx +0 -94
- package/apps/web/src/components/Footer.tsx +0 -10
- package/apps/web/src/components/PawIcon.tsx +0 -15
- package/apps/web/src/components/Sidebar.tsx +0 -287
- package/apps/web/src/components/SpawnDialog.tsx +0 -129
- package/apps/web/src/components/ThemeToggle.tsx +0 -75
- package/apps/web/src/components/TopNav.tsx +0 -34
- package/apps/web/src/components/ui/button.tsx +0 -67
- package/apps/web/src/components/ui/card.tsx +0 -103
- package/apps/web/src/components/ui/checkbox.tsx +0 -31
- package/apps/web/src/components/ui/dialog.tsx +0 -168
- package/apps/web/src/components/ui/input.tsx +0 -19
- package/apps/web/src/components/ui/label.tsx +0 -22
- package/apps/web/src/components/ui/radio-group.tsx +0 -44
- package/apps/web/src/components/ui/select.tsx +0 -192
- package/apps/web/src/components/ui/separator.tsx +0 -26
- package/apps/web/src/components/ui/table.tsx +0 -116
- package/apps/web/src/components/ui/tabs.tsx +0 -88
- package/apps/web/src/components/ui/textarea.tsx +0 -18
- package/apps/web/src/lib/auth.ts +0 -50
- package/apps/web/src/lib/daemon-client.ts +0 -34
- package/apps/web/src/lib/md.ts +0 -45
- package/apps/web/src/lib/utils.ts +0 -6
- package/apps/web/src/lib/wire-constants.ts +0 -27
- package/apps/web/src/routeTree.gen.ts +0 -408
- package/apps/web/src/router.tsx +0 -20
- package/apps/web/src/routes/__root.tsx +0 -123
- package/apps/web/src/routes/agents/$id/inbox.tsx +0 -207
- package/apps/web/src/routes/agents/$id/index.tsx +0 -527
- package/apps/web/src/routes/agents/$id/triggers.tsx +0 -239
- package/apps/web/src/routes/agents/index.tsx +0 -265
- package/apps/web/src/routes/api/$.ts +0 -88
- package/apps/web/src/routes/config/index.tsx +0 -315
- package/apps/web/src/routes/config/services.tsx +0 -49
- package/apps/web/src/routes/config/tokens.tsx +0 -192
- package/apps/web/src/routes/groups/$id/index.tsx +0 -153
- package/apps/web/src/routes/groups/$id/memory.tsx +0 -321
- package/apps/web/src/routes/groups/index.tsx +0 -191
- package/apps/web/src/routes/index.tsx +0 -133
- package/apps/web/src/routes/login.tsx +0 -63
- package/apps/web/src/routes/profiles/$id.tsx +0 -549
- package/apps/web/src/routes/profiles/index.tsx +0 -458
- package/apps/web/src/routes/skills/index.tsx +0 -297
- package/apps/web/src/routes/welcome.tsx +0 -61
- package/apps/web/src/styles.css +0 -449
- package/apps/web/tsconfig.json +0 -25
- package/apps/web/vite.config.ts +0 -25
- package/biome.json +0 -23
- package/docs/agent-engine.md +0 -219
- package/docs/architecture.md +0 -627
- package/docs/backlog/README.md +0 -42
- package/docs/backlog/draft/BAZ-001-a2a-federation-spike.md +0 -125
- package/docs/openclaw-reference.md +0 -210
- package/packages/api-types/package.json +0 -11
- package/packages/api-types/src/entities.ts +0 -146
- package/packages/api-types/src/events.ts +0 -55
- package/packages/api-types/src/index.ts +0 -488
- package/packages/api-types/src/memory.ts +0 -15
- package/packages/client/package.json +0 -13
- package/packages/client/src/index.ts +0 -117
- package/pnpm-workspace.yaml +0 -3
- package/tsconfig.base.json +0 -23
- package/tsconfig.json +0 -11
- package/vitest.config.ts +0 -22
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).
|
package/apps/cli/package.json
DELETED
|
@@ -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
|
-
}
|
package/apps/cli/src/client.ts
DELETED
|
@@ -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
|
-
}
|