Адаптеры
Адаптер выполняет преобразование между внутренней моделью запросов/ответов opencodex и
wire-форматом одного провайдера. Каждый адаптер реализует интерфейс ProviderAdapter
(src/adapters/base.ts):
interface ProviderAdapter { name: string; buildRequest(parsed, incoming?): AdapterRequest | Promise<AdapterRequest>; fetchResponse?(request, context): Promise<Response>; // custom retry/transport parseStream(response): AsyncGenerator<AdapterEvent>; parseResponse?(response): Promise<AdapterEvent[]>; // non-streaming runTurn?(parsed, incoming, emit): Promise<void>; // bidirectional transport}buildRequest понижает OcxParsedRequest до HTTP-запроса к вышестоящему провайдеру;
parseStream / parseResponse поднимают ответ провайдера обратно во внутренние события
AdapterEvent. fetchResponse позволяет адаптеру самому управлять повторными попытками и
таймаутами, а runTurn поддерживает транспорты, которые нельзя представить как один HTTP-запрос
с последующим одним потоком ответа. Затем bridge.ts
превращает события в Responses SSE.
openai-chat
Заголовок раздела «openai-chat»Назначение: OpenAI Chat Completions (POST {baseUrl}/chat/completions) и все совместимые
провайдеры — xAI, Kimi, DeepSeek, GLM, Groq, OpenRouter, Ollama (локально) и другие.
Аутентификация: key (Bearer).
- Преобразует внутренние сообщения в роли OpenAI; инструменты отображаются в
{type:"function", function:{…}}иtool_choice(auto/none/requiredили именованная функция). - Изображения из результатов инструментов отправляются отдельным последующим user-сообщением
(части
image_url) после закрытия раунда инструментов, так как содержимоеrole:"tool"может быть только текстом; маркер[image]остаётся в сообщении инструмента как якорь. - Переписывает идентификационный промпт Codex про GPT-5 в модельно-нейтральное вступление, чтобы маршрутизируемые модели не заявляли, что они от OpenAI.
- Прижимает
reasoning_effortк объявленному моделью подмножеству, когда точный уровень недоступен;xhighиmaxостаются разными метками, если провайдер явно не настроил alias. Для id изprovider.noReasoningModelsадаптер полностью опускает этот параметр. - Стримит
delta.content(текст),delta.reasoning_content(thinking) иdelta.tool_calls[]; собираетusage. - ClinePass использует проверенный на живом API формат шлюза
reasoning: { enabled: true, effort }(или{ enabled: false }, когда reasoning отключён); в публичной документации API этот формат запроса пока не указан. Адаптер сохраняет запрошенный уровеньlow,medium,high,xhighилиmax, принимает reasoning delta изdelta.reasoning_contentилиdelta.reasoning, запрашивает usage потока черезstream_options.include_usageи читает usage из envelope нестримингового ответа.
ollama-native
Заголовок раздела «ollama-native»Цели: собственный Chat API Ollama (POST /api/chat) вместо его OpenAI-совместимой
поверхности. Встроенный провайдер ollama-cloud выбирается на этот адаптер реестром; его также
можно настроить для отдельного пользовательского или self-hosted провайдера Ollama с
adapter: "ollama-native".
Аутентификация: key (Bearer) для cloud/пользовательских адресов; учётные данные не
отправляются на loopback-цели и при authMode: "local".
- Выбор через реестр имеет решающее значение. Встроенная строка
ollama-cloudсохраняет базовый URLhttps://ollama.com/v1для живого обнаружения через/v1/models, тогда как вывод нормализуется наPOST https://ollama.com/api/chat. Настроенный уровеньadapterдля этой строки провайдера отбрасывается. Обычный встроенный локальный Ollama остаётся наopenai-chat; выборollama-nativeдля локального или self-hosted адреса — это явное решение конфигурации провайдера, определяемое по хосту, так что не-Ollama назначение никогда не переписывается молча. - Метаданные моделей:
/v1/modelsне несёт метаданных по моделям, поэтому для канонического Ollama Cloud провайдер дополняет каждый обнаружённый id через ограниченныйPOST /api/show(256 KiB на ответ, 8 с на запрос, параллельность 4, 48 запросов, дедлайн 12 с на всю фазу), чтобы получить реальное окно контекста и поддержку зрения. Запрос show — того же источника и никогда не следует за перенаправлением; сбой деградирует только эту модель и не ломает обнаружение. - Стриминг: нативный NDJSON Ollama. Дельты текста и
message.thinkingпересылаются по мере поступления; ход завершается только по терминальной записиdone: true, а буферизованныйdone: falseили отсутствующий терминал полностью подавляют частичный текст и вызовы инструментов. - Reasoning: отображается на нативное поле
thinkOllama (low/medium/high/max, плюс булевы значения), зажимается до заявленной лестницы модели и соблюдает семантику sentinel__omit__, настроенную выше по стеку. - Изображения: отправляются нативно в массиве
imagesсообщения, если модель поддерживает зрение; видео отклоняется, а не отправляется неверно, удалённые URL изображений не загружаются. - Инструменты: объявляются в нативной форме Ollama; стриминговые вызовы инструментов —
цельные записи с
argumentsв виде объекта, а повтор результатов инструментов строго сопоставляется по id вызова и имени инструмента.tool_choice: "none"иautoработают обычно;requiredили точное именованное значение завершается ошибкой, потому что/api/chatOllama не имеет поляtool_choice, которым его можно было бы навязать. - Структурированный вывод отклоняется на каноническом Ollama Cloud. Ollama в документации
указывает, что структурированные выходные данные сейчас не поддерживаются в его Cloud, и Cloud не
соблюдает поле
format, поэтому OpenCodex закрывает такой запрос с ошибкой, а не возвращает свободную прозу в ответ на запрос с указанием схемы. Локальные и пользовательскиеollama-nativeконечные точки сохраняют нативное отображениеformatOllama (json_object→"json",json_schema→ сам объект схемы).
openai-responses
Заголовок раздела «openai-responses»Назначение: OpenAI Responses API. passthrough: true — пересылает исходное тело
запроса и стримит ответ обратно без преобразования.
Аутентификация: forward (ретрансляция заголовков вызывающей стороны) или key.
При key-аутентификации retryOn429 действует и здесь: 429 до
начала потока ждёт и, до любой другой обработки или фейловера, повторяет идентичный запрос на
том же ключе, как и в переводимом пути openai-chat/Anthropic. Пользовательские транспорты
runTurn в цикл HTTP-повторов не входят.
-
Stateless-парсер DeepSeek Responses получает нормализацию истории на уровне провайдера: контекст, внедрённый хуком, переносится после однозначного батча call/result. Параллельные вызовы остаются сгруппированными перед своими результатами, поэтому каждый вызов сохраняет свой один assistant-ход с рассуждениями. Толерантные провайдеры и неоднозначные (дублирующиеся, отсутствующие или неупорядоченные) идентификаторы call сохраняют исходный порядок входа.
-
URL для
forward→{baseUrl}/responses. Провайдер сkeyпо умолчанию сохраняет прежнее построение{baseUrl}/v1/responses. -
Провайдер с
keyможет задать проверенный относительныйresponsesPath: адаптер удаляет один завершающий/изbaseUrlи отправляет запрос на{trimmedBaseUrl}{responsesPath}. Для Ark Agent Plan используйтеbaseUrl: "https://ark.cn-beijing.volces.com/api/plan/v3"иresponsesPath: "/responses". -
В режиме
forwardретранслируется только безопасный allowlist заголовков (FORWARD_HEADERS): authorization, ChatGPT account id и заголовки OpenAI beta/originator/session. Это путь входа через ChatGPT, на котором также работают сайдкары.
anthropic
Заголовок раздела «anthropic»Назначение: Anthropic Messages (/v1/messages).
Аутентификация: key (по умолчанию x-api-key, либо Authorization: Bearer при apiKeyTransport: "bearer") или oauth (Bearer + anthropic-beta, для Claude Pro/Max).
- Преобразует сообщения в блоки контента Anthropic (text, base64 image,
tool_use,thinking). - Арифметика extended thinking: Anthropic требует
max_tokens > thinking.budget_tokens. Адаптер отображает уровень рассуждений в бюджет (minimal 1024 … max 32000), затем вычисляет безопасныйmax_tokensс запасом на вывод и удаляетtemperature/top_p, когда thinking включён (Anthropic запрещает их в этом режиме). - Всегда отправляет
anthropic-version: 2023-06-01. Стримитcontent_block_delta(text_delta,thinking_delta,input_json_delta).
Назначение: Google Gemini, Vertex AI и Antigravity Cloud Code Assist. AI Studio
использует /v1beta/models/{model}:streamGenerateContent; остальные режимы используют свои
нативные конечные точки Google.
Аутентификация: API-ключ, Vertex ADC или Google Antigravity OAuth — выбирается через
googleMode.
- Системный промпт →
systemInstruction; сообщения →contents[](assistant →model); инструменты →functionDeclarations. Изображения из data-URL →inline_data. - Идентификаторы вызовов инструментов синтезируются, когда Gemini их опускает. Vertex и Antigravity
сохраняют и повторно передают непрозрачные значения
thoughtSignature, чтобы непрерывность рассуждений сохранялась после возврата результата инструмента. Кэш подписей сохраняется в каталог конфигурации, поэтому последующие ходы переживают и перезапуск прокси.
Назначение: сервис Amazon CodeWhisperer Streaming GenerateAssistantResponse, используемый
Kiro (https://runtime.{region}.kiro.dev/).
Аутентификация: Kiro OAuth access token как Bearer, с метаданными region/profile из учётных
данных Kiro.
- Формирует Kiro
conversationState, отображает инструменты Codex и результаты их вызовов и отправляет блоки изображений, поддерживаемые wire-форматом Kiro. - Декодирует
application/vnd.amazon.eventstream, восстанавливает события text/thinking/tool, обнаруживает усечённый JSON инструментов и оценивает использование, потому что вышестоящий сервис не возвращает количество токенов. - Через
fetchResponseсам управляет ограниченными повторными попытками и классифицированными ошибками с удалением чувствительных данных; его непотоковый парсер вычитывает тот же поток событий для цикла веб-поиска.
Завершение и нативный stop reason
Заголовок раздела «Завершение и нативный stop reason»Текст ассистента Kiro сам по себе не даёт надёжного признака конца хода. Однако завершающий
metadataEvent может нести нативный stopReason, но Kiro иногда помечает END_TURN обычный текст
о прогрессе. Поэтому в ходе с инструментами такой текст остаётся commentary и проходит одну
проверку приватным инструментом завершения.
Путь совместимости может использоваться для END_TURN, STOP_SEQUENCE или отсутствующего stop reason. Любая другая явная причина уже
завершила вывод на стороне провайдера, поэтому адаптер сообщает о ней, а не отправляет ещё один
запрос: лимит выходных токенов становится продолжаемым incomplete, исчерпание контекстного окна —
неповторяемой ошибкой context-length, фильтрация и срабатывание guardrail — отфильтрованным
incomplete. TOOL_USE без фактического вызова инструмента трактуется как противоречие, а не прогресс.
В ходе с инструментами opencodex добавляет приватный codex_kiro_final_answer. Повторная попытка не
создаёт пустые assistant/user-сообщения, сохраняет исходный user/tool-result и перед отправкой проверяет
чередование ролей, непустые структурные сообщения и пары tool use/result. Ответ инструмента завершения
всегда выдаётся как final_answer, даже если он совпадает с предыдущим commentary.
Если продолжить нельзя без решения, сведений или уточнения, которые может дать только пользователь, контракт предписывает отправить этот вопрос через инструмент завершения и остановиться. Такой ход тоже приходит как final_answer с завершённым ходом, а не как commentary.
Reasoning effort
Заголовок раздела «Reasoning effort»gpt-5.6-sol и claude-opus-5 поддерживают нативный effort, но называют поле запроса по-разному.
Значения low / medium / high / xhigh / max отправляются как
additionalModelRequestFields.reasoning.effort и output_config.effort соответственно.
Назначение: по умолчанию agent.v1.AgentService/Run Cursor поверх потокового HTTP/2 Connect
на api2.cursor.sh. При upstreamHttpVersion: "http1.1" (или "h1") используется совместимый
транспорт HTTP/1.1: agent.v1.AgentService/RunSSE для вывода сервера и
aiserver.v1.BidiService/BidiAppend для сообщений клиента. Эта настройка применяется и к
inference, и к live model discovery.
Аутентификация: Cursor OAuth/access token из provider.apiKey или из переданного заголовка
authorization.
- Использует
runTurnвместо обычного пути fetch/parse. Запросы, серверные события, аргументы инструментов, контрольные точки использования и ответы клиента кодируются схемами@bufbuild/protobufизcursor/gen/agent_pb.tsи оформляются как сообщения Connect. - Воспроизводит состояние диалога через content-addressed blob’ы, отображает серверные вызовы
инструментов обратно в Codex, обнаруживает актуальные модели Cursor через protobuf RPC
GetUsableModelsи повторяет попытки только до того, как run-запрос зафиксирован на wire. - После успешно завершённого хода без инструментов хранит возвращённую ConversationStateStructure локально в процессе и повторно использует checkpoint для проверенного линейного продолжения. Ходы с результатом инструмента используют checkpoint последнего завершённого хода и только ещё не охваченный suffix, когда известна граница охваченных сообщений. Поиск по префиксу без ref разрешён только при наличии запомненного разговора Cursor или стабильного идентификатора client thread (включая ограниченный fallback по Desktop session/thread) и единственного совпадающего checkpoint, принадлежащего тому же разговору provider; иначе выполняется full replay. Compaction, изоляция helper/shadow, несовпадение account/model, отсутствие ref, ошибки decode, forced-fresh recovery и повтор после invalid_argument также используют full replay. Перезапуск процесса удаляет хранилище из памяти и приводит к full replay. Cursor Connect не предоставляет достоверный cache_read_tokens, поэтому usage OpenCodex не является счётчиком cache hit. Ограниченный Desktop fallback хранит только владельца, выведенного через HMAC локально в процессе; исходные заголовки session/thread и данные OAuth/authorization в checkpoint state не записываются. Live transport с OAuth и фильтрация live model discovery по аккаунту остаются экспериментальными. Настройки входа и transport описаны в руководстве по провайдерам и конфигурации провайдера Cursor. Повторное использование checkpoint выполняется автоматически и не имеет пользовательской настройки.
- Сохраняет
cursor/grok-4.5-fastдоступной для выбора, но отправляет Cursor каноническую модельgrok-4.5, помещая отдельные значенияeffortиfast=trueвrequested_model.parameters. - Нативное для Cursor локальное выполнение операций с файловой системой/shell/сетью по умолчанию
запрещено. Явные интеграции
mcpServersиdesktopExecutorвключаются отдельно;nativeLocalExec: "on"включает более широкий встроенный executor и обходит семантику одобрений/песочницы Codex; устаревшийunsafeAllowNativeLocalExec: trueэквивалентен только еслиnativeLocalExecне задан.
azure-openai (алиас: azure)
Заголовок раздела «azure-openai (алиас: azure)»Назначение: Azure OpenAI. Обёртка над openai-responses (поэтому тоже
passthrough: true).
Аутентификация: key через заголовок api-key (не Bearer).
- Делегирует построение запроса passthrough-адаптеру Responses, проверяет, что
baseUrlне содержит неразрешённых плейсхолдеров шаблона, и заменяетAuthorizationнаapi-key. Настроенный URL указывает напрямую на Azure v1 Responses API, поэтому адаптер не добавляетapi-version.
Утилиты для изображений (image.ts)
Заголовок раздела «Утилиты для изображений (image.ts)»Общие хелперы, используемые адаптерами с поддержкой изображений:
parseDataUrl(url)— разбивает URL видаdata:<type>;base64,<data>на{ mediaType, base64 }для блоков изображений Anthropic/Google.contentPartsToText(content)— сплющивает части контента в текст для текстовых сообщений инструментов (изображение без описания становится коротким маркером[image], а не раздувающим токены base64-блобом).

