import { createSignal, onCleanup, onMount, Show, For } from "solid-js" import { useParams } from "@solidjs/router" import { type UIMessage } from "ai" type Message = { key: string content: string } type SessionInfo = { tokens?: { input?: number output?: number reasoning?: number } } export default function App() { const params = useParams<{ id: string }>() const [connectionStatus, setConnectionStatus] = createSignal("Disconnected") const [sessionInfo, setSessionInfo] = createSignal(null) const [systemMessage, setSystemMessage] = createSignal(null) const [messages, setMessages] = createSignal([]) const [expandedSystemMessage, setExpandedSystemMessage] = createSignal(false) onMount(() => { // Get the API URL from environment const apiUrl = import.meta.env.VITE_API_URL const shareId = params.id console.log("Mounting Share component with ID:", shareId) console.log("API URL:", apiUrl) if (!shareId) { console.error("Share ID not found in environment variables") setConnectionStatus("Error: Share ID not found") return } if (!apiUrl) { console.error("API URL not found in environment variables") setConnectionStatus("Error: API URL not found") return } let reconnectTimer: number | undefined let socket: WebSocket | null = null // Function to create and set up WebSocket with auto-reconnect const setupWebSocket = () => { // Close any existing connection if (socket) { socket.close() } setConnectionStatus("Connecting...") // Always use secure WebSocket protocol (wss) const wsBaseUrl = apiUrl.replace(/^https?:\/\//, "wss://") const wsUrl = `${wsBaseUrl}/share_poll?shareID=${shareId}` console.log("Connecting to WebSocket URL:", wsUrl) // Create WebSocket connection socket = new WebSocket(wsUrl) // Handle connection opening socket.onopen = () => { setConnectionStatus("Connected") console.log("WebSocket connection established") } // Handle incoming messages socket.onmessage = (event) => { console.log("WebSocket message received") try { const data = JSON.parse(event.data) as Message // Check if this is a session info message if (data.key.startsWith("session/info/")) { const infoContent = JSON.parse(data.content) as SessionInfo setSessionInfo(infoContent) console.log("Session info updated:", infoContent) return } // Check if it's a system message const msgContent = JSON.parse(data.content) as UIMessage if (msgContent.role === "system") { setSystemMessage(data) console.log("System message updated:", data) return } // Non-system messages setMessages((prev) => { // Check if message with this key already exists const existingIndex = prev.findIndex((msg) => msg.key === data.key) if (existingIndex >= 0) { // Update existing message const updated = [...prev] updated[existingIndex] = data return updated } else { // Add new message return [...prev, data] } }) } catch (error) { console.error("Error parsing WebSocket message:", error) } } // Handle errors socket.onerror = (error) => { console.error("WebSocket error:", error) setConnectionStatus("Error: Connection failed") } // Handle connection close and reconnection socket.onclose = (event) => { console.log(`WebSocket closed: ${event.code} ${event.reason}`) setConnectionStatus("Disconnected, reconnecting...") // Try to reconnect after 2 seconds clearTimeout(reconnectTimer) reconnectTimer = window.setTimeout( setupWebSocket, 2000, ) as unknown as number } } // Initial connection setupWebSocket() // Clean up on component unmount onCleanup(() => { console.log("Cleaning up WebSocket connection") if (socket) { socket.close() } clearTimeout(reconnectTimer) }) }) return (

Share: {params.id}

WebSocket Connection

Status: {connectionStatus()}

Live Updates

Session Information

Input Tokens:{" "} {sessionInfo()?.tokens?.input || 0}
Output Tokens:{" "} {sessionInfo()?.tokens?.output || 0}
Reasoning Tokens:{" "} {sessionInfo()?.tokens?.reasoning || 0}
{/* Display system message as context in the Session Information block */}

Context

{(() => { try { const parsed = JSON.parse( systemMessage()?.content || "", ) as UIMessage if ( parsed.parts && parsed.parts.length > 0 && parsed.parts[0].type === "text" ) { const text = parsed.parts[0].text || "" const lines = text.split("\n") const visibleLines = expandedSystemMessage() ? lines : lines.slice(0, 5) const hasMoreLines = lines.length > 5 return ( <>
{/* Create a modified version of the text part for the system message */} {(() => { // Create a modified part with truncated text const modifiedPart = { ...parsed.parts[0], text: visibleLines.join("\n"), } return ( <>
{modifiedPart.text}
{hasMoreLines && !expandedSystemMessage() && (
{lines.length - 5} more lines...
)} ) })()}
{hasMoreLines && ( )} ) } } catch (e) { return
Error parsing system message
} return null })()}
0} fallback={

Waiting for messages...

} >
    {(msg) => (
  • Key: {msg.key}
    {(() => { try { const parsed = JSON.parse(msg.content) as UIMessage const createdTime = parsed.metadata?.time?.created ? new Date( parsed.metadata.time.created, ).toLocaleString() : "Unknown time" return ( <>
    Full Content:
                                    {JSON.stringify(parsed, null, 2)}
                                  
    {parsed.parts && parsed.parts.length > 0 && (
    Role: {parsed.role || "Unknown"} {createdTime}
    part.type !== "step-start", )} > {(part) => { if (part.type === "text") { //{ // "type": "text", // "text": "Hello! How can I help you today?" //} return (
                                                [{part.type}] {part.text}{" "}
                                              
    ) } if (part.type === "reasoning") { //{ // "type": "reasoning", // "text": "The user asked for a weather forecast. I should call the 'getWeather' tool with the location 'San Francisco'.", // "providerMetadata": { "step_id": "reason_step_1" } //} return (
                                                [{part.type}] {part.text}
                                              
    ) } if (part.type === "tool-invocation") { return (
                                                      [{part.type}]
                                                    
    {" "} Tool:{" "} {part.toolInvocation.toolName}
    {parsed.metadata?.tool?.[ part.toolInvocation.toolCallId ]?.time?.start && parsed.metadata?.tool?.[ part.toolInvocation.toolCallId ]?.time?.end && ( {( (new Date( parsed.metadata?.tool?.[ part.toolInvocation.toolCallId ].time.end, ) - new Date( parsed.metadata?.tool?.[ part.toolInvocation.toolCallId ].time.start, )) / 1000 ).toFixed(2)} s )}
    {(() => { if ( part.toolInvocation.state === "partial-call" ) { //{ // "type": "tool-invocation", // "toolInvocation": { // "state": "partial-call", // "toolCallId": "tool_abc123", // "toolName": "searchWeb", // "argsTextDelta": "{\"query\":\"latest AI news" // } //} return ( <>
                                                          {
                                                            part.toolInvocation
                                                              .argsTextDelta
                                                          }
                                                        
    ... ) } if ( part.toolInvocation.state === "call" ) { //{ // "type": "tool-invocation", // "toolInvocation": { // "state": "call", // "toolCallId": "tool_abc123", // "toolName": "searchWeb", // "args": { "query": "latest AI news", "count": 3 } // } //} return (
                                                        {JSON.stringify(
                                                          part.toolInvocation.args,
                                                          null,
                                                          2,
                                                        )}
                                                      
    ) } if ( part.toolInvocation.state === "result" ) { //{ // "type": "tool-invocation", // "toolInvocation": { // "state": "result", // "toolCallId": "tool_abc123", // "toolName": "searchWeb", // "args": { "query": "latest AI news", "count": 3 }, // "result": [ // { "title": "AI SDK v5 Announced", "url": "..." }, // { "title": "New LLM Achieves SOTA", "url": "..." } // ] // } //} return ( <>
                                                          {JSON.stringify(
                                                            part.toolInvocation
                                                              .args,
                                                            null,
                                                            2,
                                                          )}
                                                        
                                                          {JSON.stringify(
                                                            part.toolInvocation
                                                              .result,
                                                            null,
                                                            2,
                                                          )}
                                                        
    ) } if ( part.toolInvocation.state === "error" ) { //{ // "type": "tool-invocation", // "toolInvocation": { // "state": "error", // "toolCallId": "tool_abc123", // "toolName": "searchWeb", // "args": { "query": "latest AI news", "count": 3 }, // "errorMessage": "API limit exceeded for searchWeb tool." // } //} return ( <>
                                                          {JSON.stringify(
                                                            part.toolInvocation
                                                              .args,
                                                            null,
                                                            2,
                                                          )}
                                                        
                                                          {
                                                            part.toolInvocation
                                                              .errorMessage
                                                          }
                                                        
    ) } })()}
    ) } if (part.type === "source") { //{ // "type": "source", // "source": { // "sourceType": "url", // "id": "doc_xyz789", // "url": "https://example.com/research-paper.pdf", // "title": "Groundbreaking AI Research Paper" // } //} return (
    [{part.type}]
    Source:{" "} {part.source.title || part.source.id}
    {part.source.url && ( )} {part.source.sourceType && (
    Type: {part.source.sourceType}
    )}
    ) } if (part.type === "file") { //{ // "type": "file", // "mediaType": "image/jpeg", // "filename": "cat_photo.jpg", // "url": "https://example-files.com/cats/cat_photo.jpg" //} const isImage = part.mediaType?.startsWith("image/") return (
    [{part.type}]
    File: {part.filename} {part.mediaType}
    {isImage && part.url ? (
    {
    ) : (
    {part.url ? ( Download: {part.filename} ) : (
    File attachment (no URL available)
    )}
    )}
    ) } return null }}
    )} ) } catch (e) { return (
    Content:
                                  {msg.content}
                                
    ) } })()}
  • )}
) }