@synth-deploy/server 0.1.0

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 (317) hide show
  1. package/dist/agent/debrief-retention.d.ts +12 -0
  2. package/dist/agent/debrief-retention.d.ts.map +1 -0
  3. package/dist/agent/debrief-retention.js +27 -0
  4. package/dist/agent/debrief-retention.js.map +1 -0
  5. package/dist/agent/envoy-client.d.ts +216 -0
  6. package/dist/agent/envoy-client.d.ts.map +1 -0
  7. package/dist/agent/envoy-client.js +266 -0
  8. package/dist/agent/envoy-client.js.map +1 -0
  9. package/dist/agent/envoy-registry.d.ts +102 -0
  10. package/dist/agent/envoy-registry.d.ts.map +1 -0
  11. package/dist/agent/envoy-registry.js +319 -0
  12. package/dist/agent/envoy-registry.js.map +1 -0
  13. package/dist/agent/health-checker.d.ts +39 -0
  14. package/dist/agent/health-checker.d.ts.map +1 -0
  15. package/dist/agent/health-checker.js +49 -0
  16. package/dist/agent/health-checker.js.map +1 -0
  17. package/dist/agent/mcp-client-manager.d.ts +36 -0
  18. package/dist/agent/mcp-client-manager.d.ts.map +1 -0
  19. package/dist/agent/mcp-client-manager.js +106 -0
  20. package/dist/agent/mcp-client-manager.js.map +1 -0
  21. package/dist/agent/stale-deployment-detector.d.ts +15 -0
  22. package/dist/agent/stale-deployment-detector.d.ts.map +1 -0
  23. package/dist/agent/stale-deployment-detector.js +50 -0
  24. package/dist/agent/stale-deployment-detector.js.map +1 -0
  25. package/dist/agent/step-runner.d.ts +31 -0
  26. package/dist/agent/step-runner.d.ts.map +1 -0
  27. package/dist/agent/step-runner.js +80 -0
  28. package/dist/agent/step-runner.js.map +1 -0
  29. package/dist/agent/synth-agent.d.ts +168 -0
  30. package/dist/agent/synth-agent.d.ts.map +1 -0
  31. package/dist/agent/synth-agent.js +1195 -0
  32. package/dist/agent/synth-agent.js.map +1 -0
  33. package/dist/api/agent.d.ts +36 -0
  34. package/dist/api/agent.d.ts.map +1 -0
  35. package/dist/api/agent.js +867 -0
  36. package/dist/api/agent.js.map +1 -0
  37. package/dist/api/api-keys.d.ts +4 -0
  38. package/dist/api/api-keys.d.ts.map +1 -0
  39. package/dist/api/api-keys.js +118 -0
  40. package/dist/api/api-keys.js.map +1 -0
  41. package/dist/api/artifacts.d.ts +5 -0
  42. package/dist/api/artifacts.d.ts.map +1 -0
  43. package/dist/api/artifacts.js +142 -0
  44. package/dist/api/artifacts.js.map +1 -0
  45. package/dist/api/auth.d.ts +4 -0
  46. package/dist/api/auth.d.ts.map +1 -0
  47. package/dist/api/auth.js +280 -0
  48. package/dist/api/auth.js.map +1 -0
  49. package/dist/api/deployments.d.ts +11 -0
  50. package/dist/api/deployments.d.ts.map +1 -0
  51. package/dist/api/deployments.js +1098 -0
  52. package/dist/api/deployments.js.map +1 -0
  53. package/dist/api/environments.d.ts +5 -0
  54. package/dist/api/environments.d.ts.map +1 -0
  55. package/dist/api/environments.js +69 -0
  56. package/dist/api/environments.js.map +1 -0
  57. package/dist/api/envoy-reports.d.ts +17 -0
  58. package/dist/api/envoy-reports.d.ts.map +1 -0
  59. package/dist/api/envoy-reports.js +138 -0
  60. package/dist/api/envoy-reports.js.map +1 -0
  61. package/dist/api/envoys.d.ts +5 -0
  62. package/dist/api/envoys.d.ts.map +1 -0
  63. package/dist/api/envoys.js +192 -0
  64. package/dist/api/envoys.js.map +1 -0
  65. package/dist/api/fleet.d.ts +11 -0
  66. package/dist/api/fleet.d.ts.map +1 -0
  67. package/dist/api/fleet.js +394 -0
  68. package/dist/api/fleet.js.map +1 -0
  69. package/dist/api/graph.d.ts +8 -0
  70. package/dist/api/graph.d.ts.map +1 -0
  71. package/dist/api/graph.js +355 -0
  72. package/dist/api/graph.js.map +1 -0
  73. package/dist/api/health.d.ts +20 -0
  74. package/dist/api/health.d.ts.map +1 -0
  75. package/dist/api/health.js +248 -0
  76. package/dist/api/health.js.map +1 -0
  77. package/dist/api/idp-schemas.d.ts +41 -0
  78. package/dist/api/idp-schemas.d.ts.map +1 -0
  79. package/dist/api/idp-schemas.js +17 -0
  80. package/dist/api/idp-schemas.js.map +1 -0
  81. package/dist/api/idp.d.ts +6 -0
  82. package/dist/api/idp.d.ts.map +1 -0
  83. package/dist/api/idp.js +620 -0
  84. package/dist/api/idp.js.map +1 -0
  85. package/dist/api/intake.d.ts +10 -0
  86. package/dist/api/intake.d.ts.map +1 -0
  87. package/dist/api/intake.js +418 -0
  88. package/dist/api/intake.js.map +1 -0
  89. package/dist/api/partitions.d.ts +5 -0
  90. package/dist/api/partitions.d.ts.map +1 -0
  91. package/dist/api/partitions.js +113 -0
  92. package/dist/api/partitions.js.map +1 -0
  93. package/dist/api/progress-event-store.d.ts +62 -0
  94. package/dist/api/progress-event-store.d.ts.map +1 -0
  95. package/dist/api/progress-event-store.js +118 -0
  96. package/dist/api/progress-event-store.js.map +1 -0
  97. package/dist/api/schemas.d.ts +1000 -0
  98. package/dist/api/schemas.d.ts.map +1 -0
  99. package/dist/api/schemas.js +328 -0
  100. package/dist/api/schemas.js.map +1 -0
  101. package/dist/api/security-boundaries.d.ts +4 -0
  102. package/dist/api/security-boundaries.d.ts.map +1 -0
  103. package/dist/api/security-boundaries.js +32 -0
  104. package/dist/api/security-boundaries.js.map +1 -0
  105. package/dist/api/settings.d.ts +4 -0
  106. package/dist/api/settings.d.ts.map +1 -0
  107. package/dist/api/settings.js +99 -0
  108. package/dist/api/settings.js.map +1 -0
  109. package/dist/api/system.d.ts +75 -0
  110. package/dist/api/system.d.ts.map +1 -0
  111. package/dist/api/system.js +558 -0
  112. package/dist/api/system.js.map +1 -0
  113. package/dist/api/telemetry.d.ts +4 -0
  114. package/dist/api/telemetry.d.ts.map +1 -0
  115. package/dist/api/telemetry.js +24 -0
  116. package/dist/api/telemetry.js.map +1 -0
  117. package/dist/api/users.d.ts +4 -0
  118. package/dist/api/users.d.ts.map +1 -0
  119. package/dist/api/users.js +173 -0
  120. package/dist/api/users.js.map +1 -0
  121. package/dist/archive-unpacker.d.ts +24 -0
  122. package/dist/archive-unpacker.d.ts.map +1 -0
  123. package/dist/archive-unpacker.js +239 -0
  124. package/dist/archive-unpacker.js.map +1 -0
  125. package/dist/artifact-analyzer.d.ts +59 -0
  126. package/dist/artifact-analyzer.d.ts.map +1 -0
  127. package/dist/artifact-analyzer.js +334 -0
  128. package/dist/artifact-analyzer.js.map +1 -0
  129. package/dist/auth/idp/index.d.ts +9 -0
  130. package/dist/auth/idp/index.d.ts.map +1 -0
  131. package/dist/auth/idp/index.js +5 -0
  132. package/dist/auth/idp/index.js.map +1 -0
  133. package/dist/auth/idp/ldap.d.ts +56 -0
  134. package/dist/auth/idp/ldap.d.ts.map +1 -0
  135. package/dist/auth/idp/ldap.js +276 -0
  136. package/dist/auth/idp/ldap.js.map +1 -0
  137. package/dist/auth/idp/oidc.d.ts +27 -0
  138. package/dist/auth/idp/oidc.d.ts.map +1 -0
  139. package/dist/auth/idp/oidc.js +97 -0
  140. package/dist/auth/idp/oidc.js.map +1 -0
  141. package/dist/auth/idp/role-mapping.d.ts +9 -0
  142. package/dist/auth/idp/role-mapping.d.ts.map +1 -0
  143. package/dist/auth/idp/role-mapping.js +16 -0
  144. package/dist/auth/idp/role-mapping.js.map +1 -0
  145. package/dist/auth/idp/saml.d.ts +40 -0
  146. package/dist/auth/idp/saml.d.ts.map +1 -0
  147. package/dist/auth/idp/saml.js +117 -0
  148. package/dist/auth/idp/saml.js.map +1 -0
  149. package/dist/auth/idp/types.d.ts +23 -0
  150. package/dist/auth/idp/types.d.ts.map +1 -0
  151. package/dist/auth/idp/types.js +2 -0
  152. package/dist/auth/idp/types.js.map +1 -0
  153. package/dist/fleet/fleet-executor.d.ts +35 -0
  154. package/dist/fleet/fleet-executor.d.ts.map +1 -0
  155. package/dist/fleet/fleet-executor.js +228 -0
  156. package/dist/fleet/fleet-executor.js.map +1 -0
  157. package/dist/fleet/fleet-store.d.ts +13 -0
  158. package/dist/fleet/fleet-store.d.ts.map +1 -0
  159. package/dist/fleet/fleet-store.js +13 -0
  160. package/dist/fleet/fleet-store.js.map +1 -0
  161. package/dist/fleet/index.d.ts +5 -0
  162. package/dist/fleet/index.d.ts.map +1 -0
  163. package/dist/fleet/index.js +4 -0
  164. package/dist/fleet/index.js.map +1 -0
  165. package/dist/fleet/representative-selector.d.ts +15 -0
  166. package/dist/fleet/representative-selector.d.ts.map +1 -0
  167. package/dist/fleet/representative-selector.js +71 -0
  168. package/dist/fleet/representative-selector.js.map +1 -0
  169. package/dist/graph/graph-executor.d.ts +36 -0
  170. package/dist/graph/graph-executor.d.ts.map +1 -0
  171. package/dist/graph/graph-executor.js +348 -0
  172. package/dist/graph/graph-executor.js.map +1 -0
  173. package/dist/graph/graph-inference.d.ts +22 -0
  174. package/dist/graph/graph-inference.d.ts.map +1 -0
  175. package/dist/graph/graph-inference.js +149 -0
  176. package/dist/graph/graph-inference.js.map +1 -0
  177. package/dist/graph/graph-store.d.ts +12 -0
  178. package/dist/graph/graph-store.d.ts.map +1 -0
  179. package/dist/graph/graph-store.js +61 -0
  180. package/dist/graph/graph-store.js.map +1 -0
  181. package/dist/graph/index.d.ts +5 -0
  182. package/dist/graph/index.d.ts.map +1 -0
  183. package/dist/graph/index.js +4 -0
  184. package/dist/graph/index.js.map +1 -0
  185. package/dist/index.d.ts +2 -0
  186. package/dist/index.d.ts.map +1 -0
  187. package/dist/index.js +837 -0
  188. package/dist/index.js.map +1 -0
  189. package/dist/intake/index.d.ts +6 -0
  190. package/dist/intake/index.d.ts.map +1 -0
  191. package/dist/intake/index.js +5 -0
  192. package/dist/intake/index.js.map +1 -0
  193. package/dist/intake/intake-processor.d.ts +17 -0
  194. package/dist/intake/intake-processor.d.ts.map +1 -0
  195. package/dist/intake/intake-processor.js +99 -0
  196. package/dist/intake/intake-processor.js.map +1 -0
  197. package/dist/intake/intake-store.d.ts +7 -0
  198. package/dist/intake/intake-store.d.ts.map +1 -0
  199. package/dist/intake/intake-store.js +7 -0
  200. package/dist/intake/intake-store.js.map +1 -0
  201. package/dist/intake/registry-poller.d.ts +41 -0
  202. package/dist/intake/registry-poller.d.ts.map +1 -0
  203. package/dist/intake/registry-poller.js +202 -0
  204. package/dist/intake/registry-poller.js.map +1 -0
  205. package/dist/intake/webhook-handlers.d.ts +37 -0
  206. package/dist/intake/webhook-handlers.d.ts.map +1 -0
  207. package/dist/intake/webhook-handlers.js +268 -0
  208. package/dist/intake/webhook-handlers.js.map +1 -0
  209. package/dist/logger.d.ts +5 -0
  210. package/dist/logger.d.ts.map +1 -0
  211. package/dist/logger.js +15 -0
  212. package/dist/logger.js.map +1 -0
  213. package/dist/mcp/resources.d.ts +9 -0
  214. package/dist/mcp/resources.d.ts.map +1 -0
  215. package/dist/mcp/resources.js +72 -0
  216. package/dist/mcp/resources.js.map +1 -0
  217. package/dist/mcp/server.d.ts +15 -0
  218. package/dist/mcp/server.d.ts.map +1 -0
  219. package/dist/mcp/server.js +20 -0
  220. package/dist/mcp/server.js.map +1 -0
  221. package/dist/mcp/tools.d.ts +9 -0
  222. package/dist/mcp/tools.d.ts.map +1 -0
  223. package/dist/mcp/tools.js +88 -0
  224. package/dist/mcp/tools.js.map +1 -0
  225. package/dist/middleware/auth.d.ts +29 -0
  226. package/dist/middleware/auth.d.ts.map +1 -0
  227. package/dist/middleware/auth.js +76 -0
  228. package/dist/middleware/auth.js.map +1 -0
  229. package/dist/middleware/permissions.d.ts +13 -0
  230. package/dist/middleware/permissions.d.ts.map +1 -0
  231. package/dist/middleware/permissions.js +32 -0
  232. package/dist/middleware/permissions.js.map +1 -0
  233. package/dist/pattern-store.d.ts +104 -0
  234. package/dist/pattern-store.d.ts.map +1 -0
  235. package/dist/pattern-store.js +299 -0
  236. package/dist/pattern-store.js.map +1 -0
  237. package/package.json +54 -0
  238. package/src/agent/debrief-retention.ts +44 -0
  239. package/src/agent/envoy-client.ts +474 -0
  240. package/src/agent/envoy-registry.ts +384 -0
  241. package/src/agent/health-checker.ts +70 -0
  242. package/src/agent/mcp-client-manager.ts +131 -0
  243. package/src/agent/stale-deployment-detector.ts +79 -0
  244. package/src/agent/step-runner.ts +124 -0
  245. package/src/agent/synth-agent.ts +1567 -0
  246. package/src/api/agent.ts +1075 -0
  247. package/src/api/api-keys.ts +129 -0
  248. package/src/api/artifacts.ts +194 -0
  249. package/src/api/auth.ts +320 -0
  250. package/src/api/deployments.ts +1347 -0
  251. package/src/api/environments.ts +97 -0
  252. package/src/api/envoy-reports.ts +159 -0
  253. package/src/api/envoys.ts +237 -0
  254. package/src/api/fleet.ts +510 -0
  255. package/src/api/graph.ts +516 -0
  256. package/src/api/health.ts +311 -0
  257. package/src/api/idp-schemas.ts +19 -0
  258. package/src/api/idp.ts +735 -0
  259. package/src/api/intake.ts +537 -0
  260. package/src/api/partitions.ts +147 -0
  261. package/src/api/progress-event-store.ts +153 -0
  262. package/src/api/schemas.ts +376 -0
  263. package/src/api/security-boundaries.ts +54 -0
  264. package/src/api/settings.ts +118 -0
  265. package/src/api/system.ts +704 -0
  266. package/src/api/telemetry.ts +32 -0
  267. package/src/api/users.ts +210 -0
  268. package/src/archive-unpacker.ts +271 -0
  269. package/src/artifact-analyzer.ts +438 -0
  270. package/src/auth/idp/index.ts +8 -0
  271. package/src/auth/idp/ldap.ts +340 -0
  272. package/src/auth/idp/oidc.ts +117 -0
  273. package/src/auth/idp/role-mapping.ts +22 -0
  274. package/src/auth/idp/saml.ts +148 -0
  275. package/src/auth/idp/types.ts +22 -0
  276. package/src/fleet/fleet-executor.ts +309 -0
  277. package/src/fleet/fleet-store.ts +13 -0
  278. package/src/fleet/index.ts +4 -0
  279. package/src/fleet/representative-selector.ts +83 -0
  280. package/src/graph/graph-executor.ts +446 -0
  281. package/src/graph/graph-inference.ts +184 -0
  282. package/src/graph/graph-store.ts +75 -0
  283. package/src/graph/index.ts +4 -0
  284. package/src/index.ts +916 -0
  285. package/src/intake/index.ts +5 -0
  286. package/src/intake/intake-processor.ts +111 -0
  287. package/src/intake/intake-store.ts +7 -0
  288. package/src/intake/registry-poller.ts +230 -0
  289. package/src/intake/webhook-handlers.ts +328 -0
  290. package/src/logger.ts +19 -0
  291. package/src/mcp/resources.ts +98 -0
  292. package/src/mcp/server.ts +34 -0
  293. package/src/mcp/tools.ts +117 -0
  294. package/src/middleware/auth.ts +103 -0
  295. package/src/middleware/permissions.ts +35 -0
  296. package/src/pattern-store.ts +409 -0
  297. package/tests/agent-mode.test.ts +536 -0
  298. package/tests/api-handlers.test.ts +1245 -0
  299. package/tests/archive-unpacker.test.ts +179 -0
  300. package/tests/artifact-analyzer.test.ts +240 -0
  301. package/tests/auth-middleware.test.ts +189 -0
  302. package/tests/decision-diary.test.ts +957 -0
  303. package/tests/diary-reader.test.ts +782 -0
  304. package/tests/envoy-client.test.ts +342 -0
  305. package/tests/envoy-reports.test.ts +156 -0
  306. package/tests/mcp-tools.test.ts +213 -0
  307. package/tests/orchestration.test.ts +536 -0
  308. package/tests/partition-deletion.test.ts +143 -0
  309. package/tests/partition-isolation.test.ts +830 -0
  310. package/tests/pattern-store.test.ts +371 -0
  311. package/tests/rbac-enforcement.test.ts +409 -0
  312. package/tests/ssrf-validation.test.ts +56 -0
  313. package/tests/stale-deployment.test.ts +85 -0
  314. package/tests/step-runner.test.ts +308 -0
  315. package/tests/ui-journey.test.ts +330 -0
  316. package/tsconfig.json +11 -0
  317. package/vitest.config.ts +27 -0
