perf(startup): lazy load dashboard runtime surfaces
This commit is contained in:
parent
f8b96d12d3
commit
08725c4e33
2 changed files with 197 additions and 85 deletions
|
|
@ -7,7 +7,7 @@
|
|||
* Only rendered in Electron mode.
|
||||
*/
|
||||
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { lazy, Suspense, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import {
|
||||
CODEX_ACCOUNT_STARTUP_IDLE_DELAY_MS,
|
||||
|
|
@ -35,13 +35,10 @@ import {
|
|||
} from '@renderer/components/runtime/providerConnectionUi';
|
||||
import { ProviderModelBadges } from '@renderer/components/runtime/ProviderModelBadges';
|
||||
import { getProviderRuntimeBackendSummary } from '@renderer/components/runtime/ProviderRuntimeBackendSelector';
|
||||
import { ProviderRuntimeSettingsDialog } from '@renderer/components/runtime/ProviderRuntimeSettingsDialog';
|
||||
import {
|
||||
getProviderTerminalCommand,
|
||||
getProviderTerminalLogoutCommand,
|
||||
} from '@renderer/components/runtime/providerTerminalCommands';
|
||||
import { TerminalLogPanel } from '@renderer/components/terminal/TerminalLogPanel';
|
||||
import { TerminalModal } from '@renderer/components/terminal/TerminalModal';
|
||||
import { useCliInstaller } from '@renderer/hooks/useCliInstaller';
|
||||
import {
|
||||
loadDashboardCliStatusBannerCollapsed,
|
||||
|
|
@ -113,6 +110,22 @@ const ATLAS_CLOUD_CODING_PLAN_URL = 'https://www.atlascloud.ai/console/coding-pl
|
|||
const ATLAS_CLOUD_DESCRIPTION =
|
||||
"Atlas Cloud is a full-modal AI inference platform that gives developers a single AI API to access video generation, image generation, and LLM APIs. Instead of managing multiple vendor integrations, you connect once and get unified access to 300+ curated models across all modalities. Check out Atlas Cloud's new coding plan promotion for more budget-friendly API access.";
|
||||
|
||||
const ProviderRuntimeSettingsDialog = lazy(() =>
|
||||
import('@renderer/components/runtime/ProviderRuntimeSettingsDialog').then((module) => ({
|
||||
default: module.ProviderRuntimeSettingsDialog,
|
||||
}))
|
||||
);
|
||||
const TerminalLogPanel = lazy(() =>
|
||||
import('@renderer/components/terminal/TerminalLogPanel').then((module) => ({
|
||||
default: module.TerminalLogPanel,
|
||||
}))
|
||||
);
|
||||
const TerminalModal = lazy(() =>
|
||||
import('@renderer/components/terminal/TerminalModal').then((module) => ({
|
||||
default: module.TerminalModal,
|
||||
}))
|
||||
);
|
||||
|
||||
const DashboardRateLimitChips = ({
|
||||
providerId,
|
||||
items,
|
||||
|
|
@ -1655,50 +1668,58 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
const installedAuxiliaryUi =
|
||||
renderCliStatus !== null ? (
|
||||
<>
|
||||
<ProviderRuntimeSettingsDialog
|
||||
open={manageDialogOpen}
|
||||
onOpenChange={handleManageDialogOpenChange}
|
||||
providers={visibleCliProviders}
|
||||
projectPath={selectedProjectPath}
|
||||
initialProviderId={
|
||||
visibleCliProviders.some((provider) => provider.providerId === manageProviderId)
|
||||
? manageProviderId
|
||||
: (visibleCliProviders[0]?.providerId ?? 'anthropic')
|
||||
}
|
||||
initialRuntimeProviderId={manageRuntimeProviderId}
|
||||
initialRuntimeProviderAction={manageRuntimeProviderId ? 'connect' : null}
|
||||
providerStatusLoading={cliProviderStatusLoading}
|
||||
disabled={isBusy || cliStatusLoading || !renderCliStatus.binaryPath}
|
||||
codexRuntimeStatus={codexRuntimeStatus}
|
||||
codexRuntimeStatusLoading={codexRuntimeStatusLoading}
|
||||
onInstallCodexRuntime={() => installCodexRuntime()}
|
||||
onSelectBackend={handleProviderBackendChange}
|
||||
onRefreshProvider={handleProviderRefresh}
|
||||
onRequestLogin={(providerId) => setProviderTerminal({ providerId, action: 'login' })}
|
||||
/>
|
||||
{manageDialogOpen && (
|
||||
<Suspense fallback={null}>
|
||||
<ProviderRuntimeSettingsDialog
|
||||
open={manageDialogOpen}
|
||||
onOpenChange={handleManageDialogOpenChange}
|
||||
providers={visibleCliProviders}
|
||||
projectPath={selectedProjectPath}
|
||||
initialProviderId={
|
||||
visibleCliProviders.some((provider) => provider.providerId === manageProviderId)
|
||||
? manageProviderId
|
||||
: (visibleCliProviders[0]?.providerId ?? 'anthropic')
|
||||
}
|
||||
initialRuntimeProviderId={manageRuntimeProviderId}
|
||||
initialRuntimeProviderAction={manageRuntimeProviderId ? 'connect' : null}
|
||||
providerStatusLoading={cliProviderStatusLoading}
|
||||
disabled={isBusy || cliStatusLoading || !renderCliStatus.binaryPath}
|
||||
codexRuntimeStatus={codexRuntimeStatus}
|
||||
codexRuntimeStatusLoading={codexRuntimeStatusLoading}
|
||||
onInstallCodexRuntime={() => installCodexRuntime()}
|
||||
onSelectBackend={handleProviderBackendChange}
|
||||
onRefreshProvider={handleProviderRefresh}
|
||||
onRequestLogin={(providerId) => setProviderTerminal({ providerId, action: 'login' })}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
{providerTerminal && renderCliStatus.binaryPath && (
|
||||
<TerminalModal
|
||||
title={`${getHumanRuntimeDisplayName(renderCliStatus, multimodelEnabled)} ${
|
||||
providerTerminal.action === 'login' ? 'Login' : 'Logout'
|
||||
}: ${getProviderLabel(providerTerminal.providerId)}`}
|
||||
command={renderCliStatus.binaryPath}
|
||||
args={providerTerminalCommand?.args}
|
||||
env={providerTerminalCommand?.env}
|
||||
onClose={() => {
|
||||
setProviderTerminal(null);
|
||||
recheckAuthState();
|
||||
}}
|
||||
onExit={() => {
|
||||
recheckAuthState();
|
||||
}}
|
||||
autoCloseOnSuccessMs={3000}
|
||||
successMessage={
|
||||
providerTerminal.action === 'login' ? 'Authentication updated' : 'Provider logged out'
|
||||
}
|
||||
failureMessage={
|
||||
providerTerminal.action === 'login' ? 'Authentication failed' : 'Logout failed'
|
||||
}
|
||||
/>
|
||||
<Suspense fallback={null}>
|
||||
<TerminalModal
|
||||
title={`${getHumanRuntimeDisplayName(renderCliStatus, multimodelEnabled)} ${
|
||||
providerTerminal.action === 'login' ? 'Login' : 'Logout'
|
||||
}: ${getProviderLabel(providerTerminal.providerId)}`}
|
||||
command={renderCliStatus.binaryPath}
|
||||
args={providerTerminalCommand?.args}
|
||||
env={providerTerminalCommand?.env}
|
||||
onClose={() => {
|
||||
setProviderTerminal(null);
|
||||
recheckAuthState();
|
||||
}}
|
||||
onExit={() => {
|
||||
recheckAuthState();
|
||||
}}
|
||||
autoCloseOnSuccessMs={3000}
|
||||
successMessage={
|
||||
providerTerminal.action === 'login'
|
||||
? 'Authentication updated'
|
||||
: 'Provider logged out'
|
||||
}
|
||||
failureMessage={
|
||||
providerTerminal.action === 'login' ? 'Authentication failed' : 'Logout failed'
|
||||
}
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
</>
|
||||
) : null;
|
||||
|
|
@ -1877,7 +1898,9 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
Installing {runtimeDisplayName}...
|
||||
</span>
|
||||
</div>
|
||||
<TerminalLogPanel chunks={installerRawChunks} />
|
||||
<Suspense fallback={null}>
|
||||
<TerminalLogPanel chunks={installerRawChunks} />
|
||||
</Suspense>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -2250,45 +2273,47 @@ export const CliStatusBanner = (): React.JSX.Element | null => {
|
|||
</div>
|
||||
{installedAuxiliaryUi}
|
||||
{showLoginTerminal && renderCliStatus.binaryPath && (
|
||||
<TerminalModal
|
||||
title={`${getHumanRuntimeDisplayName(renderCliStatus, multimodelEnabled)} Login`}
|
||||
command={renderCliStatus.binaryPath}
|
||||
args={['auth', 'login']}
|
||||
onClose={() => {
|
||||
setShowLoginTerminal(false);
|
||||
setIsVerifyingAuth(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await invalidateCliStatus();
|
||||
if (multimodelEnabled) {
|
||||
await bootstrapCliStatus({ multimodelEnabled: true });
|
||||
} else {
|
||||
await fetchCliStatus();
|
||||
<Suspense fallback={null}>
|
||||
<TerminalModal
|
||||
title={`${getHumanRuntimeDisplayName(renderCliStatus, multimodelEnabled)} Login`}
|
||||
command={renderCliStatus.binaryPath}
|
||||
args={['auth', 'login']}
|
||||
onClose={() => {
|
||||
setShowLoginTerminal(false);
|
||||
setIsVerifyingAuth(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await invalidateCliStatus();
|
||||
if (multimodelEnabled) {
|
||||
await bootstrapCliStatus({ multimodelEnabled: true });
|
||||
} else {
|
||||
await fetchCliStatus();
|
||||
}
|
||||
} finally {
|
||||
setIsVerifyingAuth(false);
|
||||
}
|
||||
} finally {
|
||||
setIsVerifyingAuth(false);
|
||||
}
|
||||
})();
|
||||
}}
|
||||
onExit={() => {
|
||||
setIsVerifyingAuth(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await invalidateCliStatus();
|
||||
if (multimodelEnabled) {
|
||||
await bootstrapCliStatus({ multimodelEnabled: true });
|
||||
} else {
|
||||
await fetchCliStatus();
|
||||
})();
|
||||
}}
|
||||
onExit={() => {
|
||||
setIsVerifyingAuth(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await invalidateCliStatus();
|
||||
if (multimodelEnabled) {
|
||||
await bootstrapCliStatus({ multimodelEnabled: true });
|
||||
} else {
|
||||
await fetchCliStatus();
|
||||
}
|
||||
} finally {
|
||||
setIsVerifyingAuth(false);
|
||||
}
|
||||
} finally {
|
||||
setIsVerifyingAuth(false);
|
||||
}
|
||||
})();
|
||||
}}
|
||||
autoCloseOnSuccessMs={4000}
|
||||
successMessage="Login complete"
|
||||
failureMessage="Login failed"
|
||||
/>
|
||||
})();
|
||||
}}
|
||||
autoCloseOnSuccessMs={4000}
|
||||
successMessage="Login complete"
|
||||
failureMessage="Login failed"
|
||||
/>
|
||||
</Suspense>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -173,6 +173,14 @@ vi.mock('@renderer/store', () => {
|
|||
import { CliStatusBanner } from '@renderer/components/dashboard/CliStatusBanner';
|
||||
import { CliStatusSection } from '@renderer/components/settings/sections/CliStatusSection';
|
||||
|
||||
async function flushLazyImports(): Promise<void> {
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
await new Promise<void>((resolve) => {
|
||||
setTimeout(resolve, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function createInstalledCliStatus(
|
||||
overrides?: Partial<Record<string, unknown>>
|
||||
): Record<string, unknown> {
|
||||
|
|
@ -450,6 +458,63 @@ describe('CLI status visibility during completed install state', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('keeps the dashboard terminal modal unmounted until login is requested', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliStatus = createInstalledCliStatus({
|
||||
authLoggedIn: false,
|
||||
});
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const root = createRoot(host);
|
||||
|
||||
await act(async () => {
|
||||
root.render(React.createElement(CliStatusBanner));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(host.querySelector('[data-testid="terminal-modal"]')).toBeNull();
|
||||
|
||||
const loginButton = Array.from(host.querySelectorAll('button')).find(
|
||||
(button) => button.textContent?.trim() === 'Login'
|
||||
);
|
||||
expect(loginButton).not.toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
loginButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(host.querySelector('[data-testid="terminal-modal"]')).not.toBeNull();
|
||||
|
||||
await act(async () => {
|
||||
root.unmount();
|
||||
await flushLazyImports();
|
||||
});
|
||||
});
|
||||
|
||||
it('loads the installer terminal log only while installation is active', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'installing';
|
||||
storeState.cliInstallerRawChunks = ['installing...\n'];
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
const root = createRoot(host);
|
||||
|
||||
await act(async () => {
|
||||
root.render(React.createElement(CliStatusBanner));
|
||||
await flushLazyImports();
|
||||
});
|
||||
|
||||
expect(host.textContent).toContain('terminal-log');
|
||||
|
||||
await act(async () => {
|
||||
root.unmount();
|
||||
await flushLazyImports();
|
||||
});
|
||||
});
|
||||
|
||||
it('shows an OpenCode install action on the dashboard when the OpenCode CLI is missing', async () => {
|
||||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'idle';
|
||||
|
|
@ -1089,6 +1154,15 @@ describe('CLI status visibility during completed install state', () => {
|
|||
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
||||
storeState.cliInstallerState = 'idle';
|
||||
storeState.fetchCliProviderStatus = vi.fn(() => Promise.reject(new Error('refresh failed')));
|
||||
storeState.cliStatus = createInstalledCliStatus({
|
||||
flavor: 'agent_teams_orchestrator',
|
||||
displayName: 'Multimodel runtime',
|
||||
supportsSelfUpdate: false,
|
||||
showVersionDetails: false,
|
||||
showBinaryPath: false,
|
||||
authLoggedIn: true,
|
||||
providers: [createCodexNativeRolloutProvider()],
|
||||
});
|
||||
|
||||
const host = document.createElement('div');
|
||||
document.body.appendChild(host);
|
||||
|
|
@ -1099,6 +1173,19 @@ describe('CLI status visibility during completed install state', () => {
|
|||
await Promise.resolve();
|
||||
});
|
||||
|
||||
expect(providerRuntimeSettingsDialogProps).toBeNull();
|
||||
|
||||
const manageButton = Array.from(host.querySelectorAll('button')).find(
|
||||
(button) => button.textContent?.trim() === 'Manage'
|
||||
);
|
||||
expect(manageButton).not.toBeUndefined();
|
||||
|
||||
await act(async () => {
|
||||
manageButton?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
await Promise.resolve();
|
||||
await Promise.resolve();
|
||||
});
|
||||
|
||||
const onSelectBackend = providerRuntimeSettingsDialogProps?.onSelectBackend;
|
||||
expect(onSelectBackend).toBeTypeOf('function');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue