patchwork-os 0.2.0-alpha.3 → 0.2.0-alpha.31
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.bridge.md +6 -0
- package/README.md +40 -15
- package/deploy/bootstrap-vps.sh +184 -0
- package/deploy/deploy-dashboard.sh +174 -0
- package/deploy/deploy-landing.sh +79 -0
- package/dist/activationMetrics.d.ts +67 -0
- package/dist/activationMetrics.js +255 -0
- package/dist/activationMetrics.js.map +1 -0
- package/dist/approvalHttp.d.ts +24 -2
- package/dist/approvalHttp.js +150 -10
- package/dist/approvalHttp.js.map +1 -1
- package/dist/approvalQueue.d.ts +16 -1
- package/dist/approvalQueue.js +44 -3
- package/dist/approvalQueue.js.map +1 -1
- package/dist/automation.d.ts +20 -0
- package/dist/automation.js +54 -1
- package/dist/automation.js.map +1 -1
- package/dist/bridge.d.ts +2 -0
- package/dist/bridge.js +55 -130
- package/dist/bridge.js.map +1 -1
- package/dist/bridgeToken.js +57 -19
- package/dist/bridgeToken.js.map +1 -1
- package/dist/ccPermissions.js +6 -4
- package/dist/ccPermissions.js.map +1 -1
- package/dist/claudeOrchestrator.d.ts +1 -1
- package/dist/claudeOrchestrator.js +14 -8
- package/dist/claudeOrchestrator.js.map +1 -1
- package/dist/commands/launchd.d.ts +2 -0
- package/dist/commands/launchd.js +94 -0
- package/dist/commands/launchd.js.map +1 -0
- package/dist/commands/recipe.d.ts +258 -0
- package/dist/commands/recipe.js +1130 -0
- package/dist/commands/recipe.js.map +1 -0
- package/dist/commands/recipeInstall.d.ts +72 -0
- package/dist/commands/recipeInstall.js +339 -0
- package/dist/commands/recipeInstall.js.map +1 -0
- package/dist/config.d.ts +14 -1
- package/dist/config.js +99 -8
- 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/datadog.d.ts +116 -0
- package/dist/connectors/datadog.js +385 -0
- package/dist/connectors/datadog.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.d.ts +58 -8
- package/dist/connectors/github.js +312 -84
- package/dist/connectors/github.js.map +1 -1
- package/dist/connectors/gmail.d.ts +4 -1
- package/dist/connectors/gmail.js +79 -16
- package/dist/connectors/gmail.js.map +1 -1
- package/dist/connectors/googleCalendar.d.ts +60 -0
- package/dist/connectors/googleCalendar.js +345 -0
- package/dist/connectors/googleCalendar.js.map +1 -0
- package/dist/connectors/hubspot.d.ts +112 -0
- package/dist/connectors/hubspot.js +408 -0
- package/dist/connectors/hubspot.js.map +1 -0
- package/dist/connectors/intercom.d.ts +102 -0
- package/dist/connectors/intercom.js +402 -0
- package/dist/connectors/intercom.js.map +1 -0
- 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.d.ts +69 -19
- package/dist/connectors/linear.js +170 -129
- package/dist/connectors/linear.js.map +1 -1
- package/dist/connectors/mcpClient.d.ts +56 -0
- package/dist/connectors/mcpClient.js +189 -0
- package/dist/connectors/mcpClient.js.map +1 -0
- package/dist/connectors/mcpOAuth.d.ts +84 -0
- package/dist/connectors/mcpOAuth.js +389 -0
- package/dist/connectors/mcpOAuth.js.map +1 -0
- 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.d.ts +17 -21
- package/dist/connectors/sentry.js +115 -131
- package/dist/connectors/sentry.js.map +1 -1
- package/dist/connectors/slack.d.ts +50 -0
- package/dist/connectors/slack.js +324 -0
- package/dist/connectors/slack.js.map +1 -0
- package/dist/connectors/stripe.d.ts +116 -0
- package/dist/connectors/stripe.js +379 -0
- package/dist/connectors/stripe.js.map +1 -0
- package/dist/connectors/tokenStorage.d.ts +35 -0
- package/dist/connectors/tokenStorage.js +459 -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/drivers/gemini/index.d.ts +5 -1
- package/dist/drivers/gemini/index.js +39 -5
- package/dist/drivers/gemini/index.js.map +1 -1
- package/dist/drivers/index.d.ts +5 -0
- package/dist/drivers/index.js +1 -1
- package/dist/drivers/index.js.map +1 -1
- 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 +621 -61
- package/dist/index.js.map +1 -1
- package/dist/installGuard.d.ts +25 -0
- package/dist/installGuard.js +48 -0
- package/dist/installGuard.js.map +1 -0
- package/dist/oauth.d.ts +4 -1
- package/dist/oauth.js +50 -14
- package/dist/oauth.js.map +1 -1
- package/dist/patchworkConfig.d.ts +9 -0
- package/dist/patchworkConfig.js.map +1 -1
- package/dist/recipeOrchestration.d.ts +53 -0
- package/dist/recipeOrchestration.js +272 -0
- package/dist/recipeOrchestration.js.map +1 -0
- package/dist/recipes/RecipeOrchestrator.d.ts +40 -0
- package/dist/recipes/RecipeOrchestrator.js +51 -0
- package/dist/recipes/RecipeOrchestrator.js.map +1 -0
- package/dist/recipes/agentExecutor.d.ts +28 -0
- package/dist/recipes/agentExecutor.js +42 -0
- package/dist/recipes/agentExecutor.js.map +1 -0
- package/dist/recipes/chainedRunner.d.ts +140 -0
- package/dist/recipes/chainedRunner.js +539 -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 +2 -0
- package/dist/recipes/legacyRecipeCompat.js +112 -0
- package/dist/recipes/legacyRecipeCompat.js.map +1 -0
- package/dist/recipes/manifest.d.ts +47 -0
- package/dist/recipes/manifest.js +141 -0
- package/dist/recipes/manifest.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/scheduler.d.ts +23 -7
- package/dist/recipes/scheduler.js +131 -41
- package/dist/recipes/scheduler.js.map +1 -1
- package/dist/recipes/schema.d.ts +17 -2
- package/dist/recipes/schemaGenerator.d.ts +28 -0
- package/dist/recipes/schemaGenerator.js +565 -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/datadog.d.ts +6 -0
- package/dist/recipes/tools/datadog.js +239 -0
- package/dist/recipes/tools/datadog.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/hubspot.d.ts +6 -0
- package/dist/recipes/tools/hubspot.js +232 -0
- package/dist/recipes/tools/hubspot.js.map +1 -0
- package/dist/recipes/tools/index.d.ts +22 -0
- package/dist/recipes/tools/index.js +25 -0
- package/dist/recipes/tools/index.js.map +1 -0
- package/dist/recipes/tools/intercom.d.ts +6 -0
- package/dist/recipes/tools/intercom.js +226 -0
- package/dist/recipes/tools/intercom.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/stripe.d.ts +6 -0
- package/dist/recipes/tools/stripe.js +265 -0
- package/dist/recipes/tools/stripe.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/validation.d.ts +13 -0
- package/dist/recipes/validation.js +433 -0
- package/dist/recipes/validation.js.map +1 -0
- package/dist/recipes/yamlRunner.d.ts +87 -0
- package/dist/recipes/yamlRunner.js +693 -409
- package/dist/recipes/yamlRunner.js.map +1 -1
- package/dist/recipesHttp.d.ts +34 -6
- package/dist/recipesHttp.js +285 -15
- package/dist/recipesHttp.js.map +1 -1
- package/dist/riskTier.js +1 -0
- package/dist/riskTier.js.map +1 -1
- package/dist/runLog.d.ts +23 -0
- package/dist/runLog.js +56 -1
- package/dist/runLog.js.map +1 -1
- package/dist/schemas/dry-run-plan.v1.json +139 -0
- package/dist/schemas/recipe.v1.json +684 -0
- package/dist/server.d.ts +32 -1
- package/dist/server.js +980 -97
- package/dist/server.js.map +1 -1
- package/dist/streamableHttp.js +2 -0
- package/dist/streamableHttp.js.map +1 -1
- package/dist/tools/addLinearComment.d.ts +55 -0
- package/dist/tools/addLinearComment.js +72 -0
- package/dist/tools/addLinearComment.js.map +1 -0
- package/dist/tools/bridgeDoctor.js +2 -2
- package/dist/tools/bridgeDoctor.js.map +1 -1
- package/dist/tools/createLinearIssue.d.ts +84 -0
- package/dist/tools/createLinearIssue.js +146 -0
- package/dist/tools/createLinearIssue.js.map +1 -0
- package/dist/tools/fetchCalendarEvents.d.ts +94 -0
- package/dist/tools/fetchCalendarEvents.js +97 -0
- package/dist/tools/fetchCalendarEvents.js.map +1 -0
- package/dist/tools/fetchGithubIssue.d.ts +80 -0
- package/dist/tools/fetchGithubIssue.js +84 -0
- package/dist/tools/fetchGithubIssue.js.map +1 -0
- package/dist/tools/fetchGithubPR.d.ts +89 -0
- package/dist/tools/fetchGithubPR.js +96 -0
- package/dist/tools/fetchGithubPR.js.map +1 -0
- package/dist/tools/fetchSlackProfile.d.ts +43 -0
- package/dist/tools/fetchSlackProfile.js +46 -0
- package/dist/tools/fetchSlackProfile.js.map +1 -0
- package/dist/tools/getConnectorStatus.d.ts +58 -0
- package/dist/tools/getConnectorStatus.js +56 -0
- package/dist/tools/getConnectorStatus.js.map +1 -0
- 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 +2 -1
- package/dist/tools/github/index.js +2 -1
- 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.d.ts +122 -0
- package/dist/tools/github/pr.js +195 -5
- package/dist/tools/github/pr.js.map +1 -1
- package/dist/tools/index.js +32 -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/tools/slackListChannels.d.ts +65 -0
- package/dist/tools/slackListChannels.js +70 -0
- package/dist/tools/slackListChannels.js.map +1 -0
- package/dist/tools/slackPostMessage.d.ts +57 -0
- package/dist/tools/slackPostMessage.js +77 -0
- package/dist/tools/slackPostMessage.js.map +1 -0
- package/dist/tools/testTraceToSource.js +2 -2
- package/dist/tools/testTraceToSource.js.map +1 -1
- package/dist/tools/updateLinearIssue.d.ts +89 -0
- package/dist/tools/updateLinearIssue.js +117 -0
- package/dist/tools/updateLinearIssue.js.map +1 -0
- package/dist/transport.d.ts +7 -1
- package/dist/transport.js +85 -11
- package/dist/transport.js.map +1 -1
- package/package.json +5 -2
- package/scripts/start-all.sh +56 -19
- package/templates/automation-policies/recipe-authoring.json +25 -0
- package/templates/automation-policy.example.json +6 -0
- package/templates/co.patchwork-os.bridge.plist +34 -0
- package/templates/recipes/ctx-loop-test.yaml +75 -0
- package/templates/recipes/lint-on-save.yaml +1 -2
- package/templates/recipes/morning-brief-slack.yaml +57 -0
- package/templates/recipes/morning-brief.yaml +14 -6
- package/templates/recipes/project-health-check.yaml +50 -0
- package/templates/recipes/sentry-to-linear.yaml +77 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
import { Ajv } from "ajv";
|
|
2
|
+
import { FLAG_SCHEMA_LINT, isEnabled } from "../featureFlags.js";
|
|
3
|
+
import { normalizeRecipeForRuntime } from "./legacyRecipeCompat.js";
|
|
4
|
+
import { generateSchemaSet } from "./schemaGenerator.js";
|
|
5
|
+
import { listToolOutputContextKeys } from "./toolRegistry.js";
|
|
6
|
+
export function validateRecipeDefinition(recipe) {
|
|
7
|
+
const issues = [];
|
|
8
|
+
const normalizedRecipe = normalizeRecipeForValidation(recipe);
|
|
9
|
+
if (!normalizedRecipe || typeof normalizedRecipe !== "object") {
|
|
10
|
+
issues.push({ level: "error", message: "Recipe must be a YAML object" });
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const r = normalizedRecipe;
|
|
14
|
+
if (!r.name || typeof r.name !== "string") {
|
|
15
|
+
issues.push({
|
|
16
|
+
level: "error",
|
|
17
|
+
message: "Missing or invalid 'name' field",
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else if (!/^[a-z0-9-]+$/.test(r.name)) {
|
|
21
|
+
issues.push({
|
|
22
|
+
level: "warning",
|
|
23
|
+
message: "Recipe name should use kebab-case (lowercase letters, numbers, hyphens)",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
if (!r.description || typeof r.description !== "string") {
|
|
27
|
+
issues.push({ level: "warning", message: "Missing 'description' field" });
|
|
28
|
+
}
|
|
29
|
+
if (!r.trigger || typeof r.trigger !== "object") {
|
|
30
|
+
issues.push({
|
|
31
|
+
level: "error",
|
|
32
|
+
message: "Missing or invalid 'trigger' field",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
const trigger = r.trigger;
|
|
37
|
+
const validTypes = [
|
|
38
|
+
"manual",
|
|
39
|
+
"cron",
|
|
40
|
+
"webhook",
|
|
41
|
+
"file_watch",
|
|
42
|
+
"git_hook",
|
|
43
|
+
"on_file_save",
|
|
44
|
+
"on_test_run",
|
|
45
|
+
"chained",
|
|
46
|
+
];
|
|
47
|
+
if (!trigger.type || !validTypes.includes(trigger.type)) {
|
|
48
|
+
issues.push({
|
|
49
|
+
level: "error",
|
|
50
|
+
message: `Invalid trigger.type. Must be one of: ${validTypes.join(", ")}`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (trigger.type === "cron" && !trigger.at) {
|
|
54
|
+
issues.push({
|
|
55
|
+
level: "warning",
|
|
56
|
+
message: "cron trigger should have 'at' (cron expression)",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (!Array.isArray(r.steps) || r.steps.length === 0) {
|
|
61
|
+
issues.push({
|
|
62
|
+
level: "error",
|
|
63
|
+
message: "Recipe must have at least one step",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const triggerType = r.trigger && typeof r.trigger === "object"
|
|
68
|
+
? r.trigger.type
|
|
69
|
+
: undefined;
|
|
70
|
+
const allowNestedRecipeSteps = triggerType === "chained";
|
|
71
|
+
for (let i = 0; i < r.steps.length; i++) {
|
|
72
|
+
const step = r.steps[i];
|
|
73
|
+
const hasTool = typeof step.tool === "string";
|
|
74
|
+
const hasAgent = !!step.agent;
|
|
75
|
+
const hasNestedRecipe = allowNestedRecipeSteps &&
|
|
76
|
+
(typeof step.recipe === "string" || typeof step.chain === "string");
|
|
77
|
+
if (!hasTool && !hasAgent && !hasNestedRecipe) {
|
|
78
|
+
issues.push({
|
|
79
|
+
level: "error",
|
|
80
|
+
message: `Step ${i + 1}: Must have 'tool' or 'agent' field${allowNestedRecipeSteps ? " (or 'recipe'/'chain' for chained recipes)" : ""}`,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (step.agent && typeof step.agent === "object") {
|
|
84
|
+
const agent = step.agent;
|
|
85
|
+
if (!agent.prompt || typeof agent.prompt !== "string") {
|
|
86
|
+
issues.push({
|
|
87
|
+
level: "error",
|
|
88
|
+
message: `Step ${i + 1}: Agent step missing 'prompt'`,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
validateTemplateReferences(r, issues);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (isEnabled(FLAG_SCHEMA_LINT)) {
|
|
97
|
+
issues.push(...validateRecipeSchema(normalizedRecipe));
|
|
98
|
+
}
|
|
99
|
+
const errors = issues.filter((i) => i.level === "error").length;
|
|
100
|
+
const warnings = issues.filter((i) => i.level === "warning").length;
|
|
101
|
+
return {
|
|
102
|
+
valid: errors === 0,
|
|
103
|
+
issues,
|
|
104
|
+
warnings,
|
|
105
|
+
errors,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function normalizeRecipeForValidation(recipe) {
|
|
109
|
+
const normalized = normalizeRecipeForRuntime(recipe, console.warn);
|
|
110
|
+
if (!normalized ||
|
|
111
|
+
typeof normalized !== "object" ||
|
|
112
|
+
Array.isArray(normalized)) {
|
|
113
|
+
return normalized;
|
|
114
|
+
}
|
|
115
|
+
const validationReady = {
|
|
116
|
+
...normalized,
|
|
117
|
+
};
|
|
118
|
+
if (validationReady.trigger &&
|
|
119
|
+
typeof validationReady.trigger === "object" &&
|
|
120
|
+
!Array.isArray(validationReady.trigger)) {
|
|
121
|
+
validationReady.trigger = normalizeValidationTrigger(validationReady.trigger);
|
|
122
|
+
}
|
|
123
|
+
if (Array.isArray(validationReady.steps)) {
|
|
124
|
+
validationReady.steps = flattenValidationSteps(validationReady.steps);
|
|
125
|
+
}
|
|
126
|
+
return validationReady;
|
|
127
|
+
}
|
|
128
|
+
function normalizeValidationTrigger(trigger) {
|
|
129
|
+
const normalized = { ...trigger };
|
|
130
|
+
if (normalized.type === "event") {
|
|
131
|
+
normalized.type = "webhook";
|
|
132
|
+
normalized.legacyType = "event";
|
|
133
|
+
if (typeof normalized.on === "string") {
|
|
134
|
+
normalized.eventSource = normalized.on;
|
|
135
|
+
}
|
|
136
|
+
delete normalized.on;
|
|
137
|
+
if (normalized.filter !== undefined &&
|
|
138
|
+
typeof normalized.filter !== "string") {
|
|
139
|
+
normalized.eventFilter = normalized.filter;
|
|
140
|
+
delete normalized.filter;
|
|
141
|
+
}
|
|
142
|
+
if (normalized.lead_time_hours !== undefined) {
|
|
143
|
+
normalized.eventLeadTimeHours = normalized.lead_time_hours;
|
|
144
|
+
delete normalized.lead_time_hours;
|
|
145
|
+
}
|
|
146
|
+
if (normalized.lead_time_minutes !== undefined) {
|
|
147
|
+
normalized.eventLeadTimeMinutes = normalized.lead_time_minutes;
|
|
148
|
+
delete normalized.lead_time_minutes;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return normalized;
|
|
152
|
+
}
|
|
153
|
+
function flattenValidationSteps(steps) {
|
|
154
|
+
const normalizedSteps = [];
|
|
155
|
+
for (const step of steps) {
|
|
156
|
+
normalizedSteps.push(...flattenValidationStep(step));
|
|
157
|
+
}
|
|
158
|
+
return normalizedSteps;
|
|
159
|
+
}
|
|
160
|
+
function flattenValidationStep(step) {
|
|
161
|
+
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
162
|
+
return [step];
|
|
163
|
+
}
|
|
164
|
+
const record = step;
|
|
165
|
+
if (Array.isArray(record.parallel)) {
|
|
166
|
+
const parallelSteps = [];
|
|
167
|
+
for (const nestedStep of record.parallel) {
|
|
168
|
+
parallelSteps.push(...flattenValidationStep(nestedStep));
|
|
169
|
+
}
|
|
170
|
+
return parallelSteps;
|
|
171
|
+
}
|
|
172
|
+
if (Array.isArray(record.branch)) {
|
|
173
|
+
const branchSteps = [];
|
|
174
|
+
for (const branchStep of record.branch) {
|
|
175
|
+
if (!branchStep ||
|
|
176
|
+
typeof branchStep !== "object" ||
|
|
177
|
+
Array.isArray(branchStep)) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const branchRecord = branchStep;
|
|
181
|
+
const otherwiseStep = branchRecord.otherwise;
|
|
182
|
+
if (otherwiseStep &&
|
|
183
|
+
typeof otherwiseStep === "object" &&
|
|
184
|
+
!Array.isArray(otherwiseStep)) {
|
|
185
|
+
branchSteps.push(...flattenValidationStep(otherwiseStep));
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
branchSteps.push(...flattenValidationStep(branchRecord));
|
|
189
|
+
}
|
|
190
|
+
return branchSteps.length > 0 ? branchSteps : [record];
|
|
191
|
+
}
|
|
192
|
+
return [record];
|
|
193
|
+
}
|
|
194
|
+
function validateRecipeSchema(recipe) {
|
|
195
|
+
try {
|
|
196
|
+
const schemas = generateSchemaSet();
|
|
197
|
+
const ajv = new Ajv({ strict: false, allErrors: true });
|
|
198
|
+
for (const schema of Object.values(schemas.namespaces)) {
|
|
199
|
+
ajv.addSchema(schema);
|
|
200
|
+
}
|
|
201
|
+
const validate = ajv.compile(schemas.recipe);
|
|
202
|
+
const valid = validate(recipe);
|
|
203
|
+
if (valid) {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
return (validate.errors ?? []).map(toSchemaLintIssue);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
level: "error",
|
|
212
|
+
message: `Schema validation failed to initialize: ${err instanceof Error ? err.message : String(err)}`,
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function registerRecipeContextKeys(recipe, availableKeys) {
|
|
218
|
+
const trigger = recipe.trigger && typeof recipe.trigger === "object"
|
|
219
|
+
? recipe.trigger
|
|
220
|
+
: undefined;
|
|
221
|
+
if (trigger?.type === "git_hook") {
|
|
222
|
+
availableKeys.add("hash");
|
|
223
|
+
availableKeys.add("message");
|
|
224
|
+
availableKeys.add("branch");
|
|
225
|
+
}
|
|
226
|
+
if (trigger?.type === "on_file_save") {
|
|
227
|
+
availableKeys.add("file");
|
|
228
|
+
}
|
|
229
|
+
if (trigger?.type === "on_test_run") {
|
|
230
|
+
availableKeys.add("runner");
|
|
231
|
+
availableKeys.add("failed");
|
|
232
|
+
availableKeys.add("passed");
|
|
233
|
+
availableKeys.add("total");
|
|
234
|
+
availableKeys.add("failures");
|
|
235
|
+
}
|
|
236
|
+
if (trigger?.legacyType === "event") {
|
|
237
|
+
availableKeys.add("event");
|
|
238
|
+
}
|
|
239
|
+
if (Array.isArray(trigger?.vars)) {
|
|
240
|
+
for (const item of trigger.vars) {
|
|
241
|
+
if (item && typeof item === "object" && typeof item.name === "string") {
|
|
242
|
+
availableKeys.add(item.name);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (Array.isArray(trigger?.inputs)) {
|
|
247
|
+
for (const item of trigger.inputs) {
|
|
248
|
+
if (item && typeof item === "object" && typeof item.name === "string") {
|
|
249
|
+
availableKeys.add(item.name);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (Array.isArray(recipe.context)) {
|
|
254
|
+
for (const block of recipe.context) {
|
|
255
|
+
if (!block || typeof block !== "object") {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
const typedBlock = block;
|
|
259
|
+
if (typedBlock.type === "env" && Array.isArray(typedBlock.keys)) {
|
|
260
|
+
for (const key of typedBlock.keys) {
|
|
261
|
+
if (typeof key === "string") {
|
|
262
|
+
availableKeys.add(key);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
function toSchemaLintIssue(error) {
|
|
270
|
+
const path = error.instancePath
|
|
271
|
+
? error.instancePath.slice(1).replace(/\//g, ".")
|
|
272
|
+
: "recipe";
|
|
273
|
+
return {
|
|
274
|
+
level: "error",
|
|
275
|
+
message: `Schema validation: ${path} ${error.message ?? "is invalid"}`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function validateTemplateReferences(recipe, issues) {
|
|
279
|
+
const builtinKeys = new Set([
|
|
280
|
+
"date",
|
|
281
|
+
"time",
|
|
282
|
+
"YYYY-MM",
|
|
283
|
+
"YYYY-MM-DD",
|
|
284
|
+
"ISO_NOW",
|
|
285
|
+
]);
|
|
286
|
+
const availableKeys = new Set(builtinKeys);
|
|
287
|
+
registerRecipeContextKeys(recipe, availableKeys);
|
|
288
|
+
const triggerType = recipe.trigger && typeof recipe.trigger === "object"
|
|
289
|
+
? recipe.trigger.type
|
|
290
|
+
: undefined;
|
|
291
|
+
const isChainedRecipe = triggerType === "chained";
|
|
292
|
+
const steps = Array.isArray(recipe.steps)
|
|
293
|
+
? recipe.steps
|
|
294
|
+
: [];
|
|
295
|
+
const seenIntoKeys = new Map();
|
|
296
|
+
for (let index = 0; index < steps.length; index++) {
|
|
297
|
+
const step = steps[index] ?? {};
|
|
298
|
+
const templates = collectRenderedTemplates(step, isChainedRecipe);
|
|
299
|
+
for (const template of templates) {
|
|
300
|
+
const scopedKeys = template.extraKeys
|
|
301
|
+
? new Set([...availableKeys, ...template.extraKeys])
|
|
302
|
+
: availableKeys;
|
|
303
|
+
for (const expression of extractTemplateExpressions(template.value)) {
|
|
304
|
+
for (const identifier of extractTemplateIdentifiers(expression)) {
|
|
305
|
+
if (!scopedKeys.has(identifier)) {
|
|
306
|
+
issues.push({
|
|
307
|
+
level: "error",
|
|
308
|
+
message: `Step ${index + 1}: Unknown template reference '{{${expression}}}' in ${template.label}`,
|
|
309
|
+
});
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
const intoKey = resolveStepIntoKey(step, isChainedRecipe);
|
|
316
|
+
if (intoKey) {
|
|
317
|
+
if (builtinKeys.has(intoKey)) {
|
|
318
|
+
issues.push({
|
|
319
|
+
level: "error",
|
|
320
|
+
message: `Step ${index + 1}: 'into: ${intoKey}' shadows a built-in context key`,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
const firstSeen = seenIntoKeys.get(intoKey);
|
|
325
|
+
if (firstSeen !== undefined) {
|
|
326
|
+
issues.push({
|
|
327
|
+
level: "warning",
|
|
328
|
+
message: `Step ${index + 1}: 'into: ${intoKey}' overwrites value already written by step ${firstSeen}`,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
seenIntoKeys.set(intoKey, index + 1);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
registerStepContextKeys(step, availableKeys);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function collectRenderedTemplates(step, isChainedRecipe) {
|
|
340
|
+
const templates = [];
|
|
341
|
+
// transform: renders with $result injected (raw tool output); any key under
|
|
342
|
+
// $result.* is resolved at runtime and cannot be statically validated.
|
|
343
|
+
const transformExtraKeys = new Set(["$result"]);
|
|
344
|
+
for (const [key, value] of Object.entries(step)) {
|
|
345
|
+
if (key === "tool" || key === "into" || key === "agent") {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
if (typeof value === "string") {
|
|
349
|
+
if (key === "transform") {
|
|
350
|
+
templates.push({ label: key, value, extraKeys: transformExtraKeys });
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
templates.push({ label: key, value });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
if (step.agent && typeof step.agent === "object") {
|
|
358
|
+
const agent = step.agent;
|
|
359
|
+
if (typeof agent.prompt === "string") {
|
|
360
|
+
templates.push({ label: "agent.prompt", value: agent.prompt });
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (isChainedRecipe && step.vars && typeof step.vars === "object") {
|
|
364
|
+
for (const [key, value] of Object.entries(step.vars)) {
|
|
365
|
+
if (typeof value === "string") {
|
|
366
|
+
templates.push({ label: `vars.${key}`, value });
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return templates;
|
|
371
|
+
}
|
|
372
|
+
function extractTemplateExpressions(template) {
|
|
373
|
+
const matches = template.matchAll(/\{\{\s*([^}]+?)\s*\}\}/g);
|
|
374
|
+
const expressions = [];
|
|
375
|
+
for (const match of matches) {
|
|
376
|
+
const expression = match[1]?.trim();
|
|
377
|
+
if (expression) {
|
|
378
|
+
expressions.push(expression);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return expressions;
|
|
382
|
+
}
|
|
383
|
+
function extractTemplateIdentifiers(expression) {
|
|
384
|
+
const reserved = new Set(["true", "false", "null"]);
|
|
385
|
+
const identifiers = new Set();
|
|
386
|
+
for (const match of expression.matchAll(/\$?[A-Za-z_][A-Za-z0-9_-]*(?:\.[A-Za-z0-9_-]+)*/g)) {
|
|
387
|
+
const rawIdentifier = match[0];
|
|
388
|
+
if (!rawIdentifier) {
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
const rootIdentifier = rawIdentifier.split(".")[0] ?? rawIdentifier;
|
|
392
|
+
if (!reserved.has(rootIdentifier)) {
|
|
393
|
+
identifiers.add(rootIdentifier);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return Array.from(identifiers);
|
|
397
|
+
}
|
|
398
|
+
function registerStepContextKeys(step, availableKeys) {
|
|
399
|
+
const stepId = typeof step.id === "string" ? step.id : undefined;
|
|
400
|
+
if (stepId) {
|
|
401
|
+
availableKeys.add(stepId);
|
|
402
|
+
}
|
|
403
|
+
if (step.agent && typeof step.agent === "object") {
|
|
404
|
+
const agent = step.agent;
|
|
405
|
+
const intoKey = typeof agent.into === "string" ? agent.into : "agent_output";
|
|
406
|
+
availableKeys.add(intoKey);
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
const intoKey = typeof step.into === "string" ? step.into : undefined;
|
|
410
|
+
if (!intoKey) {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
availableKeys.add(intoKey);
|
|
414
|
+
const toolId = typeof step.tool === "string" ? step.tool : undefined;
|
|
415
|
+
if (!toolId) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
for (const key of listToolOutputContextKeys(toolId, intoKey)) {
|
|
419
|
+
availableKeys.add(key);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function resolveStepIntoKey(step, isChainedRecipe) {
|
|
423
|
+
if (step.agent && typeof step.agent === "object") {
|
|
424
|
+
const agent = step.agent;
|
|
425
|
+
return typeof agent.into === "string" ? agent.into : "agent_output";
|
|
426
|
+
}
|
|
427
|
+
if (typeof step.into === "string")
|
|
428
|
+
return step.into;
|
|
429
|
+
if (isChainedRecipe && typeof step.id === "string")
|
|
430
|
+
return step.id;
|
|
431
|
+
return null;
|
|
432
|
+
}
|
|
433
|
+
//# sourceMappingURL=validation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/recipes/validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
* manual, cron — both run immediately via CLI
|
|
21
21
|
* git_hook, on_file_save — also runnable manually; trigger context injected
|
|
22
22
|
*/
|
|
23
|
+
import type { ErrorPolicy } from "./schema.js";
|
|
24
|
+
import "./tools/index.js";
|
|
23
25
|
export interface YamlStep {
|
|
24
26
|
tool?: string;
|
|
25
27
|
agent?: {
|
|
@@ -30,6 +32,11 @@ export interface YamlStep {
|
|
|
30
32
|
};
|
|
31
33
|
into?: string;
|
|
32
34
|
optional?: boolean;
|
|
35
|
+
/** Retry count for this step on failure (overrides recipe-level on_error.retry). */
|
|
36
|
+
retry?: number;
|
|
37
|
+
/** Delay in ms between retries (default 1000). */
|
|
38
|
+
retryDelay?: number;
|
|
39
|
+
transform?: string;
|
|
33
40
|
[key: string]: unknown;
|
|
34
41
|
}
|
|
35
42
|
export interface YamlTrigger {
|
|
@@ -39,14 +46,31 @@ export interface YamlTrigger {
|
|
|
39
46
|
on?: string;
|
|
40
47
|
filter?: string;
|
|
41
48
|
}
|
|
49
|
+
export interface YamlRecipeExpect {
|
|
50
|
+
stepsRun?: number;
|
|
51
|
+
outputs?: string[];
|
|
52
|
+
errorMessage?: string | null;
|
|
53
|
+
context?: Record<string, string>;
|
|
54
|
+
}
|
|
55
|
+
export interface AssertionFailure {
|
|
56
|
+
assertion: string;
|
|
57
|
+
expected: unknown;
|
|
58
|
+
actual: unknown;
|
|
59
|
+
message: string;
|
|
60
|
+
}
|
|
61
|
+
export declare function evaluateExpect(result: Pick<RunResult, "stepsRun" | "outputs" | "context" | "errorMessage">, expect: YamlRecipeExpect): AssertionFailure[];
|
|
42
62
|
export interface YamlRecipe {
|
|
43
63
|
name: string;
|
|
44
64
|
description?: string;
|
|
45
65
|
trigger: YamlTrigger;
|
|
46
66
|
steps: YamlStep[];
|
|
67
|
+
expect?: YamlRecipeExpect;
|
|
47
68
|
output?: {
|
|
48
69
|
path: string;
|
|
49
70
|
};
|
|
71
|
+
/** Plugin specs (npm package name or local path) to load before running steps. */
|
|
72
|
+
servers?: string[];
|
|
73
|
+
on_error?: ErrorPolicy;
|
|
50
74
|
}
|
|
51
75
|
export type RunContext = Record<string, string>;
|
|
52
76
|
export type FetchFn = (url: string, init?: {
|
|
@@ -55,6 +79,9 @@ export type FetchFn = (url: string, init?: {
|
|
|
55
79
|
ok: boolean;
|
|
56
80
|
json(): Promise<unknown>;
|
|
57
81
|
}>;
|
|
82
|
+
export interface MockToolConnector {
|
|
83
|
+
invoke<TOutput = unknown>(operation: string, input?: unknown): Promise<TOutput>;
|
|
84
|
+
}
|
|
58
85
|
export interface RunnerDeps {
|
|
59
86
|
now?: () => Date;
|
|
60
87
|
readFile?: (p: string) => string;
|
|
@@ -71,22 +98,82 @@ export interface RunnerDeps {
|
|
|
71
98
|
fetchFn?: FetchFn;
|
|
72
99
|
/** Optional token resolver for Gmail. Defaults to getValidAccessToken(). */
|
|
73
100
|
getGmailToken?: () => Promise<string>;
|
|
101
|
+
/** Override the ~/.patchwork dir used by RecipeRunLog. Useful for tests. */
|
|
102
|
+
logDir?: string;
|
|
74
103
|
/** Optional Anthropic API caller for agent steps. Defaults to fetch-based impl. */
|
|
75
104
|
claudeFn?: (prompt: string, model: string) => Promise<string>;
|
|
76
105
|
/** Optional Claude Code CLI caller for agent steps with driver: claude-code. */
|
|
77
106
|
claudeCodeFn?: (prompt: string) => Promise<string>;
|
|
107
|
+
/** Optional local LLM caller (Ollama / LM Studio) for agent steps with driver: local or model: local. */
|
|
108
|
+
localFn?: (prompt: string, model: string) => Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Optional provider driver invoker for agent steps with driver: openai|grok|gemini.
|
|
111
|
+
* Dispatches to src/drivers/* under the hood. If not provided, the runner will
|
|
112
|
+
* lazily construct a driver via createDriver() from drivers/index.js.
|
|
113
|
+
*/
|
|
114
|
+
providerDriverFn?: (driverName: "openai" | "grok" | "gemini", prompt: string, model: string | undefined) => Promise<string>;
|
|
115
|
+
/** Mock connector replays used by `patchwork recipe test`. */
|
|
116
|
+
mockConnectors?: Partial<Record<string, MockToolConnector>>;
|
|
117
|
+
/** Directory to store recorded connector fixtures for `patchwork recipe record`. */
|
|
118
|
+
recordFixturesDir?: string;
|
|
119
|
+
/** Suppress run logs / notifications for mocked recipe test execution. */
|
|
120
|
+
testMode?: boolean;
|
|
78
121
|
}
|
|
79
122
|
export interface RunResult {
|
|
80
123
|
recipe: string;
|
|
81
124
|
stepsRun: number;
|
|
82
125
|
outputs: string[];
|
|
83
126
|
context: RunContext;
|
|
127
|
+
stepResults: StepResult[];
|
|
128
|
+
errorMessage?: string;
|
|
129
|
+
assertionFailures?: AssertionFailure[];
|
|
84
130
|
}
|
|
131
|
+
export type StepResult = {
|
|
132
|
+
id: string;
|
|
133
|
+
tool?: string;
|
|
134
|
+
status: "ok" | "skipped" | "error";
|
|
135
|
+
error?: string;
|
|
136
|
+
durationMs: number;
|
|
137
|
+
};
|
|
138
|
+
export type StepDeps = Required<Omit<RunnerDeps, "now" | "logDir" | "recordFixturesDir">> & {
|
|
139
|
+
workdir: string;
|
|
140
|
+
logDir?: string;
|
|
141
|
+
recordFixturesDir?: string;
|
|
142
|
+
testMode: boolean;
|
|
143
|
+
};
|
|
85
144
|
export declare function loadYamlRecipe(filePath: string): YamlRecipe;
|
|
86
145
|
export declare function validateYamlRecipe(raw: unknown): YamlRecipe;
|
|
146
|
+
/**
|
|
147
|
+
* Load plugin specs declared in `recipe.servers` and register their tools into
|
|
148
|
+
* the recipe tool registry. Errors per-spec are logged as warnings — never fatal.
|
|
149
|
+
*/
|
|
150
|
+
export declare function loadRecipeServers(specs: string[]): Promise<void>;
|
|
87
151
|
export declare function runYamlRecipe(recipe: YamlRecipe, deps?: RunnerDeps, seedContext?: RunContext): Promise<RunResult>;
|
|
152
|
+
export declare function executeStep(step: YamlStep, ctx: RunContext, deps: StepDeps): Promise<string | null>;
|
|
88
153
|
/** Minimal `{{ expr }}` renderer — replaces against flat context map. */
|
|
89
154
|
export declare function render(template: string, ctx: RunContext): string;
|
|
155
|
+
/**
|
|
156
|
+
* Build ExecutionDeps for ChainedRecipeRunner backed by the yamlRunner step
|
|
157
|
+
* handlers. This lets chained recipes use the same tool set (file.*, git.*,
|
|
158
|
+
* gmail.*, github.*, linear.*, diagnostics.*) as simple YAML recipes.
|
|
159
|
+
*
|
|
160
|
+
* Pass the result as `chainedDeps` when calling `dispatchRecipe` or
|
|
161
|
+
* `runChainedRecipe` so that `executeTool` is properly wired.
|
|
162
|
+
*/
|
|
163
|
+
export declare function buildChainedDeps(runnerDeps: RunnerDeps, claudeCodeFnOverride?: (prompt: string) => Promise<string>): import("./chainedRunner.js").ExecutionDeps;
|
|
164
|
+
/**
|
|
165
|
+
* Dispatch a loaded recipe to the appropriate runner.
|
|
166
|
+
*
|
|
167
|
+
* Recipes with `trigger.type: "chained"` are routed to the ChainedRecipeRunner
|
|
168
|
+
* (parallel execution, template variables, nested recipes, dry-run).
|
|
169
|
+
* All other recipes use the existing synchronous yamlRunner path.
|
|
170
|
+
*
|
|
171
|
+
* `chainedDeps` is only required when the recipe is chained; omit for simple recipes.
|
|
172
|
+
*/
|
|
173
|
+
export declare function dispatchRecipe(recipe: YamlRecipe, deps: RunnerDeps & {
|
|
174
|
+
chainedDeps?: import("./chainedRunner.js").ExecutionDeps;
|
|
175
|
+
chainedOptions?: Partial<import("./chainedRunner.js").RunOptions>;
|
|
176
|
+
}, seedContext?: RunContext): Promise<RunResult | import("./chainedRunner.js").ChainedRunResult>;
|
|
90
177
|
/** List all YAML recipes in a directory. Returns names. */
|
|
91
178
|
export declare function listYamlRecipes(recipesDir: string): Array<{
|
|
92
179
|
name: string;
|