@seed-ship/mcp-ui-solid 1.0.29 → 1.0.32

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 (85) hide show
  1. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -0
  2. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -0
  3. package/dist/components/StreamingUIRenderer.cjs.map +1 -0
  4. package/dist/components/StreamingUIRenderer.js.map +1 -0
  5. package/dist/{mcp-ui-solid/src/components → components}/UIResourceRenderer.cjs +115 -104
  6. package/dist/components/UIResourceRenderer.cjs.map +1 -0
  7. package/dist/components/UIResourceRenderer.d.ts +0 -11
  8. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  9. package/dist/{mcp-ui-solid/src/components → components}/UIResourceRenderer.js +116 -105
  10. package/dist/components/UIResourceRenderer.js.map +1 -0
  11. package/dist/components.cjs +3 -3
  12. package/dist/components.d.ts +12 -0
  13. package/dist/components.js +3 -3
  14. package/dist/hooks/useStreamingUI.cjs.map +1 -0
  15. package/dist/hooks/useStreamingUI.js.map +1 -0
  16. package/dist/hooks.cjs +1 -1
  17. package/dist/hooks.d.ts +8 -0
  18. package/dist/hooks.js +1 -1
  19. package/dist/index.cjs +6 -6
  20. package/dist/index.js +6 -6
  21. package/dist/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.cjs +1006 -0
  22. package/dist/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.cjs.map +1 -0
  23. package/dist/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.js +1007 -0
  24. package/dist/node_modules/.pnpm/dompurify@3.3.0/node_modules/dompurify/dist/purify.es.js.map +1 -0
  25. package/dist/services/component-registry.cjs.map +1 -0
  26. package/dist/services/component-registry.js.map +1 -0
  27. package/dist/services/validation.cjs.map +1 -0
  28. package/dist/services/validation.js.map +1 -0
  29. package/dist/types.d.ts +265 -0
  30. package/dist/utils/logger.cjs.map +1 -0
  31. package/dist/utils/logger.js.map +1 -0
  32. package/dist/validation.cjs +1 -1
  33. package/dist/validation.js +1 -1
  34. package/package.json +20 -23
  35. package/src/components/ActionRenderer.tsx +33 -0
  36. package/src/components/ArtifactRenderer.tsx +54 -0
  37. package/src/components/CarouselRenderer.tsx +77 -0
  38. package/src/components/FooterRenderer.tsx +66 -0
  39. package/src/components/GenerativeUIErrorBoundary.tsx +259 -0
  40. package/src/components/StreamingUIRenderer.tsx +327 -0
  41. package/src/components/UIResourceRenderer.tsx +581 -0
  42. package/src/components/index.ts +14 -0
  43. package/src/hooks/index.ts +14 -0
  44. package/src/hooks/useStreamingUI.ts +447 -0
  45. package/src/index.test.ts +36 -0
  46. package/src/index.ts +70 -0
  47. package/src/services/component-registry.ts +378 -0
  48. package/src/services/index.ts +9 -0
  49. package/src/services/validation.ts +472 -0
  50. package/src/types/index.ts +320 -0
  51. package/src/types-export.ts +31 -0
  52. package/src/utils/logger.ts +74 -0
  53. package/src/validation.ts +38 -0
  54. package/src/vite-env.d.ts +11 -0
  55. package/tsconfig.json +20 -0
  56. package/tsconfig.tsbuildinfo +1 -0
  57. package/vite.config.ts +52 -0
  58. package/vite.config.ts.timestamp-1763266929437-a71eed80b91318.mjs +45 -0
  59. package/vitest.config.ts +10 -0
  60. package/dist/mcp-ui-solid/src/components/GenerativeUIErrorBoundary.cjs.map +0 -1
  61. package/dist/mcp-ui-solid/src/components/GenerativeUIErrorBoundary.js.map +0 -1
  62. package/dist/mcp-ui-solid/src/components/StreamingUIRenderer.cjs.map +0 -1
  63. package/dist/mcp-ui-solid/src/components/StreamingUIRenderer.js.map +0 -1
  64. package/dist/mcp-ui-solid/src/components/UIResourceRenderer.cjs.map +0 -1
  65. package/dist/mcp-ui-solid/src/components/UIResourceRenderer.js.map +0 -1
  66. package/dist/mcp-ui-solid/src/hooks/useStreamingUI.cjs.map +0 -1
  67. package/dist/mcp-ui-solid/src/hooks/useStreamingUI.js.map +0 -1
  68. package/dist/mcp-ui-solid/src/services/component-registry.cjs.map +0 -1
  69. package/dist/mcp-ui-solid/src/services/component-registry.js.map +0 -1
  70. package/dist/mcp-ui-solid/src/services/validation.cjs.map +0 -1
  71. package/dist/mcp-ui-solid/src/services/validation.js.map +0 -1
  72. package/dist/mcp-ui-solid/src/utils/logger.cjs.map +0 -1
  73. package/dist/mcp-ui-solid/src/utils/logger.js.map +0 -1
  74. /package/dist/{mcp-ui-solid/src/components → components}/GenerativeUIErrorBoundary.cjs +0 -0
  75. /package/dist/{mcp-ui-solid/src/components → components}/GenerativeUIErrorBoundary.js +0 -0
  76. /package/dist/{mcp-ui-solid/src/components → components}/StreamingUIRenderer.cjs +0 -0
  77. /package/dist/{mcp-ui-solid/src/components → components}/StreamingUIRenderer.js +0 -0
  78. /package/dist/{mcp-ui-solid/src/hooks → hooks}/useStreamingUI.cjs +0 -0
  79. /package/dist/{mcp-ui-solid/src/hooks → hooks}/useStreamingUI.js +0 -0
  80. /package/dist/{mcp-ui-solid/src/services → services}/component-registry.cjs +0 -0
  81. /package/dist/{mcp-ui-solid/src/services → services}/component-registry.js +0 -0
  82. /package/dist/{mcp-ui-solid/src/services → services}/validation.cjs +0 -0
  83. /package/dist/{mcp-ui-solid/src/services → services}/validation.js +0 -0
  84. /package/dist/{mcp-ui-solid/src/utils → utils}/logger.cjs +0 -0
  85. /package/dist/{mcp-ui-solid/src/utils → utils}/logger.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStreamingUI.cjs","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// ============================================================================\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 // 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":["createLogger","createSignal","error","onCleanup"],"mappings":"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"}
