Buckets:
| import { createMemo, createSignal } from "solid-js" | |
| import { useLocal } from "../context/local" | |
| import { useSync } from "../context/sync" | |
| import { map, pipe, entries, sortBy } from "remeda" | |
| import { DialogSelect, type DialogSelectRef, type DialogSelectOption } from "../ui/dialog-select" | |
| import { useTheme } from "../context/theme" | |
| import { TextAttributes } from "@opentui/core" | |
| import { useSDK } from "../context/sdk" | |
| function Status(props: { enabled: boolean; loading: boolean }) { | |
| const { theme } = useTheme() | |
| if (props.loading) { | |
| return <span style={{ fg: theme.textMuted }}>⋯ Loading</span> | |
| } | |
| if (props.enabled) { | |
| return <span style={{ fg: theme.success, attributes: TextAttributes.BOLD }}>✓ Enabled</span> | |
| } | |
| return <span style={{ fg: theme.textMuted }}>○ Disabled</span> | |
| } | |
| export function DialogMcp() { | |
| const local = useLocal() | |
| const sync = useSync() | |
| const sdk = useSDK() | |
| const [, setRef] = createSignal<DialogSelectRef<unknown>>() | |
| const [loading, setLoading] = createSignal<string | null>(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: <Status enabled={local.mcp.isEnabled(name)} loading={loadingMcp === name} />, | |
| category: undefined, | |
| })), | |
| ) | |
| }) | |
| const actions = createMemo(() => [ | |
| { | |
| command: "dialog.mcp.toggle", | |
| title: "toggle", | |
| onTrigger: async (option: DialogSelectOption<string>) => { | |
| // 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 ( | |
| <DialogSelect | |
| ref={setRef} | |
| title="MCPs" | |
| options={options()} | |
| actions={actions()} | |
| onSelect={(_option) => { | |
| // Don't close on select, only on escape | |
| }} | |
| /> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 2.64 kB
- Xet hash:
- 7f9993e52885c950d065f5e5ffe0d391b20cff4cb0201a7fbd7a61d7ca2a4e88
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.