feat: add deterministic message interaction stages

This commit is contained in:
Xin Wang
2026-08-03 07:10:41 +08:00
parent 479a516546
commit 9daa46ed4d
26 changed files with 1356 additions and 414 deletions

View File

@@ -85,55 +85,18 @@ export function PromptEditor({
handlePromptVisionEnabledChange,
handlePromptModelChange,
}: PromptEditorProps) {
const openingMessage = form.startup.actions.find(
(action) => action.id === "opening_message" && action.phase === "opening",
);
const openingArguments = openingMessage?.arguments ?? {};
const openingButtons = Array.isArray(openingArguments.actions)
? openingArguments.actions
: [];
const openingButton =
openingButtons[0] && typeof openingButtons[0] === "object"
? (openingButtons[0] as Record<string, unknown>)
: {};
const showMessageTools = tools
.filter(
(tool) =>
tool.status === "active" &&
tool.type === "client" &&
tool.functionName === "show_message" &&
tool.definition.type === "client" &&
tool.definition.config.waitForResponse &&
tool.definition.config.responseWaitMode === "session",
)
.map((tool) => ({ value: tool.id, label: tool.name }));
const openingMessage = form.startup.openingMessage;
function setOpeningMessage(enabled: boolean) {
const otherActions = form.startup.actions.filter(
(action) => action.id !== "opening_message",
);
const defaultToolId = showMessageTools[0]?.value ?? "";
updateForm("startup", {
executionMode: "sequential",
actions: enabled
? [
...otherActions,
{
id: "opening_message",
phase: "opening",
toolId: defaultToolId,
required: true,
arguments: {
title: "重要提示",
message: "请确认已阅读以上信息。",
actions: [
{ id: "confirmed", label: "确认", style: "primary" },
],
dismissible: false,
},
},
]
: otherActions,
...form.startup,
openingMessage: enabled
? {
title: "重要提示",
message: "请确认已阅读以上信息。",
confirmLabel: "确认",
}
: null,
});
}
@@ -143,16 +106,10 @@ export function PromptEditor({
if (!openingMessage) return;
updateForm("startup", {
...form.startup,
actions: form.startup.actions.map((action) =>
action.id === openingMessage.id ? { ...action, ...patch } : action,
),
openingMessage: { ...openingMessage, ...patch },
});
}
function updateOpeningArguments(patch: Record<string, unknown>) {
updateOpeningMessage({ arguments: { ...openingArguments, ...patch } });
}
return (
<div className="-mt-6 flex h-full flex-col gap-4">
<div className="flex shrink-0 items-center justify-between gap-6 border-b border-hairline pb-3 pt-1">
@@ -235,33 +192,21 @@ export function PromptEditor({
<div className="mt-4 space-y-3 border-t border-hairline pt-4">
<ToggleRow
title="开场确认弹窗"
description="与开场白同时显示,确认且播报完成后才允许用户开始对话。"
description="与开场白同时显示,用户确认后即可开始对话,不等待播报完成。"
checked={Boolean(openingMessage)}
onChange={setOpeningMessage}
/>
{openingMessage && (
<div className="space-y-3 rounded-xl border border-hairline bg-canvas-soft p-4">
<ResourceSelectField
label="消息工具"
value={openingMessage.toolId}
options={showMessageTools}
noneLabel="请选择 show_message 工具"
onChange={(toolId) => updateOpeningMessage({ toolId })}
/>
{showMessageTools.length === 0 && (
<p className="text-xs leading-5 text-muted-foreground">
functionName show_message Client Tool
</p>
)}
<label className="block">
<span className="mb-1.5 block text-sm font-medium text-foreground">
</span>
<Input
value={String(openingArguments.title ?? "")}
value={openingMessage.title}
onChange={(event) =>
updateOpeningArguments({ title: event.target.value })
updateOpeningMessage({ title: event.target.value })
}
placeholder="重要提示"
className="border-hairline-strong bg-background"
@@ -269,8 +214,8 @@ export function PromptEditor({
</label>
<TextAreaField
label="重要信息"
value={String(openingArguments.message ?? "")}
onChange={(message) => updateOpeningArguments({ message })}
value={openingMessage.message}
onChange={(message) => updateOpeningMessage({ message })}
placeholder="请输入需要用户确认的重要信息"
rows={4}
/>
@@ -279,16 +224,10 @@ export function PromptEditor({
</span>
<Input
value={String(openingButton.label ?? "")}
value={openingMessage.confirmLabel}
onChange={(event) =>
updateOpeningArguments({
actions: [
{
id: "confirmed",
label: event.target.value,
style: "primary",
},
],
updateOpeningMessage({
confirmLabel: event.target.value,
})
}
placeholder="确认"
@@ -296,8 +235,8 @@ export function PromptEditor({
/>
</label>
<p className="text-xs leading-5 text-muted-foreground">
</p>
</div>
)}
@@ -318,10 +257,14 @@ export function PromptEditor({
value={form.runtimeMode}
onChange={(runtimeMode) => {
updateForm("runtimeMode", runtimeMode);
if (runtimeMode === "realtime" && form.startup.actions.length) {
if (
runtimeMode === "realtime" &&
(form.startup.actions.length || form.startup.openingMessage)
) {
updateForm("startup", {
executionMode: "sequential",
actions: [],
openingMessage: null,
});
}
}}