DashboardCodeSession 0D61K5Borc8J

Session 0D61K5Borc8J

Full ID: 0D61K5Borc8Jn4iF7
Messages: 16
Distillations: 0
Time range: 2026-06-05 00:48:45 — 2026-06-05 00:50:09

Conversation (16 messages)

result
task_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. ...
<system-reminder> The user sent the following message: maybe models.dev also provides that model/provider -> url mapping somehow?

Please address this message and continue with your tasks. </system-reminder>

gateway · 2026-06-05 00:48:45

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.

claude-opus-4-6 · 2026-06-05 00:48:45 · ~65 tokens
result
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 ...
result
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 ...
gateway · 2026-06-05 00:48:50

Let me check the models.dev providers page and API — it may expose structured provider data with base URLs.

claude-opus-4-6 · 2026-06-05 00:48:50 · ~37 tokens
result
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 ...
result
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 / ...
gateway · 2026-06-05 00:48:56

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.

claude-opus-4-6 · 2026-06-05 00:48:56 · ~106 tokens
result

...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.
gateway · 2026-06-05 00:49:04

The JSON is huge. Let me check its structure and specifically find the MiniMax provider entry to see the schema.

claude-opus-4-6 · 2026-06-05 00:49:04 · ~38 tokens

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.

  1. Read the first 100 lines to understand the top-level structure
  2. Search for "minimax" entries (case-insensitive) to see the provider data schema
  3. Search for "anthropic" entries to see how providers with SDK-based packages (no URL) are represented
  4. Search for "deepseek" to see another provider with a URL
  5. Specifically, I need to know: does each provider entry include 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.

gateway · 2026-06-05 00:49:10

I'll start by reading the first 100 lines and searching for the three providers in parallel.

claude-opus-4-6 · 2026-06-05 00:49:10 · ~32 tokens
result
<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...
result
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...
result
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...
result
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...
gateway · 2026-06-05 00:49:25

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.

claude-opus-4-6 · 2026-06-05 00:49:25 · ~56 tokens
result
[
  "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",
  ...
result
{
  "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
  }
}
result
{
  "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": {
 ...
result
{
  "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
      }
    },
    ...
gateway · 2026-06-05 00:49:36

Now let me check one more thing -- whether anthropic truly has no api field (confirming it's absent, not just omitted by my script):

claude-opus-4-6 · 2026-06-05 00:49:36 · ~46 tokens
result
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'] ...
gateway · 2026-06-05 00:50:09

Here are the complete findings:


Top-Level Structure

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.


Provider Entry Schema

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).

  • 24 providers lack 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.
  • 115 providers have api -- these typically use @ai-sdk/openai-compatible or @ai-sdk/anthropic as a generic adapter pointing at a custom base URL.

Three Provider Entries

1. 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)",
  ...
claude-opus-4-6 · 2026-06-05 00:50:09 · ~2.1K tokens