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.
Files changed (301) hide show
  1. package/README.bridge.md +6 -0
  2. package/README.md +40 -15
  3. package/deploy/bootstrap-vps.sh +184 -0
  4. package/deploy/deploy-dashboard.sh +174 -0
  5. package/deploy/deploy-landing.sh +79 -0
  6. package/dist/activationMetrics.d.ts +67 -0
  7. package/dist/activationMetrics.js +255 -0
  8. package/dist/activationMetrics.js.map +1 -0
  9. package/dist/approvalHttp.d.ts +24 -2
  10. package/dist/approvalHttp.js +150 -10
  11. package/dist/approvalHttp.js.map +1 -1
  12. package/dist/approvalQueue.d.ts +16 -1
  13. package/dist/approvalQueue.js +44 -3
  14. package/dist/approvalQueue.js.map +1 -1
  15. package/dist/automation.d.ts +20 -0
  16. package/dist/automation.js +54 -1
  17. package/dist/automation.js.map +1 -1
  18. package/dist/bridge.d.ts +2 -0
  19. package/dist/bridge.js +55 -130
  20. package/dist/bridge.js.map +1 -1
  21. package/dist/bridgeToken.js +57 -19
  22. package/dist/bridgeToken.js.map +1 -1
  23. package/dist/ccPermissions.js +6 -4
  24. package/dist/ccPermissions.js.map +1 -1
  25. package/dist/claudeOrchestrator.d.ts +1 -1
  26. package/dist/claudeOrchestrator.js +14 -8
  27. package/dist/claudeOrchestrator.js.map +1 -1
  28. package/dist/commands/launchd.d.ts +2 -0
  29. package/dist/commands/launchd.js +94 -0
  30. package/dist/commands/launchd.js.map +1 -0
  31. package/dist/commands/recipe.d.ts +258 -0
  32. package/dist/commands/recipe.js +1130 -0
  33. package/dist/commands/recipe.js.map +1 -0
  34. package/dist/commands/recipeInstall.d.ts +72 -0
  35. package/dist/commands/recipeInstall.js +339 -0
  36. package/dist/commands/recipeInstall.js.map +1 -0
  37. package/dist/config.d.ts +14 -1
  38. package/dist/config.js +99 -8
  39. package/dist/config.js.map +1 -1
  40. package/dist/connectors/baseConnector.d.ts +117 -0
  41. package/dist/connectors/baseConnector.js +213 -0
  42. package/dist/connectors/baseConnector.js.map +1 -0
  43. package/dist/connectors/confluence.d.ts +111 -0
  44. package/dist/connectors/confluence.js +406 -0
  45. package/dist/connectors/confluence.js.map +1 -0
  46. package/dist/connectors/datadog.d.ts +116 -0
  47. package/dist/connectors/datadog.js +385 -0
  48. package/dist/connectors/datadog.js.map +1 -0
  49. package/dist/connectors/fixtureLibrary.d.ts +21 -0
  50. package/dist/connectors/fixtureLibrary.js +70 -0
  51. package/dist/connectors/fixtureLibrary.js.map +1 -0
  52. package/dist/connectors/fixtureRecorder.d.ts +1 -0
  53. package/dist/connectors/fixtureRecorder.js +35 -0
  54. package/dist/connectors/fixtureRecorder.js.map +1 -0
  55. package/dist/connectors/github.d.ts +58 -8
  56. package/dist/connectors/github.js +312 -84
  57. package/dist/connectors/github.js.map +1 -1
  58. package/dist/connectors/gmail.d.ts +4 -1
  59. package/dist/connectors/gmail.js +79 -16
  60. package/dist/connectors/gmail.js.map +1 -1
  61. package/dist/connectors/googleCalendar.d.ts +60 -0
  62. package/dist/connectors/googleCalendar.js +345 -0
  63. package/dist/connectors/googleCalendar.js.map +1 -0
  64. package/dist/connectors/hubspot.d.ts +112 -0
  65. package/dist/connectors/hubspot.js +408 -0
  66. package/dist/connectors/hubspot.js.map +1 -0
  67. package/dist/connectors/intercom.d.ts +102 -0
  68. package/dist/connectors/intercom.js +402 -0
  69. package/dist/connectors/intercom.js.map +1 -0
  70. package/dist/connectors/jira.d.ts +98 -0
  71. package/dist/connectors/jira.js +379 -0
  72. package/dist/connectors/jira.js.map +1 -0
  73. package/dist/connectors/linear.d.ts +69 -19
  74. package/dist/connectors/linear.js +170 -129
  75. package/dist/connectors/linear.js.map +1 -1
  76. package/dist/connectors/mcpClient.d.ts +56 -0
  77. package/dist/connectors/mcpClient.js +189 -0
  78. package/dist/connectors/mcpClient.js.map +1 -0
  79. package/dist/connectors/mcpOAuth.d.ts +84 -0
  80. package/dist/connectors/mcpOAuth.js +389 -0
  81. package/dist/connectors/mcpOAuth.js.map +1 -0
  82. package/dist/connectors/mockConnector.d.ts +28 -0
  83. package/dist/connectors/mockConnector.js +81 -0
  84. package/dist/connectors/mockConnector.js.map +1 -0
  85. package/dist/connectors/notion.d.ts +143 -0
  86. package/dist/connectors/notion.js +424 -0
  87. package/dist/connectors/notion.js.map +1 -0
  88. package/dist/connectors/sentry.d.ts +17 -21
  89. package/dist/connectors/sentry.js +115 -131
  90. package/dist/connectors/sentry.js.map +1 -1
  91. package/dist/connectors/slack.d.ts +50 -0
  92. package/dist/connectors/slack.js +324 -0
  93. package/dist/connectors/slack.js.map +1 -0
  94. package/dist/connectors/stripe.d.ts +116 -0
  95. package/dist/connectors/stripe.js +379 -0
  96. package/dist/connectors/stripe.js.map +1 -0
  97. package/dist/connectors/tokenStorage.d.ts +35 -0
  98. package/dist/connectors/tokenStorage.js +459 -0
  99. package/dist/connectors/tokenStorage.js.map +1 -0
  100. package/dist/connectors/zendesk.d.ts +104 -0
  101. package/dist/connectors/zendesk.js +424 -0
  102. package/dist/connectors/zendesk.js.map +1 -0
  103. package/dist/drivers/gemini/index.d.ts +5 -1
  104. package/dist/drivers/gemini/index.js +39 -5
  105. package/dist/drivers/gemini/index.js.map +1 -1
  106. package/dist/drivers/index.d.ts +5 -0
  107. package/dist/drivers/index.js +1 -1
  108. package/dist/drivers/index.js.map +1 -1
  109. package/dist/featureFlags.d.ts +73 -0
  110. package/dist/featureFlags.js +203 -0
  111. package/dist/featureFlags.js.map +1 -0
  112. package/dist/fp/automationInterpreter.js +1 -0
  113. package/dist/fp/automationInterpreter.js.map +1 -1
  114. package/dist/fp/automationProgram.d.ts +1 -1
  115. package/dist/fp/automationProgram.js.map +1 -1
  116. package/dist/fp/policyParser.js +17 -0
  117. package/dist/fp/policyParser.js.map +1 -1
  118. package/dist/index.js +621 -61
  119. package/dist/index.js.map +1 -1
  120. package/dist/installGuard.d.ts +25 -0
  121. package/dist/installGuard.js +48 -0
  122. package/dist/installGuard.js.map +1 -0
  123. package/dist/oauth.d.ts +4 -1
  124. package/dist/oauth.js +50 -14
  125. package/dist/oauth.js.map +1 -1
  126. package/dist/patchworkConfig.d.ts +9 -0
  127. package/dist/patchworkConfig.js.map +1 -1
  128. package/dist/recipeOrchestration.d.ts +53 -0
  129. package/dist/recipeOrchestration.js +272 -0
  130. package/dist/recipeOrchestration.js.map +1 -0
  131. package/dist/recipes/RecipeOrchestrator.d.ts +40 -0
  132. package/dist/recipes/RecipeOrchestrator.js +51 -0
  133. package/dist/recipes/RecipeOrchestrator.js.map +1 -0
  134. package/dist/recipes/agentExecutor.d.ts +28 -0
  135. package/dist/recipes/agentExecutor.js +42 -0
  136. package/dist/recipes/agentExecutor.js.map +1 -0
  137. package/dist/recipes/chainedRunner.d.ts +140 -0
  138. package/dist/recipes/chainedRunner.js +539 -0
  139. package/dist/recipes/chainedRunner.js.map +1 -0
  140. package/dist/recipes/dependencyGraph.d.ts +39 -0
  141. package/dist/recipes/dependencyGraph.js +199 -0
  142. package/dist/recipes/dependencyGraph.js.map +1 -0
  143. package/dist/recipes/legacyRecipeCompat.d.ts +2 -0
  144. package/dist/recipes/legacyRecipeCompat.js +112 -0
  145. package/dist/recipes/legacyRecipeCompat.js.map +1 -0
  146. package/dist/recipes/manifest.d.ts +47 -0
  147. package/dist/recipes/manifest.js +141 -0
  148. package/dist/recipes/manifest.js.map +1 -0
  149. package/dist/recipes/nestedRecipeStep.d.ts +58 -0
  150. package/dist/recipes/nestedRecipeStep.js +95 -0
  151. package/dist/recipes/nestedRecipeStep.js.map +1 -0
  152. package/dist/recipes/outputRegistry.d.ts +28 -0
  153. package/dist/recipes/outputRegistry.js +52 -0
  154. package/dist/recipes/outputRegistry.js.map +1 -0
  155. package/dist/recipes/scheduler.d.ts +23 -7
  156. package/dist/recipes/scheduler.js +131 -41
  157. package/dist/recipes/scheduler.js.map +1 -1
  158. package/dist/recipes/schema.d.ts +17 -2
  159. package/dist/recipes/schemaGenerator.d.ts +28 -0
  160. package/dist/recipes/schemaGenerator.js +565 -0
  161. package/dist/recipes/schemaGenerator.js.map +1 -0
  162. package/dist/recipes/templateEngine.d.ts +62 -0
  163. package/dist/recipes/templateEngine.js +182 -0
  164. package/dist/recipes/templateEngine.js.map +1 -0
  165. package/dist/recipes/toolRegistry.d.ts +181 -0
  166. package/dist/recipes/toolRegistry.js +300 -0
  167. package/dist/recipes/toolRegistry.js.map +1 -0
  168. package/dist/recipes/tools/calendar.d.ts +6 -0
  169. package/dist/recipes/tools/calendar.js +61 -0
  170. package/dist/recipes/tools/calendar.js.map +1 -0
  171. package/dist/recipes/tools/confluence.d.ts +6 -0
  172. package/dist/recipes/tools/confluence.js +254 -0
  173. package/dist/recipes/tools/confluence.js.map +1 -0
  174. package/dist/recipes/tools/datadog.d.ts +6 -0
  175. package/dist/recipes/tools/datadog.js +239 -0
  176. package/dist/recipes/tools/datadog.js.map +1 -0
  177. package/dist/recipes/tools/diagnostics.d.ts +6 -0
  178. package/dist/recipes/tools/diagnostics.js +36 -0
  179. package/dist/recipes/tools/diagnostics.js.map +1 -0
  180. package/dist/recipes/tools/file.d.ts +6 -0
  181. package/dist/recipes/tools/file.js +170 -0
  182. package/dist/recipes/tools/file.js.map +1 -0
  183. package/dist/recipes/tools/git.d.ts +6 -0
  184. package/dist/recipes/tools/git.js +63 -0
  185. package/dist/recipes/tools/git.js.map +1 -0
  186. package/dist/recipes/tools/github.d.ts +6 -0
  187. package/dist/recipes/tools/github.js +91 -0
  188. package/dist/recipes/tools/github.js.map +1 -0
  189. package/dist/recipes/tools/gmail.d.ts +6 -0
  190. package/dist/recipes/tools/gmail.js +210 -0
  191. package/dist/recipes/tools/gmail.js.map +1 -0
  192. package/dist/recipes/tools/hubspot.d.ts +6 -0
  193. package/dist/recipes/tools/hubspot.js +232 -0
  194. package/dist/recipes/tools/hubspot.js.map +1 -0
  195. package/dist/recipes/tools/index.d.ts +22 -0
  196. package/dist/recipes/tools/index.js +25 -0
  197. package/dist/recipes/tools/index.js.map +1 -0
  198. package/dist/recipes/tools/intercom.d.ts +6 -0
  199. package/dist/recipes/tools/intercom.js +226 -0
  200. package/dist/recipes/tools/intercom.js.map +1 -0
  201. package/dist/recipes/tools/linear.d.ts +6 -0
  202. package/dist/recipes/tools/linear.js +83 -0
  203. package/dist/recipes/tools/linear.js.map +1 -0
  204. package/dist/recipes/tools/notion.d.ts +6 -0
  205. package/dist/recipes/tools/notion.js +278 -0
  206. package/dist/recipes/tools/notion.js.map +1 -0
  207. package/dist/recipes/tools/slack.d.ts +6 -0
  208. package/dist/recipes/tools/slack.js +72 -0
  209. package/dist/recipes/tools/slack.js.map +1 -0
  210. package/dist/recipes/tools/stripe.d.ts +6 -0
  211. package/dist/recipes/tools/stripe.js +265 -0
  212. package/dist/recipes/tools/stripe.js.map +1 -0
  213. package/dist/recipes/tools/zendesk.d.ts +6 -0
  214. package/dist/recipes/tools/zendesk.js +245 -0
  215. package/dist/recipes/tools/zendesk.js.map +1 -0
  216. package/dist/recipes/validation.d.ts +13 -0
  217. package/dist/recipes/validation.js +433 -0
  218. package/dist/recipes/validation.js.map +1 -0
  219. package/dist/recipes/yamlRunner.d.ts +87 -0
  220. package/dist/recipes/yamlRunner.js +693 -409
  221. package/dist/recipes/yamlRunner.js.map +1 -1
  222. package/dist/recipesHttp.d.ts +34 -6
  223. package/dist/recipesHttp.js +285 -15
  224. package/dist/recipesHttp.js.map +1 -1
  225. package/dist/riskTier.js +1 -0
  226. package/dist/riskTier.js.map +1 -1
  227. package/dist/runLog.d.ts +23 -0
  228. package/dist/runLog.js +56 -1
  229. package/dist/runLog.js.map +1 -1
  230. package/dist/schemas/dry-run-plan.v1.json +139 -0
  231. package/dist/schemas/recipe.v1.json +684 -0
  232. package/dist/server.d.ts +32 -1
  233. package/dist/server.js +980 -97
  234. package/dist/server.js.map +1 -1
  235. package/dist/streamableHttp.js +2 -0
  236. package/dist/streamableHttp.js.map +1 -1
  237. package/dist/tools/addLinearComment.d.ts +55 -0
  238. package/dist/tools/addLinearComment.js +72 -0
  239. package/dist/tools/addLinearComment.js.map +1 -0
  240. package/dist/tools/bridgeDoctor.js +2 -2
  241. package/dist/tools/bridgeDoctor.js.map +1 -1
  242. package/dist/tools/createLinearIssue.d.ts +84 -0
  243. package/dist/tools/createLinearIssue.js +146 -0
  244. package/dist/tools/createLinearIssue.js.map +1 -0
  245. package/dist/tools/fetchCalendarEvents.d.ts +94 -0
  246. package/dist/tools/fetchCalendarEvents.js +97 -0
  247. package/dist/tools/fetchCalendarEvents.js.map +1 -0
  248. package/dist/tools/fetchGithubIssue.d.ts +80 -0
  249. package/dist/tools/fetchGithubIssue.js +84 -0
  250. package/dist/tools/fetchGithubIssue.js.map +1 -0
  251. package/dist/tools/fetchGithubPR.d.ts +89 -0
  252. package/dist/tools/fetchGithubPR.js +96 -0
  253. package/dist/tools/fetchGithubPR.js.map +1 -0
  254. package/dist/tools/fetchSlackProfile.d.ts +43 -0
  255. package/dist/tools/fetchSlackProfile.js +46 -0
  256. package/dist/tools/fetchSlackProfile.js.map +1 -0
  257. package/dist/tools/getConnectorStatus.d.ts +58 -0
  258. package/dist/tools/getConnectorStatus.js +56 -0
  259. package/dist/tools/getConnectorStatus.js.map +1 -0
  260. package/dist/tools/github/actions.js +4 -2
  261. package/dist/tools/github/actions.js.map +1 -1
  262. package/dist/tools/github/composite.d.ts +339 -0
  263. package/dist/tools/github/composite.js +343 -0
  264. package/dist/tools/github/composite.js.map +1 -0
  265. package/dist/tools/github/index.d.ts +2 -1
  266. package/dist/tools/github/index.js +2 -1
  267. package/dist/tools/github/index.js.map +1 -1
  268. package/dist/tools/github/issues.js +8 -4
  269. package/dist/tools/github/issues.js.map +1 -1
  270. package/dist/tools/github/pr.d.ts +122 -0
  271. package/dist/tools/github/pr.js +195 -5
  272. package/dist/tools/github/pr.js.map +1 -1
  273. package/dist/tools/index.js +32 -1
  274. package/dist/tools/index.js.map +1 -1
  275. package/dist/tools/searchTools.js +1 -1
  276. package/dist/tools/searchTools.js.map +1 -1
  277. package/dist/tools/slackListChannels.d.ts +65 -0
  278. package/dist/tools/slackListChannels.js +70 -0
  279. package/dist/tools/slackListChannels.js.map +1 -0
  280. package/dist/tools/slackPostMessage.d.ts +57 -0
  281. package/dist/tools/slackPostMessage.js +77 -0
  282. package/dist/tools/slackPostMessage.js.map +1 -0
  283. package/dist/tools/testTraceToSource.js +2 -2
  284. package/dist/tools/testTraceToSource.js.map +1 -1
  285. package/dist/tools/updateLinearIssue.d.ts +89 -0
  286. package/dist/tools/updateLinearIssue.js +117 -0
  287. package/dist/tools/updateLinearIssue.js.map +1 -0
  288. package/dist/transport.d.ts +7 -1
  289. package/dist/transport.js +85 -11
  290. package/dist/transport.js.map +1 -1
  291. package/package.json +5 -2
  292. package/scripts/start-all.sh +56 -19
  293. package/templates/automation-policies/recipe-authoring.json +25 -0
  294. package/templates/automation-policy.example.json +6 -0
  295. package/templates/co.patchwork-os.bridge.plist +34 -0
  296. package/templates/recipes/ctx-loop-test.yaml +75 -0
  297. package/templates/recipes/lint-on-save.yaml +1 -2
  298. package/templates/recipes/morning-brief-slack.yaml +57 -0
  299. package/templates/recipes/morning-brief.yaml +14 -6
  300. package/templates/recipes/project-health-check.yaml +50 -0
  301. package/templates/recipes/sentry-to-linear.yaml +77 -0
