feat(claude-desktop): add 44 provider presets translated from Claude Code

- New src/config/claudeDesktopProviderPresets.ts with the Claude Code
  preset list re-shaped into Desktop's three-segment route format
  (routeId / upstreamModel / displayName); excludes OAuth providers,
  AWS Bedrock (no SigV4 support) and KAT-Coder (placeholder URL).
- Non-Claude upstream presets show upstream model id as displayName
  (e.g. deepseek-v4-pro) so the Desktop model list reflects what is
  actually being requested. OpenRouter/TheRouter/PIPELLM keep
  Sonnet/Opus/Haiku since their upstream really is Anthropic Claude.
- Wire ProviderPresetSelector into ClaudeDesktopProviderForm so
  selecting a preset back-fills baseUrl, mode, routes and apiFormat.
- Drop the hard-coded ANTHROPIC_AUTH_TOKEN write in handleSubmit so
  ANTHROPIC_API_KEY presets (LemonData / AiHubMix / Gemini Native)
  save under the correct env key, and clear the opposite key on switch.
- Hide the universal-providers tab for claude-desktop because its
  meta-driven routing has no analogue in the universal flat-env shape.
- Add apps."claude-desktop" i18n key (zh/en/ja) so the dialog tab
  label resolves instead of showing the literal key.
This commit is contained in:
Jason
2026-05-09 17:19:09 +08:00
parent 292c117509
commit 5bbd83f7ca
7 changed files with 996 additions and 14 deletions
@@ -5,6 +5,7 @@ import { Zap, Star, Layers, Settings2 } from "lucide-react";
import type { ProviderPreset } from "@/config/claudeProviderPresets";
import type { CodexProviderPreset } from "@/config/codexProviderPresets";
import type { GeminiProviderPreset } from "@/config/geminiProviderPresets";
import type { ClaudeDesktopProviderPreset } from "@/config/claudeDesktopProviderPresets";
import type { ProviderCategory } from "@/types";
import {
universalProviderPresets,
@@ -12,9 +13,15 @@ import {
} from "@/config/universalProviderPresets";
import { ProviderIcon } from "@/components/ProviderIcon";
type AnyPreset =
| ProviderPreset
| CodexProviderPreset
| GeminiProviderPreset
| ClaudeDesktopProviderPreset;
type PresetEntry = {
id: string;
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset;
preset: AnyPreset;
};
interface ProviderPresetSelectorProps {
@@ -74,9 +81,7 @@ export function ProviderPresetSelector({
}
};
const renderPresetIcon = (
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset,
) => {
const renderPresetIcon = (preset: AnyPreset) => {
const iconType = preset.theme?.icon;
if (!iconType) return null;
@@ -94,10 +99,7 @@ export function ProviderPresetSelector({
}
};
const getPresetButtonClass = (
isSelected: boolean,
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset,
) => {
const getPresetButtonClass = (isSelected: boolean, preset: AnyPreset) => {
const baseClass =
"inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors";
@@ -111,10 +113,7 @@ export function ProviderPresetSelector({
return `${baseClass} bg-accent text-muted-foreground hover:bg-accent/80`;
};
const getPresetButtonStyle = (
isSelected: boolean,
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset,
) => {
const getPresetButtonStyle = (isSelected: boolean, preset: AnyPreset) => {
if (!isSelected || !preset.theme?.backgroundColor) {
return undefined;
}