Add /thinking command and improve TUI UX

- Add /thinking slash command with autocomplete for setting reasoning levels (off, minimal, low, medium, high)
- Fix Ctrl+C behavior: remove hardcoded exit in TUI, let focused component handle it
- Add empty lines before and after tool execution components for better visual separation
- Fix stats rendering: display stats AFTER tool executions complete (matches web-ui behavior)
- Remove "Press Ctrl+C again to exit" message, show "(esc to interrupt)" in loader instead
- Add bash tool abort signal support with immediate SIGKILL on interrupt
- Make Text and Markdown components return empty arrays when no actual text content
- Add setCustomBgRgb() method to Markdown for dynamic background colors
This commit is contained in:
Mario Zechner 2025-11-11 20:28:10 +01:00
parent c5083bb7cb
commit dc1e2f928b
7 changed files with 516 additions and 166 deletions

View file

@ -76,6 +76,14 @@ export class Markdown implements Component {
this.cachedLines = undefined;
}
setCustomBgRgb(customBgRgb?: { r: number; g: number; b: number }): void {
this.customBgRgb = customBgRgb;
// Invalidate cache when color changes
this.cachedText = undefined;
this.cachedWidth = undefined;
this.cachedLines = undefined;
}
render(width: number): string[] {
// Check cache
if (this.cachedLines && this.cachedText === this.text && this.cachedWidth === width) {
@ -85,6 +93,16 @@ export class Markdown implements Component {
// Calculate available width for content (subtract horizontal padding)
const contentWidth = Math.max(1, width - this.paddingX * 2);
// Don't render anything if there's no actual text
if (!this.text || this.text.trim() === "") {
const result: string[] = [];
// Update cache
this.cachedText = this.text;
this.cachedWidth = width;
this.cachedLines = result;
return result;
}
// Parse markdown to HTML-like tokens
const tokens = marked.lexer(this.text);

View file

@ -37,8 +37,9 @@ export class Text implements Component {
// Calculate available width for content (subtract horizontal padding)
const contentWidth = Math.max(1, width - this.paddingX * 2);
if (!this.text) {
const result = [""];
// Don't render anything if there's no actual text
if (!this.text || this.text.trim() === "") {
const result: string[] = [];
// Update cache
this.cachedText = this.text;
this.cachedWidth = width;

View file

@ -98,13 +98,8 @@ export class TUI extends Container {
}
private handleInput(data: string): void {
// Exit on Ctrl+C
if (data === "\x03") {
this.stop();
process.exit(0);
}
// Pass input to focused component
// Pass input to focused component (including Ctrl+C)
// The focused component can decide how to handle Ctrl+C
if (this.focusedComponent?.handleInput) {
this.focusedComponent.handleInput(data);
this.requestRender();