feat(runtime-provider-management): show directory provider models

This commit is contained in:
777genius 2026-04-25 19:24:45 +03:00
parent a8e876ada5
commit 4b77c648bf
2 changed files with 68 additions and 15 deletions

View file

@ -505,6 +505,11 @@ export function useRuntimeProviderManagement(
setDirectoryNextCursor(null); setDirectoryNextCursor(null);
}, []); }, []);
const updateDirectoryQuery = useCallback((value: string): void => {
setDirectoryQuery(value);
setDirectoryNextCursor(null);
}, []);
const loadMoreDirectory = useCallback(async (): Promise<void> => { const loadMoreDirectory = useCallback(async (): Promise<void> => {
if (!directoryNextCursor || directoryLoading || directoryRefreshing) { if (!directoryNextCursor || directoryLoading || directoryRefreshing) {
return; return;
@ -882,7 +887,7 @@ export function useRuntimeProviderManagement(
setProviderQuery, setProviderQuery,
openDirectory, openDirectory,
closeDirectory, closeDirectory,
setDirectoryQuery, setDirectoryQuery: updateDirectoryQuery,
setDirectoryFilter, setDirectoryFilter,
loadMoreDirectory, loadMoreDirectory,
refreshDirectory, refreshDirectory,
@ -919,6 +924,7 @@ export function useRuntimeProviderManagement(
startConnect, startConnect,
submitConnect, submitConnect,
testModel, testModel,
updateDirectoryQuery,
useModelForNewTeams, useModelForNewTeams,
] ]
); );

View file

@ -113,6 +113,23 @@ function getDirectoryModelsLabel(provider: RuntimeProviderDirectoryEntryDto): st
return `${provider.modelCount} model${provider.modelCount === 1 ? '' : 's'}`; return `${provider.modelCount} model${provider.modelCount === 1 ? '' : 's'}`;
} }
function directoryEntryToProviderConnection(
provider: RuntimeProviderDirectoryEntryDto
): RuntimeProviderConnectionDto {
return {
providerId: provider.providerId,
displayName: provider.displayName,
state: provider.state,
ownership: provider.ownership,
recommended: provider.recommended,
modelCount: provider.modelCount ?? 1,
defaultModelId: provider.defaultModelId,
authMethods: provider.authMethods,
actions: provider.actions,
detail: provider.detail,
};
}
function stateClassName(provider: RuntimeProviderConnectionDto): string { function stateClassName(provider: RuntimeProviderConnectionDto): string {
switch (provider.state) { switch (provider.state) {
case 'connected': case 'connected':
@ -727,10 +744,26 @@ function ProviderDirectoryPanel({
<ArrowLeft className="mr-1 size-3.5" /> <ArrowLeft className="mr-1 size-3.5" />
Providers Providers
</Button> </Button>
<div className="text-xs text-[var(--color-text-muted)]"> <div className="flex items-center gap-2">
{state.directoryTotalCount === null <div className="text-xs text-[var(--color-text-muted)]">
? 'All OpenCode providers' {state.directoryTotalCount === null
: `${state.directoryTotalCount} OpenCode providers`} ? 'All OpenCode providers'
: `${state.directoryTotalCount} OpenCode providers`}
</div>
<Button
type="button"
size="sm"
variant="ghost"
disabled={disabled || state.directoryLoading || state.directoryRefreshing}
onClick={() => void actions.refreshDirectory()}
>
{state.directoryRefreshing ? (
<Loader2 className="mr-1 size-3.5 animate-spin" />
) : (
<RefreshCcw className="mr-1 size-3.5" />
)}
Refresh
</Button>
</div> </div>
</div> </div>
@ -774,16 +807,30 @@ function ProviderDirectoryPanel({
{state.directoryLoading && state.directoryEntries.length === 0 ? ( {state.directoryLoading && state.directoryEntries.length === 0 ? (
<RuntimeProviderLoadingPlaceholder /> <RuntimeProviderLoadingPlaceholder />
) : null} ) : null}
{state.directoryEntries.map((provider) => ( {state.directoryEntries.map((provider) => {
<DirectoryProviderRow const active = state.directorySelectedProviderId === provider.providerId;
key={provider.providerId} return (
provider={provider} <div key={provider.providerId}>
active={state.directorySelectedProviderId === provider.providerId} <DirectoryProviderRow
disabled={disabled || state.directoryLoading} provider={provider}
busy={state.savingProviderId === provider.providerId} active={active}
actions={actions} disabled={disabled || state.directoryLoading}
/> busy={state.savingProviderId === provider.providerId}
))} actions={actions}
/>
{active && provider.state === 'connected' && provider.modelCount !== 0 ? (
<div className="ml-3 border-l border-sky-300/25 pl-3">
<ProviderModelList
state={state}
actions={actions}
provider={directoryEntryToProviderConnection(provider)}
disabled={disabled || state.directoryLoading}
/>
</div>
) : null}
</div>
);
})}
</div> </div>
{!state.directoryLoading && state.directoryEntries.length === 0 && !state.directoryError ? ( {!state.directoryLoading && state.directoryEntries.length === 0 && !state.directoryError ? (