@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
116 lines • 5.63 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Text, useInput } from 'ink';
import SelectInput from 'ink-select-input';
import React, { useEffect, useState } from 'react';
import { defaultTheme, getThemeColors } from '../config/themes.js';
import { TIMEOUT_VSCODE_EXTENSION_SKIP_MS } from '../constants.js';
import { installExtension, isExtensionInstalled, isVSCodeCliAvailable, } from '../vscode/extension-installer.js';
var InstallOption;
(function (InstallOption) {
InstallOption["Yes"] = "yes";
InstallOption["No"] = "no";
})(InstallOption || (InstallOption = {}));
/**
* Ink component that prompts the user to install the VS Code extension
* when running with --vscode flag and the extension isn't installed
*/
// Compute initial state synchronously
function getInitialState() {
if (isExtensionInstalled()) {
return 'checking'; // Will trigger onComplete in effect
}
if (!isVSCodeCliAvailable()) {
return 'no-cli';
}
return 'prompt';
}
export function VSCodeExtensionPrompt({ onComplete, onSkip, }) {
const [state, setState] = useState(getInitialState);
const [message, setMessage] = useState('');
const colors = getThemeColors(defaultTheme);
const handleInstall = React.useCallback(async () => {
const result = await installExtension();
if (result.success) {
setMessage(result.message);
setState('success');
// Wait for user to press Enter
}
else {
setMessage(result.message);
setState('error');
// Auto-continue after showing error
setTimeout(onSkip, TIMEOUT_VSCODE_EXTENSION_SKIP_MS);
}
}, [onSkip]);
// Handle Enter key press in success state
useInput((_input, key) => {
if (state === 'success' && key.return) {
onComplete();
}
}, { isActive: state === 'success' });
// Handle already-installed case
useEffect(() => {
if (isExtensionInstalled()) {
onComplete();
}
}, [onComplete]);
// Handle no-cli case - auto-skip after showing message
useEffect(() => {
if (state === 'no-cli') {
const timer = setTimeout(onSkip, TIMEOUT_VSCODE_EXTENSION_SKIP_MS);
return () => clearTimeout(timer);
}
}, [state, onSkip]);
const items = [
{
label: 'Yes, install extension',
value: InstallOption.Yes,
},
{
label: 'No, skip for now',
value: InstallOption.No,
},
];
const handleSelect = (item) => {
if (item.value === InstallOption.Yes) {
setState('installing');
void handleInstall();
}
else {
onSkip();
}
};
if (state === 'checking') {
return (_jsx(Box, { flexDirection: "column", paddingY: 1, children: _jsx(Text, { color: colors.primary, children: "Checking VS Code extension..." }) }));
}
if (state === 'no-cli') {
return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsx(Text, { color: colors.warning, children: "VS Code CLI not found. To enable VS Code integration:" }), _jsxs(Box, { marginLeft: 2, flexDirection: "column", marginTop: 1, children: [_jsx(Text, { color: colors.secondary, children: "1. Open VS Code" }), _jsx(Text, { color: colors.secondary, children: "2. Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows/Linux)" }), _jsx(Text, { color: colors.secondary, children: "3. Type \"Shell Command: Install 'code' command in PATH\"" })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.secondary, children: "Continuing without VS Code integration..." }) })] }));
}
if (state === 'prompt') {
return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsx(Text, { color: colors.primary, bold: true, children: "VS Code Extension" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.text, children: "The VS Code extension enables live diff previews when Nanocoder modifies files." }) }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.text, children: "Install the extension now?" }) }), _jsx(Box, { marginTop: 1, children: _jsx(SelectInput, { items: items, onSelect: handleSelect }) })] }));
}
if (state === 'installing') {
return (_jsx(Box, { flexDirection: "column", paddingY: 1, children: _jsx(Text, { color: colors.primary, children: "Installing VS Code extension..." }) }));
}
if (state === 'success') {
return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsxs(Text, { color: colors.success, children: ["\u2713 ", message] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.secondary, children: "Press Enter to continue..." }) })] }));
}
if (state === 'error') {
return (_jsxs(Box, { flexDirection: "column", paddingY: 1, children: [_jsxs(Text, { color: colors.error, children: ["\u2717 ", message] }), _jsx(Text, { color: colors.secondary, children: "Continuing without VS Code integration..." })] }));
}
return null;
}
/**
* Check if we should show the extension install prompt
* Returns true if --vscode flag is present and extension is not installed
*/
export function shouldPromptExtensionInstall() {
const hasVSCodeFlag = process.argv.includes('--vscode');
if (!hasVSCodeFlag)
return false;
// Don't prompt if extension is already installed
if (isExtensionInstalled())
return false;
return true;
}
//# sourceMappingURL=vscode-extension-prompt.js.map