feat(workflow): show variables in drawer
This commit is contained in:
@@ -151,6 +151,59 @@ export function DynamicVariablesDialog({
|
|||||||
onOpenChange: (open: boolean) => void;
|
onOpenChange: (open: boolean) => void;
|
||||||
definitions: Record<string, DynamicVariableDefinition>;
|
definitions: Record<string, DynamicVariableDefinition>;
|
||||||
onChange: (definitions: Record<string, DynamicVariableDefinition>) => void;
|
onChange: (definitions: Record<string, DynamicVariableDefinition>) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||||
|
<DialogContent className="max-h-[78vh] overflow-hidden rounded-2xl border-hairline bg-card p-0 sm:max-w-[520px]">
|
||||||
|
<DialogHeader className="border-b border-hairline px-6 py-5 text-left">
|
||||||
|
<DialogTitle className="flex items-center gap-2 text-base font-medium">
|
||||||
|
<Braces size={17} />
|
||||||
|
动态变量
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription className="text-xs leading-5">
|
||||||
|
助手配置中引用的自定义变量会自动出现在这里。
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<DynamicVariablesEditor
|
||||||
|
definitions={definitions}
|
||||||
|
onChange={onChange}
|
||||||
|
layout="dialog"
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DynamicVariablesPanel({
|
||||||
|
definitions,
|
||||||
|
onChange,
|
||||||
|
}: {
|
||||||
|
definitions: Record<string, DynamicVariableDefinition>;
|
||||||
|
onChange: (definitions: Record<string, DynamicVariableDefinition>) => void;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="flex min-h-0 flex-1 flex-col bg-canvas-soft px-4 pb-5 pt-4">
|
||||||
|
<p className="mb-3 shrink-0 text-xs leading-5 text-muted-foreground">
|
||||||
|
助手配置中引用的自定义变量会自动出现在这里。
|
||||||
|
</p>
|
||||||
|
<DynamicVariablesEditor
|
||||||
|
definitions={definitions}
|
||||||
|
onChange={onChange}
|
||||||
|
layout="panel"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function DynamicVariablesEditor({
|
||||||
|
definitions,
|
||||||
|
onChange,
|
||||||
|
layout,
|
||||||
|
}: {
|
||||||
|
definitions: Record<string, DynamicVariableDefinition>;
|
||||||
|
onChange: (definitions: Record<string, DynamicVariableDefinition>) => void;
|
||||||
|
layout: "dialog" | "panel";
|
||||||
}) {
|
}) {
|
||||||
const entries = Object.entries(definitions);
|
const entries = Object.entries(definitions);
|
||||||
const [copiedSystemVariable, setCopiedSystemVariable] = useState<string | null>(
|
const [copiedSystemVariable, setCopiedSystemVariable] = useState<string | null>(
|
||||||
@@ -168,20 +221,15 @@ export function DynamicVariablesDialog({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
<Tabs
|
||||||
<DialogContent className="max-h-[78vh] overflow-hidden rounded-2xl border-hairline bg-card p-0 sm:max-w-[520px]">
|
defaultValue="custom"
|
||||||
<DialogHeader className="border-b border-hairline px-6 py-5 text-left">
|
className={
|
||||||
<DialogTitle className="flex items-center gap-2 text-base font-medium">
|
layout === "panel"
|
||||||
<Braces size={17} />
|
? "flex min-h-0 flex-1 flex-col"
|
||||||
动态变量
|
: "min-h-0 px-6 pb-6"
|
||||||
</DialogTitle>
|
}
|
||||||
<DialogDescription className="text-xs leading-5">
|
>
|
||||||
助手配置中引用的自定义变量会自动出现在这里。
|
<TabsList className="grid w-full shrink-0 grid-cols-2 bg-surface-strong">
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
|
|
||||||
<Tabs defaultValue="custom" className="min-h-0 px-6 pb-6">
|
|
||||||
<TabsList className="grid w-full shrink-0 grid-cols-2 bg-surface-strong">
|
|
||||||
<TabsTrigger value="custom">
|
<TabsTrigger value="custom">
|
||||||
自定义变量
|
自定义变量
|
||||||
<span className="text-[11px] tabular-nums text-muted-foreground">
|
<span className="text-[11px] tabular-nums text-muted-foreground">
|
||||||
@@ -198,7 +246,11 @@ export function DynamicVariablesDialog({
|
|||||||
|
|
||||||
<TabsContent
|
<TabsContent
|
||||||
value="custom"
|
value="custom"
|
||||||
className="max-h-[calc(78vh-168px)] overflow-y-auto pt-3"
|
className={
|
||||||
|
layout === "panel"
|
||||||
|
? "scrollbar-subtle min-h-0 flex-1 overflow-y-auto pt-3"
|
||||||
|
: "max-h-[calc(78vh-168px)] overflow-y-auto pt-3"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
{entries.length === 0 ? (
|
{entries.length === 0 ? (
|
||||||
<div className="rounded-xl border border-dashed border-hairline-strong bg-canvas-soft px-4 py-5 text-center">
|
<div className="rounded-xl border border-dashed border-hairline-strong bg-canvas-soft px-4 py-5 text-center">
|
||||||
@@ -316,7 +368,11 @@ export function DynamicVariablesDialog({
|
|||||||
|
|
||||||
<TabsContent
|
<TabsContent
|
||||||
value="system"
|
value="system"
|
||||||
className="max-h-[calc(78vh-168px)] space-y-3 overflow-y-auto pt-3"
|
className={
|
||||||
|
layout === "panel"
|
||||||
|
? "scrollbar-subtle min-h-0 flex-1 space-y-3 overflow-y-auto pt-3"
|
||||||
|
: "max-h-[calc(78vh-168px)] space-y-3 overflow-y-auto pt-3"
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<p className="text-[11px] leading-5 text-muted-foreground">
|
<p className="text-[11px] leading-5 text-muted-foreground">
|
||||||
将完整引用复制到提示词或开场白中,不能只填写中文名称。
|
将完整引用复制到提示词或开场白中,不能只填写中文名称。
|
||||||
@@ -363,9 +419,7 @@ export function DynamicVariablesDialog({
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { Bug, Loader2, Save } from "lucide-react";
|
import { Bug, Loader2, Save } from "lucide-react";
|
||||||
|
|
||||||
import { DebugDrawer } from "@/components/assistant-editor/debug-preview";
|
import { DebugDrawer } from "@/components/assistant-editor/debug-preview";
|
||||||
import { DynamicVariablesDialog } from "@/components/assistant-editor/dynamic-variables";
|
import { DynamicVariablesPanel } from "@/components/assistant-editor/dynamic-variables";
|
||||||
import {
|
import {
|
||||||
AssistantIdentity,
|
AssistantIdentity,
|
||||||
EditableTitle,
|
EditableTitle,
|
||||||
@@ -115,6 +115,7 @@ export function WorkflowPage({
|
|||||||
disabled={!assistantId}
|
disabled={!assistantId}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setWorkflowSettingsOpen(false);
|
setWorkflowSettingsOpen(false);
|
||||||
|
setDynamicVariablesOpen(false);
|
||||||
setWorkflowEditingNodeId(null);
|
setWorkflowEditingNodeId(null);
|
||||||
setWorkflowEditingEdgeId(null);
|
setWorkflowEditingEdgeId(null);
|
||||||
setWorkflowDebugOpen(true);
|
setWorkflowDebugOpen(true);
|
||||||
@@ -144,7 +145,14 @@ export function WorkflowPage({
|
|||||||
onChange={setWorkflowGraph}
|
onChange={setWorkflowGraph}
|
||||||
settings={workflowSettings}
|
settings={workflowSettings}
|
||||||
onSettingsChange={setWorkflowSettings}
|
onSettingsChange={setWorkflowSettings}
|
||||||
onOpenDynamicVariables={() => setDynamicVariablesOpen(true)}
|
dynamicVariablesOpen={dynamicVariablesOpen}
|
||||||
|
onDynamicVariablesOpenChange={setDynamicVariablesOpen}
|
||||||
|
dynamicVariablesPanel={
|
||||||
|
<DynamicVariablesPanel
|
||||||
|
definitions={dynamicVariableDefinitions}
|
||||||
|
onChange={setWorkflowDynamicVariableDefinitions}
|
||||||
|
/>
|
||||||
|
}
|
||||||
editingNodeId={workflowEditingNodeId}
|
editingNodeId={workflowEditingNodeId}
|
||||||
onEditingNodeIdChange={setWorkflowEditingNodeId}
|
onEditingNodeIdChange={setWorkflowEditingNodeId}
|
||||||
editingEdgeId={workflowEditingEdgeId}
|
editingEdgeId={workflowEditingEdgeId}
|
||||||
@@ -179,13 +187,6 @@ export function WorkflowPage({
|
|||||||
knowledgeOptions={kbOptions}
|
knowledgeOptions={kbOptions}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<DynamicVariablesDialog
|
|
||||||
open={dynamicVariablesOpen}
|
|
||||||
onOpenChange={setDynamicVariablesOpen}
|
|
||||||
definitions={dynamicVariableDefinitions}
|
|
||||||
onChange={setWorkflowDynamicVariableDefinitions}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,9 @@ export function WorkflowCanvas({
|
|||||||
onSettingsChange,
|
onSettingsChange,
|
||||||
modelOptions,
|
modelOptions,
|
||||||
activeNodeId,
|
activeNodeId,
|
||||||
onOpenDynamicVariables,
|
dynamicVariablesOpen,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
|
dynamicVariablesPanel,
|
||||||
editingNodeId,
|
editingNodeId,
|
||||||
onEditingNodeIdChange,
|
onEditingNodeIdChange,
|
||||||
editingEdgeId,
|
editingEdgeId,
|
||||||
@@ -288,6 +290,7 @@ export function WorkflowCanvas({
|
|||||||
setAddSourceId(null);
|
setAddSourceId(null);
|
||||||
setAddPosition(null);
|
setAddPosition(null);
|
||||||
setSettingsOpen(false);
|
setSettingsOpen(false);
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
onDebugOpenChange(false);
|
onDebugOpenChange(false);
|
||||||
onEditingEdgeIdChange(null);
|
onEditingEdgeIdChange(null);
|
||||||
onEditingNodeIdChange(id);
|
onEditingNodeIdChange(id);
|
||||||
@@ -297,6 +300,7 @@ export function WorkflowCanvas({
|
|||||||
addSourceId,
|
addSourceId,
|
||||||
nodes,
|
nodes,
|
||||||
onDebugOpenChange,
|
onDebugOpenChange,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
onEditingEdgeIdChange,
|
onEditingEdgeIdChange,
|
||||||
onEditingNodeIdChange,
|
onEditingNodeIdChange,
|
||||||
screenToFlowPosition,
|
screenToFlowPosition,
|
||||||
@@ -456,11 +460,13 @@ export function WorkflowCanvas({
|
|||||||
);
|
);
|
||||||
const openSettings = useCallback(() => {
|
const openSettings = useCallback(() => {
|
||||||
onDebugOpenChange(false);
|
onDebugOpenChange(false);
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
onEditingNodeIdChange(null);
|
onEditingNodeIdChange(null);
|
||||||
onEditingEdgeIdChange(null);
|
onEditingEdgeIdChange(null);
|
||||||
setSettingsOpen(true);
|
setSettingsOpen(true);
|
||||||
}, [
|
}, [
|
||||||
onDebugOpenChange,
|
onDebugOpenChange,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
onEditingEdgeIdChange,
|
onEditingEdgeIdChange,
|
||||||
onEditingNodeIdChange,
|
onEditingNodeIdChange,
|
||||||
setSettingsOpen,
|
setSettingsOpen,
|
||||||
@@ -470,6 +476,7 @@ export function WorkflowCanvas({
|
|||||||
() => ({
|
() => ({
|
||||||
edit: (id: string) => {
|
edit: (id: string) => {
|
||||||
setSettingsOpen(false);
|
setSettingsOpen(false);
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
onDebugOpenChange(false);
|
onDebugOpenChange(false);
|
||||||
onEditingEdgeIdChange(null);
|
onEditingEdgeIdChange(null);
|
||||||
onEditingNodeIdChange(id);
|
onEditingNodeIdChange(id);
|
||||||
@@ -481,6 +488,7 @@ export function WorkflowCanvas({
|
|||||||
deleteNode,
|
deleteNode,
|
||||||
duplicateNode,
|
duplicateNode,
|
||||||
onDebugOpenChange,
|
onDebugOpenChange,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
onEditingEdgeIdChange,
|
onEditingEdgeIdChange,
|
||||||
onEditingNodeIdChange,
|
onEditingNodeIdChange,
|
||||||
setSettingsOpen,
|
setSettingsOpen,
|
||||||
@@ -490,6 +498,7 @@ export function WorkflowCanvas({
|
|||||||
() => ({
|
() => ({
|
||||||
edit: (id: string) => {
|
edit: (id: string) => {
|
||||||
setSettingsOpen(false);
|
setSettingsOpen(false);
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
onDebugOpenChange(false);
|
onDebugOpenChange(false);
|
||||||
onEditingNodeIdChange(null);
|
onEditingNodeIdChange(null);
|
||||||
onEditingEdgeIdChange(id);
|
onEditingEdgeIdChange(id);
|
||||||
@@ -499,11 +508,25 @@ export function WorkflowCanvas({
|
|||||||
[
|
[
|
||||||
deleteEdge,
|
deleteEdge,
|
||||||
onDebugOpenChange,
|
onDebugOpenChange,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
onEditingEdgeIdChange,
|
onEditingEdgeIdChange,
|
||||||
onEditingNodeIdChange,
|
onEditingNodeIdChange,
|
||||||
setSettingsOpen,
|
setSettingsOpen,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
const openDynamicVariables = useCallback(() => {
|
||||||
|
setSettingsOpen(false);
|
||||||
|
onDebugOpenChange(false);
|
||||||
|
onEditingNodeIdChange(null);
|
||||||
|
onEditingEdgeIdChange(null);
|
||||||
|
onDynamicVariablesOpenChange(true);
|
||||||
|
}, [
|
||||||
|
onDebugOpenChange,
|
||||||
|
onDynamicVariablesOpenChange,
|
||||||
|
onEditingEdgeIdChange,
|
||||||
|
onEditingNodeIdChange,
|
||||||
|
setSettingsOpen,
|
||||||
|
]);
|
||||||
|
|
||||||
const editingNode = nodes.find((n) => n.id === editingNodeId);
|
const editingNode = nodes.find((n) => n.id === editingNodeId);
|
||||||
const editingSpec = editingNode ? specsByType[editingNode.type as string] : null;
|
const editingSpec = editingNode ? specsByType[editingNode.type as string] : null;
|
||||||
@@ -580,6 +603,7 @@ export function WorkflowCanvas({
|
|||||||
className="h-10 w-10 rounded-full shadow-sm"
|
className="h-10 w-10 rounded-full shadow-sm"
|
||||||
aria-label="添加节点"
|
aria-label="添加节点"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
setAddSourceId(null);
|
setAddSourceId(null);
|
||||||
setAddPosition(null);
|
setAddPosition(null);
|
||||||
setAddOpen(true);
|
setAddOpen(true);
|
||||||
@@ -613,7 +637,7 @@ export function WorkflowCanvas({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
className="h-10 w-10 rounded-full border-hairline-strong bg-card text-foreground shadow-sm hover:bg-surface-strong"
|
className="h-10 w-10 rounded-full border-hairline-strong bg-card text-foreground shadow-sm hover:bg-surface-strong"
|
||||||
aria-label="动态变量"
|
aria-label="动态变量"
|
||||||
onClick={onOpenDynamicVariables}
|
onClick={openDynamicVariables}
|
||||||
>
|
>
|
||||||
<Braces size={17} />
|
<Braces size={17} />
|
||||||
</Button>
|
</Button>
|
||||||
@@ -642,6 +666,7 @@ export function WorkflowCanvas({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{(debugOpen ||
|
{(debugOpen ||
|
||||||
|
dynamicVariablesOpen ||
|
||||||
settingsOpen ||
|
settingsOpen ||
|
||||||
(editingNode && editingSpec) ||
|
(editingNode && editingSpec) ||
|
||||||
editingEdge) && (
|
editingEdge) && (
|
||||||
@@ -649,24 +674,30 @@ export function WorkflowCanvas({
|
|||||||
title={
|
title={
|
||||||
debugOpen
|
debugOpen
|
||||||
? undefined
|
? undefined
|
||||||
: settingsOpen
|
: dynamicVariablesOpen
|
||||||
? "工作流设置"
|
? "动态变量"
|
||||||
: editingEdge
|
: settingsOpen
|
||||||
? "编辑连接条件"
|
? "工作流设置"
|
||||||
: `编辑${editingSpec?.displayName ?? "节点"}`
|
: editingEdge
|
||||||
|
? "编辑连接条件"
|
||||||
|
: `编辑${editingSpec?.displayName ?? "节点"}`
|
||||||
}
|
}
|
||||||
closeLabel={
|
closeLabel={
|
||||||
settingsOpen
|
dynamicVariablesOpen
|
||||||
? "关闭工作流设置"
|
? "关闭动态变量"
|
||||||
: editingEdge
|
: settingsOpen
|
||||||
? "关闭边编辑"
|
? "关闭工作流设置"
|
||||||
: "关闭节点编辑"
|
: editingEdge
|
||||||
|
? "关闭边编辑"
|
||||||
|
: "关闭节点编辑"
|
||||||
}
|
}
|
||||||
onClose={
|
onClose={
|
||||||
debugOpen
|
debugOpen
|
||||||
? undefined
|
? undefined
|
||||||
: () => {
|
: () => {
|
||||||
if (settingsOpen) setSettingsOpen(false);
|
if (dynamicVariablesOpen) {
|
||||||
|
onDynamicVariablesOpenChange(false);
|
||||||
|
} else if (settingsOpen) setSettingsOpen(false);
|
||||||
else if (editingEdge) onEditingEdgeIdChange(null);
|
else if (editingEdge) onEditingEdgeIdChange(null);
|
||||||
else onEditingNodeIdChange(null);
|
else onEditingNodeIdChange(null);
|
||||||
}
|
}
|
||||||
@@ -674,6 +705,8 @@ export function WorkflowCanvas({
|
|||||||
>
|
>
|
||||||
{debugOpen ? (
|
{debugOpen ? (
|
||||||
debugPanel
|
debugPanel
|
||||||
|
) : dynamicVariablesOpen ? (
|
||||||
|
dynamicVariablesPanel
|
||||||
) : (
|
) : (
|
||||||
<div className="scrollbar-subtle min-h-0 flex-1 overflow-y-auto bg-canvas-soft px-4 pb-5 pt-4">
|
<div className="scrollbar-subtle min-h-0 flex-1 overflow-y-auto bg-canvas-soft px-4 pb-5 pt-4">
|
||||||
{settingsOpen ? (
|
{settingsOpen ? (
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ export type WorkflowEditorProps = {
|
|||||||
};
|
};
|
||||||
toolOptions?: ModelOption[];
|
toolOptions?: ModelOption[];
|
||||||
knowledgeOptions?: ModelOption[];
|
knowledgeOptions?: ModelOption[];
|
||||||
onOpenDynamicVariables: () => void;
|
dynamicVariablesOpen: boolean;
|
||||||
|
onDynamicVariablesOpenChange: (open: boolean) => void;
|
||||||
|
dynamicVariablesPanel: ReactNode;
|
||||||
editingNodeId: string | null;
|
editingNodeId: string | null;
|
||||||
onEditingNodeIdChange: (nodeId: string | null) => void;
|
onEditingNodeIdChange: (nodeId: string | null) => void;
|
||||||
editingEdgeId: string | null;
|
editingEdgeId: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user