@@ -0,0 +1,348 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Topological sort — Kahn's algorithm
3
+ // ---------------------------------------------------------------------------
4
+ export function topologicalSort(nodes, edges) {
5
+ const inDegree = new Map();
6
+ const adjacency = new Map();
7
+ for (const node of nodes) {
8
+ inDegree.set(node.id, 0);
9
+ adjacency.set(node.id, []);
10
+ }
11
+ for (const edge of edges) {
12
+ inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);
13
+ adjacency.get(edge.from)?.push(edge.to);
14
+ }
15
+ const queue = nodes
16
+ .filter((n) => (inDegree.get(n.id) ?? 0) === 0)
17
+ .map((n) => n.id);
18
+ const result = [];
19
+ while (queue.length > 0) {
20
+ const current = queue.shift();
21
+ result.push(current);
22
+ for (const neighbor of adjacency.get(current) ?? []) {
23
+ const deg = (inDegree.get(neighbor) ?? 1) - 1;
24
+ inDegree.set(neighbor, deg);
25
+ if (deg === 0)
26
+ queue.push(neighbor);
27
+ }
28
+ }
29
+ if (result.length !== nodes.length) {
30
+ throw new Error("Cycle detected in deployment graph — topological sort is impossible");
31
+ }
32
+ return result;
33
+ }
34
+ // ---------------------------------------------------------------------------
35
+ // Depth computation — group nodes by distance from roots for parallel exec
36
+ // ---------------------------------------------------------------------------
37
+ export function computeDepths(nodes, edges) {
38
+ const depths = new Map();
39
+ const inEdges = new Map(); // nodeId -> list of "from" nodeIds
40
+ for (const node of nodes) {
41
+ depths.set(node.id, 0);
42
+ inEdges.set(node.id, []);
43
+ }
44
+ for (const edge of edges) {
45
+ inEdges.get(edge.to)?.push(edge.from);
46
+ }
47
+ // BFS to compute max depth
48
+ let changed = true;
49
+ while (changed) {
50
+ changed = false;
51
+ for (const node of nodes) {
52
+ const parents = inEdges.get(node.id) ?? [];
53
+ const maxParent = Math.max(0, ...parents.map((p) => depths.get(p) ?? 0));
54
+ const newDepth = parents.length > 0 ? maxParent + 1 : 0;
55
+ if (newDepth > (depths.get(node.id) ?? 0)) {
56
+ depths.set(node.id, newDepth);
57
+ changed = true;
58
+ }
59
+ }
60
+ }
61
+ return depths;
62
+ }
63
+ // ---------------------------------------------------------------------------
64
+ // Downstream node computation — find all transitive dependents of a node
65
+ // ---------------------------------------------------------------------------
66
+ function getDownstreamNodeIds(nodeId, edges) {
67
+ const downstream = new Set();
68
+ const adjacency = new Map();
69
+ for (const edge of edges) {
70
+ if (!adjacency.has(edge.from))
71
+ adjacency.set(edge.from, []);
72
+ adjacency.get(edge.from).push(edge.to);
73
+ }
74
+ const queue = [nodeId];
75
+ while (queue.length > 0) {
76
+ const current = queue.shift();
77
+ for (const child of adjacency.get(current) ?? []) {
78
+ if (!downstream.has(child)) {
79
+ downstream.add(child);
80
+ queue.push(child);
81
+ }
82
+ }
83
+ }
84
+ return downstream;
85
+ }
86
+ // ---------------------------------------------------------------------------
87
+ // GraphExecutor — depth-based parallel execution
88
+ // ---------------------------------------------------------------------------
89
+ export class GraphExecutor {
90
+ envoyRegistry;
91
+ createClient;
92
+ constructor(envoyRegistry, createClient) {
93
+ this.envoyRegistry = envoyRegistry;
94
+ this.createClient = createClient;
95
+ }
96
+ /**
97
+ * Execute a deployment graph with depth-based parallelism.
98
+ * Nodes at the same depth run concurrently via Promise.allSettled().
99
+ * If a node fails, all its downstream dependents are skipped,
100
+ * but sibling nodes at the same depth continue executing.
101
+ */
102
+ async *execute(graph, plans, partitionVariables) {
103
+ // Validate topological order (detects cycles)
104
+ topologicalSort(graph.nodes, graph.edges);
105
+ const depths = computeDepths(graph.nodes, graph.edges);
106
+ const completed = new Map();
107
+ let completedCount = 0;
108
+ let failedCount = 0;
109
+ const skippedNodes = new Set();
110
+ // Group nodes by depth
111
+ const maxDepth = Math.max(0, ...Array.from(depths.values()));
112
+ const depthGroups = [];
113
+ for (let d = 0; d <= maxDepth; d++) {
114
+ depthGroups.push(graph.nodes.filter((n) => (depths.get(n.id) ?? 0) === d));
115
+ }
116
+ for (const group of depthGroups) {
117
+ // Filter out nodes that should be skipped (downstream of failed nodes)
118
+ const executableNodes = group.filter((n) => !skippedNodes.has(n.id));
119
+ if (executableNodes.length === 0)
120
+ continue;
121
+ // Collect events from parallel execution, then yield them after
122
+ const levelEvents = [];
123
+ const executingCount = executableNodes.length;
124
+ // Execute all nodes at this depth concurrently
125
+ const results = await Promise.allSettled(executableNodes.map(async (node) => {
126
+ // Resolve input bindings from completed upstream outputs
127
+ const resolvedVars = {};
128
+ // Merge partition variables first (input bindings override)
129
+ if (partitionVariables) {
130
+ Object.assign(resolvedVars, partitionVariables);
131
+ }
132
+ for (const binding of node.inputBindings ?? []) {
133
+ const upstreamOutputs = completed.get(binding.sourceNodeId);
134
+ if (upstreamOutputs?.[binding.sourceOutputName]) {
135
+ resolvedVars[binding.variable] =
136
+ upstreamOutputs[binding.sourceOutputName];
137
+ binding.resolvedValue =
138
+ upstreamOutputs[binding.sourceOutputName];
139
+ }
140
+ }
141
+ levelEvents.push({
142
+ type: "node-started",
143
+ nodeId: node.id,
144
+ graphId: graph.id,
145
+ progress: {
146
+ completed: completedCount,
147
+ total: graph.nodes.length,
148
+ executing: executingCount,
149
+ failed: failedCount,
150
+ },
151
+ });
152
+ const entry = this.envoyRegistry.get(node.envoyId);
153
+ if (!entry) {
154
+ throw new Error(`Envoy not found: ${node.envoyId}`);
155
+ }
156
+ const plan = plans.get(node.id);
157
+ if (!plan) {
158
+ throw new Error(`No plan found for node: ${node.id}`);
159
+ }
160
+ const client = this.createClient(entry.url, 60_000);
161
+ // Inject resolved variables into the plan's reasoning for traceability
162
+ const enrichedPlan = Object.keys(resolvedVars).length > 0
163
+ ? {
164
+ ...plan,
165
+ reasoning: `${plan.reasoning}\n\nResolved variables from upstream: ${JSON.stringify(resolvedVars)}`,
166
+ }
167
+ : plan;
168
+ const result = await client.executeApprovedPlan({
169
+ deploymentId: node.deploymentId ?? node.id,
170
+ plan: enrichedPlan,
171
+ rollbackPlan: {
172
+ steps: [],
173
+ reasoning: "No rollback plan provided",
174
+ },
175
+ artifactType: "graph-node",
176
+ artifactName: node.artifactId,
177
+ environmentId: "",
178
+ });
179
+ // Capture outputs from step results
180
+ const outputs = {};
181
+ for (const binding of node.outputBindings ?? []) {
182
+ if (binding.source === "plan_step_output" &&
183
+ binding.stepIndex != null &&
184
+ binding.outputKey) {
185
+ const stepResult = result.debriefEntries?.[binding.stepIndex];
186
+ if (stepResult) {
187
+ outputs[binding.name] = String(stepResult.context?.[binding.outputKey] ?? "");
188
+ }
189
+ }
190
+ else if (binding.source === "manual" && binding.value) {
191
+ outputs[binding.name] = binding.value;
192
+ }
193
+ }
194
+ return { nodeId: node.id, outputs };
195
+ }));
196
+ // Process results: update state and collect events
197
+ for (let i = 0; i < results.length; i++) {
198
+ const result = results[i];
199
+ const node = executableNodes[i];
200
+ if (result.status === "fulfilled") {
201
+ completed.set(result.value.nodeId, result.value.outputs);
202
+ completedCount++;
203
+ levelEvents.push({
204
+ type: "node-completed",
205
+ nodeId: node.id,
206
+ graphId: graph.id,
207
+ outputCapture: result.value.outputs,
208
+ progress: {
209
+ completed: completedCount,
210
+ total: graph.nodes.length,
211
+ executing: 0,
212
+ failed: failedCount,
213
+ },
214
+ });
215
+ }
216
+ else {
217
+ failedCount++;
218
+ const message = result.reason instanceof Error
219
+ ? result.reason.message
220
+ : String(result.reason);
221
+ levelEvents.push({
222
+ type: "node-failed",
223
+ nodeId: node.id,
224
+ graphId: graph.id,
225
+ error: message,
226
+ progress: {
227
+ completed: completedCount,
228
+ total: graph.nodes.length,
229
+ executing: 0,
230
+ failed: failedCount,
231
+ },
232
+ });
233
+ // Mark all downstream nodes as skipped
234
+ const downstream = getDownstreamNodeIds(node.id, graph.edges);
235
+ for (const downId of downstream) {
236
+ skippedNodes.add(downId);
237
+ }
238
+ }
239
+ }
240
+ // Yield all events from this depth level
241
+ for (const event of levelEvents) {
242
+ yield event;
243
+ }
244
+ // Yield skipped events for nodes in future depth levels that were just marked
245
+ for (const node of graph.nodes) {
246
+ if (skippedNodes.has(node.id) && !completed.has(node.id)) {
247
+ // Only yield skipped event once — remove from set tracking after yield
248
+ // We'll check depth to avoid yielding for nodes not yet reached
249
+ const nodeDepth = depths.get(node.id) ?? 0;
250
+ const currentDepth = depths.get(group[0].id) ?? 0;
251
+ if (nodeDepth === currentDepth + 1) {
252
+ // Don't yield yet — will be handled when we reach that depth level
253
+ }
254
+ }
255
+ }
256
+ }
257
+ // Yield skip events for any remaining skipped nodes
258
+ for (const nodeId of skippedNodes) {
259
+ if (!completed.has(nodeId)) {
260
+ yield {
261
+ type: "node-skipped",
262
+ nodeId,
263
+ graphId: graph.id,
264
+ error: "Skipped due to upstream failure",
265
+ progress: {
266
+ completed: completedCount,
267
+ total: graph.nodes.length,
268
+ executing: 0,
269
+ failed: failedCount,
270
+ },
271
+ };
272
+ }
273
+ }
274
+ if (failedCount === 0) {
275
+ yield {
276
+ type: "graph-completed",
277
+ graphId: graph.id,
278
+ progress: {
279
+ completed: completedCount,
280
+ total: graph.nodes.length,
281
+ executing: 0,
282
+ failed: 0,
283
+ },
284
+ };
285
+ }
286
+ else {
287
+ yield {
288
+ type: "graph-failed",
289
+ graphId: graph.id,
290
+ progress: {
291
+ completed: completedCount,
292
+ total: graph.nodes.length,
293
+ executing: 0,
294
+ failed: failedCount,
295
+ },
296
+ };
297
+ }
298
+ }
299
+ /**
300
+ * Rollback completed nodes in reverse topological order.
301
+ * Only rolls back nodes that completed successfully.
302
+ */
303
+ async *rollback(graph, rollbackPlans) {
304
+ const sorted = topologicalSort(graph.nodes, graph.edges).reverse();
305
+ let rolledBack = 0;
306
+ let rollbackFailed = 0;
307
+ for (const nodeId of sorted) {
308
+ const node = graph.nodes.find((n) => n.id === nodeId);
309
+ if (node.status !== "completed")
310
+ continue;
311
+ const plan = rollbackPlans.get(nodeId);
312
+ if (!plan)
313
+ continue;
314
+ const entry = this.envoyRegistry.get(node.envoyId);
315
+ if (!entry)
316
+ continue;
317
+ const client = this.createClient(entry.url, 60_000);
318
+ try {
319
+ await client.executeApprovedPlan({
320
+ deploymentId: node.deploymentId ?? nodeId,
321
+ plan,
322
+ rollbackPlan: {
323
+ steps: [],
324
+ reasoning: "Rollback of rollback not supported",
325
+ },
326
+ artifactType: "graph-node-rollback",
327
+ artifactName: node.artifactId,
328
+ environmentId: "",
329
+ });
330
+ rolledBack++;
331
+ }
332
+ catch {
333
+ rollbackFailed++;
334
+ }
335
+ }
336
+ yield {
337
+ type: rollbackFailed === 0 ? "graph-completed" : "graph-failed",
338
+ graphId: graph.id,
339
+ progress: {
340
+ completed: rolledBack,
341
+ total: graph.nodes.filter((n) => n.status === "completed").length,
342
+ executing: 0,
343
+ failed: rollbackFailed,
344
+ },
345
+ };
346
+ }
347
+ }
348
+ //# sourceMappingURL=graph-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-executor.js","sourceRoot":"","sources":["../../src/graph/graph-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { DeploymentGraph } from "@synth-deploy/core";
2
+ import type { LlmClient, IArtifactStore } from "@synth-deploy/core";
3
+ interface InferGraphParams {
4
+ artifactIds: string[];
5
+ envoyAssignments: Record<string, string>;
6
+ partitionId?: string;
7
+ graphName?: string;
8
+ }
9
+ export declare class GraphInferenceEngine {
10
+ private llm;
11
+ private artifactStore;
12
+ constructor(llm: LlmClient, artifactStore: IArtifactStore);
13
+ /**
14
+ * Infer a deployment graph from a set of artifacts and their envoy assignments.
15
+ * Uses the LLM to reason about ordering and data flow when available.
16
+ * Falls back to a flat graph (all parallel) when LLM is unavailable.
17
+ */
18
+ inferGraph(params: InferGraphParams): Promise<DeploymentGraph>;
19
+ private _inferEdgesWithLlm;
20
+ }
21
+ export {};
22
+ //# sourceMappingURL=graph-inference.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-inference.d.ts","sourceRoot":"","sources":["../../src/graph/graph-inference.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,SAAS,EAAa,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA0B/E,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyBD,qBAAa,oBAAoB;IAE7B,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,aAAa;gBADb,GAAG,EAAE,SAAS,EACd,aAAa,EAAE,cAAc;IAGvC;;;;OAIG;IACG,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;YAwCtD,kBAAkB;CAqEjC"}
@@ -0,0 +1,149 @@
1
+ import crypto from "node:crypto";
2
+ import { z } from "zod";
3
+ import { sanitizeForPrompt } from "@synth-deploy/core";
4
+ // ---------------------------------------------------------------------------
5
+ // Zod schema for LLM graph inference response validation
6
+ // ---------------------------------------------------------------------------
7
+ const InferredEdgeSchema = z.object({
8
+ from: z.string(),
9
+ to: z.string(),
10
+ type: z.enum(["depends_on", "data_flow"]),
11
+ dataBinding: z.object({
12
+ outputName: z.string(),
13
+ inputVariable: z.string(),
14
+ }).optional(),
15
+ });
16
+ const GraphInferenceResponseSchema = z.object({
17
+ edges: z.array(InferredEdgeSchema),
18
+ reasoning: z.string().optional(),
19
+ });
20
+ const GRAPH_INFERENCE_SYSTEM_PROMPT = `You are a deployment orchestration expert. Given a set of deployment artifacts with their analyses, determine the correct execution order and any data flow between them.
21
+
22
+ Your response must be valid JSON with this structure:
23
+ {
24
+ "edges": [
25
+ {
26
+ "from": "<artifactId that must deploy FIRST>",
27
+ "to": "<artifactId that depends on it>",
28
+ "type": "depends_on" | "data_flow",
29
+ "dataBinding": { "outputName": "<name>", "inputVariable": "<var>" } // only for data_flow edges
30
+ }
31
+ ],
32
+ "reasoning": "Plain-language explanation of why this ordering was chosen."
33
+ }
34
+
35
+ Rules:
36
+ - "from" deploys BEFORE "to"
37
+ - Only add edges where there is a genuine dependency (shared database, API dependency, config requirement)
38
+ - Use "data_flow" when one artifact produces a value (e.g., a URL, port, hostname) that another needs
39
+ - Use "depends_on" for ordering-only dependencies (e.g., database must be up before the app)
40
+ - Do not create cycles
41
+ - If artifacts are independent, return an empty edges array`;
42
+ export class GraphInferenceEngine {
43
+ llm;
44
+ artifactStore;
45
+ constructor(llm, artifactStore) {
46
+ this.llm = llm;
47
+ this.artifactStore = artifactStore;
48
+ }
49
+ /**
50
+ * Infer a deployment graph from a set of artifacts and their envoy assignments.
51
+ * Uses the LLM to reason about ordering and data flow when available.
52
+ * Falls back to a flat graph (all parallel) when LLM is unavailable.
53
+ */
54
+ async inferGraph(params) {
55
+ const { artifactIds, envoyAssignments, partitionId, graphName } = params;
56
+ const now = new Date();
57
+ // Build nodes from artifact/envoy assignments
58
+ const nodes = artifactIds.map((artifactId) => ({
59
+ id: crypto.randomUUID(),
60
+ artifactId,
61
+ envoyId: envoyAssignments[artifactId] ?? "",
62
+ outputBindings: [],
63
+ inputBindings: [],
64
+ status: "pending",
65
+ }));
66
+ // Map from artifactId to nodeId for edge resolution
67
+ const artifactToNodeId = new Map();
68
+ for (const node of nodes) {
69
+ artifactToNodeId.set(node.artifactId, node.id);
70
+ }
71
+ let edges = [];
72
+ // Attempt LLM inference
73
+ if (this.llm.isAvailable() && artifactIds.length > 1) {
74
+ edges = await this._inferEdgesWithLlm(artifactIds, artifactToNodeId);
75
+ }
76
+ return {
77
+ id: crypto.randomUUID(),
78
+ name: graphName ?? `Graph ${now.toISOString().slice(0, 19)}`,
79
+ partitionId,
80
+ nodes,
81
+ edges,
82
+ status: "draft",
83
+ approvalMode: "graph",
84
+ createdAt: now,
85
+ updatedAt: now,
86
+ };
87
+ }
88
+ async _inferEdgesWithLlm(artifactIds, artifactToNodeId) {
89
+ // Build context from artifact analyses
90
+ const artifactContext = [];
91
+ for (const artifactId of artifactIds) {
92
+ const artifact = this.artifactStore.get(artifactId);
93
+ if (!artifact) {
94
+ artifactContext.push(`- ${artifactId}: (artifact not found)`);
95
+ continue;
96
+ }
97
+ artifactContext.push(`- ID: ${artifactId}\n` +
98
+ ` Name: ${sanitizeForPrompt(artifact.name)}\n` +
99
+ ` Type: ${sanitizeForPrompt(artifact.type)}\n` +
100
+ ` Summary: ${sanitizeForPrompt(artifact.analysis.summary)}\n` +
101
+ ` Dependencies: ${sanitizeForPrompt(JSON.stringify(artifact.analysis.dependencies))}\n` +
102
+ ` Config expectations: ${sanitizeForPrompt(JSON.stringify(artifact.analysis.configurationExpectations))}\n` +
103
+ ` Deployment intent: ${sanitizeForPrompt(artifact.analysis.deploymentIntent ?? "unknown")}`);
104
+ }
105
+ const prompt = `Determine the deployment ordering for these artifacts:\n\n${artifactContext.join("\n\n")}\n\nArtifact IDs to use in edges: ${JSON.stringify(artifactIds)}`;
106
+ let result;
107
+ try {
108
+ result = await this.llm.reason({
109
+ prompt,
110
+ systemPrompt: GRAPH_INFERENCE_SYSTEM_PROMPT,
111
+ promptSummary: `Graph inference for ${artifactIds.length} artifacts`,
112
+ });
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ if (!result.ok)
118
+ return [];
119
+ try {
120
+ const jsonMatch = result.text.match(/\{[\s\S]*\}/);
121
+ if (!jsonMatch)
122
+ return [];
123
+ const raw = JSON.parse(jsonMatch[0]);
124
+ const parseResult = GraphInferenceResponseSchema.safeParse(raw);
125
+ if (!parseResult.success)
126
+ return [];
127
+ const parsed = parseResult.data;
128
+ // Convert artifact-level edges to node-level edges
129
+ const graphEdges = [];
130
+ for (const edge of parsed.edges) {
131
+ const fromNodeId = artifactToNodeId.get(edge.from);
132
+ const toNodeId = artifactToNodeId.get(edge.to);
133
+ if (!fromNodeId || !toNodeId)
134
+ continue;
135
+ graphEdges.push({
136
+ from: fromNodeId,
137
+ to: toNodeId,
138
+ type: edge.type === "data_flow" ? "data_flow" : "depends_on",
139
+ dataBinding: edge.dataBinding,
140
+ });
141
+ }
142
+ return graphEdges;
143
+ }
144
+ catch {
145
+ return [];
146
+ }
147
+ }
148
+ }
149
+ //# sourceMappingURL=graph-inference.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-inference.js","sourceRoot":"","sources":["../../src/graph/graph-inference.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { DeploymentGraph, DeploymentGraphStatus, DeploymentGraphNode } from "@synth-deploy/core";
2
+ export declare class DeploymentGraphStore {
3
+ private graphs;
4
+ create(graph: DeploymentGraph): DeploymentGraph;
5
+ getById(id: string): DeploymentGraph | undefined;
6
+ update(id: string, updates: Partial<Pick<DeploymentGraph, "name" | "nodes" | "edges" | "status" | "approvalMode" | "partitionId">>): DeploymentGraph | undefined;
7
+ updateStatus(id: string, status: DeploymentGraphStatus): DeploymentGraph | undefined;
8
+ updateNode(graphId: string, nodeId: string, updates: Partial<Pick<DeploymentGraphNode, "status" | "deploymentId">>): DeploymentGraphNode | undefined;
9
+ list(): DeploymentGraph[];
10
+ delete(id: string): boolean;
11
+ }
12
+ //# sourceMappingURL=graph-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-store.d.ts","sourceRoot":"","sources":["../../src/graph/graph-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAM5B,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAsC;IAEpD,MAAM,CAAC,KAAK,EAAE,eAAe,GAAG,eAAe;IAK/C,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIhD,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,cAAc,GAAG,aAAa,CAAC,CAAC,GAC9G,eAAe,GAAG,SAAS;IAe9B,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,eAAe,GAAG,SAAS;IASpF,UAAU,CACR,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,cAAc,CAAC,CAAC,GACrE,mBAAmB,GAAG,SAAS;IAclC,IAAI,IAAI,eAAe,EAAE;IAIzB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;CAG5B"}
@@ -0,0 +1,61 @@
1
+ // ---------------------------------------------------------------------------
2
+ // DeploymentGraphStore — in-memory store for deployment graphs
3
+ // ---------------------------------------------------------------------------
4
+ export class DeploymentGraphStore {
5
+ graphs = new Map();
6
+ create(graph) {
7
+ this.graphs.set(graph.id, graph);
8
+ return graph;
9
+ }
10
+ getById(id) {
11
+ return this.graphs.get(id);
12
+ }
13
+ update(id, updates) {
14
+ const existing = this.graphs.get(id);
15
+ if (!existing)
16
+ return undefined;
17
+ if (updates.name !== undefined)
18
+ existing.name = updates.name;
19
+ if (updates.nodes !== undefined)
20
+ existing.nodes = updates.nodes;
21
+ if (updates.edges !== undefined)
22
+ existing.edges = updates.edges;
23
+ if (updates.status !== undefined)
24
+ existing.status = updates.status;
25
+ if (updates.approvalMode !== undefined)
26
+ existing.approvalMode = updates.approvalMode;
27
+ if (updates.partitionId !== undefined)
28
+ existing.partitionId = updates.partitionId;
29
+ existing.updatedAt = new Date();
30
+ return existing;
31
+ }
32
+ updateStatus(id, status) {
33
+ const existing = this.graphs.get(id);
34
+ if (!existing)
35
+ return undefined;
36
+ existing.status = status;
37
+ existing.updatedAt = new Date();
38
+ return existing;
39
+ }
40
+ updateNode(graphId, nodeId, updates) {
41
+ const graph = this.graphs.get(graphId);
42
+ if (!graph)
43
+ return undefined;
44
+ const node = graph.nodes.find((n) => n.id === nodeId);
45
+ if (!node)
46
+ return undefined;
47
+ if (updates.status !== undefined)
48
+ node.status = updates.status;
49
+ if (updates.deploymentId !== undefined)
50
+ node.deploymentId = updates.deploymentId;
51
+ graph.updatedAt = new Date();
52
+ return node;
53
+ }
54
+ list() {
55
+ return Array.from(this.graphs.values());
56
+ }
57
+ delete(id) {
58
+ return this.graphs.delete(id);
59
+ }
60
+ }
61
+ //# sourceMappingURL=graph-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph-store.js","sourceRoot":"","sources":["../../src/graph/graph-store.ts"],"names":[],"mappings":"AAMA,8EAA8E;AAC9E,+DAA+D;AAC/D,8EAA8E;AAE9E,MAAM,OAAO,oBAAoB;IACvB,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAEpD,MAAM,CAAC,KAAsB;QAC3B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,EAAU;QAChB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CACJ,EAAU,EACV,OAA+G;QAE/G,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QAEhC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC7D,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAChE,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAChE,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAAE,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACnE,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;YAAE,QAAQ,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACrF,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS;YAAE,QAAQ,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAClF,QAAQ,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAEhC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,YAAY,CAAC,EAAU,EAAE,MAA6B;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ;YAAE,OAAO,SAAS,CAAC;QAEhC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;QACzB,QAAQ,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAChC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,UAAU,CACR,OAAe,EACf,MAAc,EACd,OAAsE;QAEtE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAE5B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC/D,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS;YAAE,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACjF,KAAK,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAE7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI;QACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,CAAC,EAAU;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export { GraphExecutor, topologicalSort } from "./graph-executor.js";
2
+ export type { GraphProgressEvent } from "./graph-executor.js";
3
+ export { GraphInferenceEngine } from "./graph-inference.js";
4
+ export { DeploymentGraphStore } from "./graph-store.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACrE,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GraphExecutor, topologicalSort } from "./graph-executor.js";
2
+ export { GraphInferenceEngine } from "./graph-inference.js";
3
+ export { DeploymentGraphStore } from "./graph-store.js";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/graph/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC"}