Files
cc-switch/tests/config/subrouterProviderPresets.test.ts
Jason 50a9d103d3 chore(presets): refresh preset models to the latest vendor lineups
Move first-party, sponsor and relay presets to current model IDs so a
pasted Key works without editing the model list.

- Claude: opus/sonnet 5 -> 5.5, haiku 4.5 -> 5.5, fable 5 -> 5.1
- GPT: gpt-5.6-sol / gpt-6-sol -> gpt-6.1-sol; add gpt-6-astra/luna
- Gemini 3.6 Flash -> 3.8 Flash, 3.1 Pro preview -> 4 Argon;
  Grok 4.5 -> 4.7; GLM 5.1/5.2 -> 5.3 (+5.3 Flash);
  DeepSeek V4 Flash -> V4.1 Flash; Doubao 2.1 Pro 260628 -> 260915;
  StepFun Step Plan -> step-5-preview; add Kimi K3.1 Pro, Qwen3.8 Max,
  MiniMax M3.1 Flash where the site serves them
- Drop retired models: NVIDIA moonshotai/kimi-k3 (EOL 2026-10-15,
  now kimi-k2.6 without unverified Codex reasoning levels),
  MiMo V2.5 / V2.5 Pro, Claude Sonnet 4.5, MiniMax M2.7 on Tencent
  Token Plan Enterprise Pro
- Relay presets follow each site's own ID spelling and catalog;
  DIT.ai, BuyToken and hao.ai are left as configured from their docs;
  Soshow, SiliconFlow CN, OpenCode Zen and the Ark rolling alias stay
- MoArk Codex keeps the tested Kimi-K2.7-Code; K3.1 Pro and Qwen3.8
  Max stay out of its Codex catalog until their levels are verified

Tests updated to the new IDs; cross-app invariants unchanged.
2026-10-24 22:56:15 +08:00

131 lines
4.9 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { claudeDesktopProviderPresets } from "@/config/claudeDesktopProviderPresets";
import { providerPresets } from "@/config/claudeProviderPresets";
import { codexProviderPresets } from "@/config/codexProviderPresets";
import { geminiProviderPresets } from "@/config/geminiProviderPresets";
import { hermesProviderPresets } from "@/config/hermesProviderPresets";
import { openclawProviderPresets } from "@/config/openclawProviderPresets";
import { opencodeProviderPresets } from "@/config/opencodeProviderPresets";
import { hasIcon } from "@/icons/extracted";
const WEBSITE_URL = "https://subrouter.ai";
const API_KEY_URL = "https://subrouter.ai/register?aff=l3ri";
describe("SubRouter provider presets", () => {
it("uses the Anthropic-compatible root endpoint for Claude", () => {
const preset = providerPresets.find((item) => item.name === "SubRouter");
expect(preset).toBeDefined();
expect(preset?.websiteUrl).toBe(WEBSITE_URL);
expect(preset?.apiKeyUrl).toBe(API_KEY_URL);
expect(preset?.category).toBe("aggregator");
expect(preset?.isPartner).toBe(true);
expect(preset?.partnerPromotionKey).toBe("subrouter");
expect(preset?.icon).toBe("subrouter");
const env = (preset?.settingsConfig as { env: Record<string, string> }).env;
expect(env.ANTHROPIC_BASE_URL).toBe("https://subrouter.ai");
expect(env.ANTHROPIC_AUTH_TOKEN).toBe("");
});
it("uses the OpenAI-compatible v1 endpoint for Codex", () => {
const preset = codexProviderPresets.find(
(item) => item.name === "SubRouter",
);
expect(preset).toBeDefined();
expect(preset?.websiteUrl).toBe(WEBSITE_URL);
expect(preset?.apiKeyUrl).toBe(API_KEY_URL);
expect(preset?.category).toBe("aggregator");
expect(preset?.endpointCandidates).toEqual(["https://subrouter.ai/v1"]);
expect(preset?.auth).toEqual({ OPENAI_API_KEY: "" });
expect(preset?.config).toContain('name = "subrouter"');
expect(preset?.config).toContain('model = "gpt-6.1-sol"');
expect(preset?.config).toContain('base_url = "https://subrouter.ai/v1"');
expect(preset?.config).toContain('wire_api = "responses"');
});
it("uses the Gemini-compatible v1beta endpoint for Gemini", () => {
const preset = geminiProviderPresets.find(
(item) => item.name === "SubRouter",
);
expect(preset).toBeDefined();
expect(preset?.baseURL).toBe("https://subrouter.ai/v1beta");
expect(preset?.endpointCandidates).toEqual(["https://subrouter.ai/v1beta"]);
expect(preset?.model).toBe("gemini-3.8-flash");
const env = (preset?.settingsConfig as { env: Record<string, string> }).env;
expect(env.GOOGLE_GEMINI_BASE_URL).toBe("https://subrouter.ai/v1beta");
expect(env.GEMINI_MODEL).toBe("gemini-3.8-flash");
});
it("uses OpenAI-compatible config for OpenCode", () => {
const preset = opencodeProviderPresets.find(
(item) => item.name === "SubRouter",
);
expect(preset).toBeDefined();
expect(preset?.settingsConfig.npm).toBe("@ai-sdk/openai-compatible");
expect(preset?.settingsConfig.options?.baseURL).toBe(
"https://subrouter.ai/v1",
);
expect(preset?.settingsConfig.options?.apiKey).toBe("");
expect(preset?.settingsConfig.models).toHaveProperty("gpt-6.1-sol");
});
it("uses OpenAI completions config for OpenClaw without hardcoded pricing", () => {
const preset = openclawProviderPresets.find(
(item) => item.name === "SubRouter",
);
const [model] = preset?.settingsConfig.models ?? [];
expect(preset).toBeDefined();
expect(preset?.settingsConfig.baseUrl).toBe("https://subrouter.ai/v1");
expect(preset?.settingsConfig.api).toBe("openai-completions");
expect(model).toMatchObject({
id: "gpt-6.1-sol",
name: "GPT-6.1 Sol",
contextWindow: 272000,
});
expect(model).not.toHaveProperty("cost");
expect(preset?.suggestedDefaults?.model).toEqual({
primary: "subrouter/gpt-6.1-sol",
});
});
it("uses chat completions config for Hermes", () => {
const preset = hermesProviderPresets.find(
(item) => item.name === "SubRouter",
);
expect(preset).toBeDefined();
expect(preset?.settingsConfig).toMatchObject({
name: "subrouter",
base_url: "https://subrouter.ai/v1",
api_key: "",
api_mode: "chat_completions",
});
expect(preset?.suggestedDefaults?.model).toEqual({
default: "gpt-6.1-sol",
provider: "subrouter",
});
});
it("uses direct Anthropic routing for Claude Desktop", () => {
const preset = claudeDesktopProviderPresets.find(
(item) => item.name === "SubRouter",
);
expect(preset).toBeDefined();
expect(preset?.baseUrl).toBe("https://subrouter.ai");
expect(preset?.mode).toBe("direct");
expect(preset?.apiFormat).toBe("anthropic");
expect(preset?.modelRoutes?.length).toBeGreaterThan(0);
});
it("registers the SubRouter provider icon", () => {
expect(hasIcon("subrouter")).toBe(true);
});
});