Dashboard › Code › Session 0D61K5Borc8J
0D61K5Borc8Jn4iF7task_id: ses_16ac3205affe1KN3JKTcVQujIs (for resuming to continue this task if needed) <task_result> Now I have a comprehensive understanding of the entire routing system. Let me design the solution. --- ## Design: Provider-ID-Based Upstream Routing ### 1. The Problem The current `UPSTREAM_ROUTES` table maps **model name prefixes** to upstream URLs. This breaks for: - **MiniMax** — model names don't follow a prefix convention that the gateway knows - **OpenRouter, Vercel AI Gateway** — they proxy many models with arbitrary names - **Any new provider** — requires adding prefix entries to the gateway, which is fragile Meanwhile, both plugins (OpenCode and Pi) already know the **provider ID** at request time. They just don't send it. ### 2. Priority Chain ``` 1. X-Lore-Upstream-URL header (explicit user override via LORE_UPSTREAM_<PROVIDER> env var) 2. Provider-ID-based route (X-Lore-Provider header → PROVIDER_ROUTES lookup) 3. ...
Please address this message and continue with your tasks. </system-reminder>
Good idea — if models.dev already has provider → URL mappings, we could potentially pull from that rather than maintaining our own PROVIDER_ROUTES table. Let me check what models.dev exposes.
Models.dev — An open-source database of AI models [ # Models.dev ](/) An open-source database of AI models [Models](/models)[Providers](/providers)[Labs](/labs) [](https://github.com/sst/models.dev) ⌘K How to use Model Lab Providers Context Output Input Reasoning Tool Call Structured Temperature Weights Price Release Updated [Qwen3.7 Plus](/models/alibaba/qwen3.7-plus)alibaba/qwen3.7-plus [Alibaba](/labs/alibaba) [2](/models/alibaba/qwen3.7-plus#providers) 131,072 16,384 Yes Yes \- Yes Closed $0.50 / $3.00 2026-06-02 2026-06-02 [MiniMax-M3](/models/minimax/MiniMax-M3)minimax/MiniMax-M3 [MiniMax](/labs/minimax) [2](/models/minimax/MiniMax-M3#providers) 512,000 128,000 Yes Yes \- Yes Closed $0.30 / $1.20 2026-06-01 2026-06-01 [Claude Opus ...
Models.dev — An open-source database of AI models [ # Models.dev ](/) An open-source database of AI models [Models](/models)[Providers](/providers)[Labs](/labs) [](https://github.com/sst/models.dev) ⌘K How to use Model Lab Providers Context Output Input Reasoning Tool Call Structured Temperature Weights Price Release Updated [Qwen3.7 Plus](/models/alibaba/qwen3.7-plus)alibaba/qwen3.7-plus [Alibaba](/labs/alibaba) [2](/models/alibaba/qwen3.7-plus#providers) 131,072 16,384 Yes Yes \- Yes Closed $0.50 / $3.00 2026-06-02 2026-06-02 [MiniMax-M3](/models/minimax/MiniMax-M3)minimax/MiniMax-M3 [MiniMax](/labs/minimax) [2](/models/minimax/MiniMax-M3#providers) 512,000 128,000 Yes Yes \- Yes Closed $0.30 / $1.20 2026-06-01 2026-06-01 [Claude Opus ...
Let me check the models.dev providers page and API — it may expose structured provider data with base URLs.
Models.dev — An open-source database of AI models [ # Models.dev ](/) An open-source database of AI models [Models](/models)[Providers](/providers)[Labs](/labs) [](https://github.com/sst/models.dev) ⌘K How to use Provider Models Package API Docs [302.AI](/providers/302ai) 97 @ai-sdk/openai-compatible https://api.302.ai/v1 [Docs](https://doc.302.ai) [Abacus](/providers/abacus) 65 @ai-sdk/openai-compatible https://routellm.abacus.ai/v1 [Docs](https://abacus.ai/help/api) [Abliteration .ai abliteration.ai](/providers/abliteration-ai) 1 @ai-sdk/openai-compatible https://api.abliteration.ai/v1 [Docs](https://docs.abliteration.ai/models) [AIHubMix](/providers/aihubmix) 50 @aihubmix/ai-sdk-provider \- [Docs](https://docs.aihubmix.com) [Alibaba](/providers/alibaba) 51 @ai-sdk/openai-compatible https://dashscope-intl.aliyuncs.com/compatible-mode/v1 [Docs](https://www.alibabacloud.com/help/en/model-studio/models) [Alibaba ...
Models.dev — An open-source database of AI models [ # Models.dev ](/) An open-source database of AI models [Models](/models)[Providers](/providers)[Labs](/labs) [](https://github.com/sst/models.dev) ⌘K How to use [Providers](/providers) ## MiniMax (minimax.io) `minimax` Models 7 Package @ai-sdk/anthropic API https://api.minimax.io/anthropic/v1 Docs [Provider docs](https://platform.minimax.io/docs/guides/quickstart) ### Models 7 Model Model ID Context Output Price Reasoning Tool Call Structured Temperature [MiniMax-M2](/models/minimax/MiniMax-M2)minimax/MiniMax-M2 MiniMax-M2 196,608 128,000 $0.30 / $1.20 Yes Yes \- Yes [MiniMax-M2.1](/models/minimax/MiniMax-M2.1)minimax/MiniMax-M2.1 MiniMax-M2.1 204,800 131,072 $0.30 / $1.20 Yes Yes \- Yes [MiniMax-M2.5](/models/minimax/MiniMax-M2.5)minimax/MiniMax-M2.5 MiniMax-M2.5 204,800 131,072 $0.30 / ...
This is exactly what we need. The models.dev /providers page has structured data for every provider: provider ID, SDK package, and API base URL. And there's a JSON API at https://models.dev/api.json. Let me check what that JSON looks like — it likely has the provider → URL mapping in machine-readable form.
...2205556 bytes truncated... The tool call succeeded but the output was truncated. Full output saved to: /home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1 Use the Task tool to have explore agent process this file with Grep and Read (with offset/limit). Do NOT read the full file yourself - delegate to save context.
The JSON is huge. Let me check its structure and specifically find the MiniMax provider entry to see the schema.
The file /home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1 contains the JSON response from https://models.dev/api.json. I need to understand its structure.
api (the base URL) and package (the SDK package name)? What are the exact field names?Return the exact JSON structure for the minimax, anthropic, and deepseek provider entries, plus the top-level schema of the file.
I'll start by reading the first 100 lines and searching for the three providers in parallel.
<path>/home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1</path>
<type>file</type>
<content>
1: {"upstage":{"id":"upstage","env":["UPSTAGE_API_KEY"],"npm":"@ai-sdk/openai-compatible","api":"https://api.upstage.ai/v1/solar","name":"Upstage","doc":"https://developers.upstage.ai/docs/apis/chat","models":{"solar-mini":{"id":"solar-mini","name":"solar-mini","family":"solar-mini","attachment":false,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-09","release_date":"2024-06-12","last_updated":"2025-04-22","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":32768,"output":4096},"cost":{"input":0.15,"output":0.15}},"solar-pro3":{"id":"solar-pro3","name":"solar-pro3","family":"solar-pro","attachment":false,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03","release_date":"2026-01","last_updated":"2026-01","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"co...
Found 3 matches
/home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1:
Line 1: {"upstage":{"id":"upstage","env":["UPSTAGE_API_KEY"],"npm":"@ai-sdk/openai-compatible","api":"https://api.upstage.ai/v1/solar","name":"Upstage","doc":"https://developers.upstage.ai/docs/apis/chat","models":{"solar-mini":{"id":"solar-mini","name":"solar-mini","family":"solar-mini","attachment":false,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-09","release_date":"2024-06-12","last_updated":"2025-04-22","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":32768,"output":4096},"cost":{"input":0.15,"output":0.15}},"solar-pro3":{"id":"solar-pro3","name":"solar-pro3","family":"solar-pro","attachment":false,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03","release_date":"2026-01","last_updated":"2026-01","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":131072,"ou...
Found 27 matches
/home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1:
Line 1: {"upstage":{"id":"upstage","env":["UPSTAGE_API_KEY"],"npm":"@ai-sdk/openai-compatible","api":"https://api.upstage.ai/v1/solar","name":"Upstage","doc":"https://developers.upstage.ai/docs/apis/chat","models":{"solar-mini":{"id":"solar-mini","name":"solar-mini","family":"solar-mini","attachment":false,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-09","release_date":"2024-06-12","last_updated":"2025-04-22","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":32768,"output":4096},"cost":{"input":0.15,"output":0.15}},"solar-pro3":{"id":"solar-pro3","name":"solar-pro3","family":"solar-pro","attachment":false,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03","release_date":"2026-01","last_updated":"2026-01","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":131072,"o...
Found 6 matches
/home/byk/.local/share/opencode/tool-output/tool_e95412957001LlEYF0h5k1AXV1:
Line 1: {"upstage":{"id":"upstage","env":["UPSTAGE_API_KEY"],"npm":"@ai-sdk/openai-compatible","api":"https://api.upstage.ai/v1/solar","name":"Upstage","doc":"https://developers.upstage.ai/docs/apis/chat","models":{"solar-mini":{"id":"solar-mini","name":"solar-mini","family":"solar-mini","attachment":false,"reasoning":false,"tool_call":true,"temperature":true,"knowledge":"2024-09","release_date":"2024-06-12","last_updated":"2025-04-22","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":32768,"output":4096},"cost":{"input":0.15,"output":0.15}},"solar-pro3":{"id":"solar-pro3","name":"solar-pro3","family":"solar-pro","attachment":false,"reasoning":true,"tool_call":true,"temperature":true,"knowledge":"2025-03","release_date":"2026-01","last_updated":"2026-01","modalities":{"input":["text"],"output":["text"]},"open_weights":false,"limit":{"context":131072,"ou...
The file is a single-line JSON blob. I need to use jq to extract the specific provider entries. Let me extract the three providers and also get the top-level keys.
[ "upstage", "clarifai", "ollama-cloud", "the-grid-ai", "fireworks-ai", "ambient", "stackit", "ovhcloud", "iflowcn", "302ai", "nano-gpt", "alibaba-cn", "digitalocean", "submodel", "bailing", "kimi-for-coding", "dinference", "novita-ai", "kilo", "regolo-ai", "google-vertex", "deepseek", "orcarouter", "moonshotai-cn", "minimax-cn-coding-plan", "inception", "kuae-cloud-coding-plan", "chutes", "crof", "frogbot", "anthropic", "alibaba", "xiaomi", "mistral", "vivgrid", "databricks", "siliconflow-cn", "zhipuai-coding-plan", "xai", "v0", "neuralwatt", "friendli", "github-copilot", "inference", "huggingface", "cohere", "azure-cognitive-services", "openrouter", "privatemode-ai", "snowflake-cortex", "moonshotai", "perplexity", "llmgateway", "togetherai", "moark", "github-models", "xiaomi-token-plan-cn", "lmstudio", "zenmux", "claudinio", "alibaba-coding-plan", ...
{
"id": "minimax",
"env": [
"MINIMAX_API_KEY"
],
"npm": "@ai-sdk/anthropic",
"api": "https://api.minimax.io/anthropic/v1",
"name": "MiniMax (minimax.io)",
"doc": "https://platform.minimax.io/docs/guides/quickstart",
"models": {
"MiniMax-M2.5": {
"id": "MiniMax-M2.5",
"name": "MiniMax-M2.5",
"family": "minimax",
"attachment": false,
"reasoning": true,
"tool_call": true,
"temperature": true,
"release_date": "2026-02-12",
"last_updated": "2026-02-12",
"modalities": {
"input": [
"text"
],
"output": [
"text"
]
},
"open_weights": true,
"limit": {
"context": 204800,
"output": 131072
},
"cost": {
"input": 0.3,
"output": 1.2,
"cache_read": 0.03,
"cache_write": 0.375
}
},
"__remaining_count__": 6
}
}
{
"id": "anthropic",
"env": [
"ANTHROPIC_API_KEY"
],
"npm": "@ai-sdk/anthropic",
"name": "Anthropic",
"doc": "https://docs.anthropic.com/en/docs/about-claude/models",
"models": {
"claude-opus-4-5": {
"id": "claude-opus-4-5",
"name": "Claude Opus 4.5 (latest)",
"family": "claude-opus",
"attachment": true,
"reasoning": true,
"reasoning_options": [
{
"type": "effort",
"values": [
"low",
"medium",
"high"
]
},
{
"type": "budget_tokens",
"min": 1024
}
],
"tool_call": true,
"temperature": true,
"knowledge": "2025-03-31",
"release_date": "2025-11-24",
"last_updated": "2025-11-24",
"modalities": {
"input": [
"text",
"image",
"pdf"
],
"output": [
"text"
]
},
"open_weights": false,
"limit": {
...
{
"id": "deepseek",
"env": [
"DEEPSEEK_API_KEY"
],
"npm": "@ai-sdk/openai-compatible",
"api": "https://api.deepseek.com",
"name": "DeepSeek",
"doc": "https://api-docs.deepseek.com/quick_start/pricing",
"models": {
"deepseek-reasoner": {
"id": "deepseek-reasoner",
"name": "DeepSeek Reasoner",
"family": "deepseek-thinking",
"attachment": true,
"reasoning": true,
"tool_call": true,
"interleaved": {
"field": "reasoning_content"
},
"temperature": true,
"knowledge": "2025-09",
"release_date": "2025-12-01",
"last_updated": "2026-02-28",
"modalities": {
"input": [
"text"
],
"output": [
"text"
]
},
"open_weights": true,
"limit": {
"context": 1000000,
"output": 384000
},
"cost": {
"input": 0.14,
"output": 0.28,
"cache_read": 0.028
}
},
...
Now let me check one more thing -- whether anthropic truly has no api field (confirming it's absent, not just omitted by my script):
anthropic top-level fields (excluding models):
{
"id": "anthropic",
"env": [
"ANTHROPIC_API_KEY"
],
"npm": "@ai-sdk/anthropic",
"name": "Anthropic",
"doc": "https://docs.anthropic.com/en/docs/about-claude/models"
}
Has api field: False
Has npm field: True
Providers WITHOUT api field (24 total): ['google-vertex', 'anthropic', 'mistral', 'xai', 'v0', 'cohere', 'azure-cognitive-services', 'perplexity', 'togetherai', 'aihubmix'] ...
Providers WITH api field (115 total): ['upstage', 'clarifai', 'ollama-cloud', 'the-grid-ai', 'fireworks-ai', 'ambient', 'stackit', 'ovhcloud', 'iflowcn', '302ai'] ...
Here are the complete findings:
The file is a single-line JSON object (1 line total). The top-level structure is a flat dictionary keyed by provider ID (string), with 139 provider entries total. There is no wrapper object, no version field, no metadata -- just:
{
"<provider_id>": { <provider_entry> },
"<provider_id>": { <provider_entry> },
...
}
The 139 top-level keys include providers like "upstage", "anthropic", "deepseek", "minimax", "openai", "google", "xai", "mistral", etc.
Each provider entry has these fields:
| Field | Type | Required? | Description |
|---|---|---|---|
| id | string | Always present | Same as the top-level key |
| name | string | Always present | Human-readable provider name |
| env | string[] | Always present | Environment variable(s) for API key |
| npm | string | Always present | NPM package name for SDK |
| api | string | Optional (115 of 139 have it, 24 do not) | Base URL for the API |
| doc | string | Always present | Documentation URL |
| models | object | Always present | Dictionary of model entries keyed by model ID |
Key finding: The field names are api (not url or baseUrl) and npm (not package).
api -- these include anthropic, google-vertex, mistral, xai, cohere, perplexity, togetherai, azure-cognitive-services, v0, etc. These are providers with dedicated SDK packages (e.g. @ai-sdk/anthropic) that handle URL routing internally.api -- these typically use @ai-sdk/openai-compatible or @ai-sdk/anthropic as a generic adapter pointing at a custom base URL.minimax (has both api and npm){
"id": "minimax",
"env": ["MINIMAX_API_KEY"],
"npm": "@ai-sdk/anthropic",
"api": "https://api.minimax.io/anthropic/v1",
"name": "MiniMax (minimax.io)",
...