82 lines
1.9 KiB
TypeScript
82 lines
1.9 KiB
TypeScript
|
|
import { normalizeUnixTimestamp } from "@/features/chat/state"
|
||
|
|
import { updateChatStore } from "@/store/chat"
|
||
|
|
|
||
|
|
export interface PicoMessage {
|
||
|
|
type: string
|
||
|
|
id?: string
|
||
|
|
session_id?: string
|
||
|
|
timestamp?: number | string
|
||
|
|
payload?: Record<string, unknown>
|
||
|
|
}
|
||
|
|
|
||
|
|
export function handlePicoMessage(
|
||
|
|
message: PicoMessage,
|
||
|
|
expectedSessionId: string,
|
||
|
|
) {
|
||
|
|
if (message.session_id && message.session_id !== expectedSessionId) {
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const payload = message.payload || {}
|
||
|
|
|
||
|
|
switch (message.type) {
|
||
|
|
case "message.create": {
|
||
|
|
const content = (payload.content as string) || ""
|
||
|
|
const messageId = (payload.message_id as string) || `pico-${Date.now()}`
|
||
|
|
const timestamp =
|
||
|
|
message.timestamp !== undefined &&
|
||
|
|
Number.isFinite(Number(message.timestamp))
|
||
|
|
? normalizeUnixTimestamp(Number(message.timestamp))
|
||
|
|
: Date.now()
|
||
|
|
|
||
|
|
updateChatStore((prev) => ({
|
||
|
|
messages: [
|
||
|
|
...prev.messages,
|
||
|
|
{
|
||
|
|
id: messageId,
|
||
|
|
role: "assistant",
|
||
|
|
content,
|
||
|
|
timestamp,
|
||
|
|
},
|
||
|
|
],
|
||
|
|
isTyping: false,
|
||
|
|
}))
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
case "message.update": {
|
||
|
|
const content = (payload.content as string) || ""
|
||
|
|
const messageId = payload.message_id as string
|
||
|
|
if (!messageId) {
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
updateChatStore((prev) => ({
|
||
|
|
messages: prev.messages.map((msg) =>
|
||
|
|
msg.id === messageId ? { ...msg, content } : msg,
|
||
|
|
),
|
||
|
|
}))
|
||
|
|
break
|
||
|
|
}
|
||
|
|
|
||
|
|
case "typing.start":
|
||
|
|
updateChatStore({ isTyping: true })
|
||
|
|
break
|
||
|
|
|
||
|
|
case "typing.stop":
|
||
|
|
updateChatStore({ isTyping: false })
|
||
|
|
break
|
||
|
|
|
||
|
|
case "error":
|
||
|
|
console.error("Pico error:", payload)
|
||
|
|
updateChatStore({ isTyping: false })
|
||
|
|
break
|
||
|
|
|
||
|
|
case "pong":
|
||
|
|
break
|
||
|
|
|
||
|
|
default:
|
||
|
|
console.log("Unknown pico message type:", message.type)
|
||
|
|
}
|
||
|
|
}
|