@warlock.js/ai 4.4.0 → 4.5.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 (535) hide show
  1. package/CHANGELOG.md +52 -55
  2. package/cjs/index.cjs +221 -14147
  3. package/cjs/src-C02yzsLs.cjs +22991 -0
  4. package/cjs/src-C02yzsLs.cjs.map +1 -0
  5. package/cjs/src-DFibP2FQ.cjs +30 -0
  6. package/esm/agent/agent-config.type.d.mts +90 -1
  7. package/esm/agent/agent-config.type.d.mts.map +1 -1
  8. package/esm/agent/agent-input-builder.mjs +27 -6
  9. package/esm/agent/agent-input-builder.mjs.map +1 -1
  10. package/esm/agent/agent.d.mts +40 -1
  11. package/esm/agent/agent.d.mts.map +1 -1
  12. package/esm/agent/agent.mjs +203 -30
  13. package/esm/agent/agent.mjs.map +1 -1
  14. package/esm/agent/index.d.mts +2 -1
  15. package/esm/agent/index.mjs +1 -0
  16. package/esm/agent/judge-config.type.d.mts +33 -0
  17. package/esm/agent/judge-config.type.d.mts.map +1 -0
  18. package/esm/agent/judge-config.type.mjs +13 -0
  19. package/esm/agent/judge-config.type.mjs.map +1 -0
  20. package/esm/ai-openai/src/embedder.mjs +4 -0
  21. package/esm/ai-openai/src/index.mjs +4 -0
  22. package/esm/ai-openai/src/model.mjs +5 -0
  23. package/esm/ai-openai/src/sdk.mjs +6 -0
  24. package/esm/ai-openai/src/utils/index.mjs +4 -0
  25. package/esm/ai-openai/src/utils/to-openai-tools.mjs +3 -0
  26. package/esm/ai-openai/src/utils/wrap-openai-error.mjs +4 -0
  27. package/esm/ai.d.mts +119 -53
  28. package/esm/ai.d.mts.map +1 -1
  29. package/esm/ai.mjs +43 -8
  30. package/esm/ai.mjs.map +1 -1
  31. package/esm/batch/batch.d.mts.map +1 -1
  32. package/esm/batch/batch.mjs +21 -1
  33. package/esm/batch/batch.mjs.map +1 -1
  34. package/esm/batch/batch.type.d.mts +11 -4
  35. package/esm/batch/batch.type.d.mts.map +1 -1
  36. package/esm/config.d.mts +39 -3
  37. package/esm/config.d.mts.map +1 -1
  38. package/esm/config.mjs +26 -2
  39. package/esm/config.mjs.map +1 -1
  40. package/esm/contracts/agent/agent-options.type.d.mts +11 -3
  41. package/esm/contracts/agent/agent-options.type.d.mts.map +1 -1
  42. package/esm/contracts/agent/eval.type.d.mts +43 -2
  43. package/esm/contracts/agent/eval.type.d.mts.map +1 -1
  44. package/esm/contracts/attachment-policy.type.d.mts +51 -0
  45. package/esm/contracts/attachment-policy.type.d.mts.map +1 -0
  46. package/esm/contracts/attachment.type.d.mts +16 -7
  47. package/esm/contracts/attachment.type.d.mts.map +1 -1
  48. package/esm/contracts/content-part.type.d.mts +14 -5
  49. package/esm/contracts/content-part.type.d.mts.map +1 -1
  50. package/esm/contracts/events/supervisor-events.type.d.mts.map +1 -1
  51. package/esm/contracts/index.d.mts +6 -4
  52. package/esm/contracts/model.contract.d.mts +11 -8
  53. package/esm/contracts/model.contract.d.mts.map +1 -1
  54. package/esm/contracts/orchestrator/index.d.mts +1 -0
  55. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts +31 -2
  56. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts.map +1 -1
  57. package/esm/contracts/orchestrator/session-lock.contract.d.mts +47 -0
  58. package/esm/contracts/orchestrator/session-lock.contract.d.mts.map +1 -0
  59. package/esm/contracts/planner/index.d.mts +1 -1
  60. package/esm/contracts/planner/planner-config.type.d.mts +31 -0
  61. package/esm/contracts/planner/planner-config.type.d.mts.map +1 -1
  62. package/esm/contracts/planner/planner-execute-options.type.d.mts +48 -1
  63. package/esm/contracts/planner/planner-execute-options.type.d.mts.map +1 -1
  64. package/esm/contracts/planner/planner-result.type.d.mts +8 -0
  65. package/esm/contracts/planner/planner-result.type.d.mts.map +1 -1
  66. package/esm/contracts/planner/planner.contract.d.mts +1 -1
  67. package/esm/contracts/result/agent-result.type.d.mts +6 -4
  68. package/esm/contracts/result/agent-result.type.d.mts.map +1 -1
  69. package/esm/contracts/result/base-report.type.d.mts +21 -3
  70. package/esm/contracts/result/base-report.type.d.mts.map +1 -1
  71. package/esm/contracts/result/base-report.type.mjs.map +1 -1
  72. package/esm/contracts/result/execution-report.type.d.mts +53 -1
  73. package/esm/contracts/result/execution-report.type.d.mts.map +1 -1
  74. package/esm/contracts/result/supervisor-result.type.d.mts +14 -2
  75. package/esm/contracts/result/supervisor-result.type.d.mts.map +1 -1
  76. package/esm/contracts/result/workflow-result.type.d.mts +2 -1
  77. package/esm/contracts/result/workflow-result.type.d.mts.map +1 -1
  78. package/esm/contracts/supervisor/supervisor-config.type.d.mts +29 -0
  79. package/esm/contracts/supervisor/supervisor-config.type.d.mts.map +1 -1
  80. package/esm/contracts/system-prompt.contract.d.mts +103 -1
  81. package/esm/contracts/system-prompt.contract.d.mts.map +1 -1
  82. package/esm/contracts/team/index.d.mts +1 -0
  83. package/esm/contracts/team/team-config.type.d.mts +127 -0
  84. package/esm/contracts/team/team-config.type.d.mts.map +1 -0
  85. package/esm/contracts/tool.contract.d.mts +4 -2
  86. package/esm/contracts/tool.contract.d.mts.map +1 -1
  87. package/esm/contracts/workflow/step.contract.d.mts +30 -5
  88. package/esm/contracts/workflow/step.contract.d.mts.map +1 -1
  89. package/esm/contracts/workflow/workflow.contract.d.mts +16 -0
  90. package/esm/contracts/workflow/workflow.contract.d.mts.map +1 -1
  91. package/esm/errors/error-code.type.d.mts +1 -1
  92. package/esm/errors/index.d.mts +1 -0
  93. package/esm/errors/index.mjs +1 -0
  94. package/esm/errors/outbound-policy-error.d.mts +27 -0
  95. package/esm/errors/outbound-policy-error.d.mts.map +1 -0
  96. package/esm/errors/outbound-policy-error.mjs +32 -0
  97. package/esm/errors/outbound-policy-error.mjs.map +1 -0
  98. package/esm/eval/dataset.d.mts +28 -0
  99. package/esm/eval/dataset.d.mts.map +1 -0
  100. package/esm/eval/dataset.mjs +112 -0
  101. package/esm/eval/dataset.mjs.map +1 -0
  102. package/esm/eval/dataset.type.d.mts +53 -0
  103. package/esm/eval/dataset.type.d.mts.map +1 -0
  104. package/esm/eval/eval-runner.d.mts.map +1 -1
  105. package/esm/eval/eval-runner.mjs +16 -2
  106. package/esm/eval/eval-runner.mjs.map +1 -1
  107. package/esm/eval/index.d.mts +20 -1
  108. package/esm/eval/index.d.mts.map +1 -1
  109. package/esm/eval/index.mjs +20 -2
  110. package/esm/eval/index.mjs.map +1 -1
  111. package/esm/eval/regression.d.mts +30 -0
  112. package/esm/eval/regression.d.mts.map +1 -0
  113. package/esm/eval/regression.mjs +51 -0
  114. package/esm/eval/regression.mjs.map +1 -0
  115. package/esm/eval/report-json.d.mts +30 -0
  116. package/esm/eval/report-json.d.mts.map +1 -0
  117. package/esm/eval/report-json.mjs +33 -0
  118. package/esm/eval/report-json.mjs.map +1 -0
  119. package/esm/eval/report-junit.d.mts +22 -0
  120. package/esm/eval/report-junit.d.mts.map +1 -0
  121. package/esm/eval/report-junit.mjs +60 -0
  122. package/esm/eval/report-junit.mjs.map +1 -0
  123. package/esm/guard/contracts/guard-options.type.d.mts +165 -0
  124. package/esm/guard/contracts/guard-options.type.d.mts.map +1 -0
  125. package/esm/guard/contracts/guardrail.contract.d.mts +78 -0
  126. package/esm/guard/contracts/guardrail.contract.d.mts.map +1 -0
  127. package/esm/guard/contracts/index.d.mts +4 -0
  128. package/esm/guard/contracts/openai-client.contract.d.mts +51 -0
  129. package/esm/guard/contracts/openai-client.contract.d.mts.map +1 -0
  130. package/esm/guard/contracts/verdict.type.d.mts +76 -0
  131. package/esm/guard/contracts/verdict.type.d.mts.map +1 -0
  132. package/esm/guard/detectors/index.d.mts +4 -0
  133. package/esm/guard/detectors/index.mjs +6 -0
  134. package/esm/guard/detectors/injection.d.mts +34 -0
  135. package/esm/guard/detectors/injection.d.mts.map +1 -0
  136. package/esm/guard/detectors/injection.mjs +254 -0
  137. package/esm/guard/detectors/injection.mjs.map +1 -0
  138. package/esm/guard/detectors/moderation.d.mts +32 -0
  139. package/esm/guard/detectors/moderation.d.mts.map +1 -0
  140. package/esm/guard/detectors/moderation.mjs +134 -0
  141. package/esm/guard/detectors/moderation.mjs.map +1 -0
  142. package/esm/guard/detectors/pii.d.mts +41 -0
  143. package/esm/guard/detectors/pii.d.mts.map +1 -0
  144. package/esm/guard/detectors/pii.mjs +199 -0
  145. package/esm/guard/detectors/pii.mjs.map +1 -0
  146. package/esm/guard/detectors/topic.d.mts +29 -0
  147. package/esm/guard/detectors/topic.d.mts.map +1 -0
  148. package/esm/guard/detectors/topic.mjs +99 -0
  149. package/esm/guard/detectors/topic.mjs.map +1 -0
  150. package/esm/guard/errors.d.mts +12 -0
  151. package/esm/guard/errors.d.mts.map +1 -0
  152. package/esm/guard/errors.mjs +18 -0
  153. package/esm/guard/errors.mjs.map +1 -0
  154. package/esm/guard/guard.d.mts +67 -0
  155. package/esm/guard/guard.d.mts.map +1 -0
  156. package/esm/guard/guard.mjs +209 -0
  157. package/esm/guard/guard.mjs.map +1 -0
  158. package/esm/guard/guardrail.d.mts +39 -0
  159. package/esm/guard/guardrail.d.mts.map +1 -0
  160. package/esm/guard/guardrail.mjs +22 -0
  161. package/esm/guard/guardrail.mjs.map +1 -0
  162. package/esm/human/contracts/approval.type.d.mts +154 -0
  163. package/esm/human/contracts/approval.type.d.mts.map +1 -0
  164. package/esm/human/contracts/human-approval.type.d.mts +38 -0
  165. package/esm/human/contracts/human-approval.type.d.mts.map +1 -0
  166. package/esm/human/contracts/index.d.mts +4 -0
  167. package/esm/human/contracts/interrupt-store.contract.d.mts +112 -0
  168. package/esm/human/contracts/interrupt-store.contract.d.mts.map +1 -0
  169. package/esm/human/contracts/resume.type.d.mts +77 -0
  170. package/esm/human/contracts/resume.type.d.mts.map +1 -0
  171. package/esm/human/errors.d.mts +84 -0
  172. package/esm/human/errors.d.mts.map +1 -0
  173. package/esm/human/errors.mjs +60 -0
  174. package/esm/human/errors.mjs.map +1 -0
  175. package/esm/human/human-approval.d.mts +57 -0
  176. package/esm/human/human-approval.d.mts.map +1 -0
  177. package/esm/human/human-approval.mjs +170 -0
  178. package/esm/human/human-approval.mjs.map +1 -0
  179. package/esm/human/policy.d.mts +55 -0
  180. package/esm/human/policy.d.mts.map +1 -0
  181. package/esm/human/policy.mjs +67 -0
  182. package/esm/human/policy.mjs.map +1 -0
  183. package/esm/human/register.mjs +37 -0
  184. package/esm/human/register.mjs.map +1 -0
  185. package/esm/human/resume-seed.mjs +53 -0
  186. package/esm/human/resume-seed.mjs.map +1 -0
  187. package/esm/human/resume.d.mts +54 -0
  188. package/esm/human/resume.d.mts.map +1 -0
  189. package/esm/human/resume.mjs +121 -0
  190. package/esm/human/resume.mjs.map +1 -0
  191. package/esm/human/stores/index.mjs +5 -0
  192. package/esm/human/stores/memory.d.mts +30 -0
  193. package/esm/human/stores/memory.d.mts.map +1 -0
  194. package/esm/human/stores/memory.mjs +91 -0
  195. package/esm/human/stores/memory.mjs.map +1 -0
  196. package/esm/human/stores/pg.d.mts +59 -0
  197. package/esm/human/stores/pg.d.mts.map +1 -0
  198. package/esm/human/stores/pg.mjs +220 -0
  199. package/esm/human/stores/pg.mjs.map +1 -0
  200. package/esm/human/stores/redis.d.mts +56 -0
  201. package/esm/human/stores/redis.d.mts.map +1 -0
  202. package/esm/human/stores/redis.mjs +201 -0
  203. package/esm/human/stores/redis.mjs.map +1 -0
  204. package/esm/index.d.mts +113 -22
  205. package/esm/index.mjs +82 -11
  206. package/esm/middleware/builtins/budget.mjs +6 -2
  207. package/esm/middleware/builtins/budget.mjs.map +1 -1
  208. package/esm/middleware/utils/extract-user-text.d.mts +8 -1
  209. package/esm/middleware/utils/extract-user-text.d.mts.map +1 -1
  210. package/esm/middleware/utils/extract-user-text.mjs +8 -1
  211. package/esm/middleware/utils/extract-user-text.mjs.map +1 -1
  212. package/esm/object-stream/index.d.mts +2 -0
  213. package/esm/object-stream/index.mjs +4 -0
  214. package/esm/object-stream/parse-partial-json.d.mts +22 -0
  215. package/esm/object-stream/parse-partial-json.d.mts.map +1 -0
  216. package/esm/object-stream/parse-partial-json.mjs +78 -0
  217. package/esm/object-stream/parse-partial-json.mjs.map +1 -0
  218. package/esm/object-stream/stream-object.d.mts +68 -0
  219. package/esm/object-stream/stream-object.d.mts.map +1 -0
  220. package/esm/object-stream/stream-object.mjs +104 -0
  221. package/esm/object-stream/stream-object.mjs.map +1 -0
  222. package/esm/observe/index.mjs +4 -0
  223. package/esm/observe/observer-registry.d.mts +30 -0
  224. package/esm/observe/observer-registry.d.mts.map +1 -0
  225. package/esm/observe/observer-registry.mjs +51 -0
  226. package/esm/observe/observer-registry.mjs.map +1 -0
  227. package/esm/observe/observer.contract.d.mts +40 -0
  228. package/esm/observe/observer.contract.d.mts.map +1 -0
  229. package/esm/observe/resolve-observers.d.mts +40 -0
  230. package/esm/observe/resolve-observers.d.mts.map +1 -0
  231. package/esm/observe/resolve-observers.mjs +73 -0
  232. package/esm/observe/resolve-observers.mjs.map +1 -0
  233. package/esm/orchestrator/execution.d.mts.map +1 -1
  234. package/esm/orchestrator/execution.mjs +5 -2
  235. package/esm/orchestrator/execution.mjs.map +1 -1
  236. package/esm/orchestrator/index.d.mts +1 -0
  237. package/esm/orchestrator/index.mjs +1 -0
  238. package/esm/orchestrator/orchestrator.d.mts.map +1 -1
  239. package/esm/orchestrator/orchestrator.mjs +39 -6
  240. package/esm/orchestrator/orchestrator.mjs.map +1 -1
  241. package/esm/orchestrator/session-lock.d.mts +25 -0
  242. package/esm/orchestrator/session-lock.d.mts.map +1 -0
  243. package/esm/orchestrator/session-lock.mjs +83 -0
  244. package/esm/orchestrator/session-lock.mjs.map +1 -0
  245. package/esm/planner/dag-scheduler.mjs +97 -0
  246. package/esm/planner/dag-scheduler.mjs.map +1 -0
  247. package/esm/planner/plan-prompt.d.mts +1 -1
  248. package/esm/planner/plan-prompt.d.mts.map +1 -1
  249. package/esm/planner/plan-prompt.mjs +2 -1
  250. package/esm/planner/plan-prompt.mjs.map +1 -1
  251. package/esm/planner/planner-run.d.mts.map +1 -1
  252. package/esm/planner/planner-run.mjs +300 -29
  253. package/esm/planner/planner-run.mjs.map +1 -1
  254. package/esm/planner/planner.mjs +1 -1
  255. package/esm/planner/planner.mjs.map +1 -1
  256. package/esm/prompt/errors.d.mts +57 -0
  257. package/esm/prompt/errors.d.mts.map +1 -0
  258. package/esm/prompt/errors.mjs +73 -0
  259. package/esm/prompt/errors.mjs.map +1 -0
  260. package/esm/prompt/index.d.mts +3 -0
  261. package/esm/prompt/index.mjs +4 -0
  262. package/esm/prompt/prompt-langfuse-sync.mjs +104 -0
  263. package/esm/prompt/prompt-langfuse-sync.mjs.map +1 -0
  264. package/esm/prompt/prompt-langfuse-sync.type.d.mts +32 -0
  265. package/esm/prompt/prompt-langfuse-sync.type.d.mts.map +1 -0
  266. package/esm/prompt/prompt-validate.mjs +170 -0
  267. package/esm/prompt/prompt-validate.mjs.map +1 -0
  268. package/esm/prompt/prompt.d.mts +54 -0
  269. package/esm/prompt/prompt.d.mts.map +1 -0
  270. package/esm/prompt/prompt.mjs +218 -0
  271. package/esm/prompt/prompt.mjs.map +1 -0
  272. package/esm/prompt/prompt.type.d.mts +174 -0
  273. package/esm/prompt/prompt.type.d.mts.map +1 -0
  274. package/esm/prompts/index.d.mts +3 -0
  275. package/esm/prompts/index.mjs +3 -0
  276. package/esm/prompts/prompts-manager.contract.d.mts +154 -0
  277. package/esm/prompts/prompts-manager.contract.d.mts.map +1 -0
  278. package/esm/prompts/prompts-manager.d.mts +38 -0
  279. package/esm/prompts/prompts-manager.d.mts.map +1 -0
  280. package/esm/prompts/prompts-manager.mjs +410 -0
  281. package/esm/prompts/prompts-manager.mjs.map +1 -0
  282. package/esm/prompts/prompts-manager.type.d.mts +172 -0
  283. package/esm/prompts/prompts-manager.type.d.mts.map +1 -0
  284. package/esm/prompts/prompts-validate.mjs +200 -0
  285. package/esm/prompts/prompts-validate.mjs.map +1 -0
  286. package/esm/rag/as-tool.mjs +48 -0
  287. package/esm/rag/as-tool.mjs.map +1 -0
  288. package/esm/rag/chunk/chunk.d.mts +24 -0
  289. package/esm/rag/chunk/chunk.d.mts.map +1 -0
  290. package/esm/rag/chunk/chunk.mjs +44 -0
  291. package/esm/rag/chunk/chunk.mjs.map +1 -0
  292. package/esm/rag/chunk/fixed.mjs +32 -0
  293. package/esm/rag/chunk/fixed.mjs.map +1 -0
  294. package/esm/rag/chunk/markdown.mjs +75 -0
  295. package/esm/rag/chunk/markdown.mjs.map +1 -0
  296. package/esm/rag/chunk/recursive.mjs +132 -0
  297. package/esm/rag/chunk/recursive.mjs.map +1 -0
  298. package/esm/rag/chunk/sentence.mjs +73 -0
  299. package/esm/rag/chunk/sentence.mjs.map +1 -0
  300. package/esm/rag/contracts/chunk-options.type.d.mts +35 -0
  301. package/esm/rag/contracts/chunk-options.type.d.mts.map +1 -0
  302. package/esm/rag/contracts/citation.type.d.mts +35 -0
  303. package/esm/rag/contracts/citation.type.d.mts.map +1 -0
  304. package/esm/rag/contracts/index.d.mts +4 -0
  305. package/esm/rag/contracts/rag-config.type.d.mts +68 -0
  306. package/esm/rag/contracts/rag-config.type.d.mts.map +1 -0
  307. package/esm/rag/contracts/rag-document.type.d.mts +21 -0
  308. package/esm/rag/contracts/rag-document.type.d.mts.map +1 -0
  309. package/esm/rag/hybrid/bm25.d.mts +23 -0
  310. package/esm/rag/hybrid/bm25.d.mts.map +1 -0
  311. package/esm/rag/hybrid/bm25.mjs +51 -0
  312. package/esm/rag/hybrid/bm25.mjs.map +1 -0
  313. package/esm/rag/hybrid/hybrid-rank.d.mts +33 -0
  314. package/esm/rag/hybrid/hybrid-rank.d.mts.map +1 -0
  315. package/esm/rag/hybrid/hybrid-rank.mjs +29 -0
  316. package/esm/rag/hybrid/hybrid-rank.mjs.map +1 -0
  317. package/esm/rag/hybrid/rrf.d.mts +25 -0
  318. package/esm/rag/hybrid/rrf.d.mts.map +1 -0
  319. package/esm/rag/hybrid/rrf.mjs +30 -0
  320. package/esm/rag/hybrid/rrf.mjs.map +1 -0
  321. package/esm/rag/index.d.mts +15 -0
  322. package/esm/rag/index.mjs +11 -0
  323. package/esm/rag/rag.d.mts +38 -0
  324. package/esm/rag/rag.d.mts.map +1 -0
  325. package/esm/rag/rag.mjs +126 -0
  326. package/esm/rag/rag.mjs.map +1 -0
  327. package/esm/rag/rerank/keyword-reranker.d.mts +32 -0
  328. package/esm/rag/rerank/keyword-reranker.d.mts.map +1 -0
  329. package/esm/rag/rerank/keyword-reranker.mjs +58 -0
  330. package/esm/rag/rerank/keyword-reranker.mjs.map +1 -0
  331. package/esm/rag/rerank/llm-reranker.d.mts +36 -0
  332. package/esm/rag/rerank/llm-reranker.d.mts.map +1 -0
  333. package/esm/rag/rerank/llm-reranker.mjs +85 -0
  334. package/esm/rag/rerank/llm-reranker.mjs.map +1 -0
  335. package/esm/rag/rerank/reranker.contract.d.mts +28 -0
  336. package/esm/rag/rerank/reranker.contract.d.mts.map +1 -0
  337. package/esm/rag/retrieve.mjs +68 -0
  338. package/esm/rag/retrieve.mjs.map +1 -0
  339. package/esm/rag/store/cache-vector-store.d.mts +27 -0
  340. package/esm/rag/store/cache-vector-store.d.mts.map +1 -0
  341. package/esm/rag/store/cache-vector-store.mjs +48 -0
  342. package/esm/rag/store/cache-vector-store.mjs.map +1 -0
  343. package/esm/rag/store/vector-store.contract.d.mts +38 -0
  344. package/esm/rag/store/vector-store.contract.d.mts.map +1 -0
  345. package/esm/rag/transforms/multi-query.d.mts +27 -0
  346. package/esm/rag/transforms/multi-query.d.mts.map +1 -0
  347. package/esm/rag/transforms/multi-query.mjs +41 -0
  348. package/esm/rag/transforms/multi-query.mjs.map +1 -0
  349. package/esm/security/index.mjs +5 -0
  350. package/esm/security/outbound-policy.d.mts +46 -0
  351. package/esm/security/outbound-policy.d.mts.map +1 -0
  352. package/esm/security/outbound-policy.mjs +187 -0
  353. package/esm/security/outbound-policy.mjs.map +1 -0
  354. package/esm/security/outbound-policy.type.d.mts +74 -0
  355. package/esm/security/outbound-policy.type.d.mts.map +1 -0
  356. package/esm/security/private-ip.d.mts +15 -0
  357. package/esm/security/private-ip.d.mts.map +1 -0
  358. package/esm/security/private-ip.mjs +48 -0
  359. package/esm/security/private-ip.mjs.map +1 -0
  360. package/esm/security/redact.d.mts +59 -0
  361. package/esm/security/redact.d.mts.map +1 -0
  362. package/esm/security/redact.mjs +122 -0
  363. package/esm/security/redact.mjs.map +1 -0
  364. package/esm/serve/serve.d.mts +50 -0
  365. package/esm/serve/serve.d.mts.map +1 -0
  366. package/esm/serve/serve.mjs +90 -0
  367. package/esm/serve/serve.mjs.map +1 -0
  368. package/esm/serve/sse.d.mts +20 -0
  369. package/esm/serve/sse.d.mts.map +1 -0
  370. package/esm/serve/sse.mjs +25 -0
  371. package/esm/serve/sse.mjs.map +1 -0
  372. package/esm/serve/stream-to-sse.d.mts +29 -0
  373. package/esm/serve/stream-to-sse.d.mts.map +1 -0
  374. package/esm/serve/stream-to-sse.mjs +37 -0
  375. package/esm/serve/stream-to-sse.mjs.map +1 -0
  376. package/esm/skills/catalog.d.mts +49 -0
  377. package/esm/skills/catalog.d.mts.map +1 -0
  378. package/esm/skills/catalog.mjs +140 -0
  379. package/esm/skills/catalog.mjs.map +1 -0
  380. package/esm/skills/contracts/skill-record.type.d.mts +37 -0
  381. package/esm/skills/contracts/skill-record.type.d.mts.map +1 -0
  382. package/esm/skills/contracts/skills-config.type.d.mts +108 -0
  383. package/esm/skills/contracts/skills-config.type.d.mts.map +1 -0
  384. package/esm/skills/contracts/skills-store.contract.d.mts +28 -0
  385. package/esm/skills/contracts/skills-store.contract.d.mts.map +1 -0
  386. package/esm/skills/contracts/skills.contract.d.mts +43 -0
  387. package/esm/skills/contracts/skills.contract.d.mts.map +1 -0
  388. package/esm/skills/index.d.mts +16 -0
  389. package/esm/skills/index.mjs +14 -0
  390. package/esm/skills/load-skill-tool.d.mts +38 -0
  391. package/esm/skills/load-skill-tool.d.mts.map +1 -0
  392. package/esm/skills/load-skill-tool.mjs +65 -0
  393. package/esm/skills/load-skill-tool.mjs.map +1 -0
  394. package/esm/skills/review-gate.d.mts +33 -0
  395. package/esm/skills/review-gate.d.mts.map +1 -0
  396. package/esm/skills/review-gate.mjs +60 -0
  397. package/esm/skills/review-gate.mjs.map +1 -0
  398. package/esm/skills/save-skill-tool.d.mts +39 -0
  399. package/esm/skills/save-skill-tool.d.mts.map +1 -0
  400. package/esm/skills/save-skill-tool.mjs +65 -0
  401. package/esm/skills/save-skill-tool.mjs.map +1 -0
  402. package/esm/skills/skills.d.mts +33 -0
  403. package/esm/skills/skills.d.mts.map +1 -0
  404. package/esm/skills/skills.mjs +109 -0
  405. package/esm/skills/skills.mjs.map +1 -0
  406. package/esm/skills/sources/directory-source.d.mts +19 -0
  407. package/esm/skills/sources/directory-source.d.mts.map +1 -0
  408. package/esm/skills/sources/directory-source.mjs +108 -0
  409. package/esm/skills/sources/directory-source.mjs.map +1 -0
  410. package/esm/skills/sources/index.d.mts +18 -0
  411. package/esm/skills/sources/index.d.mts.map +1 -0
  412. package/esm/skills/sources/index.mjs +27 -0
  413. package/esm/skills/sources/index.mjs.map +1 -0
  414. package/esm/skills/sources/parse-frontmatter.d.mts +27 -0
  415. package/esm/skills/sources/parse-frontmatter.d.mts.map +1 -0
  416. package/esm/skills/sources/parse-frontmatter.mjs +46 -0
  417. package/esm/skills/sources/parse-frontmatter.mjs.map +1 -0
  418. package/esm/skills/sources/store-source.d.mts +14 -0
  419. package/esm/skills/sources/store-source.d.mts.map +1 -0
  420. package/esm/skills/sources/store-source.mjs +15 -0
  421. package/esm/skills/sources/store-source.mjs.map +1 -0
  422. package/esm/skills/sources/url-source.d.mts +29 -0
  423. package/esm/skills/sources/url-source.d.mts.map +1 -0
  424. package/esm/skills/sources/url-source.mjs +117 -0
  425. package/esm/skills/sources/url-source.mjs.map +1 -0
  426. package/esm/skills/store/mock-skills-store.d.mts +57 -0
  427. package/esm/skills/store/mock-skills-store.d.mts.map +1 -0
  428. package/esm/skills/store/mock-skills-store.mjs +100 -0
  429. package/esm/skills/store/mock-skills-store.mjs.map +1 -0
  430. package/esm/skills/store/procedural-skill-store.d.mts +30 -0
  431. package/esm/skills/store/procedural-skill-store.d.mts.map +1 -0
  432. package/esm/skills/store/procedural-skill-store.mjs +125 -0
  433. package/esm/skills/store/procedural-skill-store.mjs.map +1 -0
  434. package/esm/supervisor/as-tool.mjs +2 -2
  435. package/esm/supervisor/as-tool.mjs.map +1 -1
  436. package/esm/supervisor/execution.d.mts.map +1 -1
  437. package/esm/supervisor/execution.mjs +31 -28
  438. package/esm/supervisor/execution.mjs.map +1 -1
  439. package/esm/supervisor/supervisor.d.mts.map +1 -1
  440. package/esm/supervisor/supervisor.mjs +8 -3
  441. package/esm/supervisor/supervisor.mjs.map +1 -1
  442. package/esm/system-prompt/index.d.mts +4 -0
  443. package/esm/system-prompt/system-prompt.d.mts +68 -4
  444. package/esm/system-prompt/system-prompt.d.mts.map +1 -1
  445. package/esm/system-prompt/system-prompt.mjs +89 -5
  446. package/esm/system-prompt/system-prompt.mjs.map +1 -1
  447. package/esm/team/gates.mjs +48 -0
  448. package/esm/team/gates.mjs.map +1 -0
  449. package/esm/team/index.d.mts +1 -0
  450. package/esm/team/index.mjs +3 -0
  451. package/esm/team/team.d.mts +42 -0
  452. package/esm/team/team.d.mts.map +1 -0
  453. package/esm/team/team.mjs +94 -0
  454. package/esm/team/team.mjs.map +1 -0
  455. package/esm/tool/executable-as-tool.d.mts.map +1 -1
  456. package/esm/tool/executable-as-tool.mjs +2 -2
  457. package/esm/tool/executable-as-tool.mjs.map +1 -1
  458. package/esm/tool/tool.d.mts.map +1 -1
  459. package/esm/tool/tool.mjs +2 -2
  460. package/esm/tool/tool.mjs.map +1 -1
  461. package/esm/utils/compute-cost.d.mts +17 -1
  462. package/esm/utils/compute-cost.d.mts.map +1 -1
  463. package/esm/utils/compute-cost.mjs +26 -1
  464. package/esm/utils/compute-cost.mjs.map +1 -1
  465. package/esm/utils/extract-json-lenient.d.mts +42 -0
  466. package/esm/utils/extract-json-lenient.d.mts.map +1 -0
  467. package/esm/utils/extract-json-lenient.mjs +97 -0
  468. package/esm/utils/extract-json-lenient.mjs.map +1 -0
  469. package/esm/utils/index.d.mts +4 -2
  470. package/esm/utils/index.mjs +3 -1
  471. package/esm/utils/json-schema.d.mts +1 -1
  472. package/esm/utils/prepare-attachment-part.d.mts +10 -1
  473. package/esm/utils/prepare-attachment-part.d.mts.map +1 -1
  474. package/esm/utils/prepare-attachment-part.mjs +103 -11
  475. package/esm/utils/prepare-attachment-part.mjs.map +1 -1
  476. package/esm/utils/resolve-attachment.d.mts +4 -3
  477. package/esm/utils/resolve-attachment.d.mts.map +1 -1
  478. package/esm/utils/resolve-attachment.mjs +4 -3
  479. package/esm/utils/resolve-attachment.mjs.map +1 -1
  480. package/esm/utils/run-context.d.mts +94 -0
  481. package/esm/utils/run-context.d.mts.map +1 -0
  482. package/esm/utils/run-context.mjs +98 -0
  483. package/esm/utils/run-context.mjs.map +1 -0
  484. package/esm/vcr/cassette-io.mjs +57 -0
  485. package/esm/vcr/cassette-io.mjs.map +1 -0
  486. package/esm/vcr/errors.d.mts +42 -0
  487. package/esm/vcr/errors.d.mts.map +1 -0
  488. package/esm/vcr/errors.mjs +37 -0
  489. package/esm/vcr/errors.mjs.map +1 -0
  490. package/esm/vcr/hash-request.d.mts +28 -0
  491. package/esm/vcr/hash-request.d.mts.map +1 -0
  492. package/esm/vcr/hash-request.mjs +118 -0
  493. package/esm/vcr/hash-request.mjs.map +1 -0
  494. package/esm/vcr/index.d.mts +4 -0
  495. package/esm/vcr/index.mjs +5 -0
  496. package/esm/vcr/vcr.d.mts +32 -0
  497. package/esm/vcr/vcr.d.mts.map +1 -0
  498. package/esm/vcr/vcr.mjs +248 -0
  499. package/esm/vcr/vcr.mjs.map +1 -0
  500. package/esm/vcr/vcr.type.d.mts +118 -0
  501. package/esm/vcr/vcr.type.d.mts.map +1 -0
  502. package/esm/workflow/as-tool.mjs +2 -2
  503. package/esm/workflow/as-tool.mjs.map +1 -1
  504. package/esm/workflow/engine.mjs +1 -0
  505. package/esm/workflow/engine.mjs.map +1 -1
  506. package/esm/workflow/step-runner.mjs +19 -20
  507. package/esm/workflow/step-runner.mjs.map +1 -1
  508. package/esm/workflow/workflow.d.mts.map +1 -1
  509. package/esm/workflow/workflow.mjs +8 -3
  510. package/esm/workflow/workflow.mjs.map +1 -1
  511. package/llms-full.txt +1683 -68
  512. package/llms.txt +16 -4
  513. package/package.json +7 -3
  514. package/skills/README.md +40 -4
  515. package/skills/ai-dx-helpers/SKILL.md +2 -2
  516. package/skills/approve-tool-calls/SKILL.md +134 -0
  517. package/skills/attach-ai-middleware/SKILL.md +1 -1
  518. package/skills/detect-and-redact-pii/SKILL.md +104 -0
  519. package/skills/durable-resume/SKILL.md +128 -0
  520. package/skills/escalate-block-to-human/SKILL.md +85 -0
  521. package/skills/eval-datasets-and-ci/SKILL.md +117 -0
  522. package/skills/guard-input-output/SKILL.md +117 -0
  523. package/skills/manage-prompts/SKILL.md +186 -0
  524. package/skills/observe-ai-flows/SKILL.md +94 -0
  525. package/skills/record-replay-llm/SKILL.md +92 -0
  526. package/skills/run-ai-agent/SKILL.md +26 -1
  527. package/skills/run-ai-rag/SKILL.md +139 -0
  528. package/skills/run-ai-team/SKILL.md +107 -0
  529. package/skills/run-orchestrator/SKILL.md +2 -0
  530. package/skills/run-planner/SKILL.md +73 -8
  531. package/skills/run-supervisor/SKILL.md +20 -1
  532. package/skills/use-runtime-skills/SKILL.md +106 -0
  533. package/skills/write-system-prompt/SKILL.md +30 -1
  534. package/cjs/index.cjs.map +0 -1
  535. package/esm/contracts/result/index.d.mts +0 -15
