Dodaj niestandardowego providera kompatybilnego z OpenAI do OpenCode.

Updated 2026-07-29

OpenCode odczytuje niestandardowych providerów bezpośrednio z opencode.json. Zadeklaruj blok provider z pakietem @ai-sdk/openai-compatible, wskaż options.baseURL na https://api.apisrouter.com/v1, a każdy wymieniony model staje się wybieralny w pickerze /models pod jednym kluczem.

Szybka odpowiedź: jeden blok provider w opencode.json.

OpenCode natywnie obsługuje niestandardowych providerów kompatybilnych z OpenAI. Dodaj wpis providera do opencode.json z npm ustawionym na „@ai-sdk/openai-compatible", ustaw options.baseURL na https://api.apisrouter.com/v1, odczytaj klucz ze zmiennej środowiskowej za pomocą szablonu {env:...} i wylistuj identyfikatory modeli, których chcesz, pod models. Następnie ustaw pole model na najwyższym poziomie na „apisrouter/<model-id>", a OpenCode skieruje całą pętlę agenta przez bramkę. To udokumentowana w dokumentacji OpenCode ścieżka niestandardowego providera, nie wrapper ani fork. Plik konfiguracyjny znajduje się albo w katalogu głównym projektu (opencode.json), albo globalnie pod ~/.config/opencode/opencode.json, a oba są scalane, więc blok providera można zadeklarować raz i używać go we wszystkich repozytoriach.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "apisrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "APIsRouter",
      "options": {
        "baseURL": "https://api.apisrouter.com/v1",
        "apiKey": "{env:APISROUTER_API_KEY}"
      },
      "models": {
        "claude-sonnet-4-6": { "name": "Claude Sonnet 4.6" }
      }
    }
  },
  "model": "apisrouter/claude-sonnet-4-6"
}

Jak OpenCode rozwiązuje providerów i modele.

OpenCode (anomalyco na GitHubie, jeden z najczęściej oznaczanych gwiazdką terminalowych agentów do kodowania, z ok. 186 tys. gwiazdek) buduje swoją warstwę providerów na Vercel AI SDK. Pole npm w bloku providera określa, który pakiet SDK OpenCode ładuje, żeby rozmawiać z danym providerem: „@ai-sdk/openai-compatible" mówi standardowym protokołem /v1/chat/completions, a „@ai-sdk/openai" mówi protokołem /v1/responses OpenAI. Wielodostawcza bramka obsługuje chat completions, więc openai-compatible to właściwy pakiet; wybranie „@ai-sdk/openai" przy endpoincie chat-completions to najczęstszy sposób, w jaki ta konfiguracja się psuje. Modele są adresowane jako pary provider/model. Identyfikator providera to dowolny klucz, który wybrałeś w bloku providera („apisrouter" powyżej), a identyfikator modelu to klucz wewnątrz mapy models, więc domyślny model staje się „apisrouter/claude-sonnet-4-6". Wszystko, co zadeklarujesz, pojawia się w pickerze /models wewnątrz TUI, przełączalne w trakcie sesji. Jedno zachowanie warte przyswojenia: dla niestandardowych providerów mapa models jest listą dozwolonych. Wbudowani providerzy dostarczają znany katalog, ale OpenCode nie potrafi samodzielnie wyliczyć modeli niestandardowego endpointu, więc adresowalne są tylko identyfikatory jawnie zadeklarowane. Gdy endpoint za baseURL obsługuje obok siebie identyfikatory Claude, GPT, DeepSeek i Kimi, zadeklarowanie jednego wpisu na model zamienia picker w międzydostawcową centralę pod jednym kluczem.

Pełna konfiguracja: konfiguracja globalna, konfiguracja projektu, limity per model.

Czysty układ to zadeklarowanie providera raz w konfiguracji globalnej pod ~/.config/opencode/opencode.json i trzymanie w opencode.json każdego projektu tylko wyborów per repo (który model, które agenty). OpenCode scala pliki konfiguracyjne, zamiast je zastępować, więc plik projektu pozostaje mały, a blok providera nigdy się nie duplikuje. Szablon {env:APISROUTER_API_KEY} rozwiązuje się w czasie ładowania ze środowiska, co trzyma klucz poza jakimkolwiek plikiem, który mógłby trafić do commita. Wyeksportuj go z profilu swojej powłoki, żeby każda sesja terminala uruchamiająca OpenCode mogła go zobaczyć. Każdy wpis modelu akceptuje też obiekt limit z górnymi granicami tokenów kontekstu i wyjścia. Ich zadeklarowanie ma większe znaczenie, niż się wydaje: OpenCode używa wartości kontekstu, żeby zdecydować, kiedy sesja potrzebuje streszczenia, więc model z długim kontekstem zadeklarowany bez limitów jest traktowany bardziej zachowawczo, niż powinien. Ustaw limit.context na to, co model faktycznie obsługuje, a długie sesje będą kompresowane później zamiast wcześniej.

