From d596562ce21b7cef2352b625e62105ee53a0fb3f Mon Sep 17 00:00:00 2001 From: Wes Date: Sat, 18 Jul 2026 12:22:58 -0600 Subject: [PATCH 1/2] fix(desktop): show provider API key field in onboarding defaults Follow-up to #2079, which restored the provider dropdown in the onboarding default-config step. Selecting a credential-backed provider (Anthropic/OpenAI) still gave no way to enter the API key: the field was gated behind showAdvancedFields, which onboarding sets to false. Show the API key field whenever the provider field is visible and the selected provider requires a secret, and remove the now-unused hideUnconfiguredCredentialProviders machinery left behind by #2079. Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes --- .../agents/ui/GlobalAgentConfigFields.tsx | 31 ++----------------- .../e2e/onboarding-agent-defaults.spec.ts | 2 +- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/desktop/src/features/agents/ui/GlobalAgentConfigFields.tsx b/desktop/src/features/agents/ui/GlobalAgentConfigFields.tsx index 7020070103..95b1a182c9 100644 --- a/desktop/src/features/agents/ui/GlobalAgentConfigFields.tsx +++ b/desktop/src/features/agents/ui/GlobalAgentConfigFields.tsx @@ -24,7 +24,6 @@ import { AUTO_PROVIDER_DROPDOWN_VALUE, BLOCK_BUILD_HIDDEN_PROVIDER_IDS, CUSTOM_PROVIDER_DROPDOWN_VALUE, - PERSONA_LLM_PROVIDER_OPTIONS, getPersonaProviderOptions, getProviderApiKeyEnvVar, requiredCredentialEnvKeys, @@ -76,7 +75,6 @@ export type GlobalAgentConfigFieldsProps = { disableModelSelectDuringDiscovery?: boolean; effortPlaceholderLabel?: string; effortLabel?: string; - hideUnconfiguredCredentialProviders?: boolean; keepSelectedModelValueLabel?: boolean; modelPlaceholderLabel?: string; placeholderClassName?: string; @@ -112,7 +110,6 @@ export function GlobalAgentConfigFields({ disableModelSelectDuringDiscovery = true, effortPlaceholderLabel, effortLabel = "Thinking/effort", - hideUnconfiguredCredentialProviders = false, keepSelectedModelValueLabel = false, modelPlaceholderLabel = "Select model", placeholderClassName, @@ -191,13 +188,6 @@ export function GlobalAgentConfigFields({ () => bakedEnv.map((entry) => entry.key), [bakedEnv], ); - const configuredCredentialKeys = React.useMemo(() => { - const keys = new Set(bakedEnvKeys); - for (const [key, value] of Object.entries(config.env_vars)) { - if (value.trim().length > 0) keys.add(key); - } - return keys; - }, [bakedEnvKeys, config.env_vars]); const apiKeyInherited = apiKeyEnvVar !== null && apiKeyValue.length === 0 && @@ -355,28 +345,11 @@ export function GlobalAgentConfigFields({ hidden.add(providerId); } } - if (hideUnconfiguredCredentialProviders) { - for (const option of PERSONA_LLM_PROVIDER_OPTIONS) { - const requiredKeys = requiredCredentialEnvKeys( - credentialRuntimeId, - option.id, - ); - if (requiredKeys.some((key) => !configuredCredentialKeys.has(key))) { - hidden.add(option.id); - } - } - } if (selectedRuntimeId !== "buzz-agent") { hidden.add("relay-mesh"); } return hidden; - }, [ - bakedEnvKeys, - configuredCredentialKeys, - credentialRuntimeId, - hideUnconfiguredCredentialProviders, - selectedRuntimeId, - ]); + }, [bakedEnvKeys, selectedRuntimeId]); const providerOptions = getPersonaProviderOptions( providerValue, credentialRuntimeId, @@ -510,7 +483,7 @@ export function GlobalAgentConfigFields({ ) : null} - {showAdvancedFields && providerFieldVisible && apiKeyEnvVar ? ( + {providerFieldVisible && apiKeyEnvVar ? (
Date: Sat, 18 Jul 2026 12:33:57 -0600 Subject: [PATCH 2/2] feat(desktop): add search to the onboarding model dropdown The onboarding model list can run long (Databricks discovery returns dozens of models) and the custom dropdown from #2039 dropped the typeahead search the persona dialog combobox already has. Add an inline filter input to AgentDropdownSelect, enabled for the model field, matching the persona combobox behavior. Co-authored-by: Brain <21994759fc7a6fa6b965551d35cfd7897d262f2495467f2d78694ddcfa6a5c7e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: Wes --- .../agents/ui/personaProviderModelFields.tsx | 47 +++++++++++++++++-- .../e2e/onboarding-agent-defaults.spec.ts | 43 +++++++++++++++++ 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/desktop/src/features/agents/ui/personaProviderModelFields.tsx b/desktop/src/features/agents/ui/personaProviderModelFields.tsx index 83b5a33d6a..325deb3fc1 100644 --- a/desktop/src/features/agents/ui/personaProviderModelFields.tsx +++ b/desktop/src/features/agents/ui/personaProviderModelFields.tsx @@ -5,7 +5,7 @@ * instead of duplicating the picker logic. */ import * as React from "react"; -import { Check, ChevronDown } from "lucide-react"; +import { Check, ChevronDown, Search } from "lucide-react"; import type { AcpRuntimeCatalogEntry } from "@/shared/api/types"; import { cn } from "@/shared/lib/cn"; @@ -47,6 +47,7 @@ export function AgentDropdownSelect({ placeholder = "Select", placeholderClassName, placeholderValue, + searchable = false, selectedLabel, testId, value, @@ -60,11 +61,14 @@ export function AgentDropdownSelect({ placeholder?: string; placeholderClassName?: string; placeholderValue?: string; + /** Show a filter input above the options when the list is long. */ + searchable?: boolean; selectedLabel?: React.ReactNode; testId?: string; value: string; }) { const [open, setOpen] = React.useState(false); + const [query, setQuery] = React.useState(""); const selectedOption = options.find((option) => option.value === value); const isPlaceholderSelection = selectedLabel === undefined && @@ -72,8 +76,24 @@ export function AgentDropdownSelect({ (placeholderValue !== undefined && selectedOption.value === placeholderValue)); + const showSearch = searchable && options.length > 1; + const filteredOptions = React.useMemo(() => { + const trimmed = query.trim().toLowerCase(); + if (!showSearch || trimmed === "") return options; + return options.filter((option) => + (typeof option.label === "string" ? option.label : option.value) + .toLowerCase() + .includes(trimmed), + ); + }, [options, query, showSearch]); + + function handleOpenChange(next: boolean) { + setOpen(next); + if (!next) setQuery(""); + } + return ( - +