summaryrefslogtreecommitdiffhomepage
path: root/context.md
blob: 896eed449ad7676c469bb3601a770531621f030f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# Dispatch — Phase 1 Implementation Context

This file captures all decisions, open questions, and constraints established during planning. It serves as the source of truth for any agent working on Phase 1 implementation.

---

## Stack Decisions

| Layer | Choice | Notes |
|---|---|---|
| Runtime | **Bun** | Runtime + package manager. Native SQLite, fast installs/execution |
| Backend framework | **Hono.js** | Lightweight, WebSocket support |
| Frontend framework | **Vite + Svelte + DaisyUI** | Strict TypeScript throughout |
| Language | **TypeScript (strict mode)** | Both frontend and backend |
| LLM SDK | **Vercel AI SDK (`ai`)** | Provider-agnostic, streaming, tool calling |
| Default LLM | **DeepSeek V4 Flash Free** | Via OpenCode Go (Zen). Hardcoded for Phase 1 |
| Database | **SQLite (no ORM)** | `bun:sqlite` (native), no Drizzle or other ORM |
| Testing | **Vitest** | Set up across all packages from day one |
| Linting/Formatting | **Biome** | Single tool for both linting and formatting. Confirmed compatible with OpenCode |
| Package Manager | **Bun workspaces** | Monorepo with `@dispatch/*` packages |
| Dev Server | **Separate ports + CORS** | Frontend `:5173`, backend `:3000`, explicit CORS |

---

## Resolved Decisions

### Streaming Architecture: WebSocket Only
All real-time communication flows over a single WebSocket connection:
- Chat messages (user -> server)
- Streaming LLM tokens (server -> client)
- Tool call notifications and results (server -> client)
- Agent status updates (server -> client)

`POST /chat` is not a streaming endpoint — it just queues/sends a message. The WebSocket handles all real-time data. `GET /status` remains as a simple REST endpoint for polling agent state.

### Database: SQLite Without ORM
No Drizzle ORM. Use `better-sqlite3` (or equivalent) directly with raw SQL. Keep it simple. The question of whether to set up persistence in Phase 1 or defer to Phase 5 is still open — the user indicated willingness to use SQLite but the timing wasn't finalized. **Default assumption: defer heavy persistence to Phase 5, but the library choice is locked in.**

### Tool Scoping: Working Directory
File tools (`read_file`, `write_file`, `list_files`) will be scoped to a configurable working directory from Phase 1. This prevents accidental filesystem damage and provides a clean foundation for the permission system in Phase 2.

### Testing: Vitest From Day One
Vitest set up across the monorepo. Unit tests for core logic (agent loop, tool registry, individual tools).

### DaisyUI Theme: Configurable With Persistence
Support multiple DaisyUI themes with a user-selectable theme switcher in settings. The selected theme is remembered across sessions (localStorage or equivalent).

### Default LLM Provider: DeepSeek V4 Flash via OpenRouter
The Phase 1 hardcoded model is DeepSeek V4 Flash, accessed through OpenRouter. This means:
- The Vercel AI SDK OpenRouter provider will be used
- A single `OPENROUTER_API_KEY` env var (or equivalent) is needed
- Model ID will be the OpenRouter model string for DeepSeek V4 Flash

---

## Resolved Decisions (Previously Open Questions)

### 1. Package Manager and Monorepo Tooling: Bun Workspaces
**Decision:** Bun as both runtime and package manager, using Bun workspaces.

Bun workspaces work similarly to pnpm workspaces — `packages/core`, `packages/api`, and `packages/frontend` reference each other as `@dispatch/*` dependencies, and Bun symlinks them locally.

### 2. Runtime: Bun
**Decision:** Bun is the runtime.

Implications:
- Native SQLite via `bun:sqlite` — no need for `better-sqlite3`
- Bun is faster for installs, script execution, and testing
- Vitest is the test runner (works with Bun)
- No Node.js version to manage

