import { createMemo, createSignal } from "solid-js" import { useLocal } from "@tui/context/local" import { useSync } from "@tui/context/sync" import { map, pipe, entries, sortBy } from "remeda" import { DialogSelect, type DialogSelectRef, type DialogSelectOption } from "@tui/ui/dialog-select" import { useTheme } from "../context/theme" import { Keybind } from "@/util/keybind" import { TextAttributes } from "@opentui/core" import { useSDK } from "@tui/context/sdk" function Status(props: { enabled: boolean; loading: boolean }) { const { theme } = useTheme() if (props.loading) { return ⋯ Loading } if (props.enabled) { return ✓ Enabled } return ○ Disabled } export function DialogMcp() { const local = useLocal() const sync = useSync() const sdk = useSDK() const [, setRef] = createSignal>() const [loading, setLoading] = createSignal(null) const options = createMemo(() => { // Track sync data and loading state to trigger re-render when they change const mcpData = sync.data.mcp const loadingMcp = loading() return pipe( mcpData ?? {}, entries(), sortBy(([name]) => name), map(([name, status]) => ({ value: name, title: name, description: status.status === "failed" ? "failed" : status.status, footer: , category: undefined, })), ) }) const keybinds = createMemo(() => [ { keybind: Keybind.parse("space")[0], title: "toggle", onTrigger: async (option: DialogSelectOption) => { // Prevent toggling while an operation is already in progress if (loading() !== null) return setLoading(option.value) try { await local.mcp.toggle(option.value) // Refresh MCP status from server const status = await sdk.client.mcp.status() if (status.data) { sync.set("mcp", status.data) } else { console.error("Failed to refresh MCP status: no data returned") } } catch (error) { console.error("Failed to toggle MCP:", error) } finally { setLoading(null) } }, }, ]) return ( { // Don't close on select, only on escape }} /> ) }