/**
* JARVIS — StreamingMessageFeed
* Drop-in replacement for MessageFeed that shows streaming tokens in real-time.
* Uses useStreamingChat (WebSocket) with REST fallback.
*
* Replace with in ChatPage.jsx
* to enable live token streaming.
*/
import React, { useEffect, useRef, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import { Bot, User, Mic, Image, Wrench, Brain, Zap } from 'lucide-react'
import clsx from 'clsx'
import useAppStore from '../../stores/appStore'
import MessageBubble from './MessageBubble'
import { useStreamingChat } from '../../hooks/useStreamingChat'
export default function StreamingMessageFeed() {
const { getActiveMessages, activeSessionId, isLoading } = useAppStore()
const messages = getActiveMessages()
const bottomRef = useRef(null)
// WebSocket streaming state
const {
sendMessage: wsSend,
isStreaming,
currentTokens,
toolEvents,
error: wsError,
} = useStreamingChat(activeSessionId)
// Auto-scroll
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [messages.length, currentTokens, isLoading])
if (messages.length === 0 && !isStreaming) {
return
}
return (
{messages.map((msg) => (
))}
{/* Live streaming bubble */}
{(isStreaming || isLoading) && (
)}
)
}
// ── Message row (reused from MessageFeed) ──────────────────────
function MessageRow({ message, isUser }) {
if (message.content === '__typing__') return
return (
{message.used_tools?.length > 0 && (
{message.used_tools.map((tool) => (
))}
)}
)
}
// ── Live streaming bubble ──────────────────────────────────────
function StreamingBubble({ tokens, toolEvents, isLoading }) {
return (
{/* Tool use events */}
{toolEvents.map((evt, i) => (
{evt}
))}
{/* Token stream or typing indicator */}
{isLoading ? (
) : tokens && tokens !== '...' ? (
{tokens}
) : (
Reasoning…
)}
)
}
// ── Sub-components ─────────────────────────────────────────────
function Avatar({ isUser, modality }) {
const Icon = isUser ? User : Bot
return (
)
}
function ToolBadge({ name }) {
return (
{name}
)
}
function TypingDots() {
return (
)
}
function TypingBubble() {
return (
)
}
function StreamingEmptyState() {
return (
JARVIS ONLINE
Multi-modal AI assistant with real-time streaming. Speak, upload, or type.
{[
{ icon: '💬', label: 'Text Chat', hint: 'Streaming responses' },
{ icon: '🖼️', label: 'Vision', hint: 'BLIP + CLIP analysis' },
{ icon: '🎤', label: 'Voice', hint: 'Whisper + TTS' },
].map(({ icon, label, hint }) => (
))}
)
}