feat(runtime-provider-management): expose provider directory search
This commit is contained in:
parent
7fb5c8cf85
commit
a8e876ada5
1 changed files with 72 additions and 21 deletions
|
|
@ -1100,6 +1100,8 @@ export function RuntimeProviderManagementPanelView({
|
||||||
)
|
)
|
||||||
? state.selectedProviderId
|
? state.selectedProviderId
|
||||||
: (filteredProviders[0]?.providerId ?? state.selectedProviderId ?? null);
|
: (filteredProviders[0]?.providerId ?? state.selectedProviderId ?? null);
|
||||||
|
const canSearchDirectory =
|
||||||
|
state.directorySupported && providerQuery.length >= 2 && filteredProviders.length === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
|
|
@ -1138,7 +1140,32 @@ export function RuntimeProviderManagementPanelView({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{state.providers.length > 0 ? (
|
{state.directoryOpen ? (
|
||||||
|
<ProviderDirectoryPanel state={state} actions={actions} disabled={disabled} />
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{!state.directoryOpen && state.directorySupported ? (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="w-full rounded-lg border px-3 py-2.5 text-left transition-colors hover:border-sky-300/55 hover:bg-sky-400/[0.07]"
|
||||||
|
style={{
|
||||||
|
borderColor: 'var(--color-border-subtle)',
|
||||||
|
color: 'var(--color-text-secondary)',
|
||||||
|
}}
|
||||||
|
onClick={actions.openDirectory}
|
||||||
|
>
|
||||||
|
<div className="text-sm font-medium text-[var(--color-text)]">
|
||||||
|
Browse all OpenCode providers
|
||||||
|
</div>
|
||||||
|
<div className="mt-0.5 text-xs">
|
||||||
|
{state.directoryTotalCount === null
|
||||||
|
? 'Load the dynamic provider catalog from OpenCode'
|
||||||
|
: `${state.directoryTotalCount} providers available from OpenCode`}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{!state.directoryOpen && state.providers.length > 0 ? (
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-[var(--color-text-muted)]" />
|
<Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-[var(--color-text-muted)]" />
|
||||||
<Input
|
<Input
|
||||||
|
|
@ -1146,6 +1173,11 @@ export function RuntimeProviderManagementPanelView({
|
||||||
value={state.providerQuery}
|
value={state.providerQuery}
|
||||||
disabled={disabled || state.loading}
|
disabled={disabled || state.loading}
|
||||||
onChange={(event) => actions.setProviderQuery(event.target.value)}
|
onChange={(event) => actions.setProviderQuery(event.target.value)}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (event.key === 'Enter' && state.providerQuery.trim().length >= 2) {
|
||||||
|
actions.searchAllProviders(state.providerQuery.trim());
|
||||||
|
}
|
||||||
|
}}
|
||||||
placeholder="Search providers"
|
placeholder="Search providers"
|
||||||
className="h-9 pr-3 text-sm"
|
className="h-9 pr-3 text-sm"
|
||||||
style={{ paddingLeft: 40 }}
|
style={{ paddingLeft: 40 }}
|
||||||
|
|
@ -1153,26 +1185,45 @@ export function RuntimeProviderManagementPanelView({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div className="max-h-[62vh] space-y-2 overflow-y-auto pr-1">
|
{!state.directoryOpen && canSearchDirectory ? (
|
||||||
{state.loading && state.providers.length === 0 ? (
|
<button
|
||||||
<RuntimeProviderLoadingPlaceholder />
|
type="button"
|
||||||
) : null}
|
className="w-full rounded-md border px-3 py-2 text-left text-sm transition-colors hover:border-sky-300/55 hover:bg-sky-400/[0.07]"
|
||||||
{filteredProviders.map((provider) => (
|
style={{
|
||||||
<ProviderRow
|
borderColor: 'var(--color-border-subtle)',
|
||||||
key={provider.providerId}
|
color: 'var(--color-text)',
|
||||||
provider={provider}
|
}}
|
||||||
state={state}
|
onClick={() => actions.searchAllProviders(state.providerQuery.trim())}
|
||||||
active={provider.providerId === selectedProviderId}
|
>
|
||||||
formOpen={state.activeFormProviderId === provider.providerId}
|
Search all OpenCode providers for "{state.providerQuery.trim()}"
|
||||||
apiKeyValue={state.apiKeyValue}
|
</button>
|
||||||
busy={state.savingProviderId === provider.providerId}
|
) : null}
|
||||||
disabled={disabled || state.loading}
|
|
||||||
actions={actions}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!state.loading && state.providers.length > 0 && filteredProviders.length === 0 ? (
|
{!state.directoryOpen ? (
|
||||||
|
<div className="max-h-[62vh] space-y-2 overflow-y-auto pr-1">
|
||||||
|
{state.loading && state.providers.length === 0 ? (
|
||||||
|
<RuntimeProviderLoadingPlaceholder />
|
||||||
|
) : null}
|
||||||
|
{filteredProviders.map((provider) => (
|
||||||
|
<ProviderRow
|
||||||
|
key={provider.providerId}
|
||||||
|
provider={provider}
|
||||||
|
state={state}
|
||||||
|
active={provider.providerId === selectedProviderId}
|
||||||
|
formOpen={state.activeFormProviderId === provider.providerId}
|
||||||
|
apiKeyValue={state.apiKeyValue}
|
||||||
|
busy={state.savingProviderId === provider.providerId}
|
||||||
|
disabled={disabled || state.loading}
|
||||||
|
actions={actions}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{!state.directoryOpen &&
|
||||||
|
!state.loading &&
|
||||||
|
state.providers.length > 0 &&
|
||||||
|
filteredProviders.length === 0 ? (
|
||||||
<div
|
<div
|
||||||
className="rounded-lg border p-3 text-sm"
|
className="rounded-lg border p-3 text-sm"
|
||||||
style={{
|
style={{
|
||||||
|
|
@ -1184,7 +1235,7 @@ export function RuntimeProviderManagementPanelView({
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!state.loading && state.providers.length === 0 ? (
|
{!state.directoryOpen && !state.loading && state.providers.length === 0 ? (
|
||||||
<div
|
<div
|
||||||
className="rounded-lg border p-3 text-sm"
|
className="rounded-lg border p-3 text-sm"
|
||||||
style={{
|
style={{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue