"""HUX-06 provider-neutral friendly modes and scoped route selection. Automatic modes express intent to Switchyard and never name a provider. An exact route can only be selected through the explicit advanced path and must exist in the operator-provided route catalog. Private mode is local-only. """ from __future__ import annotations import hashlib import json import os import re from typing import Any from hux import contracts, rules from hux.errors import Conflict, Invalid, NotFound from hux.http import Request, Response, Router, page from hux.store import now_iso CARD = "HUX-06" FAMILY = "mode_selections" MODE_NAMES = ("fast", "thoughtful", "research", "create", "private") MANUAL_ROUTE = re.compile(r"^atlas/manual/(codex|claude|local)/[a-z0-9][a-z0-9/-]{0,100}$") MAX_CATALOG_ROUTES = 256 SCHEMAS = contracts.load_all() def _body(request: Request) -> dict[str, Any]: if not isinstance(request.body, dict): raise Invalid("body must be a JSON object") extra = set(request.body) - {"project_id", "mode", "advanced", "override_route_id"} if extra: raise Invalid("unexpected mode fields", sorted(extra)) return request.body def _scope(request: Request, project_id: Any) -> tuple[dict[str, Any], dict[str, Any]]: """Resolve a conversation and its mandatory owning project.""" from hux import organization try: conversation = request.store.get(organization.CONVERSATIONS, request.params["id"]) except (Invalid, NotFound) as error: raise NotFound("conversation not found") from error path_project = request.params.get("project_id") actual = conversation.get("project_id") if not isinstance(project_id, str) or project_id != path_project or not actual or project_id != actual: raise NotFound("project or conversation not found") try: project = request.store.get(organization.PROJECTS, project_id) except (Invalid, NotFound) as error: raise NotFound("project or conversation not found") from error return project, conversation def _record_id(conversation_id: str) -> str: digest = hashlib.sha256(conversation_id.encode()).hexdigest()[:24] return f"mode_{digest}" def _catalog() -> set[str]: raw = os.environ.get("HUX_SWITCHYARD_ROUTE_CATALOG", "") items = [item.strip() for item in raw.split(",") if item.strip()] if len(items) > MAX_CATALOG_ROUTES: return set() return {item for item in items if MANUAL_ROUTE.fullmatch(item)} def _contract(mode: str, advanced: bool, override: Any) -> dict[str, Any]: if not isinstance(mode, str) or mode not in MODE_NAMES: raise Invalid("unknown friendly mode") if override is not None: if not advanced or not isinstance(override, str) or not MANUAL_ROUTE.fullmatch(override): raise Invalid("an exact route requires a valid advanced manual route") if override not in _catalog(): raise Invalid("advanced route is not in the Switchyard catalog") if mode == "private" and not override.startswith("atlas/manual/local/"): raise Invalid("private mode is local-only") elif advanced: raise Invalid("advanced selection requires override_route_id") try: result = rules.mode_contract(mode, override) except ValueError as error: raise Invalid(str(error)) from error problems = contracts.validate("mode.schema.json", result, SCHEMAS) if problems: raise Invalid("mode failed contract validation", problems) if mode != "private" and result["switchyard"]["route_id"].startswith("atlas/manual/"): raise Invalid("automatic modes may not pin a provider") return result def _fingerprint(body: dict[str, Any]) -> str: allowed = {key: body.get(key) for key in ("project_id", "mode", "advanced", "override_route_id")} return hashlib.sha256(json.dumps(allowed, sort_keys=True, separators=(",", ":")).encode()).hexdigest() def _replay(request: Request, key: str, fingerprint: str) -> dict[str, Any] | None: for row in request.store.read(FAMILY, "idempotency"): if row.get("key") != key: continue if row.get("fingerprint") != fingerprint: raise Conflict("Idempotency-Key was already used for a different selection") return request.store.get(FAMILY, row["id"]) return None def list_modes(request: Request) -> Response: """Return all provider-neutral mode contracts.""" items = [_contract(name, False, None) for name in MODE_NAMES] request.audit("modes.list", "modes") return page(items) def get_selection(request: Request) -> Response: """Return the selected mode for one bound conversation.""" project_id = request.params["project_id"] _, conversation = _scope(request, project_id) record = request.store.get(FAMILY, _record_id(conversation["id"])) request.audit("modes.read", record["id"]) return Response(200, record, {"ETag": str(record["revision"]), "Cache-Control": "no-store"}) def put_selection(request: Request) -> Response: """Select a mode using If-Match and Idempotency-Key.""" body = _body(request) _, conversation = _scope(request, body.get("project_id")) key = request.idempotency_key() if not key: raise Invalid("Idempotency-Key is required") expected = request.if_match() if expected is None: raise Invalid("If-Match is required; use 0 for the first selection") fingerprint = _fingerprint(body) mode = _contract(body.get("mode"), body.get("advanced") is True, body.get("override_route_id")) record_id = _record_id(conversation["id"]) with request.store.lock(FAMILY): replayed = _replay(request, key, fingerprint) if replayed is not None: request.audit("modes.select", replayed["id"], reason="idempotent_replay") return Response(200, replayed, {"ETag": str(replayed["revision"]), "HUX-Replayed": "true", "Cache-Control": "no-store"}) exists = request.store.exists(FAMILY, record_id) if expected != (request.store.get(FAMILY, record_id)["revision"] if exists else 0): raise Conflict("mode selection revision does not match If-Match") stamp = now_iso() record = { "id": record_id, "schema": "hux.mode_selection.v1", "owner": request.identity.subject, "project_id": body["project_id"], "conversation_id": conversation["id"], "mode": mode, "updated_at": stamp, } stored = request.store.put(FAMILY, record, expected_revision=expected) request.store.append(FAMILY, "idempotency", {"key": key, "fingerprint": fingerprint, "id": record_id, "at": stamp}) with request.store.lock("conversations"): current = request.store.get("conversations", conversation["id"]) request.store.put("conversations", {**current, "mode": mode["mode"], "updated_at": stamp}, current["revision"]) request.audit("modes.select", record_id) return Response(200, stored, {"ETag": str(stored["revision"]), "Cache-Control": "no-store"}) def register(router: Router) -> None: """Attach HUX-06 routes.""" router.add("GET", "/hux/v1/modes", CARD, "modes.list", list_modes) router.add("GET", "/hux/v1/projects/{project_id}/conversations/{id}/mode", CARD, "modes.read", get_selection) router.add("PUT", "/hux/v1/projects/{project_id}/conversations/{id}/mode", CARD, "modes.select", put_selection)