import type { TuiPluginApi, TuiSlotContext, TuiSlotMap, TuiSlotProps } from "@opencode-ai/plugin/tui" import { createSlot, createSolidSlotRegistry, type JSX, type SolidPlugin } from "@opentui/solid" import { createSignal } from "solid-js" import { isRecord } from "../util/record" type RuntimeSlotMap = TuiSlotMap> type SlotView = (props: TuiSlotProps) => JSX.Element | null export type HostSlotPlugin = {}> = SolidPlugin, TuiSlotContext> export type HostPluginApi = TuiPluginApi export type HostSlots = { register: { (plugin: HostSlotPlugin): () => void >(plugin: HostSlotPlugin): () => void } dispose: () => void } function isHostSlotPlugin(value: unknown): value is HostSlotPlugin> { if (!isRecord(value)) return false if (typeof value.id !== "string") return false return isRecord(value.slots) } export function createSlots() { const empty: SlotView = () => null const [view, setView] = createSignal(empty) const Slot: SlotView = (props) => view()(props) return { Slot, setup(api: HostPluginApi): HostSlots { const registry = createSolidSlotRegistry( api.renderer, { theme: api.theme }, { onPluginError(event) { console.error("[tui.slot] plugin error", { plugin: event.pluginId, slot: event.slot, phase: event.phase, source: event.source, message: event.error.message, }) }, }, ) const slot = createSlot(registry) setView(() => (props: TuiSlotProps) => slot(props)) return { register(plugin: HostSlotPlugin) { if (!isHostSlotPlugin(plugin)) return () => {} return registry.register(plugin) }, dispose() { setView(() => empty) }, } }, clear() { setView(() => empty) }, } }