@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,7 @@
1
+ import {
2
+ publicAccountMemberships
3
+ } from "../chunk-FRRRWAHO.js";
4
+ export {
5
+ publicAccountMemberships
6
+ };
7
+ //# sourceMappingURL=public-memberships.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,181 @@
1
+ import { Context } from 'hono';
2
+
3
+ /**
4
+ * Per-fetch storage controls for {@link MemoryCacheManager.getOrSet}.
5
+ */
6
+ interface CacheOptions {
7
+ /** Retention in milliseconds; finite and nonnegative. Zero disables storing; omission uses the manager default. */
8
+ ttlMs?: number;
9
+ /** Tags attached to a newly stored entry for invalidation; defaults to none. */
10
+ tags?: string[];
11
+ /** Fetch even when a cached value exists; successful fetches may still populate the cache. @defaultValue false */
12
+ bypass?: boolean;
13
+ }
14
+ /**
15
+ * Verified identity partition used by {@link MemoryCacheManager.forScope}.
16
+ */
17
+ interface CacheScope {
18
+ /** Nonblank authenticated tenant ID. */
19
+ tenantId: string;
20
+ /** Nonblank trusted plugin ID. */
21
+ pluginId: string;
22
+ /** Nonblank authenticated user ID. */
23
+ userId: string;
24
+ /** Permission revision included in the key partition; defaults to an empty string. */
25
+ permissionVersion?: string;
26
+ }
27
+ /**
28
+ * Stores cloned values in a bounded process-local cache with TTL and tag invalidation.
29
+ * @remarks Values must support structuredClone. Entries expire lazily on access; no timers, persistent storage, or cross-process invalidation are installed. Capacity eviction removes the oldest inserted entry. Concurrent misses run separate fetchers; only the latest fetch started for a key may populate it, and any invalidation prevents previously started fetches from repopulating entries.
30
+ * @example
31
+ * ```typescript
32
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
33
+ * const cache = new MemoryCacheManager();
34
+ * const result = await cache.getOrSet("answer", async () => ({ value: 42 }));
35
+ * console.log(result.value);
36
+ * cache.clear();
37
+ * ```
38
+ */
39
+ declare class MemoryCacheManager {
40
+ private readonly values;
41
+ private readonly tags;
42
+ private readonly pending;
43
+ private epoch;
44
+ private readonly maxEntries;
45
+ private readonly ttl;
46
+ /**
47
+ * Creates an independent cache with validated capacity and default retention.
48
+ * @param options - maxEntries defaults to 1000 and must be a positive safe integer; defaultTtlMs defaults to 60000 milliseconds and must be finite and nonnegative.
49
+ * @throws If capacity or default retention is invalid.
50
+ */
51
+ constructor(options?: {
52
+ /**
53
+ * Maximum retained cache entries; defaults to 1000 and must be a positive safe integer. Capacity eviction removes the oldest inserted entry.
54
+ */
55
+ maxEntries?: number;
56
+ /**
57
+ * Default retention in milliseconds, finite and nonnegative; defaults to 60000. Zero disables retaining newly fetched/set entries.
58
+ */
59
+ defaultTtlMs?: number;
60
+ });
61
+ /** Request bypass detector; see {@link isNoCacheRequested} for parameter semantics and example. */
62
+ isNoCacheRequested: typeof isNoCacheRequested;
63
+ private remove;
64
+ private prune;
65
+ /**
66
+ * Stores a cloned value, replacing an existing key and invalidating its in-flight fetch token.
67
+ * @typeParam T - Structured-cloneable value type.
68
+ * @param key - Exact cache key, without automatic authorization or partitioning.
69
+ * @param value - Value to clone for storage.
70
+ * @param ttlMs - Nonnegative finite milliseconds from the current clock; defaults to the manager retention. Zero removes the prior entry without storing.
71
+ * @param tags - Invalidation tags; duplicates are collapsed and omission uses none.
72
+ * @returns No value; completes after cloning and inserting or removing the entry.
73
+ * @throws For invalid TTL or a value that cannot be structured-cloned. A previous entry may already have been removed when cloning fails.
74
+ * @example
75
+ * ```typescript
76
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
77
+ * const cache = new MemoryCacheManager();
78
+ * cache.set("answer", { value: 42 }, 1000, ["answers"]);
79
+ * ```
80
+ */
81
+ set<T>(key: string, value: T, ttlMs?: number, tags?: string[]): void;
82
+ /**
83
+ * Returns a cloned cached value or fetches and conditionally caches a new value.
84
+ * @typeParam T - Structured-cloneable value returned by fetcher and this method.
85
+ * @param key - Exact cache key; use forScope for authenticated partitions.
86
+ * @param fetcher - Called without arguments on a miss or bypass; resolves a cloneable value. Concurrent misses are not coalesced.
87
+ * @param options - Retention, tags, and bypass settings; see {@link CacheOptions}.
88
+ * @returns A separate clone of the cached or fetched value, including when invalidation prevents storage.
89
+ * @throws Rejects on fetcher failure, invalid TTL used for insertion, or structuredClone failure.
90
+ * @example
91
+ * ```typescript
92
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
93
+ * const cache = new MemoryCacheManager();
94
+ * console.log(await cache.getOrSet("answer", async () => 42));
95
+ * ```
96
+ */
97
+ getOrSet<T>(key: string, fetcher: () => Promise<T>, options?: CacheOptions): Promise<T>;
98
+ /**
99
+ * Removes entries carrying any requested tag and prevents pending fetches from populating the cache.
100
+ * @param tags - One exact tag or multiple tags; an empty array removes no stored entries but still invalidates pending writes.
101
+ * @returns No value; removal completes synchronously.
102
+ * @example
103
+ * ```typescript
104
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
105
+ * const cache = new MemoryCacheManager();
106
+ * cache.set("answer", 42, 1000, ["answers"]);
107
+ * cache.invalidateTags("answers");
108
+ * ```
109
+ */
110
+ invalidateTags(tags: string | string[]): void;
111
+ /**
112
+ * Removes entries whose exact keys start with the supplied prefix and invalidates pending writes.
113
+ * @param prefix - Case-sensitive key prefix; an empty prefix matches every entry.
114
+ * @returns No value; removal completes synchronously.
115
+ * @example
116
+ * ```typescript
117
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
118
+ * const cache = new MemoryCacheManager();
119
+ * cache.invalidatePrefix("reports:");
120
+ * ```
121
+ */
122
+ invalidatePrefix(prefix: string): void;
123
+ /**
124
+ * Removes every cached entry, tag index, and pending write token.
125
+ * @returns No value; clearing completes synchronously without cancelling fetchers already running.
126
+ * @example
127
+ * ```typescript
128
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
129
+ * const cache = new MemoryCacheManager();
130
+ * cache.clear();
131
+ * ```
132
+ */
133
+ clear(): void;
134
+ /**
135
+ * Prunes expired entries and counts the remaining stored values.
136
+ * @returns Current number of unexpired entries, excluding pending fetches.
137
+ * @example
138
+ * ```typescript
139
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
140
+ * const cache = new MemoryCacheManager();
141
+ * console.log(cache.size()); // 0
142
+ * ```
143
+ */
144
+ size(): number;
145
+ /**
146
+ * Creates a tenant/plugin/user partition with authorization before and after asynchronous work.
147
+ * @param scope - Verified nonblank identity IDs and optional permission revision; see {@link CacheScope}.
148
+ * @param authorize - Called without arguments on every lookup, including hits, and after fetching and before returning. Any truthy result permits access; errors propagate.
149
+ * @returns A scoped getOrSet using the same key/fetcher/options semantics as this manager, plus invalidate(), which removes this partition without returning a value or calling authorize.
150
+ * @throws Synchronously for missing/blank scope IDs. Scoped lookups reject for denied access or propagated authorization/fetch/clone errors.
151
+ * @remarks Tenant and plugin tags are added to fetched entries. The host must supply trusted identity and live authorization; partitioning does not authenticate callers. Invalidating a scope also prevents other in-flight manager fetches from populating entries.
152
+ * @example
153
+ * ```typescript
154
+ * import { MemoryCacheManager, type CacheScope } from "@alneas/eaos-server/cache";
155
+ * export function userCache(scope: CacheScope, authorize: () => Promise<boolean>) {
156
+ * return new MemoryCacheManager().forScope(scope, authorize);
157
+ * }
158
+ * ```
159
+ */
160
+ forScope(scope: CacheScope, authorize: () => boolean | Promise<boolean>): {
161
+ getOrSet: <T>(key: string, fetcher: () => Promise<T>, options?: CacheOptions) => Promise<T>;
162
+ invalidate: () => void;
163
+ };
164
+ }
165
+ /**
166
+ * Detects request directives or query flags asking to bypass cached values.
167
+ * @param c - Hono request context; reads Cache-Control, Pragma, refresh, and nocache.
168
+ * @returns True for no-cache, max-age=0 (optionally quoted), or refresh/nocache equal to true or 1; false otherwise. Header directives are case-insensitive; query flag values are case-sensitive.
169
+ * @example
170
+ * ```typescript
171
+ * import { Hono } from "hono";
172
+ * import { isNoCacheRequested } from "@alneas/eaos-server/cache";
173
+ * const app = new Hono();
174
+ * app.get("/cache-policy", c => c.json({ bypass: isNoCacheRequested(c) }));
175
+ * console.log(await (await app.request("/cache-policy?refresh=1")).json());
176
+ * ```
177
+ */
178
+ declare function isNoCacheRequested(c: Pick<Context, 'req'>): boolean;
179
+
180
+ export { MemoryCacheManager, isNoCacheRequested };
181
+ export type { CacheOptions, CacheScope };
@@ -0,0 +1,197 @@
1
+ // src/cache/index.ts
2
+ var MemoryCacheManager = class {
3
+ values = /* @__PURE__ */ new Map();
4
+ tags = /* @__PURE__ */ new Map();
5
+ pending = /* @__PURE__ */ new Map();
6
+ epoch = 0;
7
+ maxEntries;
8
+ ttl;
9
+ /**
10
+ * Creates an independent cache with validated capacity and default retention.
11
+ * @param options - maxEntries defaults to 1000 and must be a positive safe integer; defaultTtlMs defaults to 60000 milliseconds and must be finite and nonnegative.
12
+ * @throws If capacity or default retention is invalid.
13
+ */
14
+ constructor(options = {}) {
15
+ this.maxEntries = options.maxEntries ?? 1e3;
16
+ this.ttl = options.defaultTtlMs ?? 6e4;
17
+ if (!Number.isSafeInteger(this.maxEntries) || this.maxEntries < 1 || !Number.isFinite(this.ttl) || this.ttl < 0) throw new Error("Invalid cache limits");
18
+ }
19
+ /** Request bypass detector; see {@link isNoCacheRequested} for parameter semantics and example. */
20
+ isNoCacheRequested = isNoCacheRequested;
21
+ remove(key) {
22
+ const entry = this.values.get(key);
23
+ if (entry) for (const tag of entry.tags) {
24
+ const keys = this.tags.get(tag);
25
+ keys.delete(key);
26
+ if (!keys.size) this.tags.delete(tag);
27
+ }
28
+ this.values.delete(key);
29
+ }
30
+ prune() {
31
+ const now = Date.now();
32
+ for (const [key, entry] of this.values) if (entry.expiresAt <= now) this.remove(key);
33
+ }
34
+ /**
35
+ * Stores a cloned value, replacing an existing key and invalidating its in-flight fetch token.
36
+ * @typeParam T - Structured-cloneable value type.
37
+ * @param key - Exact cache key, without automatic authorization or partitioning.
38
+ * @param value - Value to clone for storage.
39
+ * @param ttlMs - Nonnegative finite milliseconds from the current clock; defaults to the manager retention. Zero removes the prior entry without storing.
40
+ * @param tags - Invalidation tags; duplicates are collapsed and omission uses none.
41
+ * @returns No value; completes after cloning and inserting or removing the entry.
42
+ * @throws For invalid TTL or a value that cannot be structured-cloned. A previous entry may already have been removed when cloning fails.
43
+ * @example
44
+ * ```typescript
45
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
46
+ * const cache = new MemoryCacheManager();
47
+ * cache.set("answer", { value: 42 }, 1000, ["answers"]);
48
+ * ```
49
+ */
50
+ set(key, value, ttlMs = this.ttl, tags = []) {
51
+ if (!Number.isFinite(ttlMs) || ttlMs < 0) throw new Error("Invalid cache TTL");
52
+ this.pending.delete(key);
53
+ this.remove(key);
54
+ this.prune();
55
+ if (ttlMs === 0) return;
56
+ const entry = { value: structuredClone(value), expiresAt: Date.now() + ttlMs, tags: new Set(tags) };
57
+ while (this.values.size >= this.maxEntries) this.remove(this.values.keys().next().value);
58
+ this.values.set(key, entry);
59
+ for (const tag of entry.tags) {
60
+ let keys = this.tags.get(tag);
61
+ if (!keys) this.tags.set(tag, keys = /* @__PURE__ */ new Set());
62
+ keys.add(key);
63
+ }
64
+ }
65
+ /**
66
+ * Returns a cloned cached value or fetches and conditionally caches a new value.
67
+ * @typeParam T - Structured-cloneable value returned by fetcher and this method.
68
+ * @param key - Exact cache key; use forScope for authenticated partitions.
69
+ * @param fetcher - Called without arguments on a miss or bypass; resolves a cloneable value. Concurrent misses are not coalesced.
70
+ * @param options - Retention, tags, and bypass settings; see {@link CacheOptions}.
71
+ * @returns A separate clone of the cached or fetched value, including when invalidation prevents storage.
72
+ * @throws Rejects on fetcher failure, invalid TTL used for insertion, or structuredClone failure.
73
+ * @example
74
+ * ```typescript
75
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
76
+ * const cache = new MemoryCacheManager();
77
+ * console.log(await cache.getOrSet("answer", async () => 42));
78
+ * ```
79
+ */
80
+ async getOrSet(key, fetcher, options = {}) {
81
+ this.prune();
82
+ const cached = this.values.get(key);
83
+ if (!options.bypass && cached) return structuredClone(cached.value);
84
+ const token = /* @__PURE__ */ Symbol(), epoch = this.epoch;
85
+ this.pending.set(key, token);
86
+ try {
87
+ const value = await fetcher();
88
+ if (epoch === this.epoch && this.pending.get(key) === token) this.set(key, value, options.ttlMs ?? this.ttl, options.tags);
89
+ return structuredClone(value);
90
+ } finally {
91
+ if (this.pending.get(key) === token) this.pending.delete(key);
92
+ }
93
+ }
94
+ /**
95
+ * Removes entries carrying any requested tag and prevents pending fetches from populating the cache.
96
+ * @param tags - One exact tag or multiple tags; an empty array removes no stored entries but still invalidates pending writes.
97
+ * @returns No value; removal completes synchronously.
98
+ * @example
99
+ * ```typescript
100
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
101
+ * const cache = new MemoryCacheManager();
102
+ * cache.set("answer", 42, 1000, ["answers"]);
103
+ * cache.invalidateTags("answers");
104
+ * ```
105
+ */
106
+ invalidateTags(tags) {
107
+ this.epoch++;
108
+ for (const tag of typeof tags === "string" ? [tags] : tags) for (const key of [...this.tags.get(tag) ?? []]) this.remove(key);
109
+ }
110
+ /**
111
+ * Removes entries whose exact keys start with the supplied prefix and invalidates pending writes.
112
+ * @param prefix - Case-sensitive key prefix; an empty prefix matches every entry.
113
+ * @returns No value; removal completes synchronously.
114
+ * @example
115
+ * ```typescript
116
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
117
+ * const cache = new MemoryCacheManager();
118
+ * cache.invalidatePrefix("reports:");
119
+ * ```
120
+ */
121
+ invalidatePrefix(prefix) {
122
+ this.epoch++;
123
+ for (const key of this.values.keys()) if (key.startsWith(prefix)) this.remove(key);
124
+ }
125
+ /**
126
+ * Removes every cached entry, tag index, and pending write token.
127
+ * @returns No value; clearing completes synchronously without cancelling fetchers already running.
128
+ * @example
129
+ * ```typescript
130
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
131
+ * const cache = new MemoryCacheManager();
132
+ * cache.clear();
133
+ * ```
134
+ */
135
+ clear() {
136
+ this.epoch++;
137
+ this.values.clear();
138
+ this.tags.clear();
139
+ this.pending.clear();
140
+ }
141
+ /**
142
+ * Prunes expired entries and counts the remaining stored values.
143
+ * @returns Current number of unexpired entries, excluding pending fetches.
144
+ * @example
145
+ * ```typescript
146
+ * import { MemoryCacheManager } from "@alneas/eaos-server/cache";
147
+ * const cache = new MemoryCacheManager();
148
+ * console.log(cache.size()); // 0
149
+ * ```
150
+ */
151
+ size() {
152
+ this.prune();
153
+ return this.values.size;
154
+ }
155
+ /**
156
+ * Creates a tenant/plugin/user partition with authorization before and after asynchronous work.
157
+ * @param scope - Verified nonblank identity IDs and optional permission revision; see {@link CacheScope}.
158
+ * @param authorize - Called without arguments on every lookup, including hits, and after fetching and before returning. Any truthy result permits access; errors propagate.
159
+ * @returns A scoped getOrSet using the same key/fetcher/options semantics as this manager, plus invalidate(), which removes this partition without returning a value or calling authorize.
160
+ * @throws Synchronously for missing/blank scope IDs. Scoped lookups reject for denied access or propagated authorization/fetch/clone errors.
161
+ * @remarks Tenant and plugin tags are added to fetched entries. The host must supply trusted identity and live authorization; partitioning does not authenticate callers. Invalidating a scope also prevents other in-flight manager fetches from populating entries.
162
+ * @example
163
+ * ```typescript
164
+ * import { MemoryCacheManager, type CacheScope } from "@alneas/eaos-server/cache";
165
+ * export function userCache(scope: CacheScope, authorize: () => Promise<boolean>) {
166
+ * return new MemoryCacheManager().forScope(scope, authorize);
167
+ * }
168
+ * ```
169
+ */
170
+ forScope(scope, authorize) {
171
+ for (const id of [scope.tenantId, scope.pluginId, scope.userId]) if (typeof id !== "string" || !id.trim()) throw new Error("Verified cache scope required");
172
+ const prefix = JSON.stringify([scope.tenantId, scope.pluginId, scope.userId, scope.permissionVersion ?? ""]) + ":";
173
+ const tenantTag = `tenant:${scope.tenantId}`, pluginTag = `plugin:${scope.pluginId}`;
174
+ const allowed = async () => {
175
+ if (!await authorize()) throw new Error("Cache access denied");
176
+ };
177
+ return { getOrSet: async (key, fetcher, options = {}) => {
178
+ await allowed();
179
+ const value = await this.getOrSet(prefix + key, async () => {
180
+ const result = await fetcher();
181
+ await allowed();
182
+ return result;
183
+ }, { ...options, tags: [...options.tags ?? [], tenantTag, pluginTag] });
184
+ await allowed();
185
+ return value;
186
+ }, invalidate: () => this.invalidatePrefix(prefix) };
187
+ }
188
+ };
189
+ function isNoCacheRequested(c) {
190
+ const directives = `${c.req.header("cache-control") ?? ""},${c.req.header("pragma") ?? ""}`.toLowerCase().split(",").map((v) => v.trim());
191
+ return directives.some((v) => v === "no-cache" || /^max-age\s*=\s*"?0"?$/.test(v)) || ["refresh", "nocache"].some((key) => ["true", "1"].includes(c.req.query(key) ?? ""));
192
+ }
193
+ export {
194
+ MemoryCacheManager,
195
+ isNoCacheRequested
196
+ };
197
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cache/index.ts"],"sourcesContent":["import type { Context } from 'hono'\n/**\n * Per-fetch storage controls for {@link MemoryCacheManager.getOrSet}.\n */\nexport interface CacheOptions {\n /** Retention in milliseconds; finite and nonnegative. Zero disables storing; omission uses the manager default. */\n ttlMs?: number\n /** Tags attached to a newly stored entry for invalidation; defaults to none. */\n tags?: string[]\n /** Fetch even when a cached value exists; successful fetches may still populate the cache. @defaultValue false */\n bypass?: boolean\n}\n/**\n * Verified identity partition used by {@link MemoryCacheManager.forScope}.\n */\nexport interface CacheScope {\n /** Nonblank authenticated tenant ID. */\n tenantId: string\n /** Nonblank trusted plugin ID. */\n pluginId: string\n /** Nonblank authenticated user ID. */\n userId: string\n /** Permission revision included in the key partition; defaults to an empty string. */\n permissionVersion?: string\n}\ninterface Entry { value: unknown; expiresAt: number; tags: Set<string> }\n/**\n * Stores cloned values in a bounded process-local cache with TTL and tag invalidation.\n * @remarks Values must support structuredClone. Entries expire lazily on access; no timers, persistent storage, or cross-process invalidation are installed. Capacity eviction removes the oldest inserted entry. Concurrent misses run separate fetchers; only the latest fetch started for a key may populate it, and any invalidation prevents previously started fetches from repopulating entries.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * const result = await cache.getOrSet(\"answer\", async () => ({ value: 42 }));\n * console.log(result.value);\n * cache.clear();\n * ```\n */\nexport class MemoryCacheManager {\n private readonly values = new Map<string, Entry>()\n private readonly tags = new Map<string, Set<string>>()\n private readonly pending = new Map<string, symbol>()\n private epoch = 0\n private readonly maxEntries: number\n private readonly ttl: number\n /**\n * Creates an independent cache with validated capacity and default retention.\n * @param options - maxEntries defaults to 1000 and must be a positive safe integer; defaultTtlMs defaults to 60000 milliseconds and must be finite and nonnegative.\n * @throws If capacity or default retention is invalid.\n */\n constructor(options: { \n /**\n * Maximum retained cache entries; defaults to 1000 and must be a positive safe integer. Capacity eviction removes the oldest inserted entry.\n */\n maxEntries?: number; \n /**\n * Default retention in milliseconds, finite and nonnegative; defaults to 60000. Zero disables retaining newly fetched/set entries.\n */\n defaultTtlMs?: number } = {}) {\n this.maxEntries = options.maxEntries ?? 1000; this.ttl = options.defaultTtlMs ?? 60_000\n if (!Number.isSafeInteger(this.maxEntries) || this.maxEntries < 1 || !Number.isFinite(this.ttl) || this.ttl < 0) throw new Error('Invalid cache limits')\n }\n /** Request bypass detector; see {@link isNoCacheRequested} for parameter semantics and example. */\n isNoCacheRequested = isNoCacheRequested\n private remove(key: string) {\n const entry = this.values.get(key)\n if (entry) for (const tag of entry.tags) { const keys = this.tags.get(tag)!; keys.delete(key); if (!keys.size) this.tags.delete(tag) }\n this.values.delete(key)\n }\n private prune() { const now = Date.now(); for (const [key, entry] of this.values) if (entry.expiresAt <= now) this.remove(key) }\n /**\n * Stores a cloned value, replacing an existing key and invalidating its in-flight fetch token.\n * @typeParam T - Structured-cloneable value type.\n * @param key - Exact cache key, without automatic authorization or partitioning.\n * @param value - Value to clone for storage.\n * @param ttlMs - Nonnegative finite milliseconds from the current clock; defaults to the manager retention. Zero removes the prior entry without storing.\n * @param tags - Invalidation tags; duplicates are collapsed and omission uses none.\n * @returns No value; completes after cloning and inserting or removing the entry.\n * @throws For invalid TTL or a value that cannot be structured-cloned. A previous entry may already have been removed when cloning fails.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * cache.set(\"answer\", { value: 42 }, 1000, [\"answers\"]);\n * ```\n */\n set<T>(key: string, value: T, ttlMs = this.ttl, tags: string[] = []) {\n if (!Number.isFinite(ttlMs) || ttlMs < 0) throw new Error('Invalid cache TTL')\n this.pending.delete(key); this.remove(key); this.prune()\n if (ttlMs === 0) return\n const entry = { value: structuredClone(value), expiresAt: Date.now() + ttlMs, tags: new Set(tags) }\n while (this.values.size >= this.maxEntries) this.remove(this.values.keys().next().value!)\n this.values.set(key, entry)\n for (const tag of entry.tags) { let keys = this.tags.get(tag); if (!keys) this.tags.set(tag, keys = new Set()); keys.add(key) }\n }\n /**\n * Returns a cloned cached value or fetches and conditionally caches a new value.\n * @typeParam T - Structured-cloneable value returned by fetcher and this method.\n * @param key - Exact cache key; use forScope for authenticated partitions.\n * @param fetcher - Called without arguments on a miss or bypass; resolves a cloneable value. Concurrent misses are not coalesced.\n * @param options - Retention, tags, and bypass settings; see {@link CacheOptions}.\n * @returns A separate clone of the cached or fetched value, including when invalidation prevents storage.\n * @throws Rejects on fetcher failure, invalid TTL used for insertion, or structuredClone failure.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * console.log(await cache.getOrSet(\"answer\", async () => 42));\n * ```\n */\n async getOrSet<T>(key: string, fetcher: () => Promise<T>, options: CacheOptions = {}): Promise<T> {\n this.prune()\n const cached = this.values.get(key)\n if (!options.bypass && cached) return structuredClone(cached.value) as T\n const token = Symbol(), epoch = this.epoch; this.pending.set(key, token)\n try {\n const value = await fetcher()\n if (epoch === this.epoch && this.pending.get(key) === token) this.set(key, value, options.ttlMs ?? this.ttl, options.tags)\n return structuredClone(value)\n } finally { if (this.pending.get(key) === token) this.pending.delete(key) }\n }\n /**\n * Removes entries carrying any requested tag and prevents pending fetches from populating the cache.\n * @param tags - One exact tag or multiple tags; an empty array removes no stored entries but still invalidates pending writes.\n * @returns No value; removal completes synchronously.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * cache.set(\"answer\", 42, 1000, [\"answers\"]);\n * cache.invalidateTags(\"answers\");\n * ```\n */\n invalidateTags(tags: string | string[]) {\n this.epoch++\n for (const tag of typeof tags === 'string' ? [tags] : tags) for (const key of [...(this.tags.get(tag) ?? [])]) this.remove(key)\n }\n /**\n * Removes entries whose exact keys start with the supplied prefix and invalidates pending writes.\n * @param prefix - Case-sensitive key prefix; an empty prefix matches every entry.\n * @returns No value; removal completes synchronously.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * cache.invalidatePrefix(\"reports:\");\n * ```\n */\n invalidatePrefix(prefix: string) { this.epoch++; for (const key of this.values.keys()) if (key.startsWith(prefix)) this.remove(key) }\n /**\n * Removes every cached entry, tag index, and pending write token.\n * @returns No value; clearing completes synchronously without cancelling fetchers already running.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * cache.clear();\n * ```\n */\n clear() { this.epoch++; this.values.clear(); this.tags.clear(); this.pending.clear() }\n /**\n * Prunes expired entries and counts the remaining stored values.\n * @returns Current number of unexpired entries, excluding pending fetches.\n * @example\n * ```typescript\n * import { MemoryCacheManager } from \"@alneas/eaos-server/cache\";\n * const cache = new MemoryCacheManager();\n * console.log(cache.size()); // 0\n * ```\n */\n size() { this.prune(); return this.values.size }\n /**\n * Creates a tenant/plugin/user partition with authorization before and after asynchronous work.\n * @param scope - Verified nonblank identity IDs and optional permission revision; see {@link CacheScope}.\n * @param authorize - Called without arguments on every lookup, including hits, and after fetching and before returning. Any truthy result permits access; errors propagate.\n * @returns A scoped getOrSet using the same key/fetcher/options semantics as this manager, plus invalidate(), which removes this partition without returning a value or calling authorize.\n * @throws Synchronously for missing/blank scope IDs. Scoped lookups reject for denied access or propagated authorization/fetch/clone errors.\n * @remarks Tenant and plugin tags are added to fetched entries. The host must supply trusted identity and live authorization; partitioning does not authenticate callers. Invalidating a scope also prevents other in-flight manager fetches from populating entries.\n * @example\n * ```typescript\n * import { MemoryCacheManager, type CacheScope } from \"@alneas/eaos-server/cache\";\n * export function userCache(scope: CacheScope, authorize: () => Promise<boolean>) {\n * return new MemoryCacheManager().forScope(scope, authorize);\n * }\n * ```\n */\n forScope(scope: CacheScope, authorize: () => boolean | Promise<boolean>) {\n for (const id of [scope.tenantId, scope.pluginId, scope.userId]) if (typeof id !== 'string' || !id.trim()) throw new Error('Verified cache scope required')\n const prefix = JSON.stringify([scope.tenantId, scope.pluginId, scope.userId, scope.permissionVersion ?? '']) + ':'\n const tenantTag = `tenant:${scope.tenantId}`, pluginTag = `plugin:${scope.pluginId}`\n const allowed = async () => { if (!await authorize()) throw new Error('Cache access denied') }\n return { getOrSet: async <T>(key: string, fetcher: () => Promise<T>, options: CacheOptions = {}) => {\n await allowed()\n const value = await this.getOrSet(prefix + key, async () => { const result = await fetcher(); await allowed(); return result }, { ...options, tags: [...(options.tags ?? []), tenantTag, pluginTag] })\n await allowed(); return value\n }, invalidate: () => this.invalidatePrefix(prefix) }\n }\n}\n/**\n * Detects request directives or query flags asking to bypass cached values.\n * @param c - Hono request context; reads Cache-Control, Pragma, refresh, and nocache.\n * @returns True for no-cache, max-age=0 (optionally quoted), or refresh/nocache equal to true or 1; false otherwise. Header directives are case-insensitive; query flag values are case-sensitive.\n * @example\n * ```typescript\n * import { Hono } from \"hono\";\n * import { isNoCacheRequested } from \"@alneas/eaos-server/cache\";\n * const app = new Hono();\n * app.get(\"/cache-policy\", c => c.json({ bypass: isNoCacheRequested(c) }));\n * console.log(await (await app.request(\"/cache-policy?refresh=1\")).json());\n * ```\n */\nexport function isNoCacheRequested(c: Pick<Context, 'req'>): boolean {\n const directives = `${c.req.header('cache-control') ?? ''},${c.req.header('pragma') ?? ''}`.toLowerCase().split(',').map(v => v.trim())\n return directives.some(v => v === 'no-cache' || /^max-age\\s*=\\s*\"?0\"?$/.test(v)) || ['refresh', 'nocache'].some(key => ['true', '1'].includes(c.req.query(key) ?? ''))\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,131 @@
1
+ import {
2
+ ServerAgentExecutionError
3
+ } from "./chunk-YABTQZDJ.js";
4
+
5
+ // src/agentic/executor.ts
6
+ import { randomUUID } from "node:crypto";
7
+ import { spawn } from "node:child_process";
8
+ import { resolve } from "node:path";
9
+ import { defaultRuntimePlacementPolicy } from "@alneas/eaos-core";
10
+ function validateAgentRuntimePolicy(policy) {
11
+ const baseline = defaultRuntimePlacementPolicy().ai.agentRuntime;
12
+ if (!policy || policy.placement !== "ai" || policy.rootFilesystem !== "read-only" || policy.network !== "private-only" || !Number.isSafeInteger(policy.maxConcurrent) || policy.maxConcurrent < 1 || policy.maxConcurrent > baseline.maxConcurrent || !Number.isSafeInteger(policy.maxRuntimeMs) || policy.maxRuntimeMs < 1 || policy.maxRuntimeMs > baseline.maxRuntimeMs || !Number.isSafeInteger(policy.memoryLimitMb) || policy.memoryLimitMb < 1 || policy.memoryLimitMb > baseline.memoryLimitMb || !Number.isSafeInteger(policy.pidsLimit) || policy.pidsLimit < 1 || policy.pidsLimit > baseline.pidsLimit || policy.tmpfs.path !== "/tmp" || policy.tmpfs.noexec !== true || policy.tmpfs.nosuid !== true || policy.tmpfs.nodev !== true || !Number.isSafeInteger(policy.tmpfs.maxBytes) || policy.tmpfs.maxBytes < 1 || policy.tmpfs.maxBytes > baseline.tmpfs.maxBytes || policy.workspace.path !== "/workspace" || policy.workspace.mode !== baseline.workspace.mode || policy.workspace.persistent !== false || !Number.isSafeInteger(policy.workspace.maxBytes) || policy.workspace.maxBytes < 1 || policy.workspace.maxBytes > baseline.workspace.maxBytes) {
13
+ throw new Error("Agent runtime policy may only tighten the framework default");
14
+ }
15
+ return structuredClone(policy);
16
+ }
17
+ function buildSystemdRunArgs(command, args, policy, cwd, unit) {
18
+ const workingDirectory = resolve(cwd || process.cwd());
19
+ const runtimeSeconds = Math.max(1, Math.ceil(policy.maxRuntimeMs / 1e3));
20
+ const user = typeof process.getuid === "function" && process.getuid() !== 0;
21
+ return [
22
+ ...user ? ["--user"] : [],
23
+ "--wait",
24
+ "--collect",
25
+ "--pipe",
26
+ "--quiet",
27
+ `--unit=${unit}`,
28
+ `--property=MemoryMax=${policy.memoryLimitMb}M`,
29
+ `--property=TasksMax=${policy.pidsLimit}`,
30
+ `--property=RuntimeMaxSec=${runtimeSeconds}s`,
31
+ "--property=ProtectSystem=strict",
32
+ "--property=NoNewPrivileges=yes",
33
+ "--property=PrivateTmp=yes",
34
+ `--property=TemporaryFileSystem=${policy.tmpfs.path}:rw,noexec,nosuid,nodev,size=${policy.tmpfs.maxBytes}`,
35
+ `--property=ReadWritePaths=${workingDirectory}`,
36
+ `--working-directory=${workingDirectory}`,
37
+ "--",
38
+ command,
39
+ ...args
40
+ ];
41
+ }
42
+ function sandboxMode(options) {
43
+ return options?.mode || "auto";
44
+ }
45
+ function useSystemd(mode) {
46
+ if (mode === "direct") return false;
47
+ if (mode === "systemd") return true;
48
+ return process.platform === "linux";
49
+ }
50
+ function stopSystemdUnit(unit) {
51
+ const user = typeof process.getuid === "function" && process.getuid() !== 0;
52
+ const child = spawn("systemctl", [...user ? ["--user"] : [], "stop", unit], { stdio: "ignore" });
53
+ child.once("error", () => void 0);
54
+ }
55
+ function createCommandAgentExecutor(options) {
56
+ if (typeof options.command !== "string" || !options.command.trim() || typeof options.buildArgs !== "function") throw new Error("Invalid command agent executor");
57
+ const timeoutDefault = options.timeoutMs ?? 6e4;
58
+ const maxOutputChars = options.maxOutputChars ?? 1e6;
59
+ if (!Number.isSafeInteger(timeoutDefault) || timeoutDefault < 1 || timeoutDefault > 36e5 || !Number.isSafeInteger(maxOutputChars) || maxOutputChars < 1 || maxOutputChars > 1e7) throw new Error("Invalid command agent executor limits");
60
+ return async (request) => {
61
+ const args = options.buildArgs(structuredClone(request));
62
+ if (!Array.isArray(args) || args.some((arg) => typeof arg !== "string")) throw new Error("Command agent arguments must be strings");
63
+ const timeoutMs = request.timeoutMs ?? timeoutDefault;
64
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 36e5) throw new Error("Invalid command agent timeout");
65
+ const customEnv = options.env?.(structuredClone(request)) ?? {};
66
+ const env = {
67
+ ...options.includeProcessEnv ? process.env : {},
68
+ EAOS_TENANT_ID: request.tenantId,
69
+ EAOS_TASK_ID: request.id,
70
+ ...request.executionContext?.workflowId ? { EAOS_WORKFLOW_ID: request.executionContext.workflowId } : {},
71
+ ...request.executionContext?.correlationId ? { EAOS_CORRELATION_ID: request.executionContext.correlationId } : {},
72
+ ...request.executionContext?.idempotencyKey ? { EAOS_IDEMPOTENCY_KEY: request.executionContext.idempotencyKey } : {},
73
+ ...request.executionContext?.toolMode ? { EAOS_TOOL_MODE: request.executionContext.toolMode } : {},
74
+ ...request.executionContext?.allowedToolNames ? { EAOS_ALLOWED_TOOL_NAMES: JSON.stringify(request.executionContext.allowedToolNames) } : {},
75
+ ...customEnv
76
+ };
77
+ const policy = validateAgentRuntimePolicy(options.sandbox?.policy || request.runtimePolicy || defaultRuntimePlacementPolicy().ai.agentRuntime);
78
+ const unit = `eaos-agent-${randomUUID()}`;
79
+ const managed = useSystemd(sandboxMode(options.sandbox));
80
+ const launchCommand = managed ? "systemd-run" : options.command;
81
+ const launchArgs = managed ? buildSystemdRunArgs(options.command, args, policy, options.cwd, unit) : args;
82
+ return new Promise((resolve2, reject) => {
83
+ let stdout = "";
84
+ let stderr = "";
85
+ let settled = false;
86
+ const child = spawn(launchCommand, launchArgs, { cwd: options.cwd, env, stdio: ["ignore", "pipe", "pipe"] });
87
+ const timer = setTimeout(() => {
88
+ fail(new ServerAgentExecutionError("Agent runtime timed out", "TIMEOUT", true));
89
+ }, timeoutMs);
90
+ const fail = (error) => {
91
+ if (settled) return;
92
+ settled = true;
93
+ clearTimeout(timer);
94
+ if (managed) stopSystemdUnit(unit);
95
+ child.kill("SIGTERM");
96
+ reject(error);
97
+ };
98
+ const append = (target, data) => {
99
+ if (settled) return;
100
+ if (target === "stdout") stdout += data.toString();
101
+ else stderr += data.toString();
102
+ if (stdout.length + stderr.length > maxOutputChars) fail(new ServerAgentExecutionError("Agent output exceeds configured limit", "OUTPUT_LIMIT", false));
103
+ };
104
+ child.stdout?.on("data", (data) => append("stdout", data));
105
+ child.stderr?.on("data", (data) => append("stderr", data));
106
+ child.once("error", (error) => fail(new ServerAgentExecutionError(`Agent runtime unavailable: ${error.message}`, "AGENT_UNAVAILABLE", true, { cause: error })));
107
+ child.once("close", (code) => {
108
+ if (settled) return;
109
+ settled = true;
110
+ clearTimeout(timer);
111
+ if (code !== 0) {
112
+ const sandboxUnavailable = managed && /(?:systemd-run|Failed to (?:connect|start|find executable)|No medium found)/i.test(stderr);
113
+ const message = sandboxUnavailable ? `Agent runtime unavailable: ${stderr.slice(0, 1e3)}` : `Agent runtime exited with code ${code}: ${stderr.slice(0, 1e3)}`;
114
+ return reject(new ServerAgentExecutionError(
115
+ message,
116
+ sandboxUnavailable ? "AGENT_UNAVAILABLE" : "RUNTIME_FAILED",
117
+ true
118
+ ));
119
+ }
120
+ resolve2(stdout);
121
+ });
122
+ });
123
+ };
124
+ }
125
+
126
+ export {
127
+ validateAgentRuntimePolicy,
128
+ buildSystemdRunArgs,
129
+ createCommandAgentExecutor
130
+ };
131
+ //# sourceMappingURL=chunk-32746UQZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/agentic/executor.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { spawn } from 'node:child_process'\nimport { resolve } from 'node:path'\nimport { defaultRuntimePlacementPolicy, type AgentRuntimeResourcePolicy } from '@alneas/eaos-core'\nimport { ServerAgentExecutionError, type ServerAgentExecutor, type ServerAgentTaskRequest } from './types'\n\n/**\n * Chooses Linux systemd-run, direct spawning, or automatic platform selection.\n * @see createCommandAgentExecutor.\n */\nexport type CommandAgentSandboxMode = 'auto' | 'systemd' | 'direct'\n\n/**\n * Host sandbox selection for {@link createCommandAgentExecutor}.\n */\nexport interface CommandAgentSandboxOptions {\n /** auto uses transient systemd on Linux and direct execution on local development hosts. */\n mode?: CommandAgentSandboxMode\n /** Resource policy is framework-owned by default; consumers may only tighten it in a host adapter. */\n policy?: AgentRuntimeResourcePolicy\n}\n\n/**\n * Trusted executable, argument/environment builders, and limits for {@link createCommandAgentExecutor}.\n */\nexport interface CommandAgentExecutorOptions {\n /** Host-configured executable. It is never taken from a task request. */\n command: string\n /** Called once per task with a structured clone; must return string arguments. Arguments are passed without a shell, and callback errors reject execution. */\n buildArgs: (request: ServerAgentTaskRequest) => readonly string[]\n /** Process working directory; omitted uses the host process directory. Under systemd this directory is also explicitly writable. */\n cwd?: string\n /** Per-task environment callback receiving a clone; its entries override framework EAOS variables. Defaults to no additional variables. */\n env?: (request: ServerAgentTaskRequest) => Record<string, string | undefined>\n /** Inherit host process environment before framework/custom variables. @defaultValue false */\n includeProcessEnv?: boolean\n /** Default task timeout in milliseconds, safe integer 1–3600000; task.timeoutMs overrides it. @defaultValue 60000 */\n timeoutMs?: number\n /** Combined stdout/stderr string-length ceiling, safe integer 1–10000000. @defaultValue 1000000 */\n maxOutputChars?: number\n /** Sandbox selection; defaults to auto and a validated task/framework policy. Direct mode does not apply systemd resource/filesystem restrictions. */\n sandbox?: CommandAgentSandboxOptions\n}\n\n/**\n * Validates that resource-policy fields retain or tighten the current framework baseline.\n * @param policy - Runtime resource policy with AI placement, read-only root, private-only network, and bounded resources.\n * @returns A structured clone of the accepted policy.\n * @throws For weaker/invalid fields; malformed nested fields can also throw property-access errors.\n * @remarks Validation does not itself apply operating-system isolation, concurrency, or network controls.\n * @example\n * ```typescript\n * import { defaultRuntimePlacementPolicy } from \"@alneas/eaos-core\";\n * import { validateAgentRuntimePolicy } from \"@alneas/eaos-server/agentic/executor\";\n * const policy = validateAgentRuntimePolicy(defaultRuntimePlacementPolicy().ai.agentRuntime);\n * console.log(policy.placement); // \"ai\"\n * ```\n */\nexport function validateAgentRuntimePolicy(policy: AgentRuntimeResourcePolicy): AgentRuntimeResourcePolicy {\n const baseline = defaultRuntimePlacementPolicy().ai.agentRuntime\n if (!policy || policy.placement !== 'ai' || policy.rootFilesystem !== 'read-only' || policy.network !== 'private-only' ||\n !Number.isSafeInteger(policy.maxConcurrent) || policy.maxConcurrent < 1 || policy.maxConcurrent > baseline.maxConcurrent ||\n !Number.isSafeInteger(policy.maxRuntimeMs) || policy.maxRuntimeMs < 1 || policy.maxRuntimeMs > baseline.maxRuntimeMs ||\n !Number.isSafeInteger(policy.memoryLimitMb) || policy.memoryLimitMb < 1 || policy.memoryLimitMb > baseline.memoryLimitMb ||\n !Number.isSafeInteger(policy.pidsLimit) || policy.pidsLimit < 1 || policy.pidsLimit > baseline.pidsLimit ||\n policy.tmpfs.path !== '/tmp' || policy.tmpfs.noexec !== true || policy.tmpfs.nosuid !== true || policy.tmpfs.nodev !== true ||\n !Number.isSafeInteger(policy.tmpfs.maxBytes) || policy.tmpfs.maxBytes < 1 || policy.tmpfs.maxBytes > baseline.tmpfs.maxBytes ||\n policy.workspace.path !== '/workspace' || policy.workspace.mode !== baseline.workspace.mode || policy.workspace.persistent !== false ||\n !Number.isSafeInteger(policy.workspace.maxBytes) || policy.workspace.maxBytes < 1 || policy.workspace.maxBytes > baseline.workspace.maxBytes) {\n throw new Error('Agent runtime policy may only tighten the framework default')\n }\n return structuredClone(policy)\n}\n\n/**\n * Builds systemd-run arguments for transient process resource and filesystem restrictions.\n * @param command - Trusted executable passed after the systemd option terminator.\n * @param args - Executable arguments, passed unchanged without a shell.\n * @param policy - Already validated resource policy; this helper does not validate it.\n * @param cwd - Working directory, resolved absolutely; absent/empty uses process.cwd().\n * @param unit - Host-selected transient unit name, used for later stop requests.\n * @returns A new argument array, using --user for a nonroot host user and rounding runtime milliseconds upward to at least one second.\n * @remarks Requires a host with systemd-run and appropriate service-manager permissions when executed. This array does not implement network allowlisting, workspace capacity, or a concurrency scheduler; those policy fields require host enforcement.\n * @example\n * ```typescript\n * import { defaultRuntimePlacementPolicy } from \"@alneas/eaos-core\";\n * import { buildSystemdRunArgs } from \"@alneas/eaos-server/agentic/executor\";\n * const args = buildSystemdRunArgs(\"agent-runtime\", [\"--version\"], defaultRuntimePlacementPolicy().ai.agentRuntime, undefined, \"example-agent\");\n * console.log(args.includes(\"--wait\")); // true\n * ```\n */\nexport function buildSystemdRunArgs(command: string, args: readonly string[], policy: AgentRuntimeResourcePolicy, cwd: string | undefined, unit: string): string[] {\n const workingDirectory = resolve(cwd || process.cwd())\n const runtimeSeconds = Math.max(1, Math.ceil(policy.maxRuntimeMs / 1000))\n const user = typeof process.getuid === 'function' && process.getuid() !== 0\n return [\n ...(user ? ['--user'] : []),\n '--wait', '--collect', '--pipe', '--quiet', `--unit=${unit}`,\n `--property=MemoryMax=${policy.memoryLimitMb}M`,\n `--property=TasksMax=${policy.pidsLimit}`,\n `--property=RuntimeMaxSec=${runtimeSeconds}s`,\n '--property=ProtectSystem=strict',\n '--property=NoNewPrivileges=yes',\n '--property=PrivateTmp=yes',\n `--property=TemporaryFileSystem=${policy.tmpfs.path}:rw,noexec,nosuid,nodev,size=${policy.tmpfs.maxBytes}`,\n `--property=ReadWritePaths=${workingDirectory}`,\n `--working-directory=${workingDirectory}`,\n '--', command, ...args,\n ]\n}\n\nfunction sandboxMode(options: CommandAgentSandboxOptions | undefined): CommandAgentSandboxMode {\n return options?.mode || 'auto'\n}\n\nfunction useSystemd(mode: CommandAgentSandboxMode): boolean {\n if (mode === 'direct') return false\n if (mode === 'systemd') return true\n return process.platform === 'linux'\n}\n\nfunction stopSystemdUnit(unit: string) {\n const user = typeof process.getuid === 'function' && process.getuid() !== 0\n const child = spawn('systemctl', [...(user ? ['--user'] : []), 'stop', unit], { stdio: 'ignore' })\n child.once('error', () => undefined)\n}\n\n/**\n * Creates a shell-free executor for OpenCode, Codex, Goose or another trusted\n * CLI. Authorization and approval happen before this adapter is called.\n * @param options - Trusted executable, argument/environment callbacks, output/timeout limits, and sandbox settings.\n * @returns A per-task async executor resolving stdout on exit code zero, including an empty string when no output was produced.\n * @throws Synchronously for invalid factory settings. Execution rejects callback/clone/policy errors and ServerAgentExecutionError for spawn, timeout, output-limit, or nonzero-exit failures.\n * @remarks Requires Node child_process. auto selects systemd on Linux and direct execution elsewhere. No task concurrency limit is enforced here. stdin is ignored, stdout/stderr are bounded together, and stderr is excluded from successful output. On timeout/output/spawn failure the timer is cleared, SIGTERM is sent, and systemd stop is requested when managed; termination is not awaited and descendants may outlive direct-mode failure. Idempotency is only propagated through environment variables; host/runtime code must enforce safe retries.\n * @example\n * ```typescript\n * import { createCommandAgentExecutor, type CommandAgentExecutorOptions } from \"@alneas/eaos-server/agentic/executor\";\n * export function hostExecutor(configuration: CommandAgentExecutorOptions) {\n * // The host provisions the executable and performs admission/approval first.\n * return createCommandAgentExecutor(configuration);\n * }\n * ```\n */\nexport function createCommandAgentExecutor(options: CommandAgentExecutorOptions): ServerAgentExecutor {\n if (typeof options.command !== 'string' || !options.command.trim() || typeof options.buildArgs !== 'function') throw new Error('Invalid command agent executor')\n const timeoutDefault = options.timeoutMs ?? 60_000\n const maxOutputChars = options.maxOutputChars ?? 1_000_000\n if (!Number.isSafeInteger(timeoutDefault) || timeoutDefault < 1 || timeoutDefault > 3_600_000 || !Number.isSafeInteger(maxOutputChars) || maxOutputChars < 1 || maxOutputChars > 10_000_000) throw new Error('Invalid command agent executor limits')\n\n return async request => {\n const args = options.buildArgs(structuredClone(request))\n if (!Array.isArray(args) || args.some(arg => typeof arg !== 'string')) throw new Error('Command agent arguments must be strings')\n const timeoutMs = request.timeoutMs ?? timeoutDefault\n if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 3_600_000) throw new Error('Invalid command agent timeout')\n const customEnv = options.env?.(structuredClone(request)) ?? {}\n const env = {\n ...(options.includeProcessEnv ? process.env : {}),\n EAOS_TENANT_ID: request.tenantId,\n EAOS_TASK_ID: request.id,\n ...(request.executionContext?.workflowId ? { EAOS_WORKFLOW_ID: request.executionContext.workflowId } : {}),\n ...(request.executionContext?.correlationId ? { EAOS_CORRELATION_ID: request.executionContext.correlationId } : {}),\n ...(request.executionContext?.idempotencyKey ? { EAOS_IDEMPOTENCY_KEY: request.executionContext.idempotencyKey } : {}),\n ...(request.executionContext?.toolMode ? { EAOS_TOOL_MODE: request.executionContext.toolMode } : {}),\n ...(request.executionContext?.allowedToolNames ? { EAOS_ALLOWED_TOOL_NAMES: JSON.stringify(request.executionContext.allowedToolNames) } : {}),\n ...customEnv,\n }\n const policy = validateAgentRuntimePolicy(options.sandbox?.policy || request.runtimePolicy || defaultRuntimePlacementPolicy().ai.agentRuntime)\n const unit = `eaos-agent-${randomUUID()}`\n const managed = useSystemd(sandboxMode(options.sandbox))\n const launchCommand = managed ? 'systemd-run' : options.command\n const launchArgs = managed ? buildSystemdRunArgs(options.command, args, policy, options.cwd, unit) : args\n\n return new Promise((resolve, reject) => {\n let stdout = ''\n let stderr = ''\n let settled = false\n const child = spawn(launchCommand, launchArgs, { cwd: options.cwd, env, stdio: ['ignore', 'pipe', 'pipe'] })\n const timer = setTimeout(() => {\n fail(new ServerAgentExecutionError('Agent runtime timed out', 'TIMEOUT', true))\n }, timeoutMs)\n const fail = (error: Error) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (managed) stopSystemdUnit(unit)\n child.kill('SIGTERM')\n reject(error)\n }\n const append = (target: 'stdout' | 'stderr', data: Buffer | string) => {\n if (settled) return\n if (target === 'stdout') stdout += data.toString()\n else stderr += data.toString()\n if (stdout.length + stderr.length > maxOutputChars) fail(new ServerAgentExecutionError('Agent output exceeds configured limit', 'OUTPUT_LIMIT', false))\n }\n child.stdout?.on('data', data => append('stdout', data))\n child.stderr?.on('data', data => append('stderr', data))\n child.once('error', error => fail(new ServerAgentExecutionError(`Agent runtime unavailable: ${error.message}`, 'AGENT_UNAVAILABLE', true, { cause: error })))\n child.once('close', code => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (code !== 0) {\n const sandboxUnavailable = managed && /(?:systemd-run|Failed to (?:connect|start|find executable)|No medium found)/i.test(stderr)\n const message = sandboxUnavailable\n ? `Agent runtime unavailable: ${stderr.slice(0, 1000)}`\n : `Agent runtime exited with code ${code}: ${stderr.slice(0, 1000)}`\n return reject(new ServerAgentExecutionError(\n message,\n sandboxUnavailable ? 'AGENT_UNAVAILABLE' : 'RUNTIME_FAILED',\n true,\n ))\n }\n resolve(stdout)\n })\n })\n }\n}\n"],"mappings":"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","names":["resolve"]}