@@ -0,0 +1,73 @@
1
+ import { isNestedRun } from "../utils/run-context.mjs";
2
+ import { getObservers, isObserveAll } from "./observer-registry.mjs";
3
+
4
+ //#region ../@warlock.js/ai/src/observe/resolve-observers.ts
5
+ /**
6
+ * Resolve a flow's `observe` option into the concrete list of
7
+ * {@link Observer}s to notify with that flow's completed report:
8
+ *
9
+ * - `false` → `[]` (opted out).
10
+ * - `true` → the globally registered observers.
11
+ * - an `Observer` object → just that one (flow-local).
12
+ * - `undefined` → the globally registered observers when observe-all is
13
+ * on AND this is a ROOT run, otherwise `[]`.
14
+ *
15
+ * Reads the ambient {@link currentRunFrame} for the observe-all path:
16
+ * flows call it at completion, so a present frame means the run is nested
17
+ * inside an orchestration callback and is already attached to its parent's
18
+ * report tree — self-routing it again would double-count it as a separate
19
+ * top-level trace (and double its tokens/cost in the aggregate). Explicit
20
+ * `observe: true` / an `Observer` still route regardless of nesting.
21
+ */
22
+ function resolveObservers(observe) {
23
+ if (observe === false) return [];
24
+ if (observe === true) return getObservers();
25
+ if (observe !== void 0) return [observe];
26
+ return isObserveAll() && !isNestedRun() ? getObservers() : [];
27
+ }
28
+ /**
29
+ * Observers whose `collect()` already threw once — so the isolate-but-
30
+ * surface warning fires at most once per observer object, never spamming
31
+ * the log when every flow report hits the same broken exporter. Keyed by
32
+ * object identity via a {@link WeakSet} so a discarded observer is GC'd
33
+ * without leaking. Mirrors panoptic's per-exporter `warnedExporters`.
34
+ */
35
+ const warnedObservers = /* @__PURE__ */ new WeakSet();
36
+ /**
37
+ * Route a completed flow report to every observer the flow's `observe`
38
+ * option resolves to. Each `collect` is awaited so async exporters
39
+ * finish before the flow returns; a throw is **isolated** (never breaks
40
+ * the run) but no longer **silent** — it is surfaced via `onError` when
41
+ * supplied, otherwise a `console.warn` once per observer. A broken
42
+ * observer/exporter must not disappear from production with no signal
43
+ * (C5). Adopts the isolate-but-surface pattern panoptic's collector
44
+ * already uses for exporters.
45
+ */
46
+ async function notifyObservers(observe, report, onError) {
47
+ for (const observer of resolveObservers(observe)) try {
48
+ await observer.collect(report);
49
+ } catch (error) {
50
+ surfaceObserverError(observer, error, onError);
51
+ }
52
+ }
53
+ /**
54
+ * Surface an isolated observer failure without ever rethrowing into the
55
+ * flow. Prefers the caller-supplied `onError` (itself guarded so a
56
+ * throwing handler can't escape); otherwise warns once per observer.
57
+ */
58
+ function surfaceObserverError(observer, error, onError) {
59
+ if (onError) {
60
+ try {
61
+ onError(error, observer);
62
+ } catch {}
63
+ return;
64
+ }
65
+ if (warnedObservers.has(observer)) return;
66
+ warnedObservers.add(observer);
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ console.warn(`[warlock-ai] an observer's collect() threw and was isolated: ${message}`);
69
+ }
70
+
71
+ //#endregion
72
+ export { notifyObservers, resolveObservers };
73
+ //# sourceMappingURL=resolve-observers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-observers.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/observe/resolve-observers.ts"],"sourcesContent":["import { isNestedRun } from \"../utils/run-context\";\nimport { getObservers, isObserveAll } from \"./observer-registry\";\nimport type { Observer } from \"./observer.contract\";\n\n/**\n * The value a flow's `observe` config option may take. Additive and\n * gated — when `undefined` (the default), behavior follows the global\n * observe-all flag, so a flow that never sets `observe` behaves exactly\n * as before unless an observability tool turned observe-all on.\n *\n * - `true` → route this flow to the globally registered observers,\n * even when observe-all is off.\n * - `false` → opt this flow out entirely, even when observe-all is on.\n * - an {@link Observer} object → a flow-local collector; only this flow's\n * report is routed, and only to it (the global observers are skipped).\n * A panoptic flow-local collector implements `Observer`, so it can be\n * passed here directly — core stays panoptic-agnostic.\n * - `undefined` → follow the global observe-all flag.\n */\nexport type FlowObserveOption = boolean | Observer;\n\n/**\n * Resolve a flow's `observe` option into the concrete list of\n * {@link Observer}s to notify with that flow's completed report:\n *\n * - `false` → `[]` (opted out).\n * - `true` → the globally registered observers.\n * - an `Observer` object → just that one (flow-local).\n * - `undefined` → the globally registered observers when observe-all is\n * on AND this is a ROOT run, otherwise `[]`.\n *\n * Reads the ambient {@link currentRunFrame} for the observe-all path:\n * flows call it at completion, so a present frame means the run is nested\n * inside an orchestration callback and is already attached to its parent's\n * report tree — self-routing it again would double-count it as a separate\n * top-level trace (and double its tokens/cost in the aggregate). Explicit\n * `observe: true` / an `Observer` still route regardless of nesting.\n */\nexport function resolveObservers(observe: FlowObserveOption | undefined): readonly Observer[] {\n if (observe === false) {\n return [];\n }\n\n if (observe === true) {\n return getObservers();\n }\n\n if (observe !== undefined) {\n return [observe];\n }\n\n // Observe-all captures ROOT runs only. A run nested inside any parent\n // capture (orchestration callback, supervisor member dispatch, workflow\n // step) already nests in its parent's report, so routing it here too would\n // duplicate it as a standalone top-level trace.\n return isObserveAll() && !isNestedRun() ? getObservers() : [];\n}\n\n/**\n * Observers whose `collect()` already threw once — so the isolate-but-\n * surface warning fires at most once per observer object, never spamming\n * the log when every flow report hits the same broken exporter. Keyed by\n * object identity via a {@link WeakSet} so a discarded observer is GC'd\n * without leaking. Mirrors panoptic's per-exporter `warnedExporters`.\n */\nconst warnedObservers = new WeakSet<Observer>();\n\n/**\n * Route a completed flow report to every observer the flow's `observe`\n * option resolves to. Each `collect` is awaited so async exporters\n * finish before the flow returns; a throw is **isolated** (never breaks\n * the run) but no longer **silent** — it is surfaced via `onError` when\n * supplied, otherwise a `console.warn` once per observer. A broken\n * observer/exporter must not disappear from production with no signal\n * (C5). Adopts the isolate-but-surface pattern panoptic's collector\n * already uses for exporters.\n */\nexport async function notifyObservers(\n observe: FlowObserveOption | undefined,\n report: Parameters<Observer[\"collect\"]>[0],\n onError?: (error: unknown, observer: Observer) => void,\n): Promise<void> {\n for (const observer of resolveObservers(observe)) {\n try {\n await observer.collect(report);\n } catch (error) {\n surfaceObserverError(observer, error, onError);\n }\n }\n}\n\n/**\n * Surface an isolated observer failure without ever rethrowing into the\n * flow. Prefers the caller-supplied `onError` (itself guarded so a\n * throwing handler can't escape); otherwise warns once per observer.\n */\nfunction surfaceObserverError(\n observer: Observer,\n error: unknown,\n onError?: (error: unknown, observer: Observer) => void,\n): void {\n if (onError) {\n try {\n onError(error, observer);\n } catch {\n // Never let the error handler itself escape into the flow.\n }\n return;\n }\n\n if (warnedObservers.has(observer)) return;\n warnedObservers.add(observer);\n\n const message = error instanceof Error ? error.message : String(error);\n console.warn(`[warlock-ai] an observer's collect() threw and was isolated: ${message}`);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,iBAAiB,SAA6D;CAC5F,IAAI,YAAY,OACd,OAAO,CAAC;CAGV,IAAI,YAAY,MACd,OAAO,aAAa;CAGtB,IAAI,YAAY,QACd,OAAO,CAAC,OAAO;CAOjB,OAAO,aAAa,KAAK,CAAC,YAAY,IAAI,aAAa,IAAI,CAAC;AAC9D;;;;;;;;AASA,MAAM,kCAAkB,IAAI,QAAkB;;;;;;;;;;;AAY9C,eAAsB,gBACpB,SACA,QACA,SACe;CACf,KAAK,MAAM,YAAY,iBAAiB,OAAO,GAC7C,IAAI;EACF,MAAM,SAAS,QAAQ,MAAM;CAC/B,SAAS,OAAO;EACd,qBAAqB,UAAU,OAAO,OAAO;CAC/C;AAEJ;;;;;;AAOA,SAAS,qBACP,UACA,OACA,SACM;CACN,IAAI,SAAS;EACX,IAAI;GACF,QAAQ,OAAO,QAAQ;EACzB,QAAQ,CAER;EACA;CACF;CAEA,IAAI,gBAAgB,IAAI,QAAQ,GAAG;CACnC,gBAAgB,IAAI,QAAQ;CAE5B,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;CACrE,QAAQ,KAAK,gEAAgE,SAAS;AACxF"}
@@ -1 +1 @@
1
- {"version":3,"file":"execution.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/execution.ts"],"mappings":";;;;;;;;;;;;;;AAmEA;;;;;;;;;;;KAAY,2BAAA;EACV,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,MAAA,GAOY;EALhD,OAAA,GAAU,GAAA,SAAY,mBAAA;EACtB,SAAA;EACA,OAAA,EAAS,mBAAA;EACT,KAAA,GAAQ,eAAA;EACR,OAAA,GAAU,0BAAA,CAA2B,MAAA;EACrC,gBAAA,GAAmB,4BAAA,CAA6B,kBAAA,CAAmB,OAAA;EACnE,eAAA;EACA,aAAA,GAAgB,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;cAsBL,qBAAA;EAAA,iBACM,MAAA;EAAA,iBACA,GAAA;EAAA,iBACA,gBAAA;cAIE,MAAA,EAAQ,2BAAA,CAA4B,OAAA,EAAS,MAAA;EAAT;;;;;;EAyB1C,GAAA,IAAO,OAAA,CAAQ,kBAAA,CAAmB,OAAA;EA4BhB;;;;EAAlB,MAAA,IAAU,OAAA,CAAQ,kBAAA,CAAmB,OAAA;EAiBxC;;;;;EAFG,OAAA,CACX,IAAA,EAAM,oBAAA,sBACL,OAAA,CAAQ,oBAAA;AAAA;;;;;;;;;;;;iBAkPS,OAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,KAAA,EAAO,eAAA,EACP,OAAA,EAAS,0BAAA,CAA2B,MAAA,IACnC,OAAA,CAAQ,kBAAA,CAAmB,OAAA;;;;;;;;AAtPG;AAkPjC;;iBA2MsB,SAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,SAAA,UACA,OAAA,GAAU,yBAAA,GACT,OAAA,CAAQ,kBAAA,CAAmB,OAAA;;;;;;;;;;;iBAiDR,UAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,KAAA,EAAO,eAAA,EACP,OAAA,EAAS,0BAAA,CAA2B,MAAA,IACnC,OAAA,CAAQ,kBAAA,CAAmB,OAAA"}
1
+ {"version":3,"file":"execution.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/execution.ts"],"mappings":";;;;;;;;;;;;;;AAqEA;;;;;;;;;;;KAAY,2BAAA;EACV,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,MAAA,GAOY;EALhD,OAAA,GAAU,GAAA,SAAY,mBAAA;EACtB,SAAA;EACA,OAAA,EAAS,mBAAA;EACT,KAAA,GAAQ,eAAA;EACR,OAAA,GAAU,0BAAA,CAA2B,MAAA;EACrC,gBAAA,GAAmB,4BAAA,CAA6B,kBAAA,CAAmB,OAAA;EACnE,eAAA;EACA,aAAA,GAAgB,yBAAA;AAAA;;;;;;;;;;;;;;;;;;;;cAsBL,qBAAA;EAAA,iBACM,MAAA;EAAA,iBACA,GAAA;EAAA,iBACA,gBAAA;cAIE,MAAA,EAAQ,2BAAA,CAA4B,OAAA,EAAS,MAAA;EAAT;;;;;;EAyB1C,GAAA,IAAO,OAAA,CAAQ,kBAAA,CAAmB,OAAA;EAiChB;;;;EAAlB,MAAA,IAAU,OAAA,CAAQ,kBAAA,CAAmB,OAAA;EAiBxC;;;;;EAFG,OAAA,CACX,IAAA,EAAM,oBAAA,sBACL,OAAA,CAAQ,oBAAA;AAAA;;;;;;;;;;;;iBAuPS,OAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,KAAA,EAAO,eAAA,EACP,OAAA,EAAS,0BAAA,CAA2B,MAAA,IACnC,OAAA,CAAQ,kBAAA,CAAmB,OAAA;;;;;;;;AA3PG;AAuPjC;;iBA4MsB,SAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,SAAA,UACA,OAAA,GAAU,yBAAA,GACT,OAAA,CAAQ,kBAAA,CAAmB,OAAA;;;;;;;;;;;iBAiDR,UAAA,kBACpB,GAAA,EAAK,yBAAA,CAA0B,OAAA,EAAS,MAAA,GACxC,KAAA,EAAO,eAAA,EACP,OAAA,EAAS,0BAAA,CAA2B,MAAA,IACnC,OAAA,CAAQ,kBAAA,CAAmB,OAAA"}
@@ -4,6 +4,7 @@ import "../errors/index.mjs";
4
4
  import { generateRunId } from "../utils/generate-run-id.mjs";