@@ -0,0 +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// ============================================================================\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 // 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/hooks.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const useStreamingUI = require("./mcp-ui-solid/src/hooks/useStreamingUI.cjs");
3
+ const useStreamingUI = require("./hooks/useStreamingUI.cjs");
4
4
  exports.useStreamingUI = useStreamingUI.useStreamingUI;
5
5
  //# sourceMappingURL=hooks.cjs.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * MCP UI Solid - Hooks
3
+ *
4
+ * SolidJS hooks for managing UI resource state and streaming
5
+ */
6
+ export { useStreamingUI } from './useStreamingUI';
7
+ export type { UseStreamingUIOptions, StreamingUIState, StreamProgress, StreamError, CompleteMetadata, } from './useStreamingUI';
8
+ //# sourceMappingURL=index.d.ts.map
package/dist/hooks.js CHANGED
@@ -1,4 +1,4 @@
1
- import { useStreamingUI } from "./mcp-ui-solid/src/hooks/useStreamingUI.js";
1
+ import { useStreamingUI } from "./hooks/useStreamingUI.js";
2
2
  export {
3
3
  useStreamingUI
4
4
  };
package/dist/index.cjs CHANGED
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const UIResourceRenderer = require("./mcp-ui-solid/src/components/UIResourceRenderer.cjs");
4
- const StreamingUIRenderer = require("./mcp-ui-solid/src/components/StreamingUIRenderer.cjs");
5
- const GenerativeUIErrorBoundary = require("./mcp-ui-solid/src/components/GenerativeUIErrorBoundary.cjs");
6
- const useStreamingUI = require("./mcp-ui-solid/src/hooks/useStreamingUI.cjs");
7
- const validation = require("./mcp-ui-solid/src/services/validation.cjs");
8
- const componentRegistry = require("./mcp-ui-solid/src/services/component-registry.cjs");
3
+ const UIResourceRenderer = require("./components/UIResourceRenderer.cjs");
4
+ const StreamingUIRenderer = require("./components/StreamingUIRenderer.cjs");
5
+ const GenerativeUIErrorBoundary = require("./components/GenerativeUIErrorBoundary.cjs");
6
+ const useStreamingUI = require("./hooks/useStreamingUI.cjs");
7
+ const validation = require("./services/validation.cjs");
8
+ const componentRegistry = require("./services/component-registry.cjs");
9
9
  exports.UIResourceRenderer = UIResourceRenderer.UIResourceRenderer;
10
10
  exports.StreamingUIRenderer = StreamingUIRenderer.StreamingUIRenderer;
11
11
  exports.GenerativeUIErrorBoundary = GenerativeUIErrorBoundary.GenerativeUIErrorBoundary;
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { UIResourceRenderer } from "./mcp-ui-solid/src/components/UIResourceRenderer.js";
2
- import { StreamingUIRenderer } from "./mcp-ui-solid/src/components/StreamingUIRenderer.js";
3
- import { GenerativeUIErrorBoundary } from "./mcp-ui-solid/src/components/GenerativeUIErrorBoundary.js";
4
- import { useStreamingUI } from "./mcp-ui-solid/src/hooks/useStreamingUI.js";
5
- import { DEFAULT_RESOURCE_LIMITS, validateComponent, validateLayout } from "./mcp-ui-solid/src/services/validation.js";
6
- import { ComponentRegistry } from "./mcp-ui-solid/src/services/component-registry.js";
1
+ import { UIResourceRenderer } from "./components/UIResourceRenderer.js";
2
+ import { StreamingUIRenderer } from "./components/StreamingUIRenderer.js";
3
+ import { GenerativeUIErrorBoundary } from "./components/GenerativeUIErrorBoundary.js";
4
+ import { useStreamingUI } from "./hooks/useStreamingUI.js";
5
+ import { DEFAULT_RESOURCE_LIMITS, validateComponent, validateLayout } from "./services/validation.js";
6
+ import { ComponentRegistry } from "./services/component-registry.js";
7
7
  export {
8
8
  ComponentRegistry,
9
9
  DEFAULT_RESOURCE_LIMITS,