@alneas/eaos-server 0.0.0-stage → 0.2.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 (360) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +21 -0
  3. package/README.ja.md +49 -0
  4. package/README.md +46 -2
  5. package/dist/agentic/agent-jobs.d.ts +333 -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 +122 -0
  21. package/dist/agentic/autonomous-worker.js +10 -0
  22. package/dist/agentic/autonomous-worker.js.map +1 -0
  23. package/dist/agentic/event-bridge.d.ts +350 -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 +28 -0
  36. package/dist/agentic/index.js +87 -0
  37. package/dist/agentic/index.js.map +1 -0
  38. package/dist/agentic/local-runner.d.ts +106 -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-4BARRLJR.js +180 -0
  98. package/dist/chunk-4BARRLJR.js.map +1 -0
  99. package/dist/chunk-4VORUFKR.js +45 -0
  100. package/dist/chunk-4VORUFKR.js.map +1 -0
  101. package/dist/chunk-55D4ERWO.js +1 -0
  102. package/dist/chunk-55D4ERWO.js.map +1 -0
  103. package/dist/chunk-5TBBZIND.js +18 -0
  104. package/dist/chunk-5TBBZIND.js.map +1 -0
  105. package/dist/chunk-5WOZWPZA.js +211 -0
  106. package/dist/chunk-5WOZWPZA.js.map +1 -0
  107. package/dist/chunk-6CBVZ6CT.js +168 -0
  108. package/dist/chunk-6CBVZ6CT.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-EJKWDZIU.js +111 -0
  124. package/dist/chunk-EJKWDZIU.js.map +1 -0
  125. package/dist/chunk-F2J6IQ6I.js +247 -0
  126. package/dist/chunk-F2J6IQ6I.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-F4IITPGX.js +221 -0
  130. package/dist/chunk-F4IITPGX.js.map +1 -0
  131. package/dist/chunk-FD6VC2NA.js +66 -0
  132. package/dist/chunk-FD6VC2NA.js.map +1 -0
  133. package/dist/chunk-FRRRWAHO.js +14 -0
  134. package/dist/chunk-FRRRWAHO.js.map +1 -0
  135. package/dist/chunk-HCKAGLLB.js +17 -0
  136. package/dist/chunk-HCKAGLLB.js.map +1 -0
  137. package/dist/chunk-HVC7FG6B.js +191 -0
  138. package/dist/chunk-HVC7FG6B.js.map +1 -0
  139. package/dist/chunk-HXFVOR7Z.js +496 -0
  140. package/dist/chunk-HXFVOR7Z.js.map +1 -0
  141. package/dist/chunk-IJWYS2PF.js +122 -0
  142. package/dist/chunk-IJWYS2PF.js.map +1 -0
  143. package/dist/chunk-INCHXAFK.js +1395 -0
  144. package/dist/chunk-INCHXAFK.js.map +1 -0
  145. package/dist/chunk-JT6BRGQM.js +1 -0
  146. package/dist/chunk-JT6BRGQM.js.map +1 -0
  147. package/dist/chunk-L6PMAEMB.js +115 -0
  148. package/dist/chunk-L6PMAEMB.js.map +1 -0
  149. package/dist/chunk-LOUGW6MU.js +126 -0
  150. package/dist/chunk-LOUGW6MU.js.map +1 -0
  151. package/dist/chunk-LYPZPE53.js +129 -0
  152. package/dist/chunk-LYPZPE53.js.map +1 -0
  153. package/dist/chunk-NNCCN7JP.js +186 -0
  154. package/dist/chunk-NNCCN7JP.js.map +1 -0
  155. package/dist/chunk-PBC3MZUL.js +212 -0
  156. package/dist/chunk-PBC3MZUL.js.map +1 -0
  157. package/dist/chunk-R4ADP2DC.js +20 -0
  158. package/dist/chunk-R4ADP2DC.js.map +1 -0
  159. package/dist/chunk-RHN4Y6VS.js +44 -0
  160. package/dist/chunk-RHN4Y6VS.js.map +1 -0
  161. package/dist/chunk-SDJNYPYK.js +770 -0
  162. package/dist/chunk-SDJNYPYK.js.map +1 -0
  163. package/dist/chunk-UGNTCOVR.js +28 -0
  164. package/dist/chunk-UGNTCOVR.js.map +1 -0
  165. package/dist/chunk-VC2PCK2S.js +31 -0
  166. package/dist/chunk-VC2PCK2S.js.map +1 -0
  167. package/dist/chunk-VF5YDZJC.js +305 -0
  168. package/dist/chunk-VF5YDZJC.js.map +1 -0
  169. package/dist/chunk-VISRDVTK.js +675 -0
  170. package/dist/chunk-VISRDVTK.js.map +1 -0
  171. package/dist/chunk-W6O3LVBY.js +102 -0
  172. package/dist/chunk-W6O3LVBY.js.map +1 -0
  173. package/dist/chunk-WFEAKJLR.js +47 -0
  174. package/dist/chunk-WFEAKJLR.js.map +1 -0
  175. package/dist/chunk-XIEY2OF4.js +67 -0
  176. package/dist/chunk-XIEY2OF4.js.map +1 -0
  177. package/dist/chunk-XITLHDG3.js +37 -0
  178. package/dist/chunk-XITLHDG3.js.map +1 -0
  179. package/dist/chunk-XMWPYZWZ.js +61 -0
  180. package/dist/chunk-XMWPYZWZ.js.map +1 -0
  181. package/dist/chunk-XUP6CNOM.js +34 -0
  182. package/dist/chunk-XUP6CNOM.js.map +1 -0
  183. package/dist/chunk-YABTQZDJ.js +25 -0
  184. package/dist/chunk-YABTQZDJ.js.map +1 -0
  185. package/dist/chunk-YMHVRBUU.js +199 -0
  186. package/dist/chunk-YMHVRBUU.js.map +1 -0
  187. package/dist/chunk-YMJ7BRKU.js +510 -0
  188. package/dist/chunk-YMJ7BRKU.js.map +1 -0
  189. package/dist/chunk-ZC3XWU7B.js +28 -0
  190. package/dist/chunk-ZC3XWU7B.js.map +1 -0
  191. package/dist/chunk-ZHMTD5KV.js +90 -0
  192. package/dist/chunk-ZHMTD5KV.js.map +1 -0
  193. package/dist/chunk-ZWZDLOE7.js +160 -0
  194. package/dist/chunk-ZWZDLOE7.js.map +1 -0
  195. package/dist/db-package/db/local-first-sqlite-adapter.d.ts +432 -0
  196. package/dist/db-package/db/local-first-sqlite-adapter.js +7 -0
  197. package/dist/db-package/db/local-first-sqlite-adapter.js.map +1 -0
  198. package/dist/db-package/index.d.ts +7 -0
  199. package/dist/db-package/index.js +16 -0
  200. package/dist/db-package/index.js.map +1 -0
  201. package/dist/db-package/migration/aggregator.d.ts +86 -0
  202. package/dist/db-package/migration/aggregator.js +7 -0
  203. package/dist/db-package/migration/aggregator.js.map +1 -0
  204. package/dist/db-package/migration/index.d.ts +3 -0
  205. package/dist/db-package/migration/index.js +8 -0
  206. package/dist/db-package/migration/index.js.map +1 -0
  207. package/dist/engine.d.ts +205 -0
  208. package/dist/engine.js +20 -0
  209. package/dist/engine.js.map +1 -0
  210. package/dist/entitlements/index.d.ts +313 -0
  211. package/dist/entitlements/index.js +23 -0
  212. package/dist/entitlements/index.js.map +1 -0
  213. package/dist/execution/chat.d.ts +7 -0
  214. package/dist/execution/chat.js +7 -0
  215. package/dist/execution/chat.js.map +1 -0
  216. package/dist/execution/index.d.ts +342 -0
  217. package/dist/execution/index.js +66 -0
  218. package/dist/execution/index.js.map +1 -0
  219. package/dist/execution/tool-agent.d.ts +7 -0
  220. package/dist/execution/tool-agent.js +8 -0
  221. package/dist/execution/tool-agent.js.map +1 -0
  222. package/dist/extensions/index.d.ts +172 -0
  223. package/dist/extensions/index.js +95 -0
  224. package/dist/extensions/index.js.map +1 -0
  225. package/dist/health/index.d.ts +35 -0
  226. package/dist/health/index.js +7 -0
  227. package/dist/health/index.js.map +1 -0
  228. package/dist/index.d.ts +43 -0
  229. package/dist/index.js +161 -0
  230. package/dist/index.js.map +1 -0
  231. package/dist/lifecycle/index.d.ts +133 -0
  232. package/dist/lifecycle/index.js +13 -0
  233. package/dist/lifecycle/index.js.map +1 -0
  234. package/dist/lifecycle-engine/backend-migration.d.ts +2 -0
  235. package/dist/lifecycle-engine/backend-migration.js +11 -0
  236. package/dist/lifecycle-engine/backend-migration.js.map +1 -0
  237. package/dist/lifecycle-engine/baseline.d.ts +2 -0
  238. package/dist/lifecycle-engine/baseline.js +9 -0
  239. package/dist/lifecycle-engine/baseline.js.map +1 -0
  240. package/dist/lifecycle-engine/index.d.ts +1497 -0
  241. package/dist/lifecycle-engine/index.js +41 -0
  242. package/dist/lifecycle-engine/index.js.map +1 -0
  243. package/dist/lifecycle-engine/platform/artifacts.d.ts +4 -0
  244. package/dist/lifecycle-engine/platform/artifacts.js +7 -0
  245. package/dist/lifecycle-engine/platform/artifacts.js.map +1 -0
  246. package/dist/lifecycle-engine/platform/control-plane.d.ts +12 -0
  247. package/dist/lifecycle-engine/platform/control-plane.js +2 -0
  248. package/dist/lifecycle-engine/platform/control-plane.js.map +1 -0
  249. package/dist/lifecycle-engine/platform/database-router.d.ts +118 -0
  250. package/dist/lifecycle-engine/platform/database-router.js +7 -0
  251. package/dist/lifecycle-engine/platform/database-router.js.map +1 -0
  252. package/dist/lifecycle-engine/platform/deployment-placements.d.ts +464 -0
  253. package/dist/lifecycle-engine/platform/deployment-placements.js +16 -0
  254. package/dist/lifecycle-engine/platform/deployment-placements.js.map +1 -0
  255. package/dist/lifecycle-engine/platform/deployment.d.ts +4 -0
  256. package/dist/lifecycle-engine/platform/deployment.js +17 -0
  257. package/dist/lifecycle-engine/platform/deployment.js.map +1 -0
  258. package/dist/lifecycle-engine/platform/index.d.ts +737 -0
  259. package/dist/lifecycle-engine/platform/index.js +60 -0
  260. package/dist/lifecycle-engine/platform/index.js.map +1 -0
  261. package/dist/lifecycle-engine/platform/runtime.d.ts +80 -0
  262. package/dist/lifecycle-engine/platform/runtime.js +11 -0
  263. package/dist/lifecycle-engine/platform/runtime.js.map +1 -0
  264. package/dist/lifecycle-engine/platform/site-publication.d.ts +102 -0
  265. package/dist/lifecycle-engine/platform/site-publication.js +7 -0
  266. package/dist/lifecycle-engine/platform/site-publication.js.map +1 -0
  267. package/dist/lifecycle-engine/platform/user-directory.d.ts +139 -0
  268. package/dist/lifecycle-engine/platform/user-directory.js +13 -0
  269. package/dist/lifecycle-engine/platform/user-directory.js.map +1 -0
  270. package/dist/mcp.d.ts +92 -0
  271. package/dist/mcp.js +10 -0
  272. package/dist/mcp.js.map +1 -0
  273. package/dist/middleware/auth.d.ts +118 -0
  274. package/dist/middleware/auth.js +7 -0
  275. package/dist/middleware/auth.js.map +1 -0
  276. package/dist/middleware/error-handler.d.ts +35 -0
  277. package/dist/middleware/error-handler.js +7 -0
  278. package/dist/middleware/error-handler.js.map +1 -0
  279. package/dist/middleware/module-guard.d.ts +33 -0
  280. package/dist/middleware/module-guard.js +7 -0
  281. package/dist/middleware/module-guard.js.map +1 -0
  282. package/dist/platform-admin/index.d.ts +37 -0
  283. package/dist/platform-admin/index.js +11 -0
  284. package/dist/platform-admin/index.js.map +1 -0
  285. package/dist/platform-admin/store.d.ts +346 -0
  286. package/dist/platform-admin/store.js +7 -0
  287. package/dist/platform-admin/store.js.map +1 -0
  288. package/dist/plugin-data/annotations.d.ts +6 -0
  289. package/dist/plugin-data/annotations.js +12 -0
  290. package/dist/plugin-data/annotations.js.map +1 -0
  291. package/dist/plugin-data/atomic-context.d.ts +41 -0
  292. package/dist/plugin-data/atomic-context.js +9 -0
  293. package/dist/plugin-data/atomic-context.js.map +1 -0
  294. package/dist/plugin-data/atomic.d.ts +6 -0
  295. package/dist/plugin-data/atomic.js +26 -0
  296. package/dist/plugin-data/atomic.js.map +1 -0
  297. package/dist/plugin-data/audit.d.ts +6 -0
  298. package/dist/plugin-data/audit.js +12 -0
  299. package/dist/plugin-data/audit.js.map +1 -0
  300. package/dist/plugin-data/commands.d.ts +6 -0
  301. package/dist/plugin-data/commands.js +8 -0
  302. package/dist/plugin-data/commands.js.map +1 -0
  303. package/dist/plugin-data/composite.d.ts +6 -0
  304. package/dist/plugin-data/composite.js +8 -0
  305. package/dist/plugin-data/composite.js.map +1 -0
  306. package/dist/plugin-data/delivery.d.ts +6 -0
  307. package/dist/plugin-data/delivery.js +16 -0
  308. package/dist/plugin-data/delivery.js.map +1 -0
  309. package/dist/plugin-data/index.d.ts +2798 -0
  310. package/dist/plugin-data/index.js +102 -0
  311. package/dist/plugin-data/index.js.map +1 -0
  312. package/dist/plugin-data/json-documents.d.ts +6 -0
  313. package/dist/plugin-data/json-documents.js +16 -0
  314. package/dist/plugin-data/json-documents.js.map +1 -0
  315. package/dist/plugin-data/outbox.d.ts +6 -0
  316. package/dist/plugin-data/outbox.js +16 -0
  317. package/dist/plugin-data/outbox.js.map +1 -0
  318. package/dist/plugin-data/scoped-records.d.ts +6 -0
  319. package/dist/plugin-data/scoped-records.js +10 -0
  320. package/dist/plugin-data/scoped-records.js.map +1 -0
  321. package/dist/plugin-sdk.d.ts +41 -0
  322. package/dist/plugin-sdk.js +10 -0
  323. package/dist/plugin-sdk.js.map +1 -0
  324. package/dist/sql-lifecycle/index.d.ts +138 -0
  325. package/dist/sql-lifecycle/index.js +167 -0
  326. package/dist/sql-lifecycle/index.js.map +1 -0
  327. package/dist/storage/index.d.ts +2 -0
  328. package/dist/storage/index.js +13 -0
  329. package/dist/storage/index.js.map +1 -0
  330. package/dist/storage/s3-compatible.d.ts +139 -0
  331. package/dist/storage/s3-compatible.js +11 -0
  332. package/dist/storage/s3-compatible.js.map +1 -0
  333. package/dist/tenant.d.ts +108 -0
  334. package/dist/tenant.js +9 -0
  335. package/dist/tenant.js.map +1 -0
  336. package/dist/workspace-context.d.ts +119 -0
  337. package/dist/workspace-context.js +9 -0
  338. package/dist/workspace-context.js.map +1 -0
  339. package/docs/api.md +30560 -0
  340. package/docs/db/README.md +49 -0
  341. package/docs/db/docs/api.md +1613 -0
  342. package/docs/db/docs/guide.md +47 -0
  343. package/docs/entitlements.md +60 -0
  344. package/docs/guide.md +92 -0
  345. package/docs/index.md +57 -0
  346. package/docs/ja/db/README.md +46 -0
  347. package/docs/ja/db/docs/guide.md +53 -0
  348. package/docs/ja/guide.md +46 -0
  349. package/docs/ja/lifecycle/README.md +46 -0
  350. package/docs/ja/lifecycle/docs/guide.md +45 -0
  351. package/docs/ja/storage/README.md +46 -0
  352. package/docs/ja/storage/docs/guide.md +43 -0
  353. package/docs/lifecycle/README.md +49 -0
  354. package/docs/lifecycle/docs/api.md +3770 -0
  355. package/docs/lifecycle/docs/baseline.md +50 -0
  356. package/docs/lifecycle/docs/guide.md +47 -0
  357. package/docs/storage/README.md +49 -0
  358. package/docs/storage/docs/api.md +470 -0
  359. package/docs/storage/docs/guide.md +47 -0
  360. package/package.json +354 -4
