fix(opencode): pass project path to provider management
This commit is contained in:
parent
351ae4f4ed
commit
2eba377be2
8 changed files with 166 additions and 64 deletions
|
|
@ -150,22 +150,26 @@ export interface RuntimeProviderManagementModelTestResponse {
|
|||
|
||||
export interface RuntimeProviderManagementLoadViewInput {
|
||||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
projectPath?: string | null;
|
||||
}
|
||||
|
||||
export interface RuntimeProviderManagementConnectApiKeyInput {
|
||||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
providerId: string;
|
||||
apiKey: string;
|
||||
projectPath?: string | null;
|
||||
}
|
||||
|
||||
export interface RuntimeProviderManagementForgetInput {
|
||||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
providerId: string;
|
||||
projectPath?: string | null;
|
||||
}
|
||||
|
||||
export interface RuntimeProviderManagementLoadModelsInput {
|
||||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
providerId: string;
|
||||
projectPath?: string | null;
|
||||
query?: string | null;
|
||||
limit?: number | null;
|
||||
}
|
||||
|
|
@ -174,6 +178,7 @@ export interface RuntimeProviderManagementTestModelInput {
|
|||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
providerId: string;
|
||||
modelId: string;
|
||||
projectPath?: string | null;
|
||||
}
|
||||
|
||||
export interface RuntimeProviderManagementSetDefaultModelInput {
|
||||
|
|
@ -181,4 +186,5 @@ export interface RuntimeProviderManagementSetDefaultModelInput {
|
|||
providerId: string;
|
||||
modelId: string;
|
||||
probe?: boolean;
|
||||
projectPath?: string | null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,6 +107,22 @@ function normalizeCommandFailure(error: unknown): string {
|
|||
return 'Runtime provider management command failed';
|
||||
}
|
||||
|
||||
function normalizeProjectPath(projectPath: string | null | undefined): string | null {
|
||||
const normalized = projectPath?.trim();
|
||||
return normalized ? normalized : null;
|
||||
}
|
||||
|
||||
function appendProjectPathArgs(args: string[], projectPath: string | null): string[] {
|
||||
return projectPath ? [...args, '--project-path', projectPath] : args;
|
||||
}
|
||||
|
||||
function runtimeProviderCommandOptions<T extends { env: NodeJS.ProcessEnv }>(
|
||||
options: T,
|
||||
projectPath: string | null
|
||||
): T & { cwd?: string } {
|
||||
return projectPath ? { ...options, cwd: projectPath } : options;
|
||||
}
|
||||
|
||||
async function resolveCliEnv(): Promise<{
|
||||
binaryPath: string | null;
|
||||
env: NodeJS.ProcessEnv;
|
||||
|
|
@ -194,11 +210,15 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
try {
|
||||
const { stdout } = await execCli(
|
||||
binaryPath,
|
||||
['runtime', 'providers', 'view', '--runtime', input.runtimeId, '--json', '--compact'],
|
||||
{ env, timeout: COMMAND_TIMEOUT_MS }
|
||||
appendProjectPathArgs(
|
||||
['runtime', 'providers', 'view', '--runtime', input.runtimeId, '--json', '--compact'],
|
||||
projectPath
|
||||
),
|
||||
runtimeProviderCommandOptions({ env, timeout: COMMAND_TIMEOUT_MS }, projectPath)
|
||||
);
|
||||
return extractJsonObject<RuntimeProviderManagementViewResponse>(stdout);
|
||||
} catch (error) {
|
||||
|
|
@ -225,24 +245,31 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
try {
|
||||
const child = spawnCli(
|
||||
binaryPath,
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'connect-api-key',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--stdin-key',
|
||||
'--json',
|
||||
],
|
||||
{
|
||||
env,
|
||||
stdio: 'pipe',
|
||||
}
|
||||
appendProjectPathArgs(
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'connect-api-key',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--stdin-key',
|
||||
'--json',
|
||||
],
|
||||
projectPath
|
||||
),
|
||||
runtimeProviderCommandOptions(
|
||||
{
|
||||
env,
|
||||
stdio: 'pipe' as const,
|
||||
},
|
||||
projectPath
|
||||
)
|
||||
) as ChildProcessWithoutNullStreams;
|
||||
const result = await collectSpawnOutput(child, input.apiKey);
|
||||
if (result.code === 0) {
|
||||
|
|
@ -281,20 +308,24 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
try {
|
||||
const { stdout } = await execCli(
|
||||
binaryPath,
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'forget',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--json',
|
||||
],
|
||||
{ env, timeout: COMMAND_TIMEOUT_MS }
|
||||
appendProjectPathArgs(
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'forget',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--json',
|
||||
],
|
||||
projectPath
|
||||
),
|
||||
runtimeProviderCommandOptions({ env, timeout: COMMAND_TIMEOUT_MS }, projectPath)
|
||||
);
|
||||
return extractJsonObject<RuntimeProviderManagementProviderResponse>(stdout);
|
||||
} catch (error) {
|
||||
|
|
@ -317,7 +348,8 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const args = [
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
let args = [
|
||||
'runtime',
|
||||
'providers',
|
||||
'models',
|
||||
|
|
@ -333,10 +365,11 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
if (typeof input.limit === 'number' && Number.isFinite(input.limit) && input.limit > 0) {
|
||||
args.push('--limit', String(Math.floor(input.limit)));
|
||||
}
|
||||
args = appendProjectPathArgs(args, projectPath);
|
||||
|
||||
try {
|
||||
const { stdout } = await execCli(binaryPath, args, {
|
||||
env,
|
||||
...runtimeProviderCommandOptions({ env }, projectPath),
|
||||
timeout: COMMAND_TIMEOUT_MS,
|
||||
});
|
||||
return extractJsonObject<RuntimeProviderManagementModelsResponse>(stdout);
|
||||
|
|
@ -364,22 +397,26 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
try {
|
||||
const { stdout } = await execCli(
|
||||
binaryPath,
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'test-model',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--model',
|
||||
input.modelId,
|
||||
'--json',
|
||||
],
|
||||
{ env, timeout: PROBE_COMMAND_TIMEOUT_MS }
|
||||
appendProjectPathArgs(
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'test-model',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--model',
|
||||
input.modelId,
|
||||
'--json',
|
||||
],
|
||||
projectPath
|
||||
),
|
||||
runtimeProviderCommandOptions({ env, timeout: PROBE_COMMAND_TIMEOUT_MS }, projectPath)
|
||||
);
|
||||
return extractJsonObject<RuntimeProviderManagementModelTestResponse>(stdout);
|
||||
} catch (error) {
|
||||
|
|
@ -408,24 +445,28 @@ export class AgentTeamsRuntimeProviderManagementCliClient implements RuntimeProv
|
|||
);
|
||||
}
|
||||
|
||||
const projectPath = normalizeProjectPath(input.projectPath);
|
||||
try {
|
||||
const { stdout } = await execCli(
|
||||
binaryPath,
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'set-default',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--model',
|
||||
input.modelId,
|
||||
'--probe',
|
||||
'--compact',
|
||||
'--json',
|
||||
],
|
||||
{ env, timeout: PROBE_COMMAND_TIMEOUT_MS }
|
||||
appendProjectPathArgs(
|
||||
[
|
||||
'runtime',
|
||||
'providers',
|
||||
'set-default',
|
||||
'--runtime',
|
||||
input.runtimeId,
|
||||
'--provider',
|
||||
input.providerId,
|
||||
'--model',
|
||||
input.modelId,
|
||||
'--probe',
|
||||
'--compact',
|
||||
'--json',
|
||||
],
|
||||
projectPath
|
||||
),
|
||||
runtimeProviderCommandOptions({ env, timeout: PROBE_COMMAND_TIMEOUT_MS }, projectPath)
|
||||
);
|
||||
return extractJsonObject<RuntimeProviderManagementViewResponse>(stdout);
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import type { JSX } from 'react';
|
|||
interface RuntimeProviderManagementPanelProps {
|
||||
readonly runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
readonly open: boolean;
|
||||
readonly projectPath?: string | null;
|
||||
readonly disabled?: boolean;
|
||||
readonly onProviderChanged?: () => Promise<void> | void;
|
||||
}
|
||||
|
|
@ -14,14 +15,23 @@ interface RuntimeProviderManagementPanelProps {
|
|||
export function RuntimeProviderManagementPanel({
|
||||
runtimeId,
|
||||
open,
|
||||
projectPath = null,
|
||||
disabled = false,
|
||||
onProviderChanged,
|
||||
}: RuntimeProviderManagementPanelProps): JSX.Element {
|
||||
const [state, actions] = useRuntimeProviderManagement({
|
||||
runtimeId,
|
||||
enabled: open,
|
||||
projectPath,
|
||||
onProviderChanged,
|
||||
});
|
||||
|
||||
return <RuntimeProviderManagementPanelView state={state} actions={actions} disabled={disabled} />;
|
||||
return (
|
||||
<RuntimeProviderManagementPanelView
|
||||
state={state}
|
||||
actions={actions}
|
||||
disabled={disabled}
|
||||
projectPath={projectPath}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import type {
|
|||
interface UseRuntimeProviderManagementOptions {
|
||||
runtimeId: RuntimeProviderManagementRuntimeId;
|
||||
enabled: boolean;
|
||||
projectPath?: string | null;
|
||||
onProviderChanged?: () => Promise<void> | void;
|
||||
}
|
||||
|
||||
|
|
@ -175,6 +176,7 @@ export function useRuntimeProviderManagement(
|
|||
try {
|
||||
const response = await api.runtimeProviderManagement.loadView({
|
||||
runtimeId: options.runtimeId,
|
||||
projectPath: options.projectPath ?? null,
|
||||
});
|
||||
if (response.error) {
|
||||
setView(null);
|
||||
|
|
@ -195,7 +197,7 @@ export function useRuntimeProviderManagement(
|
|||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [options.enabled, options.runtimeId]);
|
||||
}, [options.enabled, options.projectPath, options.runtimeId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!options.enabled) {
|
||||
|
|
@ -226,6 +228,7 @@ export function useRuntimeProviderManagement(
|
|||
api.runtimeProviderManagement.loadModels({
|
||||
runtimeId: options.runtimeId,
|
||||
providerId: modelPickerProviderId,
|
||||
projectPath: options.projectPath ?? null,
|
||||
query: modelQuery.trim() || null,
|
||||
limit: 250,
|
||||
}),
|
||||
|
|
@ -268,7 +271,7 @@ export function useRuntimeProviderManagement(
|
|||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [modelPickerProviderId, modelQuery, options.enabled, options.runtimeId]);
|
||||
}, [modelPickerProviderId, modelQuery, options.enabled, options.projectPath, options.runtimeId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!options.enabled || activeFormProviderId) {
|
||||
|
|
@ -338,6 +341,7 @@ export function useRuntimeProviderManagement(
|
|||
runtimeId: options.runtimeId,
|
||||
providerId,
|
||||
apiKey,
|
||||
projectPath: options.projectPath ?? null,
|
||||
}),
|
||||
'Provider connect timed out'
|
||||
);
|
||||
|
|
@ -381,6 +385,7 @@ export function useRuntimeProviderManagement(
|
|||
api.runtimeProviderManagement.forgetCredential({
|
||||
runtimeId: options.runtimeId,
|
||||
providerId,
|
||||
projectPath: options.projectPath ?? null,
|
||||
}),
|
||||
'Provider forget timed out'
|
||||
);
|
||||
|
|
@ -456,6 +461,7 @@ export function useRuntimeProviderManagement(
|
|||
runtimeId: options.runtimeId,
|
||||
providerId,
|
||||
modelId,
|
||||
projectPath: options.projectPath ?? null,
|
||||
}),
|
||||
'Model test timed out',
|
||||
100_000
|
||||
|
|
@ -486,7 +492,7 @@ export function useRuntimeProviderManagement(
|
|||
setTestingModelId(null);
|
||||
}
|
||||
},
|
||||
[options.runtimeId]
|
||||
[options.projectPath, options.runtimeId]
|
||||
);
|
||||
|
||||
const setDefaultModel = useCallback(
|
||||
|
|
@ -501,6 +507,7 @@ export function useRuntimeProviderManagement(
|
|||
providerId,
|
||||
modelId,
|
||||
probe: true,
|
||||
projectPath: options.projectPath ?? null,
|
||||
}),
|
||||
'Set default model timed out',
|
||||
100_000
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ interface RuntimeProviderManagementPanelViewProps {
|
|||
readonly state: RuntimeProviderManagementState;
|
||||
readonly actions: RuntimeProviderManagementActions;
|
||||
readonly disabled: boolean;
|
||||
readonly projectPath?: string | null;
|
||||
}
|
||||
|
||||
interface ProviderActionsProps {
|
||||
|
|
@ -97,7 +98,8 @@ function RuntimeSummary({
|
|||
state,
|
||||
onRefresh,
|
||||
disabled,
|
||||
}: Pick<RuntimeProviderManagementPanelViewProps, 'state' | 'disabled'> & {
|
||||
projectPath,
|
||||
}: Pick<RuntimeProviderManagementPanelViewProps, 'state' | 'disabled' | 'projectPath'> & {
|
||||
onRefresh: () => void;
|
||||
}): JSX.Element {
|
||||
const runtime = state.view?.runtime;
|
||||
|
|
@ -136,6 +138,15 @@ function RuntimeSummary({
|
|||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<div
|
||||
className="mt-1 truncate text-[11px]"
|
||||
style={{ color: 'var(--color-text-muted)' }}
|
||||
title={projectPath ?? undefined}
|
||||
>
|
||||
{projectPath
|
||||
? `Managing selected project profile: ${projectPath}`
|
||||
: 'Managing fallback OpenCode profile. Select a project to manage launch credentials for that project.'}
|
||||
</div>
|
||||
{state.loading ? (
|
||||
<div
|
||||
className="mt-2 flex items-center gap-2 text-xs"
|
||||
|
|
@ -784,6 +795,7 @@ export function RuntimeProviderManagementPanelView({
|
|||
state,
|
||||
actions,
|
||||
disabled,
|
||||
projectPath = null,
|
||||
}: RuntimeProviderManagementPanelViewProps): JSX.Element {
|
||||
const providerQuery = state.providerQuery.trim().toLowerCase();
|
||||
const filteredProviders = providerQuery
|
||||
|
|
@ -809,7 +821,12 @@ export function RuntimeProviderManagementPanelView({
|
|||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<RuntimeSummary state={state} disabled={disabled} onRefresh={() => void actions.refresh()} />
|
||||
<RuntimeSummary
|
||||
state={state}
|
||||
disabled={disabled}
|
||||
projectPath={projectPath}
|
||||
onRefresh={() => void actions.refresh()}
|
||||
/>
|
||||
|
||||
{state.error ? (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import { createLoadingMultimodelCliStatus } from '@renderer/store/slices/cliInst
|
|||
import { formatBytes } from '@renderer/utils/formatters';
|
||||
import { filterMainScreenCliProviders } from '@renderer/utils/geminiUiFreeze';
|
||||
import { isMultimodelRuntimeStatus } from '@renderer/utils/multimodelProviderVisibility';
|
||||
import { resolveProjectPathById } from '@renderer/utils/projectLookup';
|
||||
import { refreshCliStatusForCurrentMode } from '@renderer/utils/refreshCliStatus';
|
||||
import { getRuntimeDisplayName as getHumanRuntimeDisplayName } from '@renderer/utils/runtimeDisplayName';
|
||||
import {
|
||||
|
|
@ -1013,6 +1014,9 @@ const InstalledBanner = ({
|
|||
export const CliStatusBanner = (): React.JSX.Element | null => {
|
||||
const isElectron = useMemo(() => isElectronMode(), []);
|
||||
const appConfig = useStore((s) => s.appConfig);
|
||||
const selectedProjectId = useStore((s) => s.selectedProjectId);
|
||||
const projects = useStore((s) => s.projects);
|
||||
const repositoryGroups = useStore((s) => s.repositoryGroups);
|
||||
const updateConfig = useStore((s) => s.updateConfig);
|
||||
const {
|
||||
cliStatus,
|
||||
|
|
@ -1048,6 +1052,10 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
loadDashboardCliStatusBannerCollapsed()
|
||||
);
|
||||
const multimodelEnabled = appConfig?.general?.multimodelEnabled ?? true;
|
||||
const selectedProjectPath = useMemo(
|
||||
() => resolveProjectPathById(selectedProjectId, projects, repositoryGroups)?.path ?? null,
|
||||
[projects, repositoryGroups, selectedProjectId]
|
||||
);
|
||||
const loadingCliStatus = useMemo(
|
||||
() =>
|
||||
!cliStatus && cliStatusLoading && multimodelEnabled
|
||||
|
|
@ -1289,6 +1297,7 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
open={manageDialogOpen}
|
||||
onOpenChange={setManageDialogOpen}
|
||||
providers={visibleCliProviders}
|
||||
projectPath={selectedProjectPath}
|
||||
initialProviderId={
|
||||
visibleCliProviders.some((provider) => provider.providerId === manageProviderId)
|
||||
? manageProviderId
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ interface Props {
|
|||
readonly onOpenChange: (open: boolean) => void;
|
||||
readonly providers: CliProviderStatus[];
|
||||
readonly initialProviderId: CliProviderId;
|
||||
readonly projectPath?: string | null;
|
||||
readonly providerStatusLoading?: Partial<Record<CliProviderId, boolean>>;
|
||||
readonly disabled?: boolean;
|
||||
readonly onSelectBackend: (providerId: CliProviderId, backendId: string) => Promise<void> | void;
|
||||
|
|
@ -543,6 +544,7 @@ export const ProviderRuntimeSettingsDialog = ({
|
|||
onOpenChange,
|
||||
providers,
|
||||
initialProviderId,
|
||||
projectPath = null,
|
||||
providerStatusLoading = {},
|
||||
disabled = false,
|
||||
onSelectBackend,
|
||||
|
|
@ -1168,6 +1170,7 @@ export const ProviderRuntimeSettingsDialog = ({
|
|||
<RuntimeProviderManagementPanel
|
||||
runtimeId="opencode"
|
||||
open={open}
|
||||
projectPath={projectPath}
|
||||
disabled={disabled || selectedProviderLoading}
|
||||
onProviderChanged={() => onRefreshProvider?.('opencode')}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import { useCliInstaller } from '@renderer/hooks/useCliInstaller';
|
|||
import { useStore } from '@renderer/store';
|
||||
import { createLoadingMultimodelCliStatus } from '@renderer/store/slices/cliInstallerSlice';
|
||||
import { formatBytes } from '@renderer/utils/formatters';
|
||||
import { resolveProjectPathById } from '@renderer/utils/projectLookup';
|
||||
import { refreshCliStatusForCurrentMode } from '@renderer/utils/refreshCliStatus';
|
||||
import { getRuntimeDisplayName } from '@renderer/utils/runtimeDisplayName';
|
||||
import {
|
||||
|
|
@ -185,6 +186,9 @@ function getProviderTerminalLogoutCommand(provider: CliProviderStatus): {
|
|||
export const CliStatusSection = (): React.JSX.Element | null => {
|
||||
const isElectron = useMemo(() => isElectronMode(), []);
|
||||
const appConfig = useStore((s) => s.appConfig);
|
||||
const selectedProjectId = useStore((s) => s.selectedProjectId);
|
||||
const projects = useStore((s) => s.projects);
|
||||
const repositoryGroups = useStore((s) => s.repositoryGroups);
|
||||
const openExtensionsTab = useStore((s) => s.openExtensionsTab);
|
||||
const updateConfig = useStore((s) => s.updateConfig);
|
||||
const {
|
||||
|
|
@ -211,6 +215,10 @@ export const CliStatusSection = (): React.JSX.Element | null => {
|
|||
const [manageProviderId, setManageProviderId] = useState<CliProviderId>('gemini');
|
||||
const [manageDialogOpen, setManageDialogOpen] = useState(false);
|
||||
const multimodelEnabled = appConfig?.general?.multimodelEnabled ?? true;
|
||||
const selectedProjectPath = useMemo(
|
||||
() => resolveProjectPathById(selectedProjectId, projects, repositoryGroups)?.path ?? null,
|
||||
[projects, repositoryGroups, selectedProjectId]
|
||||
);
|
||||
const loadingCliStatus =
|
||||
!cliStatus && cliStatusLoading && multimodelEnabled
|
||||
? createLoadingMultimodelCliStatus()
|
||||
|
|
@ -645,6 +653,7 @@ export const CliStatusSection = (): React.JSX.Element | null => {
|
|||
open={manageDialogOpen}
|
||||
onOpenChange={setManageDialogOpen}
|
||||
providers={effectiveCliStatus.providers}
|
||||
projectPath={selectedProjectPath}
|
||||
initialProviderId={manageProviderId}
|
||||
providerStatusLoading={cliProviderStatusLoading}
|
||||
disabled={!effectiveCliStatus.binaryPath || isBusy || cliStatusLoading}
|
||||
|
|
|
|||
Loading…
Reference in a new issue