feat(session): persist model tier overrides per session

Store per-session config in SQLite and route /model and /reset through command fast-paths so channel sessions keep independent model selection across reconnects and restarts.
This commit is contained in:
William Valentin
2026-02-13 01:04:26 -08:00
parent 3472a0b926
commit 9f81c01603
35 changed files with 1438 additions and 144 deletions
@@ -1,5 +1,7 @@
# Plan: Model Persistence with Per-Session Overrides
Status: implemented (2026-02-13)
## Summary
This plan fixes model tier persistence so it works correctly across TUI, WebChat, and Telegram channels, and adds per-session model overrides that survive daemon restarts. Currently the model tier is a single global preference stored in `preferences.json` and propagated via `ModelRouter.setTier()`. This creates three problems:
@@ -823,18 +825,20 @@ The `ToolUseEvent` type is the same for both.
## Testing
Validation run on 2026-02-13: `pnpm typecheck`, targeted model-persistence tests, full `pnpm test:run` (1586/1586), and `pnpm build` all passing.
### Unit Tests
- [ ] **`src/session/store.test.ts`**: Test `session_config` CRUD — set, get, getAll, delete, clearAll
- [ ] **`src/session/store.test.ts`**: Test `clearSession()` also clears config
- [ ] **`src/session/store.test.ts`**: Test `pruneStale()` also cleans config
- [ ] **`src/session/manager.test.ts`**: Test `ManagedSession.getConfig/setConfig/deleteConfig`
- [ ] **`src/daemon/routing.test.ts`**: Test model resolution chain (session → agent → global)
- [ ] **`src/daemon/routing.test.ts`**: Test `/model` command sets session config and updates agent tier
- [ ] **`src/daemon/routing.test.ts`**: Test `/reset` command clears session config
- [ ] **`src/gateway/session-bridge.test.ts`**: Test that tier changes in TUI do NOT affect WebChat sessions
- [ ] **`src/gateway/session-bridge.test.ts`**: Test that new agents load tier from session config
- [ ] **`src/gateway/handlers/handlers.test.ts`**: Test `agent.send` with model command
- [x] **`src/session/store.test.ts`**: Test `session_config` CRUD — set, get, getAll, delete, clearAll
- [x] **`src/session/store.test.ts`**: Test `clearSession()` also clears config
- [x] **`src/session/store.test.ts`**: Test `pruneStale()` also cleans config
- [x] **`src/session/manager.test.ts`**: Test `ManagedSession.getConfig/setConfig/deleteConfig`
- [x] **`src/daemon/routing.test.ts`**: Test model resolution chain (session → agent → global)
- [x] **`src/daemon/routing.test.ts`**: Test `/model` command sets session config and updates agent tier
- [x] **`src/daemon/routing.test.ts`**: Test `/reset` command clears session config
- [x] **`src/gateway/session-bridge.test.ts`**: Test that tier changes in TUI do NOT affect WebChat sessions
- [x] **`src/gateway/session-bridge.test.ts`**: Test that new agents load tier from session config
- [x] **`src/gateway/handlers/agent.test.ts`**: Test `agent.send` with model command
### Integration Tests