Changeset 0.22.2 (#96)

This commit is contained in:
2026-03-02 10:31:18 +00:00
parent cae6fd9f93
commit a44c768741
20 changed files with 1563 additions and 22 deletions

View File

@@ -2,6 +2,40 @@
All notable changes to Chat Switchboard.
## [0.22.2] — 2026-03-02
### Added
- **Routing policy engine.** Rules-based request routing evaluated between "what model was requested" and "which provider serves it." `routing/` package with evaluator, fallback runner, and type-safe policy model.
- **`provider_prefer`**: Ordered list of preferred provider configs — fallback to others if preferred are unavailable.
- **`team_route`**: Restrict a team to only use specific provider configs (team-scoped access control).
- **`cost_limit`**: Filter out providers above a heuristic cost threshold per request.
- **`model_alias`**: Map alias names ("fast", "smart") to specific provider+model pairs.
- **Health-aware routing.** Candidates sorted by health status (healthy > degraded > unknown > down). `skip_down` flag removes down providers from consideration when healthy alternatives exist. All-down graceful degradation: keeps candidates rather than returning empty.
- **Fallback runner.** `routing.RunWithFallback()` tries candidates in order with configurable retry depth. Logs each failure and tries the next candidate. Returns the winning candidate and updated decision with fallback depth.
- **`routing_policies` table.** New migration (Postgres 014, SQLite 013) with scope (global/team), priority ordering, JSONB config, and active flag. Index on `(is_active, priority)` for efficient policy loading.
- **Routing policy admin CRUD.** Full REST API for policy management:
- `GET /api/v1/admin/routing/policies` — list all policies
- `GET /api/v1/admin/routing/policies/:id` — get single policy
- `POST /api/v1/admin/routing/policies` — create policy (validates type, scope, team_id)
- `PUT /api/v1/admin/routing/policies/:id` — update policy
- `DELETE /api/v1/admin/routing/policies/:id` — delete policy
- **Dry-run routing test.** `POST /api/v1/admin/routing/test` accepts model + user_id + team_ids, evaluates active policies against all global provider configs with live health status, returns ranked candidates and the routing decision.
- **`X-Switchboard-Provider` response header.** Every completion response includes `providerID/configID` for routing observability.
- **`routing_decision` column on `usage_log`.** JSONB field for recording which policy matched, fallback depth, and total candidates evaluated.
- **`RoutingPolicyStore` interface** with Postgres and SQLite implementations. Supports Create, Update, Delete, GetByID, ListActive, ListAll, ListForTeam.
- **12 evaluator tests.** Coverage: no policies, provider_prefer ordering, team_route filtering (including wrong-team no-op), model_alias rewrite, health skip-down, health sorting, all-down graceful degradation, priority ordering, empty candidates, inactive policy skip.
### Changed
- `models/models.go`: Added `RoutingPolicy` struct and `RoutingDecision` field on `UsageEntry`.
- `store/interfaces.go`: Added `RoutingPolicyStore` interface and `RoutingPolicies` field on `Stores`.
- `store/postgres/stores.go`, `store/sqlite/stores.go`: Wired `RoutingPolicyStore` into factory.
- `handlers/completion.go`: Added `router`, `healthStore` fields. `HealthStatusQuerier` interface. `evaluateRouting()` method builds candidates from accessible configs, queries health status, runs evaluator, reloads credentials on config switch. `X-Switchboard-Provider`, `X-Switchboard-Route`, `X-Switchboard-Fallback` response headers.
- `main.go`: Creates `routing.Evaluator`, wires into completion handler via `SetRoutingEvaluator()` and `SetHealthStore()`. Registers 6 admin routing routes.
### Database
- Postgres: `server/database/migrations/014_v0222_routing.sql`
- SQLite: `server/database/migrations/sqlite/013_v0222_routing.sql`
## [0.22.1] — 2026-03-02
### Added