Add 5 pi extensions: pi-subagents, pi-crew, rpiv-pi, pi-interactive-shell, pi-intercom

This commit is contained in:
2026-05-08 15:59:25 +10:00
parent d0d1d9b045
commit 31b4110c87
457 changed files with 85157 additions and 0 deletions

View File

@@ -0,0 +1,162 @@
import type { Component } from "@mariozechner/pi-tui";
import { truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
import type { KeybindingsManager, Theme } from "@mariozechner/pi-coding-agent";
import type { SessionInfo } from "../types.js";
function middleTruncate(text: string, maxWidth: number): string {
if (visibleWidth(text) <= maxWidth) {
return text;
}
if (maxWidth <= 3) {
return truncateToWidth(text, maxWidth, "");
}
const chars = [...text];
const targetSideWidth = Math.max(1, Math.floor((maxWidth - 1) / 2));
let left = "";
for (const char of chars) {
if (visibleWidth(left + char) > targetSideWidth) break;
left += char;
}
let right = "";
for (const char of chars.slice().reverse()) {
if (visibleWidth(char + right) > targetSideWidth) break;
right = char + right;
}
return truncateToWidth(`${left}${right}`, maxWidth, "");
}
function shortSessionId(sessionId: string): string {
return sessionId.slice(0, 8);
}
function sessionTitle(session: SessionInfo, options?: { self?: boolean; sameCwd?: boolean }): string {
const name = session.name || "Unnamed session";
const tags = [options?.self ? "self" : undefined, options?.sameCwd ? "same cwd" : undefined]
.filter((tag): tag is string => Boolean(tag));
const suffix = tags.length ? ` [${tags.join(", ")}]` : "";
return `${name} (${shortSessionId(session.id)})${suffix}`;
}
export class SessionListOverlay implements Component {
private theme: Theme;
private keybindings: KeybindingsManager;
private currentSession: SessionInfo;
private done: (result: SessionInfo | undefined) => void;
private sessions: SessionInfo[];
private selectedIndex = 0;
private maxVisible = 8;
constructor(
theme: Theme,
keybindings: KeybindingsManager,
currentSession: SessionInfo,
sessions: SessionInfo[],
done: (result: SessionInfo | undefined) => void,
) {
this.theme = theme;
this.keybindings = keybindings;
this.currentSession = currentSession;
this.sessions = sessions;
this.done = done;
}
private onSessionSelect(sessionId: string): void {
const session = this.sessions.find(s => s.id === sessionId);
if (!session) return;
this.done(session);
}
invalidate(): void {}
handleInput(data: string): void {
if (this.keybindings.matches(data, "tui.select.cancel")) {
this.done(undefined);
return;
}
if (this.sessions.length === 0) {
return;
}
if (this.keybindings.matches(data, "tui.select.up")) {
this.selectedIndex = this.selectedIndex === 0 ? this.sessions.length - 1 : this.selectedIndex - 1;
return;
}
if (this.keybindings.matches(data, "tui.select.down")) {
this.selectedIndex = this.selectedIndex === this.sessions.length - 1 ? 0 : this.selectedIndex + 1;
return;
}
if (this.keybindings.matches(data, "tui.select.confirm")) {
const session = this.sessions[this.selectedIndex];
if (session) {
this.onSessionSelect(session.id);
}
}
}
render(width: number): string[] {
const innerWidth = Math.max(36, Math.min(width - 2, 88));
const contentWidth = Math.max(1, innerWidth - 2);
const footer = `${this.keybindings.getKeys("tui.select.confirm").join("/")}: Message • ${this.keybindings.getKeys("tui.select.cancel").join("/")}: Close`;
const border = (text: string) => this.theme.fg("accent", text);
const row = (text = "") => {
const clipped = truncateToWidth(text, contentWidth, "", true);
return `${border("│")}${clipped}${" ".repeat(Math.max(0, contentWidth - visibleWidth(clipped)))}${border("│")}`;
};
const lines: string[] = [];
lines.push(border(`${"─".repeat(contentWidth)}`));
lines.push(row(this.theme.bold(" Current Session")));
lines.push(border(`${"─".repeat(contentWidth)}`));
lines.push(row());
lines.push(row(` ${this.theme.fg("dim", sessionTitle(this.currentSession, { self: true }))}`));
lines.push(row(` ${this.theme.fg("dim", `${middleTruncate(this.currentSession.cwd, Math.max(8, contentWidth - 4))}${this.currentSession.model}`)}`));
lines.push(row());
lines.push(border(`${"─".repeat(contentWidth)}`));
lines.push(row(this.theme.bold(" Other Sessions")));
lines.push(row());
if (this.sessions.length === 0) {
lines.push(row(this.theme.fg("dim", " No other intercom-connected sessions")));
} else {
const startIndex = Math.max(
0,
Math.min(this.selectedIndex - Math.floor(this.maxVisible / 2), this.sessions.length - this.maxVisible),
);
const endIndex = Math.min(startIndex + this.maxVisible, this.sessions.length);
for (let index = startIndex; index < endIndex; index += 1) {
const session = this.sessions[index];
const isSelected = index === this.selectedIndex;
const sameCwd = session.cwd === this.currentSession.cwd;
const prefix = isSelected ? this.theme.fg("accent", "→ ") : " ";
const title = sessionTitle(session, { sameCwd });
const pathText = `${middleTruncate(session.cwd, Math.max(8, contentWidth - 4))}${session.model}`;
lines.push(row(`${prefix}${isSelected ? this.theme.fg("accent", title) : title}`));
lines.push(row(` ${this.theme.fg("dim", pathText)}`));
if (index < endIndex - 1) {
lines.push(row());
}
}
if (startIndex > 0 || endIndex < this.sessions.length) {
lines.push(row());
lines.push(row(this.theme.fg("dim", ` ${this.selectedIndex + 1}/${this.sessions.length}`)));
}
}
lines.push(row());
lines.push(border(`${"─".repeat(contentWidth)}`));
lines.push(row(this.theme.fg("dim", ` ${footer}`)));
lines.push(border(`${"─".repeat(contentWidth)}`));
return lines;
}
}