UNPKG

@fusedashlabs/ui9000-workspace

Version:

UI9000 workspace MCP. One tool, show_workspace, draws a chart from your table. Set TYPESAFE_API_KEY to let Jev choose the chart.

49 lines (48 loc) • 1.74 kB
import { validateSpec } from '../validate/validate-spec.js'; /** * Validate then mount. Hostile specs never reach load() or the host. * Mount is a catalog loader on a known id — not host markup or element registry APIs. */ export async function interpretWorkspace(toolResult, catalog, load, host) { const raw = extractSpec(toolResult); if (raw === undefined) { return { mounted: false, code: 'invalid_result', reason: 'tool result has no workspace spec', }; } const validated = validateSpec(raw, catalog); if (!validated.ok) { return { mounted: false, code: validated.code, reason: validated.reason }; } const mounter = await load(validated.spec.component); if (!mounter || typeof mounter.mount !== 'function') { return { mounted: false, code: 'unknown_component', reason: `no mounter registered for "${validated.spec.component}"`, }; } host.replaceChildren(); await mounter.mount(host, validated.spec); return { mounted: true, spec: validated.spec }; } function extractSpec(toolResult) { if (!isPlain(toolResult)) return undefined; if ('spec' in toolResult) return toolResult.spec; if (isPlain(toolResult.structuredContent) && 'spec' in toolResult.structuredContent) { return toolResult.structuredContent.spec; } if (isPlain(toolResult._meta) && 'spec' in toolResult._meta) { return toolResult._meta.spec; } if (typeof toolResult.component === 'string') return toolResult; return undefined; } function isPlain(value) { return value !== null && typeof value === 'object' && !Array.isArray(value); }