feat: enable edit context options

This commit is contained in:
Henry Li
2026-01-16 09:37:04 +08:00
parent 956f8f0cfb
commit 3f2bfded41
2 changed files with 113 additions and 5 deletions

View File

@@ -114,6 +114,8 @@ export default function ChatPage() {
className="max-w-(--container-width-md)" className="max-w-(--container-width-md)"
autoFocus={isNewThread} autoFocus={isNewThread}
status={thread.isLoading ? "streaming" : "ready"} status={thread.isLoading ? "streaming" : "ready"}
context={threadContext}
onContextChange={setThreadContext}
onSubmit={handleSubmit} onSubmit={handleSubmit}
onStop={handleStop} onStop={handleStop}
/> />

View File

@@ -1,6 +1,6 @@
import type { ChatStatus } from "ai"; import type { ChatStatus } from "ai";
import { LightbulbIcon, LightbulbOffIcon } from "lucide-react"; import { CheckIcon, LightbulbIcon, LightbulbOffIcon } from "lucide-react";
import { useCallback, type ComponentProps } from "react"; import { useCallback, useMemo, useState, type ComponentProps } from "react";
import { import {
PromptInput, PromptInput,
@@ -11,23 +11,70 @@ import {
PromptInputTextarea, PromptInputTextarea,
type PromptInputMessage, type PromptInputMessage,
} from "@/components/ai-elements/prompt-input"; } from "@/components/ai-elements/prompt-input";
import type { AgentThreadContext } from "@/core/threads";
import { cn } from "@/lib/utils"; 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"; 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({ export function InputBox({
className, className,
autoFocus, autoFocus,
status = "ready", status = "ready",
context,
onContextChange,
onSubmit, onSubmit,
onStop, onStop,
...props ...props
}: Omit<ComponentProps<typeof PromptInput>, "onSubmit"> & { }: Omit<ComponentProps<typeof PromptInput>, "onSubmit"> & {
assistantId?: string | null; assistantId?: string | null;
status?: ChatStatus; status?: ChatStatus;
context: AgentThreadContext;
onContextChange?: (context: AgentThreadContext) => void;
onSubmit?: (message: PromptInputMessage) => void; onSubmit?: (message: PromptInputMessage) => void;
onStop?: () => 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( const handleSubmit = useCallback(
async (message: PromptInputMessage) => { async (message: PromptInputMessage) => {
if (status === "streaming") { if (status === "streaming") {
@@ -62,13 +109,72 @@ export function InputBox({
</PromptInputBody> </PromptInputBody>
<PromptInputFooter className="flex"> <PromptInputFooter className="flex">
<div> <div>
<Tooltip content=""> <Tooltip
<PromptInputButton> content={
<LightbulbOffIcon className="size-4" /> 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> </PromptInputButton>
</Tooltip> </Tooltip>
</div> </div>
<div className="flex items-center gap-2"> <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 <PromptInputSubmit
className="rounded-full" className="rounded-full"
variant="outline" variant="outline"