From 36e0378e783923fdbe62fd74e26c8c1ee9616227 Mon Sep 17 00:00:00 2001 From: Jason Date: Mon, 29 Jun 2026 18:49:41 +0800 Subject: [PATCH] feat(providers): show API key link in Claude Desktop, OpenClaw and Hermes forms 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). --- .../forms/ClaudeDesktopProviderForm.tsx | 35 ++++++++++++++----- .../providers/forms/HermesFormFields.tsx | 4 ++- .../providers/forms/OpenClawFormFields.tsx | 4 ++- .../providers/forms/hooks/useApiKeyLink.ts | 9 +++-- .../forms/hooks/useProviderCategory.ts | 14 +++++++- 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/components/providers/forms/ClaudeDesktopProviderForm.tsx b/src/components/providers/forms/ClaudeDesktopProviderForm.tsx index bd0fd3e44..1030c6d0f 100644 --- a/src/components/providers/forms/ClaudeDesktopProviderForm.tsx +++ b/src/components/providers/forms/ClaudeDesktopProviderForm.tsx @@ -39,9 +39,11 @@ import { Switch } from "@/components/ui/switch"; import { BasicFormFields } from "./BasicFormFields"; import { CodexOAuthSection } from "./CodexOAuthSection"; import { CopilotAuthSection } from "./CopilotAuthSection"; +import { ApiKeySection } from "./shared/ApiKeySection"; import { EndpointField } from "./shared/EndpointField"; import { ModelDropdown } from "./shared/ModelDropdown"; import { ProviderPresetSelector } from "./ProviderPresetSelector"; +import { useApiKeyLink } from "./hooks/useApiKeyLink"; import { providerSchema, type ProviderFormData } from "@/lib/schemas/provider"; import type { ClaudeApiFormat, @@ -383,6 +385,21 @@ export function ClaudeDesktopProviderForm({ activeProviderType === "github_copilot" || activeProviderType === "codex_oauth"; + // API Key 获取/邀请链接(与 Claude Code 表单同款,见 ClaudeFormFields) + const apiKeyLinkCategory = activePreset?.category ?? initialData?.category; + const { + shouldShowApiKeyLink, + websiteUrl: apiKeyLinkWebsiteUrl, + isPartner: apiKeyLinkIsPartner, + partnerPromotionKey: apiKeyLinkPromotionKey, + } = useApiKeyLink({ + appId: "claude-desktop", + category: apiKeyLinkCategory, + selectedPresetId, + presetEntries, + formWebsiteUrl: form.watch("websiteUrl") || "", + }); + const applyDesktopPreset = (preset: ClaudeDesktopProviderPreset) => { form.setValue("name", preset.nameKey ? t(preset.nameKey) : preset.name); form.setValue("websiteUrl", preset.websiteUrl); @@ -766,15 +783,15 @@ export function ClaudeDesktopProviderForm({ )} ) : ( -
- - setApiKey(event.target.value)} - type="password" - placeholder="sk-..." - /> -
+ )}