یک provider سفارشی سازگار با OpenAI به OpenCode اضافه کنید.

Updated 2026-07-29

OpenCode provider های سفارشی را مستقیم از opencode.json می‌خواند. یک بلاک provider با پکیج @ai-sdk/openai-compatible اعلام کنید، options.baseURL را به https://api.apisrouter.com/v1 اشاره دهید، و هر مدلی که فهرست کنید در انتخاب‌گر /models زیر یک کلید قابل‌انتخاب می‌شود.

پاسخ سریع: یک بلاک provider در opencode.json.

OpenCode به‌صورت native از provider های سفارشی سازگار با OpenAI پشتیبانی می‌کند. یک entry provider به opencode.json اضافه کنید با npm تنظیم‌شده روی "@ai-sdk/openai-compatible"، options.baseURL را روی https://api.apisrouter.com/v1 تنظیم کنید، کلید را از یک متغیر محیطی با قالب {env:...} بخوانید، و id های مدلی که می‌خواهید را زیر models فهرست کنید. سپس فیلد model سطح-بالا را روی "apisrouter/<model-id>" تنظیم کنید و OpenCode کل loop agent را از طریق gateway مسیردهی می‌کند. این مسیر مستند provider سفارشی در مستندات OpenCode است، نه یک wrapper یا fork. فایل پیکربندی یا در ریشه پروژه شما (opencode.json) یا به‌صورت سراسری در ~/.config/opencode/opencode.json زندگی می‌کند، و این دو merge می‌شوند، پس بلاک provider می‌تواند یک بار اعلام و در هر repo دوباره استفاده شود.

{
  "$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"
}

OpenCode چطور provider ها و مدل‌ها را resolve می‌کند.

OpenCode (anomalyco روی GitHub، یکی از پرستاره‌ترین agent های کدنویسی ترمینال با حدود ۱۸۶ هزار ستاره) لایه provider خود را روی Vercel AI SDK می‌سازد. فیلد npm در یک بلاک provider نام می‌برد کدام پکیج SDK را OpenCode برای صحبت با آن provider بارگذاری کند: "@ai-sdk/openai-compatible" پروتکل استاندارد /v1/chat/completions را صحبت می‌کند، در حالی که "@ai-sdk/openai" پروتکل /v1/responses از OpenAI را صحبت می‌کند. یک gateway چند-vendor chat completions سرویس می‌دهد، پس openai-compatible پکیج درست است؛ انتخاب "@ai-sdk/openai" در برابر یک endpoint chat-completions رایج‌ترین راهی است که این راه‌اندازی می‌شکند. مدل‌ها به‌صورت جفت‌های provider/model آدرس‌دهی می‌شوند. id provider هرچه کلیدی است که در بلاک provider انتخاب کرده‌اید ("apisrouter" بالا)، و id مدل کلید داخل map مدل‌ها است، پس مدل پیش‌فرض "apisrouter/claude-sonnet-4-6" می‌شود. هرچه اعلام کنید داخل انتخاب‌گر /models درون TUI ظاهر می‌شود، قابل‌تعویض در وسط session. یک رفتار ارزش درونی‌سازی: برای provider های سفارشی، map مدل‌ها یک allowlist است. provider های built-in با یک کاتالوگ شناخته‌شده عرضه می‌شوند، اما OpenCode نمی‌تواند مدل‌های یک endpoint سفارشی را خودش شمارش کند، پس فقط id هایی که صریح اعلام می‌کنید قابل‌آدرس‌دهی هستند. وقتی endpoint پشت baseURL id های Claude، GPT، DeepSeek، و Kimi را کنار هم سرویس می‌دهد، اعلام یک entry به ازای هر مدل انتخاب‌گر را به یک سوییچ‌بورد چند-vendor پشت یک کلید تبدیل می‌کند.

راه‌اندازی کامل: پیکربندی سراسری، پیکربندی پروژه، محدودیت‌های هر-مدل.

