// Shared state surface that any admin page can publish to so the assistant // can read live data without scraping the DOM. // // Pages call `useRegisterAdminContext("tenants", { tenants: [...] })` while // mounted; the assistant calls `getAdminContextSnapshot()` each turn to // inject a structured snapshot into the system prompt. import { useEffect } from "react" type Surface = Record export type AdminContextSnapshot = { route: string surfaces: Record } const surfaces = new Map() export function publishAdminSurface(name: string, data: Surface): void { surfaces.set(name, data) if (typeof window !== "undefined") { ;(window as unknown as { __adminContext?: unknown }).__adminContext = getAdminContextSnapshot() } } export function clearAdminSurface(name: string): void { surfaces.delete(name) if (typeof window !== "undefined") { ;(window as unknown as { __adminContext?: unknown }).__adminContext = getAdminContextSnapshot() } } export function getAdminContextSnapshot(): AdminContextSnapshot { const route = typeof window !== "undefined" ? window.location.pathname : "" return { route, surfaces: Object.fromEntries(surfaces.entries()), } } /** * Render a snapshot as a markdown block for the LLM system prompt. * Keeps it compact: route, then one section per surface with JSON. */ export function formatAdminContextForPrompt(snapshot = getAdminContextSnapshot()): string { const sections: string[] = [`Admin context (read-only — for answering factual questions):`] sections.push(`Route: ${snapshot.route || "?"}`) const names = Object.keys(snapshot.surfaces) if (names.length === 0) { sections.push(`Surfaces: (none registered)`) } else { for (const name of names) { const json = safeJson(snapshot.surfaces[name]) sections.push(`Surface "${name}":\n${json}`) } } return sections.join("\n\n") } function safeJson(value: unknown): string { try { const text = JSON.stringify(value, null, 2) if (text.length > 4000) return text.slice(0, 4000) + "\n…(truncated)" return text } catch { return "(unserializable)" } } /** Hook: publish a surface while the component is mounted. */ export function useRegisterAdminContext(name: string, data: Surface): void { useEffect(() => { publishAdminSurface(name, data) return () => clearAdminSurface(name) }, [name, data]) }