fix: vscode runtime stability and cli connection
This commit is contained in:
@@ -6,7 +6,6 @@ import { useSessionStore } from '@/stores/useSessionStore';
|
||||
import { useConfigStore } from '@/stores/useConfigStore';
|
||||
import { ContextUsageDisplay } from '@/components/ui/ContextUsageDisplay';
|
||||
import { RiAddLine, RiArrowLeftLine, RiSettings3Line } from '@remixicon/react';
|
||||
import { RiLoader4Line } from '@remixicon/react';
|
||||
import { SettingsPage } from '@/components/sections/settings/SettingsPage';
|
||||
|
||||
type VSCodeView = 'sessions' | 'chat' | 'settings';
|
||||
@@ -23,14 +22,6 @@ export const VSCodeLayout: React.FC = () => {
|
||||
'connecting' | 'connected' | 'error' | 'disconnected' | undefined
|
||||
: 'connecting') || 'connecting'
|
||||
);
|
||||
const [connectionError, setConnectionError] = React.useState<string | undefined>(
|
||||
() => (typeof window !== 'undefined'
|
||||
? (window as { __OPENCHAMBER_CONNECTION__?: { error?: string } }).__OPENCHAMBER_CONNECTION__?.error
|
||||
: undefined),
|
||||
);
|
||||
const [hasEverConnected, setHasEverConnected] = React.useState<boolean>(() => connectionStatus === 'connected');
|
||||
const [overlayVisible, setOverlayVisible] = React.useState<boolean>(() => connectionStatus !== 'connected');
|
||||
const overlayTimer = React.useRef<number | null>(null);
|
||||
const configInitialized = useConfigStore((state) => state.isInitialized);
|
||||
const initializeConfig = useConfigStore((state) => state.initializeApp);
|
||||
const loadSessions = useSessionStore((state) => state.loadSessions);
|
||||
@@ -62,54 +53,20 @@ export const VSCodeLayout: React.FC = () => {
|
||||
setCurrentView('chat');
|
||||
}, [openNewSessionDraft]);
|
||||
|
||||
// Listen for connection status changes
|
||||
React.useEffect(() => {
|
||||
const handler = (event: Event) => {
|
||||
const detail = (event as CustomEvent<{ status?: string; error?: string }>).detail;
|
||||
const status = detail?.status;
|
||||
if (status === 'connected' || status === 'connecting' || status === 'error' || status === 'disconnected') {
|
||||
setConnectionStatus(status);
|
||||
setConnectionError(detail?.error);
|
||||
if (status === 'connected') {
|
||||
setHasEverConnected(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('openchamber:connection-status', handler as EventListener);
|
||||
return () => window.removeEventListener('openchamber:connection-status', handler as EventListener);
|
||||
}, []);
|
||||
|
||||
const showConnectionOverlay = React.useMemo(() => {
|
||||
if (hasInitializedOnce && connectionStatus === 'connected' && !isInitializing) {
|
||||
return false;
|
||||
}
|
||||
if (!hasInitializedOnce) {
|
||||
return connectionStatus !== 'connected' || isInitializing;
|
||||
}
|
||||
return connectionStatus === 'error';
|
||||
}, [connectionStatus, hasInitializedOnce, isInitializing]);
|
||||
|
||||
const overlayDelay = hasEverConnected ? 800 : 250;
|
||||
|
||||
React.useEffect(() => {
|
||||
if (overlayTimer.current) {
|
||||
window.clearTimeout(overlayTimer.current);
|
||||
overlayTimer.current = null;
|
||||
}
|
||||
|
||||
if (showConnectionOverlay) {
|
||||
overlayTimer.current = window.setTimeout(() => setOverlayVisible(true), overlayDelay);
|
||||
} else {
|
||||
setOverlayVisible(false);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (overlayTimer.current) {
|
||||
window.clearTimeout(overlayTimer.current);
|
||||
overlayTimer.current = null;
|
||||
}
|
||||
};
|
||||
}, [overlayDelay, showConnectionOverlay]);
|
||||
|
||||
// Bootstrap config and sessions when connected
|
||||
React.useEffect(() => {
|
||||
const runBootstrap = async () => {
|
||||
if (isInitializing || hasInitializedOnce || connectionStatus !== 'connected') {
|
||||
@@ -123,7 +80,7 @@ export const VSCodeLayout: React.FC = () => {
|
||||
await loadSessions();
|
||||
setHasInitializedOnce(true);
|
||||
} catch {
|
||||
// Ignore bootstrap failures; overlay will remain until next attempt
|
||||
// Ignore bootstrap failures
|
||||
} finally {
|
||||
setIsInitializing(false);
|
||||
}
|
||||
@@ -131,6 +88,7 @@ export const VSCodeLayout: React.FC = () => {
|
||||
void runBootstrap();
|
||||
}, [connectionStatus, configInitialized, hasInitializedOnce, initializeConfig, isInitializing, loadSessions]);
|
||||
|
||||
// Hydrate messages when viewing chat
|
||||
React.useEffect(() => {
|
||||
const hydrateMessages = async () => {
|
||||
if (!hasInitializedOnce || connectionStatus !== 'connected' || currentView !== 'chat' || newSessionDraftOpen) {
|
||||
@@ -152,8 +110,6 @@ export const VSCodeLayout: React.FC = () => {
|
||||
void hydrateMessages();
|
||||
}, [connectionStatus, currentSessionId, currentView, hasInitializedOnce, loadMessages, messages, newSessionDraftOpen]);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="h-full w-full bg-background text-foreground flex flex-col">
|
||||
{currentView === 'sessions' ? (
|
||||
@@ -200,21 +156,6 @@ export const VSCodeLayout: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{overlayVisible && (
|
||||
<div className="absolute inset-0 z-50 bg-background/90 backdrop-blur-sm flex flex-col items-center justify-center gap-3 text-center px-4">
|
||||
<RiLoader4Line className="h-7 w-7 animate-spin text-muted-foreground" />
|
||||
<div className="text-sm font-medium">
|
||||
{connectionStatus === 'connecting'
|
||||
? (hasEverConnected ? 'Reconnecting to OpenCode…' : 'Starting OpenCode API…')
|
||||
: 'Lost connection to OpenCode'}
|
||||
</div>
|
||||
{connectionError && (
|
||||
<div className="text-xs text-muted-foreground max-w-md">
|
||||
{connectionError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user