refactor(frontend): optimize network queries and improve code readability (#919)

* refactor(frontend): optimize network queries and improve code readability
- useThreadStream: Add useStream with fetchStateHistory: {limit: 1}
- useThreads: Add select fields and disable refetchOnWindowFocus
- useModels: Disable refetchOnWindowFocus
- ChatPage and titleOfThread: Improve thread title logic
- loadModels: Refactor code for better readability

* fix: address the review comments of Copilot

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Zhiyunyao
2026-03-02 20:35:46 +08:00
committed by GitHub
parent a2f91c7594
commit 72df234636
5 changed files with 15 additions and 29 deletions

View File

@@ -30,12 +30,11 @@ import { Welcome } from "@/components/workspace/welcome";
import { useI18n } from "@/core/i18n/hooks"; import { useI18n } from "@/core/i18n/hooks";
import { useNotification } from "@/core/notification/hooks"; import { useNotification } from "@/core/notification/hooks";
import { useLocalSettings } from "@/core/settings"; import { useLocalSettings } from "@/core/settings";
import { type AgentThread, type AgentThreadState } from "@/core/threads"; import { type AgentThreadState } from "@/core/threads";
import { useSubmitThread, useThreadStream } from "@/core/threads/hooks"; import { useSubmitThread, useThreadStream } from "@/core/threads/hooks";
import { import {
pathOfThread, pathOfThread,
textOfMessage, textOfMessage,
titleOfThread,
} from "@/core/threads/utils"; } from "@/core/threads/utils";
import { uuid } from "@/core/utils/uuid"; import { uuid } from "@/core/utils/uuid";
import { env } from "@/env"; import { env } from "@/env";
@@ -102,7 +101,7 @@ export default function ChatPage() {
setFinalState(state); setFinalState(state);
if (document.hidden || !document.hasFocus()) { if (document.hidden || !document.hasFocus()) {
let body = "Conversation finished"; let body = "Conversation finished";
const lastMessage = state.messages[state.messages.length - 1]; const lastMessage = state.messages.at(-1);
if (lastMessage) { if (lastMessage) {
const textContent = textOfMessage(lastMessage); const textContent = textOfMessage(lastMessage);
if (textContent) { if (textContent) {
@@ -123,33 +122,20 @@ export default function ChatPage() {
if (thread.isLoading) setFinalState(null); if (thread.isLoading) setFinalState(null);
}, [thread.isLoading]); }, [thread.isLoading]);
const title = useMemo(() => { const title = thread.values?.title ?? "Untitled";
let result = isNewThread
? ""
: titleOfThread(thread as unknown as AgentThread);
if (result === "Untitled") {
result = "";
}
return result;
}, [thread, isNewThread]);
useEffect(() => { useEffect(() => {
const pageTitle = isNewThread const pageTitle = isNewThread
? t.pages.newChat ? t.pages.newChat
: thread.values?.title && thread.values.title !== "Untitled" : thread.isThreadLoading
? thread.values.title ? "Loading..."
: t.pages.untitled; : title === "Untitled" ? t.pages.untitled : title;
if (thread.isThreadLoading) { document.title = `${pageTitle} - ${t.pages.appName}`;
document.title = `Loading... - ${t.pages.appName}`;
} else {
document.title = `${pageTitle} - ${t.pages.appName}`;
}
}, [ }, [
isNewThread, isNewThread,
t.pages.newChat, t.pages.newChat,
t.pages.untitled, t.pages.untitled,
t.pages.appName, t.pages.appName,
thread.values.title, title,
thread.isThreadLoading, thread.isThreadLoading,
]); ]);

View File

@@ -3,7 +3,7 @@ import { getBackendBaseURL } from "../config";
import type { Model } from "./types"; import type { Model } from "./types";
export async function loadModels() { export async function loadModels() {
const res = fetch(`${getBackendBaseURL()}/api/models`); const res = await fetch(`${getBackendBaseURL()}/api/models`);
const { models } = (await (await res).json()) as { models: Model[] }; const { models } = (await res.json()) as { models: Model[] };
return models; return models;
} }

View File

@@ -7,6 +7,7 @@ export function useModels({ enabled = true }: { enabled?: boolean } = {}) {
queryKey: ["models"], queryKey: ["models"],
queryFn: () => loadModels(), queryFn: () => loadModels(),
enabled, enabled,
refetchOnWindowFocus: false,
}); });
return { models: data ?? [], isLoading, error }; return { models: data ?? [], isLoading, error };
} }

View File

@@ -34,7 +34,7 @@ export function useThreadStream({
assistantId: "lead_agent", assistantId: "lead_agent",
threadId: isNewThread ? undefined : threadId, threadId: isNewThread ? undefined : threadId,
reconnectOnMount: true, reconnectOnMount: true,
fetchStateHistory: true, fetchStateHistory: { limit: 1 },
onCustomEvent(event: unknown) { onCustomEvent(event: unknown) {
console.info(event); console.info(event);
if ( if (
@@ -192,6 +192,7 @@ export function useThreads(
limit: 50, limit: 50,
sortBy: "updated_at", sortBy: "updated_at",
sortOrder: "desc", sortOrder: "desc",
select: ["thread_id", "updated_at", "values"],
}, },
) { ) {
const apiClient = getAPIClient(); const apiClient = getAPIClient();
@@ -201,6 +202,7 @@ export function useThreads(
const response = await apiClient.threads.search<AgentThreadState>(params); const response = await apiClient.threads.search<AgentThreadState>(params);
return response as AgentThread[]; return response as AgentThread[];
}, },
refetchOnWindowFocus: false,
}); });
} }

View File

@@ -17,8 +17,5 @@ export function textOfMessage(message: BaseMessage) {
} }
export function titleOfThread(thread: AgentThread) { export function titleOfThread(thread: AgentThread) {
if (thread.values && "title" in thread.values) { return thread.values?.title ?? "Untitled";
return thread.values.title;
}
return "Untitled";
} }