mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-02-04 18:06:48 +00:00
feat: add WebVTT context generation to chat WebSocket endpoint
- Import topics_to_webvtt_named and recordings controller - Add _get_is_multitrack helper function - Generate WebVTT context on WebSocket connection - Add get_context message type to retrieve WebVTT - Maintain backward compatibility with echo for other messages - Add test fixture and test for WebVTT context generation Implements task fn-1.2: WebVTT context generation for transcript chat
This commit is contained in:
102
.flow/specs/fn-1.5.md
Normal file
102
.flow/specs/fn-1.5.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Task 5: Frontend WebSocket Hook
|
||||
|
||||
**File:** `www/app/(app)/transcripts/useTranscriptChat.ts`
|
||||
**Lines:** ~60
|
||||
**Dependencies:** Task 1 (protocol defined)
|
||||
|
||||
## Objective
|
||||
Create React hook for WebSocket chat communication.
|
||||
|
||||
## Implementation
|
||||
```typescript
|
||||
import { useEffect, useState, useRef } from "react"
|
||||
import { WEBSOCKET_URL } from "../../lib/apiClient"
|
||||
|
||||
type Message = {
|
||||
id: string
|
||||
role: "user" | "assistant"
|
||||
text: string
|
||||
timestamp: Date
|
||||
}
|
||||
|
||||
export const useTranscriptChat = (transcriptId: string) => {
|
||||
const [messages, setMessages] = useState<Message[]>([])
|
||||
const [isStreaming, setIsStreaming] = useState(false)
|
||||
const [currentStreamingText, setCurrentStreamingText] = useState("")
|
||||
const wsRef = useRef<WebSocket | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const ws = new WebSocket(
|
||||
`${WEBSOCKET_URL}/v1/transcripts/${transcriptId}/chat`
|
||||
)
|
||||
wsRef.current = ws
|
||||
|
||||
ws.onopen = () => console.log("Chat WebSocket connected")
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const msg = JSON.parse(event.data)
|
||||
|
||||
switch (msg.type) {
|
||||
case "token":
|
||||
setIsStreaming(true)
|
||||
setCurrentStreamingText((prev) => prev + msg.text)
|
||||
break
|
||||
|
||||
case "done":
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
role: "assistant",
|
||||
text: currentStreamingText,
|
||||
timestamp: new Date(),
|
||||
},
|
||||
])
|
||||
setCurrentStreamingText("")
|
||||
setIsStreaming(false)
|
||||
break
|
||||
|
||||
case "error":
|
||||
console.error("Chat error:", msg.message)
|
||||
setIsStreaming(false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
ws.onerror = (error) => console.error("WebSocket error:", error)
|
||||
ws.onclose = () => console.log("Chat WebSocket closed")
|
||||
|
||||
return () => ws.close()
|
||||
}, [transcriptId, currentStreamingText])
|
||||
|
||||
const sendMessage = (text: string) => {
|
||||
if (!wsRef.current) return
|
||||
|
||||
setMessages((prev) => [
|
||||
...prev,
|
||||
{
|
||||
id: Date.now().toString(),
|
||||
role: "user",
|
||||
text,
|
||||
timestamp: new Date(),
|
||||
},
|
||||
])
|
||||
|
||||
wsRef.current.send(JSON.stringify({ type: "message", text }))
|
||||
}
|
||||
|
||||
return { messages, sendMessage, isStreaming, currentStreamingText }
|
||||
}
|
||||
```
|
||||
|
||||
## Validation
|
||||
- [ ] Hook connects to WebSocket
|
||||
- [ ] Sends messages to server
|
||||
- [ ] Receives streaming tokens
|
||||
- [ ] Accumulates tokens into messages
|
||||
- [ ] Handles done/error events
|
||||
- [ ] Closes connection on unmount
|
||||
|
||||
## Notes
|
||||
- Test with browser console first
|
||||
- Verify message format matches backend protocol
|
||||
Reference in New Issue
Block a user