@@ -0,0 +1,223 @@
1
+ import {
2
+ assertPrincipal,
3
+ atomicHash
4
+ } from "./chunk-INCHXAFK.js";
5
+
6
+ // src/agentic/atomic-checkpointer.ts
7
+ import { BaseCheckpointSaver } from "@langchain/langgraph";
8
+ var specialWrites = { __error__: -1, __scheduled__: -2, __interrupt__: -3, __resume__: -4 };
9
+ function identifier(value, empty = false) {
10
+ if (typeof value !== "string" || !empty && !value || value.length > 512 || [...value].some((c) => c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127)) throw Error("Invalid checkpoint identifier");
11
+ return value;
12
+ }
13
+ var AtomicCheckpointSaver = class extends BaseCheckpointSaver {
14
+ /**
15
+ * Captures a verified plugin principal and required current-admission callback.
16
+ * @param options - Scoped repository; principal is validated/cloned; verifyCurrent must reject on revoked admission; prefix defaults to graph-checkpoint and must contain 1–64 lowercase letters/digits/underscore/hyphen.
17
+ * @throws Invalid principal, absent repository/verifier, invalid prefix, or clone failure.
18
+ */
19
+ constructor(options) {
20
+ super();
21
+ this.options = options;
22
+ assertPrincipal(options.principal);
23
+ this.principal = structuredClone(options.principal);
24
+ if (!options.repository || typeof options.verifyCurrent !== "function" || !/^[a-z0-9_-]{1,64}$/.test(options.prefix ?? "graph-checkpoint")) throw Error("Scoped checkpoint repository and current verifier required");
25
+ }
26
+ options;
27
+ principal;
28
+ pending = Promise.resolve();
29
+ scope(config) {
30
+ const threadId = identifier(config.configurable?.thread_id), namespace = identifier(config.configurable?.checkpoint_ns ?? "", true);
31
+ const checkpointId = config.configurable?.checkpoint_id === void 0 ? void 0 : identifier(config.configurable.checkpoint_id);
32
+ const prefix = `${this.options.prefix ?? "graph-checkpoint"}/${atomicHash([threadId, namespace])}/`;
33
+ return { threadId, namespace, checkpointId, prefix };
34
+ }
35
+ config(s, id) {
36
+ return { configurable: { thread_id: s.threadId, checkpoint_ns: s.namespace, checkpoint_id: id } };
37
+ }
38
+ async encode(value) {
39
+ const [kind, bytes] = await this.serde.dumpsTyped(value);
40
+ return [kind, Buffer.from(bytes).toString("base64")];
41
+ }
42
+ async decode(value) {
43
+ return this.serde.loadsTyped(value[0], Buffer.from(value[1], "base64"));
44
+ }
45
+ async run(work) {
46
+ const result = this.pending.then(async () => {
47
+ await this.options.verifyCurrent();
48
+ return this.options.repository.run(this.principal, async (tx) => {
49
+ await this.options.verifyCurrent();
50
+ const result2 = await work(tx);
51
+ await this.options.verifyCurrent();
52
+ return result2;
53
+ });
54
+ });
55
+ this.pending = result.then(() => void 0, () => void 0);
56
+ return result;
57
+ }
58
+ async tuple(v, s) {
59
+ if (v.tenantId !== this.principal.tenantId || v.threadId !== s.threadId || v.namespace !== s.namespace) throw Error("Checkpoint identity differs");
60
+ const checkpoint = await this.decode(v.checkpoint);
61
+ if (checkpoint.id !== v.checkpointId || checkpoint.v !== 4) throw Error("Checkpoint format or identity differs");
62
+ return {
63
+ config: this.config(s, v.checkpointId),
64
+ checkpoint,
65
+ metadata: await this.decode(v.metadata),
66
+ ...v.parentId ? { parentConfig: this.config(s, v.parentId) } : {},
67
+ pendingWrites: await Promise.all(v.writes.map(async (w) => [w.taskId, w.channel, await this.decode(w.value)]))
68
+ };
69
+ }
70
+ /**
71
+ * Reads one scoped checkpoint and its separately stored pending writes.
72
+ * @param config - LangGraph config with required thread_id, optional checkpoint_ns (default empty), and optional checkpoint_id (default latest lexicographic ID). Identifiers are bounded to 512 characters without control characters.
73
+ * @returns Decoded checkpoint tuple or undefined if no selected checkpoint exists.
74
+ * @throws Rejects invalid identifiers, tenant/thread/namespace or format mismatch, and admission/repository/serialization failures.
75
+ * @example
76
+ * ```typescript
77
+ * import { AtomicCheckpointSaver } from "@alneas/eaos-server/agentic/atomic-checkpointer";
78
+ * export async function read(saver: AtomicCheckpointSaver, config: Parameters<AtomicCheckpointSaver["getTuple"]>[0]) { return saver.getTuple(config); }
79
+ * ```
80
+ */
81
+ async getTuple(config) {
82
+ const s = this.scope(config);
83
+ return this.run(async (tx) => {
84
+ const id = s.checkpointId ?? (await tx.get(s.prefix + "latest"))?.value.id;
85
+ if (!id) return void 0;
86
+ const row = await tx.get(s.prefix + "item-" + id);
87
+ if (!row) return void 0;
88
+ const writes = await tx.get(s.prefix + "writes-" + id);
89
+ if (writes && (writes.value.tenantId !== this.principal.tenantId || writes.value.threadId !== s.threadId || writes.value.namespace !== s.namespace || writes.value.checkpointId !== id)) throw Error("Pending write identity differs");
90
+ return this.tuple({ ...row.value, writes: writes?.value.writes ?? [] }, s);
91
+ });
92
+ }
93
+ /**
94
+ * Lists scoped checkpoint history in descending lexicographic checkpoint-ID order.
95
+ * @param config - Required thread scope, optional namespace, and optional exact checkpoint ID filter.
96
+ * @param options - limit defaults to 100 and must be a safe integer 1–2000; before must use the same thread/namespace and excludes its ID and newer IDs; filter compares metadata fields by atomic hash.
97
+ * @returns Async sequence of decoded tuples, possibly empty, with admission rechecked before each yield.
98
+ * @throws Iteration rejects invalid scope/limits, more than 2000 scanned checkpoint rows, identity/format mismatch, or admission/repository/serialization errors.
99
+ * @remarks History is collected in a bounded repository transaction before yielding; changing authorization can still stop later yields.
100
+ * @example
101
+ * ```typescript
102
+ * import { AtomicCheckpointSaver } from "@alneas/eaos-server/agentic/atomic-checkpointer";
103
+ * export async function history(saver: AtomicCheckpointSaver, config: Parameters<AtomicCheckpointSaver["list"]>[0]) {
104
+ * const tuples = [];
105
+ * for await (const tuple of saver.list(config, { limit: 10 })) tuples.push(tuple);
106
+ * return tuples;
107
+ * }
108
+ * ```
109
+ */
110
+ async *list(config, options = {}) {
111
+ const s = this.scope(config), limit = options?.limit ?? 100, before = options?.before ? this.scope(options.before) : void 0;
112
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > 2e3 || before && (before.threadId !== s.threadId || before.namespace !== s.namespace)) throw Error("Invalid scoped checkpoint history request");
113
+ const values = await this.run(async (tx) => {
114
+ const rows = [];
115
+ let after = "";
116
+ while (true) {
117
+ const page = await tx.list(s.prefix + "item-", after, 100);
118
+ rows.push(...page.map((r) => r.value));
119
+ if (rows.length > 2e3) throw Error("Checkpoint history exceeds bounded capacity");
120
+ if (page.length < 100) break;
121
+ after = page.at(-1).id;
122
+ }
123
+ const out = [];
124
+ for (const value of rows.sort((a, b) => b.checkpointId.localeCompare(a.checkpointId))) {
125
+ if (s.checkpointId && value.checkpointId !== s.checkpointId || before?.checkpointId && value.checkpointId >= before.checkpointId) continue;
126
+ const writes = await tx.get(s.prefix + "writes-" + value.checkpointId);
127
+ if (writes && (writes.value.tenantId !== this.principal.tenantId || writes.value.threadId !== s.threadId || writes.value.namespace !== s.namespace || writes.value.checkpointId !== value.checkpointId)) throw Error("Pending write identity differs");
128
+ const tuple = await this.tuple({ ...value, writes: writes?.value.writes ?? [] }, s);
129
+ if (options?.filter && Object.entries(options.filter).some(([k, v]) => atomicHash(tuple.metadata?.[k] ?? null) !== atomicHash(v ?? null))) continue;
130
+ out.push(tuple);
131
+ if (out.length === limit) break;
132
+ }
133
+ return out;
134
+ });
135
+ for (const value of values) {
136
+ await this.options.verifyCurrent();
137
+ yield value;
138
+ }
139
+ }
140
+ /**
141
+ * Writes an immutable version-4 checkpoint and advances the scoped latest pointer when its ID sorts later.
142
+ * @param config - Thread/namespace scope; optional checkpoint_id becomes the new checkpoint's parent ID.
143
+ * @param checkpoint - Current LangGraph version-4 checkpoint with valid nonempty bounded ID.
144
+ * @param metadata - Serializer-supported checkpoint metadata.
145
+ * @returns A config selecting the stored checkpoint ID.
146
+ * @throws Rejects unsupported format, ID reuse with different content, admission/CAS/repository errors, or serialization failures.
147
+ * @remarks Repeating identical content is accepted; latest ordering is lexicographic, so host checkpoint IDs must reflect desired chronology.
148
+ * @example
149
+ * ```typescript
150
+ * import { AtomicCheckpointSaver } from "@alneas/eaos-server/agentic/atomic-checkpointer";
151
+ * export async function write(saver: AtomicCheckpointSaver, ...args: Parameters<AtomicCheckpointSaver["put"]>) { return saver.put(...args); }
152
+ * ```
153
+ */
154
+ async put(config, checkpoint, metadata) {
155
+ const s = this.scope(config), id = identifier(checkpoint.id);
156
+ if (checkpoint.v !== 4) throw Error("Only the current LangGraph checkpoint format is supported");
157
+ const checkpointBytes = await this.encode(checkpoint), metadataBytes = await this.encode(metadata);
158
+ await this.run(async (tx) => {
159
+ const key = s.prefix + "item-" + id, existing = await tx.get(key);
160
+ const value = { tenantId: this.principal.tenantId, threadId: s.threadId, namespace: s.namespace, checkpointId: id, checkpoint: checkpointBytes, metadata: metadataBytes, ...s.checkpointId ? { parentId: s.checkpointId } : {}, writes: existing?.value.writes ?? [] };
161
+ if (existing && atomicHash({ ...existing.value, writes: [] }) !== atomicHash({ ...value, writes: [] })) throw Error("Checkpoint ID reused with different content");
162
+ if (!existing) await tx.put(key, value, 0);
163
+ const latest = await tx.get(s.prefix + "latest");
164
+ if (!latest || id > latest.value.id) await tx.put(s.prefix + "latest", { id }, latest?.revision ?? 0);
165
+ });
166
+ return this.config(s, id);
167
+ }
168
+ /**
169
+ * Merges pending channel writes by task/index for one scoped checkpoint.
170
+ * @param config - Thread/namespace with required checkpoint_id.
171
+ * @param writes - At most 256 channel/value pairs; channels are valid bounded identifiers. Ordinary task/index duplicates retain their first value; reserved negative-index channels replace prior values.
172
+ * @param taskId - Nonempty bounded task identifier associating writes.
173
+ * @returns No value; resolves after the merged writes are durably stored.
174
+ * @throws Rejects missing checkpoint ID, invalid task/channel, identity mismatch, more than 2000 stored pending writes, or admission/repository/serialization errors.
175
+ * @example
176
+ * ```typescript
177
+ * import { AtomicCheckpointSaver } from "@alneas/eaos-server/agentic/atomic-checkpointer";
178
+ * export async function writePending(saver: AtomicCheckpointSaver, ...args: Parameters<AtomicCheckpointSaver["putWrites"]>) { await saver.putWrites(...args); }
179
+ * ```
180
+ */
181
+ async putWrites(config, writes, taskId) {
182
+ const s = this.scope(config);
183
+ identifier(taskId);
184
+ if (!s.checkpointId || !Array.isArray(writes) || writes.length > 256) throw Error("Checkpoint and bounded writes required");
185
+ const prepared = await Promise.all(writes.map(async ([channel, value], index) => ({ taskId, index: Object.hasOwn(specialWrites, channel) ? specialWrites[channel] : index, channel: identifier(channel), value: await this.encode(value) })));
186
+ await this.run(async (tx) => {
187
+ const key = s.prefix + "writes-" + s.checkpointId, row = await tx.get(key);
188
+ if (row && (row.value.tenantId !== this.principal.tenantId || row.value.threadId !== s.threadId || row.value.namespace !== s.namespace || row.value.checkpointId !== s.checkpointId)) throw Error("Pending write identity differs");
189
+ const value = row ? structuredClone(row.value) : { tenantId: this.principal.tenantId, threadId: s.threadId, namespace: s.namespace, checkpointId: s.checkpointId, writes: [] };
190
+ for (const write of prepared) {
191
+ const index = value.writes.findIndex((w) => w.taskId === taskId && w.index === write.index);
192
+ if (index < 0) value.writes.push(write);
193
+ else if (write.index < 0) value.writes[index] = write;
194
+ }
195
+ if (value.writes.length > 2e3) throw Error("Checkpoint pending writes exceed bounded capacity");
196
+ await tx.put(key, value, row?.revision ?? 0);
197
+ });
198
+ }
199
+ /**
200
+ * Rejects thread deletion because this repository contract provides no approved erasure operation.
201
+ * @param _threadId - Requested thread ID; not read or deleted.
202
+ * @returns No value; this operation always rejects before performing storage work.
203
+ * @throws Always rejects with an error directing the caller to the host retention executor.
204
+ * @example
205
+ * ```typescript
206
+ * import { AtomicCheckpointSaver } from "@alneas/eaos-server/agentic/atomic-checkpointer";
207
+ * export async function erase(saver: AtomicCheckpointSaver, threadId: string) {
208
+ * try { await saver.deleteThread(threadId); } catch (error) {
209
+ * // Host retention tooling must perform reviewed erasure.
210
+ * throw error;
211
+ * }
212
+ * }
213
+ * ```
214
+ */
215
+ async deleteThread(_threadId) {
216
+ throw Error("Checkpoint erasure requires the host retention executor; this repository exposes no delete contract");
217
+ }
218
+ };
219
+
220
+ export {
221
+ AtomicCheckpointSaver
222
+ };
223
+ //# sourceMappingURL=chunk-3NLSWP2Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/atomic-checkpointer.ts"],"sourcesContent":["import { BaseCheckpointSaver, type Checkpoint, type CheckpointMetadata, type CheckpointTuple } from '@langchain/langgraph'\nimport { atomicHash, type AtomicRepository, type AtomicSession } from '../plugin-data/atomic'\nimport { assertPrincipal, type PluginPrincipal } from '../plugin-data/index'\n\ntype Config = Parameters<BaseCheckpointSaver['getTuple']>[0]\ntype ListOptions = Parameters<BaseCheckpointSaver['list']>[1]\ntype Writes = Parameters<BaseCheckpointSaver['putWrites']>[1]\ntype Encoded = [string, string]\ninterface StoredCheckpoint {\n tenantId: string; threadId: string; namespace: string; checkpointId: string\n checkpoint: Encoded; metadata: Encoded; parentId?: string\n writes: Array<{ taskId: string; index: number; channel: string; value: Encoded }>\n}\nconst specialWrites: Record<string, number> = { __error__: -1, __scheduled__: -2, __interrupt__: -3, __resume__: -4 }\nfunction identifier(value: unknown, empty = false): string {\n if (typeof value !== 'string' || (!empty && !value) || value.length > 512 || [...value].some(c => c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127)) throw Error('Invalid checkpoint identifier')\n return value\n}\n\n/**\n * Stores LangGraph checkpoints and pending writes in an existing scoped atomic repository.\n * @remarks Admission and workflow writer serialization remain host-owned. Each saver instance serializes repository work through an internal Promise chain and calls verifyCurrent before the transaction and before/after its work. This does not serialize other saver instances or whole graph invocations. The repository owns durability/CAS; this saver installs no timers and does not close host storage. Checkpoint erasure requires a separate host retention executor.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export function saver(options: ConstructorParameters<typeof AtomicCheckpointSaver>[0]) {\n * return new AtomicCheckpointSaver(options);\n * }\n * ```\n */\nexport class AtomicCheckpointSaver extends BaseCheckpointSaver {\n private readonly principal: PluginPrincipal\n private pending: Promise<void> = Promise.resolve()\n /**\n * Captures a verified plugin principal and required current-admission callback.\n * @param options - Scoped repository; principal is validated/cloned; verifyCurrent must reject on revoked admission; prefix defaults to graph-checkpoint and must contain 1–64 lowercase letters/digits/underscore/hyphen.\n * @throws Invalid principal, absent repository/verifier, invalid prefix, or clone failure.\n */\n constructor(private readonly options: { \n /**\n * Connected host atomic repository used for scoped checkpoint and pending-write transactions; this saver does not close it.\n */\n repository: AtomicRepository; \n /**\n * Verified plugin principal validated and cloned at construction; fixes the tenant/plugin/user scope used for repository transactions.\n */\n principal: PluginPrincipal; \n /**\n * Recheck current host admission before repository work and at transaction boundaries.\n * @returns No value; resolve only while the captured principal remains admitted and reject when admission is revoked.\n * @remarks Required callback; called before the repository transaction and before/after its work, and before each history yield. The host owns the live policy lookup.\n * @see {@link AtomicCheckpointSaver}\n */\n verifyCurrent: () => Promise<void>; \n /**\n * Optional repository key prefix; defaults to graph-checkpoint and must contain 1–64 lowercase letters, digits, underscores or hyphens.\n */\n prefix?: string }) {\n super(); assertPrincipal(options.principal); this.principal = structuredClone(options.principal)\n if (!options.repository || typeof options.verifyCurrent !== 'function' || !/^[a-z0-9_-]{1,64}$/.test(options.prefix ?? 'graph-checkpoint')) throw Error('Scoped checkpoint repository and current verifier required')\n }\n private scope(config: Config) {\n const threadId = identifier(config.configurable?.thread_id), namespace = identifier(config.configurable?.checkpoint_ns ?? '', true)\n const checkpointId = config.configurable?.checkpoint_id === undefined ? undefined : identifier(config.configurable.checkpoint_id)\n const prefix = `${this.options.prefix ?? 'graph-checkpoint'}/${atomicHash([threadId, namespace])}/`\n return { threadId, namespace, checkpointId, prefix }\n }\n private config(s: ReturnType<AtomicCheckpointSaver['scope']>, id: string): Config { return { configurable: { thread_id: s.threadId, checkpoint_ns: s.namespace, checkpoint_id: id } } }\n private async encode(value: unknown): Promise<Encoded> { const [kind, bytes] = await this.serde.dumpsTyped(value); return [kind, Buffer.from(bytes).toString('base64')] }\n private async decode(value: Encoded) { return this.serde.loadsTyped(value[0], Buffer.from(value[1], 'base64')) }\n private async run<T>(work: (tx: AtomicSession) => Promise<T>): Promise<T> {\n const result = this.pending.then(async () => {\n await this.options.verifyCurrent()\n return this.options.repository.run(this.principal, async tx => { await this.options.verifyCurrent(); const result = await work(tx); await this.options.verifyCurrent(); return result })\n })\n this.pending = result.then(() => undefined, () => undefined)\n return result\n }\n private async tuple(v: StoredCheckpoint, s: ReturnType<AtomicCheckpointSaver['scope']>): Promise<CheckpointTuple> {\n if (v.tenantId !== this.principal.tenantId || v.threadId !== s.threadId || v.namespace !== s.namespace) throw Error('Checkpoint identity differs')\n const checkpoint = await this.decode(v.checkpoint) as Checkpoint\n if (checkpoint.id !== v.checkpointId || checkpoint.v !== 4) throw Error('Checkpoint format or identity differs')\n return { config: this.config(s, v.checkpointId), checkpoint, metadata: await this.decode(v.metadata) as CheckpointMetadata,\n ...(v.parentId ? { parentConfig: this.config(s, v.parentId) } : {}),\n pendingWrites: await Promise.all(v.writes.map(async w => [w.taskId, w.channel, await this.decode(w.value)] as [string, string, unknown])) }\n }\n /**\n * Reads one scoped checkpoint and its separately stored pending writes.\n * @param config - LangGraph config with required thread_id, optional checkpoint_ns (default empty), and optional checkpoint_id (default latest lexicographic ID). Identifiers are bounded to 512 characters without control characters.\n * @returns Decoded checkpoint tuple or undefined if no selected checkpoint exists.\n * @throws Rejects invalid identifiers, tenant/thread/namespace or format mismatch, and admission/repository/serialization failures.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export async function read(saver: AtomicCheckpointSaver, config: Parameters<AtomicCheckpointSaver[\"getTuple\"]>[0]) { return saver.getTuple(config); }\n * ```\n */\n async getTuple(config: Config): Promise<CheckpointTuple | undefined> {\n const s = this.scope(config)\n return this.run(async tx => {\n const id = s.checkpointId ?? (await tx.get<{ id: string }>(s.prefix + 'latest'))?.value.id\n if (!id) return undefined\n const row = await tx.get<StoredCheckpoint>(s.prefix + 'item-' + id)\n if (!row) return undefined\n const writes = await tx.get<Pick<StoredCheckpoint, 'tenantId' | 'threadId' | 'namespace' | 'checkpointId' | 'writes'>>(s.prefix + 'writes-' + id)\n if (writes && (writes.value.tenantId !== this.principal.tenantId || writes.value.threadId !== s.threadId || writes.value.namespace !== s.namespace || writes.value.checkpointId !== id)) throw Error('Pending write identity differs')\n return this.tuple({ ...row.value, writes: writes?.value.writes ?? [] }, s)\n })\n }\n /**\n * Lists scoped checkpoint history in descending lexicographic checkpoint-ID order.\n * @param config - Required thread scope, optional namespace, and optional exact checkpoint ID filter.\n * @param options - limit defaults to 100 and must be a safe integer 1–2000; before must use the same thread/namespace and excludes its ID and newer IDs; filter compares metadata fields by atomic hash.\n * @returns Async sequence of decoded tuples, possibly empty, with admission rechecked before each yield.\n * @throws Iteration rejects invalid scope/limits, more than 2000 scanned checkpoint rows, identity/format mismatch, or admission/repository/serialization errors.\n * @remarks History is collected in a bounded repository transaction before yielding; changing authorization can still stop later yields.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export async function history(saver: AtomicCheckpointSaver, config: Parameters<AtomicCheckpointSaver[\"list\"]>[0]) {\n * const tuples = [];\n * for await (const tuple of saver.list(config, { limit: 10 })) tuples.push(tuple);\n * return tuples;\n * }\n * ```\n */\n async *list(config: Config, options: ListOptions = {}): AsyncGenerator<CheckpointTuple> {\n const s = this.scope(config), limit = options?.limit ?? 100, before = options?.before ? this.scope(options.before) : undefined\n if (!Number.isSafeInteger(limit) || limit < 1 || limit > 2000 || before && (before.threadId !== s.threadId || before.namespace !== s.namespace)) throw Error('Invalid scoped checkpoint history request')\n const values = await this.run(async tx => {\n const rows: StoredCheckpoint[] = []; let after = ''\n while (true) { const page = await tx.list<StoredCheckpoint>(s.prefix + 'item-', after, 100); rows.push(...page.map(r => r.value)); if (rows.length > 2000) throw Error('Checkpoint history exceeds bounded capacity'); if (page.length < 100) break; after = page.at(-1)!.id }\n const out: CheckpointTuple[] = []\n for (const value of rows.sort((a, b) => b.checkpointId.localeCompare(a.checkpointId))) {\n if (s.checkpointId && value.checkpointId !== s.checkpointId || before?.checkpointId && value.checkpointId >= before.checkpointId) continue\n const writes = await tx.get<Pick<StoredCheckpoint, 'tenantId' | 'threadId' | 'namespace' | 'checkpointId' | 'writes'>>(s.prefix + 'writes-' + value.checkpointId)\n if (writes && (writes.value.tenantId !== this.principal.tenantId || writes.value.threadId !== s.threadId || writes.value.namespace !== s.namespace || writes.value.checkpointId !== value.checkpointId)) throw Error('Pending write identity differs')\n const tuple = await this.tuple({ ...value, writes: writes?.value.writes ?? [] }, s)\n if (options?.filter && Object.entries(options.filter).some(([k, v]) => atomicHash((tuple.metadata as any)?.[k] ?? null) !== atomicHash(v ?? null))) continue\n out.push(tuple); if (out.length === limit) break\n }\n return out\n })\n for (const value of values) { await this.options.verifyCurrent(); yield value }\n }\n /**\n * Writes an immutable version-4 checkpoint and advances the scoped latest pointer when its ID sorts later.\n * @param config - Thread/namespace scope; optional checkpoint_id becomes the new checkpoint's parent ID.\n * @param checkpoint - Current LangGraph version-4 checkpoint with valid nonempty bounded ID.\n * @param metadata - Serializer-supported checkpoint metadata.\n * @returns A config selecting the stored checkpoint ID.\n * @throws Rejects unsupported format, ID reuse with different content, admission/CAS/repository errors, or serialization failures.\n * @remarks Repeating identical content is accepted; latest ordering is lexicographic, so host checkpoint IDs must reflect desired chronology.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export async function write(saver: AtomicCheckpointSaver, ...args: Parameters<AtomicCheckpointSaver[\"put\"]>) { return saver.put(...args); }\n * ```\n */\n async put(config: Config, checkpoint: Checkpoint, metadata: CheckpointMetadata): Promise<Config> {\n const s = this.scope(config), id = identifier(checkpoint.id)\n if (checkpoint.v !== 4) throw Error('Only the current LangGraph checkpoint format is supported')\n const checkpointBytes = await this.encode(checkpoint), metadataBytes = await this.encode(metadata)\n await this.run(async tx => {\n const key = s.prefix + 'item-' + id, existing = await tx.get<StoredCheckpoint>(key)\n const value: StoredCheckpoint = { tenantId: this.principal.tenantId, threadId: s.threadId, namespace: s.namespace, checkpointId: id, checkpoint: checkpointBytes, metadata: metadataBytes, ...(s.checkpointId ? { parentId: s.checkpointId } : {}), writes: existing?.value.writes ?? [] }\n if (existing && atomicHash({ ...existing.value, writes: [] }) !== atomicHash({ ...value, writes: [] })) throw Error('Checkpoint ID reused with different content')\n if (!existing) await tx.put(key, value, 0)\n const latest = await tx.get<{ id: string }>(s.prefix + 'latest')\n if (!latest || id > latest.value.id) await tx.put(s.prefix + 'latest', { id }, latest?.revision ?? 0)\n })\n return this.config(s, id)\n }\n /**\n * Merges pending channel writes by task/index for one scoped checkpoint.\n * @param config - Thread/namespace with required checkpoint_id.\n * @param writes - At most 256 channel/value pairs; channels are valid bounded identifiers. Ordinary task/index duplicates retain their first value; reserved negative-index channels replace prior values.\n * @param taskId - Nonempty bounded task identifier associating writes.\n * @returns No value; resolves after the merged writes are durably stored.\n * @throws Rejects missing checkpoint ID, invalid task/channel, identity mismatch, more than 2000 stored pending writes, or admission/repository/serialization errors.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export async function writePending(saver: AtomicCheckpointSaver, ...args: Parameters<AtomicCheckpointSaver[\"putWrites\"]>) { await saver.putWrites(...args); }\n * ```\n */\n async putWrites(config: Config, writes: Writes, taskId: string): Promise<void> {\n const s = this.scope(config); identifier(taskId)\n if (!s.checkpointId || !Array.isArray(writes) || writes.length > 256) throw Error('Checkpoint and bounded writes required')\n const prepared = await Promise.all(writes.map(async ([channel, value], index) => ({ taskId, index: Object.hasOwn(specialWrites, channel) ? specialWrites[channel] : index, channel: identifier(channel), value: await this.encode(value) })))\n await this.run(async tx => {\n const key = s.prefix + 'writes-' + s.checkpointId, row = await tx.get<Pick<StoredCheckpoint, 'tenantId' | 'threadId' | 'namespace' | 'checkpointId' | 'writes'>>(key)\n if (row && (row.value.tenantId !== this.principal.tenantId || row.value.threadId !== s.threadId || row.value.namespace !== s.namespace || row.value.checkpointId !== s.checkpointId)) throw Error('Pending write identity differs')\n const value = row ? structuredClone(row.value) : { tenantId: this.principal.tenantId, threadId: s.threadId, namespace: s.namespace, checkpointId: s.checkpointId, writes: [] as StoredCheckpoint['writes'] }\n for (const write of prepared) {\n const index = value.writes.findIndex(w => w.taskId === taskId && w.index === write.index)\n if (index < 0) value.writes.push(write)\n else if (write.index < 0) value.writes[index] = write\n }\n if (value.writes.length > 2000) throw Error('Checkpoint pending writes exceed bounded capacity')\n await tx.put(key, value, row?.revision ?? 0)\n })\n }\n /**\n * Rejects thread deletion because this repository contract provides no approved erasure operation.\n * @param _threadId - Requested thread ID; not read or deleted.\n * @returns No value; this operation always rejects before performing storage work.\n * @throws Always rejects with an error directing the caller to the host retention executor.\n * @example\n * ```typescript\n * import { AtomicCheckpointSaver } from \"@alneas/eaos-server/agentic/atomic-checkpointer\";\n * export async function erase(saver: AtomicCheckpointSaver, threadId: string) {\n * try { await saver.deleteThread(threadId); } catch (error) {\n * // Host retention tooling must perform reviewed erasure.\n * throw error;\n * }\n * }\n * ```\n */\n async deleteThread(_threadId: string): Promise<void> { throw Error('Checkpoint erasure requires the host retention executor; this repository exposes no delete contract') }\n}\n"],"mappings":"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","names":["result"]}
@@ -0,0 +1,346 @@
1
+ // src/agentic/event-bridge.ts
2
+ var InMemoryEventAgentTaskStore = class {
3
+ pending = /* @__PURE__ */ new Map();
4
+ claimed = /* @__PURE__ */ new Map();
5
+ completed = /* @__PURE__ */ new Map();
6
+ results = /* @__PURE__ */ new Map();
7
+ maxTasks;
8
+ /**
9
+ * Creates an empty local queue with an active pending/claimed capacity limit.
10
+ * @param options - maxTasks defaults to 10000 and must be a safe integer 1–1000000.
11
+ * @throws Invalid capacity.
12
+ */
13
+ constructor(options = {}) {
14
+ this.maxTasks = options.maxTasks ?? 1e4;
15
+ if (!Number.isSafeInteger(this.maxTasks) || this.maxTasks < 1 || this.maxTasks > 1e6) throw new Error("Invalid in-memory agent task store limit");
16
+ }
17
+ /**
18
+ * Clones a queued task unless its ID is already identically retained.
19
+ * @param task - Nonempty task ID and event name with structured-cloneable payload/task.
20
+ * @returns No value; resolves after local insertion or matching duplicate detection.
21
+ * @throws Missing identifiers, conflicting duplicate, active capacity exhaustion, or clone/JSON failure.
22
+ * @example
23
+ * ```typescript
24
+ * import { InMemoryEventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
25
+ * import type { QueuedEventTask } from "@alneas/eaos-server/agentic/event-bridge";
26
+ * export async function enqueue(store: InMemoryEventAgentTaskStore, task: QueuedEventTask) { await store.enqueue(task); }
27
+ * ```
28
+ */
29
+ async enqueue(task) {
30
+ if (!task?.task?.id || !task.eventName) throw new Error("Invalid queued event task");
31
+ const existing = this.pending.get(task.task.id) ?? this.claimed.get(task.task.id) ?? this.completed.get(task.task.id);
32
+ if (existing) {
33
+ if (JSON.stringify(existing) !== JSON.stringify(task)) throw new Error("Conflicting duplicate event agent task");
34
+ return;
35
+ }
36
+ if (this.pending.size + this.claimed.size >= this.maxTasks) throw new Error("In-memory agent task store is full");
37
+ this.pending.set(task.task.id, structuredClone(task));
38
+ }
39
+ /**
40
+ * Moves pending items into the claimed map in insertion order.
41
+ * @param limit - Positive safe-integer maximum item count.
42
+ * @returns Cloned claimed items, or an empty array.
43
+ * @throws Invalid limit or clone failure; an item may already have moved before clone failure.
44
+ * @example
45
+ * ```typescript
46
+ * import { InMemoryEventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
47
+ * const store = new InMemoryEventAgentTaskStore();
48
+ * console.log(await store.claim(1)); // []
49
+ * ```
50
+ */
51
+ async claim(limit) {
52
+ if (!Number.isSafeInteger(limit) || limit < 1) throw new Error("Invalid in-memory agent task claim limit");
53
+ const claimed = [];
54
+ for (const [taskId, task] of this.pending) {
55
+ this.pending.delete(taskId);
56
+ this.claimed.set(taskId, task);
57
+ claimed.push(structuredClone(task));
58
+ if (claimed.length >= limit) break;
59
+ }
60
+ return claimed;
61
+ }
62
+ /**
63
+ * Moves a claimed task into retained completion history and clones its result.
64
+ * @param taskId - Current claimed task identifier.
65
+ * @param result - Normalized runtime outcome, including FAILED or PENDING_APPROVAL data.
66
+ * @returns No value; completes after retaining history and result.
67
+ * @throws Unknown/already completed task or clone failure; history can already have changed.
68
+ * @example
69
+ * ```typescript
70
+ * import { InMemoryEventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
71
+ * import type { ServerAgentTaskResult } from "@alneas/eaos-server/agentic/types";
72
+ * export async function complete(store: InMemoryEventAgentTaskStore, taskId: string, result: ServerAgentTaskResult) { await store.complete(taskId, result); }
73
+ * ```
74
+ */
75
+ async complete(taskId, result) {
76
+ const task = this.claimed.get(taskId);
77
+ if (!task) throw new Error("Unknown or already completed event agent task");
78
+ this.claimed.delete(taskId);
79
+ this.completed.set(taskId, task);
80
+ this.results.set(taskId, structuredClone(result));
81
+ }
82
+ /**
83
+ * Removes a claimed task without retaining failure history or rescheduling it.
84
+ * @param taskId - Current claimed task identifier.
85
+ * @param _error - Failure value accepted for interface compatibility and ignored.
86
+ * @returns No value; resolves after removal.
87
+ * @throws Unknown/already failed task.
88
+ * @example
89
+ * ```typescript
90
+ * import { InMemoryEventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
91
+ * export async function fail(store: InMemoryEventAgentTaskStore, taskId: string, error: unknown) { await store.fail(taskId, error); }
92
+ * ```
93
+ */
94
+ async fail(taskId, _error) {
95
+ if (!this.claimed.delete(taskId)) throw new Error("Unknown or already failed event agent task");
96
+ }
97
+ /**
98
+ * Inspects a cloned retained completion result for local tests/development.
99
+ * @param taskId - Previously completed task identifier.
100
+ * @returns Cloned result, or undefined if no completion result exists.
101
+ * @throws If a retained result cannot be cloned.
102
+ * @example
103
+ * ```typescript
104
+ * import { InMemoryEventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
105
+ * console.log(new InMemoryEventAgentTaskStore().getResult("missing")); // undefined
106
+ * ```
107
+ */
108
+ getResult(taskId) {
109
+ const result = this.results.get(taskId);
110
+ return result ? structuredClone(result) : void 0;
111
+ }
112
+ };
113
+ var EventAgentBridge = class {
114
+ eventBus;
115
+ worker;
116
+ rules = /* @__PURE__ */ new Map();
117
+ subscriptions = /* @__PURE__ */ new Map();
118
+ queue = [];
119
+ activeCount = 0;
120
+ maxConcurrent;
121
+ maxQueueSize;
122
+ onPendingApproval;
123
+ onError;
124
+ taskStore;
125
+ taskCounter = 0;
126
+ /**
127
+ * Captures an event bus and worker and validates local backpressure limits.
128
+ * @param eventBus - Host domain bus; subscriptions begin only on registerRule.
129
+ * @param worker - Host worker performing gatekeeper/runtime execution.
130
+ * @param options - Queue limits, notification/error callbacks, and optional durable store.
131
+ * @throws Invalid limits or malformed durable store.
132
+ */
133
+ constructor(eventBus, worker, options = {}) {
134
+ this.eventBus = eventBus;
135
+ this.worker = worker;
136
+ this.maxConcurrent = options.maxConcurrent ?? 1;
137
+ this.maxQueueSize = options.maxQueueSize ?? 100;
138
+ if (!Number.isSafeInteger(this.maxConcurrent) || this.maxConcurrent < 1 || this.maxConcurrent > 1024) throw new Error("Invalid EventAgentBridge maxConcurrent");
139
+ if (!Number.isSafeInteger(this.maxQueueSize) || this.maxQueueSize < 0 || this.maxQueueSize > 1e6) throw new Error("Invalid EventAgentBridge maxQueueSize");
140
+ this.onPendingApproval = options.onPendingApproval;
141
+ this.onError = options.onError;
142
+ if (options.taskStore) this.withDurableTaskStore(options.taskStore);
143
+ }
144
+ /**
145
+ * Persisted event work is deliberately drained by the host scheduler. The
146
+ * bridge never treats its in-memory queue as a durable workflow checkpoint.
147
+ * @param store - Host durable queue with enqueue/claim/complete/fail functions.
148
+ * @returns This bridge after replacing its store reference.
149
+ * @throws Missing/malformed store functions.
150
+ * @remarks Existing local queued work is not migrated by changing this store.
151
+ * @example
152
+ * ```typescript
153
+ * import { EventAgentBridge } from "@alneas/eaos-server/agentic/event-bridge";
154
+ * import type { EventAgentTaskStore } from "@alneas/eaos-server/agentic/event-bridge";
155
+ * export function persist(bridge: EventAgentBridge, store: EventAgentTaskStore) { return bridge.withDurableTaskStore(store); }
156
+ * ```
157
+ */
158
+ withDurableTaskStore(store) {
159
+ if (!store || typeof store.enqueue !== "function" || typeof store.claim !== "function" || typeof store.complete !== "function" || typeof store.fail !== "function") throw new Error("Invalid durable event agent task store");
160
+ this.taskStore = store;
161
+ return this;
162
+ }
163
+ /**
164
+ * Claims one bounded durable batch and processes it sequentially.
165
+ * @param limit - Safe integer 1–maxConcurrent; defaults to maxConcurrent.
166
+ * @returns Claim/completion/failure persistence counts; a worker FAILED result counts completed if stored successfully.
167
+ * @throws Missing store, invalid limit, claim/fail persistence errors, or synchronous error-sink errors.
168
+ * @remarks Calls are not globally serialized. Notification failures are reported after result persistence. No periodic scheduler or automatic retry is installed.
169
+ * @example
170
+ * ```typescript
171
+ * import { EventAgentBridge } from "@alneas/eaos-server/agentic/event-bridge";
172
+ * export async function drain(bridge: EventAgentBridge) { return bridge.runDurableOnce(); }
173
+ * ```
174
+ */
175
+ async runDurableOnce(limit = this.maxConcurrent) {
176
+ if (!this.taskStore) throw new Error("Durable event agent task store is not configured");
177
+ if (!Number.isSafeInteger(limit) || limit < 1 || limit > this.maxConcurrent) throw new Error("Invalid durable event agent task limit");
178
+ const tasks = await this.taskStore.claim(limit);
179
+ let completed = 0, failed = 0;
180
+ for (const queued of tasks) {
181
+ let result;
182
+ try {
183
+ result = await this.worker.runTask(queued.task);
184
+ } catch (error) {
185
+ failed++;
186
+ await this.taskStore.fail(queued.task.id, error);
187
+ this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "runTask", error });
188
+ continue;
189
+ }
190
+ try {
191
+ await this.taskStore.complete(queued.task.id, result);
192
+ completed++;
193
+ } catch (error) {
194
+ failed++;
195
+ await this.taskStore.fail(queued.task.id, error);
196
+ this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "result", error, result });
197
+ continue;
198
+ }
199
+ if (result.status === "PENDING_APPROVAL" && this.onPendingApproval) {
200
+ try {
201
+ await this.onPendingApproval({ eventName: queued.eventName, payload: queued.payload, task: queued.task, result });
202
+ } catch (error) {
203
+ this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "notification", error, result });
204
+ }
205
+ }
206
+ if (result.status === "FAILED") this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "result", error: result.error ?? new Error("Agent task failed"), result });
207
+ }
208
+ return { claimed: tasks.length, completed, failed };
209
+ }
210
+ /**
211
+ * Subscribes a task-conversion rule and returns its individual unsubscribe callback.
212
+ * @param rule - Exact event name and synchronous createTask callback; callback receives payload and returns verified task fields or null to skip.
213
+ * @returns A no-argument callback returning no value; removes this rule and unsubscribes the bus handler when no rules remain.
214
+ * @throws Event bus subscription/unsubscription errors can propagate. Event conversion errors are reported through onError.
215
+ * @remarks The rule is retained by reference; do not mutate its eventName after registration. Already accepted tasks keep running after unsubscribe.
216
+ * @example
217
+ * ```typescript
218
+ * import { EventAgentBridge } from "@alneas/eaos-server/agentic/event-bridge";
219
+ * import type { EventAgentRule } from "@alneas/eaos-server/agentic/event-bridge";
220
+ * export function listen(bridge: EventAgentBridge, rule: EventAgentRule) { return bridge.registerRule(rule); }
221
+ * ```
222
+ */
223
+ registerRule(rule) {
224
+ if (!this.rules.has(rule.eventName)) {
225
+ this.rules.set(rule.eventName, []);
226
+ const handler = (payload) => {
227
+ void this.handleEvent(rule.eventName, payload).catch((error) => {
228
+ this.reportError({ eventName: rule.eventName, phase: "createTask", error });
229
+ });
230
+ };
231
+ this.subscriptions.set(rule.eventName, handler);
232
+ this.eventBus.subscribe(rule.eventName, handler);
233
+ }
234
+ this.rules.get(rule.eventName).push(rule);
235
+ return () => {
236
+ const list = this.rules.get(rule.eventName);
237
+ if (list) {
238
+ const index = list.indexOf(rule);
239
+ if (index >= 0) list.splice(index, 1);
240
+ if (list.length === 0) {
241
+ this.rules.delete(rule.eventName);
242
+ const handler = this.subscriptions.get(rule.eventName);
243
+ if (handler) this.eventBus.unsubscribe(rule.eventName, handler);
244
+ this.subscriptions.delete(rule.eventName);
245
+ }
246
+ }
247
+ };
248
+ }
249
+ /**
250
+ * Waits until the bridge's local active count and waiting queue are empty.
251
+ * @returns No value; resolves when local work is idle. It does not wait for durable queue persistence/draining or asynchronous error sinks.
252
+ * @remarks Polls with zero-delay timers and has no timeout/cancellation; continuously arriving work can delay completion indefinitely.
253
+ * @example
254
+ * ```typescript
255
+ * import { EventAgentBridge } from "@alneas/eaos-server/agentic/event-bridge";
256
+ * export async function idle(bridge: EventAgentBridge) { await bridge.whenIdle(); }
257
+ * ```
258
+ */
259
+ async whenIdle() {
260
+ while (this.activeCount > 0 || this.queue.length > 0) await new Promise((resolve) => setTimeout(resolve, 0));
261
+ }
262
+ async handleEvent(eventName, payload) {
263
+ const list = this.rules.get(eventName);
264
+ if (!list || list.length === 0) return;
265
+ for (const rule of [...list]) {
266
+ let taskSpec;
267
+ try {
268
+ taskSpec = rule.createTask(payload);
269
+ } catch (error) {
270
+ this.reportError({ eventName, phase: "createTask", error });
271
+ continue;
272
+ }
273
+ if (!taskSpec) continue;
274
+ const taskId = `evt_${Date.now()}_${++this.taskCounter}`;
275
+ const task = {
276
+ ...taskSpec,
277
+ id: taskId,
278
+ executionContext: {
279
+ ...taskSpec.executionContext,
280
+ idempotencyKey: taskSpec.executionContext?.idempotencyKey ?? `event-agent:${eventName}:${taskId}`
281
+ }
282
+ };
283
+ if (this.taskStore) {
284
+ try {
285
+ await this.taskStore.enqueue({ eventName, payload: structuredClone(payload), task: structuredClone(task) });
286
+ } catch (error) {
287
+ this.reportError({ eventName, taskId: task.id, phase: "queue", error });
288
+ }
289
+ continue;
290
+ }
291
+ if (this.queue.length >= this.maxQueueSize && this.activeCount >= this.maxConcurrent) {
292
+ this.reportError({ eventName, taskId: task.id, phase: "queue", error: new Error("EventAgentBridge queue is full") });
293
+ continue;
294
+ }
295
+ this.queue.push({ eventName, payload, task });
296
+ }
297
+ this.drain();
298
+ }
299
+ drain() {
300
+ while (this.activeCount < this.maxConcurrent && this.queue.length > 0) {
301
+ const queued = this.queue.shift();
302
+ this.activeCount += 1;
303
+ void this.execute(queued).finally(() => {
304
+ this.activeCount -= 1;
305
+ this.drain();
306
+ });
307
+ }
308
+ }
309
+ async execute(queued) {
310
+ let result;
311
+ try {
312
+ result = await this.worker.runTask(queued.task);
313
+ } catch (error) {
314
+ this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "runTask", error });
315
+ return;
316
+ }
317
+ if (result.status === "PENDING_APPROVAL") {
318
+ try {
319
+ if (this.onPendingApproval) await this.onPendingApproval({ eventName: queued.eventName, payload: queued.payload, task: queued.task, result });
320
+ else console.warn("[EventAgentBridge] Agent task pending approval", { eventName: queued.eventName, taskId: queued.task.id, approvalTicketId: result.approvalTicketId });
321
+ } catch (error) {
322
+ this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "notification", error, result });
323
+ }
324
+ return;
325
+ }
326
+ if (result.status === "FAILED") this.reportError({ eventName: queued.eventName, taskId: queued.task.id, phase: "result", error: result.error ?? new Error("Agent task failed"), result });
327
+ }
328
+ reportError(detail) {
329
+ if (this.onError) {
330
+ void Promise.resolve(this.onError(detail)).catch((error) => console.error("[EventAgentBridge] Error sink failed", error));
331
+ return;
332
+ }
333
+ console.error("[EventAgentBridge] Event task failed", {
334
+ eventName: detail.eventName,
335
+ taskId: detail.taskId,
336
+ phase: detail.phase,
337
+ error: detail.error instanceof Error ? detail.error.message : String(detail.error)
338
+ });
339
+ }
340
+ };
341
+
342
+ export {
343
+ InMemoryEventAgentTaskStore,
344
+ EventAgentBridge
345
+ };
346
+ //# sourceMappingURL=chunk-3P4XTTQH.js.map