Thinking selector fix: - Replace hardcoded 50-character borders with DynamicBorder component that adjusts to viewport width - Prevents crash when terminal is resized narrow Text/Markdown rendering fixes: - Fix Markdown wrapSingleLine to check if adding next character would exceed width BEFORE adding it (was checking AFTER, causing lines to be 1 character too long) - Add word truncation in Text component for words longer than contentWidth (prevents long unbreakable words from exceeding width) These fixes prevent "Rendered line exceeds terminal width" errors.
61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import type { ThinkingLevel } from "@mariozechner/pi-agent";
|
|
import { type Component, Container, type SelectItem, SelectList } from "@mariozechner/pi-tui";
|
|
import chalk from "chalk";
|
|
|
|
/**
|
|
* Dynamic border component that adjusts to viewport width
|
|
*/
|
|
class DynamicBorder implements Component {
|
|
render(width: number): string[] {
|
|
return [chalk.blue("─".repeat(Math.max(1, width)))];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Component that renders a thinking level selector with borders
|
|
*/
|
|
export class ThinkingSelectorComponent extends Container {
|
|
private selectList: SelectList;
|
|
|
|
constructor(currentLevel: ThinkingLevel, onSelect: (level: ThinkingLevel) => void, onCancel: () => void) {
|
|
super();
|
|
|
|
const thinkingLevels: SelectItem[] = [
|
|
{ value: "off", label: "off", description: "No reasoning" },
|
|
{ value: "minimal", label: "minimal", description: "Very brief reasoning (~1k tokens)" },
|
|
{ value: "low", label: "low", description: "Light reasoning (~2k tokens)" },
|
|
{ value: "medium", label: "medium", description: "Moderate reasoning (~8k tokens)" },
|
|
{ value: "high", label: "high", description: "Deep reasoning (~16k tokens)" },
|
|
];
|
|
|
|
// Add top border
|
|
this.addChild(new DynamicBorder());
|
|
|
|
// Create selector
|
|
this.selectList = new SelectList(thinkingLevels, 5);
|
|
|
|
// Preselect current level
|
|
const currentIndex = thinkingLevels.findIndex((item) => item.value === currentLevel);
|
|
if (currentIndex !== -1) {
|
|
this.selectList.setSelectedIndex(currentIndex);
|
|
}
|
|
|
|
this.selectList.onSelect = (item) => {
|
|
onSelect(item.value as ThinkingLevel);
|
|
};
|
|
|
|
this.selectList.onCancel = () => {
|
|
onCancel();
|
|
};
|
|
|
|
this.addChild(this.selectList);
|
|
|
|
// Add bottom border
|
|
this.addChild(new DynamicBorder());
|
|
}
|
|
|
|
getSelectList(): SelectList {
|
|
return this.selectList;
|
|
}
|
|
}
|