mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(routing): cost-tiered complexity routing + saved presets (#656)
The 08-31 lever: model_assignments gains one compound rung —
AGENT_SLUG > ROLE('{role}:{complexity}') > ROLE > GLOBAL — so a
low-complexity task can route to a cheaper tier while coordinators stay
pinned. Structurally opt-in: zero rows means byte-identical routing
(pinned by a named test across every precedence case), the cost_tiered
apply-mode (seeds developer:low→haiku) is reachable only from the
explicit PM-gated endpoint — verified no startup path can apply it.
Overrides are downgrade-only (input-price comparator), allowlisted to
{developer, qa, documenter} — cell_pm excluded per the org's own
coordinator definition and its documented weak-model incidents — and
validated at write time (disabled/unconfigured provider rejected with
remediation; cross-provider-family overrides warn explicitly).
Per adversarial review: the four mode-switch applies now spare compound
rows exactly like agent pins (the 2026-07-17 unscoped-wipe class, new
victim, same fix extended via one shared wipe helper) with panel cache
invalidation + truthful confirm dialogs; preset apply validates the
entire payload BEFORE the wipe (validate-all-first), with a savepoint
crash test proving rollback.
Presets (CEO request): routing_presets table (migration 082) snapshots
the full mix — mode, per-agent overrides, complexity rows — with
save/apply/delete endpoints and a panel preset bar; applying skips
since-removed models with per-entry notes, never silently.
Task complexity threads task_id through _resolve_agent_route at both
call sites; taskless spawns unchanged. 235 backend + 23 panel tests.
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
"""Routing presets — named, full snapshots of the AI-routing state.
|
||||
|
||||
Lets an operator save the current routing state (mode + every
|
||||
`model_assignments` row: GLOBAL / plain ROLE / compound ROLE(":"complexity)
|
||||
cost-tier overrides / AGENT_SLUG pins) under a name and re-apply it later in
|
||||
one call, instead of re-picking every per-agent Select. ``payload`` mirrors
|
||||
exactly what ``GET /providers`` + ``GET /providers/complexity-overrides``
|
||||
already serve, so a preset is "what the card currently shows" — see
|
||||
``ModelRoutingService.save_routing_preset`` / ``apply_routing_preset``
|
||||
(roboco/services/llm.py). Pure additive new table; no backfill, no data
|
||||
migration — applying a preset is the only thing that ever mutates
|
||||
``model_assignments`` as a side effect, and only on an explicit call.
|
||||
|
||||
Revision ID: 082_routing_presets
|
||||
Revises: 081_doctrine_version
|
||||
Create Date: 2026-07-23
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
revision = "082_routing_presets"
|
||||
down_revision = "081_doctrine_version"
|
||||
branch_labels: dict[str, str] | None = None
|
||||
depends_on: dict[str, str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.create_table(
|
||||
"routing_presets",
|
||||
sa.Column("id", sa.UUID(as_uuid=True), primary_key=True),
|
||||
sa.Column("name", sa.String(length=100), nullable=False),
|
||||
sa.Column("payload", postgresql.JSONB(), nullable=False),
|
||||
sa.Column(
|
||||
"created_at",
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=False,
|
||||
server_default=sa.text("now()"),
|
||||
),
|
||||
sa.UniqueConstraint("name", name="uq_routing_presets_name"),
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_table("routing_presets")
|
||||
Reference in New Issue
Block a user