Files
oh-my-pi/packages/coding-agent/src/modes/components/skill-message.ts
T
2026-02-10 07:39:39 +01:00

91 lines
2.5 KiB
TypeScript

import type { TextContent } from "@oh-my-pi/pi-ai";
import type { Component } from "@oh-my-pi/pi-tui";
import { Box, Container, Markdown, Spacer, Text } from "@oh-my-pi/pi-tui";
import { getMarkdownTheme, theme } from "../../modes/theme/theme";
import type { CustomMessage, SkillPromptDetails } from "../../session/messages";
export class SkillMessageComponent extends Container {
#box: Box;
#contentComponent?: Component;
#expanded = false;
constructor(private readonly message: CustomMessage<SkillPromptDetails>) {
super();
this.addChild(new Spacer(1));
this.#box = new Box(1, 1, t => theme.bg("customMessageBg", t));
this.#rebuild();
}
setExpanded(expanded: boolean): void {
if (this.#expanded !== expanded) {
this.#expanded = expanded;
this.#rebuild();
}
}
override invalidate(): void {
super.invalidate();
this.#rebuild();
}
#rebuild(): void {
if (this.#contentComponent) {
this.removeChild(this.#contentComponent);
this.#contentComponent = undefined;
}
this.removeChild(this.#box);
this.addChild(this.#box);
this.#box.clear();
const label = theme.fg("customMessageLabel", theme.bold("[skill]"));
this.#box.addChild(new Text(label, 0, 0));
this.#box.addChild(new Spacer(1));
const details = this.message.details;
const args = details?.args?.trim();
const infoLines = [
`Skill: ${details?.name ?? "unknown"}`,
args ? `Args: ${args}` : undefined,
details?.path ? `Path: ${details.path}` : undefined,
typeof details?.lineCount === "number" ? `Prompt: ${details.lineCount} lines` : undefined,
].filter((line): line is string => Boolean(line));
this.#box.addChild(
new Markdown(infoLines.join("\n"), 0, 0, getMarkdownTheme(), {
color: (value: string) => theme.fg("customMessageText", value),
}),
);
if (!this.#expanded) {
return;
}
const text = this.#extractText();
if (!text) {
return;
}
this.#box.addChild(new Spacer(1));
const promptHeader = theme.fg("customMessageLabel", theme.bold("Prompt"));
this.#box.addChild(new Text(promptHeader, 0, 0));
this.#box.addChild(new Spacer(1));
this.#contentComponent = new Markdown(text, 0, 0, getMarkdownTheme(), {
color: (value: string) => theme.fg("customMessageText", value),
});
this.#box.addChild(this.#contentComponent);
}
#extractText(): string {
if (typeof this.message.content === "string") {
return this.message.content;
}
return this.message.content
.filter((c): c is TextContent => c.type === "text")
.map(c => c.text)
.join("\n");
}
}