{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "apisrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "APIsRouter",
      "options": {
        "baseURL": "https://api.apisrouter.com/v1",
        "apiKey": "{env:APISROUTER_API_KEY}"
      },
      "models": {
        "claude-opus-4-7":   { "name": "Claude Opus 4.7",   "limit": { "context": 200000, "output": 32000 } },
        "claude-sonnet-4-6": { "name": "Claude Sonnet 4.6", "limit": { "context": 200000, "output": 64000 } },
        "gpt-5.5":           { "name": "GPT-5.5" },
        "gpt-5.6-sol": { "name": "GPT-5.6 Sol" },
        "kimi-k2.7-code":    { "name": "Kimi K2.7 Code" }
      }
    }
  },
  "model": "apisrouter/claude-sonnet-4-6",
  "small_model": "apisrouter/kimi-k2.7-code"
}

Dobór model i small_model.

Praktyczny workflow to trzymanie slotu main na modelu, któremu ufasz przy edycjach, i rotowanie kandydatów przez prawdziwe sesje zamiast benchmarków: popołudnie prawdziwych diffów na Twojej własnej bazie kodu mówi więcej niż ranking. Kierowanie przez jeden endpoint sprawia, że każdy kandydat to zmiana jednej linii, a widok użycia per klucz pokazuje, ile faktycznie kosztował każdy eksperyment.

  • model napędza główną pętlę agenta: czytanie plików, planowanie edycji, pisanie diffów, uruchamianie narzędzi. Ten slot widzi najdłuższe konteksty i wykonuje faktyczny inżynieryjny wysiłek, więc należy tu flagowy model do kodowania (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5).
  • small_model obsługuje lekkie zadania, takie jak generowanie tytułów sesji. Uruchamia się często, ale nigdy nie dźwiga pracy kodowania, więc odpowiednim kształtem jest szybki, tani identyfikator; nie ma powodu spalać flagowych tokenów na tytuły.
  • Identyfikatory dostrojone pod kodowanie, takie jak gpt-5.6-sol i kimi-k2.7-code, warto zadeklarować, nawet jeśli nie są Twoim domyślnym wyborem: przełączenie się na nie przy sesji z dużą ilością refaktoryzacji to jeden wybór w /models, a nie edycja konfiguracji.
  • Ponieważ oba sloty przyjmują stringi provider/model względem tego samego bloku providera, sloty main i small mogą pochodzić od różnych dostawców w tej samej sesji — czego nie umożliwia żaden klucz jednego dostawcy.

Płatność za użycie · poniżej cen oficjalnych

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModelCena oficjalnaNasza cena
Claude Sonnet 4.6$3.00 / $15.00 per M$2.40 / $12.00 per M
Claude Opus 4.7$5.00 / $25.00 per M$4.00 / $20.00 per M
GPT-5.5$5.00 / $30.00 per M$4.00 / $24.00 per M
GPT-5.6 Sol$5.00 / $30.00 per M$4.00 / $24.00 per M
Kimi K2.7 Code$0.95 / $4.00 per M$1.00 / $4.00 per M

Tryby awarii charakterystyczne dla niestandardowych providerów w OpenCode.

Zły pakiet SDK. „@ai-sdk/openai" wysyła żądania do /v1/responses; bramka obsługująca chat-completions odpowiada na tę trasę błędem. Jeśli Twoje pierwsze żądanie zawodzi błędem w kształcie protokołu albo trasy, a nie błędem uwierzytelniania, sprawdź, czy pole npm zawiera dokładnie „@ai-sdk/openai-compatible". Model nieobecny w pickerze. Modele niestandardowego providera istnieją tylko wtedy, gdy są zadeklarowane; literówka w kluczu models albo identyfikator, który zakładałeś, ale nigdy nie dodałeś, po prostu nie pojawi się w /models. Identyfikatory to dokładne stringi, łącznie z sufiksami wersji, a lista /v1/models bramki to źródło prawdy, z którego warto kopiować. Nierozwiązany {env:...}. Szablon rozwiązuje się ze środowiska procesu, który uruchomił OpenCode. Klucz wyeksportowany w jednym terminalu nie dotrze do instancji OpenCode uruchomionej z innego terminala albo z desktopowego launchera, który nigdy nie wczytał Twojego profilu. Umieść export w profilu powłoki, a nie w jednorazowej sesji. Niespodzianki przy scalaniu konfiguracji. Ponieważ konfiguracja globalna i projektu się scalają, opencode.json projektu, który ustawia model na innego providera, po cichu nadpisuje Twoją globalną wartość domyślną, a pozostałość bloku providera w starym projekcie może zaburzać oczekiwania. Gdy routing wygląda źle, przeczytaj oba pliki, zanim uznasz, że to bramka źle się zachowuje. baseURL bez /v1. SDK dokleja ścieżki tras, takie jak /chat/completions, do dowolnej podanej przez Ciebie bazy, więc https://api.apisrouter.com/v1 jest poprawne, a sam host już nie. Awaria połączenia albo w kształcie 404 przy poza tym poprawnej konfiguracji to prawie zawsze to.

