patchwork-os 0.2.0-alpha.21 → 0.2.0-alpha.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -12
- package/deploy/bootstrap-vps.sh +184 -0
- package/dist/approvalHttp.js +6 -1
- package/dist/approvalHttp.js.map +1 -1
- package/dist/automation.d.ts +20 -0
- package/dist/automation.js +35 -0
- package/dist/automation.js.map +1 -1
- package/dist/bridge.js +22 -4
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeToken.js +57 -19
- package/dist/bridgeToken.js.map +1 -1
- package/dist/commands/recipe.d.ts +256 -0
- package/dist/commands/recipe.js +1313 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +9 -0
- package/dist/config.js.map +1 -1
- package/dist/connectors/baseConnector.d.ts +117 -0
- package/dist/connectors/baseConnector.js +213 -0
- package/dist/connectors/baseConnector.js.map +1 -0
- package/dist/connectors/confluence.d.ts +111 -0
- package/dist/connectors/confluence.js +406 -0
- package/dist/connectors/confluence.js.map +1 -0
- package/dist/connectors/fixtureLibrary.d.ts +21 -0
- package/dist/connectors/fixtureLibrary.js +70 -0
- package/dist/connectors/fixtureLibrary.js.map +1 -0
- package/dist/connectors/fixtureRecorder.d.ts +1 -0
- package/dist/connectors/fixtureRecorder.js +35 -0
- package/dist/connectors/fixtureRecorder.js.map +1 -0
- package/dist/connectors/github.js +2 -11
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gmail.js +23 -7
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.js +23 -7
- package/dist/connectors/googleCalendar.js.map +1 -1
- package/dist/connectors/jira.d.ts +98 -0
- package/dist/connectors/jira.js +379 -0
- package/dist/connectors/jira.js.map +1 -0
- package/dist/connectors/linear.js +2 -11
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpOAuth.d.ts +1 -0
- package/dist/connectors/mcpOAuth.js +30 -4
- package/dist/connectors/mcpOAuth.js.map +1 -1
- package/dist/connectors/mockConnector.d.ts +28 -0
- package/dist/connectors/mockConnector.js +81 -0
- package/dist/connectors/mockConnector.js.map +1 -0
- package/dist/connectors/notion.d.ts +143 -0
- package/dist/connectors/notion.js +424 -0
- package/dist/connectors/notion.js.map +1 -0
- package/dist/connectors/sentry.js +2 -11
- package/dist/connectors/sentry.js.map +1 -1
- package/dist/connectors/slack.js +50 -15
- package/dist/connectors/slack.js.map +1 -1
- package/dist/connectors/tokenStorage.d.ts +35 -0
- package/dist/connectors/tokenStorage.js +394 -0
- package/dist/connectors/tokenStorage.js.map +1 -0
- package/dist/connectors/zendesk.d.ts +104 -0
- package/dist/connectors/zendesk.js +424 -0
- package/dist/connectors/zendesk.js.map +1 -0
- package/dist/featureFlags.d.ts +73 -0
- package/dist/featureFlags.js +203 -0
- package/dist/featureFlags.js.map +1 -0
- package/dist/fp/automationInterpreter.js +1 -0
- package/dist/fp/automationInterpreter.js.map +1 -1
- package/dist/fp/automationProgram.d.ts +1 -1
- package/dist/fp/automationProgram.js.map +1 -1
- package/dist/fp/policyParser.js +17 -0
- package/dist/fp/policyParser.js.map +1 -1
- package/dist/index.js +508 -36
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +4 -1
- package/dist/oauth.js +50 -14
- package/dist/oauth.js.map +1 -1
- package/dist/recipes/chainedRunner.d.ts +104 -0
- package/dist/recipes/chainedRunner.js +359 -0
- package/dist/recipes/chainedRunner.js.map +1 -0
- package/dist/recipes/dependencyGraph.d.ts +39 -0
- package/dist/recipes/dependencyGraph.js +199 -0
- package/dist/recipes/dependencyGraph.js.map +1 -0
- package/dist/recipes/legacyRecipeCompat.d.ts +1 -0
- package/dist/recipes/legacyRecipeCompat.js +97 -0
- package/dist/recipes/legacyRecipeCompat.js.map +1 -0
- package/dist/recipes/nestedRecipeStep.d.ts +58 -0
- package/dist/recipes/nestedRecipeStep.js +95 -0
- package/dist/recipes/nestedRecipeStep.js.map +1 -0
- package/dist/recipes/outputRegistry.d.ts +28 -0
- package/dist/recipes/outputRegistry.js +52 -0
- package/dist/recipes/outputRegistry.js.map +1 -0
- package/dist/recipes/schemaGenerator.d.ts +28 -0
- package/dist/recipes/schemaGenerator.js +484 -0
- package/dist/recipes/schemaGenerator.js.map +1 -0
- package/dist/recipes/templateEngine.d.ts +62 -0
- package/dist/recipes/templateEngine.js +182 -0
- package/dist/recipes/templateEngine.js.map +1 -0
- package/dist/recipes/toolRegistry.d.ts +181 -0
- package/dist/recipes/toolRegistry.js +300 -0
- package/dist/recipes/toolRegistry.js.map +1 -0
- package/dist/recipes/tools/calendar.d.ts +6 -0
- package/dist/recipes/tools/calendar.js +61 -0
- package/dist/recipes/tools/calendar.js.map +1 -0
- package/dist/recipes/tools/confluence.d.ts +6 -0
- package/dist/recipes/tools/confluence.js +254 -0
- package/dist/recipes/tools/confluence.js.map +1 -0
- package/dist/recipes/tools/diagnostics.d.ts +6 -0
- package/dist/recipes/tools/diagnostics.js +36 -0
- package/dist/recipes/tools/diagnostics.js.map +1 -0
- package/dist/recipes/tools/file.d.ts +6 -0
- package/dist/recipes/tools/file.js +170 -0
- package/dist/recipes/tools/file.js.map +1 -0
- package/dist/recipes/tools/git.d.ts +6 -0
- package/dist/recipes/tools/git.js +63 -0
- package/dist/recipes/tools/git.js.map +1 -0
- package/dist/recipes/tools/github.d.ts +6 -0
- package/dist/recipes/tools/github.js +91 -0
- package/dist/recipes/tools/github.js.map +1 -0
- package/dist/recipes/tools/gmail.d.ts +6 -0
- package/dist/recipes/tools/gmail.js +210 -0
- package/dist/recipes/tools/gmail.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +18 -0
- package/dist/recipes/tools/index.js +21 -0
- package/dist/recipes/tools/index.js.map +1 -0
- package/dist/recipes/tools/linear.d.ts +6 -0
- package/dist/recipes/tools/linear.js +83 -0
- package/dist/recipes/tools/linear.js.map +1 -0
- package/dist/recipes/tools/notion.d.ts +6 -0
- package/dist/recipes/tools/notion.js +278 -0
- package/dist/recipes/tools/notion.js.map +1 -0
- package/dist/recipes/tools/slack.d.ts +6 -0
- package/dist/recipes/tools/slack.js +72 -0
- package/dist/recipes/tools/slack.js.map +1 -0
- package/dist/recipes/tools/zendesk.d.ts +6 -0
- package/dist/recipes/tools/zendesk.js +245 -0
- package/dist/recipes/tools/zendesk.js.map +1 -0
- package/dist/recipes/yamlRunner.d.ts +71 -7
- package/dist/recipes/yamlRunner.js +406 -439
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/riskTier.js +1 -0
- package/dist/riskTier.js.map +1 -1
- package/dist/runLog.d.ts +18 -0
- package/dist/runLog.js +5 -0
- package/dist/runLog.js.map +1 -1
- package/dist/server.d.ts +4 -0
- package/dist/server.js +224 -0
- package/dist/server.js.map +1 -1
- package/dist/streamableHttp.js +2 -0
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tools/github/actions.js +4 -2
- package/dist/tools/github/actions.js.map +1 -1
- package/dist/tools/github/composite.d.ts +339 -0
- package/dist/tools/github/composite.js +343 -0
- package/dist/tools/github/composite.js.map +1 -0
- package/dist/tools/github/index.d.ts +1 -0
- package/dist/tools/github/index.js +1 -0
- package/dist/tools/github/index.js.map +1 -1
- package/dist/tools/github/issues.js +8 -4
- package/dist/tools/github/issues.js.map +1 -1
- package/dist/tools/github/pr.js +14 -7
- package/dist/tools/github/pr.js.map +1 -1
- package/dist/tools/index.js +10 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/searchTools.js +1 -1
- package/dist/tools/searchTools.js.map +1 -1
- package/dist/transport.d.ts +7 -1
- package/dist/transport.js +85 -11
- package/dist/transport.js.map +1 -1
- package/package.json +1 -1
- package/templates/automation-policies/recipe-authoring.json +25 -0
- package/templates/automation-policy.example.json +6 -0
- package/templates/recipes/lint-on-save.yaml +1 -2
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChainedRecipeRunner — executes recipes with:
|
|
3
|
+
* - Parallel step execution (respecting dependencies)
|
|
4
|
+
* - Template-based variable resolution
|
|
5
|
+
* - Nested recipe calls
|
|
6
|
+
* - Conditional step execution (when)
|
|
7
|
+
* - Dry-run mode
|
|
8
|
+
*/
|
|
9
|
+
import type { NestedRecipeConfig } from "./nestedRecipeStep.js";
|
|
10
|
+
import type { OutputRegistry } from "./outputRegistry.js";
|
|
11
|
+
import type { TemplateContext, TemplateError } from "./templateEngine.js";
|
|
12
|
+
export interface ChainedStep {
|
|
13
|
+
id: string;
|
|
14
|
+
tool?: string;
|
|
15
|
+
agent?: {
|
|
16
|
+
prompt: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
driver?: string;
|
|
19
|
+
};
|
|
20
|
+
recipe?: NestedRecipeConfig["recipe"];
|
|
21
|
+
vars?: Record<string, string>;
|
|
22
|
+
awaits?: string[];
|
|
23
|
+
when?: string;
|
|
24
|
+
output?: string;
|
|
25
|
+
risk?: "low" | "medium" | "high";
|
|
26
|
+
optional?: boolean;
|
|
27
|
+
transform?: string;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
export interface ChainedRecipe {
|
|
31
|
+
name: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
steps: ChainedStep[];
|
|
34
|
+
maxConcurrency?: number;
|
|
35
|
+
maxDepth?: number;
|
|
36
|
+
/** Plugin specs (npm package name or local path) to load before running steps. */
|
|
37
|
+
servers?: string[];
|
|
38
|
+
}
|
|
39
|
+
export interface RunOptions {
|
|
40
|
+
env: Record<string, string | undefined>;
|
|
41
|
+
maxConcurrency: number;
|
|
42
|
+
maxDepth: number;
|
|
43
|
+
dryRun: boolean;
|
|
44
|
+
onStepStart?: (stepId: string) => void;
|
|
45
|
+
onStepComplete?: (stepId: string, error?: Error) => void;
|
|
46
|
+
}
|
|
47
|
+
export interface StepExecutionContext {
|
|
48
|
+
registry: OutputRegistry;
|
|
49
|
+
step: ChainedStep;
|
|
50
|
+
options: RunOptions;
|
|
51
|
+
recipe: ChainedRecipe;
|
|
52
|
+
depth: number;
|
|
53
|
+
}
|
|
54
|
+
export type ToolExecutor = (tool: string, params: Record<string, unknown>) => Promise<unknown>;
|
|
55
|
+
export type AgentExecutor = (prompt: string, model?: string, driver?: string) => Promise<string>;
|
|
56
|
+
export interface ExecutionDeps {
|
|
57
|
+
executeTool: ToolExecutor;
|
|
58
|
+
executeAgent: AgentExecutor;
|
|
59
|
+
loadNestedRecipe: (name: string) => Promise<ChainedRecipe | null>;
|
|
60
|
+
}
|
|
61
|
+
/** Build template context from registry and env */
|
|
62
|
+
export declare function buildTemplateContext(registry: OutputRegistry, env: Record<string, string | undefined>): TemplateContext;
|
|
63
|
+
/** Resolve all template strings in a step */
|
|
64
|
+
export declare function resolveStepTemplates(step: ChainedStep, context: TemplateContext): {
|
|
65
|
+
resolved: Record<string, unknown>;
|
|
66
|
+
conditionResult: boolean;
|
|
67
|
+
errors: TemplateError[];
|
|
68
|
+
};
|
|
69
|
+
/** Execute a single step */
|
|
70
|
+
export declare function executeChainedStep(ctx: StepExecutionContext, deps: ExecutionDeps): Promise<{
|
|
71
|
+
success: boolean;
|
|
72
|
+
skipped?: boolean;
|
|
73
|
+
data?: unknown;
|
|
74
|
+
error?: string;
|
|
75
|
+
}>;
|
|
76
|
+
export interface ChainedRunResult {
|
|
77
|
+
success: boolean;
|
|
78
|
+
stepResults: Map<string, {
|
|
79
|
+
success: boolean;
|
|
80
|
+
error?: Error;
|
|
81
|
+
}>;
|
|
82
|
+
summary: {
|
|
83
|
+
total: number;
|
|
84
|
+
succeeded: number;
|
|
85
|
+
failed: number;
|
|
86
|
+
skipped: number;
|
|
87
|
+
};
|
|
88
|
+
errorMessage?: string;
|
|
89
|
+
}
|
|
90
|
+
/** Main entry point: run a chained recipe */
|
|
91
|
+
export declare function runChainedRecipe(recipe: ChainedRecipe, options: RunOptions, deps: ExecutionDeps, existingRegistry?: OutputRegistry, depth?: number): Promise<ChainedRunResult>;
|
|
92
|
+
/** Generate execution plan for dry-run mode */
|
|
93
|
+
export declare function generateExecutionPlan(recipe: ChainedRecipe): {
|
|
94
|
+
steps: Array<{
|
|
95
|
+
id: string;
|
|
96
|
+
type: "tool" | "agent" | "recipe";
|
|
97
|
+
dependencies: string[];
|
|
98
|
+
condition?: string;
|
|
99
|
+
risk: "low" | "medium" | "high";
|
|
100
|
+
optional?: boolean;
|
|
101
|
+
}>;
|
|
102
|
+
parallelGroups: string[][];
|
|
103
|
+
maxDepth: number;
|
|
104
|
+
};
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChainedRecipeRunner — executes recipes with:
|
|
3
|
+
* - Parallel step execution (respecting dependencies)
|
|
4
|
+
* - Template-based variable resolution
|
|
5
|
+
* - Nested recipe calls
|
|
6
|
+
* - Conditional step execution (when)
|
|
7
|
+
* - Dry-run mode
|
|
8
|
+
*/
|
|
9
|
+
import { buildDependencyGraph, executeWithDependencies, } from "./dependencyGraph.js";
|
|
10
|
+
import { mockNestedRecipe, resolveNestedVars, validateNestedRecipe, } from "./nestedRecipeStep.js";
|
|
11
|
+
import { createOutputRegistry } from "./outputRegistry.js";
|
|
12
|
+
import { compileTemplate } from "./templateEngine.js";
|
|
13
|
+
/** Build template context from registry and env */
|
|
14
|
+
export function buildTemplateContext(registry, env) {
|
|
15
|
+
return registry.toTemplateContext(env);
|
|
16
|
+
}
|
|
17
|
+
/** Resolve all template strings in a step */
|
|
18
|
+
export function resolveStepTemplates(step, context) {
|
|
19
|
+
const resolved = {};
|
|
20
|
+
const errors = [];
|
|
21
|
+
// W3: keys that are recipe metadata, not tool params
|
|
22
|
+
const STEP_META_KEYS = new Set([
|
|
23
|
+
"id",
|
|
24
|
+
"tool",
|
|
25
|
+
"agent",
|
|
26
|
+
"recipe",
|
|
27
|
+
"awaits",
|
|
28
|
+
"when",
|
|
29
|
+
"output",
|
|
30
|
+
"risk",
|
|
31
|
+
"optional",
|
|
32
|
+
"vars",
|
|
33
|
+
"transform",
|
|
34
|
+
]);
|
|
35
|
+
// Resolve tool params
|
|
36
|
+
for (const [key, value] of Object.entries(step)) {
|
|
37
|
+
if (STEP_META_KEYS.has(key)) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (typeof value === "string" && value.includes("{{")) {
|
|
41
|
+
const compiled = compileTemplate(value);
|
|
42
|
+
const result = compiled.evaluate(context);
|
|
43
|
+
if ("error" in result) {
|
|
44
|
+
errors.push(result.error);
|
|
45
|
+
resolved[key] = value;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// Try to parse JSON for structured data
|
|
49
|
+
try {
|
|
50
|
+
resolved[key] = JSON.parse(result.value);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
resolved[key] = result.value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
resolved[key] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Resolve agent prompt if present
|
|
62
|
+
if (step.agent && typeof step.agent.prompt === "string") {
|
|
63
|
+
const compiled = compileTemplate(step.agent.prompt);
|
|
64
|
+
const result = compiled.evaluate(context);
|
|
65
|
+
if ("error" in result) {
|
|
66
|
+
errors.push(result.error);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
resolved.agentPrompt = result.value;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Evaluate when condition
|
|
73
|
+
let conditionResult = true;
|
|
74
|
+
if (step.when) {
|
|
75
|
+
const compiled = compileTemplate(step.when);
|
|
76
|
+
const result = compiled.evaluate(context);
|
|
77
|
+
if ("error" in result) {
|
|
78
|
+
errors.push(result.error);
|
|
79
|
+
conditionResult = false;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Simple truthiness check (empty string, "0", "false" are falsy)
|
|
83
|
+
const val = result.value.trim().toLowerCase();
|
|
84
|
+
conditionResult =
|
|
85
|
+
!!val &&
|
|
86
|
+
val !== "0" &&
|
|
87
|
+
val !== "false" &&
|
|
88
|
+
val !== "null" &&
|
|
89
|
+
val !== "undefined";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { resolved, conditionResult, errors };
|
|
93
|
+
}
|
|
94
|
+
/** Execute a single step */
|
|
95
|
+
export async function executeChainedStep(ctx, deps) {
|
|
96
|
+
const { registry, step, options, depth } = ctx;
|
|
97
|
+
const { dryRun } = options;
|
|
98
|
+
// Build template context
|
|
99
|
+
const templateContext = buildTemplateContext(registry, options.env);
|
|
100
|
+
// Resolve templates
|
|
101
|
+
const { resolved, conditionResult, errors } = resolveStepTemplates(step, templateContext);
|
|
102
|
+
if (errors.length > 0) {
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: `Template errors: ${errors.map((e) => e.message).join(", ")}`,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// Check when condition
|
|
109
|
+
if (!conditionResult) {
|
|
110
|
+
return {
|
|
111
|
+
success: true,
|
|
112
|
+
skipped: true,
|
|
113
|
+
data: { skipped: true, reason: "when condition falsy" },
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Dry run: just report what would happen
|
|
117
|
+
if (dryRun) {
|
|
118
|
+
return {
|
|
119
|
+
success: true,
|
|
120
|
+
data: {
|
|
121
|
+
dryRun: true,
|
|
122
|
+
stepType: step.recipe ? "recipe" : step.agent ? "agent" : "tool",
|
|
123
|
+
wouldExecute: (step.tool ?? step.agent) ? "prompt" : step.recipe,
|
|
124
|
+
resolvedParams: Object.keys(resolved).length > 0 ? resolved : undefined,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/** Flat `{{ key }}` renderer for transform strings — mirrors yamlRunner.render */
|
|
129
|
+
function applyTransform(template, rawResult, ctx) {
|
|
130
|
+
const resultStr = typeof rawResult === "string" ? rawResult : JSON.stringify(rawResult);
|
|
131
|
+
const flatCtx = { $result: resultStr };
|
|
132
|
+
// Expose env keys as flat vars too
|
|
133
|
+
for (const [k, v] of Object.entries(ctx.env)) {
|
|
134
|
+
if (v !== undefined)
|
|
135
|
+
flatCtx[k] = v;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
return template.replace(/\{\{\s*([^}]+?)\s*\}\}/g, (_, expr) => {
|
|
139
|
+
const key = expr.trim();
|
|
140
|
+
return Object.hasOwn(flatCtx, key) ? (flatCtx[key] ?? "") : "";
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return rawResult;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Execute based on step type
|
|
148
|
+
try {
|
|
149
|
+
if (step.recipe) {
|
|
150
|
+
// Nested recipe call
|
|
151
|
+
const nestedConfig = {
|
|
152
|
+
recipe: step.recipe,
|
|
153
|
+
vars: step.vars ?? {},
|
|
154
|
+
output: step.output ?? step.id,
|
|
155
|
+
risk: step.risk,
|
|
156
|
+
id: step.id,
|
|
157
|
+
};
|
|
158
|
+
const nestedContext = {
|
|
159
|
+
parentRegistry: registry,
|
|
160
|
+
parentEnv: options.env,
|
|
161
|
+
recipeMaxDepth: options.maxDepth,
|
|
162
|
+
currentDepth: depth,
|
|
163
|
+
dryRun,
|
|
164
|
+
};
|
|
165
|
+
if (dryRun) {
|
|
166
|
+
const result = await mockNestedRecipe(nestedConfig, nestedContext);
|
|
167
|
+
return {
|
|
168
|
+
success: result.success,
|
|
169
|
+
data: result.data,
|
|
170
|
+
error: result.error,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Load and execute nested recipe
|
|
174
|
+
const nestedRecipe = await deps.loadNestedRecipe(step.recipe);
|
|
175
|
+
if (!nestedRecipe) {
|
|
176
|
+
return {
|
|
177
|
+
success: false,
|
|
178
|
+
error: `Nested recipe "${step.recipe}" not found`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const validation = validateNestedRecipe(nestedConfig, nestedContext);
|
|
182
|
+
if (!validation.valid) {
|
|
183
|
+
return { success: false, error: validation.error };
|
|
184
|
+
}
|
|
185
|
+
// Resolve vars for child
|
|
186
|
+
const { resolved: resolvedVars, errors: varErrors } = resolveNestedVars(step.vars ?? {}, templateContext);
|
|
187
|
+
if (varErrors.length > 0) {
|
|
188
|
+
return {
|
|
189
|
+
success: false,
|
|
190
|
+
error: `Variable template errors: ${varErrors.map((e) => e.message).join(", ")}`,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// Execute child recipe with isolated registry
|
|
194
|
+
const childRegistry = createOutputRegistry();
|
|
195
|
+
const childOptions = {
|
|
196
|
+
...options,
|
|
197
|
+
maxDepth: options.maxDepth,
|
|
198
|
+
env: { ...options.env, ...resolvedVars }, // Merge resolved vars into env
|
|
199
|
+
};
|
|
200
|
+
const childResult = await runChainedRecipe(nestedRecipe, childOptions, deps, childRegistry, depth + 1);
|
|
201
|
+
return {
|
|
202
|
+
success: !childResult.errorMessage,
|
|
203
|
+
data: {
|
|
204
|
+
recipe: step.recipe,
|
|
205
|
+
childSummary: childRegistry.summary(),
|
|
206
|
+
childOutputs: Object.fromEntries(childRegistry.keys().map((k) => [k, childRegistry.get(k)?.data])),
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
else if (step.agent) {
|
|
211
|
+
// Agent step
|
|
212
|
+
const prompt = resolved.agentPrompt ?? step.agent.prompt;
|
|
213
|
+
let result = await deps.executeAgent(prompt, step.agent.model, step.agent.driver);
|
|
214
|
+
if (step.transform) {
|
|
215
|
+
try {
|
|
216
|
+
result = applyTransform(step.transform, result, templateContext);
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
console.warn(`transform failed for step ${step.id}: ${err}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { success: true, data: result };
|
|
223
|
+
}
|
|
224
|
+
else if (step.tool) {
|
|
225
|
+
// Tool step
|
|
226
|
+
let result = await deps.executeTool(step.tool, resolved);
|
|
227
|
+
if (step.transform) {
|
|
228
|
+
try {
|
|
229
|
+
result = applyTransform(step.transform, result, templateContext);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
console.warn(`transform failed for step ${step.id}: ${err}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { success: true, data: result };
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
return { success: false, error: "Step has no tool, agent, or recipe" };
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
243
|
+
return { success: false, error: msg };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Main entry point: run a chained recipe */
|
|
247
|
+
export async function runChainedRecipe(recipe, options, deps, existingRegistry, depth = 0) {
|
|
248
|
+
// Load plugin servers declared in the recipe before executing any steps.
|
|
249
|
+
// Only done at the top-level call (depth 0) to avoid redundant loads in nested recipes.
|
|
250
|
+
if (depth === 0 && recipe.servers?.length) {
|
|
251
|
+
try {
|
|
252
|
+
const { loadRecipeServers } = await import("./yamlRunner.js");
|
|
253
|
+
await loadRecipeServers(recipe.servers);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
// Non-fatal — if yamlRunner import fails, proceed without plugins
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const registry = existingRegistry ?? createOutputRegistry();
|
|
260
|
+
// Build dependency graph
|
|
261
|
+
const depGraph = buildDependencyGraph(recipe.steps.map((s, i) => ({ id: s.id ?? `step_${i}`, awaits: s.awaits })));
|
|
262
|
+
if (depGraph.hasCycles) {
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
stepResults: new Map(),
|
|
266
|
+
summary: { total: 0, succeeded: 0, failed: 0, skipped: 0 },
|
|
267
|
+
errorMessage: "Recipe has circular dependencies",
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// Create step lookup
|
|
271
|
+
const stepMap = new Map();
|
|
272
|
+
for (let i = 0; i < recipe.steps.length; i++) {
|
|
273
|
+
const step = recipe.steps[i];
|
|
274
|
+
if (!step)
|
|
275
|
+
continue;
|
|
276
|
+
const stepId = step.id ?? `step_${i}`;
|
|
277
|
+
stepMap.set(stepId, { ...step, id: stepId });
|
|
278
|
+
}
|
|
279
|
+
// Execute with dependency tracking
|
|
280
|
+
const execOptions = {
|
|
281
|
+
maxConcurrency: options.maxConcurrency,
|
|
282
|
+
onStepStart: options.onStepStart,
|
|
283
|
+
onStepComplete: options.onStepComplete,
|
|
284
|
+
};
|
|
285
|
+
const stepExecutor = async (stepId) => {
|
|
286
|
+
const step = stepMap.get(stepId);
|
|
287
|
+
if (!step)
|
|
288
|
+
throw new Error(`Step ${stepId} not found`);
|
|
289
|
+
const ctx = {
|
|
290
|
+
registry,
|
|
291
|
+
step,
|
|
292
|
+
options,
|
|
293
|
+
recipe,
|
|
294
|
+
depth,
|
|
295
|
+
};
|
|
296
|
+
const result = await executeChainedStep(ctx, deps);
|
|
297
|
+
const isOptional = step.optional === true;
|
|
298
|
+
const effectiveSuccess = result.success || isOptional;
|
|
299
|
+
// Store output in registry with accurate status
|
|
300
|
+
registry.set(stepId, {
|
|
301
|
+
status: result.skipped
|
|
302
|
+
? "skipped"
|
|
303
|
+
: result.success
|
|
304
|
+
? "success"
|
|
305
|
+
: isOptional
|
|
306
|
+
? "success"
|
|
307
|
+
: "error",
|
|
308
|
+
data: result.data,
|
|
309
|
+
});
|
|
310
|
+
// Optional steps must not propagate failure to the executor
|
|
311
|
+
if (!effectiveSuccess) {
|
|
312
|
+
throw new Error(result.error ?? `Step ${stepId} failed`);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
const stepResults = await executeWithDependencies(depGraph, stepExecutor, execOptions);
|
|
316
|
+
// Calculate overall success
|
|
317
|
+
let failed = 0;
|
|
318
|
+
for (const [_, result] of stepResults) {
|
|
319
|
+
if (!result.success)
|
|
320
|
+
failed++;
|
|
321
|
+
}
|
|
322
|
+
return {
|
|
323
|
+
success: failed === 0,
|
|
324
|
+
stepResults,
|
|
325
|
+
summary: registry.summary(),
|
|
326
|
+
errorMessage: failed > 0 ? `${failed} step(s) failed` : undefined,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
/** Generate execution plan for dry-run mode */
|
|
330
|
+
export function generateExecutionPlan(recipe) {
|
|
331
|
+
const depGraph = buildDependencyGraph(recipe.steps.map((s, i) => ({ id: s.id ?? `step_${i}`, awaits: s.awaits })));
|
|
332
|
+
// Group by topological levels (parallelizable)
|
|
333
|
+
const levels = [];
|
|
334
|
+
const completed = new Set();
|
|
335
|
+
while (completed.size < depGraph.topologicalOrder.length) {
|
|
336
|
+
const ready = depGraph.topologicalOrder.filter((id) => !completed.has(id) &&
|
|
337
|
+
depGraph.steps
|
|
338
|
+
.find((s) => s.stepId === id)
|
|
339
|
+
?.awaits.every((dep) => completed.has(dep)));
|
|
340
|
+
if (ready.length === 0)
|
|
341
|
+
break;
|
|
342
|
+
levels.push(ready);
|
|
343
|
+
for (const id of ready)
|
|
344
|
+
completed.add(id);
|
|
345
|
+
}
|
|
346
|
+
return {
|
|
347
|
+
steps: recipe.steps.map((s) => ({
|
|
348
|
+
id: s.id,
|
|
349
|
+
type: s.recipe ? "recipe" : s.agent ? "agent" : "tool",
|
|
350
|
+
dependencies: s.awaits ?? [],
|
|
351
|
+
condition: s.when,
|
|
352
|
+
risk: s.risk ?? "low",
|
|
353
|
+
optional: s.optional,
|
|
354
|
+
})),
|
|
355
|
+
parallelGroups: levels,
|
|
356
|
+
maxDepth: recipe.maxDepth ?? 3,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
//# sourceMappingURL=chainedRunner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chainedRunner.js","sourceRoot":"","sources":["../../src/recipes/chainedRunner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DependencyGraph — builds and executes recipe step dependencies.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - Parallel execution up to maxConcurrency
|
|
6
|
+
* - Explicit dependencies (awaits: [stepA, stepB])
|
|
7
|
+
* - Conditional execution (when: condition)
|
|
8
|
+
* - Cycle detection
|
|
9
|
+
*/
|
|
10
|
+
export interface StepDependency {
|
|
11
|
+
stepId: string;
|
|
12
|
+
awaits: string[];
|
|
13
|
+
index: number;
|
|
14
|
+
}
|
|
15
|
+
export interface DependencyGraph {
|
|
16
|
+
steps: StepDependency[];
|
|
17
|
+
hasCycles: boolean;
|
|
18
|
+
topologicalOrder: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface ExecutionOptions {
|
|
21
|
+
maxConcurrency: number;
|
|
22
|
+
onStepStart?: (stepId: string) => void;
|
|
23
|
+
onStepComplete?: (stepId: string, error?: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
export type StepExecutor = (stepId: string) => Promise<void>;
|
|
26
|
+
/** Build dependency graph from step definitions */
|
|
27
|
+
export declare function buildDependencyGraph(steps: Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
awaits?: string[];
|
|
30
|
+
}>): DependencyGraph;
|
|
31
|
+
/** Format cycle for error message */
|
|
32
|
+
export declare function formatCycle(cycles: string[][]): string;
|
|
33
|
+
/** Execute steps respecting dependencies with limited concurrency */
|
|
34
|
+
export declare function executeWithDependencies(graph: DependencyGraph, executeStep: StepExecutor, options: ExecutionOptions): Promise<Map<string, {
|
|
35
|
+
success: boolean;
|
|
36
|
+
error?: Error;
|
|
37
|
+
}>>;
|
|
38
|
+
/** Get steps that can run immediately (no unresolved dependencies) */
|
|
39
|
+
export declare function getReadySteps(graph: DependencyGraph, completed: Set<string>): string[];
|