5
5
  import { REPORT_SCHEMA_VERSION } from "../contracts/result/base-report.type.mjs";
6
6
  import { resolveDefaultCheckpointStore, resolveDefaultSnapshotStore } from "../config.mjs";
7
+ import { notifyObservers } from "../observe/resolve-observers.mjs";
7
8
  import { injectMemories, outcomeTextFromTurn, recallForTurn, rememberTurnOutcome, resolveOrchestratorMemory } from "./memory.mjs";
8
9
  import { persistCheckpoint, summarizeRoute } from "./checkpoint.mjs";
9
10
  import { acquireLock } from "./lock.mjs";
@@ -62,6 +63,7 @@ var OrchestratorExecution = class {
62
63
  if (this.params.input === void 0 || !this.params.options) throw new OrchestratorConfigError(`ai.orchestrator("${this.params.config.name}"): internal — run() invoked without input/options`);
63
64
  try {
64
65
  const result = await runTurn(this.ctx, this.params.input, this.params.options);
66
+ await notifyObservers(this.ctx.config.observe, result.report);
65
67
  this.streamController?.end(result);
66
68
  return result;
67
69
  } catch (error) {
@@ -183,7 +185,7 @@ function applyStatePatch(seed, patch) {
183
185
  * `children[]` carries only the CURRENT turn's dispatched primitive
184
186
  * reports) while the per-turn forensic record lives on `turns[]`.
185
187
  */
186
- function buildReport(ctx, sessionId, turnIndex, status, turnSnapshot, childReport) {
188
+ function buildReport(ctx, sessionId, turnIndex, status, turnSnapshot, childReport, error) {
187
189
  const now = (/* @__PURE__ */ new Date()).toISOString();
188
190
  const usage = turnSnapshot?.usage ?? childReport?.usage ?? ZERO_USAGE;
189
191
  return {
@@ -194,6 +196,7 @@ function buildReport(ctx, sessionId, turnIndex, status, turnSnapshot, childRepor
194
196
  sessionId,
195
197
  type: "orchestrator",
196
198
  status,
199
+ ...error ? { error } : {},
197
200
  startedAt: turnSnapshot?.startedAt ?? now,
198
201
  endedAt: turnSnapshot?.endedAt ?? now,
199
202
  duration: turnSnapshot?.duration ?? 0,
@@ -298,7 +301,7 @@ async function runTurn(ctx, input, options) {
298
301
  });
299
302
  const status = result.error ? deriveStatus(result.report.status) : "awaiting-input";
300
303
  if (result.error) {
301
- const report = buildReport(ctx, sessionId, loaded.turnIndex, status, turnSnapshot, result.report);
304
+ const report = buildReport(ctx, sessionId, loaded.turnIndex, status, turnSnapshot, result.report, result.error);
302
305
  emitTerminal(ctx, sessionId, loaded.turnIndex, status);
303
306
  return {
304
307
  data: result.data,
@@ -1 +1 @@
1
- {"version":3,"file":"execution.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/execution.ts"],"sourcesContent":["import type { Message } from \"../contracts/conversation-message.type\";\nimport type { OrchestratorCommands } from \"../contracts/orchestrator/orchestrator-commands.type\";\nimport type { OrchestratorConfig } from \"../contracts/orchestrator/orchestrator-config.type\";\nimport type {\n OrchestratorEvent,\n OrchestratorEventHandlers,\n OrchestratorEventMap,\n OrchestratorEventName,\n} from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type {\n OrchestratorExecuteOptions,\n OrchestratorResumeOptions,\n} from \"../contracts/orchestrator/orchestrator-execute-options.type\";\nimport type {\n CompactionResult,\n OrchestratorReport,\n OrchestratorReportStatus,\n OrchestratorResult,\n TurnSnapshot,\n} from \"../contracts/result/orchestrator-result.type\";\nimport { REPORT_SCHEMA_VERSION } from \"../contracts/result/base-report.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport type { EventIdentity } from \"../contracts/events/event-identity.type\";\nimport {\n resolveDefaultCheckpointStore,\n resolveDefaultSnapshotStore,\n} from \"../config\";\nimport { OrchestratorConfigError, OrchestratorDriftError } from \"../errors\";\nimport type { ResolvedIntentEntry } from \"../supervisor/entries\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport { persistCheckpoint, summarizeRoute } from \"./checkpoint\";\nimport { runCompaction, runManualCompaction, shouldCompact } from \"./compaction\";\nimport { deriveRunId, dispatchTurn } from \"./dispatch\";\nimport type { OrchestratorEmitter } from \"./emitter\";\nimport type { OrchestratorEmitterLike } from \"./emitter-port.type\";\nimport type { OrchestratorEngineContext } from \"./engine-context.type\";\nimport { acquireLock } from \"./lock\";\nimport { loadSession } from \"./load\";\nimport {\n injectMemories,\n outcomeTextFromTurn,\n recallForTurn,\n rememberTurnOutcome,\n resolveOrchestratorMemory,\n} from \"./memory\";\nimport type { OrchestratorStreamController } from \"./orchestrator-stream\";\nimport { resolveResume } from \"./resume\";\nimport { windowHistory } from \"./window\";\n\n/** Empty rolled-up usage for turns that never dispatched (drift/seed). */\nconst ZERO_USAGE: Usage = { input: 0, output: 0, total: 0 };\n\n/**\n * Constructor params the C1 factory passes when building an\n * {@link OrchestratorExecution} per call. The factory owns author-time\n * validation, intent-entry resolution, and signature computation; it\n * hands the engine the validated `config`, the resolved `entries`, the\n * computed `signature`, and the shared three-tier `emitter`. The\n * per-call inputs vary by entry point:\n *\n * - `execute` / `stream` — `input` + `options` (and `streamController`\n * for `stream`).\n * - `resume` — `resumeSessionId` + `resumeOptions`.\n * - `command(\"compact\")` — neither; `compact(args)` carries its own.\n */\nexport type OrchestratorExecutionParams<TOutput, TState> = {\n config: OrchestratorConfig<TOutput, TState>;\n /** Resolved intent entries (validated by C1; the engine delegates dispatch to the supervisor). */\n entries?: Map<string, ResolvedIntentEntry>;\n signature: string;\n emitter: OrchestratorEmitter;\n input?: SupervisorInput;\n options?: OrchestratorExecuteOptions<TState>;\n streamController?: OrchestratorStreamController<OrchestratorResult<TOutput>>;\n resumeSessionId?: string;\n resumeOptions?: OrchestratorResumeOptions;\n};\n\n/**\n * Per-call lifecycle engine — the single object the C1 factory\n * constructs and drives. Owns the 7-phase lifecycle (orchestrator.md §3:\n * load → drift → lock → window → dispatch → persist → compaction),\n * resolving the durable stores (own config field → `ai.config` default)\n * and adapting C1's three-tier {@link OrchestratorEmitter} to the\n * {@link OrchestratorEmitterLike} port the phase modules call.\n *\n * The factory creates a fresh instance per `execute` / `stream` /\n * `resume` / `command` call (single-call lifecycle invariant — §18.8);\n * the heavy lifting lives in the standalone phase functions\n * ({@link runTurn} / {@link runResume}) which this class delegates to.\n *\n * @example\n * const execution = new OrchestratorExecution({\n * config, entries, signature, emitter, input, options,\n * });\n * const result = await execution.run();\n */\nexport class OrchestratorExecution<TOutput, TState> {\n private readonly params: OrchestratorExecutionParams<TOutput, TState>;\n private readonly ctx: OrchestratorEngineContext<TOutput, TState>;\n private readonly streamController?: OrchestratorStreamController<\n OrchestratorResult<TOutput>\n >;\n\n public constructor(params: OrchestratorExecutionParams<TOutput, TState>) {\n this.params = params;\n this.streamController = params.streamController;\n this.ctx = {\n config: params.config,\n signature: params.signature,\n checkpointStore: resolveCheckpointStore(params.config),\n snapshotStore: resolveSnapshotStore(params.config),\n emitter: adaptEmitter(\n params.emitter,\n generateRunId(\"orchestrator\"),\n this.streamController as\n | OrchestratorStreamController<unknown>\n | undefined,\n ),\n memory: resolveOrchestratorMemory(params.config.memory),\n };\n }\n\n /**\n * `execute()` / `stream()` entry — run one turn through the 7-phase\n * lifecycle. When a `streamController` was supplied, the adapter mirrors\n * every emitted event into the stream and the controller is settled\n * (`end` / `fail`) once the result resolves.\n */\n public async run(): Promise<OrchestratorResult<TOutput>> {\n if (this.params.input === undefined || !this.params.options) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${this.params.config.name}\"): internal — run() invoked without input/options`,\n );\n }\n\n try {\n const result = await runTurn(\n this.ctx,\n this.params.input,\n this.params.options,\n );\n\n this.streamController?.end(result);\n\n return result;\n } catch (error) {\n this.streamController?.fail(error as Error);\n\n throw error;\n }\n }\n\n /**\n * `resume()` entry — drain an interrupted `iterate: true` turn (§9).\n * Returns `null` when nothing is in flight.\n */\n public async resume(): Promise<OrchestratorResult<TOutput> | null> {\n if (!this.params.resumeSessionId) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${this.params.config.name}\"): internal — resume() invoked without a sessionId`,\n );\n }\n\n return runResume(this.ctx, this.params.resumeSessionId, this.params.resumeOptions);\n }\n\n /**\n * `command(\"compact\")` entry — run a manual compaction on demand (§11 /\n * §12.1). Reuses the post-turn compaction code path against the\n * caller-supplied history and returns the raw {@link CompactionResult}.\n */\n public async compact(\n args: OrchestratorCommands[\"compact\"][\"args\"],\n ): Promise<OrchestratorCommands[\"compact\"][\"result\"]> {\n return runManualCompaction(\n this.ctx as OrchestratorEngineContext<unknown, TState>,\n args.history,\n );\n }\n}\n\n/**\n * Resolve the durable checkpoint store: the config's own field, falling\n * back to `ai.config({ defaultCheckpointStore })`. Throws\n * {@link OrchestratorConfigError} when neither resolves — persistence is\n * always on (§8.1), so a turn can never run without a checkpoint store.\n */\nfunction resolveCheckpointStore<TOutput, TState>(\n config: OrchestratorConfig<TOutput, TState>,\n) {\n const store = config.checkpointStore ?? resolveDefaultCheckpointStore();\n\n if (!store) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): a \\`checkpointStore\\` is required ` +\n `(set one on the config or via \\`ai.config({ defaultCheckpointStore })\\`)`,\n );\n }\n\n return store;\n}\n\n/**\n * Resolve the internal-supervisor snapshot store for `iterate: true`\n * turns: the config's own field, falling back to\n * `ai.config({ defaultSnapshotStore })`. Returns `undefined` for\n * `iterate: false` orchestrators (no mid-turn resume — nothing to\n * snapshot). The factory already guarantees presence when\n * `iterate: true`, so the engine never asserts here.\n */\nfunction resolveSnapshotStore<TOutput, TState>(\n config: OrchestratorConfig<TOutput, TState>,\n) {\n if (config.iterate !== true) {\n return undefined;\n }\n\n return config.snapshotStore ?? resolveDefaultSnapshotStore();\n}\n\n/**\n * Adapt C1's three-tier {@link OrchestratorEmitter} (whose `emit` takes\n * `event, payload, identity, perCallHandlers?`) to the\n * {@link OrchestratorEmitterLike} port the phase modules call (a 2-arg\n * `emit(event, payload)` plus `bindPerCall`).\n *\n * The adapter injects the run identity centrally and, when a stream\n * controller is present, mirrors every fully-stamped event into the\n * stream pipe (§14.1 — the orchestrator's own events surface on the\n * stream alongside the bubbled child events). `bindPerCall` registers\n * the per-call `options.on` bag for the turn's duration and returns a\n * disposer that clears it.\n */\nfunction adaptEmitter(\n emitter: OrchestratorEmitter,\n runId: string,\n streamController: OrchestratorStreamController<unknown> | undefined,\n): OrchestratorEmitterLike {\n // `rootRunId === runId` for a standalone run; nested propagation lands\n // in a follow-up (see `EventIdentity`).\n const fullIdentity: EventIdentity = { runId, rootRunId: runId };\n\n let perCall: OrchestratorEventHandlers | undefined;\n\n return {\n emit<K extends OrchestratorEventName>(\n event: K,\n payload: OrchestratorEventMap[K],\n ): void {\n const fullPayload = emitter.emit(event, payload, fullIdentity, perCall);\n\n // The discriminated-union correlation between `type` and the\n // matching payload variant can't be expressed structurally — the\n // cast mirrors the supervisor stream's established pattern.\n streamController?.push({ type: event, ...fullPayload } as OrchestratorEvent);\n },\n bindPerCall(handlers: OrchestratorEventHandlers | undefined): () => void {\n perCall = handlers;\n\n return () => {\n perCall = undefined;\n };\n },\n };\n}\n\n/**\n * Phase 2 — drift check (orchestrator.md §3 / §4 Phase 2). Compares the\n * loaded checkpoint's `signature` against the current definition's.\n * Mismatch throws `OrchestratorDriftError` synchronously unless\n * `force` is set. Emits `orchestrator.drift.checked` either way. A new\n * session (no loaded signature) never drifts.\n */\nfunction assertNoDrift(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n loadedSignature: string | undefined,\n force: boolean | undefined,\n): void {\n const drifted =\n loadedSignature !== undefined && loadedSignature !== ctx.signature;\n\n ctx.emitter.emit(\"orchestrator.drift.checked\", {\n sessionId,\n signature: ctx.signature,\n drifted,\n });\n\n if (drifted && !force) {\n throw new OrchestratorDriftError(\n `orchestrator \"${ctx.config.name}\": signature drift on session \"${sessionId}\" — ` +\n `the definition changed since this session was last persisted. ` +\n `Pass { force: true } only after reviewing the change, or discard / migrate the session.`,\n {\n savedSignature: loadedSignature as string,\n currentSignature: ctx.signature,\n sessionId,\n },\n );\n }\n}\n\n/**\n * Shallow-merge the per-call `state` patch (§5 — partial state\n * override) over the loaded session-state seed. The merged value\n * becomes the supervisor's seed for this turn.\n */\nfunction applyStatePatch<TState>(\n seed: TState,\n patch: Partial<TState> | undefined,\n): TState {\n if (!patch) {\n return seed;\n }\n\n return { ...seed, ...patch } as TState;\n}\n\n/**\n * Assemble the orchestrator-scope {@link OrchestratorReport} from the\n * dispatched turn's child report and the turn snapshot. Wraps the\n * child supervisor/agent report tree as `children[0]` (§15.6 —\n * `children[]` carries only the CURRENT turn's dispatched primitive\n * reports) while the per-turn forensic record lives on `turns[]`.\n */\nfunction buildReport(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n turnIndex: number,\n status: OrchestratorReportStatus,\n turnSnapshot: TurnSnapshot | undefined,\n childReport: BaseReport | undefined,\n): OrchestratorReport {\n const now = new Date().toISOString();\n const usage = turnSnapshot?.usage ?? childReport?.usage ?? ZERO_USAGE;\n\n return {\n runId: deriveRunId(sessionId, ctx.config.version, turnIndex),\n rootRunId: deriveRunId(sessionId, ctx.config.version, turnIndex),\n name: ctx.config.name,\n version: ctx.config.version,\n sessionId,\n type: \"orchestrator\",\n status,\n startedAt: turnSnapshot?.startedAt ?? now,\n endedAt: turnSnapshot?.endedAt ?? now,\n duration: turnSnapshot?.duration ?? 0,\n usage,\n children: childReport ? [childReport] : [],\n reportSchemaVersion: REPORT_SCHEMA_VERSION,\n turnIndex,\n signature: ctx.signature,\n turns: turnSnapshot ? [turnSnapshot] : [],\n };\n}\n\n/**\n * Map the dispatched supervisor result's report status onto the\n * orchestrator's status surface (§15.6). A clean completion that is\n * still mid-conversation reports `\"awaiting-input\"` (the session\n * continues) rather than `\"completed\"`; failures and cancellations\n * pass through.\n */\nfunction deriveStatus(childStatus: BaseReport[\"status\"]): OrchestratorReportStatus {\n if (childStatus === \"completed\") {\n return \"awaiting-input\";\n }\n\n return childStatus;\n}\n\n/**\n * Emit the terminal turn event matching the report status (§14.1).\n */\nfunction emitTerminal(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n turnIndex: number,\n status: OrchestratorReportStatus,\n): void {\n if (status === \"cancelled\") {\n ctx.emitter.emit(\"orchestrator.turn.cancelled\", { sessionId, turnIndex });\n\n return;\n }\n\n if (status === \"failed\" || status === \"max-iterations\") {\n ctx.emitter.emit(\"orchestrator.turn.failed\", { sessionId, turnIndex });\n\n return;\n }\n\n if (status === \"awaiting-input\") {\n ctx.emitter.emit(\"orchestrator.turn.awaiting-input\", {\n sessionId,\n turnIndex,\n });\n\n return;\n }\n\n ctx.emitter.emit(\"orchestrator.turn.completed\", { sessionId, turnIndex });\n}\n\n/**\n * Run one turn end-to-end through the 7-phase lifecycle (orchestrator\n * .md §3). The single entry the C1 factory's `execute()` delegates to.\n *\n * Phase order is the diagram's contract: load → drift → lock → window\n * → dispatch → persist → compaction. Drift / config misuse throw;\n * every other failure surfaces on `result.error` (the contract: the\n * orchestrator never throws on runtime failure). Cancellation and\n * failure do NOT persist a fresh checkpoint (§17 — state reverts to the\n * pre-turn checkpoint).\n */\nexport async function runTurn<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n): Promise<OrchestratorResult<TOutput>> {\n const sessionId = options.sessionId;\n const disposePerCall = ctx.emitter.bindPerCall(options.on);\n\n try {\n // Phase 1 — load session.\n const loaded = await loadSession(ctx, sessionId);\n\n ctx.emitter.emit(\"orchestrator.turn.starting\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n });\n\n ctx.emitter.emit(\"orchestrator.session.loaded\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n found: loaded.found,\n });\n\n // Phase 2 — drift check.\n assertNoDrift(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.record?.signature,\n options.force,\n );\n\n // Phase 3 — lock check (cooperative, fail-open).\n await acquireLock(ctx, sessionId, loaded.record);\n\n // Phase 4 — window history.\n const windowed = windowHistory(\n ctx as OrchestratorEngineContext,\n sessionId,\n options.history,\n );\n\n // Phase 5 — dispatch. When memory is configured, recall the\n // turn-relevant memories and inject them into the request-scoped\n // context bag so every route / router / evaluate / dispatch callback\n // surfaces them at `ctx.context[injectKey]` before routing runs.\n const seedState = applyStatePatch(loaded.state, options.state);\n\n let turnContext = options.context;\n\n if (ctx.memory) {\n const recalled = await recallForTurn(ctx.memory, input);\n turnContext = injectMemories(turnContext, ctx.memory, recalled);\n }\n\n const { result, state, turnSnapshot } = await dispatchTurn<TOutput, TState>({\n ctx,\n sessionId,\n input,\n seedState,\n turnIndex: loaded.turnIndex,\n history: windowed.agents,\n context: turnContext,\n signal: options.signal,\n });\n\n ctx.emitter.emit(\"orchestrator.turn.routed\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n source: turnSnapshot.decision.source,\n raw: turnSnapshot.decision.raw,\n });\n\n const status = result.error\n ? deriveStatus(result.report.status)\n : \"awaiting-input\";\n\n // Cancelled / failed turns revert: no fresh checkpoint, no compaction.\n if (result.error) {\n const report = buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.turnIndex,\n status,\n turnSnapshot,\n result.report,\n );\n\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, loaded.turnIndex, status);\n\n return {\n data: result.data,\n error: result.error,\n usage: result.usage,\n report,\n sessionId,\n turnIndex: loaded.turnIndex,\n };\n }\n\n // Phase 6 — persist checkpoint.\n await persistCheckpoint({\n ctx,\n sessionId,\n turnIndex: loaded.turnIndex,\n state,\n lastRoute: summarizeRoute(turnSnapshot.decision.raw as never),\n summarizedThrough: loaded.record?.summarized_through ?? null,\n });\n\n // Memory write-back (memory core M2). The turn settled cleanly (the\n // `result.error` branch above already returned for cancelled /\n // failed turns, which revert and never remember — §17), so remember\n // the input + its outcome for later recall.\n if (ctx.memory) {\n await rememberTurnOutcome(\n ctx.memory,\n input,\n outcomeTextFromTurn(result.data, turnSnapshot),\n );\n }\n\n // Phase 7 — post-turn compaction (only when triggered).\n let compaction: CompactionResult | undefined;\n\n if (shouldCompact(ctx as OrchestratorEngineContext, loaded.turnIndex)) {\n const outcome = await runCompaction(\n ctx as OrchestratorEngineContext<unknown, TState>,\n sessionId,\n options.history,\n );\n\n if (outcome) {\n compaction = outcome.compaction;\n\n if (outcome.applied) {\n await advanceSummarizedThrough(\n ctx as OrchestratorEngineContext<unknown, TState>,\n sessionId,\n outcome.compaction.replacesToIndex,\n );\n }\n }\n }\n\n const report = buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.turnIndex,\n \"awaiting-input\",\n turnSnapshot,\n result.report,\n );\n\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, loaded.turnIndex, \"awaiting-input\");\n\n return {\n data: result.data,\n error: undefined,\n usage: result.usage,\n report,\n sessionId,\n turnIndex: loaded.turnIndex,\n compaction,\n };\n } finally {\n disposePerCall();\n }\n}\n\n/**\n * After a framework-applied compaction (`onCompact` succeeded), advance\n * the persisted `summarized_through` to the compaction's\n * `replacesToIndex` (§12.2 step 4). Re-saves the latest row with the\n * updated marker (append-only stores keep the prior row).\n */\nasync function advanceSummarizedThrough<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n replacesToIndex: number,\n): Promise<void> {\n const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);\n\n if (!latest) {\n return;\n }\n\n await ctx.checkpointStore.save({\n ...latest,\n summarized_through: replacesToIndex,\n saved_at: new Date().toISOString(),\n });\n}\n\n/**\n * §9 resume protocol entry the C1 factory's `resume()` delegates to.\n * Returns `null` when no in-flight `iterate: true` turn is detected;\n * otherwise drains the interrupted supervisor run, persists a fresh\n * checkpoint for the resumed turn, and returns the completed result.\n *\n * Runs the same Phase 2 drift check as `runTurn` (§9.4). The heavy\n * lifting lives in `resume.ts`; this wrapper threads the engine\n * context.\n */\nexport async function runResume<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n sessionId: string,\n options?: OrchestratorResumeOptions,\n): Promise<OrchestratorResult<TOutput> | null> {\n const disposePerCall = ctx.emitter.bindPerCall(options?.on);\n\n try {\n return await resolveResume(ctx, sessionId, options, {\n assertNoDrift: (loadedSignature) =>\n assertNoDrift(\n ctx as OrchestratorEngineContext,\n sessionId,\n loadedSignature,\n options?.force,\n ),\n buildReport: (turnIndex, status, turnSnapshot, childReport) =>\n buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n turnIndex,\n status,\n turnSnapshot,\n childReport,\n ),\n deriveStatus,\n emitTerminal: (turnIndex, status) =>\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, turnIndex, status),\n persist: (turnIndex, state, lastRoute, summarizedThrough) =>\n persistCheckpoint({\n ctx,\n sessionId,\n turnIndex,\n state,\n lastRoute,\n summarizedThrough,\n }),\n });\n } finally {\n disposePerCall();\n }\n}\n\n/**\n * The `stream()` entry. The orchestrator's streaming surface bubbles\n * child agent/supervisor events under their own namespace (§14.2); the\n * C1 stream controller owns the `StreamContract` wiring. This engine\n * entry runs the same lifecycle as `runTurn` — the C1 factory passes a\n * per-call `on` bag wired to the stream controller, so the engine needs\n * no streaming-specific branch. Exposed as a distinct name for the\n * factory to call, returning the same `OrchestratorResult` the stream's\n * `.result` resolves to.\n */\nexport async function streamTurn<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n): Promise<OrchestratorResult<TOutput>> {\n return runTurn(ctx, input, options);\n}\n\nexport type { OrchestratorEngineContext } from \"./engine-context.type\";\nexport type { Message };\n"],"mappings":"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"}
1
+ {"version":3,"file":"execution.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/execution.ts"],"sourcesContent":["import type { Message } from \"../contracts/conversation-message.type\";\nimport type { OrchestratorCommands } from \"../contracts/orchestrator/orchestrator-commands.type\";\nimport type { OrchestratorConfig } from \"../contracts/orchestrator/orchestrator-config.type\";\nimport type {\n OrchestratorEvent,\n OrchestratorEventHandlers,\n OrchestratorEventMap,\n OrchestratorEventName,\n} from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type {\n OrchestratorExecuteOptions,\n OrchestratorResumeOptions,\n} from \"../contracts/orchestrator/orchestrator-execute-options.type\";\nimport type {\n CompactionResult,\n OrchestratorReport,\n OrchestratorReportStatus,\n OrchestratorResult,\n TurnSnapshot,\n} from \"../contracts/result/orchestrator-result.type\";\nimport { REPORT_SCHEMA_VERSION } from \"../contracts/result/base-report.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport type { EventIdentity } from \"../contracts/events/event-identity.type\";\nimport {\n resolveDefaultCheckpointStore,\n resolveDefaultSnapshotStore,\n} from \"../config\";\nimport type { AIError } from \"../errors/ai-error\";\nimport { OrchestratorConfigError, OrchestratorDriftError } from \"../errors\";\nimport { notifyObservers } from \"../observe/resolve-observers\";\nimport type { ResolvedIntentEntry } from \"../supervisor/entries\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport { persistCheckpoint, summarizeRoute } from \"./checkpoint\";\nimport { runCompaction, runManualCompaction, shouldCompact } from \"./compaction\";\nimport { deriveRunId, dispatchTurn } from \"./dispatch\";\nimport type { OrchestratorEmitter } from \"./emitter\";\nimport type { OrchestratorEmitterLike } from \"./emitter-port.type\";\nimport type { OrchestratorEngineContext } from \"./engine-context.type\";\nimport { acquireLock } from \"./lock\";\nimport { loadSession } from \"./load\";\nimport {\n injectMemories,\n outcomeTextFromTurn,\n recallForTurn,\n rememberTurnOutcome,\n resolveOrchestratorMemory,\n} from \"./memory\";\nimport type { OrchestratorStreamController } from \"./orchestrator-stream\";\nimport { resolveResume } from \"./resume\";\nimport { windowHistory } from \"./window\";\n\n/** Empty rolled-up usage for turns that never dispatched (drift/seed). */\nconst ZERO_USAGE: Usage = { input: 0, output: 0, total: 0 };\n\n/**\n * Constructor params the C1 factory passes when building an\n * {@link OrchestratorExecution} per call. The factory owns author-time\n * validation, intent-entry resolution, and signature computation; it\n * hands the engine the validated `config`, the resolved `entries`, the\n * computed `signature`, and the shared three-tier `emitter`. The\n * per-call inputs vary by entry point:\n *\n * - `execute` / `stream` — `input` + `options` (and `streamController`\n * for `stream`).\n * - `resume` — `resumeSessionId` + `resumeOptions`.\n * - `command(\"compact\")` — neither; `compact(args)` carries its own.\n */\nexport type OrchestratorExecutionParams<TOutput, TState> = {\n config: OrchestratorConfig<TOutput, TState>;\n /** Resolved intent entries (validated by C1; the engine delegates dispatch to the supervisor). */\n entries?: Map<string, ResolvedIntentEntry>;\n signature: string;\n emitter: OrchestratorEmitter;\n input?: SupervisorInput;\n options?: OrchestratorExecuteOptions<TState>;\n streamController?: OrchestratorStreamController<OrchestratorResult<TOutput>>;\n resumeSessionId?: string;\n resumeOptions?: OrchestratorResumeOptions;\n};\n\n/**\n * Per-call lifecycle engine — the single object the C1 factory\n * constructs and drives. Owns the 7-phase lifecycle (orchestrator.md §3:\n * load → drift → lock → window → dispatch → persist → compaction),\n * resolving the durable stores (own config field → `ai.config` default)\n * and adapting C1's three-tier {@link OrchestratorEmitter} to the\n * {@link OrchestratorEmitterLike} port the phase modules call.\n *\n * The factory creates a fresh instance per `execute` / `stream` /\n * `resume` / `command` call (single-call lifecycle invariant — §18.8);\n * the heavy lifting lives in the standalone phase functions\n * ({@link runTurn} / {@link runResume}) which this class delegates to.\n *\n * @example\n * const execution = new OrchestratorExecution({\n * config, entries, signature, emitter, input, options,\n * });\n * const result = await execution.run();\n */\nexport class OrchestratorExecution<TOutput, TState> {\n private readonly params: OrchestratorExecutionParams<TOutput, TState>;\n private readonly ctx: OrchestratorEngineContext<TOutput, TState>;\n private readonly streamController?: OrchestratorStreamController<\n OrchestratorResult<TOutput>\n >;\n\n public constructor(params: OrchestratorExecutionParams<TOutput, TState>) {\n this.params = params;\n this.streamController = params.streamController;\n this.ctx = {\n config: params.config,\n signature: params.signature,\n checkpointStore: resolveCheckpointStore(params.config),\n snapshotStore: resolveSnapshotStore(params.config),\n emitter: adaptEmitter(\n params.emitter,\n generateRunId(\"orchestrator\"),\n this.streamController as\n | OrchestratorStreamController<unknown>\n | undefined,\n ),\n memory: resolveOrchestratorMemory(params.config.memory),\n };\n }\n\n /**\n * `execute()` / `stream()` entry — run one turn through the 7-phase\n * lifecycle. When a `streamController` was supplied, the adapter mirrors\n * every emitted event into the stream and the controller is settled\n * (`end` / `fail`) once the result resolves.\n */\n public async run(): Promise<OrchestratorResult<TOutput>> {\n if (this.params.input === undefined || !this.params.options) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${this.params.config.name}\"): internal — run() invoked without input/options`,\n );\n }\n\n try {\n const result = await runTurn(\n this.ctx,\n this.params.input,\n this.params.options,\n );\n\n // Route the orchestrator's report to observers (per-flow `observe` +\n // the global observe-all gate) — parity with agent/workflow/supervisor,\n // so a durable session root no longer needs a manual observe.collect().\n await notifyObservers(this.ctx.config.observe, result.report);\n\n this.streamController?.end(result);\n\n return result;\n } catch (error) {\n this.streamController?.fail(error as Error);\n\n throw error;\n }\n }\n\n /**\n * `resume()` entry — drain an interrupted `iterate: true` turn (§9).\n * Returns `null` when nothing is in flight.\n */\n public async resume(): Promise<OrchestratorResult<TOutput> | null> {\n if (!this.params.resumeSessionId) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${this.params.config.name}\"): internal — resume() invoked without a sessionId`,\n );\n }\n\n return runResume(this.ctx, this.params.resumeSessionId, this.params.resumeOptions);\n }\n\n /**\n * `command(\"compact\")` entry — run a manual compaction on demand (§11 /\n * §12.1). Reuses the post-turn compaction code path against the\n * caller-supplied history and returns the raw {@link CompactionResult}.\n */\n public async compact(\n args: OrchestratorCommands[\"compact\"][\"args\"],\n ): Promise<OrchestratorCommands[\"compact\"][\"result\"]> {\n return runManualCompaction(\n this.ctx as OrchestratorEngineContext<unknown, TState>,\n args.history,\n );\n }\n}\n\n/**\n * Resolve the durable checkpoint store: the config's own field, falling\n * back to `ai.config({ defaultCheckpointStore })`. Throws\n * {@link OrchestratorConfigError} when neither resolves — persistence is\n * always on (§8.1), so a turn can never run without a checkpoint store.\n */\nfunction resolveCheckpointStore<TOutput, TState>(\n config: OrchestratorConfig<TOutput, TState>,\n) {\n const store = config.checkpointStore ?? resolveDefaultCheckpointStore();\n\n if (!store) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): a \\`checkpointStore\\` is required ` +\n `(set one on the config or via \\`ai.config({ defaultCheckpointStore })\\`)`,\n );\n }\n\n return store;\n}\n\n/**\n * Resolve the internal-supervisor snapshot store for `iterate: true`\n * turns: the config's own field, falling back to\n * `ai.config({ defaultSnapshotStore })`. Returns `undefined` for\n * `iterate: false` orchestrators (no mid-turn resume — nothing to\n * snapshot). The factory already guarantees presence when\n * `iterate: true`, so the engine never asserts here.\n */\nfunction resolveSnapshotStore<TOutput, TState>(\n config: OrchestratorConfig<TOutput, TState>,\n) {\n if (config.iterate !== true) {\n return undefined;\n }\n\n return config.snapshotStore ?? resolveDefaultSnapshotStore();\n}\n\n/**\n * Adapt C1's three-tier {@link OrchestratorEmitter} (whose `emit` takes\n * `event, payload, identity, perCallHandlers?`) to the\n * {@link OrchestratorEmitterLike} port the phase modules call (a 2-arg\n * `emit(event, payload)` plus `bindPerCall`).\n *\n * The adapter injects the run identity centrally and, when a stream\n * controller is present, mirrors every fully-stamped event into the\n * stream pipe (§14.1 — the orchestrator's own events surface on the\n * stream alongside the bubbled child events). `bindPerCall` registers\n * the per-call `options.on` bag for the turn's duration and returns a\n * disposer that clears it.\n */\nfunction adaptEmitter(\n emitter: OrchestratorEmitter,\n runId: string,\n streamController: OrchestratorStreamController<unknown> | undefined,\n): OrchestratorEmitterLike {\n // `rootRunId === runId` for a standalone run; nested propagation lands\n // in a follow-up (see `EventIdentity`).\n const fullIdentity: EventIdentity = { runId, rootRunId: runId };\n\n let perCall: OrchestratorEventHandlers | undefined;\n\n return {\n emit<K extends OrchestratorEventName>(\n event: K,\n payload: OrchestratorEventMap[K],\n ): void {\n const fullPayload = emitter.emit(event, payload, fullIdentity, perCall);\n\n // The discriminated-union correlation between `type` and the\n // matching payload variant can't be expressed structurally — the\n // cast mirrors the supervisor stream's established pattern.\n streamController?.push({ type: event, ...fullPayload } as OrchestratorEvent);\n },\n bindPerCall(handlers: OrchestratorEventHandlers | undefined): () => void {\n perCall = handlers;\n\n return () => {\n perCall = undefined;\n };\n },\n };\n}\n\n/**\n * Phase 2 — drift check (orchestrator.md §3 / §4 Phase 2). Compares the\n * loaded checkpoint's `signature` against the current definition's.\n * Mismatch throws `OrchestratorDriftError` synchronously unless\n * `force` is set. Emits `orchestrator.drift.checked` either way. A new\n * session (no loaded signature) never drifts.\n */\nfunction assertNoDrift(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n loadedSignature: string | undefined,\n force: boolean | undefined,\n): void {\n const drifted =\n loadedSignature !== undefined && loadedSignature !== ctx.signature;\n\n ctx.emitter.emit(\"orchestrator.drift.checked\", {\n sessionId,\n signature: ctx.signature,\n drifted,\n });\n\n if (drifted && !force) {\n throw new OrchestratorDriftError(\n `orchestrator \"${ctx.config.name}\": signature drift on session \"${sessionId}\" — ` +\n `the definition changed since this session was last persisted. ` +\n `Pass { force: true } only after reviewing the change, or discard / migrate the session.`,\n {\n savedSignature: loadedSignature as string,\n currentSignature: ctx.signature,\n sessionId,\n },\n );\n }\n}\n\n/**\n * Shallow-merge the per-call `state` patch (§5 — partial state\n * override) over the loaded session-state seed. The merged value\n * becomes the supervisor's seed for this turn.\n */\nfunction applyStatePatch<TState>(\n seed: TState,\n patch: Partial<TState> | undefined,\n): TState {\n if (!patch) {\n return seed;\n }\n\n return { ...seed, ...patch } as TState;\n}\n\n/**\n * Assemble the orchestrator-scope {@link OrchestratorReport} from the\n * dispatched turn's child report and the turn snapshot. Wraps the\n * child supervisor/agent report tree as `children[0]` (§15.6 —\n * `children[]` carries only the CURRENT turn's dispatched primitive\n * reports) while the per-turn forensic record lives on `turns[]`.\n */\nfunction buildReport(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n turnIndex: number,\n status: OrchestratorReportStatus,\n turnSnapshot: TurnSnapshot | undefined,\n childReport: BaseReport | undefined,\n error?: AIError,\n): OrchestratorReport {\n const now = new Date().toISOString();\n const usage = turnSnapshot?.usage ?? childReport?.usage ?? ZERO_USAGE;\n\n return {\n runId: deriveRunId(sessionId, ctx.config.version, turnIndex),\n rootRunId: deriveRunId(sessionId, ctx.config.version, turnIndex),\n name: ctx.config.name,\n version: ctx.config.version,\n sessionId,\n type: \"orchestrator\",\n status,\n // Stamp the terminal error so the observe path surfaces it on the\n // orchestrator span (an observer never sees the result envelope).\n // Absent on a clean turn.\n ...(error ? { error } : {}),\n startedAt: turnSnapshot?.startedAt ?? now,\n endedAt: turnSnapshot?.endedAt ?? now,\n duration: turnSnapshot?.duration ?? 0,\n usage,\n children: childReport ? [childReport] : [],\n reportSchemaVersion: REPORT_SCHEMA_VERSION,\n turnIndex,\n signature: ctx.signature,\n turns: turnSnapshot ? [turnSnapshot] : [],\n };\n}\n\n/**\n * Map the dispatched supervisor result's report status onto the\n * orchestrator's status surface (§15.6). A clean completion that is\n * still mid-conversation reports `\"awaiting-input\"` (the session\n * continues) rather than `\"completed\"`; failures and cancellations\n * pass through.\n */\nfunction deriveStatus(childStatus: BaseReport[\"status\"]): OrchestratorReportStatus {\n if (childStatus === \"completed\") {\n return \"awaiting-input\";\n }\n\n return childStatus;\n}\n\n/**\n * Emit the terminal turn event matching the report status (§14.1).\n */\nfunction emitTerminal(\n ctx: OrchestratorEngineContext,\n sessionId: string,\n turnIndex: number,\n status: OrchestratorReportStatus,\n): void {\n if (status === \"cancelled\") {\n ctx.emitter.emit(\"orchestrator.turn.cancelled\", { sessionId, turnIndex });\n\n return;\n }\n\n if (status === \"failed\" || status === \"max-iterations\") {\n ctx.emitter.emit(\"orchestrator.turn.failed\", { sessionId, turnIndex });\n\n return;\n }\n\n if (status === \"awaiting-input\") {\n ctx.emitter.emit(\"orchestrator.turn.awaiting-input\", {\n sessionId,\n turnIndex,\n });\n\n return;\n }\n\n ctx.emitter.emit(\"orchestrator.turn.completed\", { sessionId, turnIndex });\n}\n\n/**\n * Run one turn end-to-end through the 7-phase lifecycle (orchestrator\n * .md §3). The single entry the C1 factory's `execute()` delegates to.\n *\n * Phase order is the diagram's contract: load → drift → lock → window\n * → dispatch → persist → compaction. Drift / config misuse throw;\n * every other failure surfaces on `result.error` (the contract: the\n * orchestrator never throws on runtime failure). Cancellation and\n * failure do NOT persist a fresh checkpoint (§17 — state reverts to the\n * pre-turn checkpoint).\n */\nexport async function runTurn<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n): Promise<OrchestratorResult<TOutput>> {\n const sessionId = options.sessionId;\n const disposePerCall = ctx.emitter.bindPerCall(options.on);\n\n try {\n // Phase 1 — load session.\n const loaded = await loadSession(ctx, sessionId);\n\n ctx.emitter.emit(\"orchestrator.turn.starting\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n });\n\n ctx.emitter.emit(\"orchestrator.session.loaded\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n found: loaded.found,\n });\n\n // Phase 2 — drift check.\n assertNoDrift(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.record?.signature,\n options.force,\n );\n\n // Phase 3 — lock check (cooperative, fail-open).\n await acquireLock(ctx, sessionId, loaded.record);\n\n // Phase 4 — window history.\n const windowed = windowHistory(\n ctx as OrchestratorEngineContext,\n sessionId,\n options.history,\n );\n\n // Phase 5 — dispatch. When memory is configured, recall the\n // turn-relevant memories and inject them into the request-scoped\n // context bag so every route / router / evaluate / dispatch callback\n // surfaces them at `ctx.context[injectKey]` before routing runs.\n const seedState = applyStatePatch(loaded.state, options.state);\n\n let turnContext = options.context;\n\n if (ctx.memory) {\n const recalled = await recallForTurn(ctx.memory, input);\n turnContext = injectMemories(turnContext, ctx.memory, recalled);\n }\n\n const { result, state, turnSnapshot } = await dispatchTurn<TOutput, TState>({\n ctx,\n sessionId,\n input,\n seedState,\n turnIndex: loaded.turnIndex,\n history: windowed.agents,\n context: turnContext,\n signal: options.signal,\n });\n\n ctx.emitter.emit(\"orchestrator.turn.routed\", {\n sessionId,\n turnIndex: loaded.turnIndex,\n source: turnSnapshot.decision.source,\n raw: turnSnapshot.decision.raw,\n });\n\n const status = result.error\n ? deriveStatus(result.report.status)\n : \"awaiting-input\";\n\n // Cancelled / failed turns revert: no fresh checkpoint, no compaction.\n if (result.error) {\n const report = buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.turnIndex,\n status,\n turnSnapshot,\n result.report,\n result.error,\n );\n\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, loaded.turnIndex, status);\n\n return {\n data: result.data,\n error: result.error,\n usage: result.usage,\n report,\n sessionId,\n turnIndex: loaded.turnIndex,\n };\n }\n\n // Phase 6 — persist checkpoint.\n await persistCheckpoint({\n ctx,\n sessionId,\n turnIndex: loaded.turnIndex,\n state,\n lastRoute: summarizeRoute(turnSnapshot.decision.raw as never),\n summarizedThrough: loaded.record?.summarized_through ?? null,\n });\n\n // Memory write-back (memory core M2). The turn settled cleanly (the\n // `result.error` branch above already returned for cancelled /\n // failed turns, which revert and never remember — §17), so remember\n // the input + its outcome for later recall.\n if (ctx.memory) {\n await rememberTurnOutcome(\n ctx.memory,\n input,\n outcomeTextFromTurn(result.data, turnSnapshot),\n );\n }\n\n // Phase 7 — post-turn compaction (only when triggered).\n let compaction: CompactionResult | undefined;\n\n if (shouldCompact(ctx as OrchestratorEngineContext, loaded.turnIndex)) {\n const outcome = await runCompaction(\n ctx as OrchestratorEngineContext<unknown, TState>,\n sessionId,\n options.history,\n );\n\n if (outcome) {\n compaction = outcome.compaction;\n\n if (outcome.applied) {\n await advanceSummarizedThrough(\n ctx as OrchestratorEngineContext<unknown, TState>,\n sessionId,\n outcome.compaction.replacesToIndex,\n );\n }\n }\n }\n\n const report = buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n loaded.turnIndex,\n \"awaiting-input\",\n turnSnapshot,\n result.report,\n );\n\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, loaded.turnIndex, \"awaiting-input\");\n\n return {\n data: result.data,\n error: undefined,\n usage: result.usage,\n report,\n sessionId,\n turnIndex: loaded.turnIndex,\n compaction,\n };\n } finally {\n disposePerCall();\n }\n}\n\n/**\n * After a framework-applied compaction (`onCompact` succeeded), advance\n * the persisted `summarized_through` to the compaction's\n * `replacesToIndex` (§12.2 step 4). Re-saves the latest row with the\n * updated marker (append-only stores keep the prior row).\n */\nasync function advanceSummarizedThrough<TState>(\n ctx: OrchestratorEngineContext<unknown, TState>,\n sessionId: string,\n replacesToIndex: number,\n): Promise<void> {\n const latest = await ctx.checkpointStore.load(ctx.config.name, sessionId);\n\n if (!latest) {\n return;\n }\n\n await ctx.checkpointStore.save({\n ...latest,\n summarized_through: replacesToIndex,\n saved_at: new Date().toISOString(),\n });\n}\n\n/**\n * §9 resume protocol entry the C1 factory's `resume()` delegates to.\n * Returns `null` when no in-flight `iterate: true` turn is detected;\n * otherwise drains the interrupted supervisor run, persists a fresh\n * checkpoint for the resumed turn, and returns the completed result.\n *\n * Runs the same Phase 2 drift check as `runTurn` (§9.4). The heavy\n * lifting lives in `resume.ts`; this wrapper threads the engine\n * context.\n */\nexport async function runResume<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n sessionId: string,\n options?: OrchestratorResumeOptions,\n): Promise<OrchestratorResult<TOutput> | null> {\n const disposePerCall = ctx.emitter.bindPerCall(options?.on);\n\n try {\n return await resolveResume(ctx, sessionId, options, {\n assertNoDrift: (loadedSignature) =>\n assertNoDrift(\n ctx as OrchestratorEngineContext,\n sessionId,\n loadedSignature,\n options?.force,\n ),\n buildReport: (turnIndex, status, turnSnapshot, childReport) =>\n buildReport(\n ctx as OrchestratorEngineContext,\n sessionId,\n turnIndex,\n status,\n turnSnapshot,\n childReport,\n ),\n deriveStatus,\n emitTerminal: (turnIndex, status) =>\n emitTerminal(ctx as OrchestratorEngineContext, sessionId, turnIndex, status),\n persist: (turnIndex, state, lastRoute, summarizedThrough) =>\n persistCheckpoint({\n ctx,\n sessionId,\n turnIndex,\n state,\n lastRoute,\n summarizedThrough,\n }),\n });\n } finally {\n disposePerCall();\n }\n}\n\n/**\n * The `stream()` entry. The orchestrator's streaming surface bubbles\n * child agent/supervisor events under their own namespace (§14.2); the\n * C1 stream controller owns the `StreamContract` wiring. This engine\n * entry runs the same lifecycle as `runTurn` — the C1 factory passes a\n * per-call `on` bag wired to the stream controller, so the engine needs\n * no streaming-specific branch. Exposed as a distinct name for the\n * factory to call, returning the same `OrchestratorResult` the stream's\n * `.result` resolves to.\n */\nexport async function streamTurn<TOutput, TState>(\n ctx: OrchestratorEngineContext<TOutput, TState>,\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n): Promise<OrchestratorResult<TOutput>> {\n return runTurn(ctx, input, options);\n}\n\nexport type { OrchestratorEngineContext } from \"./engine-context.type\";\nexport type { Message };\n"],"mappings":"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"}
@@ -5,4 +5,5 @@ import { ResolvedOrchestratorMemory, injectMemories, memoryQueryFromInput, outco
5
5
  import { OrchestratorStreamController, createOrchestratorStream } from "./orchestrator-stream.mjs";
6
6
  import { OrchestratorExecution, OrchestratorExecutionParams, runResume, runTurn, streamTurn } from "./execution.mjs";
7
7
  import { orchestrator } from "./orchestrator.mjs";
8
+ import { inProcessSessionLock, noopSessionLock } from "./session-lock.mjs";
8
9
  import { computeOrchestratorSignature } from "./signature.mjs";
@@ -4,6 +4,7 @@ import { OrchestratorEmitter } from "./emitter.mjs";
4
4
  import { injectMemories, memoryQueryFromInput, outcomeTextFromTurn, recallForTurn, rememberTurnOutcome, resolveOrchestratorMemory } from "./memory.mjs";
5
5
  import { OrchestratorExecution, runResume, runTurn, streamTurn } from "./execution.mjs";
6
6
  import { createOrchestratorStream } from "./orchestrator-stream.mjs";
7
+ import { inProcessSessionLock, noopSessionLock } from "./session-lock.mjs";
7
8
  import { computeOrchestratorSignature } from "./signature.mjs";
8
9
  import { orchestrator } from "./orchestrator.mjs";
9
10
 
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/orchestrator.ts"],"mappings":";;;;;;;AA4DA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,YAAA,6BAEL,OAAA,mBACQ,MAAA,SAAe,qBAAA,IAAyB,MAAA,SAEvD,qBAAA,GAGF,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,MAAA,EAAQ,QAAA,IAC3C,oBAAA,CAAqB,OAAA,EAAS,MAAA"}
1
+ {"version":3,"file":"orchestrator.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/orchestrator.ts"],"mappings":";;;;;;;AA8DA;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAgB,YAAA,6BAEL,OAAA,mBACQ,MAAA,SAAe,qBAAA,IAAyB,MAAA,SAEvD,qBAAA,GAGF,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,MAAA,EAAQ,QAAA,IAC3C,oBAAA,CAAqB,OAAA,EAAS,MAAA"}
@@ -8,6 +8,7 @@ import { OrchestratorEmitter } from "./emitter.mjs";
8
8
  import { resolveIntentEntries } from "../supervisor/entries.mjs";
9
9
  import { OrchestratorExecution } from "./execution.mjs";
10
10
  import { createOrchestratorStream } from "./orchestrator-stream.mjs";
11
+ import { inProcessSessionLock, noopSessionLock } from "./session-lock.mjs";
11
12
  import { computeOrchestratorSignature } from "./signature.mjs";
12
13
 
13
14
  //#region ../@warlock.js/ai/src/orchestrator/orchestrator.ts
@@ -46,19 +47,22 @@ function orchestrator(config) {
46
47
  assertInitialAgent(config, entries);
47
48
  const signature = computeOrchestratorSignature(config, entries);
48
49
  const emitter = new OrchestratorEmitter(config.on);
50
+ const sessionLock = resolveSessionLock(config);
51
+ warnOnUnlockedDurableStore(config);
49
52
  async function execute(input, options) {
50
- return new OrchestratorExecution({
53
+ const execution = new OrchestratorExecution({
51
54
  config,
52
55
  entries,
53
56
  signature,
54
57
  emitter,
55
58
  input,
56
59
  options
57
- }).run();
60
+ });
61
+ return sessionLock.withLock(options.sessionId, () => execution.run(), { signal: options.signal });
58
62
  }
59
63
  function stream(input, options) {
60
64
  const { controller, stream: contract } = createOrchestratorStream();
61
- new OrchestratorExecution({
65
+ const execution = new OrchestratorExecution({
62
66
  config,
63
67
  entries,
64
68
  signature,
@@ -66,18 +70,20 @@ function orchestrator(config) {
66
70
  input,
67
71
  options,
68
72
  streamController: controller
69
- }).run();
73
+ });
74
+ sessionLock.withLock(options.sessionId, () => execution.run(), { signal: options.signal });
70
75
  return contract;
71
76
  }
72
77
  async function resume(sessionId, options) {
73
- return new OrchestratorExecution({
78
+ const execution = new OrchestratorExecution({
74
79
  config,
75
80
  entries,
76
81
  signature,
77
82
  emitter,
78
83
  resumeSessionId: sessionId,
79
84
  resumeOptions: options
80
- }).resume();
85
+ });
86
+ return sessionLock.withLock(sessionId, () => execution.resume(), { signal: options?.signal });
81
87
  }
82
88
  const command = createCommandDispatcher({ compact: (args) => {
83
89
  return new OrchestratorExecution({
@@ -167,6 +173,33 @@ function resolveEntries(config) {
167
173
  function assertInitialAgent(config, entries) {
168
174
  if (config.initialAgent && !entries.has(config.initialAgent)) throw new OrchestratorConfigError(`ai.orchestrator("${config.name}"): \`initialAgent\` "${config.initialAgent}" is not a key in \`intents\``, { context: { authoring: true } });
169
175
  }
176
+ /**
177
+ * Resolve the per-session lock (C4): an explicit {@link SessionLock} when
178
+ * supplied, a no-op when `sessionLock: false`, otherwise the framework
179
+ * default in-process mutex.
180
+ */
181
+ function resolveSessionLock(config) {
182
+ if (config.sessionLock === false) return noopSessionLock();
183
+ if (config.sessionLock) return config.sessionLock;
184
+ return inProcessSessionLock();
185
+ }
186
+ /** Orchestrator names already warned about an unlocked durable store. */
187
+ const warnedUnlockedStores = /* @__PURE__ */ new Set();
188
+ /**
189
+ * Warn once when a durable `checkpointStore` is configured but no explicit
190
+ * `sessionLock` was supplied (C4). The in-process default serializes
191
+ * same-session turns within one process only — a horizontally-scaled
192
+ * deployment needs a distributed lock or sticky routing. Suppressed in
193
+ * tests and when the dev explicitly chose a lock (or `sessionLock: false`).
194
+ */
195
+ function warnOnUnlockedDurableStore(config) {
196
+ if (config.sessionLock !== void 0) return;
197
+ if (!config.checkpointStore) return;
198
+ if (process.env.NODE_ENV === "test" || process.env.VITEST) return;
199
+ if (warnedUnlockedStores.has(config.name)) return;
200
+ warnedUnlockedStores.add(config.name);
201
+ console.warn(`[warlock-ai] orchestrator "${config.name}" uses a durable checkpointStore with the default in-process sessionLock. That serializes same-session turns within ONE process only; in a horizontally-scaled deployment supply a distributed \`sessionLock\` (Redis/Postgres advisory locks) or use sticky routing. Pass \`sessionLock: false\` to silence this.`);
202
+ }
170
203
 
171
204
  //#endregion
172
205
  export { orchestrator };
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator.mjs","names":["orchestratorAsTool"],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/orchestrator.ts"],"sourcesContent":["import type { OrchestratorConfig } from \"../contracts/orchestrator/orchestrator-config.type\";\nimport type {\n OrchestratorEventHandler,\n OrchestratorEventName,\n} from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type {\n OrchestratorAsToolOptions,\n OrchestratorContract,\n} from \"../contracts/orchestrator/orchestrator.contract\";\nimport type { OrchestratorCommands } from \"../contracts/orchestrator/orchestrator-commands.type\";\nimport type {\n OrchestratorExecuteOptions,\n OrchestratorResumeOptions,\n} from \"../contracts/orchestrator/orchestrator-execute-options.type\";\nimport type { OrchestratorEvent } from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type { OrchestratorResult } from \"../contracts/result/orchestrator-result.type\";\nimport type { StreamContract } from \"../contracts/stream/stream.contract\";\nimport type { SupervisorIntentValue } from \"../contracts/supervisor/intent-entry.type\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport { resolveDefaultSnapshotStore } from \"../config\";\nimport { OrchestratorConfigError } from \"../errors/orchestrator-config-error\";\nimport { resolveIntentEntries, type ResolvedIntentEntry } from \"../supervisor/entries\";\nimport { SupervisorFailedError } from \"../errors\";\nimport type { ToolContract } from \"../tool/tool\";\nimport { asTool as orchestratorAsTool } from \"./as-tool\";\nimport { createCommandDispatcher } from \"./commands\";\nimport { OrchestratorEmitter } from \"./emitter\";\nimport { OrchestratorExecution } from \"./execution\";\nimport { createOrchestratorStream } from \"./orchestrator-stream\";\nimport { computeOrchestratorSignature } from \"./signature\";\n\n/**\n * `ai.orchestrator(config)` — construct an {@link OrchestratorContract}:\n * a session-state manager wrapped around a supervisor (orchestrator.md\n * §1, §15). Validates the config at author time (throws\n * {@link OrchestratorConfigError} on bad shape), resolves the intent\n * entries, computes a stable structural signature for drift detection\n * (§10.1), wires the three-tier event emitter, and returns a handle that\n * runs one durable session turn per `execute` / `stream` call, resumes\n * an interrupted `iterate: true` turn via `resume`, and exposes typed\n * built-in commands plus an `asTool` wrapper.\n *\n * The \"what runs\" fields (`intents`, `route` / `router`, `evaluate`,\n * `state`, `output`, `initialAgent`, `maxIterations`) are the\n * supervisor's surface spread directly — the lifecycle builds the\n * supervisor lazily per turn and delegates to it (§3 Phase 5). Users\n * never see the supervisor object.\n *\n * @example\n * const supportBot = ai.orchestrator<SessionState>({\n * name: \"refund-support\",\n * intents: { classify, lookup, process, compose },\n * route: (ctx) => (ctx.iteration === 0 ? \"classify\" : END),\n * iterate: true,\n * checkpointStore: ai.checkpoint.pg({ client: pg }),\n * snapshotStore: ai.snapshot.pg({ client: pg }),\n * });\n *\n * const result = await supportBot.execute(message, { sessionId, history });\n */\nexport function orchestrator<\n TOutput = unknown,\n TState = TOutput,\n TIntents extends Record<string, SupervisorIntentValue> = Record<\n string,\n SupervisorIntentValue\n >,\n>(\n config: OrchestratorConfig<TOutput, TState, TIntents>,\n): OrchestratorContract<TOutput, TState> {\n validateFactoryConfig(config as unknown as OrchestratorConfig<unknown>);\n\n const entries = resolveEntries(config as unknown as OrchestratorConfig<unknown>);\n\n assertInitialAgent(config as unknown as OrchestratorConfig<unknown>, entries);\n\n const signature = computeOrchestratorSignature(\n config as unknown as OrchestratorConfig<unknown>,\n entries,\n );\n const emitter = new OrchestratorEmitter(config.on);\n\n async function execute(\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n ): Promise<OrchestratorResult<TOutput>> {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n input,\n options,\n });\n\n return execution.run();\n }\n\n function stream(\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n ): StreamContract<OrchestratorResult<TOutput>, OrchestratorEvent> {\n const { controller, stream: contract } = createOrchestratorStream<\n OrchestratorResult<TOutput>\n >();\n\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n input,\n options,\n streamController: controller,\n });\n\n void execution.run();\n\n return contract;\n }\n\n async function resume(\n sessionId: string,\n options?: OrchestratorResumeOptions,\n ): Promise<OrchestratorResult<TOutput> | null> {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n resumeSessionId: sessionId,\n resumeOptions: options,\n });\n\n return execution.resume();\n }\n\n // The dispatcher owns command ROUTING only; the `compact` handler\n // delegates to the shared compaction code path on the lifecycle engine\n // (§11 / §12.2 — manual compact reuses the post-turn compaction path).\n const command = createCommandDispatcher({\n compact: (args: OrchestratorCommands[\"compact\"][\"args\"]) => {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n });\n\n return execution.compact(args);\n },\n });\n\n const instance: OrchestratorContract<TOutput, TState> = {\n name: config.name,\n signature,\n version: config.version,\n execute,\n stream,\n resume,\n command,\n asTool<TToolInput = string>(\n options: OrchestratorAsToolOptions<TToolInput>,\n ): ToolContract<TToolInput, TOutput> {\n return orchestratorAsTool<TOutput, TState, TToolInput>(instance, options);\n },\n on<K extends OrchestratorEventName>(\n event: K,\n handler: OrchestratorEventHandler<K>,\n ): () => void {\n return emitter.on(event, handler);\n },\n off<K extends OrchestratorEventName>(\n event: K,\n handler: OrchestratorEventHandler<K>,\n ): void {\n emitter.off(event, handler);\n },\n };\n\n return instance;\n}\n\n/**\n * Author-time validation (orchestrator.md §17). Enforces the rules that\n * must fail at construction rather than on the first turn:\n *\n * - `name` present and a string.\n * - `intents` present.\n * - `route` XOR `router` (mutually exclusive; at least one required) —\n * the supervisor's dispatch-source rule, surfaced as an orchestrator\n * config error.\n * - `router` is a valid agent contract or `{ agent, ... }` entry.\n * - `maxIterations >= 1` when set.\n * - `snapshotStore` resolvable when `iterate: true` — explicit field or\n * the global `ai.config({ defaultSnapshotStore })` fallback.\n *\n * `initialAgent` membership is checked separately once the intent\n * entries are resolved.\n */\nfunction validateFactoryConfig(config: OrchestratorConfig<unknown>): void {\n if (!config.name || typeof config.name !== \"string\") {\n throw new OrchestratorConfigError(\n \"ai.orchestrator: `name` is required and must be a string\",\n { context: { authoring: true } },\n );\n }\n\n if (!config.intents || typeof config.intents !== \"object\") {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`intents\\` is required`,\n { context: { authoring: true } },\n );\n }\n\n const hasRoute = typeof config.route === \"function\";\n const hasRouter = Boolean(config.router);\n\n if (hasRouter) {\n const router = config.router;\n const isBareAgent = typeof (router as { execute?: unknown }).execute === \"function\";\n const isEntryForm =\n !isBareAgent &&\n typeof (router as { agent?: { execute?: unknown } }).agent === \"object\" &&\n typeof (router as { agent?: { execute?: unknown } }).agent?.execute === \"function\";\n\n if (!isBareAgent && !isEntryForm) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`router\\` must be an agent contract or a \\`{ agent, placeholders?, input? }\\` entry`,\n { context: { authoring: true } },\n );\n }\n }\n\n if (hasRoute && hasRouter) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`route\\` and \\`router\\` are mutually exclusive — configure exactly one`,\n { context: { authoring: true } },\n );\n }\n\n if (!hasRoute && !hasRouter) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): one of \\`route\\` or \\`router\\` is required`,\n { context: { authoring: true } },\n );\n }\n\n if (config.maxIterations !== undefined && config.maxIterations < 1) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`maxIterations\\` must be >= 1`,\n { context: { authoring: true, maxIterations: config.maxIterations } },\n );\n }\n\n if (config.iterate && !config.snapshotStore && !resolveDefaultSnapshotStore()) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`iterate: true\\` requires a \\`snapshotStore\\` (or \\`ai.config({ defaultSnapshotStore })\\`) for mid-turn resume`,\n { context: { authoring: true } },\n );\n }\n}\n\n/**\n * Resolve the `intents` map into the supervisor's internal entry shape,\n * re-wrapping the supervisor's authoring failure as an\n * {@link OrchestratorConfigError} so misuse surfaces under the\n * orchestrator's error family rather than the supervisor's.\n */\nfunction resolveEntries(\n config: OrchestratorConfig<unknown>,\n): Map<string, ResolvedIntentEntry> {\n try {\n return resolveIntentEntries(config.intents, config.name);\n } catch (error) {\n if (error instanceof SupervisorFailedError) {\n throw new OrchestratorConfigError(error.message, {\n context: { authoring: true },\n cause: error,\n });\n }\n\n throw error;\n }\n}\n\n/**\n * Enforce the `initialAgent` membership rule (§17) once entries are\n * resolved — `initialAgent`, when set, must name a key in `intents`.\n */\nfunction assertInitialAgent(\n config: OrchestratorConfig<unknown>,\n entries: Map<string, ResolvedIntentEntry>,\n): void {\n if (config.initialAgent && !entries.has(config.initialAgent)) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`initialAgent\\` \"${config.initialAgent}\" is not a key in \\`intents\\``,\n { context: { authoring: true } },\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator.mjs","names":["orchestratorAsTool"],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/orchestrator.ts"],"sourcesContent":["import type { OrchestratorConfig } from \"../contracts/orchestrator/orchestrator-config.type\";\nimport type {\n OrchestratorEventHandler,\n OrchestratorEventName,\n} from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type {\n OrchestratorAsToolOptions,\n OrchestratorContract,\n} from \"../contracts/orchestrator/orchestrator.contract\";\nimport type { OrchestratorCommands } from \"../contracts/orchestrator/orchestrator-commands.type\";\nimport type {\n OrchestratorExecuteOptions,\n OrchestratorResumeOptions,\n} from \"../contracts/orchestrator/orchestrator-execute-options.type\";\nimport type { OrchestratorEvent } from \"../contracts/orchestrator/orchestrator-event.type\";\nimport type { OrchestratorResult } from \"../contracts/result/orchestrator-result.type\";\nimport type { StreamContract } from \"../contracts/stream/stream.contract\";\nimport type { SupervisorIntentValue } from \"../contracts/supervisor/intent-entry.type\";\nimport type { SupervisorInput } from \"../contracts/supervisor/supervisor-input.type\";\nimport { resolveDefaultSnapshotStore } from \"../config\";\nimport { OrchestratorConfigError } from \"../errors/orchestrator-config-error\";\nimport { resolveIntentEntries, type ResolvedIntentEntry } from \"../supervisor/entries\";\nimport { SupervisorFailedError } from \"../errors\";\nimport type { ToolContract } from \"../tool/tool\";\nimport type { SessionLock } from \"../contracts/orchestrator/session-lock.contract\";\nimport { asTool as orchestratorAsTool } from \"./as-tool\";\nimport { createCommandDispatcher } from \"./commands\";\nimport { OrchestratorEmitter } from \"./emitter\";\nimport { OrchestratorExecution } from \"./execution\";\nimport { createOrchestratorStream } from \"./orchestrator-stream\";\nimport { inProcessSessionLock, noopSessionLock } from \"./session-lock\";\nimport { computeOrchestratorSignature } from \"./signature\";\n\n/**\n * `ai.orchestrator(config)` — construct an {@link OrchestratorContract}:\n * a session-state manager wrapped around a supervisor (orchestrator.md\n * §1, §15). Validates the config at author time (throws\n * {@link OrchestratorConfigError} on bad shape), resolves the intent\n * entries, computes a stable structural signature for drift detection\n * (§10.1), wires the three-tier event emitter, and returns a handle that\n * runs one durable session turn per `execute` / `stream` call, resumes\n * an interrupted `iterate: true` turn via `resume`, and exposes typed\n * built-in commands plus an `asTool` wrapper.\n *\n * The \"what runs\" fields (`intents`, `route` / `router`, `evaluate`,\n * `state`, `output`, `initialAgent`, `maxIterations`) are the\n * supervisor's surface spread directly — the lifecycle builds the\n * supervisor lazily per turn and delegates to it (§3 Phase 5). Users\n * never see the supervisor object.\n *\n * @example\n * const supportBot = ai.orchestrator<SessionState>({\n * name: \"refund-support\",\n * intents: { classify, lookup, process, compose },\n * route: (ctx) => (ctx.iteration === 0 ? \"classify\" : END),\n * iterate: true,\n * checkpointStore: ai.checkpoint.pg({ client: pg }),\n * snapshotStore: ai.snapshot.pg({ client: pg }),\n * });\n *\n * const result = await supportBot.execute(message, { sessionId, history });\n */\nexport function orchestrator<\n TOutput = unknown,\n TState = TOutput,\n TIntents extends Record<string, SupervisorIntentValue> = Record<\n string,\n SupervisorIntentValue\n >,\n>(\n config: OrchestratorConfig<TOutput, TState, TIntents>,\n): OrchestratorContract<TOutput, TState> {\n validateFactoryConfig(config as unknown as OrchestratorConfig<unknown>);\n\n const entries = resolveEntries(config as unknown as OrchestratorConfig<unknown>);\n\n assertInitialAgent(config as unknown as OrchestratorConfig<unknown>, entries);\n\n const signature = computeOrchestratorSignature(\n config as unknown as OrchestratorConfig<unknown>,\n entries,\n );\n const emitter = new OrchestratorEmitter(config.on);\n\n // Per-session turn serialization (C4). Resolved ONCE so every turn on\n // this orchestrator shares the same lock — that's what lets the\n // in-process default actually serialize concurrent same-session calls.\n const sessionLock = resolveSessionLock(config as unknown as OrchestratorConfig<unknown>);\n warnOnUnlockedDurableStore(config as unknown as OrchestratorConfig<unknown>);\n\n async function execute(\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n ): Promise<OrchestratorResult<TOutput>> {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n input,\n options,\n });\n\n // Serialize the whole turn (load → dispatch → persist) against any\n // concurrent turn for the same session, so the checkpoint's\n // read-modify-write can't lose an update.\n return sessionLock.withLock(options.sessionId, () => execution.run(), {\n signal: options.signal,\n });\n }\n\n function stream(\n input: SupervisorInput,\n options: OrchestratorExecuteOptions<TState>,\n ): StreamContract<OrchestratorResult<TOutput>, OrchestratorEvent> {\n const { controller, stream: contract } = createOrchestratorStream<\n OrchestratorResult<TOutput>\n >();\n\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n input,\n options,\n streamController: controller,\n });\n\n // The background run waits for the session lock before it starts —\n // same serialization guarantee as `execute`; the stream contract is\n // still returned synchronously.\n void sessionLock.withLock(options.sessionId, () => execution.run(), {\n signal: options.signal,\n });\n\n return contract;\n }\n\n async function resume(\n sessionId: string,\n options?: OrchestratorResumeOptions,\n ): Promise<OrchestratorResult<TOutput> | null> {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n resumeSessionId: sessionId,\n resumeOptions: options,\n });\n\n return sessionLock.withLock(sessionId, () => execution.resume(), {\n signal: options?.signal,\n });\n }\n\n // The dispatcher owns command ROUTING only; the `compact` handler\n // delegates to the shared compaction code path on the lifecycle engine\n // (§11 / §12.2 — manual compact reuses the post-turn compaction path).\n const command = createCommandDispatcher({\n compact: (args: OrchestratorCommands[\"compact\"][\"args\"]) => {\n const execution = new OrchestratorExecution<TOutput, TState>({\n config: config as unknown as OrchestratorConfig<TOutput, TState>,\n entries,\n signature,\n emitter,\n });\n\n return execution.compact(args);\n },\n });\n\n const instance: OrchestratorContract<TOutput, TState> = {\n name: config.name,\n signature,\n version: config.version,\n execute,\n stream,\n resume,\n command,\n asTool<TToolInput = string>(\n options: OrchestratorAsToolOptions<TToolInput>,\n ): ToolContract<TToolInput, TOutput> {\n return orchestratorAsTool<TOutput, TState, TToolInput>(instance, options);\n },\n on<K extends OrchestratorEventName>(\n event: K,\n handler: OrchestratorEventHandler<K>,\n ): () => void {\n return emitter.on(event, handler);\n },\n off<K extends OrchestratorEventName>(\n event: K,\n handler: OrchestratorEventHandler<K>,\n ): void {\n emitter.off(event, handler);\n },\n };\n\n return instance;\n}\n\n/**\n * Author-time validation (orchestrator.md §17). Enforces the rules that\n * must fail at construction rather than on the first turn:\n *\n * - `name` present and a string.\n * - `intents` present.\n * - `route` XOR `router` (mutually exclusive; at least one required) —\n * the supervisor's dispatch-source rule, surfaced as an orchestrator\n * config error.\n * - `router` is a valid agent contract or `{ agent, ... }` entry.\n * - `maxIterations >= 1` when set.\n * - `snapshotStore` resolvable when `iterate: true` — explicit field or\n * the global `ai.config({ defaultSnapshotStore })` fallback.\n *\n * `initialAgent` membership is checked separately once the intent\n * entries are resolved.\n */\nfunction validateFactoryConfig(config: OrchestratorConfig<unknown>): void {\n if (!config.name || typeof config.name !== \"string\") {\n throw new OrchestratorConfigError(\n \"ai.orchestrator: `name` is required and must be a string\",\n { context: { authoring: true } },\n );\n }\n\n if (!config.intents || typeof config.intents !== \"object\") {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`intents\\` is required`,\n { context: { authoring: true } },\n );\n }\n\n const hasRoute = typeof config.route === \"function\";\n const hasRouter = Boolean(config.router);\n\n if (hasRouter) {\n const router = config.router;\n const isBareAgent = typeof (router as { execute?: unknown }).execute === \"function\";\n const isEntryForm =\n !isBareAgent &&\n typeof (router as { agent?: { execute?: unknown } }).agent === \"object\" &&\n typeof (router as { agent?: { execute?: unknown } }).agent?.execute === \"function\";\n\n if (!isBareAgent && !isEntryForm) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`router\\` must be an agent contract or a \\`{ agent, placeholders?, input? }\\` entry`,\n { context: { authoring: true } },\n );\n }\n }\n\n if (hasRoute && hasRouter) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`route\\` and \\`router\\` are mutually exclusive — configure exactly one`,\n { context: { authoring: true } },\n );\n }\n\n if (!hasRoute && !hasRouter) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): one of \\`route\\` or \\`router\\` is required`,\n { context: { authoring: true } },\n );\n }\n\n if (config.maxIterations !== undefined && config.maxIterations < 1) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`maxIterations\\` must be >= 1`,\n { context: { authoring: true, maxIterations: config.maxIterations } },\n );\n }\n\n if (config.iterate && !config.snapshotStore && !resolveDefaultSnapshotStore()) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`iterate: true\\` requires a \\`snapshotStore\\` (or \\`ai.config({ defaultSnapshotStore })\\`) for mid-turn resume`,\n { context: { authoring: true } },\n );\n }\n}\n\n/**\n * Resolve the `intents` map into the supervisor's internal entry shape,\n * re-wrapping the supervisor's authoring failure as an\n * {@link OrchestratorConfigError} so misuse surfaces under the\n * orchestrator's error family rather than the supervisor's.\n */\nfunction resolveEntries(\n config: OrchestratorConfig<unknown>,\n): Map<string, ResolvedIntentEntry> {\n try {\n return resolveIntentEntries(config.intents, config.name);\n } catch (error) {\n if (error instanceof SupervisorFailedError) {\n throw new OrchestratorConfigError(error.message, {\n context: { authoring: true },\n cause: error,\n });\n }\n\n throw error;\n }\n}\n\n/**\n * Enforce the `initialAgent` membership rule (§17) once entries are\n * resolved — `initialAgent`, when set, must name a key in `intents`.\n */\nfunction assertInitialAgent(\n config: OrchestratorConfig<unknown>,\n entries: Map<string, ResolvedIntentEntry>,\n): void {\n if (config.initialAgent && !entries.has(config.initialAgent)) {\n throw new OrchestratorConfigError(\n `ai.orchestrator(\"${config.name}\"): \\`initialAgent\\` \"${config.initialAgent}\" is not a key in \\`intents\\``,\n { context: { authoring: true } },\n );\n }\n}\n\n/**\n * Resolve the per-session lock (C4): an explicit {@link SessionLock} when\n * supplied, a no-op when `sessionLock: false`, otherwise the framework\n * default in-process mutex.\n */\nfunction resolveSessionLock(config: OrchestratorConfig<unknown>): SessionLock {\n if (config.sessionLock === false) return noopSessionLock();\n if (config.sessionLock) return config.sessionLock;\n return inProcessSessionLock();\n}\n\n/** Orchestrator names already warned about an unlocked durable store. */\nconst warnedUnlockedStores = new Set<string>();\n\n/**\n * Warn once when a durable `checkpointStore` is configured but no explicit\n * `sessionLock` was supplied (C4). The in-process default serializes\n * same-session turns within one process only — a horizontally-scaled\n * deployment needs a distributed lock or sticky routing. Suppressed in\n * tests and when the dev explicitly chose a lock (or `sessionLock: false`).\n */\nfunction warnOnUnlockedDurableStore(config: OrchestratorConfig<unknown>): void {\n if (config.sessionLock !== undefined) return;\n if (!config.checkpointStore) return;\n if (process.env.NODE_ENV === \"test\" || process.env.VITEST) return;\n if (warnedUnlockedStores.has(config.name)) return;\n warnedUnlockedStores.add(config.name);\n\n console.warn(\n `[warlock-ai] orchestrator \"${config.name}\" uses a durable checkpointStore with the default in-process sessionLock. ` +\n \"That serializes same-session turns within ONE process only; in a horizontally-scaled deployment supply a distributed \" +\n \"`sessionLock` (Redis/Postgres advisory locks) or use sticky routing. Pass `sessionLock: false` to silence this.\",\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { SessionLock } from "../contracts/orchestrator/session-lock.contract.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/orchestrator/session-lock.d.ts
4
+ /**
5
+ * Framework-default in-process {@link SessionLock} — a per-key promise-
6
+ * chain mutex. It holds one tail promise per session key; each acquirer
7
+ * waits on the previous holder's release, then installs its own tail.
8
+ * Keyed by `sessionId`, so different sessions never contend. The wait is
9
+ * abortable, so a cancelled caller never deadlocks behind a stuck
10
+ * predecessor (the deadlock-on-cancel trap).
11
+ *
12
+ * In-process only: serializes same-session turns within ONE process.
13
+ * Supply a distributed {@link SessionLock} for multi-process deployments.
14
+ */
15
+ declare function inProcessSessionLock(): SessionLock;
16
+ /**
17
+ * No-op {@link SessionLock} for `sessionLock: false` — runs `fn` with no
18
+ * serialization at all. Opt out only when an external mechanism (sticky
19
+ * routing, a single-writer guarantee) already serializes same-session
20
+ * turns.
21
+ */
22
+ declare function noopSessionLock(): SessionLock;
23
+ //#endregion
24
+ export { inProcessSessionLock, noopSessionLock };
25
+ //# sourceMappingURL=session-lock.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-lock.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/session-lock.ts"],"mappings":";;;;;AAqBA;;;;AAAmD;AA4FnD;;;;iBA5FgB,oBAAA,IAAwB,WAAW;;;;;;;iBA4FnC,eAAA,IAAmB,WAAW"}
@@ -0,0 +1,83 @@
1
+ //#region ../@warlock.js/ai/src/orchestrator/session-lock.ts
2
+ /**
3
+ * Reason an aborted lock-wait rejects with — the signal's `reason` when
4
+ * one was supplied to `controller.abort(reason)`, else a generic error.
5
+ */
6
+ function abortReason(signal) {
7
+ return signal.reason ?? /* @__PURE__ */ new Error("session lock wait aborted");
8
+ }
9
+ /**
10
+ * Framework-default in-process {@link SessionLock} — a per-key promise-
11
+ * chain mutex. It holds one tail promise per session key; each acquirer
12
+ * waits on the previous holder's release, then installs its own tail.
13
+ * Keyed by `sessionId`, so different sessions never contend. The wait is
14
+ * abortable, so a cancelled caller never deadlocks behind a stuck
15
+ * predecessor (the deadlock-on-cancel trap).
16
+ *
17
+ * In-process only: serializes same-session turns within ONE process.
18
+ * Supply a distributed {@link SessionLock} for multi-process deployments.
19
+ */
20
+ function inProcessSessionLock() {
21
+ const tails = /* @__PURE__ */ new Map();
22
+ return { async withLock(key, fn, options) {
23
+ const existing = tails.get(key);
24
+ const prev = existing ?? Promise.resolve();
25
+ const waitSignal = existing ? options?.signal : void 0;
26
+ let release;
27
+ const held = new Promise((resolve) => {
28
+ release = resolve;
29
+ });
30
+ const mine = prev.then(() => held, () => held);
31
+ tails.set(key, mine);
32
+ const cleanup = () => {
33
+ if (tails.get(key) === mine) tails.delete(key);
34
+ };
35
+ try {
36
+ await waitForTurn(prev, waitSignal);
37
+ } catch (error) {
38
+ release();
39
+ cleanup();
40
+ throw error;
41
+ }
42
+ try {
43
+ return await fn();
44
+ } finally {
45
+ release();
46
+ cleanup();
47
+ }
48
+ } };
49
+ }
50
+ /**
51
+ * Wait for `prev` (the previous holder's release) to settle, racing it
52
+ * against `signal` so a cancelled caller stops waiting instead of
53
+ * deadlocking. Predecessor rejections are swallowed — a failed turn still
54
+ * releases the lock to the next waiter.
55
+ */
56
+ function waitForTurn(prev, signal) {
57
+ const settled = prev.then(() => {}, () => {});
58
+ if (!signal) return settled;
59
+ if (signal.aborted) return Promise.reject(abortReason(signal));
60
+ return new Promise((resolve, reject) => {
61
+ const onAbort = () => reject(abortReason(signal));
62
+ signal.addEventListener("abort", onAbort, { once: true });
63
+ settled.then(() => {
64
+ signal.removeEventListener("abort", onAbort);
65
+ resolve();
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * No-op {@link SessionLock} for `sessionLock: false` — runs `fn` with no
71
+ * serialization at all. Opt out only when an external mechanism (sticky
72
+ * routing, a single-writer guarantee) already serializes same-session
73
+ * turns.
74
+ */
75
+ function noopSessionLock() {
76
+ return { withLock(_key, fn) {
77
+ return fn();
78
+ } };
79
+ }
80
+
81
+ //#endregion
82
+ export { inProcessSessionLock, noopSessionLock };
83
+ //# sourceMappingURL=session-lock.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-lock.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/orchestrator/session-lock.ts"],"sourcesContent":["import type { SessionLock } from \"../contracts/orchestrator/session-lock.contract\";\n\n/**\n * Reason an aborted lock-wait rejects with — the signal's `reason` when\n * one was supplied to `controller.abort(reason)`, else a generic error.\n */\nfunction abortReason(signal: AbortSignal): unknown {\n return signal.reason ?? new Error(\"session lock wait aborted\");\n}\n\n/**\n * Framework-default in-process {@link SessionLock} — a per-key promise-\n * chain mutex. It holds one tail promise per session key; each acquirer\n * waits on the previous holder's release, then installs its own tail.\n * Keyed by `sessionId`, so different sessions never contend. The wait is\n * abortable, so a cancelled caller never deadlocks behind a stuck\n * predecessor (the deadlock-on-cancel trap).\n *\n * In-process only: serializes same-session turns within ONE process.\n * Supply a distributed {@link SessionLock} for multi-process deployments.\n */\nexport function inProcessSessionLock(): SessionLock {\n const tails = new Map<string, Promise<void>>();\n\n return {\n async withLock<T>(\n key: string,\n fn: () => Promise<T>,\n options?: { signal?: AbortSignal },\n ): Promise<T> {\n const existing = tails.get(key);\n const prev = existing ?? Promise.resolve();\n\n // The caller's signal aborts a genuine WAIT only. When the lock is\n // free (no existing tail) we acquire immediately and let `fn` own\n // cancellation — so a pre-aborted signal never pre-empts graceful\n // in-flight handling (e.g. the orchestrator emitting turn.cancelled).\n const waitSignal = existing ? options?.signal : undefined;\n\n let release!: () => void;\n const held = new Promise<void>(resolve => {\n release = resolve;\n });\n\n // Successors queue behind OUR release. A predecessor that rejects\n // still lets us through (both branches resolve to `held`), so a\n // single failed turn never wedges the whole session.\n const mine = prev.then(\n () => held,\n () => held,\n );\n tails.set(key, mine);\n\n const cleanup = () => {\n // Drop the map entry once we're the tail, so idle sessions don't\n // leak Promise references.\n if (tails.get(key) === mine) {\n tails.delete(key);\n }\n };\n\n try {\n await waitForTurn(prev, waitSignal);\n } catch (error) {\n // Never acquired the critical section — release immediately so\n // successors aren't blocked by an aborted waiter, then surface\n // the abort to the caller.\n release();\n cleanup();\n throw error;\n }\n\n try {\n return await fn();\n } finally {\n release();\n cleanup();\n }\n },\n };\n}\n\n/**\n * Wait for `prev` (the previous holder's release) to settle, racing it\n * against `signal` so a cancelled caller stops waiting instead of\n * deadlocking. Predecessor rejections are swallowed — a failed turn still\n * releases the lock to the next waiter.\n */\nfunction waitForTurn(prev: Promise<void>, signal?: AbortSignal): Promise<void> {\n const settled = prev.then(\n () => {},\n () => {},\n );\n\n if (!signal) return settled;\n if (signal.aborted) return Promise.reject(abortReason(signal));\n\n return new Promise<void>((resolve, reject) => {\n const onAbort = () => reject(abortReason(signal));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void settled.then(() => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve();\n });\n });\n}\n\n/**\n * No-op {@link SessionLock} for `sessionLock: false` — runs `fn` with no\n * serialization at all. Opt out only when an external mechanism (sticky\n * routing, a single-writer guarantee) already serializes same-session\n * turns.\n */\nexport function noopSessionLock(): SessionLock {\n return {\n withLock<T>(_key: string, fn: () => Promise<T>): Promise<T> {\n return fn();\n },\n };\n}\n"],"mappings":";;;;;AAMA,SAAS,YAAY,QAA8B;CACjD,OAAO,OAAO,0BAAU,IAAI,MAAM,2BAA2B;AAC/D;;;;;;;;;;;;AAaA,SAAgB,uBAAoC;CAClD,MAAM,wBAAQ,IAAI,IAA2B;CAE7C,OAAO,EACL,MAAM,SACJ,KACA,IACA,SACY;EACZ,MAAM,WAAW,MAAM,IAAI,GAAG;EAC9B,MAAM,OAAO,YAAY,QAAQ,QAAQ;EAMzC,MAAM,aAAa,WAAW,SAAS,SAAS;EAEhD,IAAI;EACJ,MAAM,OAAO,IAAI,SAAc,YAAW;GACxC,UAAU;EACZ,CAAC;EAKD,MAAM,OAAO,KAAK,WACV,YACA,IACR;EACA,MAAM,IAAI,KAAK,IAAI;EAEnB,MAAM,gBAAgB;GAGpB,IAAI,MAAM,IAAI,GAAG,MAAM,MACrB,MAAM,OAAO,GAAG;EAEpB;EAEA,IAAI;GACF,MAAM,YAAY,MAAM,UAAU;EACpC,SAAS,OAAO;GAId,QAAQ;GACR,QAAQ;GACR,MAAM;EACR;EAEA,IAAI;GACF,OAAO,MAAM,GAAG;EAClB,UAAU;GACR,QAAQ;GACR,QAAQ;EACV;CACF,EACF;AACF;;;;;;;AAQA,SAAS,YAAY,MAAqB,QAAqC;CAC7E,MAAM,UAAU,KAAK,WACb,CAAC,SACD,CAAC,CACT;CAEA,IAAI,CAAC,QAAQ,OAAO;CACpB,IAAI,OAAO,SAAS,OAAO,QAAQ,OAAO,YAAY,MAAM,CAAC;CAE7D,OAAO,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,gBAAgB,OAAO,YAAY,MAAM,CAAC;EAChD,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;EACxD,AAAK,QAAQ,WAAW;GACtB,OAAO,oBAAoB,SAAS,OAAO;GAC3C,QAAQ;EACV,CAAC;CACH,CAAC;AACH;;;;;;;AAQA,SAAgB,kBAA+B;CAC7C,OAAO,EACL,SAAY,MAAc,IAAkC;EAC1D,OAAO,GAAG;CACZ,EACF;AACF"}