feat: add deterministic message interaction stages
This commit is contained in:
@@ -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,
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user