68 lines
2.4 KiB
TypeScript
68 lines
2.4 KiB
TypeScript
import { cn } from "@/lib/utils";
|
|
|
|
export type PositionBuiltinAgentKind = "summary" | "action_plan";
|
|
|
|
export interface PositionBuiltinAgentSwitchOption {
|
|
kind: PositionBuiltinAgentKind;
|
|
label: string;
|
|
disabled?: boolean;
|
|
disabledReason?: string;
|
|
}
|
|
|
|
interface PositionBuiltinAgentTabsProps {
|
|
activeKind: PositionBuiltinAgentKind | null;
|
|
options: PositionBuiltinAgentSwitchOption[];
|
|
isStreaming?: boolean;
|
|
onSelect: (kind: PositionBuiltinAgentKind) => void;
|
|
}
|
|
|
|
/**
|
|
* The two closing agents are intentionally exposed as full-name buttons
|
|
* instead of another dropdown: users can see the whole progression and jump
|
|
* between the two stages with one click.
|
|
*/
|
|
export function PositionBuiltinAgentTabs({
|
|
activeKind,
|
|
options,
|
|
isStreaming,
|
|
onSelect,
|
|
}: PositionBuiltinAgentTabsProps) {
|
|
if (options.length === 0) return null;
|
|
|
|
return (
|
|
<div
|
|
className="ml-auto mr-12 flex shrink-0 items-center gap-1.5"
|
|
aria-label="收口智能体切换"
|
|
title={isStreaming ? "当前智能体正在生成,完成后可切换" : "切换收口智能体"}
|
|
>
|
|
<span className="hidden shrink-0 text-[10px] font-semibold text-muted-foreground 2xl:inline">
|
|
收口智能体
|
|
</span>
|
|
{options.map((option) => {
|
|
const active = activeKind === option.kind;
|
|
const disabled = Boolean(option.disabled || (isStreaming && !active));
|
|
return (
|
|
<button
|
|
key={option.kind}
|
|
type="button"
|
|
disabled={disabled}
|
|
aria-pressed={active}
|
|
title={disabled ? option.disabledReason || "当前阶段暂不可进入" : option.label}
|
|
onClick={() => onSelect(option.kind)}
|
|
className={cn(
|
|
"inline-flex h-8 min-w-[126px] items-center justify-center rounded-lg border px-2.5 text-xs font-semibold transition",
|
|
active
|
|
? "border-primary bg-primary text-primary-foreground shadow-sm"
|
|
: "border-slate-200 bg-white text-slate-700 hover:border-primary/45 hover:text-primary dark:border-[#2b8ffe]/35 dark:bg-[#082d5f] dark:text-[#e8edf5]",
|
|
disabled &&
|
|
"cursor-not-allowed border-slate-200 bg-slate-100 text-slate-400 opacity-75 hover:border-slate-200 hover:text-slate-400 dark:border-[#2b8ffe]/20 dark:bg-[#082d5f]/55 dark:text-[#7595be]",
|
|
)}
|
|
>
|
|
{option.label}
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|