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
4 changes: 4 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2470,6 +2470,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
// The gateway validates the ladder strictly and rejects anything above `high`.
reasoningEfforts: ["low", "medium", "high"],
reasoningEffortMap: { xhigh: "high", max: "high", ultra: "high" },
// Live token-plan verification (#1927): the Pro route rejects image input while
// mimo-v2.5 accepts it natively. Keep this provider-scoped so a hand-rolled
// provider with the same id but another destination does not inherit the claim.
noVisionModels: ["mimo-v2.5-pro"],
// A user may already have hand-rolled a provider under this id against a different host;
// without this, routedProviderConfig() would canonicalize their base URL onto ours and send
// their key somewhere they did not choose.
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 @@ -255,6 +255,21 @@ the request, and they never raise it.
`preserveCustomDestination`으로 같은 이름의 다른 host/key를 보호한다. 대신 새 preset 표면을
문서와 registry parity에서 함께 유지해야 한다.

[Decision Log]
- 목적과 의도: Xiaomi token-plan에서 image input을 거부하는 `mimo-v2.5-pro`만 vision
sidecar로 우회하고, 실제 image input을 받는 `mimo-v2.5`는 native vision 경로에 남긴다.
- 기존 구현 및 제약 조건: upstream `/v1/models`는 input modality를 제공하지 않으며,
`noVisionModels`는 text-only 모델을 sidecar로 보내면서 Codex catalog에는 image input을
광고하는 provider-scoped 계약이다.
- 검토한 주요 대안: MiMo 전체를 text-only로 분류하기, live discovery에서 modality를
추측하기, `mimo-v2.5-pro` 하나만 registry에 고정 분류하기.
- 선택한 방식: canonical `mimo` preset의 `noVisionModels`에 `mimo-v2.5-pro`만 추가한다.
- 다른 대안 대신 이 방식을 선택한 이유: live endpoint 검증으로 확인된 최소 범위만
적용하며, 정상 동작하는 `mimo-v2.5`의 native image 경로를 훼손하지 않는다.
- 장점, 단점 및 영향: Pro image 요청의 404를 sidecar 설명 경로로 바꾸고 base 모델은
그대로 유지한다. `preserveCustomDestination` guard 때문에 같은 provider id를 다른 host에
연결한 사용자 설정에는 이 capability 분류가 전파되지 않는다.

[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
26 changes: 26 additions & 0 deletions tests/catalog-vision-sidecar-modalities.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,32 @@ describe("vision-sidecar catalog modalities", () => {
const hinted = applyProviderConfigHints("opencode-go", prov, { id: "glm-5.2", provider: "opencode-go" });
expect(hinted.inputModalities).toEqual(["text", "image"]);
});

test("MiMo token-plan sends only the Pro model through the sidecar (#1927)", () => {
const canonical: OcxProviderConfig = {
adapter: "openai-chat",
baseUrl: "https://token-plan-cn.xiaomimimo.com/v1",
authMode: "key",
};
enrichProviderFromRegistry("mimo", canonical);
expect(canonical.noVisionModels).toEqual(["mimo-v2.5-pro"]);
expect(applyProviderConfigHints("mimo", canonical, {
id: "mimo-v2.5-pro",
provider: "mimo",
}).inputModalities).toEqual(["text", "image"]);
expect(applyProviderConfigHints("mimo", canonical, {
id: "mimo-v2.5",
provider: "mimo",
}).inputModalities).toBeUndefined();

const customDestination: OcxProviderConfig = {
adapter: "openai-chat",
baseUrl: "https://mimo-compatible.example/v1",
authMode: "key",
};
enrichProviderFromRegistry("mimo", customDestination);
expect(customDestination.noVisionModels).toBeUndefined();
});
});

describe("vision-sidecar custom-model override (#349/#344)", () => {
Expand Down
2 changes: 2 additions & 0 deletions tests/provider-registry-parity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ describe("provider registry parity", () => {
"qwen3.7-max",
]);
expect(KEY_LOGIN_PROVIDERS["opencode-go"].noVisionModels).not.toContain("kimi-k2.7-code");
expect(KEY_LOGIN_PROVIDERS.mimo.noVisionModels).toEqual(["mimo-v2.5-pro"]);
expect(KEY_LOGIN_PROVIDERS.mimo.noVisionModels).not.toContain("mimo-v2.5");
expect(KEY_LOGIN_PROVIDERS["opencode-go"]).toMatchObject({
modelContextWindows: { "kimi-k3": 262_144 },
modelInputModalities: { "kimi-k3": ["text", "image"] },
Expand Down
Loading