/** * Extract a text handoff of the parent session branch for planner context. * Mirrors pi-subagents buildParentContext shape so hosts that ignore * inheritContext still get conversation history in the planner prompt. */ export type BranchEntry = { type?: string; message?: { role?: string; content?: unknown; }; summary?: string; }; export type SessionBranchSource = { sessionManager?: { /** Real Pi returns session entries; typed loosely for ExtensionContext compatibility. */ getBranch?: () => unknown; }; }; function extractText(content: unknown): string { if (typeof content === "string") return content; if (!Array.isArray(content)) return ""; return content .filter((c: { type?: string }) => c?.type === "text") .map((c: { text?: string }) => c.text ?? "") .join("\n"); } /** * Build a compact parent-conversation handoff from ExtensionContext-like objects. * Returns undefined when no usable history is present. */ export function extractParentContextText( ctx: SessionBranchSource | null | undefined, opts?: { maxChars?: number }, ): string | undefined { try { const raw = ctx?.sessionManager?.getBranch?.(); if (!Array.isArray(raw) || raw.length === 0) return undefined; const entries = raw as BranchEntry[]; const parts: string[] = []; for (const entry of entries) { if (entry.type === "message" && entry.message) { const msg = entry.message; if (msg.role === "user") { const text = extractText(msg.content).trim(); if (text) parts.push(`[User]: ${text}`); } else if (msg.role === "assistant") { const text = extractText(msg.content).trim(); if (text) parts.push(`[Assistant]: ${text}`); } // Skip toolResult — too verbose for planner handoff } else if (entry.type === "compaction" && entry.summary?.trim()) { parts.push(`[Summary]: ${entry.summary.trim()}`); } } if (parts.length === 0) return undefined; let text = parts.join("\n\n"); const max = opts?.maxChars ?? 80_000; if (text.length > max) { text = `…[truncated]\n\n${text.slice(text.length - max)}`; } return text; } catch { // Best-effort handoff — never fail goal start over transcript extract. return undefined; } }