Massive refactor of API

- Switch to function based API
- Anthropic SDK style async generator
- Fully typed with escape hatches for custom models
This commit is contained in:
Mario Zechner 2025-09-02 23:59:36 +02:00
parent 004de3c9d0
commit 66cefb236e
29 changed files with 5835 additions and 6225 deletions

View file

@ -1,15 +1,6 @@
#!/usr/bin/env npx tsx
import {
Container,
LoadingAnimation,
TextComponent,
TextEditor,
TUI,
WhitespaceComponent,
} from "../src/index.js";
import chalk from "chalk";
import { Container, LoadingAnimation, TextComponent, TextEditor, TUI, WhitespaceComponent } from "../src/index.js";
/**
* Test the new smart double-buffered TUI implementation
@ -24,7 +15,7 @@ async function main() {
// Monkey-patch requestRender to measure performance
const originalRequestRender = ui.requestRender.bind(ui);
ui.requestRender = function() {
ui.requestRender = () => {
const startTime = process.hrtime.bigint();
originalRequestRender();
process.nextTick(() => {
@ -38,10 +29,12 @@ async function main() {
// Add header
const header = new TextComponent(
chalk.bold.green("Smart Double Buffer TUI Test") + "\n" +
chalk.dim("Testing new implementation with component-level caching and smart diffing") + "\n" +
chalk.dim("Press CTRL+C to exit"),
{ bottom: 1 }
chalk.bold.green("Smart Double Buffer TUI Test") +
"\n" +
chalk.dim("Testing new implementation with component-level caching and smart diffing") +
"\n" +
chalk.dim("Press CTRL+C to exit"),
{ bottom: 1 },
);
ui.addChild(header);
@ -57,7 +50,9 @@ async function main() {
// Add text editor
const editor = new TextEditor();
editor.setText("Type here to test the text editor.\n\nWith smart diffing, only changed lines are redrawn!\n\nThe animation above updates every 80ms but the editor stays perfectly still.");
editor.setText(
"Type here to test the text editor.\n\nWith smart diffing, only changed lines are redrawn!\n\nThe animation above updates every 80ms but the editor stays perfectly still.",
);
container.addChild(editor);
// Add the container to UI
@ -71,15 +66,20 @@ async function main() {
const statsInterval = setInterval(() => {
if (renderCount > 0) {
const avgRenderTime = Number(totalRenderTime / BigInt(renderCount)) / 1_000_000; // Convert to ms
const lastRenderTime = renderTimings.length > 0
? Number(renderTimings[renderTimings.length - 1]) / 1_000_000
: 0;
const lastRenderTime =
renderTimings.length > 0 ? Number(renderTimings[renderTimings.length - 1]) / 1_000_000 : 0;
const avgLinesRedrawn = ui.getAverageLinesRedrawn();
statsComponent.setText(
chalk.yellow(`Performance Stats:`) + "\n" +
chalk.dim(`Renders: ${renderCount} | Avg Time: ${avgRenderTime.toFixed(2)}ms | Last: ${lastRenderTime.toFixed(2)}ms`) + "\n" +
chalk.dim(`Lines Redrawn: ${ui.getLinesRedrawn()} total | Avg per render: ${avgLinesRedrawn.toFixed(1)}`)
chalk.yellow(`Performance Stats:`) +
"\n" +
chalk.dim(
`Renders: ${renderCount} | Avg Time: ${avgRenderTime.toFixed(2)}ms | Last: ${lastRenderTime.toFixed(2)}ms`,
) +
"\n" +
chalk.dim(
`Lines Redrawn: ${ui.getLinesRedrawn()} total | Avg per render: ${avgLinesRedrawn.toFixed(1)}`,
),
);
}
}, 1000);
@ -96,7 +96,11 @@ async function main() {
ui.stop();
console.log("\n" + chalk.green("Exited double-buffer test"));
console.log(chalk.dim(`Total renders: ${renderCount}`));
console.log(chalk.dim(`Average render time: ${renderCount > 0 ? (Number(totalRenderTime / BigInt(renderCount)) / 1_000_000).toFixed(2) : 0}ms`));
console.log(
chalk.dim(
`Average render time: ${renderCount > 0 ? (Number(totalRenderTime / BigInt(renderCount)) / 1_000_000).toFixed(2) : 0}ms`,
),
);
console.log(chalk.dim(`Total lines redrawn: ${ui.getLinesRedrawn()}`));
console.log(chalk.dim(`Average lines redrawn per render: ${ui.getAverageLinesRedrawn().toFixed(1)}`));
process.exit(0);
@ -112,4 +116,4 @@ async function main() {
main().catch((error) => {
console.error("Error:", error);
process.exit(1);
});
});