Разрешение провайдера во время выполнения
VibeOS имеет общий механизм разрешения провайдера, используемый в:
- CLI
- gateway
- cron-задачах
- ACP
- вызовах вспомогательных моделей
Основная реализация:
vibeos_cli/runtime_provider.py— разрешение учетных данных,_resolve_custom_runtime()vibeos_cli/auth.py— реестр провайдеров,resolve_provider()vibeos_cli/model_switch.py— общий конвейер переключения/model(CLI + gateway)agent/auxiliary_client.py— маршрутизация вспомогательных моделейproviders/— ABC + точки входа в реестр (ProviderProfile,register_provider,get_provider_profile,list_providers)plugins/model-providers/<name>/— плагины для каждого провайдера (встроенные), которые объявляютapi_mode,base_url,env_vars,fallback_modelsи регистрируют себя в реестре при первом обращении. Пользовательские плагины в$VIBEOS_HOME/plugins/model-providers/<name>/переопределяют встроенные с тем же именем.
get_provider_profile() в providers/ возвращает ProviderProfile для заданного идентификатора провайдера. runtime_provider.py вызывает это во время разрешения, чтобы получить канонические base_url, список приоритетов env_vars, api_mode и fallback_models без необходимости дублировать эти данные в нескольких файлах. Добавление нового плагина в plugins/model-providers/<your-provider>/ (или $VIBEOS_HOME/plugins/model-providers/<your-provider>/), который вызывает register_provider(), достаточно, чтобы runtime_provider.py его подхватил — никаких ветвлений в самом механизме разрешения не требуется.
Если вы пытаетесь добавить нового первоклассного провайдера вывода, прочитайте Добавление провайдеров и Руководство по плагину провайдера модели вместе с этой страницей.
Приоритет разрешения
На высоком уровне разрешение провайдера использует:
- явный запрос CLI/времени выполнения
- конфигурацию модели/провайдера в
config.yaml - переменные окружения
- специфичные для провайдера значения по умолчанию или автоматическое разрешение
Этот порядок важен, потому что VibeOS рассматривает сохраненный выбор модели/провайдера как источник истины для обычных запусков. Это предотвращает бесшумное переопределение конечной точки, которую пользователь последний раз выбрал в vibeos model, устаревшим экспортом оболочки.
Провайдеры
Текущие семейства провайдеров включают (полный встроенный набор см. в plugins/model-providers/):
- OpenRouter
- Nous Portal
- OpenAI Codex
- Copilot / Copilot ACP
- Anthropic (нативный)
- Google / Gemini (
gemini) - Alibaba / DashScope (
alibaba,alibaba-coding-plan) - DeepSeek
- Z.AI
- Kimi / Moonshot (
kimi-coding,kimi-coding-cn) - MiniMax (
minimax,minimax-cn,minimax-oauth) - Kilo Code
- Hugging Face
- OpenCode Zen / OpenCode Go
- AWS Bedrock
- Azure Foundry
- NVIDIA NIM
- xAI (Grok)
- Arcee
- GMI Cloud
- StepFun
- Qwen OAuth
- Xiaomi
- Ollama Cloud
- LM Studio
- Tencent TokenHub
- Custom (
provider: custom) — первоклассный провайдер для любой совместимой с OpenAI конечной точки - Именованные кастомные провайдеры (список
custom_providersвconfig.yaml)
Результат разрешения во время выполнения
Механизм разрешения возвращает такие данные, как:
providerapi_modebase_urlapi_keysource- специфичные для провайдера метаданные, такие как информация об истечении/обновлении
Почему это важно
Этот механизм разрешения является основной причиной, по которой VibeOS может разделять логику аутентификации/выполнения между:
vibeos chat- обработкой сообщений gateway
- cron-задачами, запускаемыми в новых сессиях
- сессиями редактора ACP
- задачами вспомогательных моделей
OpenRouter и кастомные базовые URL, совместимые с OpenAI
VibeOS содержит логику для предотвращения утечки неверного ключа API на кастомную конечную точку, когда существует несколько ключей провайдера (например, OPENROUTER_API_KEY и OPENAI_API_KEY).
Ключ API каждого провайдера привязан к своему базовому URL:
OPENROUTER_API_KEYотправляется только на конечные точкиopenrouter.aiOPENAI_API_KEYиспользуется для кастомных конечных точек и в качестве запасного варианта
VibeOS также различает:
- реальную кастомную конечную точку, выбранную пользователем
- запасной путь OpenRouter, используемый, когда кастомная конечная точка не настроена
Это различие особенно важно для:
- локальных серверов моделей
- совместимых с OpenAI API, отличных от OpenRouter
- переключения провайдеров без повторного запуска настройки
- сохраненных в конфигурации кастомных конечных точек, которые должны продолжать работать, даже если
OPENAI_BASE_URLне экспортирован в текущей оболочке
Нативный путь Anthropic
Anthropic теперь не просто «через OpenRouter».
Когда разрешение провайдера выбирает anthropic, VibeOS использует:
api_mode = anthropic_messages- нативный API Messages от Anthropic
agent/anthropic_adapter.pyдля трансляции
Разрешение учетных данных для нативного Anthropic теперь предпочитает обновляемые учетные данные Claude Code скопированным токенам окружения, когда присутствуют оба. На практике это означает:
- файлы учетных данных Claude Code рассматриваются как предпочтительный источник, когда они включают обновляемую аутентификацию
- ручные значения
ANTHROPIC_TOKEN/CLAUDE_CODE_OAUTH_TOKENвсе еще работают как явные переопределения - VibeOS выполняет предварительную проверку обновления учетных данных Anthropic перед вызовами нативного Messages API
- VibeOS все еще повторяет попытку один раз при 401 после перестроения клиента Anthropic в качестве запасного пути
Путь OpenAI Codex
Codex использует отдельный путь Responses API:
api_mode = codex_responses- выделенное разрешение учетных данных и поддержка хранилища аутентификации
Маршрутизация вспомогательных моделей
Вспомогательные задачи, такие как:
- vision
- обобщение извлечения веб-страниц
- сводки сжатия контекста
- операции skills hub
- операции MCP helper
- сброс памяти
могут использовать свою собственную маршрутизацию провайдера/модели, а не основную диалоговую модель.
Когда вспомогательная задача настроена с провайдером main, VibeOS разрешает ее через тот же общий путь выполнения, что и обычный чат. На практике это означает:
- управляемые окружением кастомные конечные точки все еще работают
- кастомные конечные точки, сохраненные через
vibeos model/config.yaml, также работают - вспомогательная маршрутизация может отличить реальную сохраненную кастомную конечную точку от запасного пути OpenRouter
Запасные модели
VibeOS поддерживает настроенную цепочку запасных провайдеров — список записей (provider, model), перебираемых по порядку, когда основная модель сталкивается с ошибками. Устаревший словарь fallback_model с одной парой все еще принимается для обратной совместимости (и мигрируется при первой записи).
Как это работает внутри
-
Хранение:
AIAgent.__init__сохраняет словарьfallback_modelи устанавливает_fallback_activated = False. -
Точки срабатывания:
_try_activate_fallback()вызывается из трех мест в основном цикле повторных попыток вrun_agent.py:- После максимального количества повторных попыток при недопустимых ответах API (отсутствие choices, отсутствие содержимого)
- При не подлежащих повторению клиентских ошибках (HTTP 401, 403, 404)
- После максимального количества повторных попыток при временных ошибках (HTTP 429, 500, 502, 503)
-
Поток активации (
_try_activate_fallback):- Возвращает
Falseнемедленно, если уже активирован или не настроен - Вызывает
resolve_provider_client()изauxiliary_client.pyдля создания нового клиента с правильной аутентификацией - Определяет
api_mode:codex_responsesдля openai-codex,anthropic_messagesдля anthropic,chat_completionsдля всего остального - Заменяет на месте:
self.model,self.provider,self.base_url,self.api_mode,self.client,self._client_kwargs - Для запасного варианта anthropic: создает нативный клиент Anthropic вместо совместимого с OpenAI
- Повторно оценивает кэширование подсказок (включено для моделей Claude на OpenRouter)
- Устанавливает
_fallback_activated = True— предотвращает повторный запуск - Сбрасывает счетчик повторных попыток на 0 и продолжает цикл
- Возвращает
-
Поток конфигурации:
- CLI:
cli.pyчитаетCLI_CONFIG["fallback_model"]→ передает вAIAgent(fallback_model=...) - Gateway:
gateway/run.py._load_fallback_model()читаетconfig.yaml→ передает вAIAgent - Валидация: оба ключа
providerиmodelдолжны быть непустыми, иначе запасной вариант отключен
- CLI:
Что НЕ поддерживает запасной вариант
- Делегирование сабагента (
tools/delegate_tool.py): сабагенты наследуют провайдера родителя, но не конфигурацию запасного варианта - Вспомогательные задачи: используют свою собственную независимую цепочку автоопределения провайдера (см. Маршрутизацию вспомогательных моделей выше)
Cron-задачи поддерживают запасной вариант: run_job() читает fallback_providers (или устаревший fallback_model) из config.yaml и передает его в AIAgent(fallback_model=...), соответствуя шаблону _load_fallback_model() из gateway. См. Внутреннее устройство Cron.
Тестовое покрытие
Поведение запасного варианта проверяется в нескольких наборах тестов:
tests/run_agent/test_fallback_credential_isolation.py— изоляция учетных данных между основным и запасным вариантамиtests/vibeos_cli/test_fallback_cmd.py— команда CLI/fallbacktests/gateway/test_fallback_eviction.py— вытеснение отказавших провайдеров в gateway