10. Провайдеры моделей
AstraCode работает с LLM-провайдерами через плоскую схему [[providers]] в config.toml. Каждый провайдер считается говорящим по OpenAI Chat Completions (<base_url>/chat/completions + /v1/models для обнаружения списка моделей); трансляцию в Responses-API выполняет встроенный мост (см. раздел 2 и responses-api-proxy/). API-ключи хранятся отдельно — в зашифрованном ~/.astracode/secrets/local.age (см. 09-security.md).
1. Конфигурация провайдера
default_provider = "openai" [[providers]] id = "openai" display_name = "OpenAI" base_url = "https://api.openai.com/v1" [[providers]] id = "local-vllm" display_name = "Local vLLM" base_url = "http://172.16.20.83:8000/v1" [[providers]] id = "provider-glm" display_name = "Zhipu GLM" base_url = "https://api.z.ai/api/coding/paas/v4" strip_strict = true
Корневого поля
default_modelв схеме нет. Модель не задаётся вconfig.tomlнапрямую — она выбирается через/model(список моделей подтягивается из эндпоинта/v1/modelsпровайдера), а сделанный выбор сохраняется в[ui_state].last_used_modelи подхватывается при следующем запуске. Параметрdefault_providerзадаёт лишь провайдера по умолчанию, когда нет других сигналов (CLI-переопределения или сохранённогоlast_used_provider).
Поля [[providers]] (struct ProviderEntry, config/src/providers_toml.rs, схема deny_unknown_fields):
- id — стабильный slug, ключ в default_provider/[ui_state].last_used_provider и ключ в secrets-store для API-ключа этого провайдера.
- display_name — подпись в меню выбора /model.
- base_url — корневой URL (должен оканчиваться на /v1, чтобы мост дописал /chat/completions и /models).
- model_override — опц.: принудительно подставить это значение в поле model upstream (когда id модели в AstraCode не совпадает с --served-model-name бэкенда).
- extra_body — опц.: доп. поля, добавляются в тело запроса upstream (vLLM/SGLang-ручки: top_k, min_p, chat_template_kwargs).
- strip_strict — опц. (по умолч. false): убрать "strict": true из схем function-tool'ов (нужно некоторым бэкендам, в частности Z.AI / GLM).
- forward_reasoning_summaries — опц. (по умолч. false): пробрасывать upstream-чанки reasoning_content как Responses-события reasoning-summary.
Полей
api_formatиauth_methodв схеме нет. Нативные форматы Anthropic Messages / AWS Bedrock текущей[[providers]]-схемой не описываются — каждый провайдер общается по Chat Completions, а Responses-API получается через мост.
2. Chat Completions bridge
In-process прокси из responses-api-proxy --mode chat-completions (astracode-rs/responses-api-proxy/src/bridge/) транслирует Responses-API запросы AstraCode'а в обычный /v1/chat/completions upstream. Это нужно когда AstraCode-core ходит через Responses-API канал, а upstream-сервер умеет только Chat Completions (типичный кейс для vLLM, llama.cpp, LiteLLM, многих on-prem развёртываний).
Архитектура цепочки:
AstraCode core
→ POST /v1/responses на in-process прокси (responses-api-proxy)
→ request::translate: Responses JSON → Chat Completions JSON
→ POST <upstream>/v1/chat/completions
→ response::StreamTranslator: Chat SSE → Responses SSE
→ AstraCode core читает Responses SSE как обычно
Что делает прокси:
request::translate(bridge/request.rs) — нормализует tool definitions, страм/non-stream, flattens nested content, опционально снимаетstrict: trueиз tool schema (--strip-strict).response::StreamTranslator(bridge/response.rs) — синхронныйRead-адаптер, превращает Chat SSE chunks (delta,tool_calls,usage) в Responses-API SSE event stream (response.created,output_item.added,output_text.delta,function_call_arguments.delta,response.completed).NamespaceMap(bridge/tools.rs) — хранит соответствие(namespace, name)чтобы восстановить original tool name при возврате, даже если модель выдаёт flattened имя.
Запуск standalone:
astracode-responses-api-proxy --mode chat-completions \ --upstream-url https://api.upstream/v1/chat/completions \ --model gpt-4o-mini
Запуск in-process из TUI: AstraCode сам поднимает прокси на свободном localhost-порту, передаёт upstream-URL из конфига и тушит при завершении — пользователю ничего конфигурировать не нужно.
3. Установка API-ключа
Ключ берётся из зашифрованного secrets-store по id провайдера (~/.astracode/secrets/local.age), а не из config.toml и не из переменных окружения.
Через TUI:
/model → + Add provider (или выбрать существующего) → ввести API-ключ (вводится скрыто) → ключ шифруется и пишется в ~/.astracode/secrets/local.age
Через CLI (команда provider-secret, читает ключ из stdin):
echo "sk-..." | astracode provider-secret set openai
Связанные подкоманды: provider-secret status <id>, provider-secret delete <id>.
4. Выбор модели
model = "gpt-5" model_provider = "openai"
В TUI:
/model
Каталог моделей берётся из model-provider-info (захардкоженный список + дозагрузка из API провайдера, если поддерживается).
models-manager кэширует список моделей в ~/.astracode/state_5.sqlite с TTL.
5. On-prem / self-hosted
Локальный AstraCode-server
Если организация поднимает свой прокси-сервер (например, для централизованного биллинга и ACL):
default_provider = "company-llm" [[providers]] id = "company-llm" display_name = "Company LLM Gateway" base_url = "https://llm-gateway.company.internal/v1"
Если у gateway self-signed CA:
export ASTRACODE_CA_CERTIFICATE=/etc/ssl/certs/company-ca.pem astracode
vLLM / llama.cpp
[[providers]] id = "local-llama" display_name = "Local llama.cpp" base_url = "http://localhost:8080/v1"
Если бэкенд требует ключ — поставьте любой (или dummy):
echo "dummy" | astracode provider-secret set local-llama
Ollama
[[providers]] id = "ollama" display_name = "Ollama" base_url = "http://localhost:11434/v1"
6. Параметры запроса
model = "gpt-5" model_context_window = 200000 model_auto_compact_token_limit = 180000 model_reasoning_effort = "high" plan_mode_reasoning_effort = "high" model_verbosity = "medium"
model_context_window— учитывается для UI-индикатора заполнения.model_auto_compact_token_limit— порог автоматического предложения/compact.model_reasoning_effort— для моделей с extended thinking (o1, GPT-5 reasoning).model_verbosity— для GPT-5 (low/medium/high).
7. Несколько провайдеров одновременно
Можно держать в config несколько [[providers]] и переключаться через /model:
[[providers]] id = "openai" base_url = "https://api.openai.com/v1" [[providers]] id = "anthropic" base_url = "https://api.anthropic.com/v1" [[providers]] id = "local" base_url = "http://localhost:8000/v1"
AstraCode запомнит последний выбор в [ui_state]:
[ui_state] last_used_provider = "anthropic" last_used_model = "claude-sonnet-4-6"
8. Прокси
Отдельной секции [network] в config.toml нет (схема ConfigToml использует deny_unknown_fields). Прокси задаётся стандартными переменными окружения, которые читает HTTP-клиент:
export HTTPS_PROXY="http://proxy.company.com:3128" export HTTP_PROXY="http://proxy.company.com:3128" export NO_PROXY="localhost,127.0.0.1,*.internal" astracode
Поддерживаются как заглавные (HTTP_PROXY, HTTPS_PROXY, NO_PROXY), так и строчные (http_proxy, https_proxy, no_proxy) варианты.
9. Стриминг
AstraCode использует SSE (Server-Sent Events) для стриминга ответов модели:
- Каждая дельта токена приходит как TextDelta событие.
- Tool-вызовы — ToolUseStart / ToolUseDelta / ToolUseEnd.
- Размышления (extended thinking) — ReasoningDelta.
Если провайдер не поддерживает стриминг — используется блокирующий запрос с буферизацией.
10. Retries и rate limiting
Встроенные ретраи на: - 429 (rate limit) — exponential backoff. - 5xx — до 3 попыток. - Timeouts на network errors — одна попытка.
Логика ретраев встроена и не настраивается через config.toml: отдельной секции [network.retry] в схеме нет (ConfigToml использует deny_unknown_fields).
11. Локальное прокси astracode-responses-api-proxy (standalone)
Тот же мост из раздела 2 можно запустить отдельным процессом. Бинарь — astracode-responses-api-proxy; в режиме chat-completions он принимает POST /v1/responses и транслирует в /v1/chat/completions upstream'а:
astracode-responses-api-proxy --mode chat-completions \ --upstream-url https://api.upstream/v1/chat/completions \ --port 7100
Полный набор флагов (см. responses-api-proxy/README.md):
astracode-responses-api-proxy --upstream-url <URL> \ [--mode chat-completions|openai] [--no-auth] [--port <PORT>] \ [--server-info <FILE>] [--http-shutdown] [--dump-dir <DIR>]
В config провайдер указывает на локальный порт прокси как на обычный base_url:
[[providers]] id = "via-proxy" display_name = "Via local proxy" base_url = "http://localhost:7100/v1"
12. Отладка запросов
Отдельного CLI-флага для дампа запросов нет. Диагностика выполняется через переменную RUST_LOG:
RUST_LOG=astracode_model_provider=debug astracode
Покажет request/response body (с маскированием API-ключей).
13. Файлы кода
- Схема
[[providers]](ProviderEntry):config/src/providers_toml.rs - Provider-крейт:
model-provider/src/(lib.rs,provider.rs,auth.rs,models_endpoint.rs) - Информация о провайдерах/моделях:
model-provider-info/src/lib.rs - Менеджер моделей:
models-manager/src/lib.rs - Responses↔Chat Completions мост:
responses-api-proxy/(встраивание —responses-api-proxy/src/embed.rs, мост —src/bridge/) - Secrets-store ключей провайдеров: крейт
astracode-secrets - AWS SigV4 (вспомогательный крейт):
aws-auth/