termcode
Version:
Superior terminal AI coding agent with enterprise-grade security, intelligent error recovery, performance monitoring, and plugin system - Advanced Claude Code alternative
85 lines (84 loc) โข 4.87 kB
JavaScript
#!/usr/bin/env node
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useCallback } from 'react';
import { render, Box, useInput, useApp } from 'ink';
import { useStdoutDimensions } from 'ink-use-stdout-dimensions';
import { StatusBar } from './panes/StatusBar.js';
import { Sidebar } from './panes/Sidebar.js';
import { DiffOutput } from './panes/DiffOutput.js';
import { PromptInput } from './panes/PromptInput.js';
import { CommandPalette } from './panes/CommandPalette.js';
import { useAppState } from './hooks/useAppState.js';
import { useKeyboardShortcuts } from './hooks/useKeyboardShortcuts.js';
export const App = ({ repo, provider, model, config, session, projectInfo }) => {
const { exit } = useApp();
const [width, height] = useStdoutDimensions();
const { appState, setMode, setActivePane, showCommandPalette, setShowCommandPalette, addOutputLine, setCurrentTask, updateStatus } = useAppState({
repo,
provider,
model,
config,
session,
projectInfo
});
// Keyboard shortcuts
useKeyboardShortcuts({
onToggleMode: () => setMode(appState.mode === 'easy' ? 'pro' : 'easy'),
onShowCommandPalette: () => setShowCommandPalette(true),
onFocusPrompt: () => setActivePane('prompt'),
onRunTests: () => handleRunTests(),
onRollback: () => handleRollback(),
onCreatePR: () => handleCreatePR(),
onMerge: () => handleMerge(),
onExit: exit
});
// Handle cycling between panes with Tab
useInput((input, key) => {
if (key.tab && !appState.showCommandPalette) {
const panes = ['sidebar', 'diff', 'prompt'];
const currentIndex = panes.indexOf(appState.activePane);
const nextIndex = (currentIndex + 1) % panes.length;
setActivePane(panes[nextIndex]);
}
});
const handleRunTests = useCallback(async () => {
updateStatus('Running tests...');
addOutputLine('๐งช Starting test run...');
// Implementation would call the test runner
}, [addOutputLine, updateStatus]);
const handleRollback = useCallback(async () => {
updateStatus('Rolling back changes...');
addOutputLine('โช Rolling back all changes...');
// Implementation would call git rollback
}, [addOutputLine, updateStatus]);
const handleCreatePR = useCallback(async () => {
updateStatus('Creating pull request...');
addOutputLine('๐ Creating pull request...');
// Implementation would create PR
}, [addOutputLine, updateStatus]);
const handleMerge = useCallback(async () => {
updateStatus('Merging changes...');
addOutputLine('๐ Merging changes to main...');
// Implementation would merge branch
}, [addOutputLine, updateStatus]);
const handleTaskSubmit = useCallback(async (task) => {
setCurrentTask(task);
updateStatus(`Processing: ${task.substring(0, 30)}...`);
addOutputLine(`๐ Task: ${task}`);
// Implementation would call the AI agent
}, [addOutputLine, setCurrentTask, updateStatus]);
// Calculate layout dimensions
const statusHeight = 3;
const promptHeight = 3;
const contentHeight = height - statusHeight - promptHeight;
const sidebarWidth = Math.floor(width * 0.25);
const diffWidth = width - sidebarWidth;
return (_jsxs(Box, { flexDirection: "column", width: width, height: height, children: [_jsx(StatusBar, { height: statusHeight, mode: appState.mode, provider: appState.provider, model: appState.model, status: appState.status, branch: appState.branch, project: appState.projectInfo?.type }), _jsxs(Box, { flexDirection: "row", height: contentHeight, children: [_jsx(Sidebar, { width: sidebarWidth, height: contentHeight, active: appState.activePane === 'sidebar', mode: appState.mode, session: appState.session, onTaskSubmit: handleTaskSubmit, onRunTests: handleRunTests, onRollback: handleRollback, onCreatePR: handleCreatePR, onMerge: handleMerge }), _jsx(DiffOutput, { width: diffWidth, height: contentHeight, active: appState.activePane === 'diff', output: appState.output, currentDiff: appState.currentDiff, streaming: appState.streaming })] }), _jsx(PromptInput, { height: promptHeight, active: appState.activePane === 'prompt', mode: appState.mode, onSubmit: handleTaskSubmit }), appState.showCommandPalette && (_jsx(CommandPalette, { onClose: () => setShowCommandPalette(false), onExecute: (command) => {
setShowCommandPalette(false);
// Handle command execution
}, providers: Object.keys(config.models), currentProvider: appState.provider, currentModel: appState.model }))] }));
};
// CLI entry point for TUI mode
export function startTUI(props) {
render(_jsx(App, { ...props }));
}