Skip to content

feat(terminal): версионированные модели вендоров + best-effort Pro/Max квоты#247

Closed
gently-whitesnow wants to merge 1 commit into
masterfrom
feat/terminal-live-models-quotas
Closed

feat(terminal): версионированные модели вендоров + best-effort Pro/Max квоты#247
gently-whitesnow wants to merge 1 commit into
masterfrom
feat/terminal-live-models-quotas

Conversation

@gently-whitesnow

Copy link
Copy Markdown
Owner

Цель

Убрать хардкод списка моделей Claude/Codex в TerminalVendorDescriptors.cs
и опционально показывать оператору использование его Pro/Max подписки —
как минимум 5-часовое окно, где-то и weekly + credits — прямо в панели
запуска терминала.

Основные изменения

  • Metadata-файл vendor-models.json (embedded resource) — единственный
    источник моделей для claude/codex. TerminalVendorDescriptors теперь
    берёт Models через VendorModelMetadata.For(vendor). Правка списка
    моделей — коммит в один файл данных.
  • Best-effort квоты (ADR-0054 §2) — новый порт IVendorQuotaAdapter,
    общий базовый класс HttpVendorQuotaAdapterBase (60с TTL кэш + гарант.
    проглатывание любой ошибки в null) и два конкретных адаптера поверх
    недокументированных GET api.anthropic.com/api/oauth/usage (Claude) и
    GET chatgpt.com/backend-api/wham/usage (ChatGPT).
  • OpenAPI — добавлены TerminalVendorQuotaDto и
    TerminalVendorQuotaWindowDto, опциональное quota поле на
    TerminalVendorMetadataDto. Регенерированы NSwag и openapi-typescript.
  • UI — под селектором моделей появился компактный блок квоты
    (5ч/неделя/credits/reset) + кнопка «Обновить», invalidating catalog
    query. При открытии панели каталог инвалидируется однократно, чтобы
    подтянуть свежее состояние. Блок значений исчезает при quota=null,
    оставляя только Refresh.

Решения

  • Модели — статический JSON, а не live /v1/models. Причины:
    Anthropic Feb-2026 ToS запрещает OAuth-токены вне Claude Code/claude.ai,
    а у Codex /v1/models не существует. /v1/models у Anthropic всё равно
    не фильтрует по подписке оператора — фильтровали бы вручную по allow-list.
  • Квоты — HTTP-проба тех же приватных эндпоинтов, что дёргают сами CLI.
    Failure isolation: одна try/catch на весь цикл в базовом классе,
    ошибочный адаптер → null → блок в UI скрыт, Run никогда не блокируется.
  • ISO 8601 UTC на wire как единый формат reset-стемпа; Codex-специфика с
    Unix seconds уходит внутрь адаптера.

Отброшено

  • Live-фетч /v1/models через OAuth. Ломает ToS, не решает исходный
    запрос «фактические права оператора».
  • Shell-out в claude models / codex models list. Таких команд у CLI нет.
  • Реестр моделей в БД + миграция. Слишком много механики ради 5 строк.
  • Refresh-таймер на клиенте. Кнопка + on-mount invalidate дают явный
    контроль без лишних сетевых спам-запросов.

Ограничения

  • Claude Code на macOS хранит OAuth в Keychain: файл
    ~/.claude/.credentials.json есть не у всех операторов — у большинства
    Claude-квота останется null (Refresh отработает, значений не будет).
    Это документировано в ADR-0054.
  • /wham/usage и /api/oauth/usage — приватные эндпоинты, их изменение
    вендором молча скроет блок до нашей правки схемы адаптера.
  • Обновление vendor-models.json требует релиза нового бинаря — это
    осознанный трейд-офф против live-пробы (см. ADR-0054 § Отброшено).

Как проверить

  1. Открыть панель Run на любом интенте → каталог инвалидируется однократно.
  2. Нажать «Запустить в терминале» — в модалке под селекторами появится
    строка блока квоты. При наличии ~/.claude/.credentials.json или
    актуального ~/.codex/auth.json — значения; иначе — только кнопка
    «Обновить», Run продолжит работать.
  3. Клик по «Обновить» вызывает queryClient.invalidateQueries — сеть
    идёт заново, кнопка блокируется на время refetch.

Тесты

  • Backend: VendorModelMetadataTests (5 кейсов, embedded loading + parse),
    VendorQuotaAdapterTests (9 кейсов, Parse + credentials + cache/failure),
    расширены TerminalVendorCatalogMapperTests (3 новых quota-кейса).
  • Frontend: новый VendorQuotaBlock.test.tsx (3 кейса).
  • verify.sh backend+verify.sh frontend зелёные.

Ссылка на ADR: specs/ADR/0054-terminal-vendor-model-metadata-and-quotas.md.

…ты Pro/Max

Panel запуска теперь тянет модели Claude/Codex из версионированного
`vendor-models.json` (загружается один раз как embedded resource) и
опционально показывает 5ч/недельные квоты подписки. Rest — refresh-кнопка
над панелью (invalidate query catalog) и одноразовый invalidate при
монтировании панели.

Решения:
- Модели — статический JSON, а не live `/v1/models`. Полностью снимает
  риск нарушения Anthropic ToS Feb-2026 (OAuth токены — только под
  Claude Code / claude.ai), устраняет несуществующий у Codex `/v1/models`
  и оставляет apples-to-apples поведение (порядок = native-default-first).
  Обновление вендорного списка — PR-правка одной строки JSON, а не .cs.
- Квоты — best-effort HTTP-адаптер поверх недокументированных
  `/api/oauth/usage` (Claude) и `/backend-api/wham/usage` (ChatGPT).
  Общий базовый класс кэширует ответ 60 сек (совпадает с частотой пуллинга
  CLI-Codex) и гарантированно превращает ЛЮБУЮ ошибку — отсутствие токена,
  401, битую схему — в `null`. Каталог-мэппер видит `null` и прячет блок,
  Run НЕ блокируется по контракту ADR-0054 §2.
- ISO 8601 UTC на wire как единый формат reset-таймстампов; Codex адаптер
  нормализует Unix seconds внутри, вендор-специфика не течёт в UI.
- OpenAPI-контракт расширен опциональным `quota` полем на
  `TerminalVendorMetadataDto` + новыми `TerminalVendorQuotaDto` /
  `TerminalVendorQuotaWindowDto` — фронт получает готовые типы через
  openapi-typescript, ничего не мапит руками.

Отброшено:
- Живые `/v1/models` через OAuth Claude/Codex — Anthropic ToS + Codex
  не имеет эндпоинта, а даже у Claude `/v1/models` не фильтрует по
  подписке оператора (Pro/Max/Team), пришлось бы фильтровать вручную.
- Shell-out в `claude models` / `codex models list` — таких команд не
  существует в текущих CLI.
- Хранение catalog в БД + миграции — тяжело, для 2–3 моделей на вендора
  не окупается.

Ограничения:
- Claude Code хранит OAuth в macOS Keychain; файл `~/.claude/.credentials.json`
  появляется только у операторов, зашедших SSH-friendly-flow или
  явно выставивших `CLAUDE_CONFIG_DIR`. У большинства macOS-пользователей
  Claude-квота останется `null` (Refresh отработает, значений не будет).
- `/wham/usage` и `/api/oauth/usage` — приватные эндпоинты; при их
  изменении квоты молча спрячутся до правки схемы адаптера.
- Изменение `vendor-models.json` требует деплоя нового бинаря (это
  осознанный трейд-офф против live-пробы).
@gently-whitesnow

Copy link
Copy Markdown
Owner Author

Сложная таска пока отложим

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants