import { copyToClipboard, type ExtensionAPI, } from "@earendil-works/pi-coding-agent"; function textFromContent(content: unknown) { if (typeof content === "string") return content; if (!Array.isArray(content)) return ""; return content .map((block) => { if (!block || typeof block !== "object") return ""; if (!("type" in block)) return ""; if ( block.type === "text" && "text" in block && typeof block.text === "string" ) { return block.text; } if (block.type === "image") return "[image]"; return ""; }) .filter(Boolean) .join("\n"); } export default function (pi: ExtensionAPI) { pi.registerCommand("copy-all", { description: "Copy the current branch's visible user and assistant conversation to the clipboard", handler: async (_args, ctx) => { await ctx.waitForIdle(); const sections = ctx.sessionManager .getBranch() .filter((entry) => entry.type === "message") .map((entry) => entry.message) .filter( (message) => message.role === "user" || message.role === "assistant", ) .map((message) => ({ role: message.role, content: textFromContent(message.content).trim(), })) .filter(({ content }) => content) .map(({ role, content }) => `${role.toUpperCase()}:\n${content}`); if (sections.length === 0) { ctx.ui.notify("No user or assistant messages to copy", "info"); return; } const conversation = sections.join("\n\n---\n\n"); await copyToClipboard(conversation); ctx.ui.notify( `Copied ${sections.length} visible messages (${conversation.length.toLocaleString()} characters) from the current branch`, "info", ); }, }); }