Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
ce27071
chore: require Node >=22.5.0 for node:sqlite support
dibstern Apr 9, 2026
9aa6602
feat(persistence): add SqliteClient wrapper with WAL mode, statement …
dibstern Apr 9, 2026
e84ef72
feat(persistence): add migration runner with ordered execution and ro…
dibstern Apr 9, 2026
6a64246
feat(persistence): add schema migration with all 12 event store tables
dibstern Apr 9, 2026
a02a35f
feat(persistence): add EventStore with append, batch, read, and per-s…
dibstern Apr 9, 2026
2eb20db
feat(persistence): add CommandReceiptRepository for idempotent comman…
dibstern Apr 9, 2026
9c3b54f
feat(persistence): add CanonicalEventTranslator mapping SSE events to…
dibstern Apr 9, 2026
c02bcb8
feat(persistence): add PersistenceLayer as single entry point for dat…
dibstern Apr 9, 2026
7c141df
feat(persistence): add SessionSeeder for INSERT OR IGNORE session row…
dibstern Apr 9, 2026
6973ebb
feat(persistence): add DualWriteHook coordinating translation, seedin…
dibstern Apr 9, 2026
ec53e85
feat(persistence): wire DualWriteHook into SSE pipeline — events flow…
dibstern Apr 9, 2026
84bd4c8
feat(persistence): wire dual-write into relay stack with dualWriteEna…
dibstern Apr 9, 2026
cd88f6c
feat(persistence): add ProjectorCursorRepository for tracking project…
dibstern Apr 9, 2026
be2aa0a
feat(persistence): add Projector interface and shared helpers for pro…
dibstern Apr 9, 2026
e4c5211
feat(persistence): add SessionProjector for session lifecycle events
dibstern Apr 9, 2026
13b9c58
feat(persistence): add MessageProjector for message, text, thinking, …
dibstern Apr 9, 2026
3a343b3
feat(persistence): add TurnProjector for turn lifecycle events
dibstern Apr 9, 2026
6a02966
feat(persistence): add ProviderProjector for session-provider binding…
dibstern Apr 9, 2026
07993e4
feat(persistence): add ApprovalProjector for permission and question …
dibstern Apr 9, 2026
c25177c
feat(persistence): add ActivityProjector for chronological activity t…
dibstern Apr 9, 2026
d60951b
feat(persistence): add ProjectionRunner with batch projection and sta…
dibstern Apr 9, 2026
0c42675
feat(persistence): wire ProjectionRunner into dual-write — events aut…
dibstern Apr 9, 2026
2f391e4
feat(persistence): add PersistenceDiagnostics with health check and i…
dibstern Apr 9, 2026
5677256
feat(persistence): add ReadQueryService — centralized SQLite read lay…
dibstern Apr 9, 2026
ab2816c
feat(persistence): add three-state ReadFlags (legacy/shadow/sqlite) f…
dibstern Apr 9, 2026
de33d67
feat(persistence): add ReadAdapter and wire Phase 4 read switchover i…
dibstern Apr 9, 2026
593de64
feat(provider): add ProviderAdapter interface and supporting types (7…
dibstern Apr 9, 2026
e2f95e3
feat(provider): add EventSink wrapping EventStore + ProjectionRunner
dibstern Apr 9, 2026
5ca9720
feat(provider): add ProviderRegistry for adapter lookup and lifecycle…
dibstern Apr 9, 2026
97606b7
feat(provider): add OpenCodeAdapter wrapping existing client as Provi…
dibstern Apr 9, 2026
1553bbf
feat(provider): add OrchestrationEngine for command dispatch to provi…
dibstern Apr 9, 2026
7cd0c6a
feat(provider): wire OrchestrationEngine into relay via factory function
dibstern Apr 9, 2026
9c7face
feat(provider): install @anthropic-ai/claude-agent-sdk
dibstern Apr 9, 2026
1313c4f
feat(provider): add Claude adapter types (Task 43)
dibstern Apr 9, 2026
c5cafbd
feat(provider): add PromptQueue async bridge for Claude SDK query() i…
dibstern Apr 9, 2026
7b50f05
feat(provider): add ClaudeEventTranslator mapping SDKMessage to canon…
dibstern Apr 9, 2026
1b57e2e
feat(provider): add ClaudePermissionBridge converting canUseTool call…
dibstern Apr 9, 2026
e952750
feat(provider): add ClaudeAdapter with discover(), shutdown(), interr…
dibstern Apr 9, 2026
dc545ea
feat(provider): add provider wiring tests for ClaudeAdapter registrat…
dibstern Apr 9, 2026
dee5c1a
feat(persistence): add session history adapter for MessageRow→History…
dibstern Apr 9, 2026
90ab333
feat(read-switchover): 4e — session switch history reads from SQLite …
dibstern Apr 9, 2026
463337d
feat(read-switchover): 4a — tool content reads from SQLite via ReadAd…
dibstern Apr 9, 2026
69c05c2
feat(read-switchover): 4b — fork metadata reads from SQLite sessions …
dibstern Apr 9, 2026
7aca1fd
feat(read-switchover): 4c — session list reads from SQLite with compa…
dibstern Apr 9, 2026
f14a8c8
feat(read-switchover): 4d — session status reads from SQLite sessions…
dibstern Apr 9, 2026
330d9b2
feat(provider): wire prompt.ts through OrchestrationEngine (Phase 5 r…
dibstern Apr 9, 2026
a6d68f4
refactor(task-50.5): strip MessageCache/ToolContentStore/PendingUserM…
dibstern Apr 9, 2026
8b7b48e
refactor(task-51): remove MessageCache and JSONL caching — replaced b…
dibstern Apr 9, 2026
6d96709
docs: update PROGRESS.md for Tasks 50.5 and 51
dibstern Apr 9, 2026
06fe9a1
refactor(task-52): remove ToolContentStore and PendingUserMessages — …
dibstern Apr 9, 2026
37bb7d3
refactor: remove dual-write feature flags — SQLite is sole read/write…
dibstern Apr 9, 2026
419d8cc
refactor: rewrite SessionStatusPoller as 5-10s reconciliation loop wi…
dibstern Apr 9, 2026
91a68a6
docs: update AGENTS.md and architecture guide to reflect orchestrator…
dibstern Apr 10, 2026
fae2a90
docs: add Claude adapter sendTurn implementation plan with audit amen…
dibstern Apr 10, 2026
c079cf1
docs: add Task 3.5 — E2E test with real Claude SDK (gated, Haiku)
dibstern Apr 10, 2026
593387b
refactor: replace Claude SDK type stubs with real @anthropic-ai/claud…
dibstern Apr 10, 2026
fecaabf
feat: rewrite ClaudeEventTranslator tests for real SDK message types
dibstern Apr 10, 2026
b820b16
feat: implement ClaudeAdapter.sendTurn() — SDK query lifecycle and st…
dibstern Apr 10, 2026
c31803b
fix: address code quality review — extract isInterruptedResult, renam…
dibstern Apr 10, 2026
a4ca650
test: add Claude adapter sendTurn integration tests for orchestration…
dibstern Apr 10, 2026
88ac699
test: add real-SDK E2E test for ClaudeAdapter.sendTurn() (gated behin…
dibstern Apr 10, 2026
8bab7e8
docs: mark Claude sendTurn tasks complete, remove SDK-not-available c…
dibstern Apr 10, 2026
832833b
fix: E2E test — add settingSources for OAuth auth, use Haiku 4.5, add…
dibstern Apr 10, 2026
8988470
docs: add SDK migration design — replace OpenCodeClient with @opencod…
dibstern Apr 10, 2026
94e4c0c
docs: add SDK migration implementation plan — 17 tasks across 5 phases
dibstern Apr 10, 2026
d13c9c3
fix(plan): resolve 5 audit findings in SDK migration plan
dibstern Apr 10, 2026
047fce9
docs: SDK migration audit amendments v2-v4
dibstern Apr 13, 2026
9053563
chore: add @opencode-ai/sdk dependency
dibstern Apr 13, 2026
b1de6c0
feat: add retryFetch adapter for SDK with exponential backoff
dibstern Apr 13, 2026
446da1b
feat: add GapEndpoints for SDK-uncovered endpoints
dibstern Apr 13, 2026
2dd440c
feat: add SDK factory with auth and retry-fetch injection
dibstern Apr 13, 2026
0a8d1e5
feat: add OpenCodeAPI adapter wrapping SDK + gap endpoints
dibstern Apr 13, 2026
42121c4
wip: wire OpenCodeAPI into relay-stack (callers not yet updated)
dibstern Apr 13, 2026
9e740fe
refactor: migrate all callers from OpenCodeClient to OpenCodeAPI name…
dibstern Apr 13, 2026
ec1df25
fix: update remaining test mocks to namespaced OpenCodeAPI methods
dibstern Apr 13, 2026
2712e23
fix: resolve remaining type errors in test mocks for namespaced API
dibstern Apr 13, 2026
929419f
refactor: replace SessionDetail and SessionStatus with SDK types
dibstern Apr 13, 2026
04ac5f0
refactor: replace PartType and ToolStatus with SDK discriminated unions
dibstern Apr 13, 2026
a045a01
refactor: replace OpenCodeEvent with SSEEvent discriminated union
dibstern Apr 13, 2026
a65154d
refactor: clean up replaced type definitions from shared-types and types
dibstern Apr 13, 2026
edba04c
feat: add SSEStream backed by SDK event.subscribe() with reconnection
dibstern Apr 13, 2026
3265e6e
refactor: wire SSEStream into relay-stack replacing SSEConsumer
dibstern Apr 13, 2026
b0eccdf
cleanup: delete OpenCodeClient, SSEConsumer, and unused SSE utilities
dibstern Apr 13, 2026
d403f6c
fix: add provider normalization and message flattening to OpenCodeAPI…
dibstern Apr 14, 2026
849a97e
fix: update contract test snapshots and version pin for SDK 1.4.3
dibstern Apr 14, 2026
2c72b4c
fix: resolve 3 integration test failures from SDK migration
dibstern Apr 14, 2026
1edf48a
feat: wire ClaudeAdapter into orchestration layer with provider routing
dibstern Apr 14, 2026
2e040ae
refactor: extract Deferred<T>, fix stale bindings and canUseTool wiring
dibstern Apr 14, 2026
1719aaa
test: add permission, translator, and lifecycle gap tests
dibstern Apr 14, 2026
846aa3d
test: add error context logging tests for OrchestrationEngine dispatch
dibstern Apr 14, 2026
ac8c6cf
test: add Claude adapter integration tests (full lifecycle and permis…
dibstern Apr 14, 2026
2921e20
feat: add endSession to ProviderAdapter and auto-evict stopped sessions
dibstern Apr 16, 2026
9adbbc4
feat: add reload_provider_session message to pick up new skills/commands
dibstern Apr 16, 2026
c311600
feat: show Claude SDK models separately from OpenCode-proxied Anthropic
dibstern Apr 16, 2026
6bf6b56
feat: route Claude SDK events to browser via RelayEventSink
dibstern Apr 16, 2026
89dc3a6
feat: surface Claude SDK api_retry and non-streamed results
dibstern Apr 16, 2026
4127c23
feat: add optional persistence to RelayEventSink push()
dibstern Apr 16, 2026
8af1127
feat: thread claudeEventPersist through HandlerDeps
dibstern Apr 16, 2026
81ea82b
feat: wire Claude event persistence and projector recovery from relay…
dibstern Apr 16, 2026
4680c1c
feat: pass persistence to RelayEventSink for Claude sessions
dibstern Apr 16, 2026
bc89955
test: integration test for Claude event persistence chain
dibstern Apr 16, 2026
ef03174
fix: wire PersistenceLayer through daemon + readQuery through session…
dibstern Apr 17, 2026
021ec37
fix: persist Claude session messages to SQLite for history on session…
dibstern Apr 17, 2026
589e70b
test: regression tests for three Claude history wiring gaps
dibstern Apr 17, 2026
f685308
fix: persist tool calls and thinking blocks for Claude sessions
dibstern Apr 17, 2026
4c80f7a
fix: implement missing orchestrator plan details for Claude sessions
dibstern Apr 17, 2026
22b27c5
fix: emit session.created event for Claude sessions before message pe…
dibstern Apr 17, 2026
2fd6ea9
fix: emit session.status busy at Claude turn start for TurnProjector
dibstern Apr 17, 2026
f6543a8
feat: add ProviderStateService for per-session key-value state
dibstern Apr 17, 2026
40ef0fb
feat: wire ProviderStateService into prompt handler for resume cursor…
dibstern Apr 17, 2026
eea32b2
fix: clear stale resume cursor on invalid session errors
dibstern Apr 17, 2026
7b6b33a
feat: add QuestionBridge for session-switch question replay
dibstern Apr 17, 2026
9d2dfed
fix(plan): resolve 13 audit findings for Claude SDK event parity plan
dibstern Apr 18, 2026
65f148e
feat(plan): add Phase 2 tasks 9-11 for typed SDK data extraction
dibstern Apr 18, 2026
3001764
fix: emit thinking.end for thinking blocks in Claude event translator
dibstern Apr 18, 2026
b6e79a9
test: add thinking lifecycle round-trip through relay-event-sink
dibstern Apr 18, 2026
38b085a
fix: finalize open thinking blocks in handleDone as safety net
dibstern Apr 18, 2026
7380a2a
feat: auto-rename Claude sessions after first turn
dibstern Apr 18, 2026
7cad6ec
feat: add compile-time exhaustiveness guard for canonical event types
dibstern Apr 18, 2026
9a8ef9e
test: add exhaustiveness check for relay-event-sink translations
dibstern Apr 18, 2026
4cdbcc0
docs: update PROGRESS.md with Claude SDK event parity fixes
dibstern Apr 18, 2026
117f833
refactor: type translate() dispatch and translateSystem() with SDK types
dibstern Apr 18, 2026
61b5f6b
refactor: type stream event handlers with SDK discriminated unions
dibstern Apr 18, 2026
c947514
refactor: type result/user/assistant handlers, remove asRecord helpers
dibstern Apr 18, 2026
4829728
docs: add pipeline resilience tests design
dibstern Apr 18, 2026
deeb363
fix(plan): resolve 10 audit findings for pipeline resilience tests
dibstern Apr 18, 2026
27d6141
fix(plan): change it.fails to it.todo for rejoin specs
dibstern Apr 18, 2026
ba2b461
fix: handle 'thinking' part type in history-to-chat converter
dibstern Apr 19, 2026
9345d35
docs: update convertAssistantParts JSDoc to include 'thinking' part type
dibstern Apr 19, 2026
3db5a1a
test: add thinking lifecycle pipeline integration test
dibstern Apr 19, 2026
12281d5
test: add thinking block reload scenario to pipeline test
dibstern Apr 19, 2026
69d7c2f
test: add partial thinking block (safety net) pipeline scenario
dibstern Apr 19, 2026
04f465f
test: add thinking block invariant tests
dibstern Apr 19, 2026
676ea70
test: add fork-split thinking block invariant tests
dibstern Apr 19, 2026
a7e5352
test: add Claude session rejoin contract tests — server-side event flow
dibstern Apr 19, 2026
571544c
test: add thinking lifecycle across rejoin contract test
dibstern Apr 19, 2026
7c07833
test: add PROCESSING_TIMEOUT interaction contract test
dibstern Apr 19, 2026
6596507
test: add todo specs for delivery-layer rejoin bug
dibstern Apr 19, 2026
dd17235
test: add projector resilience tests — out-of-order, duplicates, edge…
dibstern Apr 19, 2026
d118b1d
test: add history conversion regression tests — part types, duration,…
dibstern Apr 19, 2026
5044026
test: add event translation snapshots + sink lifecycle tests
dibstern Apr 19, 2026
85e945d
test: add pipeline property-based tests (fast-check)
dibstern Apr 19, 2026
2160255
test: add malformed/adversarial payload tests to projector resilience
dibstern Apr 19, 2026
b41ee27
test: add unicode/encoding stress tests to projector resilience
dibstern Apr 19, 2026
605db89
test: add orphan event edge cases + duplicate idempotency for all eve…
dibstern Apr 19, 2026
59b22f5
fix: replace flaky PBT session isolation test with count-based assert…
dibstern Apr 19, 2026
e94fbeb
test: add PBT invalid/corrupted event sequence tests
dibstern Apr 19, 2026
7ae0481
test: add frontend error→recovery cycle and zombie state tests
dibstern Apr 19, 2026
453a452
test: add rejoin integration test with delivery-layer fidelity
dibstern Apr 19, 2026
d690287
test: add pre-existing data round-trip tests (migration safety)
dibstern Apr 19, 2026
177269f
test: add cross-session event injection test — documents mismatch risk
dibstern Apr 19, 2026
d63c3fb
test: document snapshot strategy + add structural minimum safety net
dibstern Apr 19, 2026
fae9ecb
test: add DB constraint guard, event type snapshot, and exhaustivenes…
dibstern Apr 19, 2026
32777fb
test: add concurrent projection stress test — interleaved sessions
dibstern Apr 19, 2026
71b129b
test: verify 3+ delta concatenation order for text and thinking
dibstern Apr 19, 2026
3e9ba09
test: add multi-turn conversation pipeline test
dibstern Apr 19, 2026
f8df179
style: auto-fix safe biome issues in pipeline test files
dibstern Apr 19, 2026
ed7c200
test: add clearMessages + active thinking race tests
dibstern Apr 19, 2026
9b8fb0e
test: add unknown part type runtime drop behavior tests
dibstern Apr 19, 2026
30bdd9d
test: add session deletion FK constraint contract tests
dibstern Apr 19, 2026
cb08146
test: add SSE reconnection replay test — overlap + gap detection
dibstern Apr 19, 2026
40a749d
test: add multi-client / multi-tab delivery tests
dibstern Apr 19, 2026
68e4040
test: add permission + thinking interleaving pipeline tests
dibstern Apr 19, 2026
6ad07bb
test: add PBT seed preservation + regression case block
dibstern Apr 19, 2026
7c4a2ca
test: add rewind/fork feature todo specs for thinking invariants
dibstern Apr 19, 2026
ab324fb
style: sort imports in permission-thinking-interleave.test.ts
dibstern Apr 19, 2026
7ab8968
docs: update PROGRESS.md with pipeline resilience tests
dibstern Apr 19, 2026
3fb82bc
docs: Plans
dibstern Apr 19, 2026
bd59121
fix: Enable newline entering on mobile
dibstern Apr 19, 2026
c5a1ed3
gitignore: Add .conduit
dibstern Apr 19, 2026
4761364
fix: forward tool.input_updated to browser as tool_executing
dibstern Apr 19, 2026
6f70d0e
fix: show Claude SDK tool input fields in chat tool cards
dibstern Apr 19, 2026
16f99f9
docs: per-session chat state design
dibstern Apr 19, 2026
a613916
fix(plan): resolve audit findings \u2014 per-session chat state
dibstern Apr 19, 2026
5239527
fix(plan): resolve audit findings — per-session chat state (two-tier)
dibstern Apr 20, 2026
ada3829
fix(plan): Loop 3 amendments — resolve 46 Amend + 8 Ask-User findings
dibstern Apr 20, 2026
8c7d544
docs: final audit synthesis — per-session chat state plan audit passed
dibstern Apr 20, 2026
ac77f34
feat: add sessionId to every PerSessionEvent + F3 fix + session_delet…
dibstern Apr 21, 2026
f400d43
feat(frontend): add two-tier per-session chat state API, gated
dibstern Apr 21, 2026
95c0e83
feat(frontend): flip handlers to per-session (activity, messages, eve…
dibstern Apr 21, 2026
cb29177
feat(frontend): flip replay path + buffer to per-slot
dibstern Apr 21, 2026
222d658
feat(frontend): flip dispatcher to routePerSession + F2 fix
dibstern Apr 21, 2026
7fc3079
feat(frontend): flip components to currentChat() + per-session reads
dibstern Apr 22, 2026
ed6a6f2
feat(frontend): delete legacy globals + wire session teardown
dibstern Apr 22, 2026
cbcfc49
refactor(frontend): delete dead code from per-session migration
dibstern Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ media/_debug/
media/_test_output/

/test-output.log
/.conduit
2 changes: 1 addition & 1 deletion .opencode-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.3.0
1.3.13
12 changes: 7 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,28 @@ NEVER stash changes, you are interrupting other sessions and work.

## Purpose

`conduit` is a web UI relay for OpenCode. It lets one long-lived relay daemon expose OpenCode sessions to browser clients across multiple projects.
`conduit` is a web UI orchestrator for AI coding assistants. It lets one long-lived daemon expose sessions to browser clients across multiple projects. Provider adapters (OpenCode, Claude Agent SDK) are stateless execution engines that stream events into conduit's SQLite event store.

## Architecture At A Glance

- `src/bin/cli.ts` is the thin CLI entrypoint; `src/bin/cli-core.ts` routes commands.
- The CLI either runs a relay in-process with `foreground` or manages a long-lived `Daemon` over Unix socket IPC.
- `src/lib/daemon/daemon.ts` owns process lifecycle, persisted config, the shared HTTP and IPC servers, project registration, and the OpenCode instance registry.
- One daemon can host many projects. Each project gets its own relay stack mounted under `/p/<slug>`.
- `src/lib/relay/relay-stack.ts` builds the per-project relay around `OpenCodeClient`, `SessionManager`, `SSEConsumer`, `WebSocketHandler`, caches, pollers, and PTY wiring.
- `src/lib/relay/relay-stack.ts` builds the per-project relay around `OpenCodeClient`, `SessionManager`, `SSEConsumer`, `WebSocketHandler`, pollers, and PTY wiring.
- `src/lib/server/*` handles the shared HTTP and WebSocket edge; `src/lib/handlers/*` dispatch browser messages into focused domain handlers.
- OpenCode is the source of truth for sessions and messages. Relay-side caches are for responsiveness and recovery.
- The SQLite event store is the source of truth for sessions and messages. Provider adapters are stateless execution engines that stream events into the store.

Read `docs/agent-guide/architecture.md` before changing daemon behavior, routing, relay wiring, SSE flow, session flow, instance management, or PTY behavior.
Read `docs/agent-guide/architecture.md` before changing daemon behavior, project routing, relay wiring, event store, projectors, provider adapters, session flow, instance management, or PTY behavior.

## Source Map

- `src/bin/`: CLI entrypoints.
- `src/lib/daemon/`: daemon lifecycle, IPC, config persistence, projects.
- `src/lib/server/`: HTTP and WebSocket server, router, static files, push.
- `src/lib/relay/`: OpenCode event pipeline, caches, pollers, PTY upstream wiring.
- `src/lib/relay/`: OpenCode event pipeline, pollers, PTY upstream wiring.
- `src/lib/persistence/`: SQLite event store, projectors, migrations.
- `src/lib/provider/`: Provider adapters (OpenCode, Claude SDK).
- `src/lib/session/`: session orchestration and status polling.
- `src/lib/instance/`: OpenCode instance management and client access.
- `src/lib/handlers/`: browser message handlers.
Expand Down
3 changes: 2 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"!docs/**/*.html",
"!.opencode",
"!.conduit",
"!test/e2e/fixtures/recorded/*.json"
"!test/e2e/fixtures/recorded/*.json",
"!test/e2e/fixtures/subagent-snapshot.json"
]
},
"css": {
Expand Down
179 changes: 172 additions & 7 deletions docs/PROGRESS.md

Large diffs are not rendered by default.

18 changes: 10 additions & 8 deletions docs/agent-guide/architecture.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Architecture Guide

Use this guide before changing daemon behavior, project routing, relay wiring, SSE flow, session flow, instance management, or PTY behavior.
Use this guide before changing daemon behavior, project routing, relay wiring, event store, projectors, provider adapters, session flow, instance management, or PTY behavior.

## Runtime Shape

Expand All @@ -22,7 +22,9 @@ Mermaid Diagram: docs/agent-guide/system-context-diagram.mermaid
| CLI / control | `src/bin/*`, `src/lib/cli/*` | Operator-facing commands, setup, watcher, TLS helpers |
| Daemon | `src/lib/daemon/*` | Process lifecycle, persisted state, IPC, project and instance registration |
| HTTP / WS edge | `src/lib/server/*` | Shared HTTP server, auth gate, static assets, project route dispatch, WebSocket upgrades |
| Project relay | `src/lib/relay/*` | OpenCode SSE consumption, event translation, message cache, pollers, PTY upstreams |
| Project relay | `src/lib/relay/*` | OpenCode SSE consumption, event translation, pollers, PTY upstreams |
| Persistence | `src/lib/persistence/*` | SQLite event store, projectors (sessions, messages, turns, providers, approvals, activities), migrations |
| Provider adapters | `src/lib/provider/*` | Stateless execution engines (OpenCode, Claude Agent SDK) that stream events into the event store |
| Session domain | `src/lib/session/*` | Active session tracking, history paging, status polling, client-to-session registry |
| OpenCode instances | `src/lib/instance/*` | Managed and unmanaged OpenCode instances, health checks, URL resolution, spawn/stop |
| Browser handlers | `src/lib/handlers/*` | Message-type dispatch into session, prompt, model, file, terminal, and instance actions |
Expand All @@ -38,16 +40,16 @@ Mermaid diagram: docs/agent-guide/per-project-relay-flow-diagram.mermaid

| Boundary | Meaning |
|---|---|
| Relay composition | Each relay combines `OpenCodeClient`, `SessionManager`, `SSEConsumer`, event pipeline modules, `WebSocketHandler`, caches, pollers, PTY wiring, and permission/question bridges. |
| Source of truth | Durable conversation state lives in OpenCode, not relay-owned storage. |
| Relay-owned state | Per-project caches exist for responsiveness and recovery, not as the primary record. |
| Daemon-owned state | The config directory holds socket and PID files, daemon config, recent projects, push settings, and caches. |
| Relay composition | Each relay combines `OpenCodeClient`, `SessionManager`, `SSEConsumer`, event pipeline modules, `WebSocketHandler`, pollers, PTY wiring, and permission/question bridges. |
| Source of truth | Durable conversation state lives in conduit's SQLite event store. Provider adapters are stateless execution engines that stream events into the store. |
| Relay-owned state | The event store and its projections (sessions, messages, turns, providers, approvals, activities) are the primary record. Projectors maintain materialized views from the append-only event log. |
| Daemon-owned state | The config directory holds socket and PID files, daemon config, recent projects, and push settings. |
| Frontend delivery | Frontend assets are built separately with Vite and served as static files by the relay server. |

## Communication Flow

| Flow | Path |
|---|---|
| Browser to relay | Browser loads the SPA over HTTP, `RequestRouter` serves auth/setup/health/info/themes/project routes, project WebSocket upgrades go to `WebSocketHandler`, and `src/lib/handlers/index.ts` dispatches incoming message types to session, instance, file, terminal, and bridge services. |
| OpenCode to relay to browser | Each project relay connects upstream through `SSEConsumer`, pipeline modules translate events, caches and pollers update relay-side view state, and `WebSocketHandler` broadcasts normalized events to relevant clients or session viewers. |
| CLI to daemon | Commands such as `status`, `stop`, `add_project`, and `set_pin` go over IPC; the daemon updates config and registries, mounts new relays on the shared HTTP and WebSocket surface, and rebroadcasts instance status changes. |
| Provider to event store to browser | Provider adapters stream events into the SQLite event store. Projectors update materialized views (sessions, messages, turns). Pollers reconcile provider-side status. `WebSocketHandler` broadcasts normalized events to relevant clients or session viewers. |
| CLI to daemon | Commands such as `status`, `stop`, `add_project`, and `set_pin` go over IPC; the daemon updates config and registries, mounts new relays on the shared HTTP and WebSocket surface, and rebroadcasts instance status changes. |
16 changes: 10 additions & 6 deletions docs/agent-guide/per-project-relay-flow-diagram.mermaid
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ flowchart LR
question bridges]
relayCore[Event pipeline
SSEConsumer
cache, pollers, PTY wiring]
client[OpenCodeClient]
opencode[OpenCode server
source of truth]
pollers, PTY wiring]
eventStore[SQLite event store
projectors]
provider[Provider adapter
stateless execution engine]
opencode[OpenCode server]

browser <-->|WebSocket messages| ws
ws --> handlers
Expand All @@ -22,5 +24,7 @@ flowchart LR
sessions --> relayCore
bridges --> relayCore
relayCore --> ws
relayCore --> client
client <-->|REST, SSE, PTY upstream| opencode
relayCore --> provider
provider -->|stream events| eventStore
provider <-->|REST, SSE, PTY upstream| opencode
eventStore --> ws
13 changes: 10 additions & 3 deletions docs/agent-guide/system-context-diagram.mermaid
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ flowchart LR
src/lib/daemon/daemon.ts]
server[Shared HTTP and WS edge
src/lib/server/*]
persistence[SQLite event store
src/lib/persistence/*]
providers[Provider adapters
src/lib/provider/*]

subgraph projects[Per-project mounts under /p/<slug>]
relayA[Project Relay A]
Expand All @@ -19,14 +23,17 @@ flowchart LR

opencode[OpenCode server]
state[Daemon config dir
PID, socket, config, caches]
PID, socket, config, push settings]

cli -->|foreground or IPC control| daemon
browser -->|HTTP for SPA and APIs| server
browser <-->|WebSocket messages| server
daemon --> server
server --> relayA
server --> relayB
relayA <-->|REST, SSE, PTY upstream| opencode
relayB <-->|REST, SSE, PTY upstream| opencode
relayA --> providers
relayB --> providers
providers <-->|REST, SSE, PTY upstream| opencode
providers -->|stream events| persistence
persistence --> server
daemon <--> state
Loading