Add the declarative worker registry that epic #797 makes the source of truth for the scheduled multi-LLM worker fleet. Providers and configured workers are modelled as separate entities so a provider can be listed with no worker configured, and so provider facts are not copied into every worker record. A worker records provider, model, project, role, namespace, profile, workflow, schedule, timeout, enabled state, and scheduler metadata. Validation fails closed: unknown fields are refused rather than ignored, so a typo cannot silently disable a timeout; a worker naming an undeclared provider is rejected; worker ids, provider ids, and LaunchAgent labels must be unique. Persistence is atomic (temp file in the same directory, fsync, replace). Every superseded document is retained as a numbered revision, and rollback republishes a chosen revision as a new head, so history stays append-only and a rollback is itself reversible. The credential-rejection guard is extracted to webui/registry_safety.py so both registries share one implementation instead of two copies of a security check; project_registry.py keeps identical behaviour. Scope: data model, validation, persistence only. No routes, scheduler, process control, or provider probing - those are #799/#800/#804/#805. The workers array ships empty because populating it is #808. Tests: tests/test_webui_worker_registry.py, 44 cases. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
58 lines
1.6 KiB
JSON
58 lines
1.6 KiB
JSON
{
|
|
"version": 1,
|
|
"revision": 1,
|
|
"updated_at": "2026-07-22T00:00:00Z",
|
|
"providers": [
|
|
{
|
|
"id": "claude",
|
|
"display_name": "Claude",
|
|
"vendor": "Anthropic",
|
|
"executable": "claude",
|
|
"available": true,
|
|
"models": [
|
|
"claude-opus-4-8",
|
|
"claude-sonnet-5",
|
|
"claude-haiku-4-5-20251001"
|
|
],
|
|
"notes": "Model list is a declaration. Live enumeration and version inspection belong to the provider adapter framework (#800)."
|
|
},
|
|
{
|
|
"id": "grok",
|
|
"display_name": "Grok",
|
|
"vendor": "xAI",
|
|
"executable": "grok",
|
|
"available": true,
|
|
"models": [],
|
|
"notes": "Models enumerated by the provider adapter (#800); not declared here."
|
|
},
|
|
{
|
|
"id": "codex",
|
|
"display_name": "Codex",
|
|
"vendor": "OpenAI",
|
|
"executable": "codex",
|
|
"available": true,
|
|
"models": [],
|
|
"notes": "Models enumerated by the provider adapter (#800); not declared here."
|
|
},
|
|
{
|
|
"id": "agy",
|
|
"display_name": "AGY",
|
|
"vendor": "Antigravity",
|
|
"executable": "agy",
|
|
"available": true,
|
|
"models": [],
|
|
"notes": "MCP allowlist gating applies to this provider; confirm server-side allowlist before configuring a worker."
|
|
},
|
|
{
|
|
"id": "kimi-k",
|
|
"display_name": "Kimi K",
|
|
"vendor": "Moonshot AI",
|
|
"executable": "kimi",
|
|
"available": true,
|
|
"models": [],
|
|
"notes": "Provider id is kimi-k; the executable on PATH is kimi. Models enumerated by the provider adapter (#800)."
|
|
}
|
|
],
|
|
"workers": []
|
|
}
|