From e60e1f6453dc8d6304a23b4a7fa47283e089ce44 Mon Sep 17 00:00:00 2001 From: Huarch Date: Thu, 4 Jun 2026 15:02:27 +0800 Subject: [PATCH] refactor: use backend chat sessions --- src/components/chat/AgentHistoryPanel.tsx | 3 - src/components/chat/GlobalChatbox.tsx | 24 +++---- src/components/chat/GlobalChatbox.types.ts | 26 +------- src/components/chat/chatStorage.test.ts | 34 +--------- src/components/chat/chatStorage.ts | 60 +++++++----------- .../chat/hooks/useAgentChatSession.test.tsx | 52 +++++++-------- .../chat/hooks/useAgentChatSession.ts | 63 +++++++------------ src/lib/chatStream.test.ts | 4 +- src/lib/chatStream.ts | 3 +- 9 files changed, 91 insertions(+), 178 deletions(-) diff --git a/src/components/chat/AgentHistoryPanel.tsx b/src/components/chat/AgentHistoryPanel.tsx index 79230a2..668c5a2 100644 --- a/src/components/chat/AgentHistoryPanel.tsx +++ b/src/components/chat/AgentHistoryPanel.tsx @@ -165,9 +165,6 @@ export const AgentHistoryPanel = ({ 历史会话 - - 本地保存于浏览器 - diff --git a/src/components/chat/GlobalChatbox.tsx b/src/components/chat/GlobalChatbox.tsx index a199342..a56c79e 100644 --- a/src/components/chat/GlobalChatbox.tsx +++ b/src/components/chat/GlobalChatbox.tsx @@ -60,7 +60,7 @@ export const GlobalChatbox: React.FC = ({ open, onClose }) => { const { messages, chatSessions, - activeStorageSessionId, + activeSessionId, branchGroups, branchTransition, isHydrating, @@ -129,33 +129,33 @@ export const GlobalChatbox: React.FC = ({ open, onClose }) => { }, []); const handleSelectSession = useCallback( - (storageSessionId: string) => { + (sessionId: string) => { composerRef.current?.clear(); - void switchSession(storageSessionId); + void switchSession(sessionId); }, [switchSession], ); const handleDeleteSession = useCallback( - (storageSessionId: string) => { - void removeSession(storageSessionId); + (sessionId: string) => { + void removeSession(sessionId); }, [removeSession], ); const handleRenameSession = useCallback( - (storageSessionId: string, title: string) => { - void renameSession(storageSessionId, title); + (sessionId: string, title: string) => { + void renameSession(sessionId, title); }, [renameSession], ); const handleRenameActiveSession = useCallback( (title: string) => { - if (!activeStorageSessionId) return; - void renameSession(activeStorageSessionId, title); + if (!activeSessionId) return; + void renameSession(activeSessionId, title); }, - [activeStorageSessionId, renameSession], + [activeSessionId, renameSession], ); const handleMouseDown = useCallback((event: React.MouseEvent) => { @@ -255,7 +255,7 @@ export const GlobalChatbox: React.FC = ({ open, onClose }) => { = ({ open, onClose }) => { > { handleNewConversation(); diff --git a/src/components/chat/GlobalChatbox.types.ts b/src/components/chat/GlobalChatbox.types.ts index acba4e7..4ac085b 100644 --- a/src/components/chat/GlobalChatbox.types.ts +++ b/src/components/chat/GlobalChatbox.types.ts @@ -66,23 +66,6 @@ export type Props = { export type SpeechState = "idle" | "playing" | "paused"; -export type LegacyPersistedChatState = { - messages: Message[]; - sessionId?: string; - branchGroups?: BranchGroup[]; -}; - -export type ChatSessionRecord = { - id: string; - title: string; - isTitleManuallyEdited?: boolean; - createdAt: number; - updatedAt: number; - sessionId?: string; - messages: Message[]; - branchGroups: BranchGroup[]; -}; - export type ChatSessionSummary = { id: string; title: string; @@ -90,17 +73,10 @@ export type ChatSessionSummary = { updatedAt: number; }; -export type ChatStorageMeta = { - key: "chat-meta"; - activeSessionId?: string; - migratedFromLocalStorage?: boolean; -}; - export type LoadedChatState = { - storageSessionId?: string; + sessionId?: string; title?: string; isTitleManuallyEdited?: boolean; messages: Message[]; - sessionId?: string; branchGroups: BranchGroup[]; }; diff --git a/src/components/chat/chatStorage.test.ts b/src/components/chat/chatStorage.test.ts index ffbef3d..f1117c9 100644 --- a/src/components/chat/chatStorage.test.ts +++ b/src/components/chat/chatStorage.test.ts @@ -1,5 +1,5 @@ import { - loadActiveChatState, + createEmptyChatState, saveActiveChatState, } from "./chatStorage"; @@ -11,17 +11,13 @@ jest.mock("@/lib/apiFetch", () => ({ describe("chatStorage backend-only persistence", () => { beforeEach(() => { - window.localStorage.clear(); apiFetch.mockReset(); }); - it("starts from an empty conversation instead of restoring a stored active id", async () => { - window.localStorage.setItem("tjwater_agent_active_session_id_v2", "chat-active-1"); - - const loaded = await loadActiveChatState(); + it("creates an empty initial conversation state without backend calls", () => { + const loaded = createEmptyChatState(); expect(loaded).toMatchObject({ - storageSessionId: undefined, title: undefined, messages: [], sessionId: undefined, @@ -30,24 +26,6 @@ describe("chatStorage backend-only persistence", () => { expect(apiFetch).not.toHaveBeenCalled(); }); - it("starts from an empty conversation when a project has a stored active id", async () => { - window.localStorage.setItem( - "tjwater_agent_active_session_id_v2:project-a", - "chat-project-a", - ); - window.localStorage.setItem( - "tjwater_agent_active_session_id_v2:project-b", - "chat-project-b", - ); - - const loaded = await loadActiveChatState("project-b"); - - expect(loaded.storageSessionId).toBeUndefined(); - expect(loaded.title).toBeUndefined(); - expect(loaded.messages).toEqual([]); - expect(apiFetch).not.toHaveBeenCalled(); - }); - it("creates a backend conversation when saving the first non-empty state", async () => { apiFetch.mockImplementation(async (url: string, init?: RequestInit) => { if (url.endsWith("/api/v1/agent/chat/session")) { @@ -75,7 +53,6 @@ describe("chatStorage backend-only persistence", () => { const savedSessionId = await saveActiveChatState( { - storageSessionId: undefined, title: "新对话", isTitleManuallyEdited: false, messages: [ @@ -89,13 +66,8 @@ describe("chatStorage backend-only persistence", () => { sessionId: undefined, branchGroups: [], }, - "project-a", ); expect(savedSessionId).toBe("chat-new-1"); - expect( - window.localStorage.getItem("tjwater_agent_active_session_id_v2:project-a"), - ).toBeNull(); }); - }); diff --git a/src/components/chat/chatStorage.ts b/src/components/chat/chatStorage.ts index bda1fbc..5cfed97 100644 --- a/src/components/chat/chatStorage.ts +++ b/src/components/chat/chatStorage.ts @@ -9,15 +9,14 @@ import type { } from "./GlobalChatbox.types"; import { cloneBranchGroups, cloneMessages } from "./GlobalChatbox.utils"; -type RemoteSessionPayload = { +type BackendSessionPayload = { id?: string; title?: string; created_at?: string | number; updated_at?: string | number; }; -const emptyLoadedChatState = (): LoadedChatState => ({ - storageSessionId: undefined, +export const createEmptyChatState = (): LoadedChatState => ({ title: undefined, isTitleManuallyEdited: false, messages: [], @@ -58,7 +57,7 @@ const toMillis = (value: string | number | undefined) => const normalizeTitle = (value?: string) => value?.trim() || "新对话"; -const fetchRemoteChatSessions = async (): Promise => { +const fetchBackendChatSessions = async (): Promise => { const response = await apiFetch(`${config.AGENT_URL}/api/v1/agent/chat/sessions`, { method: "GET", projectHeaderMode: "include", @@ -69,7 +68,7 @@ const fetchRemoteChatSessions = async (): Promise => { throw new Error(await response.text()); } const payload = (await response.json()) as { - sessions?: RemoteSessionPayload[]; + sessions?: BackendSessionPayload[]; }; return (payload.sessions ?? []) .map((session) => ({ @@ -82,7 +81,7 @@ const fetchRemoteChatSessions = async (): Promise => { .sort(compareSessionsByAnchorTime); }; -const fetchRemoteChatSession = async (sessionId: string): Promise => { +const fetchBackendChatSession = async (sessionId: string): Promise => { const response = await apiFetch( `${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}`, { @@ -94,7 +93,7 @@ const fetchRemoteChatSession = async (sessionId: string): Promise { @@ -146,7 +144,7 @@ const createRemoteChatSession = async (payload?: { return sessionId; }; -const saveRemoteChatState = async ( +const saveBackendChatState = async ( sessionId: string, state: LoadedChatState, ): Promise => { @@ -175,7 +173,7 @@ const saveRemoteChatState = async ( return payload.id ?? payload.session_id ?? sessionId; }; -const updateRemoteChatSessionTitle = async ( +const updateBackendChatSessionTitle = async ( sessionId: string, title: string, isTitleManuallyEdited?: boolean, @@ -201,7 +199,7 @@ const updateRemoteChatSessionTitle = async ( } }; -const deleteRemoteChatSession = async (sessionId: string) => { +const deleteBackendChatSession = async (sessionId: string) => { const response = await apiFetch( `${config.AGENT_URL}/api/v1/agent/chat/session/${encodeURIComponent(sessionId)}`, { @@ -216,42 +214,34 @@ const deleteRemoteChatSession = async (sessionId: string) => { } }; -export const loadActiveChatState = async ( - _projectId?: string | null, -): Promise => { - return emptyLoadedChatState(); -}; - export const saveActiveChatState = async ( state: LoadedChatState, - _projectId?: string | null, ): Promise => { - if (typeof window === "undefined") return state.storageSessionId; + if (typeof window === "undefined") return state.sessionId; if (!hasChatContent(state)) { return undefined; } - let remoteSessionId = state.sessionId ?? state.storageSessionId; - if (!remoteSessionId) { - remoteSessionId = await createRemoteChatSession(); + let backendSessionId = state.sessionId; + if (!backendSessionId) { + backendSessionId = await createBackendChatSession(); } - const savedSessionId = await saveRemoteChatState(remoteSessionId, { + const savedSessionId = await saveBackendChatState(backendSessionId, { ...state, - storageSessionId: remoteSessionId, - sessionId: remoteSessionId, + sessionId: backendSessionId, }); return savedSessionId; }; export const listChatSessions = async (): Promise => { if (typeof window === "undefined") return []; - return await fetchRemoteChatSessions(); + return await fetchBackendChatSessions(); }; export const updateChatSessionTitle = async ( - storageSessionId: string, + sessionId: string, title: string, options?: { isTitleManuallyEdited?: boolean; @@ -261,8 +251,8 @@ export const updateChatSessionTitle = async ( const normalizedTitle = title.trim(); if (!normalizedTitle) return; - await updateRemoteChatSessionTitle( - storageSessionId, + await updateBackendChatSessionTitle( + sessionId, normalizedTitle, options?.isTitleManuallyEdited, ); @@ -270,20 +260,18 @@ export const updateChatSessionTitle = async ( export const loadChatSessionById = async ( sessionId: string, - _projectId?: string | null, ): Promise => { - if (typeof window === "undefined") return emptyLoadedChatState(); + if (typeof window === "undefined") return createEmptyChatState(); - return await fetchRemoteChatSession(sessionId); + return await fetchBackendChatSession(sessionId); }; export const deleteChatSession = async ( sessionId: string, - _projectId?: string | null, ): Promise => { if (typeof window === "undefined") return undefined; - await deleteRemoteChatSession(sessionId); + await deleteBackendChatSession(sessionId); const nextActiveSession = (await listChatSessions())[0]; return nextActiveSession?.id; }; diff --git a/src/components/chat/hooks/useAgentChatSession.test.tsx b/src/components/chat/hooks/useAgentChatSession.test.tsx index d321c55..eba37a8 100644 --- a/src/components/chat/hooks/useAgentChatSession.test.tsx +++ b/src/components/chat/hooks/useAgentChatSession.test.tsx @@ -12,44 +12,38 @@ jest.mock("@/lib/chatStream", () => ({ streamAgentChat: jest.fn(async () => undefined), })); -const loadActiveChatState = jest.fn(); const listChatSessions = jest.fn(); const saveActiveChatState = jest.fn(); const updateChatSessionTitle = jest.fn(); jest.mock("../chatStorage", () => ({ - deleteChatSession: jest.fn(async () => undefined), - listChatSessions: (...args: unknown[]) => listChatSessions(...args), - loadActiveChatState: (...args: unknown[]) => loadActiveChatState(...args), - loadChatSessionById: jest.fn(async () => ({ - storageSessionId: "session-loaded", - title: "已存在会话", + createEmptyChatState: jest.fn(() => ({ + title: undefined, isTitleManuallyEdited: false, messages: [], sessionId: undefined, branchGroups: [], })), + deleteChatSession: jest.fn(async () => undefined), + listChatSessions: (...args: unknown[]) => listChatSessions(...args), + loadChatSessionById: jest.fn(async () => ({ + title: "已存在会话", + isTitleManuallyEdited: false, + messages: [], + sessionId: "session-loaded", + branchGroups: [], + })), saveActiveChatState: (...args: unknown[]) => saveActiveChatState(...args), updateChatSessionTitle: (...args: unknown[]) => updateChatSessionTitle(...args), })); describe("useAgentChatSession", () => { beforeEach(() => { - loadActiveChatState.mockReset(); listChatSessions.mockReset(); saveActiveChatState.mockReset(); updateChatSessionTitle.mockReset(); jest.mocked(streamAgentChat).mockReset(); - saveActiveChatState.mockImplementation(async (state) => state.storageSessionId); - - loadActiveChatState.mockResolvedValue({ - storageSessionId: undefined, - title: undefined, - isTitleManuallyEdited: false, - messages: [], - sessionId: undefined, - branchGroups: [], - }); + saveActiveChatState.mockImplementation(async (state) => state.sessionId); }); it("does not add a new empty session to history until there is actual chat content", async () => { @@ -70,7 +64,7 @@ describe("useAgentChatSession", () => { await waitFor(() => expect(result.current.sessionTitle).toBe("新对话")); expect(result.current.chatSessions).toEqual([]); - expect(result.current.activeStorageSessionId).toBeUndefined(); + expect(result.current.activeSessionId).toBeUndefined(); expect(result.current.messages).toEqual([]); expect(result.current.isStreaming).toBe(false); expect(listChatSessions).toHaveBeenCalledTimes(1); @@ -164,14 +158,6 @@ describe("useAgentChatSession", () => { it("ignores generated session titles after the title was edited manually", async () => { listChatSessions.mockResolvedValue([]); - loadActiveChatState.mockResolvedValue({ - storageSessionId: "session-1", - title: "手动标题", - isTitleManuallyEdited: true, - messages: [], - sessionId: "session-1", - branchGroups: [], - }); jest.mocked(streamAgentChat).mockImplementationOnce(async ({ onEvent }) => { onEvent({ type: "session_title", @@ -193,13 +179,23 @@ describe("useAgentChatSession", () => { await waitFor(() => expect(result.current.isHydrating).toBe(false)); + await act(async () => { + await result.current.switchSession("session-loaded"); + }); + + await act(async () => { + await result.current.renameSession("session-loaded", "手动标题"); + }); + + await waitFor(() => expect(updateChatSessionTitle).toHaveBeenCalled()); + await act(async () => { await result.current.sendPrompt("帮我分析一下"); }); expect(result.current.sessionTitle).toBe("手动标题"); expect(updateChatSessionTitle).not.toHaveBeenCalledWith( - "session-1", + "session-loaded", "自动标题", expect.anything(), ); diff --git a/src/components/chat/hooks/useAgentChatSession.ts b/src/components/chat/hooks/useAgentChatSession.ts index ac0feb8..8252bdf 100644 --- a/src/components/chat/hooks/useAgentChatSession.ts +++ b/src/components/chat/hooks/useAgentChatSession.ts @@ -19,9 +19,9 @@ import { createId, } from "../GlobalChatbox.utils"; import { + createEmptyChatState, deleteChatSession, listChatSessions, - loadActiveChatState, loadChatSessionById, saveActiveChatState, updateChatSessionTitle, @@ -50,7 +50,6 @@ type PromptRunOptions = { const createPersistedStateKey = (state: LoadedChatState) => JSON.stringify({ - storageSessionId: state.storageSessionId ?? null, title: state.title ?? null, isTitleManuallyEdited: state.isTitleManuallyEdited ?? false, sessionId: state.sessionId ?? null, @@ -151,7 +150,6 @@ export const useAgentChatSession = ({ onBeforeSend, getModel, }: UseAgentChatSessionOptions) => { - const storageSessionIdRef = useRef(undefined); const hydrationCompletedRef = useRef(false); const hydrationNonceRef = useRef(0); @@ -171,11 +169,10 @@ export const useAgentChatSession = ({ const titleUpdateNonceRef = useRef(0); const lastPersistedStateKeyRef = useRef( createPersistedStateKey({ - storageSessionId: undefined, + sessionId: undefined, title: undefined, isTitleManuallyEdited: false, messages: [], - sessionId: undefined, branchGroups: [], }), ); @@ -196,10 +193,8 @@ export const useAgentChatSession = ({ hydrationCompletedRef.current = false; if (!projectId) { - storageSessionIdRef.current = undefined; sessionIdRef.current = undefined; lastPersistedStateKeyRef.current = createPersistedStateKey({ - storageSessionId: undefined, title: undefined, isTitleManuallyEdited: false, messages: [], @@ -222,12 +217,11 @@ export const useAgentChatSession = ({ try { const [loadedState, sessions] = await Promise.all([ - loadActiveChatState(projectId), + Promise.resolve(createEmptyChatState()), listChatSessions(), ]); if (cancelled) return; - storageSessionIdRef.current = loadedState.storageSessionId; sessionIdRef.current = loadedState.sessionId; lastPersistedStateKeyRef.current = createPersistedStateKey(loadedState); hydrationCompletedRef.current = true; @@ -262,7 +256,6 @@ export const useAgentChatSession = ({ const currentHydrationNonce = hydrationNonceRef.current; const persistTimer = window.setTimeout(() => { const state: LoadedChatState = { - storageSessionId: storageSessionIdRef.current, title: sessionTitle, isTitleManuallyEdited: isSessionTitleManuallyEdited, messages, @@ -271,7 +264,6 @@ export const useAgentChatSession = ({ }; if ( isStreaming && - !state.storageSessionId && !state.sessionId && state.messages.length > 0 ) { @@ -283,13 +275,13 @@ export const useAgentChatSession = ({ return; } - void saveActiveChatState(state, projectId) - .then((storageSessionId) => { + void saveActiveChatState(state) + .then((sessionId) => { if (hydrationNonceRef.current !== currentHydrationNonce) return; - storageSessionIdRef.current = storageSessionId; + sessionIdRef.current = sessionId; lastPersistedStateKeyRef.current = createPersistedStateKey({ ...state, - storageSessionId, + sessionId, }); return listChatSessions(); }) @@ -431,10 +423,10 @@ export const useAgentChatSession = ({ const nextTitle = event.title.trim(); if (nextTitle && !isSessionTitleManuallyEditedRef.current) { setSessionTitle(nextTitle); - const currentStorageSessionId = storageSessionIdRef.current; - if (currentStorageSessionId) { + const currentSessionId = sessionIdRef.current; + if (currentSessionId) { const currentNonce = ++titleUpdateNonceRef.current; - void updateChatSessionTitle(currentStorageSessionId, nextTitle, { + void updateChatSessionTitle(currentSessionId, nextTitle, { isTitleManuallyEdited: false, }) .then(() => listChatSessions()) @@ -555,10 +547,8 @@ export const useAgentChatSession = ({ setBranchTransition(null); hydrationNonceRef.current += 1; titleUpdateNonceRef.current += 1; - storageSessionIdRef.current = undefined; sessionIdRef.current = undefined; lastPersistedStateKeyRef.current = createPersistedStateKey({ - storageSessionId: undefined, title: "新对话", isTitleManuallyEdited: false, messages: [], @@ -574,21 +564,20 @@ export const useAgentChatSession = ({ }, [isHydrating, isStreaming]); const switchSession = useCallback( - async (nextStorageSessionId: string) => { - if (isHydrating || isStreaming || storageSessionIdRef.current === nextStorageSessionId) { + async (nextSessionId: string) => { + if (isHydrating || isStreaming || sessionIdRef.current === nextSessionId) { return; } setIsHydrating(true); try { const [nextState, sessions] = await Promise.all([ - loadChatSessionById(nextStorageSessionId, projectId), + loadChatSessionById(nextSessionId), listChatSessions(), ]); hydrationNonceRef.current += 1; titleUpdateNonceRef.current += 1; - storageSessionIdRef.current = nextState.storageSessionId; sessionIdRef.current = nextState.sessionId; lastPersistedStateKeyRef.current = createPersistedStateKey(nextState); setBranchTransition(null); @@ -604,32 +593,29 @@ export const useAgentChatSession = ({ setIsHydrating(false); } }, - [isHydrating, isStreaming, projectId], + [isHydrating, isStreaming], ); const removeSession = useCallback( - async (targetStorageSessionId: string) => { + async (targetSessionId: string) => { if (isHydrating || isStreaming) return; try { const nextActiveSessionId = await deleteChatSession( - targetStorageSessionId, - projectId, + targetSessionId, ); const sessions = await listChatSessions(); setChatSessions(sessions); - if (storageSessionIdRef.current !== targetStorageSessionId) { + if (sessionIdRef.current !== targetSessionId) { return; } if (!nextActiveSessionId) { hydrationNonceRef.current += 1; titleUpdateNonceRef.current += 1; - storageSessionIdRef.current = undefined; sessionIdRef.current = undefined; lastPersistedStateKeyRef.current = createPersistedStateKey({ - storageSessionId: undefined, title: undefined, isTitleManuallyEdited: false, messages: [], @@ -647,12 +633,11 @@ export const useAgentChatSession = ({ setIsHydrating(true); const [nextState, sessionsAfterDelete] = await Promise.all([ - loadChatSessionById(nextActiveSessionId, projectId), + loadChatSessionById(nextActiveSessionId), listChatSessions(), ]); hydrationNonceRef.current += 1; titleUpdateNonceRef.current += 1; - storageSessionIdRef.current = nextState.storageSessionId; sessionIdRef.current = nextState.sessionId; lastPersistedStateKeyRef.current = createPersistedStateKey(nextState); setBranchTransition(null); @@ -668,7 +653,7 @@ export const useAgentChatSession = ({ setIsHydrating(false); } }, - [isHydrating, isStreaming, projectId], + [isHydrating, isStreaming], ); const sendPrompt = useCallback( @@ -679,22 +664,22 @@ export const useAgentChatSession = ({ ); const renameSession = useCallback( - async (targetStorageSessionId: string, nextTitle: string) => { + async (targetSessionId: string, nextTitle: string) => { const normalizedTitle = nextTitle.trim(); if (!normalizedTitle || isHydrating) return; try { - await updateChatSessionTitle(targetStorageSessionId, normalizedTitle, { + await updateChatSessionTitle(targetSessionId, normalizedTitle, { isTitleManuallyEdited: true, }); const sessions = await listChatSessions(); setChatSessions(sessions); - if (storageSessionIdRef.current === targetStorageSessionId) { + if (sessionIdRef.current === targetSessionId) { setSessionTitle(normalizedTitle); setIsSessionTitleManuallyEdited(true); lastPersistedStateKeyRef.current = createPersistedStateKey({ - storageSessionId: targetStorageSessionId, + sessionId: targetSessionId, title: normalizedTitle, isTitleManuallyEdited: true, messages, @@ -864,7 +849,7 @@ export const useAgentChatSession = ({ return { messages, chatSessions, - activeStorageSessionId: storageSessionIdRef.current, + activeSessionId: sessionIdRef.current, branchGroups, branchTransition, isHydrating, diff --git a/src/lib/chatStream.test.ts b/src/lib/chatStream.test.ts index 064ead6..79e400f 100644 --- a/src/lib/chatStream.test.ts +++ b/src/lib/chatStream.test.ts @@ -103,11 +103,11 @@ describe("streamAgentChat", () => { }); }); - it("parses legacy tool_call arguments when params is empty", async () => { + it("parses tool_call arguments when params is empty", async () => { apiFetch.mockResolvedValue({ ok: true, body: makeStream([ - 'event: tool_call\ndata: {"conversationId":"agent-1e75dd01-29e","tool":"locate_features","params":{},"arguments":"{\\"ids\\":[\\"142902\\"],\\"feature_type\\":\\"junction\\"}"}\n\n', + 'event: tool_call\ndata: {"session_id":"agent-1e75dd01-29e","tool":"locate_features","params":{},"arguments":"{\\"ids\\":[\\"142902\\"],\\"feature_type\\":\\"junction\\"}"}\n\n', 'event: done\ndata: {"session_id":"agent-1e75dd01-29e"}\n\n', ]), }); diff --git a/src/lib/chatStream.ts b/src/lib/chatStream.ts index 9a6d981..4fd94d5 100644 --- a/src/lib/chatStream.ts +++ b/src/lib/chatStream.ts @@ -163,7 +163,6 @@ export const streamAgentChat = async ({ try { const parsed = JSON.parse(data) as { session_id?: string; - conversationId?: string; content?: string; message?: string; detail?: string; @@ -223,7 +222,7 @@ export const streamAgentChat = async ({ } else if (event === "tool_call") { onEvent({ type: "tool_call", - sessionId: parsed.session_id ?? parsed.conversationId ?? "", + sessionId: parsed.session_id ?? "", tool: parsed.tool ?? "", params: resolveToolParams(parsed.params, parsed.arguments), });