91 lines
2.5 KiB
TypeScript
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");
|
|
}
|
|
}
|