fix: show special module toggle on workflow modules
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-22 19:44:34 +08:00
parent 885708b2ec
commit 28a2531082
4 changed files with 67 additions and 14 deletions

View File

@ -55,6 +55,7 @@ import {
findAgentWorkflowOptionByKey,
findAgentWorkflowStepByKey,
flattenAgentWorkflowOptionTree,
getAgentWorkflowSpecialModuleRootOptions,
getEnabledAgentWorkflowOptionTree,
getAgentWorkflowCategoryLabels,
getAgentWorkflowConstraintSettings,
@ -508,6 +509,7 @@ function createWorkflowStepDraft(
description: "",
enabled: true,
sortOrder: stepIndex,
specialModuleEnabled: false,
options: [createWorkflowOptionDraft(stepKey, 0, [])],
children: [],
};
@ -2115,17 +2117,12 @@ export function AgentWorkflowSettingsClient({
);
const workflowSpecialModuleOptions = useMemo(
() =>
flattenAgentWorkflowSteps(deferredWorkflowSteps || []).flatMap(({ step }) =>
[...(step.options || [])]
.sort((left, right) => left.sortOrder - right.sortOrder)
.filter((option) => option.specialModuleEnabled)
.map((option) => ({
option,
stepKey: step.key,
stepTitle: step.title || step.key,
path: `${step.title || step.key} / ${option.buttonName || option.key}`,
}))
),
getAgentWorkflowSpecialModuleRootOptions(deferredWorkflowSteps || []).map((option) => ({
option,
stepKey: option.key,
stepTitle: option.buttonName || option.key,
path: option.buttonName || option.key,
})),
[deferredWorkflowSteps]
);
const workflowOptionGapDetails = useMemo(
@ -4962,8 +4959,25 @@ export function AgentWorkflowSettingsClient({
<div className="flex flex-wrap items-center gap-2">
<Badge variant="secondary">{optionCardCount} 张卡片</Badge>
<Badge variant="outline">卡片树结构</Badge>
{step.specialModuleEnabled ? <Badge variant="default">特殊模块</Badge> : null}
{isTopLevelStep ? (
<>
<div className="flex h-8 items-center gap-2 rounded-md border border-emerald-500/20 bg-emerald-500/5 px-2">
<span className="whitespace-nowrap text-xs font-medium text-emerald-700">
特殊模块
</span>
<Switch
checked={Boolean(step.specialModuleEnabled)}
onCheckedChange={(checked) =>
updateStep(step.key, (currentStep) => ({
...currentStep,
specialModuleEnabled: checked,
}))
}
className="scale-75"
aria-label={`设置模块 ${step.title || step.key} 为特殊模块`}
/>
</div>
<Button
type="button"
variant="outline"

View File

@ -923,6 +923,7 @@ const agentWorkflowStepSchema: z.ZodTypeAny = z.lazy(() =>
description: z.string().trim().max(300).nullable().optional(),
enabled: z.boolean().optional(),
sortOrder: z.number().min(0).max(999).optional(),
specialModuleEnabled: z.boolean().optional(),
options: z.array(agentWorkflowOptionSchema).max(100),
children: z.array(agentWorkflowStepSchema).max(100).optional(),
})

View File

@ -71,6 +71,7 @@ function cloneStep(step: AgentWorkflowStepUiConfig): AgentWorkflowStepUiConfig {
return {
...step,
description: step.description || "",
specialModuleEnabled: Boolean(step.specialModuleEnabled),
options: step.options.map(cloneOption),
children: (step.children || []).map(cloneStep),
};
@ -88,6 +89,7 @@ function createStep(
description,
enabled: true,
sortOrder: 0,
specialModuleEnabled: false,
options,
children: [],
};
@ -561,6 +563,39 @@ function sanitizeBlockedWorkflowStepTree(
}));
}
function createSpecialModuleRootOptionFromStep(
step: AgentWorkflowStepUiConfig
): AgentWorkflowOptionUiConfig {
return {
key: step.key,
buttonName: step.title || step.key,
description: step.description || "",
previewImageUrl: "",
enabled: step.enabled,
sortOrder: step.sortOrder,
promptFragment: "",
blockedOptionKeys: [],
specialModuleEnabled: true,
specialModuleExclusionEnabled: false,
specialModuleAllowedOptionKeys: [],
children: [
...(step.options || []),
...(step.children || []).map(createSpecialModuleRootOptionFromStep),
].sort((left, right) => left.sortOrder - right.sortOrder),
};
}
export function getAgentWorkflowSpecialModuleRootOptions(
steps: AgentWorkflowStepUiConfig[]
): AgentWorkflowOptionUiConfig[] {
return flattenAgentWorkflowSteps(steps).flatMap(({ step }) => {
const specialRoots = (step.options || []).filter((option) => option.specialModuleEnabled);
return step.specialModuleEnabled
? [createSpecialModuleRootOptionFromStep(step), ...specialRoots]
: specialRoots;
});
}
export function normalizeAgentWorkflowUiConfig(value: unknown): AgentWorkflowUiConfig {
const raw =
value && typeof value === "object" && !Array.isArray(value)
@ -1018,6 +1053,10 @@ export function normalizeAgentWorkflowUiConfig(value: unknown): AgentWorkflowUiC
description: normalizeText(stepRecord?.description, 300) || fallbackDescription,
enabled: normalizeBoolean(stepRecord?.enabled, defaultStep?.enabled ?? true),
sortOrder: normalizeNumber(stepRecord?.sortOrder, defaultStep?.sortOrder ?? stepIndex),
specialModuleEnabled: normalizeBoolean(
stepRecord?.specialModuleEnabled,
defaultStep?.specialModuleEnabled ?? false
),
options,
children:
depth < AGENT_WORKFLOW_MAX_TREE_DEPTH
@ -1544,9 +1583,7 @@ export function getAgentWorkflowBlockedOptionKeysForSelections(params: {
] as const)
)
);
const specialModuleRootOptions = visibleSteps.flatMap((step) =>
(step.options || []).filter((option) => option.specialModuleEnabled)
);
const specialModuleRootOptions = getAgentWorkflowSpecialModuleRootOptions(visibleSteps);
const directlyBlockedKeys = Array.from(
new Set(

View File

@ -100,6 +100,7 @@ export interface AgentWorkflowStepUiConfig {
description?: string | null;
enabled: boolean;
sortOrder: number;
specialModuleEnabled?: boolean;
options: AgentWorkflowOptionUiConfig[];
children?: AgentWorkflowStepUiConfig[];
}