Update CLI and ModelDialog to enhance functionality and user experience. Modify interrogation command in CLI for improved output generation, adjust model settings in ModelDialog for better reasoning effort, and introduce a new plugin structure in plan.md for LLM integration in Roundcube. Add spinner functionality in InkApp for loading states and improve error handling in read_file.js to ensure proper line breaks in file content output.
This commit is contained in:
@@ -3,6 +3,10 @@ import { Box, Text } from 'ink';
|
||||
import uiService from './uiService.js';
|
||||
import TextInput from 'ink-text-input';
|
||||
import terminalService from '../terminalService.js';
|
||||
import ModelDialog from '../../modelDialog.js';
|
||||
|
||||
const sharedModelDialog = new ModelDialog();
|
||||
const npmSpinnerFrames = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
|
||||
|
||||
class Pane extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -113,7 +117,9 @@ export default class InkApp extends React.Component {
|
||||
menuIndex: 0,
|
||||
model: 'gpt-5',
|
||||
reasoningEffort: 'minimal',
|
||||
outputVerbosity: 'low'
|
||||
outputVerbosity: 'low',
|
||||
isLoading: false,
|
||||
spinnerIndex: 0
|
||||
};
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
@@ -156,6 +162,12 @@ export default class InkApp extends React.Component {
|
||||
try { process.stdin.setRawMode(true); } catch {}
|
||||
process.stdin.on('data', this.onKeypress);
|
||||
}
|
||||
// spinner timer
|
||||
this._spinnerTimer = setInterval(() => {
|
||||
if (this.state.isLoading) {
|
||||
this.setState((s) => ({ spinnerIndex: (s.spinnerIndex + 1) % npmSpinnerFrames.length }));
|
||||
}
|
||||
}, 80);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
if (this.terminalUnsub) {
|
||||
@@ -169,6 +181,10 @@ export default class InkApp extends React.Component {
|
||||
if (process.stdin && process.stdin.off) {
|
||||
process.stdin.off('data', this.onKeypress);
|
||||
}
|
||||
if (this._spinnerTimer) {
|
||||
clearInterval(this._spinnerTimer);
|
||||
this._spinnerTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
setPaneLines(stateKey, lines) {
|
||||
@@ -205,21 +221,42 @@ export default class InkApp extends React.Component {
|
||||
this.setState({ input: value });
|
||||
}
|
||||
|
||||
handleSubmit() {
|
||||
async handleSubmit() {
|
||||
const { input } = this.state;
|
||||
if (!input) return;
|
||||
try {
|
||||
terminalService.write(`${input}\r`);
|
||||
} catch (e) {
|
||||
// do not hide errors; show in logs
|
||||
this.setState((state) => ({
|
||||
logs: [...state.logs, `! write error: ${String(e && e.message ? e.message : e)}`],
|
||||
}));
|
||||
}
|
||||
this.setState((state) => ({
|
||||
logs: [...state.logs, `> ${input}`],
|
||||
input: ''
|
||||
input: '',
|
||||
isLoading: true
|
||||
}));
|
||||
try {
|
||||
const result = await sharedModelDialog.interrogate(input);
|
||||
const finalOutput = Array.isArray(result && result.output) ? result.output : [String(result && result.output ? result.output : '')];
|
||||
const finalReasoning = Array.isArray(result && result.reasoning) ? result.reasoning : (result && result.reasoning ? [String(result.reasoning)] : []);
|
||||
// Append to LLM output with a separator, overwrite chain of thought
|
||||
this.setState((state) => ({
|
||||
llmOutput: [
|
||||
...state.llmOutput,
|
||||
...(state.llmOutput.length ? ['----------'] : []),
|
||||
...finalOutput
|
||||
]
|
||||
}));
|
||||
this.setChainOfThought(finalReasoning);
|
||||
this.setState((state) => ({
|
||||
logs: [
|
||||
...state.logs,
|
||||
`tokens input: ${JSON.stringify(result && result.inputTokens)}`,
|
||||
`tokens cached: ${JSON.stringify(result && result.cachedTokens)}`,
|
||||
`tokens output: ${JSON.stringify(result && result.outputTokens)}`
|
||||
]
|
||||
}));
|
||||
} catch (e) {
|
||||
this.setState((state) => ({
|
||||
logs: [...state.logs, `! interrogate error: ${String(e && e.message ? e.message : e)}`]
|
||||
}));
|
||||
} finally {
|
||||
this.setState({ isLoading: false });
|
||||
}
|
||||
}
|
||||
|
||||
toggleMenu(open) {
|
||||
@@ -412,12 +449,16 @@ export default class InkApp extends React.Component {
|
||||
)}
|
||||
<Box marginTop={1}>
|
||||
<Text>Input: </Text>
|
||||
<TextInput
|
||||
value={input}
|
||||
onChange={this.handleChange}
|
||||
onSubmit={this.handleSubmit}
|
||||
placeholder="Type and press Enter..."
|
||||
/>
|
||||
{this.state.isLoading ? (
|
||||
<Text color="yellow">{npmSpinnerFrames[this.state.spinnerIndex]} Processing...</Text>
|
||||
) : (
|
||||
<TextInput
|
||||
value={input}
|
||||
onChange={this.handleChange}
|
||||
onSubmit={this.handleSubmit}
|
||||
placeholder="Type and press Enter..."
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user