چیدمان تمیز این است که provider را یک بار در پیکربندی سراسری در ~/.config/opencode/opencode.json اعلام کنید و فقط انتخاب‌های هر-repo (کدام مدل، کدام agent) را در opencode.json هر پروژه نگه دارید. OpenCode فایل‌های پیکربندی را merge می‌کند نه جایگزین، پس فایل پروژه کوچک می‌ماند و بلاک provider هرگز تکراری نمی‌شود. قالب {env:APISROUTER_API_KEY} در زمان بارگذاری از محیط resolve می‌شود، که کلید را از هر فایلی که ممکن است commit شود دور نگه می‌دارد. آن را از profile شل خود export کنید تا هر session ترمینالی که OpenCode را راه‌اندازی می‌کند بتواند آن را ببیند. هر entry مدل همچنین یک شیء limit با سقف token context و خروجی می‌پذیرد. اعلام آن‌ها بیشتر از ظاهرش اهمیت دارد: OpenCode از رقم context برای تصمیم‌گیری اینکه یک session کِی نیاز به خلاصه‌سازی دارد استفاده می‌کند، پس یک مدل long-context اعلام‌شده بدون محدودیت‌ها محافظه‌کارانه‌تر از آنچه باید در نظر گرفته می‌شود. limit.context را روی چیزی که مدل واقعاً پشتیبانی می‌کند تنظیم کنید و session های بلند دیرتر به‌جای زودتر فشرده می‌شوند.

{
  "$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"
}

انتخاب model و small_model.

workflow عملی این است که slot main را روی مدلی که برای edit اعتماد دارید نگه دارید و کاندیدها را از طریق session های واقعی بچرخانید نه benchmark ها: یک بعدازظهر diff های واقعی در برابر codebase خودتان بیشتر از یک leaderboard به شما می‌گوید. مسیردهی از طریق یک endpoint هر کاندید را یک تغییر یک-خطی می‌کند، و نمای usage هر-کلید نشان می‌دهد هر آزمایش واقعاً چقدر هزینه داشته.

  • model loop اصلی agent را هدایت می‌کند: خواندن فایل‌ها، برنامه‌ریزی edit، نوشتن diff، اجرای ابزار. این slot طولانی‌ترین context ها را می‌بیند و مهندسی واقعی را انجام می‌دهد، پس یک مدل کدنویسی مرزی (claude-sonnet-4-6، claude-opus-4-7، gpt-5.5) اینجا تعلق دارد.
  • small_model وظایف سبک مثل تولید عنوان session را مدیریت می‌کند. اغلب شلیک می‌شود اما هرگز کار کدنویسی را حمل نمی‌کند، پس یک id سریع و ارزان شکل درست است؛ دلیلی برای سوزاندن token های مرزی روی عنوان‌ها وجود ندارد.
  • id های تنظیم‌شده برای کدنویسی مثل gpt-5.6-sol و kimi-k2.7-code حتی اگر پیش‌فرض شما نیستند ارزش اعلام دارند: سوییچ به آن‌ها برای یک session سنگین refactor یک انتخاب /models است، نه یک ویرایش پیکربندی.
  • چون هر دو slot رشته‌های provider/model را در برابر همان بلاک provider می‌گیرند، slot های main و small می‌توانند در همان session از vendor های مختلف بیایند، چیزی که هیچ کلید تک-vendor اجازه نمی‌دهد.

پرداخت بر اساس مصرف · پایین‌تر از قیمت رسمی

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

مدلقیمت رسمیقیمت ما
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

حالت‌های شکست مختص provider های سفارشی OpenCode.

