fix: isolate startup tools and preview dialogs
This commit is contained in:
@@ -645,6 +645,8 @@ function DebugVoicePanel({
|
||||
const recording = status === "connecting" || status === "connected";
|
||||
const [textDraft, setTextDraft] = useState("");
|
||||
const [inputMode, setInputMode] = useState<DebugInputMode>("mic");
|
||||
const [clientDialogContainer, setClientDialogContainer] =
|
||||
useState<HTMLDivElement | null>(null);
|
||||
const inChatView = view === "chat" && (!SHOW_VOICE_VIZ || showTranscript);
|
||||
const idleOrFailed = status === "idle" || status === "failed";
|
||||
const showIdleHub =
|
||||
@@ -682,10 +684,17 @@ function DebugVoicePanel({
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<div
|
||||
ref={setClientDialogContainer}
|
||||
className="relative isolate flex min-h-0 flex-1 flex-col overflow-hidden"
|
||||
>
|
||||
{/* 后端 TTS 音频经 WebRTC 媒体流过来,挂这里播放 */}
|
||||
<audio ref={audioRef} autoPlay playsInline className="hidden" />
|
||||
<ClientMessageDialog preview={preview} />
|
||||
<ClientMessageDialog
|
||||
preview={preview}
|
||||
container={clientDialogContainer}
|
||||
contained
|
||||
/>
|
||||
{vision && !showIdleHub ? (
|
||||
<DebugVisionWorkspace
|
||||
view={view}
|
||||
|
||||
@@ -135,13 +135,6 @@ export function PromptEditor({
|
||||
]
|
||||
: otherActions,
|
||||
});
|
||||
if (
|
||||
enabled &&
|
||||
defaultToolId &&
|
||||
!form.toolIds.includes(defaultToolId)
|
||||
) {
|
||||
updateForm("toolIds", [...form.toolIds, defaultToolId]);
|
||||
}
|
||||
}
|
||||
|
||||
function updateOpeningMessage(
|
||||
@@ -254,12 +247,7 @@ export function PromptEditor({
|
||||
value={openingMessage.toolId}
|
||||
options={showMessageTools}
|
||||
noneLabel="请选择 show_message 工具"
|
||||
onChange={(toolId) => {
|
||||
updateOpeningMessage({ toolId });
|
||||
if (toolId && !form.toolIds.includes(toolId)) {
|
||||
updateForm("toolIds", [...form.toolIds, toolId]);
|
||||
}
|
||||
}}
|
||||
onChange={(toolId) => updateOpeningMessage({ toolId })}
|
||||
/>
|
||||
{showMessageTools.length === 0 && (
|
||||
<p className="text-xs leading-5 text-muted-foreground">
|
||||
@@ -308,7 +296,8 @@ export function PromptEditor({
|
||||
/>
|
||||
</label>
|
||||
<p className="text-xs leading-5 text-muted-foreground">
|
||||
弹窗不可通过关闭按钮、Esc 或点击外部跳过;失败时将结束本次通话。
|
||||
弹窗不可跳过;失败时将结束本次通话。该工具仅用于开场,
|
||||
如需允许模型后续调用,请另外在“工具”区域勾选。
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -120,7 +120,15 @@ function actionVariant(style: MessageActionStyle) {
|
||||
* Renders messages requested by the agent through the generic Client Tool
|
||||
* channel. The tool result is held until the user chooses an action.
|
||||
*/
|
||||
export function ClientMessageDialog({ preview }: { preview: VoicePreview }) {
|
||||
export function ClientMessageDialog({
|
||||
preview,
|
||||
container,
|
||||
contained = false,
|
||||
}: {
|
||||
preview: VoicePreview;
|
||||
container?: HTMLElement | null;
|
||||
contained?: boolean;
|
||||
}) {
|
||||
const { registerClientTool, status } = preview;
|
||||
const [message, setMessage] = useState<MessageState | null>(null);
|
||||
const pendingRef = useRef<PendingMessage | null>(null);
|
||||
@@ -163,6 +171,7 @@ export function ClientMessageDialog({ preview }: { preview: VoicePreview }) {
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
modal={!contained}
|
||||
open={message !== null}
|
||||
onOpenChange={(open) => {
|
||||
if (!open && message?.dismissible) complete("dismissed");
|
||||
@@ -170,6 +179,8 @@ export function ClientMessageDialog({ preview }: { preview: VoicePreview }) {
|
||||
>
|
||||
<DialogContent
|
||||
className="gap-5 sm:max-w-md"
|
||||
portalContainer={container}
|
||||
contained={contained}
|
||||
showCloseButton={message?.dismissible ?? true}
|
||||
onEscapeKeyDown={(event) => {
|
||||
if (!message?.dismissible) event.preventDefault();
|
||||
|
||||
@@ -33,13 +33,17 @@ function DialogClose({
|
||||
|
||||
function DialogOverlay({
|
||||
className,
|
||||
contained = false,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Overlay> & {
|
||||
contained?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DialogPrimitive.Overlay
|
||||
data-slot="dialog-overlay"
|
||||
className={cn(
|
||||
"fixed inset-0 isolate z-50 bg-black/30 duration-100 supports-backdrop-filter:backdrop-blur-sm data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
||||
contained ? "absolute inset-0" : "fixed inset-0",
|
||||
"isolate z-50 bg-black/30 duration-100 supports-backdrop-filter:backdrop-blur-sm data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
@@ -51,17 +55,22 @@ function DialogContent({
|
||||
className,
|
||||
children,
|
||||
showCloseButton = true,
|
||||
portalContainer,
|
||||
contained = false,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
||||
showCloseButton?: boolean
|
||||
portalContainer?: Element | DocumentFragment | null
|
||||
contained?: boolean
|
||||
}) {
|
||||
return (
|
||||
<DialogPortal>
|
||||
<DialogOverlay />
|
||||
<DialogPortal container={portalContainer}>
|
||||
<DialogOverlay contained={contained} />
|
||||
<DialogPrimitive.Content
|
||||
data-slot="dialog-content"
|
||||
className={cn(
|
||||
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 rounded-4xl bg-popover p-6 text-sm text-popover-foreground shadow-xl ring-1 ring-foreground/5 duration-100 outline-none sm:max-w-md dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
||||
contained ? "absolute" : "fixed",
|
||||
"top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 rounded-4xl bg-popover p-6 text-sm text-popover-foreground shadow-xl ring-1 ring-foreground/5 duration-100 outline-none sm:max-w-md dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user