/** * References attached from the overview sidebar so the user can point Vibn at a * PRD section or discovery phase. Sent with chat; not shown in stored user text. */ export type ChatContextRef = | { kind: "section"; label: string; phaseId: string | null } | { kind: "phase"; label: string; phaseId: string } | { kind: "app"; label: string; path: string }; export function contextRefKey(r: ChatContextRef): string { if (r.kind === "section") return `s:${r.label}`; if (r.kind === "phase") return `p:${r.phaseId}`; return `a:${r.path}`; } export function augmentAtlasMessage( message: string, refs: ChatContextRef[] | null | undefined ): string { const list = refs?.filter(Boolean) ?? []; if (!list.length) return message; const lines = list.map(r => r.kind === "section" ? `- PRD section: "${r.label}"${r.phaseId ? ` (discovery phase: ${r.phaseId})` : ""}` : r.kind === "phase" ? `- Discovery phase: "${r.label}" (id: ${r.phaseId})` : `- Monorepo workspace / package: "${r.label}" (path: ${r.path})` ); return `[The user attached these project references for this message. Prioritize them in your reply:\n${lines.join("\n")}\n]\n\n${message}`; } export function parseContextRefs(raw: unknown): ChatContextRef[] { if (!Array.isArray(raw)) return []; const out: ChatContextRef[] = []; for (const item of raw) { if (!item || typeof item !== "object") continue; const o = item as Record; if (o.kind === "section" && typeof o.label === "string") { const phaseId: string | null = o.phaseId === null ? null : typeof o.phaseId === "string" ? o.phaseId : null; out.push({ kind: "section", label: o.label, phaseId }); } else if (o.kind === "phase" && typeof o.label === "string" && typeof o.phaseId === "string") { out.push({ kind: "phase", label: o.label, phaseId: o.phaseId }); } else if (o.kind === "app" && typeof o.label === "string" && typeof o.path === "string") { out.push({ kind: "app", label: o.label, path: o.path }); } } return out; }