پکیج SDK اشتباه. "@ai-sdk/openai" به /v1/responses پست می‌کند؛ یک gateway chat-completions به آن route با یک خطا پاسخ می‌دهد. اگر اولین درخواست شما با یک خطای شکل-پروتکل یا شکل-route به‌جای خطای احراز هویت شکست بخورد، چک کنید فیلد npm دقیقاً "@ai-sdk/openai-compatible" بگوید. مدل غایب از انتخاب‌گر. مدل‌های provider سفارشی فقط اگر اعلام شوند وجود دارند؛ یک غلط‌تایپی در کلید models، یا یک id که فرض کرده‌اید اما هرگز اضافه نکرده‌اید، به‌سادگی در /models ظاهر نمی‌شود. id ها رشته‌های دقیق شامل پسوندهای نسخه هستند، و فهرست /v1/models gateway منبع حقیقت برای کپی‌کردن است. {env:...} حل‌نشده. قالب از محیط فرآیندی که OpenCode را راه‌اندازی کرده resolve می‌شود. کلیدی export‌شده در یک ترمینال به یک نمونه OpenCode راه‌اندازی‌شده از ترمینال دیگر یا از یک launcher دسکتاپ که هرگز profile شما را source نکرده نمی‌رسد. export را در profile شل قرار دهید، نه یک session یک‌باره. سورپرایزهای merge پیکربندی. چون پیکربندی‌های سراسری و پروژه merge می‌شوند، یک opencode.json پروژه که model را روی provider متفاوتی تنظیم می‌کند بی‌صدا پیش‌فرض سراسری شما را override می‌کند، و یک بلاک provider باقی‌مانده در یک پروژه قدیمی می‌تواند انتظارات را سایه بیندازد. وقتی مسیردهی اشتباه به‌نظر می‌رسد، هر دو فایل را قبل از این‌که فرض کنید gateway بدرفتاری کرده بخوانید. baseURL بدون /v1. SDK مسیرهای route مثل /chat/completions را به هر base ای که می‌دهید پیوست می‌کند، پس https://api.apisrouter.com/v1 درست است و host برهنه نیست. یک شکست اتصال یا شکل-404 روی یک پیکربندی درگرچه-درست تقریباً همیشه همین است.

چه کسانی OpenCode را از طریق یک gateway مسیردهی می‌کنند.

  • توسعه‌دهندگانی که تمام روز در TUI زندگی می‌کنند و می‌خواهند Claude، GPT، و Kimi در یک انتخاب‌گر /models باشند به‌جای نگه‌داری credential های provider جدا به ازای هر vendor.
  • مهندسانی که مدل‌های کدنویسی را روی کار واقعی مقایسه می‌کنند. هر کاندید یک entry اعلام‌شده و یک انتخاب انتخاب‌گر است؛ مقایسه session-به-session نیازی به حساب جدید ندارد.
  • تیم‌هایی که یک secret استاندارد می‌کنند. یک APISROUTER_API_KEY واحد در مستندات onboarding یک چک‌لیست کلید هر-vendor را جایگزین می‌کند، و usage هر-کلید نشان می‌دهد کی چقدر خرج می‌کند.
  • کاربرانی که یک مدل main مرزی را با یک small_model کم‌هزینه از vendor دیگری جفت می‌کنند، چیزی که پیکربندی‌های تک-vendor نمی‌توانند بیان کنند.
  • توسعه‌دهندگان بدون دسترسی به صورت‌حساب یک vendor خاص. دسترسی مبتنی بر شارژ بدون الزام کارت وابستگی ثبت‌نام هر-provider را حذف می‌کند.

endpoint را تأیید کنید و session اول را عیب‌یابی کنید.

