mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
The agent drives the session's terminals (shared with the owner's panel) with
tools.terminal({ command, args }): new-window, list-windows, send-keys, read,
capture-pane, kill-window, with waits (quiet, exit, /regex/) and plain-text
output. The terminal host keeps each terminal's last MiB of output and the
agent's read cursor, answers calls with ids, and does keyed calls once, so the
tool is replay-safe. AgentTerminals serves the session's current worker on its
environments; archiving closes a session's terminals. Without code mode the
worker registry installs tool_search once for all deferred tools.
47 lines
1.7 KiB
TypeScript
47 lines
1.7 KiB
TypeScript
// The terminal tool's card in the TUI: the tmux command line, then the output it returned (the last lines; expanded,
|
|
// all of it). The TUI has no terminal panel: the owner watches agent terminals in the web.
|
|
|
|
import { Text } from "@earendil-works/pi-tui";
|
|
import { contribute, defineFacet } from "@p2/app/v1";
|
|
import { getTextOutput, lineText, str, type ToolRenderers, TuiToolRenderers } from "@p2/app/v1/tui";
|
|
|
|
/** Collapsed cards show the last lines of the output; expanded ones all. */
|
|
const PREVIEW_LINES = 8;
|
|
|
|
const terminalRenderers: ToolRenderers = {
|
|
renderCall(args, theme, context) {
|
|
const text = context.lastComponent instanceof Text ? context.lastComponent : new Text("", 0, 0);
|
|
const argv = Array.isArray(args.args) ? args.args.map(str) : [];
|
|
const line = [str(args.command), ...argv].join(" ") || "...";
|
|
text.setText(`${theme.fg("toolTitle", theme.bold("terminal"))} ${theme.fg("accent", lineText(line))}`);
|
|
return text;
|
|
},
|
|
renderResult(result, options, theme, context) {
|
|
const text = context.lastComponent instanceof Text ? context.lastComponent : new Text("", 0, 0);
|
|
const all = getTextOutput(result)
|
|
.split("\n")
|
|
.map((line) => theme.fg(context.isError ? "error" : "toolOutput", lineText(line)));
|
|
const shown = options.expanded ? all : all.slice(-PREVIEW_LINES);
|
|
const hidden = all.length - shown.length;
|
|
text.setText(
|
|
`\n${[
|
|
...(hidden > 0
|
|
? [
|
|
theme.fg(
|
|
"muted",
|
|
`... (${hidden} earlier lines, ${context.ui.keyText("app.tools.expand")} to expand)`,
|
|
),
|
|
]
|
|
: []),
|
|
...shown,
|
|
].join("\n")}`,
|
|
);
|
|
return text;
|
|
},
|
|
};
|
|
|
|
export default defineFacet((host) =>
|
|
contribute(host, "p2.tui-terminals", (self) => {
|
|
self.contribute(TuiToolRenderers, { terminal: terminalRenderers });
|
|
}),
|
|
);
|