diff --git a/frontend/src/components/workspace/input-box.tsx b/frontend/src/components/workspace/input-box.tsx index 880dc60..d04b823 100644 --- a/frontend/src/components/workspace/input-box.tsx +++ b/frontend/src/components/workspace/input-box.tsx @@ -11,6 +11,7 @@ import { PromptInputTextarea, type PromptInputMessage, } from "@/components/ai-elements/prompt-input"; +import { useModels } from "@/core/models/hooks"; import type { AgentThreadContext } from "@/core/threads"; import { cn } from "@/lib/utils"; @@ -26,15 +27,6 @@ import { import { Tooltip } from "./tooltip"; -const AVAILABLE_MODELS = [ - { name: "deepseek-v3.2", displayName: "DeepSeek v3.2", provider: "deepseek" }, - { - name: "doubao-seed-1.8", - displayName: "Doubao Seed 1.8", - provider: "doubao", - }, -]; - export function InputBox({ className, autoFocus, @@ -54,19 +46,22 @@ export function InputBox({ onStop?: () => void; }) { const [modelDialogOpen, setModelDialogOpen] = useState(false); + const { models } = useModels(); const selectedModel = useMemo( - () => AVAILABLE_MODELS.find((m) => m.name === context.model_name), - [context.model_name], + () => models.find((m) => m.name === context.model_name), + [context.model_name, models], ); const handleModelSelect = useCallback( (model_name: string) => { + const supports_thinking = selectedModel?.supports_thinking ?? false; onContextChange?.({ ...context, model_name, + thinking_enabled: supports_thinking && context.thinking_enabled, }); setModelDialogOpen(false); }, - [onContextChange, context], + [selectedModel?.supports_thinking, onContextChange, context], ); const handleThinkingToggle = useCallback(() => { onContextChange?.({ @@ -90,7 +85,7 @@ export function InputBox({ return ( - - {context.thinking_enabled ? ( - - ) : ( - - )} - + {selectedModel?.supports_thinking && ( + + {context.thinking_enabled ? ( + + ) : ( + + )} + + )}
@@ -140,20 +137,20 @@ export function InputBox({ - {selectedModel?.displayName} + {selectedModel?.display_name} - {AVAILABLE_MODELS.map((m) => ( + {models.map((m) => ( handleModelSelect(m.name)} > - {m.displayName} + {m.display_name} {m.name === context.model_name ? ( ) : ( diff --git a/frontend/src/core/models/api.ts b/frontend/src/core/models/api.ts new file mode 100644 index 0000000..5fe7776 --- /dev/null +++ b/frontend/src/core/models/api.ts @@ -0,0 +1,9 @@ +import { getBackendBaseURL } from "../config"; + +import type { Model } from "./types"; + +export async function loadModels() { + const res = fetch(`${getBackendBaseURL()}/api/models`); + const { models } = (await (await res).json()) as { models: Model[] }; + return models; +} diff --git a/frontend/src/core/models/hooks.ts b/frontend/src/core/models/hooks.ts new file mode 100644 index 0000000..4c96946 --- /dev/null +++ b/frontend/src/core/models/hooks.ts @@ -0,0 +1,11 @@ +import { useQuery } from "@tanstack/react-query"; + +import { loadModels } from "./api"; + +export function useModels() { + const { data, isLoading, error } = useQuery({ + queryKey: ["models"], + queryFn: () => loadModels(), + }); + return { models: data ?? [], isLoading, error }; +} diff --git a/frontend/src/core/models/index.ts b/frontend/src/core/models/index.ts new file mode 100644 index 0000000..1d58e1a --- /dev/null +++ b/frontend/src/core/models/index.ts @@ -0,0 +1,2 @@ +export * from "./api"; +export * from "./types"; diff --git a/frontend/src/core/models/types.ts b/frontend/src/core/models/types.ts new file mode 100644 index 0000000..f923d2d --- /dev/null +++ b/frontend/src/core/models/types.ts @@ -0,0 +1,7 @@ +export interface Model { + id: string; + name: string; + display_name: string; + description?: string | null; + supports_thinking?: boolean; +}