mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-03 14:22:13 +08:00
feat: enable edit context options
This commit is contained in:
@@ -114,6 +114,8 @@ export default function ChatPage() {
|
||||
className="max-w-(--container-width-md)"
|
||||
autoFocus={isNewThread}
|
||||
status={thread.isLoading ? "streaming" : "ready"}
|
||||
context={threadContext}
|
||||
onContextChange={setThreadContext}
|
||||
onSubmit={handleSubmit}
|
||||
onStop={handleStop}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ChatStatus } from "ai";
|
||||
import { LightbulbIcon, LightbulbOffIcon } from "lucide-react";
|
||||
import { useCallback, type ComponentProps } from "react";
|
||||
import { CheckIcon, LightbulbIcon, LightbulbOffIcon } from "lucide-react";
|
||||
import { useCallback, useMemo, useState, type ComponentProps } from "react";
|
||||
|
||||
import {
|
||||
PromptInput,
|
||||
@@ -11,23 +11,70 @@ import {
|
||||
PromptInputTextarea,
|
||||
type PromptInputMessage,
|
||||
} from "@/components/ai-elements/prompt-input";
|
||||
import type { AgentThreadContext } from "@/core/threads";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import {
|
||||
ModelSelector,
|
||||
ModelSelectorContent,
|
||||
ModelSelectorInput,
|
||||
ModelSelectorItem,
|
||||
ModelSelectorList,
|
||||
ModelSelectorLogo,
|
||||
ModelSelectorName,
|
||||
ModelSelectorTrigger,
|
||||
type ModelSelectorLogoProps,
|
||||
} from "../ai-elements/model-selector";
|
||||
|
||||
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,
|
||||
status = "ready",
|
||||
context,
|
||||
onContextChange,
|
||||
onSubmit,
|
||||
onStop,
|
||||
...props
|
||||
}: Omit<ComponentProps<typeof PromptInput>, "onSubmit"> & {
|
||||
assistantId?: string | null;
|
||||
status?: ChatStatus;
|
||||
context: AgentThreadContext;
|
||||
onContextChange?: (context: AgentThreadContext) => void;
|
||||
onSubmit?: (message: PromptInputMessage) => void;
|
||||
onStop?: () => void;
|
||||
}) {
|
||||
const [modelDialogOpen, setModelDialogOpen] = useState(false);
|
||||
const selectedModel = useMemo(
|
||||
() => AVAILABLE_MODELS.find((m) => m.name === context.model),
|
||||
[context.model],
|
||||
);
|
||||
const handleModelSelect = useCallback(
|
||||
(model: string) => {
|
||||
onContextChange?.({
|
||||
...context,
|
||||
model,
|
||||
});
|
||||
setModelDialogOpen(false);
|
||||
},
|
||||
[onContextChange, context],
|
||||
);
|
||||
const handleThinkingToggle = useCallback(() => {
|
||||
onContextChange?.({
|
||||
...context,
|
||||
thinking_enabled: !context.thinking_enabled,
|
||||
});
|
||||
}, [onContextChange, context]);
|
||||
const handleSubmit = useCallback(
|
||||
async (message: PromptInputMessage) => {
|
||||
if (status === "streaming") {
|
||||
@@ -62,13 +109,72 @@ export function InputBox({
|
||||
</PromptInputBody>
|
||||
<PromptInputFooter className="flex">
|
||||
<div>
|
||||
<Tooltip content="">
|
||||
<PromptInputButton>
|
||||
<LightbulbOffIcon className="size-4" />
|
||||
<Tooltip
|
||||
content={
|
||||
context.thinking_enabled ? (
|
||||
<div className="tex-sm flex flex-col gap-1">
|
||||
<div>Thinking is enabled</div>
|
||||
<div className="opacity-50">Click to disable thinking</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="tex-sm flex flex-col gap-1">
|
||||
<div>Thinking is disabled</div>
|
||||
<div className="opacity-50">Click to enable thinking</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
>
|
||||
<PromptInputButton onClick={handleThinkingToggle}>
|
||||
{context.thinking_enabled ? (
|
||||
<LightbulbIcon className="text-primary size-4" />
|
||||
) : (
|
||||
<LightbulbOffIcon className="size-4" />
|
||||
)}
|
||||
</PromptInputButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<ModelSelector
|
||||
open={modelDialogOpen}
|
||||
onOpenChange={setModelDialogOpen}
|
||||
>
|
||||
<ModelSelectorTrigger asChild>
|
||||
<PromptInputButton>
|
||||
<ModelSelectorLogo
|
||||
className="size-4"
|
||||
provider={
|
||||
selectedModel?.provider as ModelSelectorLogoProps["provider"]
|
||||
}
|
||||
/>
|
||||
<ModelSelectorName>
|
||||
{selectedModel?.displayName}
|
||||
</ModelSelectorName>
|
||||
</PromptInputButton>
|
||||
</ModelSelectorTrigger>
|
||||
<ModelSelectorContent>
|
||||
<ModelSelectorInput placeholder="Search models..." />
|
||||
<ModelSelectorList>
|
||||
{AVAILABLE_MODELS.map((m) => (
|
||||
<ModelSelectorItem
|
||||
key={m.name}
|
||||
value={m.name}
|
||||
onSelect={() => handleModelSelect(m.name)}
|
||||
>
|
||||
<ModelSelectorLogo
|
||||
className="size-4"
|
||||
provider={m.provider}
|
||||
/>
|
||||
<ModelSelectorName>{m.displayName}</ModelSelectorName>
|
||||
{m.name === context.model ? (
|
||||
<CheckIcon className="ml-auto size-4" />
|
||||
) : (
|
||||
<div className="ml-auto size-4" />
|
||||
)}
|
||||
</ModelSelectorItem>
|
||||
))}
|
||||
</ModelSelectorList>
|
||||
</ModelSelectorContent>
|
||||
</ModelSelector>
|
||||
<PromptInputSubmit
|
||||
className="rounded-full"
|
||||
variant="outline"
|
||||
|
||||
Reference in New Issue
Block a user