@alneas/eaos-server 0.0.0-stage → 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 (350) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/LICENSE +21 -0
  3. package/README.ja.md +39 -0
  4. package/README.md +40 -2
  5. package/dist/agentic/agent-jobs.d.ts +329 -0
  6. package/dist/agentic/agent-jobs.js +15 -0
  7. package/dist/agentic/agent-jobs.js.map +1 -0
  8. package/dist/agentic/agent-node.d.ts +40 -0
  9. package/dist/agentic/agent-node.js +7 -0
  10. package/dist/agentic/agent-node.js.map +1 -0
  11. package/dist/agentic/agent-runner.d.ts +33 -0
  12. package/dist/agentic/agent-runner.js +7 -0
  13. package/dist/agentic/agent-runner.js.map +1 -0
  14. package/dist/agentic/ai-broker.d.ts +169 -0
  15. package/dist/agentic/ai-broker.js +8 -0
  16. package/dist/agentic/ai-broker.js.map +1 -0
  17. package/dist/agentic/atomic-checkpointer.d.ts +137 -0
  18. package/dist/agentic/atomic-checkpointer.js +9 -0
  19. package/dist/agentic/atomic-checkpointer.js.map +1 -0
  20. package/dist/agentic/autonomous-worker.d.ts +95 -0
  21. package/dist/agentic/autonomous-worker.js +9 -0
  22. package/dist/agentic/autonomous-worker.js.map +1 -0
  23. package/dist/agentic/event-bridge.d.ts +344 -0
  24. package/dist/agentic/event-bridge.js +9 -0
  25. package/dist/agentic/event-bridge.js.map +1 -0
  26. package/dist/agentic/executor.d.ts +91 -0
  27. package/dist/agentic/executor.js +12 -0
  28. package/dist/agentic/executor.js.map +1 -0
  29. package/dist/agentic/graph-projection.d.ts +119 -0
  30. package/dist/agentic/graph-projection.js +7 -0
  31. package/dist/agentic/graph-projection.js.map +1 -0
  32. package/dist/agentic/graph.d.ts +524 -0
  33. package/dist/agentic/graph.js +7 -0
  34. package/dist/agentic/graph.js.map +1 -0
  35. package/dist/agentic/index.d.ts +24 -0
  36. package/dist/agentic/index.js +86 -0
  37. package/dist/agentic/index.js.map +1 -0
  38. package/dist/agentic/local-runner.d.ts +102 -0
  39. package/dist/agentic/local-runner.js +7 -0
  40. package/dist/agentic/local-runner.js.map +1 -0
  41. package/dist/agentic/remote-executor.d.ts +67 -0
  42. package/dist/agentic/remote-executor.js +8 -0
  43. package/dist/agentic/remote-executor.js.map +1 -0
  44. package/dist/agentic/types.d.ts +157 -0
  45. package/dist/agentic/types.js +7 -0
  46. package/dist/agentic/types.js.map +1 -0
  47. package/dist/agentic/workflow-catalog.d.ts +152 -0
  48. package/dist/agentic/workflow-catalog.js +7 -0
  49. package/dist/agentic/workflow-catalog.js.map +1 -0
  50. package/dist/agentic/workflow-compiler.d.ts +44 -0
  51. package/dist/agentic/workflow-compiler.js +8 -0
  52. package/dist/agentic/workflow-compiler.js.map +1 -0
  53. package/dist/agentic/workflow-coordinator.d.ts +170 -0
  54. package/dist/agentic/workflow-coordinator.js +8 -0
  55. package/dist/agentic/workflow-coordinator.js.map +1 -0
  56. package/dist/agentic/workflow-manager.d.ts +91 -0
  57. package/dist/agentic/workflow-manager.js +7 -0
  58. package/dist/agentic/workflow-manager.js.map +1 -0
  59. package/dist/agentic/workflow-registry.d.ts +334 -0
  60. package/dist/agentic/workflow-registry.js +7 -0
  61. package/dist/agentic/workflow-registry.js.map +1 -0
  62. package/dist/artifacts-CteHmCMI.d.ts +614 -0
  63. package/dist/auth-hooks/api-key.d.ts +75 -0
  64. package/dist/auth-hooks/api-key.js +7 -0
  65. package/dist/auth-hooks/api-key.js.map +1 -0
  66. package/dist/auth-hooks/index.d.ts +80 -0
  67. package/dist/auth-hooks/index.js +28 -0
  68. package/dist/auth-hooks/index.js.map +1 -0
  69. package/dist/browser-auth/account-memberships.d.ts +213 -0
  70. package/dist/browser-auth/account-memberships.js +13 -0
  71. package/dist/browser-auth/account-memberships.js.map +1 -0
  72. package/dist/browser-auth/index.d.ts +8 -0
  73. package/dist/browser-auth/index.js +59 -0
  74. package/dist/browser-auth/index.js.map +1 -0
  75. package/dist/browser-auth/kratos-session.d.ts +37 -0
  76. package/dist/browser-auth/kratos-session.js +7 -0
  77. package/dist/browser-auth/kratos-session.js.map +1 -0
  78. package/dist/browser-auth/platform-session.d.ts +120 -0
  79. package/dist/browser-auth/platform-session.js +7 -0
  80. package/dist/browser-auth/platform-session.js.map +1 -0
  81. package/dist/browser-auth/public-memberships.d.ts +22 -0
  82. package/dist/browser-auth/public-memberships.js +7 -0
  83. package/dist/browser-auth/public-memberships.js.map +1 -0
  84. package/dist/cache/index.d.ts +181 -0
  85. package/dist/cache/index.js +197 -0
  86. package/dist/cache/index.js.map +1 -0
  87. package/dist/chunk-32746UQZ.js +131 -0
  88. package/dist/chunk-32746UQZ.js.map +1 -0
  89. package/dist/chunk-3NLSWP2Y.js +223 -0
  90. package/dist/chunk-3NLSWP2Y.js.map +1 -0
  91. package/dist/chunk-3P4XTTQH.js +346 -0
  92. package/dist/chunk-3P4XTTQH.js.map +1 -0
  93. package/dist/chunk-3VITSHN3.js +15 -0
  94. package/dist/chunk-3VITSHN3.js.map +1 -0
  95. package/dist/chunk-46UWPEW2.js +226 -0
  96. package/dist/chunk-46UWPEW2.js.map +1 -0
  97. package/dist/chunk-4VORUFKR.js +45 -0
  98. package/dist/chunk-4VORUFKR.js.map +1 -0
  99. package/dist/chunk-55D4ERWO.js +1 -0
  100. package/dist/chunk-55D4ERWO.js.map +1 -0
  101. package/dist/chunk-5TBBZIND.js +18 -0
  102. package/dist/chunk-5TBBZIND.js.map +1 -0
  103. package/dist/chunk-5WOZWPZA.js +211 -0
  104. package/dist/chunk-5WOZWPZA.js.map +1 -0
  105. package/dist/chunk-6CBVZ6CT.js +168 -0
  106. package/dist/chunk-6CBVZ6CT.js.map +1 -0
  107. package/dist/chunk-6KV5CJBW.js +221 -0
  108. package/dist/chunk-6KV5CJBW.js.map +1 -0
  109. package/dist/chunk-6XZXYNJR.js +74 -0
  110. package/dist/chunk-6XZXYNJR.js.map +1 -0
  111. package/dist/chunk-753HWDSC.js +222 -0
  112. package/dist/chunk-753HWDSC.js.map +1 -0
  113. package/dist/chunk-7AHSS7SO.js +81 -0
  114. package/dist/chunk-7AHSS7SO.js.map +1 -0
  115. package/dist/chunk-7FTJN4SA.js +1 -0
  116. package/dist/chunk-7FTJN4SA.js.map +1 -0
  117. package/dist/chunk-AVDMLTPF.js +24 -0
  118. package/dist/chunk-AVDMLTPF.js.map +1 -0
  119. package/dist/chunk-BKAHUEIT.js +95 -0
  120. package/dist/chunk-BKAHUEIT.js.map +1 -0
  121. package/dist/chunk-CJ7OFEF7.js +134 -0
  122. package/dist/chunk-CJ7OFEF7.js.map +1 -0
  123. package/dist/chunk-DHQGNP4T.js +770 -0
  124. package/dist/chunk-DHQGNP4T.js.map +1 -0
  125. package/dist/chunk-EJKWDZIU.js +111 -0
  126. package/dist/chunk-EJKWDZIU.js.map +1 -0
  127. package/dist/chunk-F3O7CELI.js +23 -0
  128. package/dist/chunk-F3O7CELI.js.map +1 -0
  129. package/dist/chunk-FD6VC2NA.js +66 -0
  130. package/dist/chunk-FD6VC2NA.js.map +1 -0
  131. package/dist/chunk-FRRRWAHO.js +14 -0
  132. package/dist/chunk-FRRRWAHO.js.map +1 -0
  133. package/dist/chunk-HCKAGLLB.js +17 -0
  134. package/dist/chunk-HCKAGLLB.js.map +1 -0
  135. package/dist/chunk-HVC7FG6B.js +191 -0
  136. package/dist/chunk-HVC7FG6B.js.map +1 -0
  137. package/dist/chunk-HXFVOR7Z.js +496 -0
  138. package/dist/chunk-HXFVOR7Z.js.map +1 -0
  139. package/dist/chunk-IJWYS2PF.js +122 -0
  140. package/dist/chunk-IJWYS2PF.js.map +1 -0
  141. package/dist/chunk-INCHXAFK.js +1395 -0
  142. package/dist/chunk-INCHXAFK.js.map +1 -0
  143. package/dist/chunk-JT6BRGQM.js +1 -0
  144. package/dist/chunk-JT6BRGQM.js.map +1 -0
  145. package/dist/chunk-L6PMAEMB.js +115 -0
  146. package/dist/chunk-L6PMAEMB.js.map +1 -0
  147. package/dist/chunk-LOUGW6MU.js +126 -0
  148. package/dist/chunk-LOUGW6MU.js.map +1 -0
  149. package/dist/chunk-LYPZPE53.js +129 -0
  150. package/dist/chunk-LYPZPE53.js.map +1 -0
  151. package/dist/chunk-NNCCN7JP.js +186 -0
  152. package/dist/chunk-NNCCN7JP.js.map +1 -0
  153. package/dist/chunk-PBC3MZUL.js +212 -0
  154. package/dist/chunk-PBC3MZUL.js.map +1 -0
  155. package/dist/chunk-R4ADP2DC.js +20 -0
  156. package/dist/chunk-R4ADP2DC.js.map +1 -0
  157. package/dist/chunk-RHN4Y6VS.js +44 -0
  158. package/dist/chunk-RHN4Y6VS.js.map +1 -0
  159. package/dist/chunk-THYUY5ZZ.js +204 -0
  160. package/dist/chunk-THYUY5ZZ.js.map +1 -0
  161. package/dist/chunk-UGNTCOVR.js +28 -0
  162. package/dist/chunk-UGNTCOVR.js.map +1 -0
  163. package/dist/chunk-VC2PCK2S.js +31 -0
  164. package/dist/chunk-VC2PCK2S.js.map +1 -0
  165. package/dist/chunk-VF5YDZJC.js +305 -0
  166. package/dist/chunk-VF5YDZJC.js.map +1 -0
  167. package/dist/chunk-VISRDVTK.js +675 -0
  168. package/dist/chunk-VISRDVTK.js.map +1 -0
  169. package/dist/chunk-W6O3LVBY.js +102 -0
  170. package/dist/chunk-W6O3LVBY.js.map +1 -0
  171. package/dist/chunk-WFEAKJLR.js +47 -0
  172. package/dist/chunk-WFEAKJLR.js.map +1 -0
  173. package/dist/chunk-XIEY2OF4.js +67 -0
  174. package/dist/chunk-XIEY2OF4.js.map +1 -0
  175. package/dist/chunk-XITLHDG3.js +37 -0
  176. package/dist/chunk-XITLHDG3.js.map +1 -0
  177. package/dist/chunk-XMWPYZWZ.js +61 -0
  178. package/dist/chunk-XMWPYZWZ.js.map +1 -0
  179. package/dist/chunk-XUP6CNOM.js +34 -0
  180. package/dist/chunk-XUP6CNOM.js.map +1 -0
  181. package/dist/chunk-YABTQZDJ.js +25 -0
  182. package/dist/chunk-YABTQZDJ.js.map +1 -0
  183. package/dist/chunk-YMJ7BRKU.js +510 -0
  184. package/dist/chunk-YMJ7BRKU.js.map +1 -0
  185. package/dist/chunk-ZC3XWU7B.js +28 -0
  186. package/dist/chunk-ZC3XWU7B.js.map +1 -0
  187. package/dist/chunk-ZHMTD5KV.js +90 -0
  188. package/dist/chunk-ZHMTD5KV.js.map +1 -0
  189. package/dist/chunk-ZWZDLOE7.js +160 -0
  190. package/dist/chunk-ZWZDLOE7.js.map +1 -0
  191. package/dist/db-package/db/local-first-sqlite-adapter.d.ts +432 -0
  192. package/dist/db-package/db/local-first-sqlite-adapter.js +7 -0
  193. package/dist/db-package/db/local-first-sqlite-adapter.js.map +1 -0
  194. package/dist/db-package/index.d.ts +7 -0
  195. package/dist/db-package/index.js +16 -0
  196. package/dist/db-package/index.js.map +1 -0
  197. package/dist/db-package/migration/aggregator.d.ts +86 -0
  198. package/dist/db-package/migration/aggregator.js +7 -0
  199. package/dist/db-package/migration/aggregator.js.map +1 -0
  200. package/dist/db-package/migration/index.d.ts +3 -0
  201. package/dist/db-package/migration/index.js +8 -0
  202. package/dist/db-package/migration/index.js.map +1 -0
  203. package/dist/engine.d.ts +205 -0
  204. package/dist/engine.js +20 -0
  205. package/dist/engine.js.map +1 -0
  206. package/dist/entitlements/index.d.ts +313 -0
  207. package/dist/entitlements/index.js +23 -0
  208. package/dist/entitlements/index.js.map +1 -0
  209. package/dist/execution/index.d.ts +50 -0
  210. package/dist/execution/index.js +57 -0
  211. package/dist/execution/index.js.map +1 -0
  212. package/dist/extensions/index.d.ts +172 -0
  213. package/dist/extensions/index.js +95 -0
  214. package/dist/extensions/index.js.map +1 -0
  215. package/dist/health/index.d.ts +35 -0
  216. package/dist/health/index.js +7 -0
  217. package/dist/health/index.js.map +1 -0
  218. package/dist/index.d.ts +39 -0
  219. package/dist/index.js +160 -0
  220. package/dist/index.js.map +1 -0
  221. package/dist/lifecycle/index.d.ts +133 -0
  222. package/dist/lifecycle/index.js +13 -0
  223. package/dist/lifecycle/index.js.map +1 -0
  224. package/dist/lifecycle-engine/backend-migration.d.ts +2 -0
  225. package/dist/lifecycle-engine/backend-migration.js +11 -0
  226. package/dist/lifecycle-engine/backend-migration.js.map +1 -0
  227. package/dist/lifecycle-engine/baseline.d.ts +2 -0
  228. package/dist/lifecycle-engine/baseline.js +9 -0
  229. package/dist/lifecycle-engine/baseline.js.map +1 -0
  230. package/dist/lifecycle-engine/index.d.ts +1497 -0
  231. package/dist/lifecycle-engine/index.js +41 -0
  232. package/dist/lifecycle-engine/index.js.map +1 -0
  233. package/dist/lifecycle-engine/platform/artifacts.d.ts +4 -0
  234. package/dist/lifecycle-engine/platform/artifacts.js +7 -0
  235. package/dist/lifecycle-engine/platform/artifacts.js.map +1 -0
  236. package/dist/lifecycle-engine/platform/control-plane.d.ts +12 -0
  237. package/dist/lifecycle-engine/platform/control-plane.js +2 -0
  238. package/dist/lifecycle-engine/platform/control-plane.js.map +1 -0
  239. package/dist/lifecycle-engine/platform/database-router.d.ts +118 -0
  240. package/dist/lifecycle-engine/platform/database-router.js +7 -0
  241. package/dist/lifecycle-engine/platform/database-router.js.map +1 -0
  242. package/dist/lifecycle-engine/platform/deployment-placements.d.ts +464 -0
  243. package/dist/lifecycle-engine/platform/deployment-placements.js +16 -0
  244. package/dist/lifecycle-engine/platform/deployment-placements.js.map +1 -0
  245. package/dist/lifecycle-engine/platform/deployment.d.ts +4 -0
  246. package/dist/lifecycle-engine/platform/deployment.js +17 -0
  247. package/dist/lifecycle-engine/platform/deployment.js.map +1 -0
  248. package/dist/lifecycle-engine/platform/index.d.ts +737 -0
  249. package/dist/lifecycle-engine/platform/index.js +60 -0
  250. package/dist/lifecycle-engine/platform/index.js.map +1 -0
  251. package/dist/lifecycle-engine/platform/runtime.d.ts +80 -0
  252. package/dist/lifecycle-engine/platform/runtime.js +11 -0
  253. package/dist/lifecycle-engine/platform/runtime.js.map +1 -0
  254. package/dist/lifecycle-engine/platform/site-publication.d.ts +102 -0
  255. package/dist/lifecycle-engine/platform/site-publication.js +7 -0
  256. package/dist/lifecycle-engine/platform/site-publication.js.map +1 -0
  257. package/dist/lifecycle-engine/platform/user-directory.d.ts +139 -0
  258. package/dist/lifecycle-engine/platform/user-directory.js +13 -0
  259. package/dist/lifecycle-engine/platform/user-directory.js.map +1 -0
  260. package/dist/mcp.d.ts +92 -0
  261. package/dist/mcp.js +10 -0
  262. package/dist/mcp.js.map +1 -0
  263. package/dist/middleware/auth.d.ts +118 -0
  264. package/dist/middleware/auth.js +7 -0
  265. package/dist/middleware/auth.js.map +1 -0
  266. package/dist/middleware/error-handler.d.ts +35 -0
  267. package/dist/middleware/error-handler.js +7 -0
  268. package/dist/middleware/error-handler.js.map +1 -0
  269. package/dist/middleware/module-guard.d.ts +33 -0
  270. package/dist/middleware/module-guard.js +7 -0
  271. package/dist/middleware/module-guard.js.map +1 -0
  272. package/dist/platform-admin/index.d.ts +37 -0
  273. package/dist/platform-admin/index.js +11 -0
  274. package/dist/platform-admin/index.js.map +1 -0
  275. package/dist/platform-admin/store.d.ts +346 -0
  276. package/dist/platform-admin/store.js +7 -0
  277. package/dist/platform-admin/store.js.map +1 -0
  278. package/dist/plugin-data/annotations.d.ts +6 -0
  279. package/dist/plugin-data/annotations.js +12 -0
  280. package/dist/plugin-data/annotations.js.map +1 -0
  281. package/dist/plugin-data/atomic-context.d.ts +41 -0
  282. package/dist/plugin-data/atomic-context.js +9 -0
  283. package/dist/plugin-data/atomic-context.js.map +1 -0
  284. package/dist/plugin-data/atomic.d.ts +6 -0
  285. package/dist/plugin-data/atomic.js +26 -0
  286. package/dist/plugin-data/atomic.js.map +1 -0
  287. package/dist/plugin-data/audit.d.ts +6 -0
  288. package/dist/plugin-data/audit.js +12 -0
  289. package/dist/plugin-data/audit.js.map +1 -0
  290. package/dist/plugin-data/commands.d.ts +6 -0
  291. package/dist/plugin-data/commands.js +8 -0
  292. package/dist/plugin-data/commands.js.map +1 -0
  293. package/dist/plugin-data/composite.d.ts +6 -0
  294. package/dist/plugin-data/composite.js +8 -0
  295. package/dist/plugin-data/composite.js.map +1 -0
  296. package/dist/plugin-data/delivery.d.ts +6 -0
  297. package/dist/plugin-data/delivery.js +16 -0
  298. package/dist/plugin-data/delivery.js.map +1 -0
  299. package/dist/plugin-data/index.d.ts +2798 -0
  300. package/dist/plugin-data/index.js +102 -0
  301. package/dist/plugin-data/index.js.map +1 -0
  302. package/dist/plugin-data/json-documents.d.ts +6 -0
  303. package/dist/plugin-data/json-documents.js +16 -0
  304. package/dist/plugin-data/json-documents.js.map +1 -0
  305. package/dist/plugin-data/outbox.d.ts +6 -0
  306. package/dist/plugin-data/outbox.js +16 -0
  307. package/dist/plugin-data/outbox.js.map +1 -0
  308. package/dist/plugin-data/scoped-records.d.ts +6 -0
  309. package/dist/plugin-data/scoped-records.js +10 -0
  310. package/dist/plugin-data/scoped-records.js.map +1 -0
  311. package/dist/plugin-sdk.d.ts +41 -0
  312. package/dist/plugin-sdk.js +10 -0
  313. package/dist/plugin-sdk.js.map +1 -0
  314. package/dist/sql-lifecycle/index.d.ts +138 -0
  315. package/dist/sql-lifecycle/index.js +167 -0
  316. package/dist/sql-lifecycle/index.js.map +1 -0
  317. package/dist/storage/index.d.ts +2 -0
  318. package/dist/storage/index.js +13 -0
  319. package/dist/storage/index.js.map +1 -0
  320. package/dist/storage/s3-compatible.d.ts +139 -0
  321. package/dist/storage/s3-compatible.js +11 -0
  322. package/dist/storage/s3-compatible.js.map +1 -0
  323. package/dist/tenant.d.ts +108 -0
  324. package/dist/tenant.js +9 -0
  325. package/dist/tenant.js.map +1 -0
  326. package/dist/workspace-context.d.ts +119 -0
  327. package/dist/workspace-context.js +9 -0
  328. package/dist/workspace-context.js.map +1 -0
  329. package/docs/api.md +29753 -0
  330. package/docs/db/README.md +49 -0
  331. package/docs/db/docs/api.md +1613 -0
  332. package/docs/db/docs/guide.md +47 -0
  333. package/docs/entitlements.md +60 -0
  334. package/docs/guide.md +48 -0
  335. package/docs/index.md +53 -0
  336. package/docs/ja/db/README.md +46 -0
  337. package/docs/ja/db/docs/guide.md +53 -0
  338. package/docs/ja/guide.md +46 -0
  339. package/docs/ja/lifecycle/README.md +46 -0
  340. package/docs/ja/lifecycle/docs/guide.md +45 -0
  341. package/docs/ja/storage/README.md +46 -0
  342. package/docs/ja/storage/docs/guide.md +43 -0
  343. package/docs/lifecycle/README.md +49 -0
  344. package/docs/lifecycle/docs/api.md +3770 -0
  345. package/docs/lifecycle/docs/baseline.md +50 -0
  346. package/docs/lifecycle/docs/guide.md +47 -0
  347. package/docs/storage/README.md +49 -0
  348. package/docs/storage/docs/api.md +470 -0
  349. package/docs/storage/docs/guide.md +47 -0
  350. package/package.json +345 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/platform-admin/index.ts"],"sourcesContent":["import { Hono } from 'hono'\nimport { assertBackendMigrationCutover, planBackendMigration } from '@alneas/eaos-server/lifecycle-engine'\nimport type { PlatformAdminAction, PlatformAdminAuditEvent, PlatformAdminAuthorization, PlatformAdminPrincipal, PlatformControlStore, PlatformPlacementExecutor } from '@alneas/eaos-server/platform'\nexport type { PlatformPlacementExecutor } from '@alneas/eaos-server/platform'\nexport { LifecyclePlatformControlStore } from './store'\n\n/**\n * Trusted control-plane authorization, persistence, audit, and optional migration execution dependencies.\n * @see createPlatformAdminRouter.\n */\nexport interface PlatformAdminRouterOptions extends PlatformAdminAuthorization {\n /** Shared authoritative tenant/backend/placement store. */\n store: PlatformControlStore\n /** Awaited on denied and successful mutations; receives operator/action/outcome/time, without request credentials. Audit failure may occur after persistence. */\n audit: (event: Readonly<PlatformAdminAuditEvent>) => Promise<void>\n /** Optional host migration executor; absent returns 501 for execute requests. Provisioning, credentials, and SQL remain host-owned. */\n placementExecutor?: PlatformPlacementExecutor\n /** Clock for audit/plan timestamps; defaults to fresh Date. */\n now?: () => Date\n}\n\ntype JsonObject = Record<string, unknown>\n\nfunction object(value: unknown): JsonObject {\n if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('Request body must be an object')\n return value as JsonObject\n}\n\nfunction string(value: unknown, name: string, max = 256): string {\n if (typeof value !== 'string' || !value.trim() || value.length > max) throw new Error(`Invalid ${name}`)\n return value\n}\n\nfunction stringArray(value: unknown, name: string, max = 128): string[] {\n if (!Array.isArray(value) || value.length === 0 || value.length > max || value.some(item => typeof item !== 'string' || !item.trim())) throw new Error(`Invalid ${name}`)\n return [...value]\n}\n\nasync function body(c: { req: { json: <T>() => Promise<T> } }): Promise<JsonObject> {\n return object(await c.req.json().catch(() => null))\n}\n\nfunction publicBackend(backend: Awaited<ReturnType<PlatformControlStore['listBackends']>>[number]) {\n return {\n id: backend.id,\n databaseId: backend.databaseId,\n dialect: backend.dialect,\n mode: backend.mode,\n ...(backend.tenantId === undefined ? {} : { tenantId: backend.tenantId }),\n ...(backend.label === undefined ? {} : { label: backend.label }),\n ...(backend.provider === undefined ? {} : { provider: backend.provider }),\n ...(backend.capabilities === undefined ? {} : { capabilities: backend.capabilities }),\n }\n}\n\n/**\n * Platform-wide control routes. They operate on host-registered opaque\n * backends; provisioning, credentials, SQL and tenant membership remain host-owned.\n * @param options - Shared store, live platform-admin authorization, audit sink, optional placement executor, and clock.\n * @returns A Hono router for tenants, backend discovery, placement planning/execution/status/rollback/reconciliation. Unauthenticated/unauthorized requests return 401/403.\n * @throws Synchronously for missing store/auth/audit dependencies. Request-time reads/auth/audit can fail through Hono error handling; mutation failures are generally 400 or migration conflict 409 data.\n * @remarks Every operation requires principal.isPlatformAdmin === true plus host authorize approval. Plan/rollback endpoints persist reviewed plans rather than directly changing routing. Execution verifies reports before cutover and records reconciling state on uncertain failures; host executor effects are not rolled back automatically. Reads expose opaque public backend metadata without credentials/SQL. A failed audit can follow a completed mutation, so errors do not prove no change occurred. No listener, deployment, or scheduler is started.\n * @example\n * ```typescript\n * import { createPlatformAdminRouter, type PlatformAdminRouterOptions } from \"@alneas/eaos-server/platform-admin\";\n * export function controlRoutes(options: PlatformAdminRouterOptions) { return createPlatformAdminRouter(options); }\n * ```\n */\nexport function createPlatformAdminRouter(options: PlatformAdminRouterOptions): Hono {\n if (!options?.store || !options.resolvePrincipal || !options.authorize || !options.audit) throw new Error('Platform admin router dependencies are required')\n const app = new Hono()\n const now = options.now ?? (() => new Date())\n\n const access = async (request: Request, action: PlatformAdminAction, tenantId?: string): Promise<{ principal: PlatformAdminPrincipal } | Response> => {\n const principal = await options.resolvePrincipal(request)\n if (!principal) return new Response(JSON.stringify({ error: 'Authentication required' }), { status: 401, headers: { 'content-type': 'application/json' } })\n const allowed = principal.isPlatformAdmin === true && await options.authorize(principal, action, tenantId)\n if (!allowed) {\n await options.audit({ action, actorId: principal.userId, ...(tenantId ? { tenantId } : {}), outcome: 'denied', occurredAt: now().toISOString() })\n return new Response(JSON.stringify({ error: 'Platform administrator access required' }), { status: 403, headers: { 'content-type': 'application/json' } })\n }\n return { principal }\n }\n\n const failure = (error: unknown, status = 400) => new Response(JSON.stringify({ error: error instanceof Error ? error.message : 'Request failed' }), { status, headers: { 'content-type': 'application/json' } })\n\n app.get('/tenants', async c => {\n const authorized = await access(c.req.raw, 'tenant:list')\n if (authorized instanceof Response) return authorized\n return c.json({ tenants: await options.store.listTenants() })\n })\n\n app.post('/tenants', async c => {\n const authorized = await access(c.req.raw, 'tenant:create')\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const tenant = await options.store.createTenant({ id: string(input.id, 'tenant id'), name: string(input.name, 'tenant name'), domains: stringArray(input.domains, 'domains'), backendId: string(input.backendId, 'initial backend id') })\n await options.audit({ action: 'tenant:create', actorId: authorized.principal.userId, tenantId: tenant.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ tenant }, 201)\n } catch (error) {\n return failure(error)\n }\n })\n\n app.patch('/tenants/:tenantId', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'tenant:update', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const patch = {\n ...(input.name === undefined ? {} : { name: string(input.name, 'tenant name') }),\n ...(input.active === undefined ? {} : { active: input.active === true }),\n ...(input.domains === undefined ? {} : { domains: stringArray(input.domains, 'domains') }),\n }\n if (!Object.keys(patch).length) throw new Error('Tenant patch is empty')\n const tenant = await options.store.updateTenant(tenantId, patch)\n await options.audit({ action: 'tenant:update', actorId: authorized.principal.userId, tenantId, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ tenant })\n } catch (error) {\n return failure(error)\n }\n })\n\n app.get('/backends', async c => {\n const authorized = await access(c.req.raw, 'backend:list')\n if (authorized instanceof Response) return authorized\n return c.json({ backends: (await options.store.listBackends()).map(publicBackend) })\n })\n\n app.get('/tenants/:tenantId/placement', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:read', tenantId)\n if (authorized instanceof Response) return authorized\n const placement = await options.store.getTenantPlacement(tenantId)\n if (!placement) return failure(new Error('Tenant placement not found'), 404)\n return c.json({ placement: { ...placement, backend: publicBackend(placement.backend) } })\n })\n\n app.post('/tenants/:tenantId/placement/plan', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:plan', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const targetBackendId = string(input.targetBackendId, 'target backend id')\n const pluginIds = stringArray(input.pluginIds, 'pluginIds')\n const reason = string(input.reason, 'migration reason', 1024)\n const current = await options.store.getTenantPlacement(tenantId)\n if (!current) return failure(new Error('Tenant placement not found'), 404)\n const target = await options.store.getBackend(targetBackendId)\n if (!target) return failure(new Error('Target backend not found'), 404)\n const plan = planBackendMigration({\n migrationId: `platform-${crypto.randomUUID()}`,\n source: current.backend,\n target,\n scope: { kind: 'tenants', tenantIds: [tenantId] },\n pluginIds,\n requestedAt: now().toISOString(),\n reason,\n })\n await options.store.saveMigrationPlan(plan)\n await options.audit({ action: 'placement:plan', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ plan }, 201)\n } catch (error) {\n return failure(error)\n }\n })\n\n app.post('/tenants/:tenantId/placement/execute', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:cutover', tenantId)\n if (authorized instanceof Response) return authorized\n if (!options.placementExecutor) return failure(new Error('Placement execution is not configured'), 501)\n let migrationId = ''\n let executionId = ''\n try {\n const input = await body(c)\n migrationId = string(input.migrationId, 'migration id')\n executionId = string(input.executionId, 'execution id')\n const plan = await options.store.getMigrationPlan(migrationId)\n if (!plan) return failure(new Error('Migration plan not found'), 404)\n if (plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan tenant mismatch'), 409)\n const previous = await options.store.getMigrationStatus(migrationId)\n const current = await options.store.getTenantPlacement(tenantId)\n if (previous?.status === 'cutover') return c.json({ status: previous.status, cutover: previous.cutover, placement: current ? { ...current, backend: publicBackend(current.backend) } : null })\n if (!current || current.backend.id !== plan.request.source.id || current.backend.databaseId !== plan.request.source.databaseId) return failure(new Error('Migration plan is stale'), 409)\n const previousStatus = previous?.status\n const previousExecutionId = previous?.executionId\n const record = await options.store.beginMigrationExecution({ tenantId, migrationId, executionId })\n if (record.status === 'cutover') return c.json({ status: record.status, cutover: record.cutover, placement: { ...current, backend: publicBackend(current.backend) } })\n if (previousStatus === 'running' && previousExecutionId === executionId) return c.json({ status: 'running', migrationId }, 202)\n if (record.status === 'running') {\n const result = await options.placementExecutor.execute(plan)\n const cutover = assertBackendMigrationCutover(plan, result.verification, result.cutover)\n await options.store.recordMigrationVerification({ tenantId, plan, executionId, verification: result.verification, cutover })\n } else if (record.status !== 'verified' || !record.cutover) {\n return failure(new Error('Migration is not executable'), 409)\n }\n const verified = await options.store.getMigrationStatus(migrationId)\n if (!verified?.cutover) return failure(new Error('Migration verification is missing'), 409)\n const cutover = verified.cutover\n const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover })\n await options.audit({ action: 'placement:cutover', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ cutover, placement: { ...placement, backend: publicBackend(placement.backend) } })\n } catch (error) {\n if (migrationId) await options.store.markMigrationFailure({ migrationId, executionId: executionId || undefined, status: 'reconciling', message: error instanceof Error ? error.message : 'Migration execution failed' }).catch(() => undefined)\n return failure(error, 409)\n }\n })\n\n app.get('/tenants/:tenantId/placement/migrations/:migrationId', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const migrationId = string(c.req.param('migrationId'), 'migration id')\n const authorized = await access(c.req.raw, 'placement:read', tenantId)\n if (authorized instanceof Response) return authorized\n const plan = await options.store.getMigrationPlan(migrationId)\n const migration = await options.store.getMigrationStatus(migrationId)\n if (!plan || !migration) return failure(new Error('Migration not found'), 404)\n if (plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan tenant mismatch'), 409)\n return c.json({ migration: { ...migration, plan } })\n })\n\n app.post('/tenants/:tenantId/placement/rollback', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:rollback', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const migrationId = string(input.migrationId, 'migration id')\n const reason = string(input.reason, 'rollback reason', 1024)\n const plan = await options.store.createRollbackPlan({ tenantId, migrationId, reason, requestedAt: now().toISOString() })\n await options.audit({ action: 'placement:rollback', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ plan }, 201)\n } catch (error) {\n return failure(error, 409)\n }\n })\n\n app.post('/tenants/:tenantId/placement/reconcile', async c => {\n const tenantId = string(c.req.param('tenantId'), 'tenant id')\n const authorized = await access(c.req.raw, 'placement:reconcile', tenantId)\n if (authorized instanceof Response) return authorized\n try {\n const input = await body(c)\n const migrationId = string(input.migrationId, 'migration id')\n const action = string(input.action, 'reconciliation action') as 'retry' | 'mark-failed' | 'mark-reconciling' | 'commit-verified'\n const note = string(input.note, 'reconciliation note', 2048)\n const plan = await options.store.getMigrationPlan(migrationId)\n if (!plan || plan.request.scope.kind !== 'tenants' || !plan.request.scope.tenantIds.includes(tenantId)) return failure(new Error('Migration plan not found'), 404)\n if (action === 'commit-verified') {\n const migration = await options.store.getMigrationStatus(migrationId)\n if (!migration?.verification || !migration.cutover) return failure(new Error('Verified migration data is missing'), 409)\n const placement = await options.store.recordTenantPlacement({ tenantId, plan, cutover: migration.cutover })\n await options.audit({ action: 'placement:reconcile', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ migration: await options.store.getMigrationStatus(migrationId), placement: { ...placement, backend: publicBackend(placement.backend) } })\n }\n const migration = await options.store.reconcileMigration({ migrationId, action, note })\n await options.audit({ action: 'placement:reconcile', actorId: authorized.principal.userId, tenantId, sourceBackendId: plan.request.source.id, targetBackendId: plan.request.target.id, migrationId: plan.id, outcome: 'allowed', occurredAt: now().toISOString() })\n return c.json({ migration })\n } catch (error) {\n return failure(error, 409)\n }\n })\n\n return app\n}\n"],"mappings":"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","names":["cutover","migration"]}