Kto kieruje OpenCode przez bramkę.

  • Deweloperzy, którzy cały dzień żyją w TUI i chcą mieć Claude, GPT i Kimi w jednym pickerze /models, zamiast utrzymywać osobne poświadczenia providera dla każdego dostawcy.
  • Inżynierowie porównujący modele do kodowania na prawdziwej pracy. Każdy kandydat to jeden zadeklarowany wpis i jeden wybór w pickerze; porównywanie sesja po sesji nie wymaga nowych kont.
  • Zespoły standaryzujące jeden sekret. Pojedynczy APISROUTER_API_KEY w dokumentacji wdrożeniowej zastępuje listę kontrolną kluczy per dostawca, a użycie per klucz pokazuje, kto ile wydaje.
  • Użytkownicy łączący flagowy model main z tanim small_model od innego dostawcy, czego nie da się wyrazić konfiguracją jednego dostawcy.
  • Deweloperzy bez dostępu do rozliczeń danego dostawcy. Dostęp oparty na doładowaniu, bez wymogu karty, usuwa zależność od rejestracji u każdego providera.

Zweryfikuj endpoint i debuguj pierwszą sesję.

Przed rozpoczęciem sesji wylistuj, co obsługuje bramka. Identyfikatory zwracane przez /v1/models to dokładnie te stringi, którym muszą odpowiadać klucze Twojej mapy models. Awarie pierwszej sesji są spójne. 401 oznacza, że APISROUTER_API_KEY nie był widoczny dla procesu OpenCode; wykonaj echo zmiennej w tym samym terminalu, z którego uruchamiasz. Błąd model-not-found z bramki oznacza, że zadeklarowany klucz nie odpowiada obsługiwanemu identyfikatorowi, łącznie z sufiksami wersji. Jeśli provider w ogóle się nie pojawia, zwaliduj JSON, ponieważ przecinek na końcu albo źle umieszczony nawias klamrowy sprawiają, że cały plik jest nieczytelny, a OpenCode wraca do ustawień domyślnych. Gdy żądania już płyną, konsola APIsRouter pokazuje model per żądanie, liczbę tokenów i wydatki. Agenty do kodowania to obciążenia z długim kontekstem i wieloma turami, a zobaczenie, które sesje i które modele zużywają tokeny, to sposób, żeby zdecydować, czy slot main zarabia na swoją cenę.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Częste pytania

Czy OpenCode może używać modeli Claude, GPT i Kimi przez jednego niestandardowego providera?

Tak. Niestandardowy provider to po prostu baseURL plus lista dozwolonych models. Gdy endpoint obsługuje wielu dostawców, zadeklaruj jeden wpis na identyfikator, a każdy zadeklarowany model pojawi się w pickerze /models pod tym samym providerem i kluczem, przełączalny w trakcie sesji.

Gdzie w opencode.json trafia klucz API?

W options.apiKey, przy użyciu szablonu środowiskowego, na przykład „{env:APISROUTER_API_KEY}". Szablon rozwiązuje się w czasie ładowania, więc dosłowny klucz nigdy nie siedzi w pliku konfiguracyjnym. Wyeksportuj zmienną z profilu swojej powłoki, żeby każdy terminal uruchamiający OpenCode ją odziedziczył.

Czy blok providera powinien być w konfiguracji globalnej czy projektu?

Globalnie, pod ~/.config/opencode/opencode.json. OpenCode scala pliki konfiguracyjne, więc zadeklarowanie providera raz globalnie i ustawianie tylko wyboru modelu per projekt utrzymuje repozytoria wolne od hydrauliki poświadczeń i unika rozjeżdżania się zduplikowanych bloków.

Dlaczego mój model nie pojawia się w pickerze /models?

Modele niestandardowego providera muszą być zadeklarowane jawnie; OpenCode nie potrafi wyliczyć niestandardowego endpointu. Sprawdź, czy mapa models zawiera dokładny string identyfikatora, łącznie z sufiksami wersji, i kopiuj identyfikatory z odpowiedzi /v1/models bramki, zamiast wpisywać je z pamięci.

Jaka jest różnica między @ai-sdk/openai-compatible a @ai-sdk/openai w tym przypadku?

@ai-sdk/openai-compatible mówi protokołem /v1/chat/completions, który obsługują wielodostawcowe bramki. @ai-sdk/openai mówi protokołem /v1/responses OpenAI. Dla APIsRouter używaj @ai-sdk/openai-compatible; drugi pakiet będzie wysyłał żądania do trasy, której bramka nie obsługuje w tym celu.

Czy zadeklarowane limity kontekstu faktycznie mają znaczenie?

Tak. OpenCode używa limit.context, żeby zdecydować, kiedy sesja potrzebuje kompresji. Pozostawienie limitów niezadeklarowanych na modelu z długim kontekstem oznacza, że sesje są streszczane wcześniej, niż to konieczne, więc ustaw limit.context i limit.output na to, co model naprawdę obsługuje.