0.4.11
10 · Техническая документация

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. Конфигурация провайдера

toml
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 развёртываний).

Архитектура цепочки:

text
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:

bash
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:

text
/model
→ + Add provider (или выбрать существующего)
→ ввести API-ключ (вводится скрыто)
→ ключ шифруется и пишется в ~/.astracode/secrets/local.age

Через CLI (команда provider-secret, читает ключ из stdin):

bash
echo "sk-..." | astracode provider-secret set openai

Связанные подкоманды: provider-secret status <id>, provider-secret delete <id>.

4. Выбор модели

toml
model = "gpt-5"
model_provider = "openai"

В TUI:

text
/model

Каталог моделей берётся из model-provider-info (захардкоженный список + дозагрузка из API провайдера, если поддерживается).

models-manager кэширует список моделей в ~/.astracode/state_5.sqlite с TTL.

5. On-prem / self-hosted

Локальный AstraCode-server

Если организация поднимает свой прокси-сервер (например, для централизованного биллинга и ACL):

toml
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:

bash
export ASTRACODE_CA_CERTIFICATE=/etc/ssl/certs/company-ca.pem
astracode

vLLM / llama.cpp

toml
[[providers]]
id = "local-llama"
display_name = "Local llama.cpp"
base_url = "http://localhost:8080/v1"

Если бэкенд требует ключ — поставьте любой (или dummy):

bash
echo "dummy" | astracode provider-secret set local-llama

Ollama

toml
[[providers]]
id = "ollama"
display_name = "Ollama"
base_url = "http://localhost:11434/v1"

6. Параметры запроса

toml
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:

toml
[[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]:

toml
[ui_state]
last_used_provider = "anthropic"
last_used_model = "claude-sonnet-4-6"

8. Прокси

Отдельной секции [network] в config.toml нет (схема ConfigToml использует deny_unknown_fields). Прокси задаётся стандартными переменными окружения, которые читает HTTP-клиент:

bash
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'а:

bash
astracode-responses-api-proxy --mode chat-completions \
  --upstream-url https://api.upstream/v1/chat/completions \
  --port 7100

Полный набор флагов (см. responses-api-proxy/README.md):

text
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:

toml
[[providers]]
id = "via-proxy"
display_name = "Via local proxy"
base_url = "http://localhost:7100/v1"

12. Отладка запросов

Отдельного CLI-флага для дампа запросов нет. Диагностика выполняется через переменную RUST_LOG:

bash
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/