mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-20 12:04:35 +00:00
Refactor TUI components into separate files
- Move TUI components into src/tui/ folder - Split out CustomEditor, StreamingMessageComponent, ToolExecutionComponent, FooterComponent - Trim assistant message text content - Add newline after per-message token/cost stats - Improve code organization and maintainability
This commit is contained in:
parent
fe5706885d
commit
4fa09814bd
6 changed files with 292 additions and 281 deletions
72
packages/coding-agent/src/tui/streaming-message.ts
Normal file
72
packages/coding-agent/src/tui/streaming-message.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
import type { AssistantMessage, Message } from "@mariozechner/pi-ai";
|
||||
import { Container, Markdown, Text } from "@mariozechner/pi-tui";
|
||||
import chalk from "chalk";
|
||||
|
||||
/**
|
||||
* Component that renders a streaming message with live updates
|
||||
*/
|
||||
export class StreamingMessageComponent extends Container {
|
||||
private markdown: Markdown;
|
||||
private statsText: Text;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.markdown = new Markdown("");
|
||||
this.statsText = new Text("", 1, 0);
|
||||
this.addChild(this.markdown);
|
||||
this.addChild(this.statsText);
|
||||
}
|
||||
|
||||
updateContent(message: Message | null) {
|
||||
if (!message) {
|
||||
this.markdown.setText("");
|
||||
this.statsText.setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.role === "assistant") {
|
||||
const assistantMsg = message as AssistantMessage;
|
||||
|
||||
// Update text and thinking content
|
||||
let combinedContent = "";
|
||||
for (const c of assistantMsg.content) {
|
||||
if (c.type === "text") {
|
||||
combinedContent += c.text;
|
||||
} else if (c.type === "thinking") {
|
||||
// Add thinking in italic
|
||||
const thinkingLines = c.thinking
|
||||
.split("\n")
|
||||
.map((line) => `*${line}*`)
|
||||
.join("\n");
|
||||
if (combinedContent && !combinedContent.endsWith("\n")) combinedContent += "\n";
|
||||
combinedContent += thinkingLines;
|
||||
if (!combinedContent.endsWith("\n")) combinedContent += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
this.markdown.setText(combinedContent);
|
||||
|
||||
// Update usage stats
|
||||
const usage = assistantMsg.usage;
|
||||
if (usage) {
|
||||
// Format token counts (similar to web-ui)
|
||||
const formatTokens = (count: number): string => {
|
||||
if (count < 1000) return count.toString();
|
||||
if (count < 10000) return (count / 1000).toFixed(1) + "k";
|
||||
return Math.round(count / 1000) + "k";
|
||||
};
|
||||
|
||||
const statsParts = [];
|
||||
if (usage.input) statsParts.push(`↑${formatTokens(usage.input)}`);
|
||||
if (usage.output) statsParts.push(`↓${formatTokens(usage.output)}`);
|
||||
if (usage.cacheRead) statsParts.push(`R${formatTokens(usage.cacheRead)}`);
|
||||
if (usage.cacheWrite) statsParts.push(`W${formatTokens(usage.cacheWrite)}`);
|
||||
if (usage.cost?.total) statsParts.push(`$${usage.cost.total.toFixed(3)}`);
|
||||
|
||||
this.statsText.setText(chalk.gray(statsParts.join(" ")));
|
||||
} else {
|
||||
this.statsText.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue