import chalk from 'chalk' import figures from 'figures' import * as React from 'react' import { useEffect, useState } from 'react' import { Text } from '../ink.js' import { useKeybinding } from '../keybindings/useKeybinding.js' import { toError } from '../utils/errors.js' import { logError } from '../utils/log.js' import { getSettingSourceName, type SettingSource, } from '../utils/settings/constants.js' import { updateSettingsForSource } from '../utils/settings/settings.js' import { getEnvironmentSelectionInfo } from '../utils/teleport/environmentSelection.js' import type { EnvironmentResource } from '../utils/teleport/environments.js' import { ConfigurableShortcutHint } from './ConfigurableShortcutHint.js' import { Select } from './CustomSelect/select.js' import { Byline } from './design-system/Byline.js' import { Dialog } from './design-system/Dialog.js' import { KeyboardShortcutHint } from './design-system/KeyboardShortcutHint.js' import { LoadingState } from './design-system/LoadingState.js' const DIALOG_TITLE = 'Select Remote Environment' const SETUP_HINT = `Configure environments at: https://claude.ai/code` type Props = { onDone: (message?: string) => void } type LoadingState = 'loading' | 'updating' | null export function RemoteEnvironmentDialog({ onDone }: Props): React.ReactNode { const [loadingState, setLoadingState] = useState('loading') const [environments, setEnvironments] = useState([]) const [selectedEnvironment, setSelectedEnvironment] = useState(null) const [selectedEnvironmentSource, setSelectedEnvironmentSource] = useState(null) const [error, setError] = useState(null) useEffect(() => { let cancelled = false async function fetchInfo(): Promise { try { const result = await getEnvironmentSelectionInfo() if (cancelled) return setEnvironments(result.availableEnvironments) setSelectedEnvironment(result.selectedEnvironment) setSelectedEnvironmentSource(result.selectedEnvironmentSource) setLoadingState(null) } catch (err) { if (cancelled) return const fetchError = toError(err) logError(fetchError) setError(fetchError.message) setLoadingState(null) } } void fetchInfo() return () => { cancelled = true } }, []) function handleSelect(value: string): void { if (value === 'cancel') { onDone() return } setLoadingState('updating') const selectedEnv = environments.find(env => env.environment_id === value) if (!selectedEnv) { onDone('Error: Selected environment not found') return } updateSettingsForSource('localSettings', { remote: { defaultEnvironmentId: selectedEnv.environment_id, }, }) onDone( `Set default remote environment to ${chalk.bold(selectedEnv.name)} (${selectedEnv.environment_id})`, ) } // Loading state if (loadingState === 'loading') { return ( ) } // Error state if (error) { return ( Error: {error} ) } // No environments available if (!selectedEnvironment) { return ( No remote environments available. ) } // Single environment - just show info if (environments.length === 1) { return ( ) } // Multiple environments - show selection UI return ( ) } function EnvironmentLabel({ environment, }: { environment: EnvironmentResource }): React.ReactNode { return ( {figures.tick} Using {environment.name}{' '} ({environment.environment_id}) ) } function SingleEnvironmentContent({ environment, onDone, }: { environment: EnvironmentResource onDone: () => void }): React.ReactNode { // Handle Enter to continue useKeybinding('confirm:yes', onDone, { context: 'Confirmation' }) return ( ) } function MultipleEnvironmentsContent({ environments, selectedEnvironment, selectedEnvironmentSource, loadingState, onSelect, onCancel, }: { environments: EnvironmentResource[] selectedEnvironment: EnvironmentResource selectedEnvironmentSource: SettingSource | null loadingState: LoadingState onSelect: (value: string) => void onCancel: () => void }): React.ReactNode { const sourceSuffix = selectedEnvironmentSource && selectedEnvironmentSource !== 'localSettings' ? ` (from ${getSettingSourceName(selectedEnvironmentSource)} settings)` : '' const subtitle = ( Currently using: {selectedEnvironment.name} {sourceSuffix} ) return ( {SETUP_HINT} {loadingState === 'updating' ? ( ) : (