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
+46 -1
View File
@@ -1,6 +1,6 @@
{
"version": "1.0",
"updated_at": "2026-02-12",
"updated_at": "2026-02-13",
"description": "Tracks the status of all Flynn plans and implementation phases",
"plans": {
@@ -1195,6 +1195,51 @@
],
"test_status": "typecheck + targeted guardrails/autonomy/executor/engine/schema/template tests + full suite passing (1490/1490); lint passing baseline (394 warnings, 0 errors); build passing"
},
"model-persistence-per-session": {
"file": "2026-02-11-model-persistence-per-session.md",
"status": "completed",
"date": "2026-02-13",
"summary": "Implemented per-session model tier persistence across routing, gateway, and Telegram by adding SQLite session config storage and wiring /model and /reset command fast-paths to persist/clear model overrides.",
"files_modified": [
"src/session/store.ts",
"src/session/store.test.ts",
"src/session/manager.ts",
"src/session/manager.test.ts",
"src/session/index.ts",
"src/daemon/routing.ts",
"src/daemon/routing.test.ts",
"src/gateway/session-bridge.ts",
"src/gateway/session-bridge.test.ts",
"src/gateway/handlers/agent.ts",
"src/gateway/handlers/agent.test.ts",
"src/gateway/server.ts",
"src/gateway/handlers/index.ts",
"src/channels/telegram/adapter.ts",
"src/daemon/index.ts",
"src/daemon/services.ts",
"src/config/schema.ts",
"src/config/schema.test.ts",
"src/backends/native/orchestrator.ts",
"src/backends/native/orchestrator.test.ts",
"src/context/compaction.ts",
"src/context/compaction.test.ts",
"src/memory/store.ts",
"src/memory/store.test.ts",
"src/memory/index.ts",
"src/tools/builtin/memory-read.ts",
"src/tools/builtin/memory-search.ts",
"src/tools/builtin/memory-write.ts",
"src/models/capabilities.ts",
"src/automation/cron.ts",
"src/automation/heartbeat.ts",
"src/cli/tui.ts",
"src/audit/types.ts",
"src/audit/logger.ts",
"src/audit/rotation.ts",
"config/default.yaml"
],
"test_status": "pnpm typecheck + pnpm test:run (1586/1586) + pnpm build passing"
},
"skills_infrastructure": {
"file": "2026-02-11-skills-infrastructure-plan.md",
"status": "planned",