custom provider form minor improvements (#6966)

This commit is contained in:
Zane
2026-02-04 16:03:44 -08:00
committed by GitHub
parent 950f1412ab
commit 5fc21ce094
3 changed files with 34 additions and 28 deletions
@@ -83,7 +83,11 @@ export const SwitchModelModal = ({
const [provider, setProvider] = useState<string | null>( const [provider, setProvider] = useState<string | null>(
initialProvider || currentProvider || null initialProvider || currentProvider || null
); );
const [model, setModel] = useState<string>(currentModel || ''); // Only use currentModel if we're not switching to a different provider
// Otherwise, let the auto-select logic pick an appropriate model for the new provider
const [model, setModel] = useState<string>(
initialProvider && initialProvider !== currentProvider ? '' : currentModel || ''
);
const [isCustomModel, setIsCustomModel] = useState(false); const [isCustomModel, setIsCustomModel] = useState(false);
const [validationErrors, setValidationErrors] = useState({ const [validationErrors, setValidationErrors] = useState({
provider: '', provider: '',
@@ -204,6 +204,7 @@ function ProviderCards({
api_key: '', api_key: '',
models: editingProvider.config.models.map((m) => m.name), models: editingProvider.config.models.map((m) => m.name),
supports_streaming: editingProvider.config.supports_streaming ?? true, supports_streaming: editingProvider.config.supports_streaming ?? true,
requires_auth: editingProvider.config.requires_auth ?? true,
}; };
const editable = editingProvider ? editingProvider.isEditable : true; const editable = editingProvider ? editingProvider.isEditable : true;
@@ -3,7 +3,6 @@ import { Input } from '../../../../../ui/input';
import { Select } from '../../../../../ui/Select'; import { Select } from '../../../../../ui/Select';
import { Button } from '../../../../../ui/button'; import { Button } from '../../../../../ui/button';
import { SecureStorageNotice } from '../SecureStorageNotice'; import { SecureStorageNotice } from '../SecureStorageNotice';
import { Checkbox } from '@radix-ui/themes';
import { UpdateCustomProviderRequest } from '../../../../../../api'; import { UpdateCustomProviderRequest } from '../../../../../../api';
interface CustomProviderFormProps { interface CustomProviderFormProps {
@@ -24,7 +23,7 @@ export default function CustomProviderForm({
const [apiUrl, setApiUrl] = useState(''); const [apiUrl, setApiUrl] = useState('');
const [apiKey, setApiKey] = useState(''); const [apiKey, setApiKey] = useState('');
const [models, setModels] = useState(''); const [models, setModels] = useState('');
const [noAuthRequired, setNoAuthRequired] = useState(false); const [requiresApiKey, setRequiresApiKey] = useState(false);
const [supportsStreaming, setSupportsStreaming] = useState(true); const [supportsStreaming, setSupportsStreaming] = useState(true);
const [validationErrors, setValidationErrors] = useState<Record<string, string>>({}); const [validationErrors, setValidationErrors] = useState<Record<string, string>>({});
@@ -40,13 +39,13 @@ export default function CustomProviderForm({
setApiUrl(initialData.api_url); setApiUrl(initialData.api_url);
setModels(initialData.models.join(', ')); setModels(initialData.models.join(', '));
setSupportsStreaming(initialData.supports_streaming ?? true); setSupportsStreaming(initialData.supports_streaming ?? true);
setNoAuthRequired(!(initialData.requires_auth ?? true)); setRequiresApiKey(initialData.requires_auth ?? true);
} }
}, [initialData]); }, [initialData]);
const handleNoAuthChange = (checked: boolean) => { const handleRequiresApiKeyChange = (checked: boolean) => {
setNoAuthRequired(!!checked); setRequiresApiKey(checked);
if (checked) { if (!checked) {
setApiKey(''); setApiKey('');
} }
}; };
@@ -58,7 +57,7 @@ export default function CustomProviderForm({
if (!displayName) errors.displayName = 'Display name is required'; if (!displayName) errors.displayName = 'Display name is required';
if (!apiUrl) errors.apiUrl = 'API URL is required'; if (!apiUrl) errors.apiUrl = 'API URL is required';
const existingHadAuth = initialData && (initialData.requires_auth ?? true); const existingHadAuth = initialData && (initialData.requires_auth ?? true);
if (!noAuthRequired && !apiKey && !existingHadAuth) errors.apiKey = 'API key is required'; if (requiresApiKey && !apiKey && !existingHadAuth) errors.apiKey = 'API key is required';
if (!models) errors.models = 'At least one model is required'; if (!models) errors.models = 'At least one model is required';
if (Object.keys(errors).length > 0) { if (Object.keys(errors).length > 0) {
@@ -78,7 +77,7 @@ export default function CustomProviderForm({
api_key: apiKey, api_key: apiKey,
models: modelList, models: modelList,
supports_streaming: supportsStreaming, supports_streaming: supportsStreaming,
requires_auth: !noAuthRequired, requires_auth: requiresApiKey,
}); });
}; };
@@ -174,22 +173,25 @@ export default function CustomProviderForm({
)} )}
<div> <div>
<div className="flex items-center space-x-2 mb-2"> <label className="block text-sm font-medium text-textStandard mb-2">Authentication</label>
<Checkbox <p className="text-sm text-textSubtle mb-3">
id="no-auth-required" Local LLMs like Ollama typically don't require an API key.
checked={noAuthRequired} </p>
onCheckedChange={handleNoAuthChange} <div className="flex items-center space-x-2">
<input
type="checkbox"
id="requires-api-key"
checked={requiresApiKey}
onChange={(e) => handleRequiresApiKeyChange(e.target.checked)}
className="rounded border-borderStandard"
/> />
<label <label htmlFor="requires-api-key" className="text-sm text-textSubtle">
htmlFor="no-auth-required" This provider requires an API key
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-textSubtle"
>
No authentication required
</label> </label>
</div> </div>
{!noAuthRequired && ( {requiresApiKey && (
<> <div className="mt-3">
<label <label
htmlFor="api-key" htmlFor="api-key"
className="flex items-center text-sm font-medium text-textStandard mb-2" className="flex items-center text-sm font-medium text-textStandard mb-2"
@@ -212,7 +214,7 @@ export default function CustomProviderForm({
{validationErrors.apiKey} {validationErrors.apiKey}
</p> </p>
)} )}
</> </div>
)} )}
</div> </div>
{isEditable && ( {isEditable && (
@@ -241,15 +243,14 @@ export default function CustomProviderForm({
)} )}
</div> </div>
<div className="flex items-center space-x-2 mb-10"> <div className="flex items-center space-x-2 mb-10">
<Checkbox <input
type="checkbox"
id="supports-streaming" id="supports-streaming"
checked={supportsStreaming} checked={supportsStreaming}
onCheckedChange={(checked) => setSupportsStreaming(checked as boolean)} onChange={(e) => setSupportsStreaming(e.target.checked)}
className="rounded border-borderStandard"
/> />
<label <label htmlFor="supports-streaming" className="text-sm text-textSubtle">
htmlFor="supports-streaming"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-textSubtle"
>
Provider supports streaming responses Provider supports streaming responses
</label> </label>
</div> </div>