Implement terminal restart functionality and enhance model settings menu in InkApp. Add methods for restarting the terminal and adjusting model settings, improving user interaction and menu navigation. Update state management for better handling of model settings adjustments.
This commit is contained in:
@@ -118,10 +118,16 @@ class TerminalService extends EventEmitter {
|
||||
this.ptyProcess.kill();
|
||||
this.ptyProcess = null;
|
||||
}
|
||||
this.started = false;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
restart() {
|
||||
try { this.dispose(); } catch {}
|
||||
try { this.start(); } catch {}
|
||||
}
|
||||
}
|
||||
|
||||
const terminalService = new TerminalService();
|
||||
|
||||
@@ -124,6 +124,8 @@ export default class InkApp extends React.Component {
|
||||
this.toggleMenu = this.toggleMenu.bind(this);
|
||||
this.onKeypress = this.onKeypress.bind(this);
|
||||
this.menuAction = this.menuAction.bind(this);
|
||||
this.getModelSettingsItems = this.getModelSettingsItems.bind(this);
|
||||
this.handleModelSettingAdjust = this.handleModelSettingAdjust.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -230,6 +232,8 @@ export default class InkApp extends React.Component {
|
||||
const isUp = data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x41;
|
||||
const isDown = data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x42;
|
||||
const isEnter = data.length === 1 && data[0] === 0x0d;
|
||||
const isLeft = data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x44;
|
||||
const isRight = data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b && data[2] === 0x43;
|
||||
const isCtrlC = data.length === 1 && data[0] === 0x03;
|
||||
|
||||
if (!this.state.menuOpen) {
|
||||
@@ -245,7 +249,32 @@ export default class InkApp extends React.Component {
|
||||
return;
|
||||
}
|
||||
|
||||
// Menu navigation
|
||||
// Submenu: Model settings adjustments
|
||||
if (this.state.menuOpen && this.state.menuMode === 'model') {
|
||||
const items = this.getModelSettingsItems();
|
||||
if (isUp) {
|
||||
this.setState((s) => ({ menuIndex: (s.menuIndex - 1 + items.length) % items.length }));
|
||||
return;
|
||||
}
|
||||
if (isDown) {
|
||||
this.setState((s) => ({ menuIndex: (s.menuIndex + 1) % items.length }));
|
||||
return;
|
||||
}
|
||||
if (isLeft || isRight) {
|
||||
const idx = this.state.menuIndex;
|
||||
const dir = isRight ? 1 : -1;
|
||||
this.handleModelSettingAdjust(items[idx].key, dir);
|
||||
return;
|
||||
}
|
||||
if (isEnter) {
|
||||
// Enter exits model submenu back to main menu
|
||||
this.setState({ menuMode: undefined, menuIndex: 0 });
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Menu navigation (main menu)
|
||||
const items = this.getMenuItems();
|
||||
if (isUp) {
|
||||
this.setState((s) => ({ menuIndex: (s.menuIndex - 1 + items.length) % items.length }));
|
||||
@@ -278,12 +307,11 @@ export default class InkApp extends React.Component {
|
||||
try { terminalService.write('\x03'); } catch {}
|
||||
break;
|
||||
case 'Restart Terminal':
|
||||
try { terminalService.dispose(); } catch {}
|
||||
try { terminalService.start(); } catch {}
|
||||
try { terminalService.restart(); } catch {}
|
||||
break;
|
||||
case 'Model settings':
|
||||
// Toggle a sub-menu state
|
||||
this.setState({ menuMode: 'model' });
|
||||
this.setState({ menuMode: 'model', menuIndex: 0 });
|
||||
break;
|
||||
case 'Exit the app':
|
||||
try { process.exit(0); } catch {}
|
||||
@@ -296,6 +324,30 @@ export default class InkApp extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
getModelSettingsItems() {
|
||||
return [
|
||||
{ key: 'model', label: 'Model', options: ['gpt-5', 'gpt-5-mini', 'gpt-5-nano', 'gpt-4.1', 'gpt-4.1-mini', 'gpt-4.1-nano'] },
|
||||
{ key: 'reasoningEffort', label: 'Reasoning effort', options: ['minimal', 'low', 'medium', 'high'] },
|
||||
{ key: 'outputVerbosity', label: 'Output verbosity', options: ['low', 'medium', 'high'] },
|
||||
{ key: 'back', label: 'Back to main menu' }
|
||||
];
|
||||
}
|
||||
|
||||
handleModelSettingAdjust(key, dir) {
|
||||
if (key === 'back') {
|
||||
this.setState({ menuMode: undefined, menuIndex: 0 });
|
||||
return;
|
||||
}
|
||||
const items = this.getModelSettingsItems();
|
||||
const item = items.find((i) => i.key === key);
|
||||
if (!item || !item.options) return;
|
||||
const currentValue = this.state[key];
|
||||
const idx = item.options.indexOf(currentValue);
|
||||
const nextIdx = ((idx === -1 ? 0 : idx) + dir + item.options.length) % item.options.length;
|
||||
const nextValue = item.options[nextIdx];
|
||||
this.setState({ [key]: nextValue });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { input, logs, terminal, chainOfThought, llmOutput } = this.state;
|
||||
const totalCols = (process && process.stdout && process.stdout.columns) ? process.stdout.columns : 80;
|
||||
@@ -337,7 +389,7 @@ export default class InkApp extends React.Component {
|
||||
<Pane title="Logging" lines={logsView} maxWidth={paneContentWidth} />
|
||||
</Box>
|
||||
</Box>
|
||||
{this.state.menuOpen && (
|
||||
{this.state.menuOpen && this.state.menuMode !== 'model' && (
|
||||
<Box borderStyle="round" paddingX={1} paddingY={0} marginTop={1} flexDirection="column">
|
||||
<Text color="yellow">Main Menu (Up/Down to navigate, Enter to select)</Text>
|
||||
{menuItems.map((label, i) => (
|
||||
@@ -345,17 +397,17 @@ export default class InkApp extends React.Component {
|
||||
{i === selected ? '› ' : ' '}{label}
|
||||
</Text>
|
||||
))}
|
||||
{this.state.menuMode === 'model' && (
|
||||
<Box flexDirection="column" marginTop={1}>
|
||||
<Text>Model: {this.state.model}</Text>
|
||||
<Text>Reasoning effort: {this.state.reasoningEffort}</Text>
|
||||
<Text>Output verbosity: {this.state.outputVerbosity}</Text>
|
||||
<Text dimColor>
|
||||
(Adjustments pending wiring: model list [gpt-5, gpt-5-mini, gpt-5-nano, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano],
|
||||
reasoning effort [minimal, low, medium, high], output verbosity [low, medium, high])
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{this.state.menuOpen && this.state.menuMode === 'model' && (
|
||||
<Box borderStyle="round" paddingX={1} paddingY={0} marginTop={1} flexDirection="column">
|
||||
<Text color="yellow">Model Settings (Up/Down select, Left/Right change, Enter back)</Text>
|
||||
{this.getModelSettingsItems().map((item, i) => (
|
||||
<Text key={item.key || item.label} color={i === selected ? 'cyan' : undefined}>
|
||||
{i === selected ? '› ' : ' '}
|
||||
{item.label}{item.options ? `: ${this.state[item.key]}` : ''}
|
||||
</Text>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
<Box marginTop={1}>
|
||||
|
||||
Reference in New Issue
Block a user