Files
cc-switch/src/config/ppioProviderPresets.test.ts
T
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

278 lines
8.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { claudeDesktopProviderPresets } from "./claudeDesktopProviderPresets";
import { providerPresets } from "./claudeProviderPresets";
import { codexProviderPresets } from "./codexProviderPresets";
import { hermesProviderPresets } from "./hermesProviderPresets";
import { openclawProviderPresets } from "./openclawProviderPresets";
import { opencodeProviderPresets } from "./opencodeProviderPresets";
import { piProviderPresets } from "./piProviderPresets";
import { getIcon, getIconMetadata } from "../icons/extracted";
const ppioPresetCollections = [
["Claude Code", providerPresets],
["Claude Desktop", claudeDesktopProviderPresets],
["Codex", codexProviderPresets],
["OpenCode", opencodeProviderPresets],
["OpenClaw", openclawProviderPresets],
["Hermes", hermesProviderPresets],
["Pi", piProviderPresets],
] as const;
const ppioModelId = "deepseek/deepseek-v4.1-flash";
const ppioModelName = "DeepSeek V4.1 Flash";
const ppioAnthropicEndpoint = "https://api.ppio.com/anthropic";
const ppioOpenAiEndpoint = "https://api.ppio.com/openai/v1";
const ppioChatCompletionsEndpoint = `${ppioOpenAiEndpoint}/chat/completions`;
const ppioModelsEndpoint = `${ppioOpenAiEndpoint}/models`;
const ppioBrandFields = {
websiteUrl: "https://ppio.com",
apiKeyUrl: "https://ppio.com/activity/ccswitch",
category: "aggregator",
isPartner: true,
partnerPromotionKey: "ppio",
icon: "ppio",
iconColor: "#2874FF",
};
function getPpioPreset<T extends { name: string }>(presets: readonly T[]) {
return presets.find((preset) => preset.name === "PPIO");
}
describe("PPIO provider presets", () => {
it.each(ppioPresetCollections)(
"%s registers exactly one PPIO preset",
(_name, presets) => {
expect(presets.filter((preset) => preset.name === "PPIO")).toHaveLength(
1,
);
},
);
it("configures Claude Code with the native Anthropic endpoint", () => {
const claude = getPpioPreset(providerPresets)!;
expect(claude).toMatchObject({
...ppioBrandFields,
settingsConfig: {
env: {
ANTHROPIC_BASE_URL: ppioAnthropicEndpoint,
ANTHROPIC_AUTH_TOKEN: "",
ANTHROPIC_MODEL: `${ppioModelId}[1M]`,
ANTHROPIC_DEFAULT_HAIKU_MODEL: `${ppioModelId}[1M]`,
ANTHROPIC_DEFAULT_SONNET_MODEL: `${ppioModelId}[1M]`,
ANTHROPIC_DEFAULT_OPUS_MODEL: `${ppioModelId}[1M]`,
},
},
endpointCandidates: [ppioAnthropicEndpoint],
modelsUrl: ppioModelsEndpoint,
});
});
it("configures Claude Desktop with the native Anthropic endpoint", () => {
expect(getPpioPreset(claudeDesktopProviderPresets)).toMatchObject({
...ppioBrandFields,
baseUrl: ppioAnthropicEndpoint,
mode: "proxy",
apiFormat: "anthropic",
modelRoutes: [
{
routeId: "claude-sonnet-5",
upstreamModel: ppioModelId,
labelOverride: ppioModelId,
supports1m: true,
},
],
endpointCandidates: [ppioAnthropicEndpoint],
});
});
it("configures Codex for OpenAI Chat translation and reasoning", () => {
const codex = getPpioPreset(codexProviderPresets)!;
expect(codex).toMatchObject({
...ppioBrandFields,
auth: { OPENAI_API_KEY: "" },
endpointCandidates: [ppioOpenAiEndpoint],
apiFormat: "openai_chat",
modelCatalog: [
{
model: ppioModelId,
displayName: ppioModelName,
contextWindow: 1048576,
inputModalities: ["text"],
},
],
codexChatReasoning: {
supportsThinking: true,
supportsEffort: false,
thinkingParam: "thinking",
effortParam: "none",
outputFormat: "reasoning_content",
},
});
expect(codex.config).toContain(`model = "${ppioModelId}"`);
expect(codex.config).toContain(`base_url = "${ppioOpenAiEndpoint}"`);
expect(codex.config).toContain('wire_api = "responses"');
});
it("configures OpenCode with a versioned OpenAI-compatible base", () => {
const opencode = getPpioPreset(opencodeProviderPresets)!;
expect(opencode).toMatchObject({
...ppioBrandFields,
settingsConfig: {
npm: "@ai-sdk/openai-compatible",
name: "PPIO",
options: {
baseURL: ppioOpenAiEndpoint,
apiKey: "",
setCacheKey: true,
},
models: { [ppioModelId]: { name: ppioModelName } },
},
templateValues: {
apiKey: { label: "API Key", placeholder: "", editorValue: "" },
},
});
expect(Object.keys(opencode.settingsConfig.models)).toEqual([
ppioModelId,
"moonshotai/kimi-k3.1-pro",
"zai-org/glm-5.3",
"deepseek/deepseek-v4-pro",
]);
expect(`${opencode.settingsConfig.options.baseURL}/chat/completions`).toBe(
ppioChatCompletionsEndpoint,
);
});
it("configures OpenClaw with a versioned OpenAI Chat base", () => {
const openclaw = getPpioPreset(openclawProviderPresets)!;
expect(openclaw).toMatchObject({
...ppioBrandFields,
settingsConfig: {
baseUrl: ppioOpenAiEndpoint,
apiKey: "",
api: "openai-completions",
},
templateValues: {
apiKey: { label: "API Key", placeholder: "sk-...", editorValue: "" },
},
suggestedDefaults: {
model: { primary: `ppio/${ppioModelId}` },
modelCatalog: { [`ppio/${ppioModelId}`]: { alias: ppioModelName } },
},
});
expect(
(openclaw.settingsConfig.models ?? []).map((model) => model.id),
).toEqual([
ppioModelId,
"moonshotai/kimi-k3.1-pro",
"zai-org/glm-5.3",
"deepseek/deepseek-v4-pro",
"xiaomimimo/mimo-v2.6-pro",
"qwen/qwen3.8-max",
"minimax/minimax-m3.1-flash",
"stepfun/step-5-preview",
]);
expect(openclaw.settingsConfig.models?.[0]).toMatchObject({
id: ppioModelId,
name: ppioModelName,
reasoning: true,
input: ["text"],
contextWindow: 1048576,
maxTokens: 393216,
cost: { input: 0.14, output: 0.29, cacheRead: 0.03 },
});
expect(`${openclaw.settingsConfig.baseUrl}/chat/completions`).toBe(
ppioChatCompletionsEndpoint,
);
});
it("configures Hermes with a versioned OpenAI Chat base", () => {
const hermes = getPpioPreset(hermesProviderPresets)!;
expect(hermes).toMatchObject({
...ppioBrandFields,
settingsConfig: {
name: "ppio",
base_url: ppioOpenAiEndpoint,
api_key: "",
api_mode: "chat_completions",
models: [
{
id: ppioModelId,
name: ppioModelName,
context_length: 1048576,
},
{
id: "moonshotai/kimi-k3.1-pro",
name: "Kimi K3.1 Pro",
context_length: 1048576,
},
{ id: "zai-org/glm-5.3", name: "GLM-5.3", context_length: 1000000 },
{
id: "deepseek/deepseek-v4-pro",
name: "DeepSeek V4 Pro",
context_length: 1000000,
},
],
},
suggestedDefaults: {
model: { default: ppioModelId, provider: "ppio" },
},
});
expect(`${hermes.settingsConfig.base_url}/chat/completions`).toBe(
ppioChatCompletionsEndpoint,
);
});
it("configures Pi with a versioned OpenAI Chat base", () => {
const pi = getPpioPreset(piProviderPresets)!;
expect(pi).toMatchObject({
...ppioBrandFields,
providerKey: "cc-switch-ppio",
settingsConfig: {
name: "PPIO",
baseUrl: ppioOpenAiEndpoint,
api: "openai-completions",
apiKey: "",
},
});
expect(pi.settingsConfig.models.map((model) => model.id)).toEqual([
ppioModelId,
"moonshotai/kimi-k3.1-pro",
"zai-org/glm-5.3",
]);
expect(pi.settingsConfig.models[0]).toMatchObject({
id: ppioModelId,
name: ppioModelName,
reasoning: true,
input: ["text"],
contextWindow: 1048576,
maxTokens: 393216,
thinkingLevelMap: {
minimal: null,
low: null,
medium: null,
high: "high",
max: "max",
},
compat: {
supportsStore: false,
supportsDeveloperRole: false,
maxTokensField: "max_tokens",
requiresReasoningContentOnAssistantMessages: true,
thinkingFormat: "deepseek",
},
});
expect(`${pi.settingsConfig.baseUrl}/chat/completions`).toBe(
ppioChatCompletionsEndpoint,
);
});
it("registers the PPIO brand icon", () => {
expect(getIcon("ppio")).toContain("<title>PPIO</title>");
expect(getIconMetadata("ppio")).toMatchObject({
displayName: "PPIO",
defaultColor: "#2874FF",
});
});
});