Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs-site/src/content/docs/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ free-experimentation model.
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| Volcengine Ark · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Document the Xiaomi MiMo reasoning contract.

The new rows identify the endpoint, but they do not state that Xiaomi MiMo supports only low, medium, and high. They also do not state that xhigh, max, and ultra are clamped to high. Users can otherwise select a tier that the CLI silently changes.

  • docs-site/src/content/docs/guides/providers.md#L294-L294: Add the supported ladder and clamping behavior.
  • docs-site/src/content/docs/ja/guides/providers.md#L221-L221: Add the equivalent localized behavior note.
  • docs-site/src/content/docs/ko/guides/providers.md#L221-L221: Add the equivalent localized behavior note.
  • docs-site/src/content/docs/ru/guides/providers.md#L232-L232: Add the equivalent localized behavior note.
  • docs-site/src/content/docs/zh-cn/guides/providers.md#L209-L209: Add the equivalent localized behavior note.
  • docs-site/src/content/docs/zh-tw/guides/providers.md#L275-L275: Add the equivalent localized behavior note.

As per path instructions, user-facing docs must stay in sync with actual CLI/API behavior. The referenced adapter documentation also requires consistent documentation of provider-specific reasoning support and higher-tier clamping.

📍 Affects 6 files
  • docs-site/src/content/docs/guides/providers.md#L294-L294 (this comment)
  • docs-site/src/content/docs/ja/guides/providers.md#L221-L221
  • docs-site/src/content/docs/ko/guides/providers.md#L221-L221
  • docs-site/src/content/docs/ru/guides/providers.md#L232-L232
  • docs-site/src/content/docs/zh-cn/guides/providers.md#L209-L209
  • docs-site/src/content/docs/zh-tw/guides/providers.md#L275-L275
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/guides/providers.md` at line 294, Document Xiaomi
MiMo’s reasoning contract alongside the provider entry: state that only low,
medium, and high are supported, and that xhigh, max, and ultra are clamped to
high. Apply the equivalent localized note in
docs-site/src/content/docs/ja/guides/providers.md:221,
docs-site/src/content/docs/ko/guides/providers.md:221,
docs-site/src/content/docs/ru/guides/providers.md:232,
docs-site/src/content/docs/zh-cn/guides/providers.md:209, and
docs-site/src/content/docs/zh-tw/guides/providers.md:275, while adding the
base-language note in docs-site/src/content/docs/guides/providers.md:294.

Source: Path instructions

| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/ja/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ Cline IDE/CLI のみで API からは使えません。`minimax/minimax-m2.5`
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| Volcengine Ark · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |
| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/ko/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ Cline IDE/CLI에서만 제공되며 API로는 사용할 수 없습니다. `minim
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| Volcengine Ark · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |
| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/ru/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ opencodex поставляется с 79 встроенными пресетам
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| Volcengine Ark · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |
| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/zh-cn/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ Cline IDE/CLI 中提供,不能通过 API 使用;`minimax/minimax-m2.5` 是
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| 火山方舟 · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |
| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down
3 changes: 2 additions & 1 deletion docs-site/src/content/docs/zh-tw/guides/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ IDE/CLI,不透過 API;`minimax/minimax-m2.5` 是文件列出的 API 免費
| SiliconFlow | `https://api.siliconflow.cn/v1` |
| Volcengine Ark · Coding Plan · Agent Plan | `https://ark.cn-beijing.volces.com/api/v3` · `https://ark.cn-beijing.volces.com/api/coding/v3` · `https://ark.cn-beijing.volces.com/api/plan/v3` |
| Xiaomi MiMo | `https://api.xiaomimimo.com/anthropic` |
| Xiaomi MiMo (OpenAI Chat) | `https://api.xiaomimimo.com/v1` |
| Kilo | `https://api.kilo.ai/api/gateway` |
| GitLab Duo | `https://cloud.gitlab.com/ai/v1/proxy/openai/v1` |
| Cloudflare AI Gateway | `https://gateway.ai.cloudflare.com/v1/{account-id}/{gateway}/anthropic` |
Expand Down Expand Up @@ -507,4 +508,4 @@ refresh 的即時 utilization bar。bar 代表特定 window(5 小時、weekly

具有 live probe 的 provider:OpenAI/Codex、Anthropic、xAI、Cursor、Kimi、Google Antigravity、
OpenRouter、DeepSeek、ClinePass、Z.AI、MiniMax、Moonshot、Venice、Synthetic、DeepInfra、Neuralwatt,
以及任何由 a6api 支援的 custom provider。
以及任何由 a6api 支援的 custom provider。
18 changes: 18 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,24 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
noVisionModels: OPENCODE_ZEN_TEXT_ONLY_MODELS,
},
{ id: "xiaomi", label: "Xiaomi MiMo", baseUrl: "https://api.xiaomimimo.com/anthropic", adapter: "anthropic", authKind: "key", dashboardUrl: "https://xiaomimimo.com", defaultModel: "mimo-v2.5-pro" },
// Xiaomi's public OpenAI-compatible endpoint is a distinct transport from both the Anthropic
// preset above and the paid token-plan host below. Keep a separate fixed-destination contract
// so existing custom providers are never retargeted while the official route receives the
// strict reasoning ladder its validator enforces (#1483).
{
id: "xiaomi-mimo",
label: "Xiaomi MiMo (OpenAI Chat)",
baseUrl: "https://api.xiaomimimo.com/v1",
adapter: "openai-chat",
authKind: "key",
dashboardUrl: "https://platform.xiaomimimo.com/console/balance",
defaultModel: "mimo-v2.5",
models: ["mimo-v2.5"],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Attach Xiaomi model metadata to the new preset

For users selecting this new static preset, mimo-v2.5 receives neither explicit context/modality metadata nor a jawcodeBundle: "xiaomi" alias. Consequently, the catalog cannot reach the existing Xiaomi metadata in src/generated/model-metadata.ts:53 and normalizes this model to the generic 128,000-token, text-only fallback instead of the repository's 1,048,576-token image-capable definition, causing premature compaction and blocking image attachments. Link the preset to the Xiaomi bundle and regenerate the metadata output, or declare the fields directly.

AGENTS.md reference: src/AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

reasoningEfforts: ["low", "medium", "high"],
reasoningEffortMap: { xhigh: "high", max: "high", ultra: "high" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve explicit none reasoning requests

When a Responses request explicitly sets reasoning.effort to none, this map has no none entry, so mapReasoningEffort() returns undefined and the OpenAI Chat adapter omits reasoning_effort entirely. Because the registry note states that Xiaomi accepts none as a distinct value, omission can invoke Xiaomi's default reasoning instead of disabling it; add none: "none" and cover the resulting request body in the focused test.

AGENTS.md reference: src/AGENTS.md:L18-L18

Useful? React with 👍 / 👎.

preserveCustomDestination: true,
note: "Official Xiaomi MiMo OpenAI-compatible Chat endpoint. The upstream validator accepts reasoning_effort none/low/medium/high; higher Codex tiers are clamped to high.",
},
{ id: "kilo", label: "Kilo", baseUrl: "https://api.kilo.ai/api/gateway", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://kilo.ai" },
{
id: "mimo-free",
Expand Down
15 changes: 15 additions & 0 deletions structure/03_catalog-and-subagents.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ wire-clamps ultra/max to each model's real top rung (e.g. gpt-5.5 ultra → xhig
(`src/server/effort-policy.ts`): they lower or preserve the requested effort rather than rejecting
the request, and they never raise it.

[Decision Log]
- 목적과 의도: Xiaomi MiMo의 공식 OpenAI Chat endpoint가 실제로 받지 않는 `max`/
`ultra` reasoning tier를 catalog에 노출하지 않도록 한다.
- 기존 구현 및 제약 조건: `xiaomi`는 Anthropic endpoint, `mimo`는 token-plan endpoint를
소유하며, 공식 `https://api.xiaomimimo.com/v1`은 generic custom provider로 처리됐다.
- 검토한 주요 대안: 기존 `xiaomi`/`mimo` contract를 확장하기, 모든 custom provider의 ladder를
일괄 축소하기, 공식 public endpoint만을 별도 registry row로 소유하기.
- 선택한 방식: `xiaomi-mimo`를 고정 목적지의 `openai-chat` preset으로 등록하고
`low`/`medium`/`high`만 노출하며 높은 direct request는 `high`로 clamp한다.
- 다른 대안 대신 이 방식을 선택한 이유: 서로 다른 auth/wire/host를 하나의 preset으로
합치지 않으면서 upstream error로 확인된 계약만 적용할 수 있다.
- 장점, 단점 및 영향: 공식 endpoint에서 안전한 picker/wire 계약을 제공하고,
`preserveCustomDestination`으로 같은 이름의 다른 host/key를 보호한다. 대신 새 preset 표면을
문서와 registry parity에서 함께 유지해야 한다.

[Decision Log]
- 목적과 의도: bare `defaultModel` selectors that route into third-party providers must keep their
adapter-owned effort ladder; only true ChatGPT-native requests should receive the mock-max repair.
Expand Down
168 changes: 168 additions & 0 deletions tests/mimo-token-plan-provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,74 @@
import { describe, expect, test } from "bun:test";
import { applyProviderConfigHints } from "../src/codex/catalog";
import { KEY_LOGIN_PROVIDERS } from "../src/oauth/key-providers";
import { PROVIDER_REGISTRY } from "../src/providers/registry";
import { mapReasoningEffort } from "../src/reasoning-effort";
import { routeModel } from "../src/router";
import type { OcxConfig } from "../src/types";

describe("Xiaomi MiMo public OpenAI Chat endpoint (#1483)", () => {
const baseUrl = "https://api.xiaomimimo.com/v1";
const entry = PROVIDER_REGISTRY.find(row => row.id === "xiaomi-mimo");

test("owns the official destination and advertises only its validated ladder", () => {
expect(entry).toMatchObject({
adapter: "openai-chat",
baseUrl,
dashboardUrl: "https://platform.xiaomimimo.com/console/balance",
defaultModel: "mimo-v2.5",
models: ["mimo-v2.5"],
preserveCustomDestination: true,
reasoningEfforts: ["low", "medium", "high"],
});
expect(KEY_LOGIN_PROVIDERS["xiaomi-mimo"]?.baseUrl).toBe(baseUrl);

const config: OcxConfig = {
port: 10100,
defaultProvider: "xiaomi-mimo",
providers: {
"xiaomi-mimo": {
adapter: "openai-chat",
baseUrl,
authMode: "key",
apiKey: "test-key",
liveModels: true,
},
},
};
const route = routeModel(config, "xiaomi-mimo/mimo-v2.5");
const catalogModel = applyProviderConfigHints("xiaomi-mimo", route.provider, {
provider: "xiaomi-mimo",
id: route.modelId,
});

expect(catalogModel.reasoningEfforts).toEqual(["low", "medium", "high"]);
for (const tier of ["xhigh", "max", "ultra"]) {
expect(mapReasoningEffort(route.provider, route.modelId, tier)).toBe("high");
}
});

test("does not claim a same-named provider at another destination", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "xiaomi-mimo",
providers: {
"xiaomi-mimo": {
adapter: "openai-chat",
baseUrl: "https://private.example/v1",
authMode: "key",
apiKey: "private-key",
},
},
};

const route = routeModel(config, "xiaomi-mimo/mimo-v2.5");
expect(route.provider.baseUrl).toBe("https://private.example/v1");
expect(route.provider.apiKey).toBe("private-key");
expect(route.provider.reasoningEfforts).toBeUndefined();
expect(route.provider.reasoningEffortMap).toBeUndefined();
});
});

describe("Xiaomi MiMo token plan (#1158)", () => {
const entry = PROVIDER_REGISTRY.find(row => row.id === "mimo");

Expand Down Expand Up @@ -53,4 +118,107 @@ describe("Xiaomi MiMo token plan (#1158)", () => {
// The registry's effort clamp must not be applied to a row we do not own either.
expect(route.provider.reasoningEfforts).toBeUndefined();
});

// A user reasoningEffortMap CAN still lift a tier, and that is the shipped contract rather
// than an oversight: `healMappedTiers` treats a wire map as authoritative evidence of the
// tiers the upstream can emit and merges its Codex values into the ladder, which is what lets
// a stale persisted ladder recover a newly documented tier without rewriting user config
// (see "stale reasoning-ladder self-heal" in tests/reasoning-effort.test.ts).
//
// So the registry clamp protects the DEFAULT route, not a user who has deliberately written a
// conflicting map. This test records that boundary so the next reader does not mistake the
// clamp for an enforcement the code does not implement.
test("a user reasoningEffortMap deliberately overrides the registry clamp", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "xiaomi-mimo",
providers: {
"xiaomi-mimo": {
adapter: "openai-chat",
baseUrl: "https://api.xiaomimimo.com/v1",
apiKey: "k",
authMode: "key",
// Conflicts with the registry clamp on purpose.
reasoningEffortMap: { max: "max", ultra: "ultra" },
},
},
};

const route = routeModel(config, "xiaomi-mimo/mimo-v2.5");
// The stored ladder is untouched — healing happens at lookup time, not on the config.
expect(route.provider.reasoningEfforts).toEqual(["low", "medium", "high"]);
// ...but `configuredReasoningEfforts` merges the user map's Codex values in, so `max`
// becomes a supported tier for resolution and the alias resolves to itself.
expect(mapReasoningEffort(route.provider, "mimo-v2.5", "max")).toBe("max");

// `ultra` still normalizes to `max` at the codex-rs boundary rather than reaching the wire.
expect(mapReasoningEffort(route.provider, "mimo-v2.5", "ultra")).toBe("max");

// Tiers inside the registry ladder are untouched.
expect(mapReasoningEffort(route.provider, "mimo-v2.5", "low")).toBe("low");
expect(mapReasoningEffort(route.provider, "mimo-v2.5", "medium")).toBe("medium");
});

// The case the clamp actually governs: no user map, so the registry ladder is authoritative
// and a direct max/ultra/xhigh request lands on `high` instead of reproducing the #1483 400.
test("without a conflicting user map the registry clamp holds", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "xiaomi-mimo",
providers: {
"xiaomi-mimo": {
adapter: "openai-chat",
baseUrl: "https://api.xiaomimimo.com/v1",
apiKey: "k",
authMode: "key",
},
},
};

const route = routeModel(config, "xiaomi-mimo/mimo-v2.5");
expect(route.provider.reasoningEfforts).toEqual(["low", "medium", "high"]);
for (const tier of ["max", "ultra", "xhigh"]) {
expect(mapReasoningEffort(route.provider, "mimo-v2.5", tier)).toBe("high");
}
expect(mapReasoningEffort(route.provider, "mimo-v2.5", "low")).toBe("low");
});

