From 028f402ff523924200a8949c40bf391f2e7f05a6 Mon Sep 17 00:00:00 2001 From: Henry Li Date: Fri, 16 Jan 2026 09:55:02 +0800 Subject: [PATCH] feat: store the local settings --- .../app/workspace/chats/[thread_id]/page.tsx | 14 ++---- .../src/components/workspace/input-box.tsx | 4 +- frontend/src/core/settings/hooks.ts | 34 ++++++++++++++ frontend/src/core/settings/index.ts | 2 + frontend/src/core/settings/local.ts | 44 +++++++++++++++++++ 5 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 frontend/src/core/settings/hooks.ts create mode 100644 frontend/src/core/settings/index.ts create mode 100644 frontend/src/core/settings/local.ts diff --git a/frontend/src/app/workspace/chats/[thread_id]/page.tsx b/frontend/src/app/workspace/chats/[thread_id]/page.tsx index 44d5e0e..233b80b 100644 --- a/frontend/src/app/workspace/chats/[thread_id]/page.tsx +++ b/frontend/src/app/workspace/chats/[thread_id]/page.tsx @@ -17,11 +17,8 @@ import { WorkspaceFooter, } from "@/components/workspace/workspace-container"; import { getLangGraphClient } from "@/core/api"; -import type { - AgentThread, - AgentThreadContext, - AgentThreadState, -} from "@/core/threads"; +import { useLocalSettings } from "@/core/settings"; +import type { AgentThread, AgentThreadState } from "@/core/threads"; import { titleOfThread } from "@/core/threads/utils"; import { uuid } from "@/core/utils/uuid"; @@ -36,11 +33,8 @@ export default function ChatPage() { [threadIdFromPath], ); const [threadId, setThreadId] = useState(null); - const [threadContext, setThreadContext] = useState({ - thread_id: "", - model: "deepseek-v3.2", - thinking_enabled: true, - }); + const { threadContext, setThreadContext } = useLocalSettings(); + useEffect(() => { if (threadIdFromPath !== "new") { setThreadId(threadIdFromPath); diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx index aaf4607..34189e7 100644 --- a/frontend/src/components/workspace/input-box.tsx +++ b/frontend/src/components/workspace/input-box.tsx @@ -49,8 +49,8 @@ export function InputBox({ }: Omit, "onSubmit"> & { assistantId?: string | null; status?: ChatStatus; - context: AgentThreadContext; - onContextChange?: (context: AgentThreadContext) => void; + context: Omit; + onContextChange?: (context: Omit) => void; onSubmit?: (message: PromptInputMessage) => void; onStop?: () => void; }) { diff --git a/frontend/src/core/settings/hooks.ts b/frontend/src/core/settings/hooks.ts new file mode 100644 index 0000000..7984763 --- /dev/null +++ b/frontend/src/core/settings/hooks.ts @@ -0,0 +1,34 @@ +import { useCallback, useState } from "react"; +import { useEffect } from "react"; + +import type { AgentThreadContext } from "../threads"; + +import { + DEFAULT_LOCAL_SETTINGS, + getLocalSettings, + updateContextOfLocalSettings, +} from "./local"; + +export function useLocalSettings() { + const [mounted, setMounted] = useState(false); + const [threadContextState, setThreadContextState] = useState< + Omit + >(DEFAULT_LOCAL_SETTINGS.context); + useEffect(() => { + if (!mounted) { + setThreadContextState(getLocalSettings().context); + } + setMounted(true); + }, [mounted]); + const setThreadContext = useCallback( + (context: Omit) => { + setThreadContextState(context); + updateContextOfLocalSettings(context); + }, + [], + ); + return { + threadContext: threadContextState, + setThreadContext, + }; +} diff --git a/frontend/src/core/settings/index.ts b/frontend/src/core/settings/index.ts new file mode 100644 index 0000000..3148fe6 --- /dev/null +++ b/frontend/src/core/settings/index.ts @@ -0,0 +1,2 @@ +export * from "./hooks"; +export * from "./local"; diff --git a/frontend/src/core/settings/local.ts b/frontend/src/core/settings/local.ts new file mode 100644 index 0000000..0afa962 --- /dev/null +++ b/frontend/src/core/settings/local.ts @@ -0,0 +1,44 @@ +import type { AgentThreadContext } from "../threads"; + +export const DEFAULT_LOCAL_SETTINGS: LocalSettings = { + context: { + model: "deepseek-v3.2", + thinking_enabled: true, + }, +}; + +const LOCAL_SETTINGS_KEY = "deerflow.local-settings"; + +export interface LocalSettings { + context: Omit; +} + +export function getLocalSettings(): LocalSettings { + if (typeof window === "undefined") { + return DEFAULT_LOCAL_SETTINGS; + } + const json = localStorage.getItem(LOCAL_SETTINGS_KEY); + try { + if (json) { + return JSON.parse(json); + } + } catch {} + return DEFAULT_LOCAL_SETTINGS; +} + +export function saveLocalSettings(settings: LocalSettings) { + localStorage.setItem(LOCAL_SETTINGS_KEY, JSON.stringify(settings)); +} + +export function updateContextOfLocalSettings( + context: LocalSettings["context"], +) { + const settings = getLocalSettings(); + saveLocalSettings({ + ...settings, + context: { + ...settings.context, + ...context, + }, + }); +}