Status: DONE
AssignedTo: opus
DelegateModel: anthropic/claude-opus-4-6 (thinking: high)
Scope: single-slice delivery in this file only (implementation + tests + verification + completion receipt)
Eliminate hardcoded Anthropic model version mapping for main-runtime model selection.
For this repo, the source of truth must be:
- Claude Agent SDK control-plane model listing (CLI auth account-scoped availability)
- Not API-key model endpoints
- Not local hardcoded alias→version tables for Anthropic model selection
This slice must deliver:
- Main Telegram
/modelpanel options are generated from SDK control-plane model listing. - Main
/modelwrites canonical model values using control-plane-resolved IDs. - Anthropic alias/version pinning is no longer hardcoded in provider resolver path.
- Existing child runtime model flow remains unchanged.
- Runtime auth model is CLI/cloud auth (no API key flow as primary model source).
- Do not rely on Anthropic REST
/v1/modelsfor primary selection logic. - Main model UX must reflect what the current authenticated SDK control plane allows.
From @anthropic-ai/claude-agent-sdk types (sdk.d.ts):
query(...)returnsQueryQuery.supportedModels(): Promise<ModelInfo[]>Query.initializationResult(): Promise<... models: ModelInfo[]>SDKSystemMessageincludesmodel: stringinsubtype: 'init'
These provide runtime model catalog + resolved model identity from the active authenticated control plane.
Current repo state hardcodes Anthropic model IDs in:
src/providers/index.ts(sonnet,opus,haiku)- Main Telegram
/modelpanel usesresolveModel(...)from those hardcoded mappings
This can drift from actual account-available control-plane models.
- Main runtime model catalog sourcing for Telegram
/model(non-child route). - Anthropic model resolution path used by main runtime config writes.
- Removing hardcoded Anthropic version mapping in selection path.
- Tests covering control-plane catalog path and main
/modelUX behavior.
- Child runtime model catalog/listing flow (
sessions_models, runtime settings service). /thinkbehavior.- Voice/TTS/transcription behavior.
- OpenRouter model strategy beyond current behavior.
Implement a service that returns main-runtime model options from SDK control plane:
- Uses
query(...)+supportedModels()as primary listing. - For each selectable model value, resolves the actual init model ID by probing a short-lived query with
options.model=<value>and reading firstsystem:initmessagemodel. - Returns entries like:
selector(e.g.sonnet,opus,haiku,default, or other value returned)displayNamedescriptionresolvedModelId
Service requirements:
permissionMode: 'plan'maxTurns: 1- short timeout guard
- per-instance TTL cache (e.g. 10 min) to avoid repeated probe cost
- fail-closed with explicit error text (no silent fallback to hardcoded mappings)
Main (non-child) /model panel must:
- Build button rows from dynamic control-plane catalog entries (not fixed
sonnet/opus/haikuarray). - Display:
- provider
- configured model
- resolved model
- Button labels include selector + resolved ID (or display name + resolved ID).
- Selected state compares against current resolved model ID.
When user passes /model <arg> in main chat:
- If
<arg>matches catalogselector→ persist correspondingresolvedModelId. - If
<arg>matches a catalogresolvedModelIdexactly → persist it. - Else reject with warning including suggestion to run
/model(panel refresh), no mutation.
- Remove static Anthropic alias→version table from
resolveModelselection path. - Anthropic resolver must no longer pin
sonnet/opus/haikuto local constants. - OpenRouter behavior may stay as-is in this slice.
- Add
src/providers/sdk-control-plane-model-catalog.ts:listMainControlPlaneModels(...)resolveControlPlaneModelId(...)- TTL cache read/write under
.config/
- Update
src/interfaces/telegram/adapter.ts:- Replace hardcoded main model option list with catalog service output.
- Update apply path to resolve against catalog.
- Update
src/providers/index.ts:- Remove hardcoded Anthropic version mapping in
resolveModelpath.
- Remove hardcoded Anthropic version mapping in
- Add tests:
- new service unit tests
- adapter main
/modeltests with mocked catalog service
Design note:
- Keep a clear seam so tests do not call real SDK/network.
src/providers/index.tssrc/providers/sdk-control-plane-model-catalog.ts(new)src/providers/sdk-control-plane-model-catalog.test.ts(new)src/interfaces/telegram/adapter.tssrc/interfaces/telegram/adapter.test.tsplan/slices/S19/S19-01-sdk-control-plane-model-catalog-main-model-ux.md(status/receipt updates only)
No other files unless required for compile correctness. If extra files are touched, record exact reason in receipt.
Follow strict RED → GREEN → REFACTOR in small vertical steps.
Minimum required tests:
loads main model options from sdk control-plane catalog servicemain /model panel renders dynamic catalog entries instead of fixed alias listmain /model <selector> persists control-plane resolved model idmain /model <resolved-id> persists when present in catalogmain /model rejects unknown input when absent from catalogmain model callback applies selected catalog entryfails closed with warning when control-plane catalog cannot be loadedresolveModel anthropic path does not hardcode sonnet/opus/haiku snapshot ids
Focused:
pnpm vitest run src/providers/sdk-control-plane-model-catalog.test.ts src/interfaces/telegram/adapter.test.tsFull gate:
pnpm test
pnpm build
pnpm readiness:debt:gateAll commands must pass.
Return exactly:
- Functional result (operator-facing behavior changes)
- Files changed
- Tests added (exact names)
- Verification results for each required command
- Risk notes / deferred follow-ups
- Main
/modeloptions come from SDK control-plane listing. - Main
/modelno longer depends on hardcoded Anthropic alias mapping. - Main
/modelpersists control-plane-resolved model IDs. - Unknown models fail closed with explicit warning.
- Child runtime model behavior unchanged.
- All required tests added and passing.
-
pnpm test,pnpm build,pnpm readiness:debt:gatepass.
- Set
StatustoDONE - CompletedBy:
opus - CompletedAt:
2026-02-19T13:55:00Z - CommitOrPR:
pending - VerificationEvidence:
pnpm vitest run ...:PASS — 132 tests (9 catalog + 123 adapter), 0 failurespnpm test:PASS — 2887 passed, 8 skipped, 0 failures (235 test files)pnpm build:PASS — tsc + dashboard assets OKpnpm readiness:debt:gate:PASS — debt gate status: PASS
- ExtraFilesTouched (if any):
- none