feat(opencode): add API key link support for OpenCode provider form

Enable API key link feature for OpenCode app, allowing users to access
provider websites for key registration directly from the form.
This commit is contained in:
Jason
2026-01-31 17:16:36 +08:00
Unverified
parent 151e43a808
commit bd8a323600
4 changed files with 34 additions and 5 deletions
@@ -139,6 +139,8 @@ interface OpenCodeFormFieldsProps {
category?: ProviderCategory;
shouldShowApiKeyLink: boolean;
websiteUrl: string;
isPartner?: boolean;
partnerPromotionKey?: string;
// Base URL
baseUrl: string;
@@ -161,6 +163,8 @@ export function OpenCodeFormFields({
category,
shouldShowApiKeyLink,
websiteUrl,
isPartner,
partnerPromotionKey,
baseUrl,
onBaseUrlChange,
models,
@@ -376,6 +380,8 @@ export function OpenCodeFormFields({
category={category}
shouldShowLink={shouldShowApiKeyLink}
websiteUrl={websiteUrl}
isPartner={isPartner}
partnerPromotionKey={partnerPromotionKey}
/>
{/* Base URL */}
@@ -1010,6 +1010,20 @@ export function ProviderForm({
formWebsiteUrl: form.watch("websiteUrl") || "",
});
// 使用 API Key 链接 hook (OpenCode)
const {
shouldShowApiKeyLink: shouldShowOpencodeApiKeyLink,
websiteUrl: opencodeWebsiteUrl,
isPartner: isOpencodePartner,
partnerPromotionKey: opencodePartnerPromotionKey,
} = useApiKeyLink({
appId: "opencode",
category,
selectedPresetId,
presetEntries,
formWebsiteUrl: form.watch("websiteUrl") || "",
});
// 使用端点测速候选 hook
const speedTestEndpoints = useSpeedTestEndpoints({
appId,
@@ -1341,8 +1355,10 @@ export function ProviderForm({
apiKey={opencodeApiKey}
onApiKeyChange={handleOpencodeApiKeyChange}
category={category}
shouldShowApiKeyLink={false}
websiteUrl=""
shouldShowApiKeyLink={shouldShowOpencodeApiKeyLink}
websiteUrl={opencodeWebsiteUrl}
isPartner={isOpencodePartner}
partnerPromotionKey={opencodePartnerPromotionKey}
baseUrl={opencodeBaseUrl}
onBaseUrlChange={handleOpencodeBaseUrlChange}
models={opencodeModels}
@@ -4,10 +4,11 @@ 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";
type PresetEntry = {
id: string;
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset;
preset: ProviderPreset | CodexProviderPreset | GeminiProviderPreset | OpenCodeProviderPreset;
};
interface UseApiKeyLinkProps {
@@ -74,7 +75,7 @@ export function useApiKeyLink({
return {
shouldShowApiKeyLink:
appId === "claude" || appId === "codex" || appId === "gemini"
appId === "claude" || appId === "codex" || appId === "gemini" || appId === "opencode"
? shouldShowApiKeyLink
: false,
websiteUrl: getWebsiteUrl,
@@ -4,6 +4,7 @@ import type { AppId } from "@/lib/api";
import { providerPresets } from "@/config/claudeProviderPresets";
import { codexProviderPresets } from "@/config/codexProviderPresets";
import { geminiProviderPresets } from "@/config/geminiProviderPresets";
import { opencodeProviderPresets } from "@/config/opencodeProviderPresets";
interface UseProviderCategoryProps {
appId: AppId;
@@ -42,7 +43,7 @@ export function useProviderCategory({
if (!selectedPresetId) return;
// 从预设 ID 提取索引
const match = selectedPresetId.match(/^(claude|codex|gemini)-(\d+)$/);
const match = selectedPresetId.match(/^(claude|codex|gemini|opencode)-(\d+)$/);
if (!match) return;
const [, type, indexStr] = match;
@@ -67,6 +68,11 @@ export function useProviderCategory({
if (preset) {
setCategory(preset.category || undefined);
}
} else if (type === "opencode" && appId === "opencode") {
const preset = opencodeProviderPresets[index];
if (preset) {
setCategory(preset.category || undefined);
}
}
}, [appId, selectedPresetId, isEditMode, initialCategory]);