### 3. Dev Server Setup: Separate Ports + CORS
**Decision:** Frontend on `:5173` (Vite dev server), backend on `:3000` (Hono). Explicit CORS configuration on the backend.

This means:
- Hono backend needs CORS middleware allowing the frontend origin
- WebSocket connections go directly to `:3000` from the frontend
- No Vite proxy configuration needed
- Production will also be cross-origin (matches the split deployment model)

### 4. Biome Compatibility: Confirmed
**Decision:** Biome is fully compatible with OpenCode.

OpenCode has Biome as a **built-in formatter**. It auto-detects `biome.json(c)` config files and handles `.js`, `.jsx`, `.ts`, `.tsx`, `.html`, `.css`, `.md`, `.json`, `.yaml`, and more. Just needs a `biome.json` in the project root and formatters enabled in OpenCode config (`"formatter": true` or `"formatter": {}`).

---

## Phase 1 Scope (from plan.md)

**Goal:** Chat with one agent in a browser, watch it read and write files.

### Backend Tasks
- Project scaffolding (monorepo with `packages/core`, `packages/api`, `packages/frontend`)
- Agent runtime: message -> LLM -> tool call -> result -> repeat loop
- Vercel AI SDK integration with streaming responses
- Single provider config (DeepSeek V4 Flash via OpenRouter, env var for API key)
- Basic tools:
  - `read_file` — read file contents (scoped to working directory)
  - `write_file` — write/overwrite a file (scoped to working directory)
  - `list_files` — glob/list directory contents (scoped to working directory)
- HTTP API:
  - `POST /chat` — send a message (non-streaming, queues to agent)
  - `GET /status` — agent status (idle, running, etc.)
- WebSocket: stream agent output tokens and tool calls in real-time

### Frontend Tasks
- Single chat panel — text input field, send button
- Streamed response rendering (tokens appear as they arrive via WebSocket)
- Tool call display (collapsible: show tool name, arguments, result)
- Model/provider indicator in header
- Basic layout: chat takes full screen, clean and minimal
- Theme switcher in settings (DaisyUI themes, persisted to localStorage)

### Done When
Open a browser, type "read the contents of package.json and summarize it," see the agent call `read_file`, stream back a summary. Ask it to create a new file — it calls `write_file` and confirms.

---

## Project Structure (Planned)

```
dispatch/
  packages/
    core/              # Agent runtime, LLM integration, tools
      src/
        agent/         # Agent loop, lifecycle
        llm/           # Vercel AI SDK wrapper, provider config
        tools/         # Tool registry, built-in tools (read_file, write_file, list_files)
        types/         # Shared TypeScript types
      tests/
    api/               # Hono HTTP + WebSocket server
      src/
        routes/        # HTTP route handlers
        ws/            # WebSocket handlers
      tests/
    frontend/          # Vite + Svelte + DaisyUI client
      src/
        lib/           # Svelte components, stores, utilities
        routes/        # Page routes (if using SvelteKit) or views
      tests/
  biome.json           # Biome config (pending compatibility check)
  tsconfig.base.json   # Shared TypeScript config
  package.json         # Root workspace config
  .env.example         # Environment variables template (OPENROUTER_API_KEY, etc.)
```

---

## Concurrency Map (What Can Be Built in Parallel)

Once scaffolding is complete, the following sections can be developed concurrently:

```
[A] Scaffolding (sequential — must be first)
        |
        +---> [B] Core Agent Runtime (agent loop, LLM, tool system)
        |
        +---> [C] API Server Shell (Hono setup, route stubs, WebSocket setup)
        |
        +---> [D] Frontend Shell (Svelte app, chat UI, WebSocket client, theme system)

Then integration (sequential — depends on B, C, D):

[E] Wire core into API (connect agent runtime to routes/WebSocket)
[F] Wire frontend to API (connect UI to live WebSocket)
[G] End-to-end testing and polish
```

Sections B, C, and D are independent and can be coded by concurrent agents. Section E requires B and C. Section F requires C and D. Section G requires everything.