mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 21:30:17 +08:00
36e0378e78
The "Get API Key" link (and partner promotion) below the API key input was only wired for claude/codex/gemini/opencode. Claude Desktop uses a separate form that never rendered it, and OpenClaw/Hermes were blocked by two gaps: - useApiKeyLink whitelisted only 4 app ids, so the link was suppressed for claude-desktop/openclaw/hermes even when a preset carried apiKeyUrl. - useProviderCategory only parsed claude/codex/gemini/opencode preset ids, so OpenClaw/Hermes category stayed undefined and the link condition (cn_official/aggregator/third_party) never held. Changes: - ClaudeDesktopProviderForm: call useApiKeyLink and replace the bare API key Input with the shared ApiKeySection. - useApiKeyLink: add claude-desktop/openclaw/hermes to the whitelist and add ClaudeDesktopProviderPreset to the PresetEntry union. - useProviderCategory: parse and resolve openclaw/hermes preset categories. - Hermes/OpenClaw form fields: don't let an "official" category disable the API key input, since these apps have no OAuth-only official providers (e.g. Hermes' Nous Research is "official" but still needs a user key).
98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import { useMemo } from "react";
|
|
import type { AppId } from "@/lib/api";
|
|
import type { ProviderCategory } from "@/types";
|
|
import type { ProviderPreset } from "@/config/claudeProviderPresets";
|
|
import type { CodexProviderPreset } from "@/config/codexProviderPresets";
|
|
import type { GeminiProviderPreset } from "@/config/geminiProviderPresets";
|
|
import type { OpenCodeProviderPreset } from "@/config/opencodeProviderPresets";
|
|
import type { ClaudeDesktopProviderPreset } from "@/config/claudeDesktopProviderPresets";
|
|
|
|
type PresetEntry = {
|
|
id: string;
|
|
preset:
|
|
| ProviderPreset
|
|
| CodexProviderPreset
|
|
| GeminiProviderPreset
|
|
| OpenCodeProviderPreset
|
|
| ClaudeDesktopProviderPreset;
|
|
};
|
|
|
|
interface UseApiKeyLinkProps {
|
|
appId: AppId;
|
|
category?: ProviderCategory;
|
|
selectedPresetId: string | null;
|
|
presetEntries: PresetEntry[];
|
|
formWebsiteUrl: string;
|
|
}
|
|
|
|
/**
|
|
* 管理 API Key 获取链接的显示和 URL
|
|
*/
|
|
export function useApiKeyLink({
|
|
appId,
|
|
category,
|
|
selectedPresetId,
|
|
presetEntries,
|
|
formWebsiteUrl,
|
|
}: UseApiKeyLinkProps) {
|
|
// 判断是否显示 API Key 获取链接
|
|
const shouldShowApiKeyLink = useMemo(() => {
|
|
return (
|
|
category !== "official" &&
|
|
(category === "cn_official" ||
|
|
category === "aggregator" ||
|
|
category === "third_party")
|
|
);
|
|
}, [category]);
|
|
|
|
// 获取当前预设条目
|
|
const currentPresetEntry = useMemo(() => {
|
|
if (selectedPresetId && selectedPresetId !== "custom") {
|
|
return presetEntries.find((item) => item.id === selectedPresetId);
|
|
}
|
|
return undefined;
|
|
}, [selectedPresetId, presetEntries]);
|
|
|
|
// 获取当前供应商的网址(用于 API Key 链接)
|
|
const getWebsiteUrl = useMemo(() => {
|
|
if (currentPresetEntry) {
|
|
const preset = currentPresetEntry.preset;
|
|
// 对于 cn_official、aggregator、third_party,优先使用 apiKeyUrl(可能包含推广参数)
|
|
if (
|
|
preset.category === "cn_official" ||
|
|
preset.category === "aggregator" ||
|
|
preset.category === "third_party"
|
|
) {
|
|
return preset.apiKeyUrl || preset.websiteUrl || "";
|
|
}
|
|
return preset.websiteUrl || "";
|
|
}
|
|
return formWebsiteUrl || "";
|
|
}, [currentPresetEntry, formWebsiteUrl]);
|
|
|
|
// 提取合作伙伴信息
|
|
const isPartner = useMemo(() => {
|
|
return currentPresetEntry?.preset.isPartner ?? false;
|
|
}, [currentPresetEntry]);
|
|
|
|
const partnerPromotionKey = useMemo(() => {
|
|
return currentPresetEntry?.preset.partnerPromotionKey;
|
|
}, [currentPresetEntry]);
|
|
|
|
return {
|
|
shouldShowApiKeyLink:
|
|
appId === "claude" ||
|
|
appId === "claude-desktop" ||
|
|
appId === "codex" ||
|
|
appId === "gemini" ||
|
|
appId === "opencode" ||
|
|
appId === "openclaw" ||
|
|
appId === "hermes"
|
|
? shouldShowApiKeyLink
|
|
: false,
|
|
websiteUrl: getWebsiteUrl,
|
|
isPartner,
|
|
partnerPromotionKey,
|
|
};
|
|
}
|