@@ -0,0 +1,199 @@
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
+ /** Build dependency graph from step definitions */
11
+ export function buildDependencyGraph(steps) {
12
+ const nodes = steps.map((s, index) => ({
13
+ stepId: s.id,
14
+ awaits: s.awaits ?? [],
15
+ index,
16
+ }));
17
+ // Detect cycles using DFS
18
+ const visited = new Set();
19
+ const visiting = new Set();
20
+ const cycles = [];
21
+ function visit(node, path) {
22
+ if (visiting.has(node.stepId)) {
23
+ // Found cycle - extract cycle from path
24
+ const cycleStart = path.indexOf(node.stepId);
25
+ cycles.push(path.slice(cycleStart).concat(node.stepId));
26
+ return;
27
+ }
28
+ if (visited.has(node.stepId))
29
+ return;
30
+ visiting.add(node.stepId);
31
+ path.push(node.stepId);
32
+ for (const depId of node.awaits) {
33
+ const dep = nodes.find((n) => n.stepId === depId);
34
+ if (dep)
35
+ visit(dep, path);
36
+ }
37
+ path.pop();
38
+ visiting.delete(node.stepId);
39
+ visited.add(node.stepId);
40
+ }
41
+ for (const node of nodes) {
42
+ if (!visited.has(node.stepId)) {
43
+ visit(node, []);
44
+ }
45
+ }
46
+ // Calculate topological order (Kahn's algorithm)
47
+ const inDegree = new Map();
48
+ const adjacency = new Map();
49
+ for (const node of nodes) {
50
+ inDegree.set(node.stepId, node.awaits.length);
51
+ for (const dep of node.awaits) {
52
+ if (!adjacency.has(dep))
53
+ adjacency.set(dep, []);
54
+ adjacency.get(dep)?.push(node.stepId);
55
+ }
56
+ }
57
+ const queue = [];
58
+ for (const [stepId, degree] of inDegree) {
59
+ if (degree === 0)
60
+ queue.push(stepId);
61
+ }
62
+ const topologicalOrder = [];
63
+ while (queue.length > 0) {
64
+ const stepId = queue.shift();
65
+ topologicalOrder.push(stepId);
66
+ const dependents = adjacency.get(stepId) ?? [];
67
+ for (const dep of dependents) {
68
+ const newDegree = (inDegree.get(dep) ?? 0) - 1;
69
+ inDegree.set(dep, newDegree);
70
+ if (newDegree === 0)
71
+ queue.push(dep);
72
+ }
73
+ }
74
+ return {
75
+ steps: nodes,
76
+ hasCycles: cycles.length > 0,
77
+ topologicalOrder,
78
+ };
79
+ }
80
+ /** Format cycle for error message */
81
+ export function formatCycle(cycles) {
82
+ if (cycles.length === 0)
83
+ return "No cycles detected";
84
+ return cycles
85
+ .map((cycle, i) => ` Cycle ${i + 1}: ${cycle.join(" → ")}`)
86
+ .join("\n");
87
+ }
88
+ /** Execute steps respecting dependencies with limited concurrency */
89
+ export async function executeWithDependencies(graph, executeStep, options) {
90
+ if (graph.hasCycles) {
91
+ throw new Error(`Dependency graph has cycles - cannot execute`);
92
+ }
93
+ const results = new Map();
94
+ const completed = new Set();
95
+ const failed = new Set(); // C1: track which completed steps failed
96
+ const inProgress = new Set();
97
+ // Store resolver functions to signal when steps complete
98
+ const resolvers = new Map();
99
+ // Track which steps are waiting for which dependencies
100
+ const waitingFor = new Map();
101
+ for (const node of graph.steps) {
102
+ waitingFor.set(node.stepId, [...node.awaits]);
103
+ }
104
+ function waitForStep(stepId) {
105
+ if (completed.has(stepId))
106
+ return Promise.resolve();
107
+ return new Promise((resolve) => {
108
+ const list = resolvers.get(stepId);
109
+ if (list) {
110
+ list.push(resolve);
111
+ }
112
+ else {
113
+ resolvers.set(stepId, [resolve]);
114
+ }
115
+ });
116
+ }
117
+ async function runStep(stepId) {
118
+ if (inProgress.has(stepId) || completed.has(stepId))
119
+ return;
120
+ // Check if all dependencies are satisfied
121
+ const deps = waitingFor.get(stepId) ?? [];
122
+ const unresolved = deps.filter((d) => !completed.has(d));
123
+ if (unresolved.length > 0) {
124
+ await Promise.all(unresolved.map(waitForStep));
125
+ }
126
+ // C1: skip if any upstream dependency failed
127
+ const failedDep = deps.find((d) => failed.has(d));
128
+ if (failedDep) {
129
+ const err = new Error(`Skipped: upstream step "${failedDep}" failed`);
130
+ results.set(stepId, { success: false, error: err });
131
+ completed.add(stepId);
132
+ failed.add(stepId);
133
+ options.onStepComplete?.(stepId, err);
134
+ // Unblock any steps waiting on this one
135
+ const waiting = resolvers.get(stepId) ?? [];
136
+ for (const resolve of waiting)
137
+ resolve();
138
+ resolvers.delete(stepId);
139
+ return;
140
+ }
141
+ inProgress.add(stepId);
142
+ options.onStepStart?.(stepId);
143
+ let stepErr;
144
+ try {
145
+ await executeStep(stepId);
146
+ results.set(stepId, { success: true });
147
+ completed.add(stepId);
148
+ }
149
+ catch (error) {
150
+ stepErr = error instanceof Error ? error : new Error(String(error));
151
+ results.set(stepId, { success: false, error: stepErr });
152
+ completed.add(stepId);
153
+ failed.add(stepId); // C1: record failure so dependents are skipped
154
+ }
155
+ finally {
156
+ options.onStepComplete?.(stepId, stepErr);
157
+ inProgress.delete(stepId);
158
+ // Signal dependents
159
+ const waiting = resolvers.get(stepId) ?? [];
160
+ for (const resolve of waiting) {
161
+ resolve();
162
+ }
163
+ resolvers.delete(stepId);
164
+ }
165
+ }
166
+ // Execute with concurrency limit
167
+ const executing = [];
168
+ const queue = [...graph.topologicalOrder];
169
+ async function processQueue() {
170
+ while (queue.length > 0 || executing.length > 0) {
171
+ // Start new steps if under concurrency limit
172
+ while (executing.length < options.maxConcurrency && queue.length > 0) {
173
+ const stepId = queue.shift();
174
+ // C2: push before attaching .then() so indexOf is never -1
175
+ let resolveSlot;
176
+ const slot = new Promise((r) => {
177
+ resolveSlot = r;
178
+ });
179
+ executing.push(slot);
180
+ runStep(stepId).then(() => {
181
+ executing.splice(executing.indexOf(slot), 1);
182
+ resolveSlot();
183
+ });
184
+ }
185
+ if (executing.length > 0) {
186
+ await Promise.race(executing);
187
+ }
188
+ }
189
+ }
190
+ await processQueue();
191
+ return results;
192
+ }
193
+ /** Get steps that can run immediately (no unresolved dependencies) */
194
+ export function getReadySteps(graph, completed) {
195
+ return graph.steps
196
+ .filter((s) => !completed.has(s.stepId) && s.awaits.every((dep) => completed.has(dep)))
197
+ .map((s) => s.stepId);
198
+ }
199
+ //# sourceMappingURL=dependencyGraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencyGraph.js","sourceRoot":"","sources":["../../src/recipes/dependencyGraph.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export type WarnFn = (msg: string) => void;
2
+ export declare function normalizeRecipeForRuntime(recipe: unknown, warn?: WarnFn): unknown;
@@ -0,0 +1,112 @@
1
+ function isRecord(value) {
2
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3
+ }
4
+ export function normalizeRecipeForRuntime(recipe, warn) {
5
+ if (!isRecord(recipe)) {
6
+ return recipe;
7
+ }
8
+ const normalized = {
9
+ ...recipe,
10
+ };
11
+ if (isRecord(normalized.trigger)) {
12
+ normalized.trigger = normalizeLegacyTriggerForRuntime(normalized.trigger, warn);
13
+ }
14
+ if (Array.isArray(normalized.steps)) {
15
+ normalized.steps = normalized.steps.map((step) => normalizeLegacyRuntimeStep(step, warn));
16
+ }
17
+ return normalized;
18
+ }
19
+ function normalizeLegacyTriggerForRuntime(trigger, warn) {
20
+ const normalized = { ...trigger };
21
+ if (normalized.type === "cron" &&
22
+ typeof normalized.schedule === "string" &&
23
+ typeof normalized.at !== "string") {
24
+ warn?.("Deprecated recipe field: trigger.schedule — rename to trigger.at (will be removed in a future major version)");
25
+ normalized.at = normalized.schedule;
26
+ }
27
+ delete normalized.schedule;
28
+ return normalized;
29
+ }
30
+ function normalizeLegacyRuntimeStep(step, warn) {
31
+ if (!isRecord(step)) {
32
+ return step;
33
+ }
34
+ const normalized = {};
35
+ for (const [key, value] of Object.entries(step)) {
36
+ if (key === "params" || key === "output" || key === "prompt") {
37
+ continue;
38
+ }
39
+ if (key === "agent" && typeof value === "boolean") {
40
+ continue;
41
+ }
42
+ if (key === "parallel" && Array.isArray(value)) {
43
+ normalized.parallel = value.map((entry) => normalizeLegacyRuntimeStep(entry, warn));
44
+ continue;
45
+ }
46
+ if (key === "branch" && Array.isArray(value)) {
47
+ normalized.branch = value.map((entry) => normalizeLegacyBranchEntry(entry, warn));
48
+ continue;
49
+ }
50
+ normalized[key] = value;
51
+ }
52
+ if (step.agent === true || isRecord(step.agent)) {
53
+ const agentConfig = isRecord(step.agent)
54
+ ? { ...step.agent }
55
+ : {};
56
+ if (typeof step.prompt === "string" &&
57
+ typeof agentConfig.prompt !== "string") {
58
+ warn?.("Deprecated recipe step field: prompt at step level — move to step.agent.prompt (will be removed in a future major version)");
59
+ agentConfig.prompt = step.prompt;
60
+ }
61
+ if (typeof step.output === "string" &&
62
+ typeof agentConfig.into !== "string") {
63
+ warn?.("Deprecated recipe step field: output — use step.agent.into instead (will be removed in a future major version)");
64
+ agentConfig.into = step.output;
65
+ }
66
+ if (step.agent === true) {
67
+ warn?.("Deprecated recipe step field: agent: true — use agent: { prompt, into } object instead (will be removed in a future major version)");
68
+ }
69
+ normalized.agent = agentConfig;
70
+ return normalized;
71
+ }
72
+ if (isRecord(step.params)) {
73
+ warn?.("Deprecated recipe step field: params — inline fields directly on the step (will be removed in a future major version)");
74
+ Object.assign(normalized, step.params);
75
+ }
76
+ if (typeof normalized.recipe !== "string" &&
77
+ typeof normalized.chain === "string") {
78
+ warn?.("Deprecated recipe step field: chain — rename to recipe (will be removed in a future major version)");
79
+ normalized.recipe = normalized.chain;
80
+ }
81
+ delete normalized.chain;
82
+ if (typeof normalized.into !== "string" && typeof step.output === "string") {
83
+ warn?.("Deprecated recipe step field: output — rename to into (will be removed in a future major version)");
84
+ normalized.into = step.output;
85
+ }
86
+ if (normalized.tool === "file.append" &&
87
+ typeof normalized.content !== "string" &&
88
+ typeof normalized.line === "string") {
89
+ warn?.("Deprecated recipe step field: line (file.append) — rename to content (will be removed in a future major version)");
90
+ normalized.content = normalized.line;
91
+ delete normalized.line;
92
+ }
93
+ return normalized;
94
+ }
95
+ function normalizeLegacyBranchEntry(entry, warn) {
96
+ if (!isRecord(entry)) {
97
+ return entry;
98
+ }
99
+ const normalized = {};
100
+ for (const [key, value] of Object.entries(entry)) {
101
+ if (key === "otherwise" && isRecord(value)) {
102
+ normalized.otherwise = normalizeLegacyRuntimeStep(value, warn);
103
+ continue;
104
+ }
105
+ normalized[key] = value;
106
+ }
107
+ if (Object.hasOwn(normalized, "otherwise")) {
108
+ return normalized;
109
+ }
110
+ return normalizeLegacyRuntimeStep(entry, warn);
111
+ }
112
+ //# sourceMappingURL=legacyRecipeCompat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacyRecipeCompat.js","sourceRoot":"","sources":["../../src/recipes/legacyRecipeCompat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * RecipeManifest — recipe.json format for the Patchwork recipe marketplace.
3
+ *
4
+ * Each recipe package directory contains a recipe.json manifest describing
5
+ * the package metadata, entry-point recipe file, child recipes, required
6
+ * connectors, and configurable variables.
7
+ */
8
+ export interface RecipeManifest {
9
+ name: string;
10
+ version: string;
11
+ description: string;
12
+ author?: string;
13
+ license?: string;
14
+ tags?: string[];
15
+ connectors?: string[];
16
+ recipes: {
17
+ main: string;
18
+ children?: string[];
19
+ };
20
+ variables?: Record<string, {
21
+ description: string;
22
+ required?: boolean;
23
+ default?: string;
24
+ }>;
25
+ homepage?: string;
26
+ repository?: string;
27
+ }
28
+ /**
29
+ * Validate an unknown value as a RecipeManifest.
30
+ * Throws a descriptive Error if any required field is missing or invalid.
31
+ */
32
+ export declare function validateManifest(manifest: unknown): RecipeManifest;
33
+ /**
34
+ * Parse and validate a recipe.json string.
35
+ * Throws with a clear error message if invalid JSON or schema violations.
36
+ */
37
+ export declare function parseManifest(json: string): RecipeManifest;
38
+ /**
39
+ * Load and parse recipe.json from a directory.
40
+ * Returns null if the file does not exist (not a recipe package dir).
41
+ * Throws if file exists but is invalid.
42
+ */
43
+ export declare function loadManifestFromDir(dir: string): RecipeManifest | null;
44
+ /**
45
+ * Returns all recipe filenames declared in the manifest: [main, ...children].
46
+ */
47
+ export declare function getManifestRecipeFiles(manifest: RecipeManifest): string[];
@@ -0,0 +1,141 @@
1
+ /**
2
+ * RecipeManifest — recipe.json format for the Patchwork recipe marketplace.
3
+ *
4
+ * Each recipe package directory contains a recipe.json manifest describing
5
+ * the package metadata, entry-point recipe file, child recipes, required
6
+ * connectors, and configurable variables.
7
+ */
8
+ import { existsSync, readFileSync } from "node:fs";
9
+ import path from "node:path";
10
+ const NAME_RE = /^(@[a-z0-9-]+\/)?[a-z0-9][a-z0-9\-_.]*$/;
11
+ const VERSION_RE = /^\d+\.\d+\.\d+/;
12
+ const YAML_EXT_RE = /\.ya?ml$/;
13
+ function isYamlFile(filename) {
14
+ return typeof filename === "string" && YAML_EXT_RE.test(filename);
15
+ }
16
+ /**
17
+ * Validate an unknown value as a RecipeManifest.
18
+ * Throws a descriptive Error if any required field is missing or invalid.
19
+ */
20
+ export function validateManifest(manifest) {
21
+ if (typeof manifest !== "object" || manifest === null) {
22
+ throw new Error("recipe.json must be a JSON object");
23
+ }
24
+ const m = manifest;
25
+ // name
26
+ if (typeof m.name !== "string" || !m.name) {
27
+ throw new Error('recipe.json: "name" is required and must be a string');
28
+ }
29
+ if (!NAME_RE.test(m.name)) {
30
+ throw new Error(`recipe.json: "name" must match pattern (@scope/)?[a-z0-9][a-z0-9-_.]* — got "${m.name}"`);
31
+ }
32
+ // version
33
+ if (typeof m.version !== "string" || !m.version) {
34
+ throw new Error('recipe.json: "version" is required and must be a string');
35
+ }
36
+ if (!VERSION_RE.test(m.version)) {
37
+ throw new Error(`recipe.json: "version" must be valid semver (e.g. "1.0.0") — got "${m.version}"`);
38
+ }
39
+ // description
40
+ if (typeof m.description !== "string" || !m.description) {
41
+ throw new Error('recipe.json: "description" is required and must be a non-empty string');
42
+ }
43
+ // recipes
44
+ if (typeof m.recipes !== "object" || m.recipes === null) {
45
+ throw new Error('recipe.json: "recipes" is required and must be an object');
46
+ }
47
+ const recipes = m.recipes;
48
+ if (!isYamlFile(recipes.main)) {
49
+ throw new Error(`recipe.json: "recipes.main" must be a .yaml or .yml filename — got "${recipes.main}"`);
50
+ }
51
+ if (recipes.children !== undefined) {
52
+ if (!Array.isArray(recipes.children)) {
53
+ throw new Error('recipe.json: "recipes.children" must be an array');
54
+ }
55
+ for (let i = 0; i < recipes.children.length; i++) {
56
+ if (!isYamlFile(recipes.children[i])) {
57
+ throw new Error(`recipe.json: "recipes.children[${i}]" must be a .yaml or .yml filename — got "${recipes.children[i]}"`);
58
+ }
59
+ }
60
+ }
61
+ // optional string fields
62
+ for (const field of [
63
+ "author",
64
+ "license",
65
+ "homepage",
66
+ "repository",
67
+ ]) {
68
+ if (m[field] !== undefined && typeof m[field] !== "string") {
69
+ throw new Error(`recipe.json: "${field}" must be a string`);
70
+ }
71
+ }
72
+ // optional string[] fields
73
+ for (const field of ["tags", "connectors"]) {
74
+ if (m[field] !== undefined) {
75
+ if (!Array.isArray(m[field])) {
76
+ throw new Error(`recipe.json: "${field}" must be an array of strings`);
77
+ }
78
+ for (let i = 0; i < m[field].length; i++) {
79
+ if (typeof m[field][i] !== "string") {
80
+ throw new Error(`recipe.json: "${field}[${i}]" must be a string`);
81
+ }
82
+ }
83
+ }
84
+ }
85
+ // variables
86
+ if (m.variables !== undefined) {
87
+ if (typeof m.variables !== "object" || m.variables === null) {
88
+ throw new Error('recipe.json: "variables" must be an object');
89
+ }
90
+ for (const [key, val] of Object.entries(m.variables)) {
91
+ if (typeof val !== "object" || val === null) {
92
+ throw new Error(`recipe.json: "variables.${key}" must be an object with a "description" field`);
93
+ }
94
+ const v = val;
95
+ if (typeof v.description !== "string" || !v.description) {
96
+ throw new Error(`recipe.json: "variables.${key}.description" is required and must be a non-empty string`);
97
+ }
98
+ if (v.required !== undefined && typeof v.required !== "boolean") {
99
+ throw new Error(`recipe.json: "variables.${key}.required" must be a boolean`);
100
+ }
101
+ if (v.default !== undefined && typeof v.default !== "string") {
102
+ throw new Error(`recipe.json: "variables.${key}.default" must be a string`);
103
+ }
104
+ }
105
+ }
106
+ return m;
107
+ }
108
+ /**
109
+ * Parse and validate a recipe.json string.
110
+ * Throws with a clear error message if invalid JSON or schema violations.
111
+ */
112
+ export function parseManifest(json) {
113
+ let parsed;
114
+ try {
115
+ parsed = JSON.parse(json);
116
+ }
117
+ catch (err) {
118
+ throw new Error(`recipe.json: invalid JSON — ${err instanceof Error ? err.message : String(err)}`);
119
+ }
120
+ return validateManifest(parsed);
121
+ }
122
+ /**
123
+ * Load and parse recipe.json from a directory.
124
+ * Returns null if the file does not exist (not a recipe package dir).
125
+ * Throws if file exists but is invalid.
126
+ */
127
+ export function loadManifestFromDir(dir) {
128
+ const manifestPath = path.join(dir, "recipe.json");
129
+ if (!existsSync(manifestPath)) {
130
+ return null;
131
+ }
132
+ const raw = readFileSync(manifestPath, "utf-8");
133
+ return parseManifest(raw);
134
+ }
135
+ /**
136
+ * Returns all recipe filenames declared in the manifest: [main, ...children].
137
+ */
138
+ export function getManifestRecipeFiles(manifest) {
139
+ return [manifest.recipes.main, ...(manifest.recipes.children ?? [])];
140
+ }
141
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/recipes/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * NestedRecipeStep — handler for calling recipes from within recipes.
3
+ *
4
+ * Supports:
5
+ * - Variable passing via template resolution
6
+ * - Isolated OutputRegistry for child
7
+ * - Risk escalation (child risk > parent risk uses child's)
8
+ * - Depth limiting (prevent infinite recursion)
9
+ */
10
+ import type { OutputRegistry } from "./outputRegistry.js";
11
+ import type { TemplateContext, TemplateError } from "./templateEngine.js";
12
+ export interface NestedRecipeConfig {
13
+ recipe: string;
14
+ vars: Record<string, string>;
15
+ output?: string;
16
+ risk?: "low" | "medium" | "high";
17
+ id: string;
18
+ }
19
+ export interface NestedRecipeContext {
20
+ parentRegistry: OutputRegistry;
21
+ parentEnv: Record<string, string | undefined>;
22
+ recipeMaxDepth: number;
23
+ currentDepth: number;
24
+ dryRun: boolean;
25
+ }
26
+ export interface NestedRecipeResult {
27
+ success: boolean;
28
+ data?: unknown;
29
+ error?: string;
30
+ childOutputs?: Record<string, unknown>;
31
+ }
32
+ export interface RecipeLoader {
33
+ loadRecipe(name: string): Promise<{
34
+ steps: unknown[];
35
+ } | null>;
36
+ }
37
+ /** Resolve template variables against parent context */
38
+ export declare function resolveNestedVars(vars: Record<string, string>, context: TemplateContext): {
39
+ resolved: Record<string, string>;
40
+ errors: TemplateError[];
41
+ };
42
+ /** Validate nested recipe call before execution */
43
+ export declare function validateNestedRecipe(config: NestedRecipeConfig, context: NestedRecipeContext): {
44
+ valid: boolean;
45
+ error?: string;
46
+ };
47
+ /** Calculate effective risk tier */
48
+ export declare function calculateNestedRisk(parentRisk: "low" | "medium" | "high" | undefined, childRisk: "low" | "medium" | "high" | undefined): "low" | "medium" | "high";
49
+ /** Format nested recipe result for parent registry */
50
+ export declare function formatNestedOutput(result: NestedRecipeResult, config: NestedRecipeConfig): {
51
+ stepId: string;
52
+ output: {
53
+ status: "success" | "error" | "skipped";
54
+ data: unknown;
55
+ };
56
+ };
57
+ /** Mock nested recipe execution for dry-run mode */
58
+ export declare function mockNestedRecipe(config: NestedRecipeConfig, context: NestedRecipeContext): Promise<NestedRecipeResult>;