feat(FN-4150): complete Step 2 — preserve plugin workflow step mode metadata
Fusion-Task-Id: FN-4150 Fusion-Task-Lineage: 153c239b-f6cd-49e4-bc13-216e0d2ca815
This commit is contained in:
@@ -128,7 +128,7 @@ describe("TaskStore Workflow Steps", () => {
|
||||
expect(found).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should resolve plugin workflow steps from injected templates", async () => {
|
||||
it("should resolve plugin script-mode workflow steps from injected templates", async () => {
|
||||
store.setPluginWorkflowStepTemplates([
|
||||
{
|
||||
pluginId: "my-plugin",
|
||||
@@ -136,6 +136,58 @@ describe("TaskStore Workflow Steps", () => {
|
||||
id: "plugin:my-plugin:my-step",
|
||||
name: "My Plugin Step",
|
||||
description: "Plugin-provided step",
|
||||
mode: "script",
|
||||
phase: "pre-merge",
|
||||
scriptName: "my-plugin:run-step",
|
||||
prompt: "",
|
||||
toolMode: "readonly",
|
||||
defaultOn: false,
|
||||
modelProvider: "anthropic",
|
||||
modelId: "claude-sonnet-4-5",
|
||||
category: "Plugin",
|
||||
icon: "puzzle",
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const listed = await store.listWorkflowSteps();
|
||||
const listedStep = listed.find((candidate) => candidate.id === "plugin:my-plugin:my-step");
|
||||
expect(listedStep).toMatchObject({
|
||||
id: "plugin:my-plugin:my-step",
|
||||
templateId: "my-step",
|
||||
name: "My Plugin Step",
|
||||
mode: "script",
|
||||
phase: "pre-merge",
|
||||
scriptName: "my-plugin:run-step",
|
||||
defaultOn: false,
|
||||
modelProvider: "anthropic",
|
||||
modelId: "claude-sonnet-4-5",
|
||||
});
|
||||
|
||||
const step = await store.getWorkflowStep("plugin:my-plugin:my-step");
|
||||
expect(step).toMatchObject({
|
||||
id: "plugin:my-plugin:my-step",
|
||||
templateId: "my-step",
|
||||
mode: "script",
|
||||
phase: "pre-merge",
|
||||
scriptName: "my-plugin:run-step",
|
||||
defaultOn: false,
|
||||
modelProvider: "anthropic",
|
||||
modelId: "claude-sonnet-4-5",
|
||||
enabled: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("should resolve plugin prompt-mode workflow steps from injected templates", async () => {
|
||||
store.setPluginWorkflowStepTemplates([
|
||||
{
|
||||
pluginId: "my-plugin",
|
||||
template: {
|
||||
id: "plugin:my-plugin:prompt-step",
|
||||
name: "My Prompt Step",
|
||||
description: "Prompt plugin step",
|
||||
mode: "prompt",
|
||||
phase: "pre-merge",
|
||||
prompt: "Run plugin checks",
|
||||
toolMode: "readonly",
|
||||
category: "Plugin",
|
||||
@@ -144,14 +196,12 @@ describe("TaskStore Workflow Steps", () => {
|
||||
},
|
||||
]);
|
||||
|
||||
const step = await store.getWorkflowStep("plugin:my-plugin:my-step");
|
||||
const step = await store.getWorkflowStep("plugin:my-plugin:prompt-step");
|
||||
expect(step).toMatchObject({
|
||||
id: "plugin:my-plugin:my-step",
|
||||
templateId: "my-step",
|
||||
name: "My Plugin Step",
|
||||
id: "plugin:my-plugin:prompt-step",
|
||||
templateId: "prompt-step",
|
||||
mode: "prompt",
|
||||
phase: "pre-merge",
|
||||
enabled: true,
|
||||
prompt: "Run plugin checks",
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1042,7 +1042,14 @@ export class PluginLoader extends EventEmitter<{
|
||||
name: step.name,
|
||||
description: step.description,
|
||||
prompt: step.prompt ?? "",
|
||||
mode: step.mode,
|
||||
phase: step.phase,
|
||||
scriptName: step.scriptName,
|
||||
toolMode: step.toolMode,
|
||||
defaultOn: step.defaultOn,
|
||||
modelProvider: step.modelProvider,
|
||||
modelId: step.modelId,
|
||||
enabled: step.enabled,
|
||||
category: "Plugin",
|
||||
icon: "puzzle",
|
||||
},
|
||||
|
||||
@@ -7163,11 +7163,15 @@ ${stepsSection}`;
|
||||
templateId: stepId,
|
||||
name: entry.template.name,
|
||||
description: entry.template.description,
|
||||
mode: "prompt",
|
||||
phase: "pre-merge",
|
||||
prompt: entry.template.prompt,
|
||||
mode: entry.template.mode ?? "prompt",
|
||||
phase: entry.template.phase ?? "pre-merge",
|
||||
prompt: entry.template.prompt ?? "",
|
||||
scriptName: entry.template.scriptName,
|
||||
toolMode: entry.template.toolMode,
|
||||
enabled: entry.template.enabled ?? true,
|
||||
defaultOn: entry.template.defaultOn,
|
||||
modelProvider: entry.template.modelProvider,
|
||||
modelId: entry.template.modelId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
@@ -396,8 +396,20 @@ export interface WorkflowStepTemplate {
|
||||
description: string;
|
||||
/** Full agent prompt template */
|
||||
prompt: string;
|
||||
/** Execution mode for plugin-contributed templates; defaults to prompt. */
|
||||
mode?: WorkflowStepMode;
|
||||
/** Task lifecycle phase for plugin-contributed templates; defaults to pre-merge. */
|
||||
phase?: "pre-merge" | "post-merge";
|
||||
/** Script name for script-mode plugin templates. */
|
||||
scriptName?: string;
|
||||
/** Tool set available when the template runs as a prompt-mode step. */
|
||||
toolMode?: WorkflowStepToolMode;
|
||||
/** Whether this template should be auto-selected for new tasks. */
|
||||
defaultOn?: boolean;
|
||||
/** AI model provider override for prompt-mode templates. */
|
||||
modelProvider?: string;
|
||||
/** AI model ID override for prompt-mode templates. */
|
||||
modelId?: string;
|
||||
/** Grouping category (e.g., "Quality", "Security") */
|
||||
category: string;
|
||||
/** Optional icon identifier for UI (e.g., "file-text", "shield") */
|
||||
|
||||
Reference in New Issue
Block a user