mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
98 lines
2.3 KiB
TypeScript
98 lines
2.3 KiB
TypeScript
import { toast } from "sonner"
|
|
|
|
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": {
|
|
const requestId =
|
|
typeof payload.request_id === "string" ? payload.request_id : ""
|
|
const errorMessage =
|
|
typeof payload.message === "string" ? payload.message : ""
|
|
|
|
console.error("Pico error:", payload)
|
|
if (errorMessage) {
|
|
toast.error(errorMessage)
|
|
}
|
|
updateChatStore((prev) => ({
|
|
messages: requestId
|
|
? prev.messages.filter((msg) => msg.id !== requestId)
|
|
: prev.messages,
|
|
isTyping: false,
|
|
}))
|
|
break
|
|
}
|
|
|
|
case "pong":
|
|
break
|
|
|
|
default:
|
|
console.log("Unknown pico message type:", message.type)
|
|
}
|
|
}
|