@seed-ship/mcp-ui-solid 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/components/ActionRenderer.cjs +34 -0
  3. package/dist/components/ActionRenderer.cjs.map +1 -0
  4. package/dist/components/ActionRenderer.js +34 -0
  5. package/dist/components/ActionRenderer.js.map +1 -0
  6. package/dist/components/ArtifactRenderer.cjs +37 -0
  7. package/dist/components/ArtifactRenderer.cjs.map +1 -0
  8. package/dist/components/ArtifactRenderer.js +37 -0
  9. package/dist/components/ArtifactRenderer.js.map +1 -0
  10. package/dist/components/CarouselRenderer.cjs +58 -0
  11. package/dist/components/CarouselRenderer.cjs.map +1 -0
  12. package/dist/components/CarouselRenderer.js +58 -0
  13. package/dist/components/CarouselRenderer.js.map +1 -0
  14. package/dist/components/UIResourceRenderer.cjs +238 -160
  15. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  16. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  17. package/dist/components/UIResourceRenderer.js +238 -160
  18. package/dist/components/UIResourceRenderer.js.map +1 -1
  19. package/dist/components/index.d.ts +10 -0
  20. package/dist/components/index.d.ts.map +1 -1
  21. package/dist/components.cjs +10 -0
  22. package/dist/components.cjs.map +1 -1
  23. package/dist/components.d.ts +10 -0
  24. package/dist/components.js +10 -0
  25. package/dist/components.js.map +1 -1
  26. package/dist/hooks/useStreamingUI.cjs +4 -1
  27. package/dist/hooks/useStreamingUI.cjs.map +1 -1
  28. package/dist/hooks/useStreamingUI.d.ts +2 -0
  29. package/dist/hooks/useStreamingUI.d.ts.map +1 -1
  30. package/dist/hooks/useStreamingUI.js +4 -1
  31. package/dist/hooks/useStreamingUI.js.map +1 -1
  32. package/dist/index.cjs +4 -0
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +4 -0
  35. package/dist/index.js.map +1 -1
  36. package/dist/services/component-registry.cjs +211 -1
  37. package/dist/services/component-registry.cjs.map +1 -1
  38. package/dist/services/component-registry.d.ts +25 -0
  39. package/dist/services/component-registry.d.ts.map +1 -1
  40. package/dist/services/component-registry.js +211 -1
  41. package/dist/services/component-registry.js.map +1 -1
  42. package/package.json +1 -1
  43. package/src/components/UIResourceRenderer.tsx +79 -3
  44. package/src/components/index.ts +16 -0
  45. package/src/hooks/useStreamingUI.ts +7 -1
  46. package/src/services/component-registry.ts +239 -0
  47. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useStreamingUI.js","sources":["../../src/hooks/useStreamingUI.ts"],"sourcesContent":["/**\n * useStreamingUI Hook - Phase 2\n *\n * Client-side hook for consuming the streaming generative UI endpoint.\n * Handles SSE connection, component buffering, reordering, and error handling.\n *\n * Features:\n * - SSE connection with automatic reconnection\n * - Component buffering and reordering by sequenceId\n * - Progress tracking and loading states\n * - Error handling with recovery attempts\n * - Cleanup on unmount\n *\n * Usage:\n * ```tsx\n * const { components, isLoading, error, progress } = useStreamingUI({\n * query: 'Show me revenue trends',\n * spaceIds: ['uuid1', 'uuid2'],\n * onComplete: (metadata) => console.log('Done!', metadata),\n * })\n * ```\n */\n\nimport { createSignal, onCleanup } from 'solid-js'\nimport type { UIComponent } from '../types'\nimport { createLogger } from '../utils/logger'\n\nconst logger = createLogger('useStreamingUI')\n\n// SSR detection without importing solid-js/web (which might cause bundler issues)\nconst isServer = typeof window === 'undefined'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseStreamingUIOptions {\n query: string\n spaceIds?: string[]\n sessionId?: string\n options?: {\n useCache?: boolean\n useLLM?: boolean\n maxComponents?: number\n preferredComponents?: Array<'chart' | 'table' | 'metric' | 'text'>\n }\n onComplete?: (metadata: CompleteMetadata) => void\n onError?: (error: StreamError) => void\n onComponentReceived?: (component: UIComponent) => void\n}\n\nexport interface StreamingUIState {\n components: UIComponent[]\n isLoading: boolean\n isStreaming: boolean\n error: StreamError | null\n progress: StreamProgress\n metadata: CompleteMetadata | null\n}\n\nexport interface StreamProgress {\n receivedCount: number\n totalCount: number | null\n message: string\n timestamp: string\n}\n\nexport interface CompleteMetadata {\n layoutId: string\n componentsCount: number\n executionTimeMs: number\n firstTokenMs: number\n provider: 'groq' | 'mock'\n model: string\n tokensUsed?: number\n costUSD?: number\n cached: boolean\n}\n\nexport interface StreamError {\n error: string\n message: string\n componentId?: string\n recoverable: boolean\n}\n\ninterface ComponentBuffer {\n [sequenceId: number]: {\n component: UIComponent\n position: { colStart: number; colSpan: number; rowStart?: number; rowSpan?: number }\n }\n}\n\n// ============================================================================\n// SSE Event Types (must match server)\n// ============================================================================\n\ntype SSEEventType = 'status' | 'component-start' | 'component' | 'complete' | 'error'\n\ninterface StatusEvent {\n message: string\n timestamp: string\n totalComponents?: number\n}\n\ninterface ComponentStartEvent {\n componentId: string\n type: 'chart' | 'table' | 'metric' | 'text'\n sequenceId: number\n position: { colStart: number; colSpan: number }\n}\n\ninterface ComponentEvent {\n componentId: string\n sequenceId: number\n component: UIComponent\n position: { colStart: number; colSpan: number; rowStart?: number; rowSpan?: number }\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\nexport function useStreamingUI(options: UseStreamingUIOptions) {\n // State\n const [components, setComponents] = createSignal<UIComponent[]>([])\n const [isLoading, setIsLoading] = createSignal(false)\n const [isStreaming, setIsStreaming] = createSignal(false)\n const [error, setError] = createSignal<StreamError | null>(null)\n const [progress, setProgress] = createSignal<StreamProgress>({\n receivedCount: 0,\n totalCount: null,\n message: 'Initializing...',\n timestamp: new Date().toISOString(),\n })\n const [metadata, setMetadata] = createSignal<CompleteMetadata | null>(null)\n\n // Component buffer for reordering\n let componentBuffer: ComponentBuffer = {}\n let nextSequenceId = 0\n let eventSource: EventSource | null = null\n let reconnectAttempts = 0\n const maxReconnectAttempts = 3\n\n /**\n * Flush components from buffer in sequence order\n */\n const flushBuffer = () => {\n const flushed: UIComponent[] = []\n\n while (componentBuffer[nextSequenceId]) {\n const { component } = componentBuffer[nextSequenceId]\n flushed.push(component)\n delete componentBuffer[nextSequenceId]\n nextSequenceId++\n }\n\n if (flushed.length > 0) {\n setComponents((prev) => [...prev, ...flushed])\n\n setProgress((prev) => ({\n ...prev,\n receivedCount: prev.receivedCount + flushed.length,\n }))\n\n logger.debug('Flushed components from buffer', {\n count: flushed.length,\n nextSequenceId,\n })\n }\n }\n\n /**\n * Handle SSE status event\n */\n const handleStatusEvent = (data: StatusEvent) => {\n logger.debug('Status event received', data as unknown as Record<string, unknown>)\n\n setProgress({\n receivedCount: progress().receivedCount,\n totalCount: data.totalComponents ?? progress().totalCount,\n message: data.message,\n timestamp: data.timestamp,\n })\n }\n\n /**\n * Handle SSE component-start event\n */\n const handleComponentStartEvent = (data: ComponentStartEvent) => {\n logger.debug('Component-start event received', data as unknown as Record<string, unknown>)\n\n setProgress((prev) => ({\n ...prev,\n message: `Loading ${data.type} component...`,\n timestamp: new Date().toISOString(),\n }))\n }\n\n /**\n * Handle SSE component event\n */\n const handleComponentEvent = (data: ComponentEvent) => {\n logger.debug('Component event received', {\n componentId: data.componentId,\n sequenceId: data.sequenceId,\n })\n\n // Add to buffer\n componentBuffer[data.sequenceId] = {\n component: data.component,\n position: data.position,\n }\n\n // Flush buffer in sequence\n flushBuffer()\n\n // Notify callback\n if (options.onComponentReceived) {\n options.onComponentReceived(data.component)\n }\n }\n\n /**\n * Handle SSE complete event\n */\n const handleCompleteEvent = (data: CompleteMetadata) => {\n logger.info('Stream completed', data as unknown as Record<string, unknown>)\n\n setIsStreaming(false)\n setIsLoading(false)\n setMetadata(data)\n\n // Flush any remaining buffered components\n flushBuffer()\n\n setProgress((prev) => ({\n ...prev,\n message: 'Dashboard loaded',\n timestamp: new Date().toISOString(),\n }))\n\n // Notify callback\n if (options.onComplete) {\n options.onComplete(data)\n }\n }\n\n /**\n * Handle SSE error event\n */\n const handleErrorEvent = (data: StreamError) => {\n logger.error('Stream error received', data as unknown as Record<string, unknown>)\n\n setError(data)\n setIsStreaming(false)\n setIsLoading(false)\n\n setProgress((prev) => ({\n ...prev,\n message: `Error: ${data.message}`,\n timestamp: new Date().toISOString(),\n }))\n\n // Notify callback\n if (options.onError) {\n options.onError(data)\n }\n\n // Try to reconnect if recoverable\n if (data.recoverable && reconnectAttempts < maxReconnectAttempts) {\n reconnectAttempts++\n logger.warn('Attempting to reconnect', { attempt: reconnectAttempts })\n setTimeout(() => startStreaming(), 1000 * reconnectAttempts)\n }\n }\n\n /**\n * Parse SSE event\n */\n const parseSSEEvent = (event: MessageEvent, eventType: SSEEventType) => {\n try {\n const data = JSON.parse(event.data)\n\n switch (eventType) {\n case 'status':\n handleStatusEvent(data as StatusEvent)\n break\n case 'component-start':\n handleComponentStartEvent(data as ComponentStartEvent)\n break\n case 'component':\n handleComponentEvent(data as ComponentEvent)\n break\n case 'complete':\n handleCompleteEvent(data as CompleteMetadata)\n break\n case 'error':\n handleErrorEvent(data as StreamError)\n break\n default:\n logger.warn('Unknown SSE event type', { eventType })\n }\n } catch (error) {\n logger.error('Failed to parse SSE event', {\n error: error instanceof Error ? error.message : String(error),\n eventType,\n })\n }\n }\n\n /**\n * Start SSE streaming\n */\n const startStreaming = () => {\n // SSR Guard: Prevent execution on server-side (Node.js environment)\n // fetch() and ReadableStream APIs are only available in browsers\n if (isServer) {\n logger.warn('startStreaming called on server-side - skipping')\n setError({\n error: 'ssr',\n message: 'Streaming UI cannot start on server-side',\n recoverable: false,\n })\n setIsLoading(false)\n return\n }\n\n // Reset state\n setComponents([])\n setError(null)\n setIsLoading(true)\n setIsStreaming(true)\n componentBuffer = {}\n nextSequenceId = 0\n\n setProgress({\n receivedCount: 0,\n totalCount: null,\n message: 'Connecting to server...',\n timestamp: new Date().toISOString(),\n })\n\n logger.info('Starting SSE stream', {\n query: options.query,\n spaceIds: options.spaceIds,\n })\n\n // Build request body\n const requestBody = {\n query: options.query,\n spaceIds: options.spaceIds,\n sessionId: options.sessionId,\n options: options.options,\n }\n\n // Create EventSource (SSE connection)\n // Note: EventSource doesn't support POST, so we need to use fetch + ReadableStream\n fetch('/api/mcp/generative-ui-stream', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n })\n .then(async (response) => {\n if (!response.ok) {\n const errorData = await response.json()\n throw new Error(errorData.message || 'Stream request failed')\n }\n\n if (!response.body) {\n throw new Error('Response body is null')\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n\n let buffer = ''\n\n // Read stream\n const readChunk = async (): Promise<void> => {\n const { done, value } = await reader.read()\n\n if (done) {\n logger.info('Stream ended')\n return\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n // Process SSE messages\n const lines = buffer.split('\\n')\n buffer = lines.pop() || '' // Keep incomplete line in buffer\n\n let currentEvent: SSEEventType | null = null\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7) as SSEEventType\n } else if (line.startsWith('data: ') && currentEvent) {\n const data = line.slice(6)\n parseSSEEvent({ data } as MessageEvent, currentEvent)\n currentEvent = null\n }\n }\n\n // Continue reading\n return readChunk()\n }\n\n await readChunk()\n })\n .catch((err) => {\n logger.error('Stream fetch failed', {\n error: err instanceof Error ? err.message : String(err),\n })\n\n handleErrorEvent({\n error: 'Stream connection failed',\n message: err instanceof Error ? err.message : 'Unknown error',\n recoverable: true,\n })\n })\n }\n\n /**\n * Stop streaming\n */\n const stopStreaming = () => {\n if (eventSource) {\n eventSource.close()\n eventSource = null\n }\n\n setIsStreaming(false)\n setIsLoading(false)\n\n logger.info('Streaming stopped')\n }\n\n /**\n * Cleanup on unmount\n */\n onCleanup(() => {\n stopStreaming()\n })\n\n // Auto-start streaming\n startStreaming()\n\n // Return state accessors and controls\n return {\n components,\n isLoading,\n isStreaming,\n error,\n progress,\n metadata,\n startStreaming,\n stopStreaming,\n }\n}\n"],"names":["error"],"mappings":"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"}
