fix(providers): complete custom openai-responses support (#436)
This commit is contained in:
@@ -59,6 +59,15 @@ function normalizeFallbackProviderIds(ids?: string[]): string[] {
|
||||
return Array.from(new Set((ids ?? []).filter(Boolean)));
|
||||
}
|
||||
|
||||
function getProtocolBaseUrlPlaceholder(
|
||||
apiProtocol: ProviderAccount['apiProtocol'],
|
||||
): string {
|
||||
if (apiProtocol === 'anthropic-messages') {
|
||||
return 'https://api.example.com/anthropic';
|
||||
}
|
||||
return 'https://api.example.com/v1';
|
||||
}
|
||||
|
||||
function fallbackProviderIdsEqual(a?: string[], b?: string[]): boolean {
|
||||
const left = normalizeFallbackProviderIds(a).sort();
|
||||
const right = normalizeFallbackProviderIds(b).sort();
|
||||
@@ -271,7 +280,7 @@ interface ProviderCardProps {
|
||||
onSaveEdits: (payload: { newApiKey?: string; updates?: Partial<ProviderConfig> }) => Promise<void>;
|
||||
onValidateKey: (
|
||||
key: string,
|
||||
options?: { baseUrl?: string; apiProtocol?: string }
|
||||
options?: { baseUrl?: string; apiProtocol?: ProviderAccount['apiProtocol'] }
|
||||
) => Promise<{ valid: boolean; error?: string }>;
|
||||
devModeUnlocked: boolean;
|
||||
}
|
||||
@@ -537,7 +546,7 @@ function ProviderCard({
|
||||
<Input
|
||||
value={baseUrl}
|
||||
onChange={(e) => setBaseUrl(e.target.value)}
|
||||
placeholder={apiProtocol === 'anthropic-messages' ? "https://api.example.com/anthropic" : "https://api.example.com/v1"}
|
||||
placeholder={getProtocolBaseUrlPlaceholder(apiProtocol)}
|
||||
className={currentInputClasses}
|
||||
/>
|
||||
</div>
|
||||
@@ -562,7 +571,14 @@ function ProviderCard({
|
||||
onClick={() => setApiProtocol('openai-completions')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'openai-completions' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.openai', 'OpenAI')}
|
||||
{t('aiProviders.protocols.openaiCompletions', 'OpenAI Completions')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setApiProtocol('openai-responses')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'openai-responses' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.openaiResponses', 'OpenAI Responses')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -740,7 +756,7 @@ interface AddProviderDialogProps {
|
||||
onValidateKey: (
|
||||
type: string,
|
||||
apiKey: string,
|
||||
options?: { baseUrl?: string; apiProtocol?: string }
|
||||
options?: { baseUrl?: string; apiProtocol?: ProviderAccount['apiProtocol'] }
|
||||
) => Promise<{ valid: boolean; error?: string }>;
|
||||
devModeUnlocked: boolean;
|
||||
}
|
||||
@@ -1182,7 +1198,7 @@ function AddProviderDialog({
|
||||
<Label htmlFor="baseUrl" className={labelClasses}>{t('aiProviders.dialog.baseUrl')}</Label>
|
||||
<Input
|
||||
id="baseUrl"
|
||||
placeholder={apiProtocol === 'anthropic-messages' ? "https://api.example.com/anthropic" : "https://api.example.com/v1"}
|
||||
placeholder={getProtocolBaseUrlPlaceholder(apiProtocol)}
|
||||
value={baseUrl}
|
||||
onChange={(e) => setBaseUrl(e.target.value)}
|
||||
className={inputClasses}
|
||||
@@ -1206,20 +1222,27 @@ function AddProviderDialog({
|
||||
</div>
|
||||
)}
|
||||
{selectedType === 'custom' && (
|
||||
<div className="space-y-2.5">
|
||||
<Label className={labelClasses}>{t('aiProviders.dialog.protocol', 'Protocol')}</Label>
|
||||
<div className="flex gap-2 text-[13px]">
|
||||
<button
|
||||
type="button"
|
||||
<div className="space-y-2.5">
|
||||
<Label className={labelClasses}>{t('aiProviders.dialog.protocol', 'Protocol')}</Label>
|
||||
<div className="flex gap-2 text-[13px]">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setApiProtocol('openai-completions')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'openai-completions' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.openai', 'OpenAI')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setApiProtocol('anthropic-messages')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'anthropic-messages' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.openaiCompletions', 'OpenAI Completions')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setApiProtocol('openai-responses')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'openai-responses' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.openaiResponses', 'OpenAI Responses')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setApiProtocol('anthropic-messages')}
|
||||
className={cn("flex-1 py-1.5 px-3 rounded-lg border transition-colors", apiProtocol === 'anthropic-messages' ? "bg-white dark:bg-card border-black/20 dark:border-white/20 shadow-sm font-medium" : "border-transparent bg-black/5 dark:bg-white/5 text-muted-foreground hover:bg-black/10 dark:hover:bg-white/10")}
|
||||
>
|
||||
{t('aiProviders.protocols.anthropic', 'Anthropic')}
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user