mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 08:13:11 +03:00
88 lines
2.3 KiB
TypeScript
88 lines
2.3 KiB
TypeScript
import {
|
|
BoxRenderable,
|
|
TextRenderable,
|
|
type CliRenderer,
|
|
} from "@opentui/core"
|
|
|
|
import type { SessionContextSnapshot } from "./protocol"
|
|
|
|
export interface ContextPanelTheme {
|
|
text: string
|
|
border: string
|
|
accent: string
|
|
}
|
|
|
|
export function formatTokenCount(value: number): string {
|
|
if (value < 1_000) return String(value)
|
|
const compact = value >= 10_000 ? Math.round(value / 1_000) : Math.round(value / 100) / 10
|
|
return `${compact}k`
|
|
}
|
|
|
|
/** Read-only explanation of the session-owned context replayed to the agent. */
|
|
export class ContextPanel {
|
|
readonly root: BoxRenderable
|
|
private readonly stats: TextRenderable
|
|
private readonly summary: TextRenderable
|
|
|
|
constructor(renderer: CliRenderer, theme: ContextPanelTheme) {
|
|
this.root = new BoxRenderable(renderer, {
|
|
id: "nanobot-tui-context-panel",
|
|
width: "100%",
|
|
maxHeight: 9,
|
|
flexShrink: 0,
|
|
flexDirection: "column",
|
|
border: true,
|
|
borderStyle: "rounded",
|
|
borderColor: theme.border,
|
|
paddingLeft: 1,
|
|
paddingRight: 1,
|
|
visible: false,
|
|
})
|
|
this.stats = new TextRenderable(renderer, {
|
|
id: "nanobot-tui-context-stats",
|
|
content: "",
|
|
width: "100%",
|
|
fg: theme.accent,
|
|
wrapMode: "word",
|
|
})
|
|
this.summary = new TextRenderable(renderer, {
|
|
id: "nanobot-tui-context-summary",
|
|
content: "",
|
|
width: "100%",
|
|
maxHeight: 6,
|
|
fg: theme.text,
|
|
wrapMode: "word",
|
|
})
|
|
this.root.add(this.stats)
|
|
this.root.add(this.summary)
|
|
}
|
|
|
|
get visible(): boolean {
|
|
return this.root.visible
|
|
}
|
|
|
|
show(context: SessionContextSnapshot): void {
|
|
this.stats.content = `~${formatTokenCount(context.estimatedSessionTokens)} tokens · ${context.replayMessages} replay · ${context.archivedMessages} archived`
|
|
this.summary.content = context.archivedSummary ?? ""
|
|
this.root.visible = true
|
|
}
|
|
|
|
hide(): void {
|
|
this.root.visible = false
|
|
}
|
|
|
|
resize(terminalHeight: number): void {
|
|
const compact = terminalHeight < 14
|
|
const medium = terminalHeight < 20
|
|
this.summary.visible = !compact
|
|
this.summary.maxHeight = medium ? 2 : 6
|
|
this.root.maxHeight = compact ? 3 : medium ? 5 : 9
|
|
}
|
|
|
|
setTheme(theme: ContextPanelTheme): void {
|
|
this.root.borderColor = theme.border
|
|
this.stats.fg = theme.accent
|
|
this.summary.fg = theme.text
|
|
}
|
|
}
|