refactor(store): migrate messages hook to Zustand store

- Move useMessages from apps/web to packages/store/src/messages.ts
- Convert useState to Zustand store for global message persistence
- Add reserved interfaces: updateMessage, loadMessages, getMessagesByAgent
- Update chat.tsx imports to use @multica/store

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Naiyuan Qing 2026-02-02 10:49:52 +08:00
parent 5275bc55fc
commit 97fce5b113
4 changed files with 68 additions and 29 deletions

View file

@ -9,10 +9,8 @@ import { MemoizedMarkdown } from "@multica/ui/components/markdown";
import { HugeiconsIcon } from "@hugeicons/react";
import { UserIcon, Copy01Icon, CheckmarkCircle02Icon } from "@hugeicons/core-free-icons";
import { toast } from "@multica/ui/components/ui/sonner";
import { useMessages } from "../hooks/use-messages";
import { useGateway } from "../hooks/use-gateway";
import { useHubStore } from "@multica/store";
import { useDeviceId } from "@multica/store";
import { useHubStore, useDeviceId, useMessagesStore } from "@multica/store";
import { useScrollFade } from "../hooks/use-scroll-fade";
import { cn } from "@multica/ui/lib/utils";
@ -26,7 +24,9 @@ const STATE_VARIANT: Record<string, "default" | "secondary" | "destructive" | "o
export function Chat() {
const activeAgentId = useHubStore((s) => s.activeAgentId)
const hub = useHubStore((s) => s.hub)
const { messages, addUserMessage, addAssistantMessage } = useMessages()
const addUserMessage = useMessagesStore((s) => s.addUserMessage)
const addAssistantMessage = useMessagesStore((s) => s.addAssistantMessage)
const messages = useMessagesStore((s) => s.messages)
const { state: gwState, send } = useGateway({
onMessage: (msg) => {

View file

@ -1,25 +0,0 @@
import { useState, useCallback } from "react"
import { v7 as uuidv7 } from "uuid"
export interface Message {
id: string
role: "user" | "assistant"
content: string
agentId: string
}
export function useMessages() {
const [messages, setMessages] = useState<Message[]>([])
const addUserMessage = useCallback((content: string, agentId: string) => {
setMessages(prev => [...prev, { id: uuidv7(), role: "user", content, agentId }])
}, [])
const addAssistantMessage = useCallback((content: string, agentId: string) => {
setMessages(prev => [...prev, { id: uuidv7(), role: "assistant", content, agentId }])
}, [])
const clearMessages = useCallback(() => setMessages([]), [])
return { messages, addUserMessage, addAssistantMessage, clearMessages }
}

View file

@ -2,3 +2,5 @@ export { useHubStore } from "./hub"
export type { HubInfo, Agent, HubStatus, HubStore } from "./hub"
export { useHubInit } from "./hub-init"
export { useDeviceId } from "./device-id"
export { useMessagesStore } from "./messages"
export type { Message, MessagesStore } from "./messages"

View file

@ -0,0 +1,62 @@
import { create } from "zustand"
import { v7 as uuidv7 } from "uuid"
export interface Message {
id: string
role: "user" | "assistant"
content: string
agentId: string
}
interface MessagesState {
messages: Message[]
}
interface MessagesActions {
addUserMessage: (content: string, agentId: string) => void
addAssistantMessage: (content: string, agentId: string) => void
updateMessage: (id: string, content: string) => void
loadMessages: (agentId: string, msgs: Message[]) => void
getMessagesByAgent: (agentId: string) => Message[]
clearMessages: (agentId?: string) => void
}
export type MessagesStore = MessagesState & MessagesActions
export const useMessagesStore = create<MessagesStore>()((set, get) => ({
messages: [],
addUserMessage: (content, agentId) => {
set((s) => ({
messages: [...s.messages, { id: uuidv7(), role: "user", content, agentId }],
}))
},
addAssistantMessage: (content, agentId) => {
set((s) => ({
messages: [...s.messages, { id: uuidv7(), role: "assistant", content, agentId }],
}))
},
updateMessage: (id, content) => {
set((s) => ({
messages: s.messages.map((m) => (m.id === id ? { ...m, content } : m)),
}))
},
loadMessages: (agentId, msgs) => {
set((s) => ({
messages: [...s.messages.filter((m) => m.agentId !== agentId), ...msgs],
}))
},
getMessagesByAgent: (agentId) => {
return get().messages.filter((m) => m.agentId === agentId)
},
clearMessages: (agentId?) => {
set((s) => ({
messages: agentId ? s.messages.filter((m) => m.agentId !== agentId) : [],
}))
},
}))