قبل از شروع یک session، آنچه gateway سرویس می‌دهد را فهرست کنید. id های برگردانده‌شده توسط /v1/models دقیقاً همان رشته‌هایی هستند که کلیدهای map مدل‌های شما باید با آن مطابقت داشته باشند. شکست‌های session اول ثابت‌اند. یک 401 یعنی APISROUTER_API_KEY برای فرآیند OpenCode قابل‌مشاهده نبوده؛ متغیر را در همان ترمینالی که از آن راه‌اندازی می‌کنید echo کنید. یک خطای model-not-found از gateway یعنی کلید اعلام‌شده با یک id سرویس‌داده‌شده مطابقت ندارد، شامل پسوندهای نسخه. اگر provider اصلاً ظاهر نشود، JSON را اعتبارسنجی کنید، چون یک کاما اضافه یا آکولاد جابه‌جا کل فایل را غیرقابل‌خواندن می‌کند و OpenCode به پیش‌فرض‌ها برمی‌گردد. وقتی درخواست‌ها جریان یابند، کنسول APIsRouter مدل، شمارش token، و هزینه به ازای هر درخواست را نشان می‌دهد. agent های کدنویسی حجم کاری context-بلند و بسیار-turn هستند، و دیدن کدام session ها و کدام مدل‌ها token ها را مصرف می‌کنند نحوه تصمیم‌گیری شماست که آیا slot main قیمتش را کسب می‌کند.

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

پرسش‌های پرتکرار

آیا OpenCode می‌تواند مدل‌های Claude، GPT، و Kimi را از طریق یک provider سفارشی استفاده کند؟

بله. یک provider سفارشی فقط یک baseURL به‌علاوه یک allowlist مدل است. وقتی endpoint چند vendor سرویس می‌دهد، یک entry به ازای هر id اعلام کنید و هر مدل اعلام‌شده در انتخاب‌گر /models زیر همان provider و کلید ظاهر می‌شود، قابل‌تعویض در وسط session.

کلید API کجای opencode.json می‌رود؟

در options.apiKey با استفاده از قالب محیطی، مثلاً "{env:APISROUTER_API_KEY}". قالب در زمان بارگذاری resolve می‌شود پس کلید تحت‌اللفظی هرگز داخل فایل پیکربندی نمی‌نشیند. متغیر را از profile شل خود export کنید تا هر ترمینالی که OpenCode را راه‌اندازی می‌کند آن را به ارث ببرد.

آیا بلاک provider باید در پیکربندی سراسری باشد یا پروژه؟

سراسری، در ~/.config/opencode/opencode.json. OpenCode فایل‌های پیکربندی را merge می‌کند، پس اعلام provider یک بار به‌صورت سراسری و تنظیم فقط انتخاب مدل به ازای هر پروژه repo ها را از سیم‌کشی credential آزاد نگه می‌دارد و از دورشدن بلاک‌های تکراری جلوگیری می‌کند.

چرا مدل من در انتخاب‌گر /models ظاهر نمی‌شود؟

مدل‌های provider سفارشی باید صریح اعلام شوند؛ OpenCode نمی‌تواند یک endpoint سفارشی را شمارش کند. چک کنید map مدل‌ها رشته دقیق id، شامل پسوندهای نسخه را دارد، و id ها را از پاسخ /v1/models gateway کپی کنید نه از حافظه تایپ کنید.

تفاوت @ai-sdk/openai-compatible و @ai-sdk/openai اینجا چیست؟

@ai-sdk/openai-compatible /v1/chat/completions را صحبت می‌کند، پروتکلی که gateway های چند-vendor سرویس می‌دهند. @ai-sdk/openai پروتکل /v1/responses از OpenAI را صحبت می‌کند. برای APIsRouter، از @ai-sdk/openai-compatible استفاده کنید؛ پکیج دیگر به route ای پست می‌کند که gateway برای این منظور سرویس نمی‌دهد.

آیا محدودیت‌های context اعلام‌شده واقعاً اهمیت دارند؟

بله. OpenCode از limit.context برای تصمیم‌گیری اینکه یک session کِی نیاز به فشرده‌سازی دارد استفاده می‌کند. رها کردن محدودیت‌ها بدون اعلام روی یک مدل long-context یعنی session ها زودتر از لازم خلاصه می‌شوند، پس limit.context و limit.output را روی چیزی که مدل واقعاً پشتیبانی می‌کند تنظیم کنید.