diff --git a/app/(admin)/settings/agent-workflow/agent-workflow-settings-client.tsx b/app/(admin)/settings/agent-workflow/agent-workflow-settings-client.tsx
index 5bd94265a..80d449e5d 100644
--- a/app/(admin)/settings/agent-workflow/agent-workflow-settings-client.tsx
+++ b/app/(admin)/settings/agent-workflow/agent-workflow-settings-client.tsx
@@ -26,6 +26,7 @@ import {
Video,
} from "lucide-react";
import {
+ AGENT_WORKFLOW_MAX_OPTION_DEPTH,
AGENT_WORKFLOW_MAX_TREE_DEPTH,
countAgentWorkflowOptions,
countAgentWorkflowOptionTree,
@@ -104,10 +105,20 @@ const itemVariants = {
visible: { opacity: 1, y: 0 }
};
-const WORKFLOW_LEVEL_LABELS = ["一级模块", "二级模块", "三级模块"];
-const WORKFLOW_OPTION_LEVEL_LABELS = ["一级卡片", "二级卡片", "三级卡片"];
+const CHINESE_LEVEL_NUMERALS = ["一", "二", "三", "四", "五", "六", "七", "八"];
+const WORKFLOW_LEVEL_LABELS = CHINESE_LEVEL_NUMERALS.map((item) => `${item}级模块`);
+const WORKFLOW_OPTION_LEVEL_LABELS = CHINESE_LEVEL_NUMERALS.map((item) => `${item}级卡片`);
const PRESET_LIBRARY_LEVEL_LABELS = ["一级分类", "二级分类", "三级分类"];
+function getWorkflowLevelLabel(depth: number, kind: "模块" | "卡片") {
+ const labels =
+ kind === "模块" ? WORKFLOW_LEVEL_LABELS : WORKFLOW_OPTION_LEVEL_LABELS;
+ return (
+ labels[Math.max(0, Math.min(depth - 1, labels.length - 1))] ||
+ `第 ${depth} 级${kind}`
+ );
+}
+
function normalizeConfigOrdering(config: AgentWorkflowUiConfig): AgentWorkflowUiConfig {
return {
...config,
@@ -168,7 +179,7 @@ function createWorkflowStepDraft(
stepIndex: number,
existingStepKeys: string[]
): AgentWorkflowStepUiConfig {
- const levelLabel = WORKFLOW_LEVEL_LABELS[Math.max(0, Math.min(depth - 1, 2))] || "模块";
+ const levelLabel = getWorkflowLevelLabel(depth, "模块");
const stepKey = ensureUniqueWorkflowKey(`step_${depth}_${stepIndex + 1}`, existingStepKeys);
return {
key: stepKey,
@@ -880,7 +891,7 @@ export function AgentWorkflowSettingsClient({
const parentDepth = flattenAgentWorkflowOptionTree(step.options || []).find(
({ option }) => option.key === parentOptionKey
)?.depth;
- if (!parentOption || !parentDepth || parentDepth >= 3) {
+ if (!parentOption || !parentDepth || parentDepth >= AGENT_WORKFLOW_MAX_OPTION_DEPTH) {
return step;
}
@@ -1196,13 +1207,11 @@ export function AgentWorkflowSettingsClient({
): ReactNode => {
const refKey = `${step.key}:${option.key}`;
const isUploading = uploadingKey === refKey;
- const levelLabel =
- WORKFLOW_OPTION_LEVEL_LABELS[Math.max(0, Math.min(depth - 1, WORKFLOW_OPTION_LEVEL_LABELS.length - 1))] ||
- `第 ${depth} 级卡片`;
+ const levelLabel = getWorkflowLevelLabel(depth, "卡片");
const sortedChildren = [...(option.children || [])].sort(
(left, right) => left.sortOrder - right.sortOrder
);
- const canAddChild = depth < 3;
+ const canAddChild = depth < AGENT_WORKFLOW_MAX_OPTION_DEPTH;
return (
1 && "pl-4 sm:pl-6")}>
@@ -1334,7 +1343,7 @@ export function AgentWorkflowSettingsClient({
新增子卡片
) : (
-
已达三级
+
{`已达 ${AGENT_WORKFLOW_MAX_OPTION_DEPTH} 级`}
)}
@@ -1394,9 +1403,7 @@ export function AgentWorkflowSettingsClient({
indexPath: number[]
) => {
const stepLabel = indexPath.join(".");
- const levelLabel =
- WORKFLOW_LEVEL_LABELS[Math.max(0, Math.min(depth - 1, WORKFLOW_LEVEL_LABELS.length - 1))] ||
- `第 ${depth} 级模块`;
+ const levelLabel = getWorkflowLevelLabel(depth, "模块");
const rootOptions = [...(step.options || [])].sort((left, right) => left.sortOrder - right.sortOrder);
const optionCardCount = countAgentWorkflowOptionTree(step.options || []);
diff --git a/components/agents/AgentWorkflowPanelDarkV2.tsx b/components/agents/AgentWorkflowPanelDarkV2.tsx
index 7d7d15d25..48b1b855d 100644
--- a/components/agents/AgentWorkflowPanelDarkV2.tsx
+++ b/components/agents/AgentWorkflowPanelDarkV2.tsx
@@ -111,6 +111,50 @@ function getWorkflowStepSelectionSummary(params: {
return selectedOptions.map((option) => option.buttonName).join(" / ");
}
+function getWorkflowStepOptionLevels(params: {
+ step: AgentWorkflowUiConfig["steps"][number];
+ selectionValue?: string;
+}) {
+ const levels: Array<{
+ depth: number;
+ options: AgentWorkflowUiConfig["steps"][number]["options"];
+ selectedKey: string;
+ selectedOption: AgentWorkflowUiConfig["steps"][number]["options"][number] | null;
+ }> = [];
+ const selectedPath = getAgentWorkflowSelectedOptionPath({
+ step: params.step,
+ selectionValue: params.selectionValue,
+ });
+
+ let depth = 1;
+ let currentOptions = getEnabledAgentWorkflowOptionTree(params.step.options || []);
+
+ while (currentOptions.length > 0) {
+ const selectedKey = selectedPath[depth - 1]?.key || "";
+ const selectedOption =
+ currentOptions.find((option) => option.key === selectedKey) || null;
+
+ levels.push({
+ depth,
+ options: currentOptions,
+ selectedKey,
+ selectedOption,
+ });
+
+ const nextOptions = getEnabledAgentWorkflowOptionTree(
+ selectedOption?.children || []
+ );
+ if (!selectedOption || nextOptions.length === 0) {
+ break;
+ }
+
+ currentOptions = nextOptions;
+ depth += 1;
+ }
+
+ return levels;
+}
+
function StepOptionCard({
option,
step,
@@ -346,6 +390,7 @@ export function AgentWorkflowPanelDarkV2({
return Object.fromEntries(entries) as Record;
}, [resolvedConfig.steps, selections]);
const [activeEmbeddedStepKey, setActiveEmbeddedStepKey] = useState("");
+ const [activeEmbeddedOptionDepth, setActiveEmbeddedOptionDepth] = useState(1);
const [pendingAutoAdvanceStepKey, setPendingAutoAdvanceStepKey] = useState(null);
const activeEmbeddedStepIndex = Math.max(
flattenedResolvedSteps.findIndex(({ step }) => step.key === activeEmbeddedStepKey),
@@ -353,6 +398,21 @@ export function AgentWorkflowPanelDarkV2({
);
const activeEmbeddedStepEntry =
flattenedResolvedSteps[activeEmbeddedStepIndex] || flattenedResolvedSteps[0] || null;
+ const activeEmbeddedOptionLevels = useMemo(
+ () =>
+ activeEmbeddedStepEntry
+ ? getWorkflowStepOptionLevels({
+ step: activeEmbeddedStepEntry.step,
+ selectionValue: selections[activeEmbeddedStepEntry.step.key],
+ })
+ : [],
+ [activeEmbeddedStepEntry, selections]
+ );
+ const activeEmbeddedOptionLevel =
+ activeEmbeddedOptionLevels.find((level) => level.depth === activeEmbeddedOptionDepth) ||
+ activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1] ||
+ activeEmbeddedOptionLevels[0] ||
+ null;
useEffect(() => {
if (!embedded) {
@@ -376,6 +436,33 @@ export function AgentWorkflowPanelDarkV2({
setActiveEmbeddedStepKey(flattenedResolvedSteps[0]?.step.key || "");
}, [activeEmbeddedStepKey, embedded, flattenedResolvedSteps]);
+ useEffect(() => {
+ if (!embedded) {
+ return;
+ }
+
+ if (!activeEmbeddedStepEntry) {
+ if (activeEmbeddedOptionDepth !== 1) {
+ setActiveEmbeddedOptionDepth(1);
+ }
+ return;
+ }
+
+ const firstIncompleteDepth =
+ activeEmbeddedOptionLevels.find((level) => !level.selectedKey)?.depth ||
+ activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]?.depth ||
+ 1;
+
+ setActiveEmbeddedOptionDepth((current) => {
+ const maxDepth =
+ activeEmbeddedOptionLevels[activeEmbeddedOptionLevels.length - 1]?.depth || 1;
+ if (current < 1 || current > maxDepth) {
+ return firstIncompleteDepth;
+ }
+ return current;
+ });
+ }, [activeEmbeddedOptionDepth, activeEmbeddedOptionLevels, activeEmbeddedStepEntry, embedded]);
+
useEffect(() => {
if (!embedded || !activeEmbeddedStepEntry) {
return;
@@ -405,6 +492,7 @@ export function AgentWorkflowPanelDarkV2({
if (nextStep && nextStep.step.key !== activeEmbeddedStepKey) {
setActiveEmbeddedStepKey(nextStep.step.key);
+ setActiveEmbeddedOptionDepth(1);
}
setPendingAutoAdvanceStepKey(null);
@@ -611,12 +699,141 @@ export function AgentWorkflowPanelDarkV2({
})}
+
+ {activeEmbeddedOptionLevels.length > 0 ? (
+
+
+
+
子节点流程
+
+ 当前步骤的子节点会在这里逐级展开,减少单屏内容堆积。
+
+
+
+ 共 {activeEmbeddedOptionLevels.length} 级
+
+
+
+ {activeEmbeddedOptionLevels.map((level, levelIndex) => {
+ const isActive = level.depth === activeEmbeddedOptionDepth;
+ const summaryText =
+ level.selectedOption?.buttonName || "待选择";
+ return (
+
+
+ {levelIndex < activeEmbeddedOptionLevels.length - 1 ? (
+
+ ) : null}
+
+ );
+ })}
+
+
+ ) : null}
- {renderOptionLevels(
- activeEmbeddedStepEntry.step,
- getEnabledAgentWorkflowOptionTree(activeEmbeddedStepEntry.step.options || [])
- )}
+ {activeEmbeddedOptionLevel ? (
+
+
+
+ {activeEmbeddedOptionLevel.depth === 1
+ ? "主卡片"
+ : `${activeEmbeddedOptionLevel.depth}级子卡片`}
+
+
+ {activeEmbeddedOptionLevel.depth === 1
+ ? "先选择当前步骤的主卡片"
+ : "当前层级只展示这一层的子节点卡片,选完再进入下一层"}
+
+
+
+
+ {activeEmbeddedOptionLevel.options.map((option, optionIndex) => {
+ const currentSelectedKey = activeEmbeddedOptionLevel.selectedKey;
+ const nextChildren = getEnabledAgentWorkflowOptionTree(
+ option.children || []
+ );
+
+ return (
+ {
+ const selectedPathKeys = activeEmbeddedOptionLevels
+ .slice(0, activeEmbeddedOptionLevel.depth - 1)
+ .map((level) => level.selectedKey)
+ .filter(Boolean);
+ const nextKeys =
+ currentSelectedKey === option.key
+ ? selectedPathKeys
+ : [...selectedPathKeys, option.key];
+
+ setPendingAutoAdvanceStepKey(activeEmbeddedStepEntry.step.key);
+ onSelectionsChange({
+ ...selections,
+ [activeEmbeddedStepEntry.step.key]:
+ nextKeys.length > 0
+ ? serializeAgentWorkflowSelectionPath(nextKeys)
+ : undefined,
+ });
+
+ if (currentSelectedKey !== option.key && nextChildren.length > 0) {
+ setActiveEmbeddedOptionDepth(
+ activeEmbeddedOptionLevel.depth + 1
+ );
+ } else {
+ setActiveEmbeddedOptionDepth(
+ activeEmbeddedOptionLevel.depth
+ );
+ }
+ }}
+ index={optionIndex}
+ />
+ );
+ })}
+
+
+ ) : null}
) : null
) : (
@@ -638,7 +855,7 @@ export function AgentWorkflowPanelDarkV2({
{step.title}
{depth > 1 ? (
- {depth === 2 ? "二级模块" : "三级模块"}
+ {`${depth}级模块`}
) : null}
diff --git a/lib/agents/workflow-ui-config.ts b/lib/agents/workflow-ui-config.ts
index 5300da8a5..4294f0ef3 100644
--- a/lib/agents/workflow-ui-config.ts
+++ b/lib/agents/workflow-ui-config.ts
@@ -6,8 +6,8 @@ import type {
} from "@/types/agent";
export const AGENT_WORKFLOW_UI_CONFIG_KEY = "agent_workflow_ui_config";
-export const AGENT_WORKFLOW_MAX_TREE_DEPTH = 3;
-export const AGENT_WORKFLOW_MAX_OPTION_DEPTH = 3;
+export const AGENT_WORKFLOW_MAX_TREE_DEPTH = 8;
+export const AGENT_WORKFLOW_MAX_OPTION_DEPTH = 8;
export interface FlattenedAgentWorkflowStep {
step: AgentWorkflowStepUiConfig;