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/docs/agent-engine.md
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
# Bazilion Agent Engine — Internals
|
|
2
|
-
|
|
3
|
-
Engineer-to-engineer walkthrough of how a chat turn actually runs, end to end.
|
|
4
|
-
|
|
5
|
-
> **What Bazilion vs. pi-coding-agent owns**: the per-turn session loop,
|
|
6
|
-
> transcript storage, compaction, tool execution, and provider retries are
|
|
7
|
-
> [pi-coding-agent](https://www.npmjs.com/package/@mariozechner/pi-coding-agent).
|
|
8
|
-
> Bazilion provides profiles, groups, skills, messaging, memory, the scheduler,
|
|
9
|
-
> the HTTP API (`apps/daemon`), the web UI (`apps/web`), and a thin bridge
|
|
10
|
-
> (`apps/daemon/src/runtime/pi/*`) that glues them together. The on-disk JSONL
|
|
11
|
-
> session file under `~/.bazilion/agents/<id>/sessions/` is the canonical
|
|
12
|
-
> transcript and the only persistent record — there is no separate `runs` /
|
|
13
|
-
> `events` audit table.
|
|
14
|
-
|
|
15
|
-
## 1. Request → subprocess boundary
|
|
16
|
-
|
|
17
|
-
A chat turn starts at `POST /api/agents/:id/chat` (the daemon at `apps/daemon`). The route hands off to `apps/daemon/src/lib/agent-turn.ts:runAgentTurn`, which is a thin relay (~30 lines). It:
|
|
18
|
-
|
|
19
|
-
1. Resolves the agent (`resolveAgent(db, paths, id)`) — joins agent + profile + group + skills.
|
|
20
|
-
2. Reads the enabled-provider set (`providerStateRepo.listEnabled(db)`).
|
|
21
|
-
3. Computes the merged env (`mergeSecretsIntoEnv(db, authToken)` — `process.env > secrets table > config table`).
|
|
22
|
-
4. Pre-fetches the API key via `apps/daemon/src/lib/api-key.ts:resolveAgentApiKey(db, authToken, agent)` — a no-op for env-key providers; for `openai-codex` it pulls the OAuth access token out of the secrets table. Throws a friendly "not connected" error here if the user hasn't done the OAuth flow.
|
|
23
|
-
5. Builds a `MessagingHost` backed by repos (`apps/daemon/src/lib/messaging-host.ts:createDbMessagingHost(db)`).
|
|
24
|
-
6. Registers an `AbortController` keyed by `agentId` (`apps/daemon/src/lib/agent-cancel.ts:registerAgent`).
|
|
25
|
-
7. Calls `spawnWorkerTurn({agent, message, enabledProviders, apiKey}, {signal, env, messagingHost})`.
|
|
26
|
-
|
|
27
|
-
**No LLM work happens in the daemon process.** The worker runs in its own Node child.
|
|
28
|
-
|
|
29
|
-
`apps/daemon/src/runtime/worker/spawn.ts` spawns the child:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
node --import <file:///…/tsx/loader.mjs> apps/daemon/src/runtime/worker/entry.ts
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The tsx loader path is discovered once via `createRequire(import.meta.url).resolve('tsx')` → `pathToFileURL`. Result cached. This lets the child execute `.ts` source with no build step and works under pnpm's hoisted layout because the specifier is absolute, not bare.
|
|
36
|
-
|
|
37
|
-
Stdio is `['pipe','pipe','inherit','ipc']`:
|
|
38
|
-
- **stdin** — parent writes one JSON line (`{agent, message, enabledProviders, apiKey?}`), closes it.
|
|
39
|
-
- **stdout** — line-buffered NDJSON stream of `ChatFrame`s (`session/frame.ts`):
|
|
40
|
-
- `{kind:'event', event}` — one per `SessionEvent`
|
|
41
|
-
- `{kind:'done', messages}` — exactly once on clean exit
|
|
42
|
-
- `{kind:'fatal', error}` — exceptional exits
|
|
43
|
-
- **stderr** — inherited to the daemon console.
|
|
44
|
-
- **fd 3 (IPC)** — bidirectional JSON RPC. Worker → daemon: `{type:'rpc', id, method, args}` for the messaging tools. Daemon → worker: `{type:'rpc-reply', id, ok, result|error}`.
|
|
45
|
-
|
|
46
|
-
Cancellation is keyed by **agentId** (not runId — there are no runIds anymore, since the runs table is gone). The agent-cancel registry is pinned to `globalThis[Symbol.for('bazilion.agent-cancel.registry')]` so module reloads don't replace it. `POST /api/agents/:id/cancel` looks up the controller and aborts it; the parent's abort handler calls `child.kill('SIGTERM')`, arms a 3s timer, and SIGKILLs if the child doesn't exit.
|
|
47
|
-
|
|
48
|
-
## 2. Child bootstrap (`worker/entry.ts`)
|
|
49
|
-
|
|
50
|
-
The worker has **no DB handle**. Everything DB-shaped came in over stdin:
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
process.on('SIGTERM' / 'SIGINT', onSignal) // installed FIRST so a signal during boot
|
|
54
|
-
// emits a synthetic 'cancelled' event + exits 0
|
|
55
|
-
const {agent, message, enabledProviders, apiKey} = await readInput()
|
|
56
|
-
paths = resolvePaths() // BAZILION_HOME from env, no DB access
|
|
57
|
-
memory = qmdBackend(join(agent.group.path, 'memory')) // GROUP-shared store, not per-agent
|
|
58
|
-
// BM25 index via @tobilu/qmd
|
|
59
|
-
messagingHost = createIpcMessagingHost() // process.send/on('message') wrapper
|
|
60
|
-
session = createBazilionSession({
|
|
61
|
-
agent, paths,
|
|
62
|
-
env: process.env, // already merged by daemon, passed via spawn env
|
|
63
|
-
memory,
|
|
64
|
-
enabledProviders: new Set(enabledProviders),
|
|
65
|
-
messagingHost,
|
|
66
|
-
apiKey, // pre-fetched OAuth token if openai-codex
|
|
67
|
-
})
|
|
68
|
-
abortSession = () => void session.abort()
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
`createBazilionSession` (in `apps/daemon/src/runtime/pi/session.ts`) is the integration seam. It instantiates pi-coding-agent's `AgentSession` with:
|
|
72
|
-
- A `SessionManager` rooted at `~/.bazilion/agents/<id>/sessions/` — pi owns the JSONL transcript, compaction, and replay. Resume-or-create: the worker walks the session dir for the newest `.jsonl`, opens it if found, otherwise creates a fresh session.
|
|
73
|
-
- Pi's own `createCodingTools(cwd)` where `cwd = group.path` — that's where `read`/`bash`/`edit`/`write`/`grep`/`find`/`ls` come from.
|
|
74
|
-
- Bazilion's custom tool list via `createBazilionCustomTools` (memory_*, home_*, web_*, bootstrap_done, optional messaging via the `messagingHost`) — see `apps/daemon/src/runtime/pi/tools.ts`.
|
|
75
|
-
- The provider/model pair from the registry, with `apiKey` (caller-supplied for OAuth providers, env-derived for API-key ones), plus the agent's `reasoning_level`.
|
|
76
|
-
|
|
77
|
-
Provider gate: `enabledProviders.size > 0 && !enabledProviders.has(providerName)` → throws "provider is disabled — enable it on /config". The set is pre-computed by the daemon so the worker doesn't have to read `provider_state`.
|
|
78
|
-
|
|
79
|
-
For `openai-codex` agents specifically, the worker doesn't get a refresher callback (it has no DB to refresh against). The initial token is expected to last the turn; turns that exceed the JWT lifetime fail. Daemon-side compact/context routes use `resolveAgentApiKey(..., {withRefresher:true})` to wire pi's mid-turn refresh hook.
|
|
80
|
-
|
|
81
|
-
After the turn finishes (or aborts), the worker calls `process.disconnect()` in its `finally` so the IPC channel doesn't pin the event loop alive after the turn settles.
|
|
82
|
-
|
|
83
|
-
## 3. The prompt
|
|
84
|
-
|
|
85
|
-
`session/prompt.ts:buildSystemPrompt` concatenates, in order, whichever of these files exist under the agent's dir:
|
|
86
|
-
`AGENTS.md → SOUL.md → TOOLS.md → IDENTITY.md → HEARTBEAT.md → BOOTSTRAP.md`.
|
|
87
|
-
|
|
88
|
-
Those were copied out of the profile at spawn time (`core/agent/spawn.ts`) so an agent can diverge from its profile. If `BOOTSTRAP.md` exists a nudge is appended telling the model to call `bootstrap_done` (which deletes the file) once it's done onboarding.
|
|
89
|
-
|
|
90
|
-
Then three group-related blocks are appended (when applicable):
|
|
91
|
-
|
|
92
|
-
- **`# Agent Home`** — describes the agent's private home (`agents/<id>/`) and points the model at `home_read` / `home_write` / `home_list` for self-edits and at `memory_write` for things-to-remember-later. Frames the distinction between "who I am" (home) and "what I produce" (group dir).
|
|
93
|
-
- **`# Group`** — `- <id> (<name>): <path>`. Reminds the model that its `read`/`bash`/`edit`/`write`/`grep`/`find`/`ls` tools are rooted at the group directory, that the group may be shared with other agents, and that it must use `home_*` (not these tools) to edit its own identity files.
|
|
94
|
-
- **`# About the User`** — only when `groups.user_md` is non-empty. Read-only context block about the human; the agent is told it can't edit it directly.
|
|
95
|
-
|
|
96
|
-
Finally appends: the list of attached skills (each skill's SKILL.md body is injected into the prompt), and a memory blurb explaining the **group-shared** scope: "You share a persistent memory backend with every other agent in this group. Use `memory_write` for project knowledge — codebase notes, decisions, things the user told you about the work. For personal notes about yourself (preferences, persona quirks), use `home_write` on IDENTITY.md instead."
|
|
97
|
-
|
|
98
|
-
## 4. The turn loop
|
|
99
|
-
|
|
100
|
-
The turn itself is run by pi-coding-agent's `AgentSession`. The worker invokes:
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
await session.prompt(message)
|
|
104
|
-
await session.agent.waitForIdle()
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
A `session.subscribe(...)` listener is installed beforehand to capture pi's session events. Each event passes through `apps/daemon/src/runtime/pi/events.ts:translatePiEvent` to one (or zero) Bazilion `SessionEvent`s, which the worker emits as `{kind:'event', event}` NDJSON frames on stdout.
|
|
108
|
-
|
|
109
|
-
### Pi owns durability and replay
|
|
110
|
-
|
|
111
|
-
The user's message lands in pi's session JSONL the moment `prompt()` is called, so a SIGKILL mid-turn doesn't lose it. On the next worker, `SessionManager.open` replays the JSONL and pi's own orphan-strip drops trailing user/tool entries with no matching assistant reply. There is no `agents.chat_messages` blob anymore; the JSONL file at `~/.bazilion/agents/<id>/sessions/<sessionId>.jsonl` is the canonical transcript and the **only** persistent record of the conversation.
|
|
112
|
-
|
|
113
|
-
### Event flow
|
|
114
|
-
|
|
115
|
-
Per pi iteration:
|
|
116
|
-
|
|
117
|
-
1. Abort check — if the worker's signal handler has fired, `session.abort()` was called and pi unwinds the in-flight provider fetch via the `AbortSignal`.
|
|
118
|
-
2. Pi calls the provider via Bazilion's `pi-adapter.ts`. Streaming text arrives via internal events; the translator yields `{type:'assistant_delta', delta}`.
|
|
119
|
-
3. When the provider resolves, the translator yields `{type:'assistant_message', text}` (full text). Tool calls produce `{type:'tool_call', ...}` → tool dispatch → `{type:'tool_result', ...}` (or `tool_error`). Messaging tools dispatch through the IPC host (see §6).
|
|
120
|
-
4. Loop continues until pi decides the turn is complete.
|
|
121
|
-
|
|
122
|
-
On clean exit, the worker emits `{kind:'done', messages}` carrying the full final `ProviderMessage[]` view (built from pi's session) so the consumer can reconcile its render with authoritative state.
|
|
123
|
-
|
|
124
|
-
## 4b. `/compact`, `/context`, `/reset` — session commands
|
|
125
|
-
|
|
126
|
-
These run **inside the daemon** (not in a worker subprocess) — they're short read/edit operations on pi's session, no LLM streaming.
|
|
127
|
-
|
|
128
|
-
**`/compact`** delegates to pi's `session.compact()`: summarize the head, preserve a verbatim tail (default 10 messages), record a compaction marker pointing at the first kept entry. The HTTP endpoint at `apps/daemon/src/routes/agents.ts` (POST `/api/agents/:id/chat/compact`) opens the agent's session via `createBazilionSession` (with `apiKey` + `refreshApiKey` from `resolveAgentApiKey` — this *is* an LLM call to summarize, so OAuth refresh matters), calls `compact({keepTail, customInstructions})`, and returns `{before, after, summarized, keptTail, tokensBefore, tokensAfter, summary}`.
|
|
129
|
-
|
|
130
|
-
On replay, pi turns the compaction marker into a synthetic `assistant` message prefixed with `[conversation summary]\n\n…`; entries before the marker are skipped; entries from `firstKeptEntryId` onward pass through verbatim. The web UI renders a divider (`chat-msg-compaction`) instead of an agent bubble.
|
|
131
|
-
|
|
132
|
-
CLI: `bazilion agent chat-compact <id> [--keep-tail N] [--instructions "..."]`.
|
|
133
|
-
|
|
134
|
-
**`/context`** (GET `/api/agents/:id/chat/context`) returns a `ChatContextResponse`: per-file system-prompt contribution, tool count + total schema JSON chars + per-tool schema/description/param-count, skill list + per-skill block size, the agent's group block + USER.md size, history breakdown (message entries / compaction entries / chars / bytes / token estimate), and a `totals` line summing system prompt + tool schemas + history.
|
|
135
|
-
|
|
136
|
-
Implementation: calls `buildSystemPrompt(resolved)` for the total, re-renders the skills/group subsections inline for subsection sizes, opens `createBazilionSession` to enumerate tools and read pi's session stats. `?detail=1` (or `--json` on the CLI) emits the full `entries` arrays; default truncates to top 30.
|
|
137
|
-
|
|
138
|
-
**`/reset`** drops the agent's session(s) so the next turn starts with an empty transcript. Endpoint: `POST /api/agents/:id/chat/reset`; CLI: `bazilion agent chat-reset <id>`; web slash: `/reset`.
|
|
139
|
-
|
|
140
|
-
**`/truncate`** keeps the first N entries (`POST /api/agents/:id/chat/truncate {keepCount}`; CLI `bazilion agent chat-trim <id> --keep N`; web "edit last message" UI).
|
|
141
|
-
|
|
142
|
-
## 5. Provider layer (`providers/pi-adapter.ts` + `registry.ts`)
|
|
143
|
-
|
|
144
|
-
All provider traffic goes through pi-ai (`@mariozechner/pi-ai`). `piProvider(cfg)` adapts pi's `streamSimple(model, {systemPrompt, messages, tools}, {signal, apiKey, reasoning, …})` to Bazilion's `Provider.chat(ProviderRequest): Promise<ProviderResponse>`.
|
|
145
|
-
|
|
146
|
-
Model lookup tries `getModel(piProviderName, modelId)` first — returns a typed `Model<>` with cost/context-window metadata for catalog hits. Miss falls back to a hand-built literal (32k ctx, 4k maxTokens, zero cost) — this is what makes `lmstudio:<any-loaded-model>` or unreleased OpenAI models Just Work.
|
|
147
|
-
|
|
148
|
-
Message conversion: `system` is passed separately (pi keeps it out of the message array), `assistant` messages with tool calls are rebuilt as `{type:'text'|'toolCall'}` content blocks, `tool` messages become pi `toolResult` messages. The synthesized `usage`/`stopReason`/`api` fields on replayed assistant messages are load-bearing only for pi's type checker, not the LLM.
|
|
149
|
-
|
|
150
|
-
`apiKey` can be a function — providers like `openai-codex` use this for lazy OAuth refresh. The registry passes `() => loadOpenAICodexAccessToken(db, authToken)` so refresh happens at each `chat()` without rebuilding the cached Provider.
|
|
151
|
-
|
|
152
|
-
`loadProviderConfigFromEnv(env, oauth?)` takes an optional `{db, authToken}` to enable OAuth-backed providers; daemon-side callers always pass it, env-only callers (currently none in production code) can omit it.
|
|
153
|
-
|
|
154
|
-
`withRetry` wraps every provider uniformly. Retryable: 5xx, 429, connection resets, `overloaded_error`, etc. Non-retryable: 4xx auth/invalid_request/context_length. **Hard rule**: if `onDelta` already fired on this attempt (`streamed=true`), we throw instead of retrying — a retry would duplicate streamed text in the UI. Exponential backoff with `AbortSignal`-aware sleep, default 3 total attempts.
|
|
155
|
-
|
|
156
|
-
## 6. Tool registry (`tools/registry.ts` + `pi/tools.ts`)
|
|
157
|
-
|
|
158
|
-
`createToolRegistry(handlers[])` gives a dumb Map keyed on `def.name` with `list()/has()/invoke(name, jsonArgs)`. On `invoke`:
|
|
159
|
-
- `JSON.parse(jsonArgs)` — wrap errors with the tool name for better debugging
|
|
160
|
-
- Guard non-object args
|
|
161
|
-
- Call `handler.invoke(args)` — handler returns a string (the tool result content)
|
|
162
|
-
|
|
163
|
-
`createBazilionCustomTools` (`apps/daemon/src/runtime/pi/tools.ts`) composes the Bazilion-specific tool list and adapts each `ToolHandler` to pi's `ToolDefinition`:
|
|
164
|
-
|
|
165
|
-
- `memory_{write,read,search,list}` — qmd BM25 over markdown files in `<group.path>/memory/`. The store is **shared by every agent in the group** — descriptions explicitly say so and direct personal notes to `home_write IDENTITY.md` instead.
|
|
166
|
-
- `home_{read,write,list}` — scope = `<agentDir>/`, hard whitelist of identity files (`SOUL.md`, `IDENTITY.md`, `BOOTSTRAP.md`, `AGENTS.md`, `TOOLS.md`, `HEARTBEAT.md`). No path arg, no traversal. `BOOTSTRAP.md` is read-only — `bootstrap_done` owns its lifecycle.
|
|
167
|
-
- `web_search` + `web_fetch` — SSRF-guarded, Readability + markdown, 15-min LRU cache, UA spoof, 20s timeout, 3 max redirects.
|
|
168
|
-
- `bootstrap_done` — deletes `BOOTSTRAP.md` after onboarding.
|
|
169
|
-
- `send_message` / `read_inbox` / `wait_for_reply` — registered only when a `messagingHost` is supplied (always true in production). The **MessagingHost interface** is the seam between the worker (which uses an IPC-backed implementation) and the daemon (which uses a DB-backed implementation):
|
|
170
|
-
|
|
171
|
-
```ts
|
|
172
|
-
// apps/daemon/src/runtime/worker/ipc-protocol.ts
|
|
173
|
-
export interface MessagingHost {
|
|
174
|
-
agentExists(agentId: string): boolean | Promise<boolean>
|
|
175
|
-
sendMessage(input: {...}): {messageId} | Promise<{messageId}>
|
|
176
|
-
listInbox(agentId, opts: {unreadOnly}): Message[] | Promise<Message[]>
|
|
177
|
-
markRead(messageId: string): void | Promise<void>
|
|
178
|
-
findReplies(agentId, replyTo): Message[] | Promise<Message[]>
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
Worker-side (`createIpcMessagingHost` in `worker/entry.ts`): each method serializes args, sends `process.send({type:'rpc', id, method, args})`, awaits the matching `rpc-reply` (correlation by `id`). Daemon-side (`createDbMessagingHost` in `daemon/src/lib/messaging-host.ts`): passes through to `messageRepo` / `agentRepo`. The daemon's `spawnWorkerTurn` wires the dispatcher: `child.on('message')` → match the request to a `MessagingHost` method → reply.
|
|
183
|
-
|
|
184
|
-
File-IO tools — `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls` — come from pi-coding-agent's own `createCodingTools(cwd, …)`. The `cwd` is the agent's group directory; that's how the model gets a single rooted view of work product without the legacy workspace-mount juggling.
|
|
185
|
-
|
|
186
|
-
## 7. Cancellation end-to-end
|
|
187
|
-
|
|
188
|
-
```
|
|
189
|
-
POST /api/agents/:id/cancel
|
|
190
|
-
→ apps/daemon/src/lib/agent-cancel.ts: cancelAgent(id) → controller.abort()
|
|
191
|
-
→ parent's spawnWorkerTurn abort handler: child.kill('SIGTERM'), arm 3s → SIGKILL
|
|
192
|
-
→ child's SIGTERM handler: aborts its internal controller (calls session.abort())
|
|
193
|
-
→ pi unwinds the in-flight provider fetch via AbortSignal
|
|
194
|
-
→ translator emits {type:'error', error:'cancelled'} on the next event
|
|
195
|
-
→ worker emits the corresponding ChatFrame {kind:'event', event:{type:'error',…}}
|
|
196
|
-
→ then on `done` (or fatal), the worker disconnects IPC and exits 0
|
|
197
|
-
→ parent's runAgentTurn unregisters the agent in `finally`
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
There is no per-run row to update — pi's session JSONL records the partial assistant message + the error event as the last entries on the branch. The next chat turn picks up from there (or `bazilion agent chat-reset` clears it).
|
|
201
|
-
|
|
202
|
-
## 8. Scheduler (`apps/daemon/src/lib/scheduler.ts`)
|
|
203
|
-
|
|
204
|
-
Not strictly the engine, but it's the other caller of `runAgentTurn`. A `setInterval` (5s default, unrefed, pinned on `Symbol.for('bazilion.scheduler')` to survive module reloads) reads enabled triggers from `agent_triggers` each tick:
|
|
205
|
-
- `interval`: due when `now - (lastFiredAt ?? createdAt) ≥ intervalSec*1000`.
|
|
206
|
-
- `cron`: a 5-field parser (`apps/daemon/src/lib/cron.ts`) matched at minute resolution, with OR semantics on DOM/DOW. Guard: don't refire within the same minute-floor as `lastFiredAt`.
|
|
207
|
-
|
|
208
|
-
The scheduler also runs an **inbox auto-deliver loop** each tick: `messageRepo.listRecipientsWithUnread(db)` returns idle agents with unread mail; for each, the scheduler drains the inbox into the agent's wake-up prompt and fires `runAgentTurn`. The agent-cancel registry's `isActiveAgent(agentId)` check prevents double-firing while a turn is in flight.
|
|
209
|
-
|
|
210
|
-
On fire: dedupe by triggerId/agentId (in-memory `firing` Set), `markFired` first, then drain `runAgentTurn` discarding frames. The turn's transcript lands in pi's session JSONL identically to HTTP chats.
|
|
211
|
-
|
|
212
|
-
## The shape that matters
|
|
213
|
-
|
|
214
|
-
Three layers, one contract:
|
|
215
|
-
- **`Provider.chat`** — pi-adapter + retry. Everything below it.
|
|
216
|
-
- **`session.prompt(message)`** — pi-coding-agent's own loop. Bazilion subscribes to its events via `session.subscribe(...)` and translates them into wire events.
|
|
217
|
-
- **NDJSON stdout** — what the worker writes is what the HTTP client reads, byte-for-byte. No translation between worker→daemon and daemon→client.
|
|
218
|
-
|
|
219
|
-
Plumbing around those three is invisible to callers: both the HTTP route and the scheduler see the same `AsyncGenerator<ChatFrame>` shape from `runAgentTurn`. The subprocess + IPC boundaries are an implementation detail.
|