1
+ {"version":3,"file":"useStreamingUI.js","sources":["../../src/hooks/useStreamingUI.ts"],"sourcesContent":["/**\n * useStreamingUI Hook - Phase 2\n *\n * Client-side hook for consuming the streaming generative UI endpoint.\n * Handles SSE connection, component buffering, reordering, and error handling.\n *\n * Features:\n * - SSE connection with automatic reconnection\n * - Component buffering and reordering by sequenceId\n * - Progress tracking and loading states\n * - Error handling with recovery attempts\n * - Cleanup on unmount\n *\n * Usage:\n * ```tsx\n * const { components, isLoading, error, progress } = useStreamingUI({\n * query: 'Show me revenue trends',\n * spaceIds: ['uuid1', 'uuid2'],\n * onComplete: (metadata) => console.log('Done!', metadata),\n * })\n * ```\n */\n\nimport { createSignal, onCleanup } from 'solid-js'\nimport type { UIComponent } from '../types'\nimport { createLogger } from '../utils/logger'\n\nconst logger = createLogger('useStreamingUI')\n\n// SSR detection without importing solid-js/web (which might cause bundler issues)\nconst isServer = typeof window === 'undefined'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface UseStreamingUIOptions {\n query: string\n spaceIds?: string[]\n sessionId?: string\n options?: {\n useCache?: boolean\n useLLM?: boolean\n maxComponents?: number\n preferredComponents?: Array<'chart' | 'table' | 'metric' | 'text'>\n }\n onComplete?: (metadata: CompleteMetadata) => void\n onError?: (error: StreamError) => void\n onComponentReceived?: (component: UIComponent) => void\n}\n\nexport interface StreamingUIState {\n components: UIComponent[]\n isLoading: boolean\n isStreaming: boolean\n error: StreamError | null\n progress: StreamProgress\n metadata: CompleteMetadata | null\n}\n\nexport interface StreamProgress {\n receivedCount: number\n totalCount: number | null\n message: string\n timestamp: string\n}\n\nexport interface CompleteMetadata {\n layoutId: string\n componentsCount: number\n executionTimeMs: number\n /** Alias for executionTimeMs (for compatibility with FooterRenderer) */\n executionTime?: number\n firstTokenMs: number\n provider: 'groq' | 'mock'\n model: string\n tokensUsed?: number\n costUSD?: number\n cached: boolean\n}\n\nexport interface StreamError {\n error: string\n message: string\n componentId?: string\n recoverable: boolean\n}\n\ninterface ComponentBuffer {\n [sequenceId: number]: {\n component: UIComponent\n position: { colStart: number; colSpan: number; rowStart?: number; rowSpan?: number }\n }\n}\n\n// ============================================================================\n// SSE Event Types (must match server)\n// ============================================================================\n\ntype SSEEventType = 'status' | 'component-start' | 'component' | 'complete' | 'error'\n\ninterface StatusEvent {\n message: string\n timestamp: string\n totalComponents?: number\n}\n\ninterface ComponentStartEvent {\n componentId: string\n type: 'chart' | 'table' | 'metric' | 'text'\n sequenceId: number\n position: { colStart: number; colSpan: number }\n}\n\ninterface ComponentEvent {\n componentId: string\n sequenceId: number\n component: UIComponent\n position: { colStart: number; colSpan: number; rowStart?: number; rowSpan?: number }\n}\n\n// ============================================================================\n// Hook Implementation\n// ============================================================================\n\nexport function useStreamingUI(options: UseStreamingUIOptions) {\n // State\n const [components, setComponents] = createSignal<UIComponent[]>([])\n const [isLoading, setIsLoading] = createSignal(false)\n const [isStreaming, setIsStreaming] = createSignal(false)\n const [error, setError] = createSignal<StreamError | null>(null)\n const [progress, setProgress] = createSignal<StreamProgress>({\n receivedCount: 0,\n totalCount: null,\n message: 'Initializing...',\n timestamp: new Date().toISOString(),\n })\n const [metadata, setMetadata] = createSignal<CompleteMetadata | null>(null)\n\n // Component buffer for reordering\n let componentBuffer: ComponentBuffer = {}\n let nextSequenceId = 0\n let eventSource: EventSource | null = null\n let reconnectAttempts = 0\n const maxReconnectAttempts = 3\n\n /**\n * Flush components from buffer in sequence order\n */\n const flushBuffer = () => {\n const flushed: UIComponent[] = []\n\n while (componentBuffer[nextSequenceId]) {\n const { component } = componentBuffer[nextSequenceId]\n flushed.push(component)\n delete componentBuffer[nextSequenceId]\n nextSequenceId++\n }\n\n if (flushed.length > 0) {\n setComponents((prev) => [...prev, ...flushed])\n\n setProgress((prev) => ({\n ...prev,\n receivedCount: prev.receivedCount + flushed.length,\n }))\n\n logger.debug('Flushed components from buffer', {\n count: flushed.length,\n nextSequenceId,\n })\n }\n }\n\n /**\n * Handle SSE status event\n */\n const handleStatusEvent = (data: StatusEvent) => {\n logger.debug('Status event received', data as unknown as Record<string, unknown>)\n\n setProgress({\n receivedCount: progress().receivedCount,\n totalCount: data.totalComponents ?? progress().totalCount,\n message: data.message,\n timestamp: data.timestamp,\n })\n }\n\n /**\n * Handle SSE component-start event\n */\n const handleComponentStartEvent = (data: ComponentStartEvent) => {\n logger.debug('Component-start event received', data as unknown as Record<string, unknown>)\n\n setProgress((prev) => ({\n ...prev,\n message: `Loading ${data.type} component...`,\n timestamp: new Date().toISOString(),\n }))\n }\n\n /**\n * Handle SSE component event\n */\n const handleComponentEvent = (data: ComponentEvent) => {\n logger.debug('Component event received', {\n componentId: data.componentId,\n sequenceId: data.sequenceId,\n })\n\n // Add to buffer\n componentBuffer[data.sequenceId] = {\n component: data.component,\n position: data.position,\n }\n\n // Flush buffer in sequence\n flushBuffer()\n\n // Notify callback\n if (options.onComponentReceived) {\n options.onComponentReceived(data.component)\n }\n }\n\n /**\n * Handle SSE complete event\n */\n const handleCompleteEvent = (data: CompleteMetadata) => {\n logger.info('Stream completed', data as unknown as Record<string, unknown>)\n\n setIsStreaming(false)\n setIsLoading(false)\n // Normalize executionTimeMs to executionTime for compatibility with FooterRenderer\n setMetadata({\n ...data,\n executionTime: data.executionTimeMs || data.executionTime,\n })\n\n // Flush any remaining buffered components\n flushBuffer()\n\n setProgress((prev) => ({\n ...prev,\n message: 'Dashboard loaded',\n timestamp: new Date().toISOString(),\n }))\n\n // Notify callback\n if (options.onComplete) {\n options.onComplete(data)\n }\n }\n\n /**\n * Handle SSE error event\n */\n const handleErrorEvent = (data: StreamError) => {\n logger.error('Stream error received', data as unknown as Record<string, unknown>)\n\n setError(data)\n setIsStreaming(false)\n setIsLoading(false)\n\n setProgress((prev) => ({\n ...prev,\n message: `Error: ${data.message}`,\n timestamp: new Date().toISOString(),\n }))\n\n // Notify callback\n if (options.onError) {\n options.onError(data)\n }\n\n // Try to reconnect if recoverable\n if (data.recoverable && reconnectAttempts < maxReconnectAttempts) {\n reconnectAttempts++\n logger.warn('Attempting to reconnect', { attempt: reconnectAttempts })\n setTimeout(() => startStreaming(), 1000 * reconnectAttempts)\n }\n }\n\n /**\n * Parse SSE event\n */\n const parseSSEEvent = (event: MessageEvent, eventType: SSEEventType) => {\n try {\n const data = JSON.parse(event.data)\n\n switch (eventType) {\n case 'status':\n handleStatusEvent(data as StatusEvent)\n break\n case 'component-start':\n handleComponentStartEvent(data as ComponentStartEvent)\n break\n case 'component':\n handleComponentEvent(data as ComponentEvent)\n break\n case 'complete':\n handleCompleteEvent(data as CompleteMetadata)\n break\n case 'error':\n handleErrorEvent(data as StreamError)\n break\n default:\n logger.warn('Unknown SSE event type', { eventType })\n }\n } catch (error) {\n logger.error('Failed to parse SSE event', {\n error: error instanceof Error ? error.message : String(error),\n eventType,\n })\n }\n }\n\n /**\n * Start SSE streaming\n */\n const startStreaming = () => {\n // SSR Guard: Prevent execution on server-side (Node.js environment)\n // fetch() and ReadableStream APIs are only available in browsers\n if (isServer) {\n logger.warn('startStreaming called on server-side - skipping')\n setError({\n error: 'ssr',\n message: 'Streaming UI cannot start on server-side',\n recoverable: false,\n })\n setIsLoading(false)\n return\n }\n\n // Reset state\n setComponents([])\n setError(null)\n setIsLoading(true)\n setIsStreaming(true)\n componentBuffer = {}\n nextSequenceId = 0\n\n setProgress({\n receivedCount: 0,\n totalCount: null,\n message: 'Connecting to server...',\n timestamp: new Date().toISOString(),\n })\n\n logger.info('Starting SSE stream', {\n query: options.query,\n spaceIds: options.spaceIds,\n })\n\n // Build request body\n const requestBody = {\n query: options.query,\n spaceIds: options.spaceIds,\n sessionId: options.sessionId,\n options: options.options,\n }\n\n // Create EventSource (SSE connection)\n // Note: EventSource doesn't support POST, so we need to use fetch + ReadableStream\n fetch('/api/mcp/generative-ui-stream', {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(requestBody),\n })\n .then(async (response) => {\n if (!response.ok) {\n const errorData = await response.json()\n throw new Error(errorData.message || 'Stream request failed')\n }\n\n if (!response.body) {\n throw new Error('Response body is null')\n }\n\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n\n let buffer = ''\n\n // Read stream\n const readChunk = async (): Promise<void> => {\n const { done, value } = await reader.read()\n\n if (done) {\n logger.info('Stream ended')\n return\n }\n\n buffer += decoder.decode(value, { stream: true })\n\n // Process SSE messages\n const lines = buffer.split('\\n')\n buffer = lines.pop() || '' // Keep incomplete line in buffer\n\n let currentEvent: SSEEventType | null = null\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7) as SSEEventType\n } else if (line.startsWith('data: ') && currentEvent) {\n const data = line.slice(6)\n parseSSEEvent({ data } as MessageEvent, currentEvent)\n currentEvent = null\n }\n }\n\n // Continue reading\n return readChunk()\n }\n\n await readChunk()\n })\n .catch((err) => {\n logger.error('Stream fetch failed', {\n error: err instanceof Error ? err.message : String(err),\n })\n\n handleErrorEvent({\n error: 'Stream connection failed',\n message: err instanceof Error ? err.message : 'Unknown error',\n recoverable: true,\n })\n })\n }\n\n /**\n * Stop streaming\n */\n const stopStreaming = () => {\n if (eventSource) {\n eventSource.close()\n eventSource = null\n }\n\n setIsStreaming(false)\n setIsLoading(false)\n\n logger.info('Streaming stopped')\n }\n\n /**\n * Cleanup on unmount\n */\n onCleanup(() => {\n stopStreaming()\n })\n\n // Auto-start streaming\n startStreaming()\n\n // Return state accessors and controls\n return {\n components,\n isLoading,\n isStreaming,\n error,\n progress,\n metadata,\n startStreaming,\n stopStreaming,\n }\n}\n"],"names":["error"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -3,6 +3,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const UIResourceRenderer = require("./components/UIResourceRenderer.cjs");
4
4
  const StreamingUIRenderer = require("./components/StreamingUIRenderer.cjs");
5
5
  const GenerativeUIErrorBoundary = require("./components/GenerativeUIErrorBoundary.cjs");
6
+ require("solid-js/web");
7
+ require("solid-js");
8
+ require("./components/ActionRenderer.cjs");
9
+ require("./components/CarouselRenderer.cjs");
6
10
  const useStreamingUI = require("./hooks/useStreamingUI.cjs");
7
11
  const useAction = require("./hooks/useAction.cjs");
8
12
  const MCPActionContext = require("./context/MCPActionContext.cjs");
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { UIResourceRenderer } from "./components/UIResourceRenderer.js";
2
2
  import { StreamingUIRenderer } from "./components/StreamingUIRenderer.js";
3
3
  import { GenerativeUIErrorBoundary } from "./components/GenerativeUIErrorBoundary.js";
4
+ import "solid-js/web";
5
+ import "solid-js";
6
+ import "./components/ActionRenderer.js";
7
+ import "./components/CarouselRenderer.js";
4
8
  import { useStreamingUI } from "./hooks/useStreamingUI.js";
5
9
  import { useAction, useToolAction } from "./hooks/useAction.js";
6
10
  import { MCPActionContext, MCPActionProvider, useMCPAction, useMCPActionSafe } from "./context/MCPActionContext.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
@@ -281,13 +281,223 @@ const TextRegistry = {
281
281
  // 1s
282
282
  }
283
283
  };
284
+ const GridRegistry = {
285
+ type: "grid",
286
+ name: "GridLayout",
287
+ description: "Nested CSS Grid layout for organizing multiple components. Supports named areas, responsive columns (1-12), and custom gap spacing. Best for complex dashboard layouts and template builder.",
288
+ schema: {
289
+ type: "object",
290
+ properties: {
291
+ columns: {
292
+ type: "number",
293
+ description: "Number of columns (default: 12)"
294
+ },
295
+ gap: {
296
+ type: "string",
297
+ description: 'Gap between items (e.g., "1rem")'
298
+ },
299
+ minRowHeight: {
300
+ type: "string",
301
+ description: "Minimum row height (optional)"
302
+ },
303
+ areas: {
304
+ type: "array",
305
+ items: {
306
+ type: "array",
307
+ items: { type: "string" }
308
+ },
309
+ description: "CSS Grid template areas for named regions"
310
+ },
311
+ children: {
312
+ type: "array",
313
+ items: { type: "object" },
314
+ description: "Child UIComponents to render within the grid"
315
+ }
316
+ },
317
+ required: ["children"]
318
+ },
319
+ examples: [],
320
+ limits: validation.DEFAULT_RESOURCE_LIMITS
321
+ };
322
+ const ActionRegistry = {
323
+ type: "action",
324
+ name: "ActionButton",
325
+ description: "Interactive button or link that triggers tool calls or navigation. Best for user interactions, form submissions, and workflow triggers.",
326
+ schema: {
327
+ type: "object",
328
+ properties: {
329
+ label: {
330
+ type: "string",
331
+ description: "Button text"
332
+ },
333
+ type: {
334
+ type: "string",
335
+ enum: ["button", "link"],
336
+ description: "Render as button or link"
337
+ },
338
+ action: {
339
+ type: "string",
340
+ enum: ["tool-call", "link", "submit"],
341
+ description: "Action type to perform"
342
+ },
343
+ toolName: {
344
+ type: "string",
345
+ description: "Tool name to call (for tool-call action)"
346
+ },
347
+ params: {
348
+ type: "object",
349
+ description: "Parameters to pass to the tool"
350
+ },
351
+ url: {
352
+ type: "string",
353
+ description: "URL for link action"
354
+ },
355
+ variant: {
356
+ type: "string",
357
+ enum: ["primary", "secondary", "outline", "ghost", "danger"],
358
+ description: "Visual style variant"
359
+ },
360
+ size: {
361
+ type: "string",
362
+ enum: ["sm", "md", "lg"],
363
+ description: "Button size"
364
+ },
365
+ disabled: {
366
+ type: "boolean",
367
+ description: "Whether the action is disabled"
368
+ }
369
+ },
370
+ required: ["label", "type", "action"]
371
+ },
372
+ examples: [],
373
+ limits: validation.DEFAULT_RESOURCE_LIMITS
374
+ };
375
+ const FooterRegistry = {
376
+ type: "footer",
377
+ name: "FooterSection",
378
+ description: "Footer section displaying execution metadata. Best for showing timing, model info, and source counts. Auto-injected by layouts when metadata is provided.",
379
+ schema: {
380
+ type: "object",
381
+ properties: {
382
+ poweredBy: {
383
+ type: "string",
384
+ description: "Powered by text (optional)"
385
+ },
386
+ executionTime: {
387
+ type: "number",
388
+ description: "Execution time in milliseconds"
389
+ },
390
+ model: {
391
+ type: "string",
392
+ description: "LLM model used"
393
+ },
394
+ sourceCount: {
395
+ type: "number",
396
+ description: "Number of sources used"
397
+ },
398
+ customText: {
399
+ type: "string",
400
+ description: "Custom footer text"
401
+ },
402
+ links: {
403
+ type: "array",
404
+ items: {
405
+ type: "object",
406
+ properties: {
407
+ label: { type: "string" },
408
+ url: { type: "string" }
409
+ }
410
+ },
411
+ description: "Footer links"
412
+ }
413
+ }
414
+ },
415
+ examples: [],
416
+ limits: {
417
+ maxDataPoints: 1,
418
+ maxTableRows: 1,
419
+ maxPayloadSize: 5 * 1024,
420
+ renderTimeout: 1e3
421
+ }
422
+ };
423
+ const CarouselRegistry = {
424
+ type: "carousel",
425
+ name: "Carousel",
426
+ description: "Horizontal carousel for displaying multiple items with snap scrolling and navigation buttons. Best for showcasing related content, image galleries, or card collections.",
427
+ schema: {
428
+ type: "object",
429
+ properties: {
430
+ items: {
431
+ type: "array",
432
+ items: { type: "object" },
433
+ description: "Array of UIComponents to display in carousel"
434
+ },
435
+ height: {
436
+ type: "string",
437
+ description: "Carousel height (optional)"
438
+ }
439
+ },
440
+ required: ["items"]
441
+ },
442
+ examples: [],
443
+ limits: validation.DEFAULT_RESOURCE_LIMITS
444
+ };
445
+ const ArtifactRegistry = {
446
+ type: "artifact",
447
+ name: "Artifact",
448
+ description: "Display downloadable artifacts like generated files or exports. Shows filename, size, and download button. Best for CSV exports, PDF reports, and generated documents.",
449
+ schema: {
450
+ type: "object",
451
+ properties: {
452
+ url: {
453
+ type: "string",
454
+ description: "Download URL for the artifact"
455
+ },
456
+ filename: {
457
+ type: "string",
458
+ description: "Display filename"
459
+ },
460
+ mimeType: {
461
+ type: "string",
462
+ description: 'MIME type (e.g., "text/csv", "application/pdf")'
463
+ },
464
+ size: {
465
+ type: "number",
466
+ description: "File size in bytes"
467
+ },
468
+ description: {
469
+ type: "string",
470
+ description: "Description of the artifact"
471
+ }
472
+ },
473
+ required: ["url", "filename", "mimeType"]
474
+ },
475
+ examples: [],
476
+ limits: {
477
+ maxDataPoints: 1,
478
+ maxTableRows: 1,
479
+ maxPayloadSize: 5 * 1024,
480
+ renderTimeout: 1e3
481
+ }
482
+ };
284
483
  const ComponentRegistry = /* @__PURE__ */ new Map([
285
484
  ["chart", QuickchartRegistry],
286
485
  ["table", TableRegistry],
287
486
  ["metric", MetricRegistry],
288
- ["text", TextRegistry]
487
+ ["text", TextRegistry],
488
+ // Sprint 4 additions
489
+ ["grid", GridRegistry],
490
+ ["action", ActionRegistry],
491
+ ["footer", FooterRegistry],
492
+ ["carousel", CarouselRegistry],
493
+ ["artifact", ArtifactRegistry]
289
494
  ]);
495
+ exports.ActionRegistry = ActionRegistry;
496
+ exports.ArtifactRegistry = ArtifactRegistry;
497
+ exports.CarouselRegistry = CarouselRegistry;
290
498
  exports.ComponentRegistry = ComponentRegistry;
499
+ exports.FooterRegistry = FooterRegistry;
500
+ exports.GridRegistry = GridRegistry;
291
501
  exports.MetricRegistry = MetricRegistry;
292
502
  exports.QuickchartRegistry = QuickchartRegistry;
293
503
  exports.TableRegistry = TableRegistry;
@@ -1 +1 @@
1
- {"version":3,"file":"component-registry.cjs","sources":["../../src/services/component-registry.ts"],"sourcesContent":["/**\n * Component Registry Service\n * Phase 0: Static registry with Quickchart and Table definitions\n * Phase 1: Dynamic registry populated from /api/mcp/tools/list\n *\n * Provides component schemas for LLM prompt engineering\n */\n\nimport type { ComponentRegistryEntry, ComponentType } from '../types'\nimport { DEFAULT_RESOURCE_LIMITS } from './validation'\n\n/**\n * Quickchart Component Registry Entry\n * Based on Quickchart API documentation\n */\nexport const QuickchartRegistry: ComponentRegistryEntry = {\n type: 'chart',\n name: 'Quickchart',\n description:\n 'Render charts using Quickchart.io API. Supports bar, line, pie, doughnut, radar, and scatter charts. Best for visualizing numerical data with 2-10 data series and up to 1000 data points.',\n schema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['bar', 'line', 'pie', 'doughnut', 'radar', 'scatter'],\n description: 'Chart type',\n },\n title: {\n type: 'string',\n description: 'Chart title (optional)',\n },\n data: {\n type: 'object',\n properties: {\n labels: {\n type: 'array',\n items: { type: 'string' },\n description: 'X-axis labels',\n },\n datasets: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n label: { type: 'string' },\n data: {\n type: 'array',\n items: { type: 'number' },\n },\n backgroundColor: {\n oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],\n },\n borderColor: {\n oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],\n },\n borderWidth: { type: 'number' },\n },\n required: ['label', 'data'],\n },\n },\n },\n required: ['labels', 'datasets'],\n },\n options: {\n type: 'object',\n description: 'Chart.js options for customization',\n },\n },\n required: ['type', 'data'],\n },\n examples: [\n {\n query: 'Show me document types distribution',\n component: {\n id: 'example-bar-1',\n type: 'chart',\n position: { colStart: 1, colSpan: 6 },\n params: {\n type: 'bar',\n title: 'Document Types',\n data: {\n labels: ['PDF', 'DOCX', 'TXT', 'XLSX'],\n datasets: [\n {\n label: 'Count',\n data: [245, 189, 123, 98],\n backgroundColor: ['rgba(59, 130, 246, 0.8)'],\n },\n ],\n },\n },\n },\n },\n {\n query: 'Display upload trends over the last week',\n component: {\n id: 'example-line-1',\n type: 'chart',\n position: { colStart: 1, colSpan: 6 },\n params: {\n type: 'line',\n title: 'Upload Trends',\n data: {\n labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n datasets: [\n {\n label: 'Uploads',\n data: [42, 38, 51, 47, 63, 29, 15],\n borderColor: 'rgb(59, 130, 246)',\n },\n ],\n },\n options: {\n tension: 0.4,\n },\n },\n },\n },\n ],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Table Component Registry Entry\n */\nexport const TableRegistry: ComponentRegistryEntry = {\n type: 'table',\n name: 'DataTable',\n description:\n 'Render tabular data with sortable columns and pagination. Best for displaying structured records with up to 100 rows. Supports column width customization and cell formatting.',\n schema: {\n type: 'object',\n properties: {\n title: {\n type: 'string',\n description: 'Table title (optional)',\n },\n columns: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n key: { type: 'string', description: 'Data key for this column' },\n label: { type: 'string', description: 'Column header label' },\n sortable: { type: 'boolean', description: 'Whether column is sortable' },\n width: { type: 'string', description: 'CSS width (e.g., \"30%\")' },\n },\n required: ['key', 'label'],\n },\n minItems: 1,\n },\n rows: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Row data matching column keys',\n },\n maxItems: 100,\n },\n pagination: {\n type: 'object',\n properties: {\n currentPage: { type: 'number' },\n pageSize: { type: 'number' },\n totalRows: { type: 'number' },\n },\n },\n },\n required: ['columns', 'rows'],\n },\n examples: [\n {\n query: 'Show me the most recent documents',\n component: {\n id: 'example-table-1',\n type: 'table',\n position: { colStart: 1, colSpan: 8 },\n params: {\n title: 'Recent Documents',\n columns: [\n { key: 'name', label: 'Name', sortable: true, width: '40%' },\n { key: 'type', label: 'Type', sortable: true, width: '15%' },\n { key: 'size', label: 'Size', width: '15%' },\n { key: 'modified', label: 'Modified', sortable: true, width: '30%' },\n ],\n rows: [\n { name: 'Report.pdf', type: 'PDF', size: '2.4 MB', modified: '2 hours ago' },\n { name: 'Slides.pptx', type: 'PPTX', size: '8.7 MB', modified: '1 day ago' },\n ],\n },\n },\n },\n ],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Metric Card Component Registry Entry\n */\nexport const MetricRegistry: ComponentRegistryEntry = {\n type: 'metric',\n name: 'MetricCard',\n description:\n 'Display a single metric with optional trend indicator. Best for KPIs, statistics, and summary numbers. Supports trend direction (up/down/neutral) and subtitles.',\n schema: {\n type: 'object',\n properties: {\n title: {\n type: 'string',\n description: 'Metric title',\n },\n value: {\n oneOf: [{ type: 'string' }, { type: 'number' }],\n description: 'Metric value',\n },\n unit: {\n type: 'string',\n description: 'Unit of measurement (optional)',\n },\n trend: {\n type: 'object',\n properties: {\n value: { type: 'number', description: 'Percentage change' },\n direction: { type: 'string', enum: ['up', 'down', 'neutral'] },\n },\n },\n subtitle: {\n type: 'string',\n description: 'Additional context (optional)',\n },\n },\n required: ['title', 'value'],\n },\n examples: [\n {\n query: 'Show total document count',\n component: {\n id: 'example-metric-1',\n type: 'metric',\n position: { colStart: 1, colSpan: 3 },\n params: {\n title: 'Total Documents',\n value: '1,247',\n trend: {\n value: 12.5,\n direction: 'up',\n },\n subtitle: '+142 this month',\n },\n },\n },\n ],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 5 * 1024, // 5KB\n renderTimeout: 1000, // 1s\n },\n}\n\n/**\n * Text Component Registry Entry\n */\nexport const TextRegistry: ComponentRegistryEntry = {\n type: 'text',\n name: 'TextBlock',\n description:\n 'Render text content with optional markdown support. Best for explanations, summaries, and context. Supports basic HTML formatting.',\n schema: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Text content (HTML allowed, will be sanitized)',\n },\n markdown: {\n type: 'boolean',\n description: 'Whether content is markdown (not yet implemented)',\n },\n className: {\n type: 'string',\n description: 'Custom CSS classes',\n },\n },\n required: ['content'],\n },\n examples: [\n {\n query: 'Explain the document distribution',\n component: {\n id: 'example-text-1',\n type: 'text',\n position: { colStart: 1, colSpan: 12 },\n params: {\n content:\n '<p>Your document library contains <strong>1,247 files</strong> across 5 different formats. PDFs represent the largest category at 35% of total storage.</p>',\n },\n },\n },\n ],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 10 * 1024, // 10KB\n renderTimeout: 1000, // 1s\n },\n}\n\n/**\n * Component Registry - All components indexed by type\n */\nexport const ComponentRegistry: Map<ComponentType, ComponentRegistryEntry> = new Map([\n ['chart', QuickchartRegistry],\n ['table', TableRegistry],\n ['metric', MetricRegistry],\n ['text', TextRegistry],\n])\n\n/**\n * Get component registry entry by type\n */\nexport function getComponentEntry(type: ComponentType): ComponentRegistryEntry | undefined {\n return ComponentRegistry.get(type)\n}\n\n/**\n * Get all component types\n */\nexport function getAllComponentTypes(): ComponentType[] {\n return Array.from(ComponentRegistry.keys())\n}\n\n/**\n * Get registry as JSON for LLM context\n */\nexport function getRegistryForLLM(): string {\n const entries = Array.from(ComponentRegistry.values()).map((entry) => ({\n type: entry.type,\n name: entry.name,\n description: entry.description,\n schema: entry.schema,\n examples: entry.examples.map((ex) => ({\n query: ex.query,\n component: ex.component,\n })),\n limits: entry.limits,\n }))\n\n return JSON.stringify(entries, null, 2)\n}\n\n/**\n * Validate component against registry schema\n * (Future: Use Zod for runtime validation)\n */\nexport function validateAgainstRegistry(\n componentType: ComponentType,\n params: any\n): { valid: boolean; errors?: string[] } {\n const entry = getComponentEntry(componentType)\n if (!entry) {\n return { valid: false, errors: [`Unknown component type: ${componentType}`] }\n }\n\n // Basic validation (Phase 1 will add Zod schema validation)\n const required = entry.schema.required || []\n const missing = required.filter((key: string) => !(key in params))\n\n if (missing.length > 0) {\n return {\n valid: false,\n errors: missing.map((key: string) => `Missing required field: ${key}`),\n }\n }\n\n return { valid: true }\n}\n"],"names":["DEFAULT_RESOURCE_LIMITS"],"mappings":"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"}
1
+ {"version":3,"file":"component-registry.cjs","sources":["../../src/services/component-registry.ts"],"sourcesContent":["/**\n * Component Registry Service\n * Phase 0: Static registry with Quickchart and Table definitions\n * Phase 1: Dynamic registry populated from /api/mcp/tools/list\n *\n * Provides component schemas for LLM prompt engineering\n */\n\nimport type { ComponentRegistryEntry, ComponentType } from '../types'\nimport { DEFAULT_RESOURCE_LIMITS } from './validation'\n\n/**\n * Quickchart Component Registry Entry\n * Based on Quickchart API documentation\n */\nexport const QuickchartRegistry: ComponentRegistryEntry = {\n type: 'chart',\n name: 'Quickchart',\n description:\n 'Render charts using Quickchart.io API. Supports bar, line, pie, doughnut, radar, and scatter charts. Best for visualizing numerical data with 2-10 data series and up to 1000 data points.',\n schema: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: ['bar', 'line', 'pie', 'doughnut', 'radar', 'scatter'],\n description: 'Chart type',\n },\n title: {\n type: 'string',\n description: 'Chart title (optional)',\n },\n data: {\n type: 'object',\n properties: {\n labels: {\n type: 'array',\n items: { type: 'string' },\n description: 'X-axis labels',\n },\n datasets: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n label: { type: 'string' },\n data: {\n type: 'array',\n items: { type: 'number' },\n },\n backgroundColor: {\n oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],\n },\n borderColor: {\n oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],\n },\n borderWidth: { type: 'number' },\n },\n required: ['label', 'data'],\n },\n },\n },\n required: ['labels', 'datasets'],\n },\n options: {\n type: 'object',\n description: 'Chart.js options for customization',\n },\n },\n required: ['type', 'data'],\n },\n examples: [\n {\n query: 'Show me document types distribution',\n component: {\n id: 'example-bar-1',\n type: 'chart',\n position: { colStart: 1, colSpan: 6 },\n params: {\n type: 'bar',\n title: 'Document Types',\n data: {\n labels: ['PDF', 'DOCX', 'TXT', 'XLSX'],\n datasets: [\n {\n label: 'Count',\n data: [245, 189, 123, 98],\n backgroundColor: ['rgba(59, 130, 246, 0.8)'],\n },\n ],\n },\n },\n },\n },\n {\n query: 'Display upload trends over the last week',\n component: {\n id: 'example-line-1',\n type: 'chart',\n position: { colStart: 1, colSpan: 6 },\n params: {\n type: 'line',\n title: 'Upload Trends',\n data: {\n labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],\n datasets: [\n {\n label: 'Uploads',\n data: [42, 38, 51, 47, 63, 29, 15],\n borderColor: 'rgb(59, 130, 246)',\n },\n ],\n },\n options: {\n tension: 0.4,\n },\n },\n },\n },\n ],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Table Component Registry Entry\n */\nexport const TableRegistry: ComponentRegistryEntry = {\n type: 'table',\n name: 'DataTable',\n description:\n 'Render tabular data with sortable columns and pagination. Best for displaying structured records with up to 100 rows. Supports column width customization and cell formatting.',\n schema: {\n type: 'object',\n properties: {\n title: {\n type: 'string',\n description: 'Table title (optional)',\n },\n columns: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n key: { type: 'string', description: 'Data key for this column' },\n label: { type: 'string', description: 'Column header label' },\n sortable: { type: 'boolean', description: 'Whether column is sortable' },\n width: { type: 'string', description: 'CSS width (e.g., \"30%\")' },\n },\n required: ['key', 'label'],\n },\n minItems: 1,\n },\n rows: {\n type: 'array',\n items: {\n type: 'object',\n description: 'Row data matching column keys',\n },\n maxItems: 100,\n },\n pagination: {\n type: 'object',\n properties: {\n currentPage: { type: 'number' },\n pageSize: { type: 'number' },\n totalRows: { type: 'number' },\n },\n },\n },\n required: ['columns', 'rows'],\n },\n examples: [\n {\n query: 'Show me the most recent documents',\n component: {\n id: 'example-table-1',\n type: 'table',\n position: { colStart: 1, colSpan: 8 },\n params: {\n title: 'Recent Documents',\n columns: [\n { key: 'name', label: 'Name', sortable: true, width: '40%' },\n { key: 'type', label: 'Type', sortable: true, width: '15%' },\n { key: 'size', label: 'Size', width: '15%' },\n { key: 'modified', label: 'Modified', sortable: true, width: '30%' },\n ],\n rows: [\n { name: 'Report.pdf', type: 'PDF', size: '2.4 MB', modified: '2 hours ago' },\n { name: 'Slides.pptx', type: 'PPTX', size: '8.7 MB', modified: '1 day ago' },\n ],\n },\n },\n },\n ],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Metric Card Component Registry Entry\n */\nexport const MetricRegistry: ComponentRegistryEntry = {\n type: 'metric',\n name: 'MetricCard',\n description:\n 'Display a single metric with optional trend indicator. Best for KPIs, statistics, and summary numbers. Supports trend direction (up/down/neutral) and subtitles.',\n schema: {\n type: 'object',\n properties: {\n title: {\n type: 'string',\n description: 'Metric title',\n },\n value: {\n oneOf: [{ type: 'string' }, { type: 'number' }],\n description: 'Metric value',\n },\n unit: {\n type: 'string',\n description: 'Unit of measurement (optional)',\n },\n trend: {\n type: 'object',\n properties: {\n value: { type: 'number', description: 'Percentage change' },\n direction: { type: 'string', enum: ['up', 'down', 'neutral'] },\n },\n },\n subtitle: {\n type: 'string',\n description: 'Additional context (optional)',\n },\n },\n required: ['title', 'value'],\n },\n examples: [\n {\n query: 'Show total document count',\n component: {\n id: 'example-metric-1',\n type: 'metric',\n position: { colStart: 1, colSpan: 3 },\n params: {\n title: 'Total Documents',\n value: '1,247',\n trend: {\n value: 12.5,\n direction: 'up',\n },\n subtitle: '+142 this month',\n },\n },\n },\n ],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 5 * 1024, // 5KB\n renderTimeout: 1000, // 1s\n },\n}\n\n/**\n * Text Component Registry Entry\n */\nexport const TextRegistry: ComponentRegistryEntry = {\n type: 'text',\n name: 'TextBlock',\n description:\n 'Render text content with optional markdown support. Best for explanations, summaries, and context. Supports basic HTML formatting.',\n schema: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Text content (HTML allowed, will be sanitized)',\n },\n markdown: {\n type: 'boolean',\n description: 'Whether content is markdown (not yet implemented)',\n },\n className: {\n type: 'string',\n description: 'Custom CSS classes',\n },\n },\n required: ['content'],\n },\n examples: [\n {\n query: 'Explain the document distribution',\n component: {\n id: 'example-text-1',\n type: 'text',\n position: { colStart: 1, colSpan: 12 },\n params: {\n content:\n '<p>Your document library contains <strong>1,247 files</strong> across 5 different formats. PDFs represent the largest category at 35% of total storage.</p>',\n },\n },\n },\n ],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 10 * 1024, // 10KB\n renderTimeout: 1000, // 1s\n },\n}\n\n// ============================================================================\n// Sprint 4: Additional Component Registry Entries\n// ============================================================================\n\n/**\n * Grid Component Registry Entry\n * Nested CSS Grid layout for organizing multiple components\n */\nexport const GridRegistry: ComponentRegistryEntry = {\n type: 'grid',\n name: 'GridLayout',\n description:\n 'Nested CSS Grid layout for organizing multiple components. Supports named areas, responsive columns (1-12), and custom gap spacing. Best for complex dashboard layouts and template builder.',\n schema: {\n type: 'object',\n properties: {\n columns: {\n type: 'number',\n description: 'Number of columns (default: 12)',\n },\n gap: {\n type: 'string',\n description: 'Gap between items (e.g., \"1rem\")',\n },\n minRowHeight: {\n type: 'string',\n description: 'Minimum row height (optional)',\n },\n areas: {\n type: 'array',\n items: {\n type: 'array',\n items: { type: 'string' },\n },\n description: 'CSS Grid template areas for named regions',\n },\n children: {\n type: 'array',\n items: { type: 'object' },\n description: 'Child UIComponents to render within the grid',\n },\n },\n required: ['children'],\n },\n examples: [],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Action Component Registry Entry\n * Interactive button or link that triggers tool calls\n */\nexport const ActionRegistry: ComponentRegistryEntry = {\n type: 'action',\n name: 'ActionButton',\n description:\n 'Interactive button or link that triggers tool calls or navigation. Best for user interactions, form submissions, and workflow triggers.',\n schema: {\n type: 'object',\n properties: {\n label: {\n type: 'string',\n description: 'Button text',\n },\n type: {\n type: 'string',\n enum: ['button', 'link'],\n description: 'Render as button or link',\n },\n action: {\n type: 'string',\n enum: ['tool-call', 'link', 'submit'],\n description: 'Action type to perform',\n },\n toolName: {\n type: 'string',\n description: 'Tool name to call (for tool-call action)',\n },\n params: {\n type: 'object',\n description: 'Parameters to pass to the tool',\n },\n url: {\n type: 'string',\n description: 'URL for link action',\n },\n variant: {\n type: 'string',\n enum: ['primary', 'secondary', 'outline', 'ghost', 'danger'],\n description: 'Visual style variant',\n },\n size: {\n type: 'string',\n enum: ['sm', 'md', 'lg'],\n description: 'Button size',\n },\n disabled: {\n type: 'boolean',\n description: 'Whether the action is disabled',\n },\n },\n required: ['label', 'type', 'action'],\n },\n examples: [],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Footer Component Registry Entry\n * Display execution metadata like timing and source count\n */\nexport const FooterRegistry: ComponentRegistryEntry = {\n type: 'footer',\n name: 'FooterSection',\n description:\n 'Footer section displaying execution metadata. Best for showing timing, model info, and source counts. Auto-injected by layouts when metadata is provided.',\n schema: {\n type: 'object',\n properties: {\n poweredBy: {\n type: 'string',\n description: 'Powered by text (optional)',\n },\n executionTime: {\n type: 'number',\n description: 'Execution time in milliseconds',\n },\n model: {\n type: 'string',\n description: 'LLM model used',\n },\n sourceCount: {\n type: 'number',\n description: 'Number of sources used',\n },\n customText: {\n type: 'string',\n description: 'Custom footer text',\n },\n links: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n label: { type: 'string' },\n url: { type: 'string' },\n },\n },\n description: 'Footer links',\n },\n },\n },\n examples: [],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 5 * 1024,\n renderTimeout: 1000,\n },\n}\n\n/**\n * Carousel Component Registry Entry\n * Display multiple items with horizontal scrolling\n */\nexport const CarouselRegistry: ComponentRegistryEntry = {\n type: 'carousel',\n name: 'Carousel',\n description:\n 'Horizontal carousel for displaying multiple items with snap scrolling and navigation buttons. Best for showcasing related content, image galleries, or card collections.',\n schema: {\n type: 'object',\n properties: {\n items: {\n type: 'array',\n items: { type: 'object' },\n description: 'Array of UIComponents to display in carousel',\n },\n height: {\n type: 'string',\n description: 'Carousel height (optional)',\n },\n },\n required: ['items'],\n },\n examples: [],\n limits: DEFAULT_RESOURCE_LIMITS,\n}\n\n/**\n * Artifact Component Registry Entry\n * Display downloadable artifacts like generated files\n */\nexport const ArtifactRegistry: ComponentRegistryEntry = {\n type: 'artifact',\n name: 'Artifact',\n description:\n 'Display downloadable artifacts like generated files or exports. Shows filename, size, and download button. Best for CSV exports, PDF reports, and generated documents.',\n schema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'Download URL for the artifact',\n },\n filename: {\n type: 'string',\n description: 'Display filename',\n },\n mimeType: {\n type: 'string',\n description: 'MIME type (e.g., \"text/csv\", \"application/pdf\")',\n },\n size: {\n type: 'number',\n description: 'File size in bytes',\n },\n description: {\n type: 'string',\n description: 'Description of the artifact',\n },\n },\n required: ['url', 'filename', 'mimeType'],\n },\n examples: [],\n limits: {\n maxDataPoints: 1,\n maxTableRows: 1,\n maxPayloadSize: 5 * 1024,\n renderTimeout: 1000,\n },\n}\n\n/**\n * Component Registry - All components indexed by type\n */\nexport const ComponentRegistry: Map<ComponentType, ComponentRegistryEntry> = new Map([\n ['chart', QuickchartRegistry],\n ['table', TableRegistry],\n ['metric', MetricRegistry],\n ['text', TextRegistry],\n // Sprint 4 additions\n ['grid', GridRegistry],\n ['action', ActionRegistry],\n ['footer', FooterRegistry],\n ['carousel', CarouselRegistry],\n ['artifact', ArtifactRegistry],\n])\n\n/**\n * Get component registry entry by type\n */\nexport function getComponentEntry(type: ComponentType): ComponentRegistryEntry | undefined {\n return ComponentRegistry.get(type)\n}\n\n/**\n * Get all component types\n */\nexport function getAllComponentTypes(): ComponentType[] {\n return Array.from(ComponentRegistry.keys())\n}\n\n/**\n * Get registry as JSON for LLM context\n */\nexport function getRegistryForLLM(): string {\n const entries = Array.from(ComponentRegistry.values()).map((entry) => ({\n type: entry.type,\n name: entry.name,\n description: entry.description,\n schema: entry.schema,\n examples: entry.examples.map((ex) => ({\n query: ex.query,\n component: ex.component,\n })),\n limits: entry.limits,\n }))\n\n return JSON.stringify(entries, null, 2)\n}\n\n/**\n * Validate component against registry schema\n * (Future: Use Zod for runtime validation)\n */\nexport function validateAgainstRegistry(\n componentType: ComponentType,\n params: any\n): { valid: boolean; errors?: string[] } {\n const entry = getComponentEntry(componentType)\n if (!entry) {\n return { valid: false, errors: [`Unknown component type: ${componentType}`] }\n }\n\n // Basic validation (Phase 1 will add Zod schema validation)\n const required = entry.schema.required || []\n const missing = required.filter((key: string) => !(key in params))\n\n if (missing.length > 0) {\n return {\n valid: false,\n errors: missing.map((key: string) => `Missing required field: ${key}`),\n }\n }\n\n return { valid: true }\n}\n"],"names":["DEFAULT_RESOURCE_LIMITS"],"mappings":"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"}
@@ -23,6 +23,31 @@ export declare const MetricRegistry: ComponentRegistryEntry;
23
23
  * Text Component Registry Entry
24
24
  */
25
25
  export declare const TextRegistry: ComponentRegistryEntry;
26
+ /**
27
+ * Grid Component Registry Entry
28
+ * Nested CSS Grid layout for organizing multiple components
29
+ */
30
+ export declare const GridRegistry: ComponentRegistryEntry;
31
+ /**
32
+ * Action Component Registry Entry
33
+ * Interactive button or link that triggers tool calls
34
+ */
35
+ export declare const ActionRegistry: ComponentRegistryEntry;
36
+ /**
37
+ * Footer Component Registry Entry
38
+ * Display execution metadata like timing and source count
39
+ */
40
+ export declare const FooterRegistry: ComponentRegistryEntry;
41
+ /**
42
+ * Carousel Component Registry Entry
43
+ * Display multiple items with horizontal scrolling
44
+ */
45
+ export declare const CarouselRegistry: ComponentRegistryEntry;
46
+ /**
47
+ * Artifact Component Registry Entry
48
+ * Display downloadable artifacts like generated files
49
+ */
50
+ export declare const ArtifactRegistry: ComponentRegistryEntry;
26
51
  /**
27
52
  * Component Registry - All components indexed by type
28
53
  */
@@ -1 +1 @@
1
- {"version":3,"file":"component-registry.d.ts","sourceRoot":"","sources":["../../src/services/component-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGrE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,sBA0GhC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,sBAqE3B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,sBA2D5B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,sBA2C1B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,GAAG,CAAC,aAAa,EAAE,sBAAsB,CAKvE,CAAA;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,sBAAsB,GAAG,SAAS,CAEzF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,aAAa,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAc1C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,GAAG,GACV;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAkBvC"}
1
+ {"version":3,"file":"component-registry.d.ts","sourceRoot":"","sources":["../../src/services/component-registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAGrE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,sBA0GhC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,sBAqE3B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,sBA2D5B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,sBA2C1B,CAAA;AAMD;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,sBAsC1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,sBAqD5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,EAAE,sBAgD5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,sBAsB9B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,sBAsC9B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,GAAG,CAAC,aAAa,EAAE,sBAAsB,CAWvE,CAAA;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,GAAG,sBAAsB,GAAG,SAAS,CAEzF;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,aAAa,EAAE,CAEtD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAc1C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,aAAa,EAAE,aAAa,EAC5B,MAAM,EAAE,GAAG,GACV;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAkBvC"}