@@ -0,0 +1,81 @@
1
+ // src/agentic/workflow-catalog.ts
2
+ var WorkflowNodeCatalog = class {
3
+ registrations = /* @__PURE__ */ new Map();
4
+ /**
5
+ * Registers a unique node type and returns a safe unregister callback.
6
+ * @param registration - Descriptor with nonblank label and type matching lowercase letters/digits/dot/underscore/hyphen up to 128 characters, plus a handler resolver.
7
+ * @returns A no-argument callback returning no value; it removes only this registration and does not remove a later replacement.
8
+ * @throws Invalid type/label, duplicate type, missing resolver, or descriptor clone failure.
9
+ * @remarks The descriptor is cloned and its label trimmed; resolver function references are retained.
10
+ * @example
11
+ * ```typescript
12
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
13
+ * const catalog = new WorkflowNodeCatalog();
14
+ * const dispose = catalog.register({ descriptor: { type: "example.task", label: "Example", kind: "task" }, resolve: () => async () => ({}) });
15
+ * dispose();
16
+ * ```
17
+ */
18
+ register(registration) {
19
+ const type = registration?.descriptor?.type;
20
+ if (!type || !/^[a-z0-9][a-z0-9._-]{0,127}$/.test(type)) throw new Error("Invalid workflow node catalog type");
21
+ if (this.registrations.has(type)) throw new Error(`Workflow node type '${type}' is already registered`);
22
+ if (!registration.resolve || typeof registration.resolve !== "function") throw new Error(`Workflow node '${type}' must provide a resolver`);
23
+ const descriptor = structuredClone({ ...registration.descriptor, type, label: registration.descriptor.label?.trim() });
24
+ if (!descriptor.label) throw new Error(`Workflow node '${type}' must provide a label`);
25
+ this.registrations.set(type, { ...registration, descriptor });
26
+ return () => {
27
+ if (this.registrations.get(type)?.descriptor === descriptor) this.registrations.delete(type);
28
+ };
29
+ }
30
+ /**
31
+ * Reads a registered resolver by exact node type.
32
+ * @param type - Case-sensitive catalog type identifier.
33
+ * @returns The retained registration, or undefined; mutation is not isolated by cloning.
34
+ * @example
35
+ * ```typescript
36
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
37
+ * console.log(new WorkflowNodeCatalog().get("example.task")); // undefined
38
+ * ```
39
+ */
40
+ get(type) {
41
+ return this.registrations.get(type);
42
+ }
43
+ /**
44
+ * Reads a registered resolver or fails if the type is unavailable.
45
+ * @param type - Exact catalog node type required by a workflow definition.
46
+ * @returns The retained registration.
47
+ * @throws If no registration exists for type.
48
+ * @example
49
+ * ```typescript
50
+ * import { WorkflowNodeCatalog, type WorkflowNodeRegistration } from "@alneas/eaos-server/agentic/workflow-catalog";
51
+ * export function registered(registration: WorkflowNodeRegistration) {
52
+ * const catalog = new WorkflowNodeCatalog();
53
+ * catalog.register(registration);
54
+ * return catalog.require(registration.descriptor.type);
55
+ * }
56
+ * ```
57
+ */
58
+ require(type) {
59
+ const registration = this.get(type);
60
+ if (!registration) throw new Error(`Workflow node type '${type}' is not registered`);
61
+ return registration;
62
+ }
63
+ /**
64
+ * Lists cloned descriptors in registration insertion order.
65
+ * @returns A new descriptor array, empty for an empty catalog; caller changes do not affect stored descriptors.
66
+ * @throws If descriptors were externally mutated to contain uncloneable values.
67
+ * @example
68
+ * ```typescript
69
+ * import { WorkflowNodeCatalog } from "@alneas/eaos-server/agentic/workflow-catalog";
70
+ * console.log(new WorkflowNodeCatalog().list()); // []
71
+ * ```
72
+ */
73
+ list() {
74
+ return structuredClone([...this.registrations.values()].map((item) => item.descriptor));
75
+ }
76
+ };
77
+
78
+ export {
79
+ WorkflowNodeCatalog
80
+ };
81
+ //# sourceMappingURL=chunk-7AHSS7SO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/workflow-catalog.ts"],"sourcesContent":["import type { WorkflowDefinition, WorkflowDefinitionNode, WorkflowDefinitionNodeKind, WorkflowToolScopeDefinition } from '@alneas/eaos-core'\nimport type { AgentGraphState, GraphNodeHandler, GraphSubgraph } from './graph'\n\n/**\n * Serializable node metadata exposed to workflow editors by {@link WorkflowNodeCatalog}.\n */\nexport interface WorkflowNodeDescriptor {\n /** Unique lowercase catalog type identifier, at most 128 characters. */\n type: string\n /** Editor label, trimmed and required during registration. */\n label: string\n /** Optional human-readable editor description. */\n description?: string\n /** Optional owning plugin ID included in visual metadata. */\n pluginId?: string\n /** Workflow node category used unless a definition overrides it. */\n kind: WorkflowDefinitionNodeKind\n /** Optional declared tool-scope metadata; execution enforcement belongs to the host handler. */\n toolScope?: WorkflowToolScopeDefinition\n /** Optional visual capability flag; compilation defaults to true when no node approval is declared. */\n canRequestApproval?: boolean\n}\n\n/**\n * Definition and node context supplied when compiling a registered workflow node.\n * @see WorkflowNodeRegistration.\n */\nexport interface WorkflowNodeResolverInput {\n /** Validated serializable workflow definition being compiled. */\n definition: WorkflowDefinition\n /** Specific definition node being resolved. */\n node: WorkflowDefinitionNode\n /** Optional runtime state for host-specific resolution; the standard compiler omits it. */\n state?: AgentGraphState\n}\n\n/**\n * Trusted host/plugin handler and optional subgraph resolution for one catalog node type.\n * @see WorkflowNodeCatalog.register.\n */\nexport interface WorkflowNodeRegistration {\n /** Serializable editor metadata cloned at registration. */\n descriptor: WorkflowNodeDescriptor\n /**\n * Resolves a plugin/host handler while preserving the Effect/Receipt boundary.\n * @param input - Validated definition and node being compiled.\n * @returns A graph handler, synchronously or asynchronously; the compiler rejects nonfunctions.\n * @throws Resolver failures reject compilation.\n \n * @example\n * ```typescript\n * import type { WorkflowNodeRegistration } from \"@alneas/eaos-server\";\n * export async function resolveHostNode(\n * registration: WorkflowNodeRegistration,\n * validatedInput: Parameters<WorkflowNodeRegistration[\"resolve\"]>[0],\n * ) {\n * const handler = await registration.resolve(validatedInput);\n * return handler; // Resolving a handler does not execute its effects.\n * }\n * ```\n */\n resolve(input: WorkflowNodeResolverInput): GraphNodeHandler | Promise<GraphNodeHandler>\n /**\n * Resolves a compiled LangGraph subgraph for a definition declaring subflow.\n * @param input - Validated definition and subflow node.\n * @returns A graph exposing invoke, synchronously or asynchronously.\n * @throws Resolver failures reject compilation.\n \n * @example\n * ```typescript\n * import type { WorkflowNodeRegistration } from \"@alneas/eaos-server\";\n * export async function resolveHostSubflow(\n * registration: WorkflowNodeRegistration,\n * validatedInput: Parameters<NonNullable<WorkflowNodeRegistration[\"resolveSubgraph\"]>>[0],\n * ) {\n * if (!registration.resolveSubgraph) throw new Error(\"This node has no subgraph resolver\");\n * return await registration.resolveSubgraph(validatedInput);\n * }\n * ```\n */\n resolveSubgraph?(input: WorkflowNodeResolverInput): GraphSubgraph | Promise<GraphSubgraph>\n}\n\n/**\n * Registers trusted host/plugin node resolvers and cloned descriptors for workflow compilation and editors.\n * @remarks Storage is process-local; no persistence or authorization is supplied.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * const catalog = new WorkflowNodeCatalog();\n * const unregister = catalog.register({ descriptor: { type: \"example.task\", label: \"Example\", kind: \"task\" }, resolve: () => async () => ({}) });\n * console.log(catalog.list().length); // 1\n * unregister();\n * ```\n */\nexport class WorkflowNodeCatalog {\n private readonly registrations = new Map<string, WorkflowNodeRegistration>()\n\n /**\n * Registers a unique node type and returns a safe unregister callback.\n * @param registration - Descriptor with nonblank label and type matching lowercase letters/digits/dot/underscore/hyphen up to 128 characters, plus a handler resolver.\n * @returns A no-argument callback returning no value; it removes only this registration and does not remove a later replacement.\n * @throws Invalid type/label, duplicate type, missing resolver, or descriptor clone failure.\n * @remarks The descriptor is cloned and its label trimmed; resolver function references are retained.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * const catalog = new WorkflowNodeCatalog();\n * const dispose = catalog.register({ descriptor: { type: \"example.task\", label: \"Example\", kind: \"task\" }, resolve: () => async () => ({}) });\n * dispose();\n * ```\n */\n register(registration: WorkflowNodeRegistration): () => void {\n const type = registration?.descriptor?.type\n if (!type || !/^[a-z0-9][a-z0-9._-]{0,127}$/.test(type)) throw new Error('Invalid workflow node catalog type')\n if (this.registrations.has(type)) throw new Error(`Workflow node type '${type}' is already registered`)\n if (!registration.resolve || typeof registration.resolve !== 'function') throw new Error(`Workflow node '${type}' must provide a resolver`)\n const descriptor = structuredClone({ ...registration.descriptor, type, label: registration.descriptor.label?.trim() })\n if (!descriptor.label) throw new Error(`Workflow node '${type}' must provide a label`)\n this.registrations.set(type, { ...registration, descriptor })\n return () => {\n if (this.registrations.get(type)?.descriptor === descriptor) this.registrations.delete(type)\n }\n }\n\n /**\n * Reads a registered resolver by exact node type.\n * @param type - Case-sensitive catalog type identifier.\n * @returns The retained registration, or undefined; mutation is not isolated by cloning.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * console.log(new WorkflowNodeCatalog().get(\"example.task\")); // undefined\n * ```\n */\n get(type: string): WorkflowNodeRegistration | undefined { return this.registrations.get(type) }\n\n /**\n * Reads a registered resolver or fails if the type is unavailable.\n * @param type - Exact catalog node type required by a workflow definition.\n * @returns The retained registration.\n * @throws If no registration exists for type.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog, type WorkflowNodeRegistration } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * export function registered(registration: WorkflowNodeRegistration) {\n * const catalog = new WorkflowNodeCatalog();\n * catalog.register(registration);\n * return catalog.require(registration.descriptor.type);\n * }\n * ```\n */\n require(type: string): WorkflowNodeRegistration {\n const registration = this.get(type)\n if (!registration) throw new Error(`Workflow node type '${type}' is not registered`)\n return registration\n }\n\n /**\n * Lists cloned descriptors in registration insertion order.\n * @returns A new descriptor array, empty for an empty catalog; caller changes do not affect stored descriptors.\n * @throws If descriptors were externally mutated to contain uncloneable values.\n * @example\n * ```typescript\n * import { WorkflowNodeCatalog } from \"@alneas/eaos-server/agentic/workflow-catalog\";\n * console.log(new WorkflowNodeCatalog().list()); // []\n * ```\n */\n list(): readonly WorkflowNodeDescriptor[] {\n return structuredClone([...this.registrations.values()].map(item => item.descriptor))\n }\n}\n"],"mappings":";AA+FO,IAAM,sBAAN,MAA0B;AAAA,EACd,gBAAgB,oBAAI,IAAsC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB3E,SAAS,cAAoD;AAC3D,UAAM,OAAO,cAAc,YAAY;AACvC,QAAI,CAAC,QAAQ,CAAC,+BAA+B,KAAK,IAAI,EAAG,OAAM,IAAI,MAAM,oCAAoC;AAC7G,QAAI,KAAK,cAAc,IAAI,IAAI,EAAG,OAAM,IAAI,MAAM,uBAAuB,IAAI,yBAAyB;AACtG,QAAI,CAAC,aAAa,WAAW,OAAO,aAAa,YAAY,WAAY,OAAM,IAAI,MAAM,kBAAkB,IAAI,2BAA2B;AAC1I,UAAM,aAAa,gBAAgB,EAAE,GAAG,aAAa,YAAY,MAAM,OAAO,aAAa,WAAW,OAAO,KAAK,EAAE,CAAC;AACrH,QAAI,CAAC,WAAW,MAAO,OAAM,IAAI,MAAM,kBAAkB,IAAI,wBAAwB;AACrF,SAAK,cAAc,IAAI,MAAM,EAAE,GAAG,cAAc,WAAW,CAAC;AAC5D,WAAO,MAAM;AACX,UAAI,KAAK,cAAc,IAAI,IAAI,GAAG,eAAe,WAAY,MAAK,cAAc,OAAO,IAAI;AAAA,IAC7F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,IAAI,MAAoD;AAAE,WAAO,KAAK,cAAc,IAAI,IAAI;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB9F,QAAQ,MAAwC;AAC9C,UAAM,eAAe,KAAK,IAAI,IAAI;AAClC,QAAI,CAAC,aAAc,OAAM,IAAI,MAAM,uBAAuB,IAAI,qBAAqB;AACnF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAA0C;AACxC,WAAO,gBAAgB,CAAC,GAAG,KAAK,cAAc,OAAO,CAAC,EAAE,IAAI,UAAQ,KAAK,UAAU,CAAC;AAAA,EACtF;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=chunk-7FTJN4SA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,24 @@
1
+ // src/middleware/error-handler.ts
2
+ function createErrorHandler(options) {
3
+ const isProduction = options?.isProduction ?? process.env.NODE_ENV === "production";
4
+ return async (err, c) => {
5
+ if (options?.logger) {
6
+ options.logger(err, c);
7
+ } else {
8
+ console.error(`[EaosServer:Error] ${c.req.method} ${c.req.path} -`, err);
9
+ }
10
+ const message = isProduction ? "Internal Server Error" : err.message;
11
+ return c.json(
12
+ {
13
+ error: message,
14
+ ...isProduction ? {} : { stack: err.stack }
15
+ },
16
+ 500
17
+ );
18
+ };
19
+ }
20
+
21
+ export {
22
+ createErrorHandler
23
+ };
24
+ //# sourceMappingURL=chunk-AVDMLTPF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware/error-handler.ts"],"sourcesContent":["import type { Context } from 'hono'\n\n/**\n * Controls error response redaction and logging for {@link createErrorHandler}.\n */\nexport interface ErrorHandlerOptions {\n /** Hide message and stack when true; defaults to NODE_ENV === \"production\". */\n isProduction?: boolean\n /** Called synchronously with the original error and request context before rendering; defaults to console.error. A thrown logger error propagates. */\n logger?: (err: Error, c: Context) => void\n}\n\n/**\n * Creates a Hono error handler that logs errors and renders a JSON 500 response.\n * @param options - Logging and redaction settings; omitted settings use console.error and NODE_ENV.\n * @returns An async handler resolving to a 500 response; production responses omit stacks and use \"Internal Server Error\".\n * @throws The returned handler rejects if the host logger throws.\n * @remarks Nonproduction responses expose error messages and stacks. Choose production redaction explicitly for externally accessible services.\n * @example\n * ```typescript\n * import { Hono } from \"hono\";\n * import { createErrorHandler } from \"@alneas/eaos-server/middleware/error-handler\";\n * const app = new Hono();\n * app.onError(createErrorHandler({ isProduction: true }));\n * app.get(\"/example\", () => { throw new Error(\"example failure\"); });\n * console.log((await app.request(\"/example\")).status); // 500\n * ```\n */\nexport function createErrorHandler(options?: ErrorHandlerOptions) {\n const isProduction = options?.isProduction ?? process.env.NODE_ENV === 'production'\n\n return async (err: Error, c: Context) => {\n if (options?.logger) {\n options.logger(err, c)\n } else {\n console.error(`[EaosServer:Error] ${c.req.method} ${c.req.path} -`, err)\n }\n\n const message = isProduction ? 'Internal Server Error' : err.message\n return c.json(\n {\n error: message,\n ...(isProduction ? {} : { stack: err.stack }),\n },\n 500\n )\n }\n}\n"],"mappings":";AA4BO,SAAS,mBAAmB,SAA+B;AAChE,QAAM,eAAe,SAAS,gBAAgB,QAAQ,IAAI,aAAa;AAEvE,SAAO,OAAO,KAAY,MAAe;AACvC,QAAI,SAAS,QAAQ;AACnB,cAAQ,OAAO,KAAK,CAAC;AAAA,IACvB,OAAO;AACL,cAAQ,MAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,IACzE;AAEA,UAAM,UAAU,eAAe,0BAA0B,IAAI;AAC7D,WAAO,EAAE;AAAA,MACP;AAAA,QACE,OAAO;AAAA,QACP,GAAI,eAAe,CAAC,IAAI,EAAE,OAAO,IAAI,MAAM;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,95 @@
1
+ // src/tenant.ts
2
+ var TenantResolver = class {
3
+ defaultTenantId;
4
+ domainTenantMap;
5
+ hostTenantMap;
6
+ /**
7
+ * Copies routing mappings, normalizing their keys to lower case.
8
+ * @param options - Routing mappings and fallback; omitted options use empty mappings and "default".
9
+ */
10
+ constructor(options = {}) {
11
+ this.defaultTenantId = options.defaultTenantId ?? "default";
12
+ this.domainTenantMap = new Map(
13
+ Object.entries(options.domainTenantMap ?? {}).map(([k, v]) => [k.toLowerCase(), v])
14
+ );
15
+ this.hostTenantMap = new Map(
16
+ Object.entries(options.hostTenantMap ?? {}).map(([k, v]) => [k.toLowerCase(), v])
17
+ );
18
+ }
19
+ /**
20
+ * Looks up the lower-case domain following the first @ in an email routing hint.
21
+ * @param email - Email hint; missing, empty, or missing @ returns null. No address validation is performed.
22
+ * @returns The configured routing ID, or null when no domain matches.
23
+ * @example
24
+ * ```typescript
25
+ * import { TenantResolver } from "@alneas/eaos-server/tenant";
26
+ * const resolver = new TenantResolver({ domainTenantMap: { "example.com": "workspace" } });
27
+ * console.log(resolver.resolveFromEmail("person@example.com"));
28
+ * ```
29
+ */
30
+ resolveFromEmail(email) {
31
+ if (!email) return null;
32
+ const parts = email.split("@");
33
+ if (parts.length < 2) return null;
34
+ const domain = parts[1].toLowerCase();
35
+ return this.domainTenantMap.get(domain) ?? null;
36
+ }
37
+ /**
38
+ * Looks up a configured hostname after removing text following the first colon and lower-casing.
39
+ * @param host - Host routing hint, optionally including a port; missing or empty values return null. IPv6 host parsing is not provided.
40
+ * @returns The exact configured host mapping, or null.
41
+ * @example
42
+ * ```typescript
43
+ * import { TenantResolver } from "@alneas/eaos-server/tenant";
44
+ * const resolver = new TenantResolver({ hostTenantMap: { "workspace.example.com": "workspace" } });
45
+ * console.log(resolver.resolveFromHost("workspace.example.com:443"));
46
+ * ```
47
+ */
48
+ resolveFromHost(host) {
49
+ if (!host) return null;
50
+ const cleanHost = host.split(":")[0].toLowerCase();
51
+ if (this.hostTenantMap.has(cleanHost)) {
52
+ return this.hostTenantMap.get(cleanHost);
53
+ }
54
+ return null;
55
+ }
56
+ /**
57
+ * Selects a truthy explicit ID, then a host mapping, then the configured fallback.
58
+ * @param input - Routing hints: explicitTenantId takes precedence over host; email is intentionally ignored. The host must establish whether an explicit ID is trusted.
59
+ * @returns The selected routing ID, without validating tenant existence or membership.
60
+ * @see TenantResolver for a complete usage example.
61
+ * @example
62
+ * ```typescript
63
+ * import { TenantResolver } from "@alneas/eaos-server/tenant";
64
+ * const resolver = new TenantResolver();
65
+ * console.log(resolver.resolve({ explicitTenantId: "workspace" }));
66
+ * ```
67
+ */
68
+ resolve(input) {
69
+ if (input.explicitTenantId) return input.explicitTenantId;
70
+ const fromHost = this.resolveFromHost(input.host);
71
+ if (fromHost) return fromHost;
72
+ return this.defaultTenantId;
73
+ }
74
+ /**
75
+ * Reads the fallback ID captured at construction.
76
+ * @returns The configured fallback, or "default" when none was supplied.
77
+ * @example
78
+ * ```typescript
79
+ * import { TenantResolver } from "@alneas/eaos-server/tenant";
80
+ * console.log(new TenantResolver().getDefaultTenantId());
81
+ * ```
82
+ */
83
+ getDefaultTenantId() {
84
+ return this.defaultTenantId;
85
+ }
86
+ };
87
+ function createTenantResolver(options) {
88
+ return new TenantResolver(options);
89
+ }
90
+
91
+ export {
92
+ TenantResolver,
93
+ createTenantResolver
94
+ };
95
+ //# sourceMappingURL=chunk-BKAHUEIT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tenant.ts"],"sourcesContent":["/**\n * Routing hints used by {@link TenantResolver}; they do not authenticate a tenant.\n * @see TenantResolver for a complete usage example.\n */\nexport interface TenantResolverOptions {\n /** Fallback when no explicit ID or host mapping matches. @defaultValue \"default\" */\n defaultTenantId?: string\n /** Routing-only email domain mappings. Never use email-derived results as an authenticated tenant claim. */\n domainTenantMap?: Record<string, string>\n /** Trusted, exact hostname mappings (e.g. { \"demo.example.com\": \"tenant-demo\" }). */\n hostTenantMap?: Record<string, string>\n}\n\n/**\n * Selects a tenant routing ID from an explicit trusted ID, configured host, or fallback.\n * @remarks This resolver performs no authentication or membership check. Host headers and explicit IDs must be validated by the host before being used for authorization. Email mappings are exposed only by resolveFromEmail.\n * @example\n * ```typescript\n * import { TenantResolver } from \"@alneas/eaos-server/tenant\";\n * const resolver = new TenantResolver({ hostTenantMap: { \"workspace.example.com\": \"workspace\" } });\n * const tenantId = resolver.resolve({ host: \"workspace.example.com:443\" });\n * console.log(tenantId); // \"workspace\"\n * ```\n */\nexport class TenantResolver {\n private defaultTenantId: string\n private domainTenantMap: Map<string, string>\n private hostTenantMap: Map<string, string>\n\n /**\n * Copies routing mappings, normalizing their keys to lower case.\n * @param options - Routing mappings and fallback; omitted options use empty mappings and \"default\".\n */\n constructor(options: TenantResolverOptions = {}) {\n this.defaultTenantId = options.defaultTenantId ?? 'default'\n this.domainTenantMap = new Map(\n Object.entries(options.domainTenantMap ?? {}).map(([k, v]) => [k.toLowerCase(), v])\n )\n this.hostTenantMap = new Map(\n Object.entries(options.hostTenantMap ?? {}).map(([k, v]) => [k.toLowerCase(), v])\n )\n }\n\n /**\n * Looks up the lower-case domain following the first @ in an email routing hint.\n * @param email - Email hint; missing, empty, or missing @ returns null. No address validation is performed.\n * @returns The configured routing ID, or null when no domain matches.\n * @example\n * ```typescript\n * import { TenantResolver } from \"@alneas/eaos-server/tenant\";\n * const resolver = new TenantResolver({ domainTenantMap: { \"example.com\": \"workspace\" } });\n * console.log(resolver.resolveFromEmail(\"person@example.com\"));\n * ```\n */\n resolveFromEmail(email: string | null | undefined): string | null {\n if (!email) return null\n const parts = email.split('@')\n if (parts.length < 2) return null\n const domain = parts[1].toLowerCase()\n return this.domainTenantMap.get(domain) ?? null\n }\n\n /**\n * Looks up a configured hostname after removing text following the first colon and lower-casing.\n * @param host - Host routing hint, optionally including a port; missing or empty values return null. IPv6 host parsing is not provided.\n * @returns The exact configured host mapping, or null.\n * @example\n * ```typescript\n * import { TenantResolver } from \"@alneas/eaos-server/tenant\";\n * const resolver = new TenantResolver({ hostTenantMap: { \"workspace.example.com\": \"workspace\" } });\n * console.log(resolver.resolveFromHost(\"workspace.example.com:443\"));\n * ```\n */\n resolveFromHost(host: string | null | undefined): string | null {\n if (!host) return null\n const cleanHost = host.split(':')[0].toLowerCase()\n if (this.hostTenantMap.has(cleanHost)) {\n return this.hostTenantMap.get(cleanHost)!\n }\n return null\n }\n\n /**\n * Selects a truthy explicit ID, then a host mapping, then the configured fallback.\n * @param input - Routing hints: explicitTenantId takes precedence over host; email is intentionally ignored. The host must establish whether an explicit ID is trusted.\n * @returns The selected routing ID, without validating tenant existence or membership.\n * @see TenantResolver for a complete usage example.\n * @example\n * ```typescript\n * import { TenantResolver } from \"@alneas/eaos-server/tenant\";\n * const resolver = new TenantResolver();\n * console.log(resolver.resolve({ explicitTenantId: \"workspace\" }));\n * ```\n */\n resolve(input: { \n /**\n * Optional host routing hint, including a possible port; checked only after a falsy/absent explicitTenantId against configured exact host mappings.\n */\n host?: string | null; \n /**\n * Optional compatibility routing hint intentionally ignored by resolve; an email domain is not an authenticated tenant claim.\n */\n email?: string | null; \n /**\n * Optional trusted tenant routing selection; any truthy value takes precedence without tenant-existence or membership validation.\n */\n explicitTenantId?: string | null }): string {\n if (input.explicitTenantId) return input.explicitTenantId\n // Email domains are routing hints only; they are deliberately not accepted\n // as an authenticated tenant selector.\n const fromHost = this.resolveFromHost(input.host)\n if (fromHost) return fromHost\n return this.defaultTenantId\n }\n\n /**\n * Reads the fallback ID captured at construction.\n * @returns The configured fallback, or \"default\" when none was supplied.\n * @example\n * ```typescript\n * import { TenantResolver } from \"@alneas/eaos-server/tenant\";\n * console.log(new TenantResolver().getDefaultTenantId());\n * ```\n */\n getDefaultTenantId(): string {\n return this.defaultTenantId\n }\n}\n\n/**\n * Creates a resolver for host-owned tenant routing hints.\n * @param options - Routing mappings and fallback; see {@link TenantResolverOptions}.\n * @returns A new independent resolver with copied mappings.\n * @example\n * ```typescript\n * import { createTenantResolver } from \"@alneas/eaos-server/tenant\";\n * const resolver = createTenantResolver({ defaultTenantId: \"workspace\" });\n * console.log(resolver.resolve({}));\n * ```\n */\nexport function createTenantResolver(options?: TenantResolverOptions): TenantResolver {\n return new TenantResolver(options)\n}\n"],"mappings":";AAwBO,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,UAAiC,CAAC,GAAG;AAC/C,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,kBAAkB,IAAI;AAAA,MACzB,OAAO,QAAQ,QAAQ,mBAAmB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC;AAAA,IACpF;AACA,SAAK,gBAAgB,IAAI;AAAA,MACvB,OAAO,QAAQ,QAAQ,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,CAAC,CAAC;AAAA,IAClF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,iBAAiB,OAAiD;AAChE,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,SAAS,EAAG,QAAO;AAC7B,UAAM,SAAS,MAAM,CAAC,EAAE,YAAY;AACpC,WAAO,KAAK,gBAAgB,IAAI,MAAM,KAAK;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,gBAAgB,MAAgD;AAC9D,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,YAAY,KAAK,MAAM,GAAG,EAAE,CAAC,EAAE,YAAY;AACjD,QAAI,KAAK,cAAc,IAAI,SAAS,GAAG;AACrC,aAAO,KAAK,cAAc,IAAI,SAAS;AAAA,IACzC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,QAAQ,OAYoC;AAC1C,QAAI,MAAM,iBAAkB,QAAO,MAAM;AAGzC,UAAM,WAAW,KAAK,gBAAgB,MAAM,IAAI;AAChD,QAAI,SAAU,QAAO;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,qBAA6B;AAC3B,WAAO,KAAK;AAAA,EACd;AACF;AAaO,SAAS,qBAAqB,SAAiD;AACpF,SAAO,IAAI,eAAe,OAAO;AACnC;","names":[]}
@@ -0,0 +1,134 @@
1
+ import {
2
+ AgentGraphEngine
3
+ } from "./chunk-HXFVOR7Z.js";
4
+
5
+ // src/agentic/workflow-compiler.ts
6
+ import { evaluateWorkflowCondition, validateWorkflowDefinition } from "@alneas/eaos-core";
7
+ async function compileWorkflowDefinition(input, options) {
8
+ const definition = validateWorkflowDefinition(input);
9
+ if (!options?.catalog) throw new Error("Workflow node catalog is required");
10
+ const graph = new AgentGraphEngine({
11
+ checkpointer: options.checkpointer,
12
+ authorizeResume: options.authorizeResume,
13
+ workflowId: definition.workflowId,
14
+ workflowVersion: definition.version
15
+ });
16
+ for (const node of definition.nodes) {
17
+ const registration = options.catalog.require(node.type);
18
+ const visual = visualNode(node, registration.descriptor);
19
+ if (node.subflow) {
20
+ if (!registration.resolveSubgraph) throw new Error(`Workflow node '${node.id}' declares a subflow but '${node.type}' has no subgraph resolver`);
21
+ const subgraph = await registration.resolveSubgraph({ definition, node });
22
+ if (!subgraph || typeof subgraph.invoke !== "function") throw new Error(`Workflow subflow '${node.id}' did not resolve to a compiled graph`);
23
+ graph.addSubgraph(node.id, subgraph, {
24
+ visual,
25
+ mapInput: (state) => node.subflow?.inputPath ? valueAtPath(state, node.subflow.inputPath).value : state,
26
+ mapOutput: (output, state) => ({ context: { ...state.context ?? {}, [node.subflow?.outputKey ?? `${node.id}.output`]: structuredClone(output) } })
27
+ });
28
+ continue;
29
+ }
30
+ const handler = await registration.resolve({ definition, node });
31
+ if (typeof handler !== "function") throw new Error(`Workflow node '${node.id}' did not resolve to a handler`);
32
+ graph.addNode(node.id, wrapNode(node, handler), { retryPolicy: retryPolicy(node), visual });
33
+ }
34
+ graph.setEntryPoint(definition.entryNode);
35
+ for (const node of definition.nodes) {
36
+ const outgoing = definition.edges.filter((edge) => edge.from === node.id);
37
+ if (!outgoing.length) continue;
38
+ for (const edge of outgoing) graph.addEdge(edge.from, edge.to, { visual: edgeVisual(edge) });
39
+ if (outgoing.some((edge) => edge.condition !== void 0)) {
40
+ const destinations = [...new Set(outgoing.map((edge) => edge.to))];
41
+ graph.addConditionalEdges(node.id, (state) => routeDefinitionEdges(outgoing, state), destinations, {
42
+ labels: Object.fromEntries(outgoing.map((edge) => [edge.to, edge.label ?? (edge.condition ? "\u6761\u4EF6\u5206\u5C90" : "\u65E2\u5B9A")])),
43
+ visual: { kind: "conditional" }
44
+ });
45
+ }
46
+ }
47
+ return { definition, graph };
48
+ }
49
+ function wrapNode(node, handler) {
50
+ return async (state) => {
51
+ const handlerState = node.toolScope ? { ...structuredClone(state), context: { ...state.context ?? {}, __eaosWorkflowToolScope: structuredClone(node.toolScope) } } : structuredClone(state);
52
+ const update = await withTimeout(handler(handlerState), node.timeoutMs, node.id);
53
+ if (!node.approval) return update;
54
+ const existing = update.pendingApproval;
55
+ const args = existing?.args ?? (node.approval.argsPath ? valueAtPath({ ...state, ...update }, node.approval.argsPath).value : {});
56
+ if (!isRecord(args)) throw new Error(`Workflow approval node '${node.id}' args must be an object`);
57
+ return {
58
+ ...update,
59
+ pendingApproval: {
60
+ ...existing ?? {},
61
+ toolName: existing?.toolName ?? node.approval.toolName,
62
+ approvalLevel: existing?.approvalLevel ?? node.approval.approvalLevel,
63
+ riskLevel: existing?.riskLevel ?? node.approval.riskLevel,
64
+ reason: existing?.reason ?? node.approval.reason,
65
+ args: structuredClone(args),
66
+ ...node.approval.permission === void 0 ? {} : { permission: existing?.permission ?? node.approval.permission },
67
+ ...node.approval.contractVersion === void 0 ? {} : { contractVersion: existing?.contractVersion ?? node.approval.contractVersion }
68
+ }
69
+ };
70
+ };
71
+ }
72
+ function retryPolicy(node) {
73
+ if (!node.retry) return void 0;
74
+ return { maxAttempts: node.retry.maxAttempts, initialInterval: node.retry.backoffMs, maxInterval: node.retry.maxBackoffMs, jitter: node.retry.jitter };
75
+ }
76
+ function visualNode(node, descriptor) {
77
+ return {
78
+ kind: node.kind ?? descriptor.kind ?? "task",
79
+ label: node.label ?? descriptor.label,
80
+ ...node.description ?? descriptor.description ? { description: node.description ?? descriptor.description } : {},
81
+ ...node.pluginId ?? descriptor.pluginId ? { pluginId: node.pluginId ?? descriptor.pluginId } : {},
82
+ ...node.approval ? { approvalLevel: node.approval.approvalLevel, riskLevel: node.approval.riskLevel, toolName: node.approval.toolName, canRequestApproval: true } : { canRequestApproval: descriptor.canRequestApproval ?? true },
83
+ ...node.retry ? { retryable: node.retry.maxAttempts > 1 } : {},
84
+ ...node.subflow ? { subgraphId: node.subflow.workflowId, subgraphVersion: node.subflow.version } : {}
85
+ };
86
+ }
87
+ function edgeVisual(edge) {
88
+ return {
89
+ kind: edge.condition ? "conditional" : edge.default ? "system" : "normal",
90
+ ...edge.label === void 0 ? {} : { label: edge.label },
91
+ ...edge.condition === void 0 ? {} : { condition: conditionLabel(edge.condition) }
92
+ };
93
+ }
94
+ function conditionLabel(condition) {
95
+ if ("all" in condition) return condition.all.map(conditionLabel).join(" AND ");
96
+ if ("any" in condition) return condition.any.map(conditionLabel).join(" OR ");
97
+ if ("not" in condition) return `NOT (${conditionLabel(condition.not)})`;
98
+ return `${condition.path} ${condition.operator}${"value" in condition ? ` ${JSON.stringify(condition.value)}` : ""}`;
99
+ }
100
+ function routeDefinitionEdges(edges, state) {
101
+ const fallback = edges.find((edge) => edge.default === true || edge.condition === void 0);
102
+ const match = edges.find((edge) => edge.condition !== void 0 && evaluateWorkflowCondition(edge.condition, state));
103
+ return (match ?? fallback)?.to ?? (() => {
104
+ throw new Error(`No workflow edge condition matched from '${state.currentStep}'`);
105
+ })();
106
+ }
107
+ function valueAtPath(input, path) {
108
+ let current = input;
109
+ for (const part of path.split(".")) {
110
+ if (!isRecord(current) || !Object.prototype.hasOwnProperty.call(current, part)) return { exists: false, value: void 0 };
111
+ current = current[part];
112
+ }
113
+ return { exists: true, value: current };
114
+ }
115
+ function isRecord(value) {
116
+ return typeof value === "object" && value !== null && !Array.isArray(value);
117
+ }
118
+ async function withTimeout(promise, timeoutMs, nodeId) {
119
+ if (timeoutMs === void 0) return promise;
120
+ let timer;
121
+ const timeout = new Promise((_, reject) => {
122
+ timer = setTimeout(() => reject(new Error(`Workflow node '${nodeId}' timed out after ${timeoutMs}ms`)), timeoutMs);
123
+ });
124
+ try {
125
+ return await Promise.race([promise, timeout]);
126
+ } finally {
127
+ if (timer !== void 0) clearTimeout(timer);
128
+ }
129
+ }
130
+
131
+ export {
132
+ compileWorkflowDefinition
133
+ };
134
+ //# sourceMappingURL=chunk-CJ7OFEF7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/workflow-compiler.ts"],"sourcesContent":["import type { WorkflowCondition, WorkflowDefinition, WorkflowDefinitionEdge, WorkflowDefinitionNode, WorkflowGraphNodeInput } from '@alneas/eaos-core'\nimport { evaluateWorkflowCondition, validateWorkflowDefinition } from '@alneas/eaos-core'\nimport type { BaseCheckpointSaver, RetryPolicy } from '@langchain/langgraph'\nimport { AgentGraphEngine, type AgentGraphEngineOptions, type AgentGraphState, type GraphNodeHandler } from './graph'\nimport { WorkflowNodeCatalog } from './workflow-catalog'\n\n/**\n * Trusted node catalog, checkpoint persistence, and live approval authority for {@link compileWorkflowDefinition}.\n */\nexport interface WorkflowCompilerOptions {\n /** Required host/plugin node resolver catalog. */\n catalog: WorkflowNodeCatalog\n /** Optional LangGraph saver; absent uses the graph engine default, which is not durable host storage. */\n checkpointer?: BaseCheckpointSaver\n /** Optional live host approval authorization forwarded to the graph engine. */\n authorizeResume?: AgentGraphEngineOptions['authorizeResume']\n}\n\n/**\n * Validated definition and configured graph produced by {@link compileWorkflowDefinition}.\n */\nexport interface CompiledWorkflow {\n /** Validated serializable workflow definition returned by core validation. */\n definition: WorkflowDefinition\n /** Newly assembled graph; compilation performs no workflow execution. */\n graph: AgentGraphEngine\n}\n\n/**\n * Validates a serializable workflow and resolves its catalog nodes into a LangGraph-backed runtime.\n * @param input - Unknown serialized definition accepted by core validateWorkflowDefinition.\n * @param options - Required catalog, optional saver, and live resume authorizer.\n * @returns Validated definition and newly configured graph with node retries, conditional routes, approval metadata, and subgraph mappings.\n * @throws Rejects definition validation, missing catalog/types/subgraph resolvers, invalid resolved handlers/graphs, or propagated resolver/graph construction errors.\n * @remarks Host resolvers may have setup side effects before a later node fails; no rollback/disposal protocol is provided. Node timeouts race the handler but do not cancel underlying work. Tool scopes are passed in workflow context; handlers must enforce them. Runtime conditional routing picks the first matching condition or first default/unconditional edge and throws if none match. Durable persistence, live authorization, and safe side-effect retry contracts remain host-owned.\n * @example\n * ```typescript\n * import { compileWorkflowDefinition, type WorkflowCompilerOptions } from \"@alneas/eaos-server/agentic/workflow-compiler\";\n * export async function compile(input: unknown, options: WorkflowCompilerOptions) {\n * return compileWorkflowDefinition(input, options);\n * }\n * ```\n */\nexport async function compileWorkflowDefinition(input: unknown, options: WorkflowCompilerOptions): Promise<CompiledWorkflow> {\n const definition = validateWorkflowDefinition(input)\n if (!options?.catalog) throw new Error('Workflow node catalog is required')\n const graph = new AgentGraphEngine({\n checkpointer: options.checkpointer,\n authorizeResume: options.authorizeResume,\n workflowId: definition.workflowId,\n workflowVersion: definition.version,\n })\n\n for (const node of definition.nodes) {\n const registration = options.catalog.require(node.type)\n const visual = visualNode(node, registration.descriptor)\n if (node.subflow) {\n if (!registration.resolveSubgraph) throw new Error(`Workflow node '${node.id}' declares a subflow but '${node.type}' has no subgraph resolver`)\n const subgraph = await registration.resolveSubgraph({ definition, node })\n if (!subgraph || typeof subgraph.invoke !== 'function') throw new Error(`Workflow subflow '${node.id}' did not resolve to a compiled graph`)\n graph.addSubgraph(node.id, subgraph, {\n visual,\n mapInput: state => node.subflow?.inputPath ? valueAtPath(state, node.subflow.inputPath).value : state,\n mapOutput: (output, state) => ({ context: { ...(state.context ?? {}), [node.subflow?.outputKey ?? `${node.id}.output`]: structuredClone(output) } }),\n })\n continue\n }\n const handler = await registration.resolve({ definition, node })\n if (typeof handler !== 'function') throw new Error(`Workflow node '${node.id}' did not resolve to a handler`)\n graph.addNode(node.id, wrapNode(node, handler), { retryPolicy: retryPolicy(node), visual })\n }\n\n graph.setEntryPoint(definition.entryNode)\n for (const node of definition.nodes) {\n const outgoing = definition.edges.filter(edge => edge.from === node.id)\n if (!outgoing.length) continue\n for (const edge of outgoing) graph.addEdge(edge.from, edge.to, { visual: edgeVisual(edge) })\n if (outgoing.some(edge => edge.condition !== undefined)) {\n const destinations = [...new Set(outgoing.map(edge => edge.to))]\n graph.addConditionalEdges(node.id, state => routeDefinitionEdges(outgoing, state), destinations, {\n labels: Object.fromEntries(outgoing.map(edge => [edge.to, edge.label ?? (edge.condition ? '条件分岐' : '既定')])),\n visual: { kind: 'conditional' },\n })\n }\n }\n return { definition, graph }\n}\n\nfunction wrapNode(node: WorkflowDefinitionNode, handler: GraphNodeHandler): GraphNodeHandler {\n return async state => {\n const handlerState = node.toolScope\n ? { ...structuredClone(state), context: { ...(state.context ?? {}), __eaosWorkflowToolScope: structuredClone(node.toolScope) } }\n : structuredClone(state)\n const update = await withTimeout(handler(handlerState), node.timeoutMs, node.id)\n if (!node.approval) return update\n const existing = update.pendingApproval\n const args = existing?.args ?? (node.approval.argsPath ? valueAtPath({ ...state, ...update }, node.approval.argsPath).value : {})\n if (!isRecord(args)) throw new Error(`Workflow approval node '${node.id}' args must be an object`)\n return {\n ...update,\n pendingApproval: {\n ...(existing ?? {}),\n toolName: existing?.toolName ?? node.approval.toolName,\n approvalLevel: existing?.approvalLevel ?? node.approval.approvalLevel,\n riskLevel: existing?.riskLevel ?? node.approval.riskLevel,\n reason: existing?.reason ?? node.approval.reason,\n args: structuredClone(args),\n ...(node.approval.permission === undefined ? {} : { permission: existing?.permission ?? node.approval.permission }),\n ...(node.approval.contractVersion === undefined ? {} : { contractVersion: existing?.contractVersion ?? node.approval.contractVersion }),\n },\n }\n }\n}\n\nfunction retryPolicy(node: WorkflowDefinitionNode): RetryPolicy | undefined {\n if (!node.retry) return undefined\n return { maxAttempts: node.retry.maxAttempts, initialInterval: node.retry.backoffMs, maxInterval: node.retry.maxBackoffMs, jitter: node.retry.jitter }\n}\n\nfunction visualNode(node: WorkflowDefinitionNode, descriptor: { label: string; description?: string; pluginId?: string; kind: WorkflowDefinitionNode['kind']; canRequestApproval?: boolean }): WorkflowGraphNodeInput {\n return {\n kind: node.kind ?? descriptor.kind ?? 'task',\n label: node.label ?? descriptor.label,\n ...(node.description ?? descriptor.description ? { description: node.description ?? descriptor.description } : {}),\n ...(node.pluginId ?? descriptor.pluginId ? { pluginId: node.pluginId ?? descriptor.pluginId } : {}),\n ...(node.approval ? { approvalLevel: node.approval.approvalLevel, riskLevel: node.approval.riskLevel, toolName: node.approval.toolName, canRequestApproval: true } : { canRequestApproval: descriptor.canRequestApproval ?? true }),\n ...(node.retry ? { retryable: node.retry.maxAttempts > 1 } : {}),\n ...(node.subflow ? { subgraphId: node.subflow.workflowId, subgraphVersion: node.subflow.version } : {}),\n }\n}\n\nfunction edgeVisual(edge: WorkflowDefinitionEdge) {\n return {\n kind: edge.condition ? 'conditional' as const : edge.default ? 'system' as const : 'normal' as const,\n ...(edge.label === undefined ? {} : { label: edge.label }),\n ...(edge.condition === undefined ? {} : { condition: conditionLabel(edge.condition) }),\n }\n}\n\nfunction conditionLabel(condition: WorkflowCondition): string {\n if ('all' in condition) return condition.all.map(conditionLabel).join(' AND ')\n if ('any' in condition) return condition.any.map(conditionLabel).join(' OR ')\n if ('not' in condition) return `NOT (${conditionLabel(condition.not)})`\n return `${condition.path} ${condition.operator}${'value' in condition ? ` ${JSON.stringify(condition.value)}` : ''}`\n}\n\nfunction routeDefinitionEdges(edges: readonly WorkflowDefinitionEdge[], state: AgentGraphState): string {\n const fallback = edges.find(edge => edge.default === true || edge.condition === undefined)\n const match = edges.find(edge => edge.condition !== undefined && evaluateWorkflowCondition(edge.condition, state))\n return (match ?? fallback)?.to ?? (() => { throw new Error(`No workflow edge condition matched from '${state.currentStep}'`) })()\n}\n\nfunction valueAtPath(input: unknown, path: string): { exists: boolean; value: unknown } {\n let current: unknown = input\n for (const part of path.split('.')) {\n if (!isRecord(current) || !Object.prototype.hasOwnProperty.call(current, part)) return { exists: false, value: undefined }\n current = current[part]\n }\n return { exists: true, value: current }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nasync function withTimeout<T>(promise: Promise<T>, timeoutMs: number | undefined, nodeId: string): Promise<T> {\n if (timeoutMs === undefined) return promise\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<never>((_, reject) => { timer = setTimeout(() => reject(new Error(`Workflow node '${nodeId}' timed out after ${timeoutMs}ms`)), timeoutMs) })\n try { return await Promise.race([promise, timeout]) } finally { if (timer !== undefined) clearTimeout(timer) }\n}\n"],"mappings":"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","names":[]}