ollama-proxy/AGENTS.md
Atte149 98bbc96bf5 docs: separate opencode vs openlama provider isolation
- opencode (global config) sees marg/fireworks only, no ocp
- openlama (OPENCODE_CONFIG=openlama.json) sees ocp only via enabled_providers
- Verified: opencode run -m ocp/... → Model not found; openlama run -m ocp/... → OK
- openlama launcher sets OPENCODE_CONFIG + NO_PROXY + execs opencode
2026-06-19 14:18:14 +03:00

7.4 KiB
Raw Blame History

AGENTS.md — ollama-proxy

Контекст

ollama-proxy — Go-прокси для Ollama Cloud (https://ollama.com). Балансирует запросы по нескольким API-ключам с round-robin и failover на 429/5xx. Слушает 127.0.0.1:11435, экспонирует нативный Ollama API (/api/*) и OpenAI-совместимый (/v1/*) passthrough. Деплой — systemd unit ollama-proxy.service. Используется opencode через кастомный провайдер ocp.

Стек

  • Go 1.22 (используется log/slog, net/http, net/http/httputil)
  • Единственная внешняя зависимость: golang.org/x/term (prompt без echo в accounts add)
  • Go 1.18 из apt НЕ подходит — нужен ~/.local/go/bin/go (Go 1.22.10). Перед сборкой: export PATH="$HOME/.local/go/bin:$PATH"
  • Сборка: make build./ollama-proxy
  • Тесты: go test ./... (43 теста, включая integration-тесты с httptest)
  • Линт: go vet ./..., gofmt -l .

Структура

main.go                        — точка входа, делегирует в cli.Run
internal/config/
  accounts.go                  — Account, AccountsFile, JSON load/save (chmod 0600, atomic)
  server.go                    — ServerConfig (addr, base_url, cooldown, retries, log_level)
internal/log/logger.go         — slog JSON logger с configurable level
internal/proxy/
  balancer.go                  — round-robin + per-account cooldown (RWMutex)
  handler.go                   — HTTP handler: reverse-proxy, Authorization подмена, SSE flush
  retry.go                     — документация стриминг-инварианта
internal/cli/
  root.go                      — dispatch подкоманд (serve / accounts / version)
  accounts.go                  — add / list / remove / set-base-url
  serve.go                     — запуск HTTP-сервера с signal handling
systemd/ollama-proxy.service   — systemd unit

Конфигурация

  • Аккаунты: ~/.config/ollama-proxy/accounts.json (XDG_CONFIG_HOME, chmod 0600, atomic write)
  • Флаги serve: --addr, --base-url, --cooldown, --retries, --log-level
  • Env vars: OLLAMA_PROXY_ADDR, OLLAMA_PROXY_BASE_URL, OLLAMA_PROXY_COOLDOWN, OLLAMA_PROXY_RETRIES, OLLAMA_PROXY_LOG_LEVEL

Типичные задачи

  • Добавить аккаунт: ollama-proxy accounts add --name <alias> (промпт) или ... add <key> --name <alias>
  • Перезапустить после правки аккаунтов: sudo systemctl restart ollama-proxy (прокси читает accounts.json при старте; runtime-обновления не поддерживаются)
  • Посмотреть логи: journalctl -u ollama-proxy -f — JSON-структурированные (account, account_id, path, status, latency_ms, stream)
  • Проверить, что прокси жив: curl http://127.0.0.1:11435/api/version → должен вернуть JSON от ollama.com
  • Проверить список моделей: curl http://127.0.0.1:11435/v1/models | jq '.data | length' (~35 моделей)
  • Запустить opencode с пулом: openlama (обёртка в ~/.local/bin/openlama, выставляет NO_PROXY и запускает opencode)
  • Обновить список моделей в opencode-конфиге: curl -sS http://127.0.0.1:11435/v1/models | jq -r '.data[].id' → обновить models блок в ~/.config/opencode/opencode.json

Интеграция с opencode

Два отдельных конфига: opencode видит только marg/fireworks, openlama видит только ocp.

  • ~/.config/opencode/opencode.json — глобальный конфиг с marg + fireworks (без ocp)
  • ~/.config/opencode/openlama.json — отдельный конфиг с ocp + "enabled_providers": ["ocp"]. Содержит те же instructions/mcp/plugins/agent что глобальный, но только провайдер ocp.
  • ~/.local/bin/openlama — обёртка, выставляет OPENCODE_CONFIG=~/.config/opencode/openlama.json + NO_PROXY=127.0.0.1,localhost,::1 + exec opencode "$@"

openlama.json (ключевая часть):

{
  "enabled_providers": ["ocp"],
  "provider": {
    "ocp": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "Ollama Cloud (pool)",
      "options": {
        "baseURL": "http://127.0.0.1:11435/v1",
        "apiKey": "proxy"
      },
      "models": {
        "gpt-oss:20b": { "name": "gpt-oss:20b" },
        "...": { "name": "..." }
      }
    }
  }
}

OPENCODE_CONFIG мерджится с глобальным конфигом, но enabled_providers: ["ocp"] перекрывает глобальный — marg/fireworks скрыты.

Модель не сделана дефолтной — выбирается через /models в TUI.

ВАЖНО: NO_PROXY. Если в окружении установлен HTTP_PROXY/HTTPS_PROXY (например http://127.0.0.1:2080), opencode (Bun runtime) направит запросы к прокси через HTTP-прокси → 502 Bad Gateway. Нужно явно исключить localhost:

# В ~/.config/environment.d/no-proxy-local.conf (systemd/desktop sessions):
NO_PROXY=127.0.0.1,localhost,::1
no_proxy=127.0.0.1,localhost,::1

Или запускать opencode с NO_PROXY=127.0.0.1,localhost opencode ....

Модели в конфиге: opencode НЕ умеет динамически резолвить модели через /v1/models для @ai-sdk/openai-compatiblemodels: {} даёт ProviderModelNotFoundError. Нужно явно перечислить модели. Обновить список: curl -sS http://127.0.0.1:11435/v1/models | jq -r '.data[].id' → вставить в models блок.

WARN

  • Никогда не запускай прокси на 0.0.0.0 без auth — он не имеет аутентификации, любой может использовать твои ключи
  • accounts.json содержит ключи в plaintext — файл chmod 0600, не коммить в git
  • После правки accounts.json нужен sudo systemctl restart ollama-proxy (прокси не перечитывает файл в рантайме)
  • Если локальная ollama запущена на 11434 — это НЕ конфликтует (прокси на 11435), но OLLAMA_HOST=127.0.0.1:11435 нужно явно указывать
  • Стриминг-инвариант: после первого flush-а 2xx ответа переключение аккаунта НЕ происходит. Mid-stream ошибки → truncated response клиенту. Это by design (нельзя дублировать вывод)
  • 5xx НЕ вызывает cooldown аккаунта (только 429). 5xx → failover на следующий аккаунт, но без penalty

План отката

  • sudo systemctl stop ollama-proxy && sudo systemctl disable ollama-proxy
  • sudo rm /usr/local/bin/ollama-proxy /etc/systemd/system/ollama-proxy.service && sudo systemctl daemon-reload
  • Убрать блок ocp из ~/.config/opencode/opencode.json