test("an alias that lands inside the ladder still resolves through the map", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "custom-alias",
providers: {
"custom-alias": {
adapter: "openai-chat",
baseUrl: "https://alias.example/v1",
apiKey: "k",
authMode: "key",
reasoningEfforts: ["low", "medium", "high"],
reasoningEffortMap: { max: "medium" },
},
},
};

const route = routeModel(config, "custom-alias/some-model");
expect(mapReasoningEffort(route.provider, "some-model", "max")).toBe("medium");
});

test("a provider without a configured ladder keeps its alias verbatim", () => {
const config: OcxConfig = {
port: 10100,
defaultProvider: "no-ladder",
providers: {
"no-ladder": {
adapter: "openai-chat",
baseUrl: "https://noladder.example/v1",
apiKey: "k",
authMode: "key",
reasoningEffortMap: { max: "turbo" },
},
},
};

const route = routeModel(config, "no-ladder/some-model");
expect(mapReasoningEffort(route.provider, "some-model", "max")).toBe("turbo");
});
});
2 changes: 1 addition & 1 deletion tests/provider-registry-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const EXPECTED_KEY_PROVIDER_IDS = [
"huggingface", "nvidia", "venice", "zai", "zhipu-bigmodel", "zhipu-bigmodel-coding", "nanogpt", "synthetic", "siliconflow", "qwen-cloud", "tencent-coding-plan",
"volcengine", "volcengine-coding-plan", "volcengine-agent-plan", "qianfan", "alibaba", "alibaba-token-plan", "alibaba-token-plan-intl", "parallel", "zenmux", "litellm", "ollama-cloud", "mistral",
"minimax", "minimax-cn", "kimi-code", "opencode-zen", "vercel-ai-gateway",
"opencode-free", "xiaomi", "kilo", "mimo-free", "mimo", "cloudflare-ai-gateway", "cloudflare-workers-ai", "gitlab-duo",
"opencode-free", "xiaomi", "xiaomi-mimo", "kilo", "mimo-free", "mimo", "cloudflare-ai-gateway", "cloudflare-workers-ai", "gitlab-duo",
];

describe("provider registry parity", () => {
Expand Down
Loading