@warlock.js/ai 4.4.0 → 4.6.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 (648) hide show
  1. package/CHANGELOG.md +63 -52
  2. package/cjs/index.cjs +240 -14147
  3. package/cjs/src-Bmajk4Qg.cjs +30 -0
  4. package/cjs/src-OZyDYHxm.cjs +25089 -0
  5. package/cjs/src-OZyDYHxm.cjs.map +1 -0
  6. package/esm/agent/agent-config.type.d.mts +119 -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 +328 -36
  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/agent/signature.mjs +57 -0
  21. package/esm/agent/signature.mjs.map +1 -0
  22. package/esm/agent/snapshot.mjs +101 -0
  23. package/esm/agent/snapshot.mjs.map +1 -0
  24. package/esm/ai-openai/src/embedder.mjs +4 -0
  25. package/esm/ai-openai/src/image.mjs +5 -0
  26. package/esm/ai-openai/src/index.mjs +7 -0
  27. package/esm/ai-openai/src/model.mjs +5 -0
  28. package/esm/ai-openai/src/sdk.mjs +9 -0
  29. package/esm/ai-openai/src/speech.mjs +5 -0
  30. package/esm/ai-openai/src/transcription.mjs +6 -0
  31. package/esm/ai-openai/src/utils/index.mjs +5 -0
  32. package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
  33. package/esm/ai-openai/src/utils/to-openai-tools.mjs +3 -0
  34. package/esm/ai-openai/src/utils/wrap-openai-error.mjs +4 -0
  35. package/esm/ai.d.mts +164 -53
  36. package/esm/ai.d.mts.map +1 -1
  37. package/esm/ai.mjs +79 -8
  38. package/esm/ai.mjs.map +1 -1
  39. package/esm/batch/batch.d.mts.map +1 -1
  40. package/esm/batch/batch.mjs +21 -1
  41. package/esm/batch/batch.mjs.map +1 -1
  42. package/esm/batch/batch.type.d.mts +11 -4
  43. package/esm/batch/batch.type.d.mts.map +1 -1
  44. package/esm/config.d.mts +39 -3
  45. package/esm/config.d.mts.map +1 -1
  46. package/esm/config.mjs +26 -2
  47. package/esm/config.mjs.map +1 -1
  48. package/esm/contracts/agent/agent-options.type.d.mts +33 -5
  49. package/esm/contracts/agent/agent-options.type.d.mts.map +1 -1
  50. package/esm/contracts/agent/agent-snapshot.type.d.mts +90 -0
  51. package/esm/contracts/agent/agent-snapshot.type.d.mts.map +1 -0
  52. package/esm/contracts/agent/agent.contract.d.mts +29 -1
  53. package/esm/contracts/agent/agent.contract.d.mts.map +1 -1
  54. package/esm/contracts/agent/eval.type.d.mts +43 -2
  55. package/esm/contracts/agent/eval.type.d.mts.map +1 -1
  56. package/esm/contracts/agent/index.d.mts +2 -1
  57. package/esm/contracts/attachment-policy.type.d.mts +51 -0
  58. package/esm/contracts/attachment-policy.type.d.mts.map +1 -0
  59. package/esm/contracts/attachment.type.d.mts +16 -7
  60. package/esm/contracts/attachment.type.d.mts.map +1 -1
  61. package/esm/contracts/content-part.type.d.mts +14 -5
  62. package/esm/contracts/content-part.type.d.mts.map +1 -1
  63. package/esm/contracts/events/supervisor-events.type.d.mts.map +1 -1
  64. package/esm/contracts/image-model.contract.d.mts +156 -0
  65. package/esm/contracts/image-model.contract.d.mts.map +1 -0
  66. package/esm/contracts/index.d.mts +13 -6
  67. package/esm/contracts/model.contract.d.mts +11 -8
  68. package/esm/contracts/model.contract.d.mts.map +1 -1
  69. package/esm/contracts/orchestrator/index.d.mts +1 -0
  70. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts +31 -2
  71. package/esm/contracts/orchestrator/orchestrator-config.type.d.mts.map +1 -1
  72. package/esm/contracts/orchestrator/session-lock.contract.d.mts +47 -0
  73. package/esm/contracts/orchestrator/session-lock.contract.d.mts.map +1 -0
  74. package/esm/contracts/planner/index.d.mts +3 -2
  75. package/esm/contracts/planner/planner-config.type.d.mts +61 -0
  76. package/esm/contracts/planner/planner-config.type.d.mts.map +1 -1
  77. package/esm/contracts/planner/planner-execute-options.type.d.mts +60 -1
  78. package/esm/contracts/planner/planner-execute-options.type.d.mts.map +1 -1
  79. package/esm/contracts/planner/planner-result.type.d.mts +8 -0
  80. package/esm/contracts/planner/planner-result.type.d.mts.map +1 -1
  81. package/esm/contracts/planner/planner-snapshot.type.d.mts +77 -0
  82. package/esm/contracts/planner/planner-snapshot.type.d.mts.map +1 -0
  83. package/esm/contracts/planner/planner.contract.d.mts +21 -1
  84. package/esm/contracts/planner/planner.contract.d.mts.map +1 -1
  85. package/esm/contracts/result/agent-result.type.d.mts +6 -4
  86. package/esm/contracts/result/agent-result.type.d.mts.map +1 -1
  87. package/esm/contracts/result/base-report.type.d.mts +21 -3
  88. package/esm/contracts/result/base-report.type.d.mts.map +1 -1
  89. package/esm/contracts/result/base-report.type.mjs.map +1 -1
  90. package/esm/contracts/result/execution-report.type.d.mts +53 -1
  91. package/esm/contracts/result/execution-report.type.d.mts.map +1 -1
  92. package/esm/contracts/result/supervisor-result.type.d.mts +14 -2
  93. package/esm/contracts/result/supervisor-result.type.d.mts.map +1 -1
  94. package/esm/contracts/result/workflow-result.type.d.mts +2 -1
  95. package/esm/contracts/result/workflow-result.type.d.mts.map +1 -1
  96. package/esm/contracts/sdk-adapter.contract.d.mts +37 -0
  97. package/esm/contracts/sdk-adapter.contract.d.mts.map +1 -1
  98. package/esm/contracts/speech-model.contract.d.mts +97 -0
  99. package/esm/contracts/speech-model.contract.d.mts.map +1 -0
  100. package/esm/contracts/supervisor/supervisor-config.type.d.mts +29 -0
  101. package/esm/contracts/supervisor/supervisor-config.type.d.mts.map +1 -1
  102. package/esm/contracts/system-prompt.contract.d.mts +103 -1
  103. package/esm/contracts/system-prompt.contract.d.mts.map +1 -1
  104. package/esm/contracts/team/index.d.mts +1 -0
  105. package/esm/contracts/team/team-config.type.d.mts +127 -0
  106. package/esm/contracts/team/team-config.type.d.mts.map +1 -0
  107. package/esm/contracts/tool.contract.d.mts +4 -2
  108. package/esm/contracts/tool.contract.d.mts.map +1 -1
  109. package/esm/contracts/transcription-model.contract.d.mts +101 -0
  110. package/esm/contracts/transcription-model.contract.d.mts.map +1 -0
  111. package/esm/contracts/workflow/step.contract.d.mts +30 -5
  112. package/esm/contracts/workflow/step.contract.d.mts.map +1 -1
  113. package/esm/contracts/workflow/workflow.contract.d.mts +16 -0
  114. package/esm/contracts/workflow/workflow.contract.d.mts.map +1 -1
  115. package/esm/errors/agent-drift-error.d.mts +32 -0
  116. package/esm/errors/agent-drift-error.d.mts.map +1 -0
  117. package/esm/errors/agent-drift-error.mjs +31 -0
  118. package/esm/errors/agent-drift-error.mjs.map +1 -0
  119. package/esm/errors/error-code.type.d.mts +1 -1
  120. package/esm/errors/index.d.mts +3 -0
  121. package/esm/errors/index.mjs +3 -0
  122. package/esm/errors/outbound-policy-error.d.mts +27 -0
  123. package/esm/errors/outbound-policy-error.d.mts.map +1 -0
  124. package/esm/errors/outbound-policy-error.mjs +32 -0
  125. package/esm/errors/outbound-policy-error.mjs.map +1 -0
  126. package/esm/errors/planner-drift-error.d.mts +34 -0
  127. package/esm/errors/planner-drift-error.d.mts.map +1 -0
  128. package/esm/errors/planner-drift-error.mjs +33 -0
  129. package/esm/errors/planner-drift-error.mjs.map +1 -0
  130. package/esm/eval/dataset.d.mts +28 -0
  131. package/esm/eval/dataset.d.mts.map +1 -0
  132. package/esm/eval/dataset.mjs +112 -0
  133. package/esm/eval/dataset.mjs.map +1 -0
  134. package/esm/eval/dataset.type.d.mts +53 -0
  135. package/esm/eval/dataset.type.d.mts.map +1 -0
  136. package/esm/eval/eval-runner.d.mts.map +1 -1
  137. package/esm/eval/eval-runner.mjs +16 -2
  138. package/esm/eval/eval-runner.mjs.map +1 -1
  139. package/esm/eval/index.d.mts +20 -1
  140. package/esm/eval/index.d.mts.map +1 -1
  141. package/esm/eval/index.mjs +20 -2
  142. package/esm/eval/index.mjs.map +1 -1
  143. package/esm/eval/regression.d.mts +30 -0
  144. package/esm/eval/regression.d.mts.map +1 -0
  145. package/esm/eval/regression.mjs +51 -0
  146. package/esm/eval/regression.mjs.map +1 -0
  147. package/esm/eval/report-json.d.mts +30 -0
  148. package/esm/eval/report-json.d.mts.map +1 -0
  149. package/esm/eval/report-json.mjs +33 -0
  150. package/esm/eval/report-json.mjs.map +1 -0
  151. package/esm/eval/report-junit.d.mts +22 -0
  152. package/esm/eval/report-junit.d.mts.map +1 -0
  153. package/esm/eval/report-junit.mjs +60 -0
  154. package/esm/eval/report-junit.mjs.map +1 -0
  155. package/esm/guard/contracts/guard-options.type.d.mts +165 -0
  156. package/esm/guard/contracts/guard-options.type.d.mts.map +1 -0
  157. package/esm/guard/contracts/guardrail.contract.d.mts +78 -0
  158. package/esm/guard/contracts/guardrail.contract.d.mts.map +1 -0
  159. package/esm/guard/contracts/index.d.mts +4 -0
  160. package/esm/guard/contracts/openai-client.contract.d.mts +51 -0
  161. package/esm/guard/contracts/openai-client.contract.d.mts.map +1 -0
  162. package/esm/guard/contracts/verdict.type.d.mts +76 -0
  163. package/esm/guard/contracts/verdict.type.d.mts.map +1 -0
  164. package/esm/guard/detectors/index.d.mts +4 -0
  165. package/esm/guard/detectors/index.mjs +6 -0
  166. package/esm/guard/detectors/injection.d.mts +34 -0
  167. package/esm/guard/detectors/injection.d.mts.map +1 -0
  168. package/esm/guard/detectors/injection.mjs +254 -0
  169. package/esm/guard/detectors/injection.mjs.map +1 -0
  170. package/esm/guard/detectors/moderation.d.mts +32 -0
  171. package/esm/guard/detectors/moderation.d.mts.map +1 -0
  172. package/esm/guard/detectors/moderation.mjs +134 -0
  173. package/esm/guard/detectors/moderation.mjs.map +1 -0
  174. package/esm/guard/detectors/pii.d.mts +41 -0
  175. package/esm/guard/detectors/pii.d.mts.map +1 -0
  176. package/esm/guard/detectors/pii.mjs +199 -0
  177. package/esm/guard/detectors/pii.mjs.map +1 -0
  178. package/esm/guard/detectors/topic.d.mts +29 -0
  179. package/esm/guard/detectors/topic.d.mts.map +1 -0
  180. package/esm/guard/detectors/topic.mjs +99 -0
  181. package/esm/guard/detectors/topic.mjs.map +1 -0
  182. package/esm/guard/errors.d.mts +12 -0
  183. package/esm/guard/errors.d.mts.map +1 -0
  184. package/esm/guard/errors.mjs +18 -0
  185. package/esm/guard/errors.mjs.map +1 -0
  186. package/esm/guard/guard.d.mts +67 -0
  187. package/esm/guard/guard.d.mts.map +1 -0
  188. package/esm/guard/guard.mjs +209 -0
  189. package/esm/guard/guard.mjs.map +1 -0
  190. package/esm/guard/guardrail.d.mts +39 -0
  191. package/esm/guard/guardrail.d.mts.map +1 -0
  192. package/esm/guard/guardrail.mjs +22 -0
  193. package/esm/guard/guardrail.mjs.map +1 -0
  194. package/esm/human/contracts/approval.type.d.mts +154 -0
  195. package/esm/human/contracts/approval.type.d.mts.map +1 -0
  196. package/esm/human/contracts/human-approval.type.d.mts +38 -0
  197. package/esm/human/contracts/human-approval.type.d.mts.map +1 -0
  198. package/esm/human/contracts/index.d.mts +4 -0
  199. package/esm/human/contracts/interrupt-store.contract.d.mts +112 -0
  200. package/esm/human/contracts/interrupt-store.contract.d.mts.map +1 -0
  201. package/esm/human/contracts/resume.type.d.mts +77 -0
  202. package/esm/human/contracts/resume.type.d.mts.map +1 -0
  203. package/esm/human/errors.d.mts +84 -0
  204. package/esm/human/errors.d.mts.map +1 -0
  205. package/esm/human/errors.mjs +60 -0
  206. package/esm/human/errors.mjs.map +1 -0
  207. package/esm/human/human-approval.d.mts +57 -0
  208. package/esm/human/human-approval.d.mts.map +1 -0
  209. package/esm/human/human-approval.mjs +170 -0
  210. package/esm/human/human-approval.mjs.map +1 -0
  211. package/esm/human/policy.d.mts +55 -0
  212. package/esm/human/policy.d.mts.map +1 -0
  213. package/esm/human/policy.mjs +67 -0
  214. package/esm/human/policy.mjs.map +1 -0
  215. package/esm/human/register.mjs +37 -0
  216. package/esm/human/register.mjs.map +1 -0
  217. package/esm/human/resume-seed.mjs +53 -0
  218. package/esm/human/resume-seed.mjs.map +1 -0
  219. package/esm/human/resume.d.mts +54 -0
  220. package/esm/human/resume.d.mts.map +1 -0
  221. package/esm/human/resume.mjs +121 -0
  222. package/esm/human/resume.mjs.map +1 -0
  223. package/esm/human/stores/index.mjs +5 -0
  224. package/esm/human/stores/memory.d.mts +30 -0
  225. package/esm/human/stores/memory.d.mts.map +1 -0
  226. package/esm/human/stores/memory.mjs +91 -0
  227. package/esm/human/stores/memory.mjs.map +1 -0
  228. package/esm/human/stores/pg.d.mts +59 -0
  229. package/esm/human/stores/pg.d.mts.map +1 -0
  230. package/esm/human/stores/pg.mjs +220 -0
  231. package/esm/human/stores/pg.mjs.map +1 -0
  232. package/esm/human/stores/redis.d.mts +56 -0
  233. package/esm/human/stores/redis.d.mts.map +1 -0
  234. package/esm/human/stores/redis.mjs +201 -0
  235. package/esm/human/stores/redis.mjs.map +1 -0
  236. package/esm/image/image-cost.d.mts +32 -0
  237. package/esm/image/image-cost.d.mts.map +1 -0
  238. package/esm/image/image-cost.mjs +55 -0
  239. package/esm/image/image-cost.mjs.map +1 -0
  240. package/esm/image/image.d.mts +92 -0
  241. package/esm/image/image.d.mts.map +1 -0
  242. package/esm/image/image.mjs +113 -0
  243. package/esm/image/image.mjs.map +1 -0
  244. package/esm/image/index.mjs +4 -0
  245. package/esm/index.d.mts +137 -24
  246. package/esm/index.mjs +101 -11
  247. package/esm/middleware/builtins/budget.mjs +6 -2
  248. package/esm/middleware/builtins/budget.mjs.map +1 -1
  249. package/esm/middleware/utils/extract-user-text.d.mts +8 -1
  250. package/esm/middleware/utils/extract-user-text.d.mts.map +1 -1
  251. package/esm/middleware/utils/extract-user-text.mjs +8 -1
  252. package/esm/middleware/utils/extract-user-text.mjs.map +1 -1
  253. package/esm/mock/index.d.mts +3 -0
  254. package/esm/mock/index.mjs +3 -0
  255. package/esm/mock/mock-config.type.d.mts +22 -0
  256. package/esm/mock/mock-config.type.d.mts.map +1 -1
  257. package/esm/mock/mock-image-model.d.mts +41 -0
  258. package/esm/mock/mock-image-model.d.mts.map +1 -0
  259. package/esm/mock/mock-image-model.mjs +52 -0
  260. package/esm/mock/mock-image-model.mjs.map +1 -0
  261. package/esm/mock/mock-sdk.d.mts +7 -1
  262. package/esm/mock/mock-sdk.d.mts.map +1 -1
  263. package/esm/mock/mock-sdk.mjs +27 -0
  264. package/esm/mock/mock-sdk.mjs.map +1 -1
  265. package/esm/mock/mock-speech-model.d.mts +31 -0
  266. package/esm/mock/mock-speech-model.d.mts.map +1 -0
  267. package/esm/mock/mock-speech-model.mjs +39 -0
  268. package/esm/mock/mock-speech-model.mjs.map +1 -0
  269. package/esm/mock/mock-transcription-model.d.mts +32 -0
  270. package/esm/mock/mock-transcription-model.d.mts.map +1 -0
  271. package/esm/mock/mock-transcription-model.mjs +36 -0
  272. package/esm/mock/mock-transcription-model.mjs.map +1 -0
  273. package/esm/object-stream/index.d.mts +2 -0
  274. package/esm/object-stream/index.mjs +4 -0
  275. package/esm/object-stream/parse-partial-json.d.mts +22 -0
  276. package/esm/object-stream/parse-partial-json.d.mts.map +1 -0
  277. package/esm/object-stream/parse-partial-json.mjs +78 -0
  278. package/esm/object-stream/parse-partial-json.mjs.map +1 -0
  279. package/esm/object-stream/stream-object.d.mts +68 -0
  280. package/esm/object-stream/stream-object.d.mts.map +1 -0
  281. package/esm/object-stream/stream-object.mjs +104 -0
  282. package/esm/object-stream/stream-object.mjs.map +1 -0
  283. package/esm/observe/index.mjs +4 -0
  284. package/esm/observe/observer-registry.d.mts +30 -0
  285. package/esm/observe/observer-registry.d.mts.map +1 -0
  286. package/esm/observe/observer-registry.mjs +51 -0
  287. package/esm/observe/observer-registry.mjs.map +1 -0
  288. package/esm/observe/observer.contract.d.mts +40 -0
  289. package/esm/observe/observer.contract.d.mts.map +1 -0
  290. package/esm/observe/resolve-observers.d.mts +40 -0
  291. package/esm/observe/resolve-observers.d.mts.map +1 -0
  292. package/esm/observe/resolve-observers.mjs +73 -0
  293. package/esm/observe/resolve-observers.mjs.map +1 -0
  294. package/esm/orchestrator/execution.d.mts.map +1 -1
  295. package/esm/orchestrator/execution.mjs +5 -2
  296. package/esm/orchestrator/execution.mjs.map +1 -1
  297. package/esm/orchestrator/index.d.mts +1 -0
  298. package/esm/orchestrator/index.mjs +1 -0
  299. package/esm/orchestrator/orchestrator.d.mts.map +1 -1
  300. package/esm/orchestrator/orchestrator.mjs +39 -6
  301. package/esm/orchestrator/orchestrator.mjs.map +1 -1
  302. package/esm/orchestrator/session-lock.d.mts +25 -0
  303. package/esm/orchestrator/session-lock.d.mts.map +1 -0
  304. package/esm/orchestrator/session-lock.mjs +83 -0
  305. package/esm/orchestrator/session-lock.mjs.map +1 -0
  306. package/esm/planner/dag-scheduler.mjs +97 -0
  307. package/esm/planner/dag-scheduler.mjs.map +1 -0
  308. package/esm/planner/plan-prompt.d.mts +1 -1
  309. package/esm/planner/plan-prompt.d.mts.map +1 -1
  310. package/esm/planner/plan-prompt.mjs +2 -1
  311. package/esm/planner/plan-prompt.mjs.map +1 -1
  312. package/esm/planner/planner-run.d.mts +8 -0
  313. package/esm/planner/planner-run.d.mts.map +1 -1
  314. package/esm/planner/planner-run.mjs +457 -31
  315. package/esm/planner/planner-run.mjs.map +1 -1
  316. package/esm/planner/planner.d.mts.map +1 -1
  317. package/esm/planner/planner.mjs +26 -2
  318. package/esm/planner/planner.mjs.map +1 -1
  319. package/esm/planner/snapshot.mjs +95 -0
  320. package/esm/planner/snapshot.mjs.map +1 -0
  321. package/esm/prompt/errors.d.mts +57 -0
  322. package/esm/prompt/errors.d.mts.map +1 -0
  323. package/esm/prompt/errors.mjs +73 -0
  324. package/esm/prompt/errors.mjs.map +1 -0
  325. package/esm/prompt/index.d.mts +3 -0
  326. package/esm/prompt/index.mjs +4 -0
  327. package/esm/prompt/prompt-langfuse-sync.mjs +104 -0
  328. package/esm/prompt/prompt-langfuse-sync.mjs.map +1 -0
  329. package/esm/prompt/prompt-langfuse-sync.type.d.mts +32 -0
  330. package/esm/prompt/prompt-langfuse-sync.type.d.mts.map +1 -0
  331. package/esm/prompt/prompt-validate.mjs +170 -0
  332. package/esm/prompt/prompt-validate.mjs.map +1 -0
  333. package/esm/prompt/prompt.d.mts +54 -0
  334. package/esm/prompt/prompt.d.mts.map +1 -0
  335. package/esm/prompt/prompt.mjs +218 -0
  336. package/esm/prompt/prompt.mjs.map +1 -0
  337. package/esm/prompt/prompt.type.d.mts +174 -0
  338. package/esm/prompt/prompt.type.d.mts.map +1 -0
  339. package/esm/prompts/index.d.mts +3 -0
  340. package/esm/prompts/index.mjs +3 -0
  341. package/esm/prompts/prompts-manager.contract.d.mts +154 -0
  342. package/esm/prompts/prompts-manager.contract.d.mts.map +1 -0
  343. package/esm/prompts/prompts-manager.d.mts +38 -0
  344. package/esm/prompts/prompts-manager.d.mts.map +1 -0
  345. package/esm/prompts/prompts-manager.mjs +410 -0
  346. package/esm/prompts/prompts-manager.mjs.map +1 -0
  347. package/esm/prompts/prompts-manager.type.d.mts +172 -0
  348. package/esm/prompts/prompts-manager.type.d.mts.map +1 -0
  349. package/esm/prompts/prompts-validate.mjs +200 -0
  350. package/esm/prompts/prompts-validate.mjs.map +1 -0
  351. package/esm/rag/as-tool.mjs +48 -0
  352. package/esm/rag/as-tool.mjs.map +1 -0
  353. package/esm/rag/chunk/chunk.d.mts +24 -0
  354. package/esm/rag/chunk/chunk.d.mts.map +1 -0
  355. package/esm/rag/chunk/chunk.mjs +44 -0
  356. package/esm/rag/chunk/chunk.mjs.map +1 -0
  357. package/esm/rag/chunk/fixed.mjs +32 -0
  358. package/esm/rag/chunk/fixed.mjs.map +1 -0
  359. package/esm/rag/chunk/markdown.mjs +75 -0
  360. package/esm/rag/chunk/markdown.mjs.map +1 -0
  361. package/esm/rag/chunk/recursive.mjs +132 -0
  362. package/esm/rag/chunk/recursive.mjs.map +1 -0
  363. package/esm/rag/chunk/sentence.mjs +73 -0
  364. package/esm/rag/chunk/sentence.mjs.map +1 -0
  365. package/esm/rag/contracts/chunk-options.type.d.mts +35 -0
  366. package/esm/rag/contracts/chunk-options.type.d.mts.map +1 -0
  367. package/esm/rag/contracts/citation.type.d.mts +35 -0
  368. package/esm/rag/contracts/citation.type.d.mts.map +1 -0
  369. package/esm/rag/contracts/index.d.mts +4 -0
  370. package/esm/rag/contracts/rag-config.type.d.mts +68 -0
  371. package/esm/rag/contracts/rag-config.type.d.mts.map +1 -0
  372. package/esm/rag/contracts/rag-document.type.d.mts +21 -0
  373. package/esm/rag/contracts/rag-document.type.d.mts.map +1 -0
  374. package/esm/rag/hybrid/bm25.d.mts +23 -0
  375. package/esm/rag/hybrid/bm25.d.mts.map +1 -0
  376. package/esm/rag/hybrid/bm25.mjs +51 -0
  377. package/esm/rag/hybrid/bm25.mjs.map +1 -0
  378. package/esm/rag/hybrid/hybrid-rank.d.mts +33 -0
  379. package/esm/rag/hybrid/hybrid-rank.d.mts.map +1 -0
  380. package/esm/rag/hybrid/hybrid-rank.mjs +29 -0
  381. package/esm/rag/hybrid/hybrid-rank.mjs.map +1 -0
  382. package/esm/rag/hybrid/rrf.d.mts +25 -0
  383. package/esm/rag/hybrid/rrf.d.mts.map +1 -0
  384. package/esm/rag/hybrid/rrf.mjs +30 -0
  385. package/esm/rag/hybrid/rrf.mjs.map +1 -0
  386. package/esm/rag/index.d.mts +22 -0
  387. package/esm/rag/index.mjs +18 -0
  388. package/esm/rag/loaders/errors.d.mts +19 -0
  389. package/esm/rag/loaders/errors.d.mts.map +1 -0
  390. package/esm/rag/loaders/errors.mjs +25 -0
  391. package/esm/rag/loaders/errors.mjs.map +1 -0
  392. package/esm/rag/loaders/index.mjs +7 -0
  393. package/esm/rag/loaders/load-html.d.mts +26 -0
  394. package/esm/rag/loaders/load-html.d.mts.map +1 -0
  395. package/esm/rag/loaders/load-html.mjs +138 -0
  396. package/esm/rag/loaders/load-html.mjs.map +1 -0
  397. package/esm/rag/loaders/load-pdf.d.mts +38 -0
  398. package/esm/rag/loaders/load-pdf.d.mts.map +1 -0
  399. package/esm/rag/loaders/load-pdf.mjs +150 -0
  400. package/esm/rag/loaders/load-pdf.mjs.map +1 -0
  401. package/esm/rag/loaders/load-text.d.mts +47 -0
  402. package/esm/rag/loaders/load-text.d.mts.map +1 -0
  403. package/esm/rag/loaders/load-text.mjs +60 -0
  404. package/esm/rag/loaders/load-text.mjs.map +1 -0
  405. package/esm/rag/loaders/load-web.d.mts +42 -0
  406. package/esm/rag/loaders/load-web.d.mts.map +1 -0
  407. package/esm/rag/loaders/load-web.mjs +89 -0
  408. package/esm/rag/loaders/load-web.mjs.map +1 -0
  409. package/esm/rag/loaders/loader.type.d.mts +89 -0
  410. package/esm/rag/loaders/loader.type.d.mts.map +1 -0
  411. package/esm/rag/rag.d.mts +38 -0
  412. package/esm/rag/rag.d.mts.map +1 -0
  413. package/esm/rag/rag.mjs +126 -0
  414. package/esm/rag/rag.mjs.map +1 -0
  415. package/esm/rag/rerank/keyword-reranker.d.mts +32 -0
  416. package/esm/rag/rerank/keyword-reranker.d.mts.map +1 -0
  417. package/esm/rag/rerank/keyword-reranker.mjs +58 -0
  418. package/esm/rag/rerank/keyword-reranker.mjs.map +1 -0
  419. package/esm/rag/rerank/llm-reranker.d.mts +36 -0
  420. package/esm/rag/rerank/llm-reranker.d.mts.map +1 -0
  421. package/esm/rag/rerank/llm-reranker.mjs +85 -0
  422. package/esm/rag/rerank/llm-reranker.mjs.map +1 -0
  423. package/esm/rag/rerank/reranker.contract.d.mts +28 -0
  424. package/esm/rag/rerank/reranker.contract.d.mts.map +1 -0
  425. package/esm/rag/retrieve.mjs +68 -0
  426. package/esm/rag/retrieve.mjs.map +1 -0
  427. package/esm/rag/store/cache-vector-store.d.mts +27 -0
  428. package/esm/rag/store/cache-vector-store.d.mts.map +1 -0
  429. package/esm/rag/store/cache-vector-store.mjs +48 -0
  430. package/esm/rag/store/cache-vector-store.mjs.map +1 -0
  431. package/esm/rag/store/pg-vector-store.d.mts +139 -0
  432. package/esm/rag/store/pg-vector-store.d.mts.map +1 -0
  433. package/esm/rag/store/pg-vector-store.mjs +328 -0
  434. package/esm/rag/store/pg-vector-store.mjs.map +1 -0
  435. package/esm/rag/store/vector-store.contract.d.mts +38 -0
  436. package/esm/rag/store/vector-store.contract.d.mts.map +1 -0
  437. package/esm/rag/transforms/multi-query.d.mts +27 -0
  438. package/esm/rag/transforms/multi-query.d.mts.map +1 -0
  439. package/esm/rag/transforms/multi-query.mjs +41 -0
  440. package/esm/rag/transforms/multi-query.mjs.map +1 -0
  441. package/esm/security/index.mjs +5 -0
  442. package/esm/security/outbound-policy.d.mts +46 -0
  443. package/esm/security/outbound-policy.d.mts.map +1 -0
  444. package/esm/security/outbound-policy.mjs +187 -0
  445. package/esm/security/outbound-policy.mjs.map +1 -0
  446. package/esm/security/outbound-policy.type.d.mts +74 -0
  447. package/esm/security/outbound-policy.type.d.mts.map +1 -0
  448. package/esm/security/private-ip.d.mts +15 -0
  449. package/esm/security/private-ip.d.mts.map +1 -0
  450. package/esm/security/private-ip.mjs +48 -0
  451. package/esm/security/private-ip.mjs.map +1 -0
  452. package/esm/security/redact.d.mts +59 -0
  453. package/esm/security/redact.d.mts.map +1 -0
  454. package/esm/security/redact.mjs +122 -0
  455. package/esm/security/redact.mjs.map +1 -0
  456. package/esm/serve/serve.d.mts +50 -0
  457. package/esm/serve/serve.d.mts.map +1 -0
  458. package/esm/serve/serve.mjs +90 -0
  459. package/esm/serve/serve.mjs.map +1 -0
  460. package/esm/serve/sse.d.mts +20 -0
  461. package/esm/serve/sse.d.mts.map +1 -0
  462. package/esm/serve/sse.mjs +25 -0
  463. package/esm/serve/sse.mjs.map +1 -0
  464. package/esm/serve/stream-to-sse.d.mts +29 -0
  465. package/esm/serve/stream-to-sse.d.mts.map +1 -0
  466. package/esm/serve/stream-to-sse.mjs +37 -0
  467. package/esm/serve/stream-to-sse.mjs.map +1 -0
  468. package/esm/skills/catalog.d.mts +49 -0
  469. package/esm/skills/catalog.d.mts.map +1 -0
  470. package/esm/skills/catalog.mjs +140 -0
  471. package/esm/skills/catalog.mjs.map +1 -0
  472. package/esm/skills/contracts/skill-record.type.d.mts +37 -0
  473. package/esm/skills/contracts/skill-record.type.d.mts.map +1 -0
  474. package/esm/skills/contracts/skills-config.type.d.mts +108 -0
  475. package/esm/skills/contracts/skills-config.type.d.mts.map +1 -0
  476. package/esm/skills/contracts/skills-store.contract.d.mts +28 -0
  477. package/esm/skills/contracts/skills-store.contract.d.mts.map +1 -0
  478. package/esm/skills/contracts/skills.contract.d.mts +43 -0
  479. package/esm/skills/contracts/skills.contract.d.mts.map +1 -0
  480. package/esm/skills/index.d.mts +16 -0
  481. package/esm/skills/index.mjs +14 -0
  482. package/esm/skills/load-skill-tool.d.mts +38 -0
  483. package/esm/skills/load-skill-tool.d.mts.map +1 -0
  484. package/esm/skills/load-skill-tool.mjs +65 -0
  485. package/esm/skills/load-skill-tool.mjs.map +1 -0
  486. package/esm/skills/review-gate.d.mts +33 -0
  487. package/esm/skills/review-gate.d.mts.map +1 -0
  488. package/esm/skills/review-gate.mjs +60 -0
  489. package/esm/skills/review-gate.mjs.map +1 -0
  490. package/esm/skills/save-skill-tool.d.mts +39 -0
  491. package/esm/skills/save-skill-tool.d.mts.map +1 -0
  492. package/esm/skills/save-skill-tool.mjs +65 -0
  493. package/esm/skills/save-skill-tool.mjs.map +1 -0
  494. package/esm/skills/skills.d.mts +33 -0
  495. package/esm/skills/skills.d.mts.map +1 -0
  496. package/esm/skills/skills.mjs +109 -0
  497. package/esm/skills/skills.mjs.map +1 -0
  498. package/esm/skills/sources/directory-source.d.mts +19 -0
  499. package/esm/skills/sources/directory-source.d.mts.map +1 -0
  500. package/esm/skills/sources/directory-source.mjs +108 -0
  501. package/esm/skills/sources/directory-source.mjs.map +1 -0
  502. package/esm/skills/sources/index.d.mts +18 -0
  503. package/esm/skills/sources/index.d.mts.map +1 -0
  504. package/esm/skills/sources/index.mjs +27 -0
  505. package/esm/skills/sources/index.mjs.map +1 -0
  506. package/esm/skills/sources/parse-frontmatter.d.mts +27 -0
  507. package/esm/skills/sources/parse-frontmatter.d.mts.map +1 -0
  508. package/esm/skills/sources/parse-frontmatter.mjs +46 -0
  509. package/esm/skills/sources/parse-frontmatter.mjs.map +1 -0
  510. package/esm/skills/sources/store-source.d.mts +14 -0
  511. package/esm/skills/sources/store-source.d.mts.map +1 -0
  512. package/esm/skills/sources/store-source.mjs +15 -0
  513. package/esm/skills/sources/store-source.mjs.map +1 -0
  514. package/esm/skills/sources/url-source.d.mts +29 -0
  515. package/esm/skills/sources/url-source.d.mts.map +1 -0
  516. package/esm/skills/sources/url-source.mjs +117 -0
  517. package/esm/skills/sources/url-source.mjs.map +1 -0
  518. package/esm/skills/store/mock-skills-store.d.mts +57 -0
  519. package/esm/skills/store/mock-skills-store.d.mts.map +1 -0
  520. package/esm/skills/store/mock-skills-store.mjs +100 -0
  521. package/esm/skills/store/mock-skills-store.mjs.map +1 -0
  522. package/esm/skills/store/procedural-skill-store.d.mts +30 -0
  523. package/esm/skills/store/procedural-skill-store.d.mts.map +1 -0
  524. package/esm/skills/store/procedural-skill-store.mjs +125 -0
  525. package/esm/skills/store/procedural-skill-store.mjs.map +1 -0
  526. package/esm/speech/index.mjs +3 -0
  527. package/esm/speech/speech.d.mts +65 -0
  528. package/esm/speech/speech.d.mts.map +1 -0
  529. package/esm/speech/speech.mjs +123 -0
  530. package/esm/speech/speech.mjs.map +1 -0
  531. package/esm/supervisor/as-tool.mjs +2 -2
  532. package/esm/supervisor/as-tool.mjs.map +1 -1
  533. package/esm/supervisor/entries.mjs +2 -2
  534. package/esm/supervisor/entries.mjs.map +1 -1
  535. package/esm/supervisor/execution.d.mts.map +1 -1
  536. package/esm/supervisor/execution.mjs +31 -28
  537. package/esm/supervisor/execution.mjs.map +1 -1
  538. package/esm/supervisor/supervisor.d.mts.map +1 -1
  539. package/esm/supervisor/supervisor.mjs +8 -3
  540. package/esm/supervisor/supervisor.mjs.map +1 -1
  541. package/esm/system-prompt/index.d.mts +4 -0
  542. package/esm/system-prompt/system-prompt.d.mts +68 -4
  543. package/esm/system-prompt/system-prompt.d.mts.map +1 -1
  544. package/esm/system-prompt/system-prompt.mjs +89 -5
  545. package/esm/system-prompt/system-prompt.mjs.map +1 -1
  546. package/esm/team/gates.mjs +48 -0
  547. package/esm/team/gates.mjs.map +1 -0
  548. package/esm/team/index.d.mts +1 -0
  549. package/esm/team/index.mjs +3 -0
  550. package/esm/team/team.d.mts +42 -0
  551. package/esm/team/team.d.mts.map +1 -0
  552. package/esm/team/team.mjs +94 -0
  553. package/esm/team/team.mjs.map +1 -0
  554. package/esm/tool/executable-as-tool.d.mts.map +1 -1
  555. package/esm/tool/executable-as-tool.mjs +2 -2
  556. package/esm/tool/executable-as-tool.mjs.map +1 -1
  557. package/esm/tool/tool.d.mts.map +1 -1
  558. package/esm/tool/tool.mjs +2 -2
  559. package/esm/tool/tool.mjs.map +1 -1
  560. package/esm/transcribe/audio-input.d.mts +47 -0
  561. package/esm/transcribe/audio-input.d.mts.map +1 -0
  562. package/esm/transcribe/audio-input.mjs +84 -0
  563. package/esm/transcribe/audio-input.mjs.map +1 -0
  564. package/esm/transcribe/index.mjs +4 -0
  565. package/esm/transcribe/transcribe.d.mts +64 -0
  566. package/esm/transcribe/transcribe.d.mts.map +1 -0
  567. package/esm/transcribe/transcribe.mjs +128 -0
  568. package/esm/transcribe/transcribe.mjs.map +1 -0
  569. package/esm/utils/compute-cost.d.mts +17 -1
  570. package/esm/utils/compute-cost.d.mts.map +1 -1
  571. package/esm/utils/compute-cost.mjs +26 -1
  572. package/esm/utils/compute-cost.mjs.map +1 -1
  573. package/esm/utils/extract-json-lenient.d.mts +42 -0
  574. package/esm/utils/extract-json-lenient.d.mts.map +1 -0
  575. package/esm/utils/extract-json-lenient.mjs +97 -0
  576. package/esm/utils/extract-json-lenient.mjs.map +1 -0
  577. package/esm/utils/index.d.mts +4 -2
  578. package/esm/utils/index.mjs +3 -1
  579. package/esm/utils/json-schema.d.mts +1 -1
  580. package/esm/utils/prepare-attachment-part.d.mts +10 -1
  581. package/esm/utils/prepare-attachment-part.d.mts.map +1 -1
  582. package/esm/utils/prepare-attachment-part.mjs +103 -11
  583. package/esm/utils/prepare-attachment-part.mjs.map +1 -1
  584. package/esm/utils/resolve-attachment.d.mts +4 -3
  585. package/esm/utils/resolve-attachment.d.mts.map +1 -1
  586. package/esm/utils/resolve-attachment.mjs +4 -3
  587. package/esm/utils/resolve-attachment.mjs.map +1 -1
  588. package/esm/utils/run-context.d.mts +94 -0
  589. package/esm/utils/run-context.d.mts.map +1 -0
  590. package/esm/utils/run-context.mjs +98 -0
  591. package/esm/utils/run-context.mjs.map +1 -0
  592. package/esm/vcr/cassette-io.mjs +57 -0
  593. package/esm/vcr/cassette-io.mjs.map +1 -0
  594. package/esm/vcr/errors.d.mts +42 -0
  595. package/esm/vcr/errors.d.mts.map +1 -0
  596. package/esm/vcr/errors.mjs +37 -0
  597. package/esm/vcr/errors.mjs.map +1 -0
  598. package/esm/vcr/hash-request.d.mts +28 -0
  599. package/esm/vcr/hash-request.d.mts.map +1 -0
  600. package/esm/vcr/hash-request.mjs +118 -0
  601. package/esm/vcr/hash-request.mjs.map +1 -0
  602. package/esm/vcr/index.d.mts +4 -0
  603. package/esm/vcr/index.mjs +5 -0
  604. package/esm/vcr/vcr.d.mts +32 -0
  605. package/esm/vcr/vcr.d.mts.map +1 -0
  606. package/esm/vcr/vcr.mjs +248 -0
  607. package/esm/vcr/vcr.mjs.map +1 -0
  608. package/esm/vcr/vcr.type.d.mts +118 -0
  609. package/esm/vcr/vcr.type.d.mts.map +1 -0
  610. package/esm/workflow/as-tool.mjs +2 -2
  611. package/esm/workflow/as-tool.mjs.map +1 -1
  612. package/esm/workflow/engine.mjs +1 -0
  613. package/esm/workflow/engine.mjs.map +1 -1
  614. package/esm/workflow/step-runner.mjs +19 -20
  615. package/esm/workflow/step-runner.mjs.map +1 -1
  616. package/esm/workflow/workflow.d.mts.map +1 -1
  617. package/esm/workflow/workflow.mjs +8 -3
  618. package/esm/workflow/workflow.mjs.map +1 -1
  619. package/llms-full.txt +2572 -204
  620. package/llms.txt +21 -4
  621. package/package.json +7 -3
  622. package/skills/README.md +44 -4
  623. package/skills/ai-dx-helpers/SKILL.md +2 -2
  624. package/skills/approve-tool-calls/SKILL.md +134 -0
  625. package/skills/attach-ai-middleware/SKILL.md +1 -1
  626. package/skills/detect-and-redact-pii/SKILL.md +104 -0
  627. package/skills/durable-agent-runs/SKILL.md +135 -0
  628. package/skills/durable-resume/SKILL.md +128 -0
  629. package/skills/escalate-block-to-human/SKILL.md +85 -0
  630. package/skills/eval-datasets-and-ci/SKILL.md +117 -0
  631. package/skills/generate-images/SKILL.md +138 -0
  632. package/skills/generate-speech/SKILL.md +139 -0
  633. package/skills/guard-input-output/SKILL.md +117 -0
  634. package/skills/manage-prompts/SKILL.md +186 -0
  635. package/skills/observe-ai-flows/SKILL.md +94 -0
  636. package/skills/rag-loaders-and-stores/SKILL.md +164 -0
  637. package/skills/record-replay-llm/SKILL.md +92 -0
  638. package/skills/run-ai-agent/SKILL.md +26 -1
  639. package/skills/run-ai-rag/SKILL.md +139 -0
  640. package/skills/run-ai-team/SKILL.md +107 -0
  641. package/skills/run-orchestrator/SKILL.md +2 -0
  642. package/skills/run-planner/SKILL.md +73 -8
  643. package/skills/run-supervisor/SKILL.md +20 -1
  644. package/skills/transcribe-audio/SKILL.md +157 -0
  645. package/skills/use-runtime-skills/SKILL.md +106 -0
  646. package/skills/write-system-prompt/SKILL.md +30 -1
  647. package/cjs/index.cjs.map +0 -1
  648. package/esm/contracts/result/index.d.mts +0 -15
@@ -0,0 +1,112 @@
1
+ import { ApprovalRequest } from "./approval.type.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/human/contracts/interrupt-store.contract.d.ts
4
+ /**
5
+ * Lifecycle status of a persisted interrupt.
6
+ *
7
+ * `"pending"` until a decision lands; the record is marked
8
+ * `"resolved"` (then deleted) once `ai.human.resume(...)` applies a
9
+ * decision. Discriminator is `status` (a closed string union), so a
10
+ * caller can branch idempotently — a second resume of a `"resolved"`
11
+ * (or already-deleted) interrupt is a no-op, never a double-apply.
12
+ */
13
+ type PendingInterruptStatus = "pending" | "resolved";
14
+ /**
15
+ * A persisted, awaiting-decision interrupt — the durable counterpart of
16
+ * an in-flight {@link ApprovalRequest}.
17
+ *
18
+ * Mirrors the shape the snapshot/checkpoint stores persist: a flat
19
+ * record keyed by a single id (`interruptId`) that the store round-trips
20
+ * verbatim. The `request` is everything a reviewer (in another process,
21
+ * hours later) needs to rule on the call; `status` tracks the lifecycle;
22
+ * `savedAt` is the ISO-8601 write time.
23
+ */
24
+ interface PendingInterrupt {
25
+ /** Stable id; the store keys the record on it. */
26
+ interruptId: string;
27
+ /** The pending call the human is asked to rule on. */
28
+ request: ApprovalRequest;
29
+ /** `"pending"` until a decision lands; then `"resolved"` and deleted. */
30
+ status: PendingInterruptStatus;
31
+ /** When the record was written, as an ISO-8601 timestamp. */
32
+ savedAt: string;
33
+ }
34
+ /**
35
+ * Durable store for {@link PendingInterrupt} records — the persistence
36
+ * seam behind durable human-in-the-loop approval.
37
+ *
38
+ * Deliberately shaped like the `@warlock.js/ai`
39
+ * `SnapshotStore` / `CheckpointStore` contracts (`load` / `save` /
40
+ * `delete` / optional `list` / `schema`), so a consumer already running
41
+ * an orchestrator can reuse the **same** `pg.Pool` / redis client for
42
+ * the interrupt table. Keyed by `interruptId`. Schema is never
43
+ * auto-migrated — {@link InterruptStore.schema} returns a DDL string the
44
+ * dev runs through their own migration tooling.
45
+ *
46
+ * Implementations: `ai.human.interrupt.{memory,pg,redis}()`. The memory
47
+ * impl ships first (pure in-process `Map`, zero deps); pg/redis lazily
48
+ * import their client via {@link PgClientLike} / {@link RedisClientLike}
49
+ * so neither driver is a hard dependency.
50
+ */
51
+ interface InterruptStore {
52
+ /**
53
+ * Persist a pending interrupt, keyed by its own `interruptId`.
54
+ * Overwrites any prior record for the same id (a call has exactly one
55
+ * live interrupt).
56
+ */
57
+ save(record: PendingInterrupt): Promise<void>;
58
+ /**
59
+ * Load the interrupt for an `interruptId`, or `undefined` when none is
60
+ * recorded (never raised, or already resolved + deleted).
61
+ */
62
+ load(interruptId: string): Promise<PendingInterrupt | undefined>;
63
+ /**
64
+ * Drop the interrupt for an `interruptId`. Idempotent — deleting an
65
+ * absent id is a no-op.
66
+ */
67
+ delete(interruptId: string): Promise<void>;
68
+ /**
69
+ * List the interrupt ids the store knows, optionally filtered by a
70
+ * prefix. Optional — stores that can't enumerate (e.g. a key/value
71
+ * driver with no `SCAN`) omit it.
72
+ */
73
+ list?(prefix?: string): Promise<string[]>;
74
+ /**
75
+ * Return the DDL string for this store's backing table. The dev runs
76
+ * it through their migration tool; the framework never auto-migrates.
77
+ * Stores with no backing table (memory, redis) return an empty string
78
+ * so callers can treat `schema()` uniformly across drivers.
79
+ */
80
+ schema(): string;
81
+ }
82
+ /**
83
+ * Minimal `pg`-compatible client surface the Postgres
84
+ * {@link InterruptStore} depends on. Both `pg.Pool` and `pg.Client`
85
+ * satisfy it — the store only ever calls `query`.
86
+ *
87
+ * `@warlock.js/ai` takes **no** hard dependency on `pg`; the dev
88
+ * installs it (an optional peer) and passes the client in. Structurally
89
+ * identical to the orchestrator stores' `PgClientLike`, so a single pool
90
+ * can back the checkpoint/snapshot stores and the interrupt table alike.
91
+ */
92
+ interface PgClientLike {
93
+ query(text: string, params?: unknown[]): Promise<{
94
+ rows: unknown[];
95
+ }>;
96
+ }
97
+ /**
98
+ * Minimal `redis`-compatible client surface the Redis
99
+ * {@link InterruptStore} depends on.
100
+ *
101
+ * `@warlock.js/ai` takes **no** hard dependency on `redis`; the dev
102
+ * installs it (an optional peer) and passes the connected client in. The
103
+ * store only calls `get` / `set` / `del`.
104
+ */
105
+ interface RedisClientLike {
106
+ get(key: string): Promise<string | null>;
107
+ set(key: string, value: string, ...args: unknown[]): Promise<unknown>;
108
+ del(key: string): Promise<number>;
109
+ }
110
+ //#endregion
111
+ export { InterruptStore, PendingInterrupt, PendingInterruptStatus, PgClientLike, RedisClientLike };
112
+ //# sourceMappingURL=interrupt-store.contract.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interrupt-store.contract.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/human/contracts/interrupt-store.contract.ts"],"mappings":";;;;;AAWA;;;;AAAkC;AAYlC;;KAZY,sBAAA;;;;;;;;;AAuBH;AAoBT;UA/BiB,gBAAA;;EAEf,WAAA;EAmCgC;EAhChC,OAAA,EAAS,eAAA;EAsCkB;EAnC3B,MAAA,EAAQ,sBAAsB;EAgDN;EA7CxB,OAAA;AAAA;;;;;;;;;;;;;;;;;AAqDM;UAjCS,cAAA;EA8CY;;;;;EAxC3B,IAAA,CAAK,MAAA,EAAQ,gBAAA,GAAmB,OAAA;EAyCS;;;AAAc;EAnCvD,IAAA,CAAK,WAAA,WAAsB,OAAA,CAAQ,gBAAA;EA8CL;;;;EAxC9B,MAAA,CAAO,WAAA,WAAsB,OAAA;EA2CJ;;;;;EApCzB,IAAA,EAAM,MAAA,YAAkB,OAAA;EAmCpB;;;;;;EA3BJ,MAAA;AAAA;AA4ByB;;;;;;;;;;AAAA,UAfV,YAAA;EACf,KAAA,CAAM,IAAA,UAAc,MAAA,eAAqB,OAAO;IAAG,IAAA;EAAA;AAAA;;;;;;;;;UAWpC,eAAA;EACf,GAAA,CAAI,GAAA,WAAc,OAAA;EAClB,GAAA,CAAI,GAAA,UAAa,KAAA,aAAkB,IAAA,cAAkB,OAAA;EACrD,GAAA,CAAI,GAAA,WAAc,OAAA;AAAA"}
@@ -0,0 +1,77 @@
1
+ import { AgentResult } from "../../contracts/result/agent-result.type.mjs";
2
+ import { AgentContract } from "../../contracts/agent/agent.contract.mjs";
3
+ import { AgentExecuteOptions } from "../../contracts/agent/agent-options.type.mjs";
4
+ import { ApprovalDecision } from "./approval.type.mjs";
5
+ import { InterruptStore } from "./interrupt-store.contract.mjs";
6
+
7
+ //#region ../@warlock.js/ai/src/human/contracts/resume.type.d.ts
8
+ /**
9
+ * Options for `ai.human.resume(interruptId, decision, options)` — the
10
+ * out-of-process resume entry point behind durable human-in-the-loop
11
+ * approval.
12
+ *
13
+ * The `store` is always required: it is where the persisted
14
+ * {@link import("./interrupt-store.contract").PendingInterrupt} is loaded
15
+ * from and deleted after the decision is applied.
16
+ *
17
+ * **Two resume shapes share this one options bag:**
18
+ * - **apply-only** — omit `agent`. The decision is loaded, validated
19
+ * against the persisted request, the pending record is deleted, and the
20
+ * `{ interruptId, decision }` is returned for the caller to re-drive the
21
+ * agent itself (e.g. a custom transport). No turn is re-run.
22
+ * - **re-run** — pass `agent` (and optionally an `input` override). v1
23
+ * durable resume re-executes the agent turn with the decision
24
+ * **pre-seeded**, so the gated tool call this time resolves to the
25
+ * human's ruling instead of pausing again. The original prompt is
26
+ * re-used unless `input` overrides it.
27
+ */
28
+ interface ResumeOptions<TOutput = unknown> {
29
+ /**
30
+ * The durable store holding the {@link PendingInterrupt}. Loaded to find
31
+ * the original request, then deleted once the decision is applied.
32
+ */
33
+ store: InterruptStore;
34
+ /**
35
+ * The agent to re-drive with the decision pre-seeded. Omit for the
36
+ * apply-only shape (load + validate + delete, return the decision for a
37
+ * caller-owned re-drive).
38
+ */
39
+ agent?: AgentContract<TOutput>;
40
+ /**
41
+ * Prompt for the re-run. Defaults to the original prompt captured on the
42
+ * persisted {@link PendingInterrupt} request context; pass it to override
43
+ * (e.g. to append the reviewer's note). Ignored when `agent` is omitted.
44
+ */
45
+ input?: string;
46
+ /**
47
+ * Extra options forwarded to `agent.execute(input, executeOptions)` on
48
+ * the re-run (history, placeholders, output schema, signal, …). Ignored
49
+ * when `agent` is omitted.
50
+ */
51
+ executeOptions?: AgentExecuteOptions<TOutput>;
52
+ }
53
+ /**
54
+ * Outcome of `ai.human.resume(...)`.
55
+ *
56
+ * A discriminated union keyed on `type` (never `kind`):
57
+ * - `"applied"` — a live `"pending"` interrupt was found, the decision was
58
+ * applied, and the record deleted. When the caller passed an `agent`,
59
+ * `result` carries the re-run's {@link AgentResult}; otherwise the caller
60
+ * re-drives the agent itself using the returned `decision`.
61
+ * - `"already-resolved"` — no live interrupt for this id (already resolved
62
+ * + deleted, or never raised). Idempotent no-op — the decision is **not**
63
+ * re-applied and no turn is re-run, mirroring the orchestrator resume's
64
+ * drain idempotency.
65
+ */
66
+ type ResumeResult<TOutput = unknown> = {
67
+ type: "applied"; /** The id of the interrupt the decision was applied to. */
68
+ interruptId: string; /** The decision that was applied. */
69
+ decision: ApprovalDecision; /** The re-run agent result, present only when an `agent` was supplied. */
70
+ result?: AgentResult<TOutput>;
71
+ } | {
72
+ type: "already-resolved"; /** The id that had no live interrupt to resume. */
73
+ interruptId: string;
74
+ };
75
+ //#endregion
76
+ export { ResumeOptions, ResumeResult };
77
+ //# sourceMappingURL=resume.type.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resume.type.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/human/contracts/resume.type.ts"],"mappings":";;;;;;;;;AA0BA;;;;;;;;;;;;;;;;;;UAAiB,aAAA;EA0BsB;;AAAO;AAgB9C;EArCE,KAAA,EAAO,cAAA;EAqCe;;;;;EA9BtB,KAAA,GAAQ,aAAA,CAAc,OAAA;EA8BC;;;;;EAvBvB,KAAA;EA+Ba;;;;;EAxBb,cAAA,GAAiB,mBAAA,CAAoB,OAAA;AAAA;;;;;;;;;;;;;;KAgB3B,YAAA;EAEN,IAAA;EAEA,WAAA;EAEA,QAAA,EAAU,gBAAA;EAEV,MAAA,GAAS,WAAA,CAAY,OAAA;AAAA;EAGrB,IAAA;EAEA,WAAA;AAAA"}
@@ -0,0 +1,84 @@
1
+ import { AIError, AIErrorOptions } from "../errors/ai-error.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/human/errors.d.ts
4
+ /**
5
+ * Stable, machine-readable codes this package raises.
6
+ *
7
+ * `@warlock.js/ai`'s `AIErrorCode` is a closed union that (by design)
8
+ * does not enumerate satellite-package codes, and this package must not
9
+ * modify the core union. These codes are therefore declared locally and
10
+ * narrowed into the base `AIError` `code` slot at the single `super(...)`
11
+ * call — the runtime string is exactly what a consumer branches on via
12
+ * `error.code`, identical to every other `AIError`.
13
+ */
14
+ type HumanErrorCode = "INTERRUPT_SUSPENDED" | "APPROVAL_REJECTED";
15
+ /**
16
+ * Payload for {@link InterruptSuspendedError}. `interruptId` is the key a
17
+ * later `ai.human.resume(interruptId, decision)` call uses to replay the
18
+ * decision against the persisted interrupt.
19
+ */
20
+ type InterruptSuspendedErrorOptions = AIErrorOptions & {
21
+ /** Id of the persisted interrupt awaiting a decision. */interruptId: string;
22
+ };
23
+ /**
24
+ * A durable approval handler suspended the run rather than denying the
25
+ * call.
26
+ *
27
+ * **Role.** The sentinel a durable {@link import("./contracts").ApprovalHandler}
28
+ * throws after persisting a
29
+ * {@link import("./contracts").PendingInterrupt}. The approval
30
+ * middleware recognizes its own sentinel (an `instanceof` check) and
31
+ * re-throws so the agent run unwinds; the dispatch records it as a failed
32
+ * tool call carrying this typed error. The caller reads
33
+ * `error.interruptId` off the surfaced `result.error`, surfaces it to the
34
+ * reviewer, and later calls `ai.human.resume(...)`.
35
+ *
36
+ * Surfaced via `result.error` like every other `AIError` — the middleware
37
+ * never lets it escape `execute()`.
38
+ *
39
+ * @example
40
+ * if (result.error instanceof InterruptSuspendedError) {
41
+ * await notifyReviewer(result.error.interruptId);
42
+ * return { status: "awaiting-approval", interruptId: result.error.interruptId };
43
+ * }
44
+ */
45
+ declare class InterruptSuspendedError extends AIError {
46
+ /** Id of the persisted interrupt awaiting a human decision. */
47
+ readonly interruptId: string;
48
+ constructor(message: string, options: InterruptSuspendedErrorOptions);
49
+ }
50
+ /**
51
+ * Payload for {@link ApprovalRejectedError}. `reason` is the reviewer's
52
+ * explanation, surfaced to the model on the next trip so it can
53
+ * self-correct; `toolName` names the call that was rejected.
54
+ */
55
+ type ApprovalRejectedErrorOptions = AIErrorOptions & {
56
+ /** The reviewer's explanation for rejecting the call. */reason: string; /** Name of the tool whose call was rejected. */
57
+ toolName: string;
58
+ };
59
+ /**
60
+ * A human rejected a gated tool call.
61
+ *
62
+ * **Role.** The typed result of an `{ type: "reject", reason }` decision.
63
+ * The approval middleware throws it from `tool.before`; the agent
64
+ * dispatch records a failed tool call and writes a `role: "tool"`
65
+ * message carrying `reason`, so the **next trip lets the model
66
+ * self-correct** — exactly the existing tool-error feedback path.
67
+ *
68
+ * Surfaced via `result.error` like every other `AIError`.
69
+ *
70
+ * @example
71
+ * if (result.error instanceof ApprovalRejectedError) {
72
+ * logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);
73
+ * }
74
+ */
75
+ declare class ApprovalRejectedError extends AIError {
76
+ /** The reviewer's explanation for rejecting the call. */
77
+ readonly reason: string;
78
+ /** Name of the tool whose call was rejected. */
79
+ readonly toolName: string;
80
+ constructor(message: string, options: ApprovalRejectedErrorOptions);
81
+ }
82
+ //#endregion
83
+ export { ApprovalRejectedError, ApprovalRejectedErrorOptions, HumanErrorCode, InterruptSuspendedError, InterruptSuspendedErrorOptions };
84
+ //# sourceMappingURL=errors.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/errors.ts"],"mappings":";;;;;AAaA;;;;AAA0B;AAO1B;;;KAPY,cAAA;AASC;AAyBb;;;;AAzBa,KAFD,8BAAA,GAAiC,cAAc;EA6BzC,yDA3BhB,WAAW;AAAA;;;;AA6BgE;AAa7E;;;;;;;;AAIU;AAmBV;;;;;;;;;cAxCa,uBAAA,SAAgC,OAAO;EA+Cd;EAAA,SA7CpB,WAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,8BAAA;AAAA;;;;;;KAanC,4BAAA,GAA+B,cAAc;2DAEvD,MAAA;EAEA,QAAA;AAAA;;;;;;;;;;;;;;;;;cAmBW,qBAAA,SAA8B,OAAO;;WAEhC,MAAA;;WAGA,QAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,4BAAA;AAAA"}
@@ -0,0 +1,60 @@
1
+ import { AIError } from "../errors/ai-error.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/human/errors.ts
4
+ /**
5
+ * A durable approval handler suspended the run rather than denying the
6
+ * call.
7
+ *
8
+ * **Role.** The sentinel a durable {@link import("./contracts").ApprovalHandler}
9
+ * throws after persisting a
10
+ * {@link import("./contracts").PendingInterrupt}. The approval
11
+ * middleware recognizes its own sentinel (an `instanceof` check) and
12
+ * re-throws so the agent run unwinds; the dispatch records it as a failed
13
+ * tool call carrying this typed error. The caller reads
14
+ * `error.interruptId` off the surfaced `result.error`, surfaces it to the
15
+ * reviewer, and later calls `ai.human.resume(...)`.
16
+ *
17
+ * Surfaced via `result.error` like every other `AIError` — the middleware
18
+ * never lets it escape `execute()`.
19
+ *
20
+ * @example
21
+ * if (result.error instanceof InterruptSuspendedError) {
22
+ * await notifyReviewer(result.error.interruptId);
23
+ * return { status: "awaiting-approval", interruptId: result.error.interruptId };
24
+ * }
25
+ */
26
+ var InterruptSuspendedError = class extends AIError {
27
+ constructor(message, options) {
28
+ super("INTERRUPT_SUSPENDED", message, options);
29
+ this.name = "InterruptSuspendedError";
30
+ this.interruptId = options.interruptId;
31
+ }
32
+ };
33
+ /**
34
+ * A human rejected a gated tool call.
35
+ *
36
+ * **Role.** The typed result of an `{ type: "reject", reason }` decision.
37
+ * The approval middleware throws it from `tool.before`; the agent
38
+ * dispatch records a failed tool call and writes a `role: "tool"`
39
+ * message carrying `reason`, so the **next trip lets the model
40
+ * self-correct** — exactly the existing tool-error feedback path.
41
+ *
42
+ * Surfaced via `result.error` like every other `AIError`.
43
+ *
44
+ * @example
45
+ * if (result.error instanceof ApprovalRejectedError) {
46
+ * logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);
47
+ * }
48
+ */
49
+ var ApprovalRejectedError = class extends AIError {
50
+ constructor(message, options) {
51
+ super("APPROVAL_REJECTED", message, options);
52
+ this.name = "ApprovalRejectedError";
53
+ this.reason = options.reason;
54
+ this.toolName = options.toolName;
55
+ }
56
+ };
57
+
58
+ //#endregion
59
+ export { ApprovalRejectedError, InterruptSuspendedError };
60
+ //# sourceMappingURL=errors.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/errors.ts"],"sourcesContent":["import { AIError, type AIErrorOptions } from \"../errors/ai-error\";\nimport type { AIErrorCode } from \"../errors/error-code.type\";\n\n/**\n * Stable, machine-readable codes this package raises.\n *\n * `@warlock.js/ai`'s `AIErrorCode` is a closed union that (by design)\n * does not enumerate satellite-package codes, and this package must not\n * modify the core union. These codes are therefore declared locally and\n * narrowed into the base `AIError` `code` slot at the single `super(...)`\n * call — the runtime string is exactly what a consumer branches on via\n * `error.code`, identical to every other `AIError`.\n */\nexport type HumanErrorCode = \"INTERRUPT_SUSPENDED\" | \"APPROVAL_REJECTED\";\n\n/**\n * Payload for {@link InterruptSuspendedError}. `interruptId` is the key a\n * later `ai.human.resume(interruptId, decision)` call uses to replay the\n * decision against the persisted interrupt.\n */\nexport type InterruptSuspendedErrorOptions = AIErrorOptions & {\n /** Id of the persisted interrupt awaiting a decision. */\n interruptId: string;\n};\n\n/**\n * A durable approval handler suspended the run rather than denying the\n * call.\n *\n * **Role.** The sentinel a durable {@link import(\"./contracts\").ApprovalHandler}\n * throws after persisting a\n * {@link import(\"./contracts\").PendingInterrupt}. The approval\n * middleware recognizes its own sentinel (an `instanceof` check) and\n * re-throws so the agent run unwinds; the dispatch records it as a failed\n * tool call carrying this typed error. The caller reads\n * `error.interruptId` off the surfaced `result.error`, surfaces it to the\n * reviewer, and later calls `ai.human.resume(...)`.\n *\n * Surfaced via `result.error` like every other `AIError` — the middleware\n * never lets it escape `execute()`.\n *\n * @example\n * if (result.error instanceof InterruptSuspendedError) {\n * await notifyReviewer(result.error.interruptId);\n * return { status: \"awaiting-approval\", interruptId: result.error.interruptId };\n * }\n */\nexport class InterruptSuspendedError extends AIError {\n /** Id of the persisted interrupt awaiting a human decision. */\n public readonly interruptId: string;\n\n public constructor(message: string, options: InterruptSuspendedErrorOptions) {\n super(\"INTERRUPT_SUSPENDED\" as AIErrorCode, message, options);\n\n this.name = \"InterruptSuspendedError\";\n this.interruptId = options.interruptId;\n }\n}\n\n/**\n * Payload for {@link ApprovalRejectedError}. `reason` is the reviewer's\n * explanation, surfaced to the model on the next trip so it can\n * self-correct; `toolName` names the call that was rejected.\n */\nexport type ApprovalRejectedErrorOptions = AIErrorOptions & {\n /** The reviewer's explanation for rejecting the call. */\n reason: string;\n /** Name of the tool whose call was rejected. */\n toolName: string;\n};\n\n/**\n * A human rejected a gated tool call.\n *\n * **Role.** The typed result of an `{ type: \"reject\", reason }` decision.\n * The approval middleware throws it from `tool.before`; the agent\n * dispatch records a failed tool call and writes a `role: \"tool\"`\n * message carrying `reason`, so the **next trip lets the model\n * self-correct** — exactly the existing tool-error feedback path.\n *\n * Surfaced via `result.error` like every other `AIError`.\n *\n * @example\n * if (result.error instanceof ApprovalRejectedError) {\n * logAudit(`${result.error.toolName} rejected: ${result.error.reason}`);\n * }\n */\nexport class ApprovalRejectedError extends AIError {\n /** The reviewer's explanation for rejecting the call. */\n public readonly reason: string;\n\n /** Name of the tool whose call was rejected. */\n public readonly toolName: string;\n\n public constructor(message: string, options: ApprovalRejectedErrorOptions) {\n super(\"APPROVAL_REJECTED\" as AIErrorCode, message, options);\n\n this.name = \"ApprovalRejectedError\";\n this.reason = options.reason;\n this.toolName = options.toolName;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAa,0BAAb,cAA6C,QAAQ;CAInD,AAAO,YAAY,SAAiB,SAAyC;EAC3E,MAAM,uBAAsC,SAAS,OAAO;EAE5D,KAAK,OAAO;EACZ,KAAK,cAAc,QAAQ;CAC7B;AACF;;;;;;;;;;;;;;;;;AA8BA,IAAa,wBAAb,cAA2C,QAAQ;CAOjD,AAAO,YAAY,SAAiB,SAAuC;EACzE,MAAM,qBAAoC,SAAS,OAAO;EAE1D,KAAK,OAAO;EACZ,KAAK,SAAS,QAAQ;EACtB,KAAK,WAAW,QAAQ;CAC1B;AACF"}
@@ -0,0 +1,57 @@
1
+ import { AgentMiddleware } from "../contracts/middleware/middleware.contract.mjs";
2
+ import { HumanApprovalOptions } from "./contracts/human-approval.type.mjs";
3
+ //#region ../@warlock.js/ai/src/human/human-approval.d.ts
4
+ /**
5
+ * Human-in-the-loop approval gate for an agent's tool calls — the
6
+ * middleware behind `ai.human.approval(options)`.
7
+ *
8
+ * **Role.** Pauses *before a specific tool call* and routes it to a human
9
+ * who can **approve** (run the real tool unchanged), **reject** (the model
10
+ * sees a typed error and self-corrects), or **edit** (run the tool with
11
+ * reviewer-replaced args). The dangerous subset is chosen by an
12
+ * {@link import("./contracts").InterruptPolicy} (allowlist / denylist /
13
+ * predicate); every other call passes through untouched.
14
+ *
15
+ * **One hook.** Declares only `tool.before`. On each tool dispatch it:
16
+ * 1. evaluates the policy — not gated → returns `void`, the real tool runs;
17
+ * 2. for a gated call, builds an {@link ApprovalRequest} and calls the
18
+ * {@link import("./contracts").ApprovalHandler};
19
+ * 3. applies the returned {@link ApprovalDecision}:
20
+ * - `approve` → returns `void`, the real tool runs;
21
+ * - `reject` → short-circuits a failed `ToolInvokeResult` carrying an
22
+ * {@link ApprovalRejectedError} (the reviewer's `reason` reaches the
23
+ * model);
24
+ * - `edit` → rewrites `ctx.request.input` to the reviewer's args and
25
+ * returns `void`, so the real tool runs with the edited args (schema
26
+ * validation still applies — bad edits surface as a tool error).
27
+ *
28
+ * **Durable mode.** When a `store` is configured and the handler throws
29
+ * {@link InterruptSuspendedError} (after persisting the interrupt
30
+ * out-of-band), the middleware catches its **own** sentinel and
31
+ * short-circuits a failed result carrying it — so the caller reads
32
+ * `result.error.interruptId` and later calls
33
+ * `ai.human.resume(interruptId, decision)`. The middleware **never throws
34
+ * out of the pipeline**: every outcome (skip, approve, reject, edit,
35
+ * suspend) returns normally; only a *handler bug* (a non-sentinel throw)
36
+ * propagates, and even then the agent dispatch funnels it onto
37
+ * `result.error` — `execute()` still never throws.
38
+ *
39
+ * @param options - Policy, handler, optional durable store, optional name.
40
+ * @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.
41
+ *
42
+ * @example
43
+ * const support = ai.agent({
44
+ * model,
45
+ * tools: [refundCustomer],
46
+ * middleware: [
47
+ * humanApproval({
48
+ * policy: { type: "allowlist", tools: ["refundCustomer"], tags: () => ["money"] },
49
+ * handler: async (req) => ui.prompt(req), // { type: "edit", args: { amount: 5 } }
50
+ * }),
51
+ * ],
52
+ * });
53
+ */
54
+ declare function humanApproval(options: HumanApprovalOptions): AgentMiddleware;
55
+ //#endregion
56
+ export { humanApproval };
57
+ //# sourceMappingURL=human-approval.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"human-approval.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/human-approval.ts"],"mappings":";;;;;;AAyKA;;;;;;;;AAA6E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA7D,aAAA,CAAc,OAAA,EAAS,oBAAA,GAAuB,eAAe"}
@@ -0,0 +1,170 @@
1
+ import { generateRunId } from "../utils/generate-run-id.mjs";
2
+ import { ApprovalRejectedError, InterruptSuspendedError } from "./errors.mjs";
3
+ import { evaluatePolicy } from "./policy.mjs";
4
+ import { takeSeededDecision } from "./resume-seed.mjs";
5
+
6
+ //#region ../@warlock.js/ai/src/human/human-approval.ts
7
+ /** Default middleware name when {@link HumanApprovalOptions.name} is omitted. */
8
+ const DEFAULT_NAME = "human-approval";
9
+ /** Zero usage for a synthetic, no-LLM-spend short-circuit result. */
10
+ const ZERO_USAGE = Object.freeze({
11
+ input: 0,
12
+ output: 0,
13
+ total: 0
14
+ });
15
+ /**
16
+ * Derive the read-only {@link PolicyContext} the policy + request are
17
+ * built from out of the wrapping {@link MiddlewareToolContext}.
18
+ */
19
+ function toPolicyContext(ctx) {
20
+ return {
21
+ toolName: ctx.tool.name,
22
+ toolDescription: ctx.tool.description,
23
+ args: ctx.request.input,
24
+ agentName: ctx.agent.name,
25
+ tripIndex: ctx.tripIndex,
26
+ sessionId: ctx.options?.sessionId
27
+ };
28
+ }
29
+ /**
30
+ * Generate a stable, unique id for a pending interrupt. Shaped
31
+ * `${agentName}.${sessionId ?? "nosession"}.${tripIndex}.${random}` so a
32
+ * reviewer can eyeball the originating run, while the trailing random
33
+ * segment guarantees per-call uniqueness even within one trip.
34
+ */
35
+ function makeInterruptId(ctx) {
36
+ const session = ctx.options?.sessionId ?? "nosession";
37
+ const random = generateRunId("interrupt");
38
+ return `${ctx.agent.name}.${session}.${ctx.tripIndex}.${random}`;
39
+ }
40
+ /**
41
+ * Build the {@link ApprovalRequest} a human rules on, from the tool
42
+ * context and the policy-derived tags.
43
+ */
44
+ function buildRequest(ctx, interruptId, tags) {
45
+ return {
46
+ interruptId,
47
+ toolName: ctx.tool.name,
48
+ toolDescription: ctx.tool.description,
49
+ args: ctx.request.input,
50
+ context: {
51
+ agentName: ctx.agent.name,
52
+ tripIndex: ctx.tripIndex,
53
+ sessionId: ctx.options?.sessionId,
54
+ originalInput: ctx.input,
55
+ ...tags ? { tags } : {}
56
+ },
57
+ requestedAt: (/* @__PURE__ */ new Date()).toISOString()
58
+ };
59
+ }
60
+ /**
61
+ * Synthesize a failed {@link ToolInvokeResult} carrying a typed error.
62
+ *
63
+ * The approval middleware returns this from `tool.before` to
64
+ * **short-circuit** the real tool without throwing: the pipeline treats a
65
+ * defined return as the tool's result, the agent records a failed
66
+ * `ToolCall`, and the model sees `{ error }` on the next trip — exactly
67
+ * the existing tool-error feedback path. Used for both `reject`
68
+ * (`ApprovalRejectedError`) and durable suspend (`InterruptSuspendedError`).
69
+ */
70
+ function failedResult(error, toolName) {
71
+ const runId = generateRunId("tool");
72
+ const nowIso = (/* @__PURE__ */ new Date()).toISOString();
73
+ return {
74
+ error,
75
+ usage: ZERO_USAGE,
76
+ report: {
77
+ runId,
78
+ rootRunId: runId,
79
+ name: toolName,
80
+ type: "tool",
81
+ status: "failed",
82
+ startedAt: nowIso,
83
+ endedAt: nowIso,
84
+ duration: 0,
85
+ usage: ZERO_USAGE,
86
+ children: []
87
+ }
88
+ };
89
+ }
90
+ /**
91
+ * Human-in-the-loop approval gate for an agent's tool calls — the
92
+ * middleware behind `ai.human.approval(options)`.
93
+ *
94
+ * **Role.** Pauses *before a specific tool call* and routes it to a human
95
+ * who can **approve** (run the real tool unchanged), **reject** (the model
96
+ * sees a typed error and self-corrects), or **edit** (run the tool with
97
+ * reviewer-replaced args). The dangerous subset is chosen by an
98
+ * {@link import("./contracts").InterruptPolicy} (allowlist / denylist /
99
+ * predicate); every other call passes through untouched.
100
+ *
101
+ * **One hook.** Declares only `tool.before`. On each tool dispatch it:
102
+ * 1. evaluates the policy — not gated → returns `void`, the real tool runs;
103
+ * 2. for a gated call, builds an {@link ApprovalRequest} and calls the
104
+ * {@link import("./contracts").ApprovalHandler};
105
+ * 3. applies the returned {@link ApprovalDecision}:
106
+ * - `approve` → returns `void`, the real tool runs;
107
+ * - `reject` → short-circuits a failed `ToolInvokeResult` carrying an
108
+ * {@link ApprovalRejectedError} (the reviewer's `reason` reaches the
109
+ * model);
110
+ * - `edit` → rewrites `ctx.request.input` to the reviewer's args and
111
+ * returns `void`, so the real tool runs with the edited args (schema
112
+ * validation still applies — bad edits surface as a tool error).
113
+ *
114
+ * **Durable mode.** When a `store` is configured and the handler throws
115
+ * {@link InterruptSuspendedError} (after persisting the interrupt
116
+ * out-of-band), the middleware catches its **own** sentinel and
117
+ * short-circuits a failed result carrying it — so the caller reads
118
+ * `result.error.interruptId` and later calls
119
+ * `ai.human.resume(interruptId, decision)`. The middleware **never throws
120
+ * out of the pipeline**: every outcome (skip, approve, reject, edit,
121
+ * suspend) returns normally; only a *handler bug* (a non-sentinel throw)
122
+ * propagates, and even then the agent dispatch funnels it onto
123
+ * `result.error` — `execute()` still never throws.
124
+ *
125
+ * @param options - Policy, handler, optional durable store, optional name.
126
+ * @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.
127
+ *
128
+ * @example
129
+ * const support = ai.agent({
130
+ * model,
131
+ * tools: [refundCustomer],
132
+ * middleware: [
133
+ * humanApproval({
134
+ * policy: { type: "allowlist", tools: ["refundCustomer"], tags: () => ["money"] },
135
+ * handler: async (req) => ui.prompt(req), // { type: "edit", args: { amount: 5 } }
136
+ * }),
137
+ * ],
138
+ * });
139
+ */
140
+ function humanApproval(options) {
141
+ const name = options.name ?? DEFAULT_NAME;
142
+ const { policy, handler } = options;
143
+ return {
144
+ name,
145
+ tool: { async before(ctx) {
146
+ const verdict = evaluatePolicy(policy, toPolicyContext(ctx));
147
+ if (!verdict.requiresApproval) return;
148
+ const request = buildRequest(ctx, makeInterruptId(ctx), verdict.tags);
149
+ const seeded = takeSeededDecision(ctx.agent.name);
150
+ let decision;
151
+ if (seeded !== void 0) decision = seeded;
152
+ else try {
153
+ decision = await handler(request);
154
+ } catch (thrown) {
155
+ if (thrown instanceof InterruptSuspendedError) return failedResult(thrown, ctx.tool.name);
156
+ throw thrown;
157
+ }
158
+ if (decision.type === "approve") return;
159
+ if (decision.type === "reject") return failedResult(new ApprovalRejectedError(`Tool call "${ctx.tool.name}" rejected by reviewer — ${decision.reason}`, {
160
+ reason: decision.reason,
161
+ toolName: ctx.tool.name
162
+ }), ctx.tool.name);
163
+ ctx.request.input = decision.args;
164
+ } }
165
+ };
166
+ }
167
+
168
+ //#endregion
169
+ export { humanApproval };
170
+ //# sourceMappingURL=human-approval.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"human-approval.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/human/human-approval.ts"],"sourcesContent":["import type { AgentMiddleware } from \"../contracts/middleware/middleware.contract\";\nimport type { MiddlewareToolContext } from \"../contracts/middleware/middleware-context.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport type { AIError } from \"../errors/ai-error\";\nimport type { ToolInvokeResult } from \"../tool/tool\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport type {\n ApprovalDecision,\n ApprovalRequest,\n HumanApprovalOptions,\n PolicyContext,\n} from \"./contracts\";\nimport { ApprovalRejectedError, InterruptSuspendedError } from \"./errors\";\nimport { evaluatePolicy } from \"./policy\";\nimport { takeSeededDecision } from \"./resume-seed\";\n\n/** Default middleware name when {@link HumanApprovalOptions.name} is omitted. */\nconst DEFAULT_NAME = \"human-approval\";\n\n/** Zero usage for a synthetic, no-LLM-spend short-circuit result. */\nconst ZERO_USAGE: Usage = Object.freeze({ input: 0, output: 0, total: 0 });\n\n/**\n * Mutable view of {@link MiddlewareToolContext.request} used only to\n * apply an `edit` decision. The context types `request.input` as\n * `readonly`, but the agent dispatch reads `request.input` (the SAME\n * object) when it invokes the real tool *after* the `tool.before`\n * pipeline returns — so reassigning it here is how an edited-args\n * decision reaches the tool. This narrow local type makes that one\n * deliberate write explicit instead of casting away the whole context.\n */\ninterface MutableToolRequest {\n input: unknown;\n}\n\n/**\n * Derive the read-only {@link PolicyContext} the policy + request are\n * built from out of the wrapping {@link MiddlewareToolContext}.\n */\nfunction toPolicyContext(ctx: MiddlewareToolContext): PolicyContext {\n return {\n toolName: ctx.tool.name,\n toolDescription: ctx.tool.description,\n args: ctx.request.input,\n agentName: ctx.agent.name,\n tripIndex: ctx.tripIndex,\n sessionId: ctx.options?.sessionId,\n };\n}\n\n/**\n * Generate a stable, unique id for a pending interrupt. Shaped\n * `${agentName}.${sessionId ?? \"nosession\"}.${tripIndex}.${random}` so a\n * reviewer can eyeball the originating run, while the trailing random\n * segment guarantees per-call uniqueness even within one trip.\n */\nfunction makeInterruptId(ctx: MiddlewareToolContext): string {\n const session = ctx.options?.sessionId ?? \"nosession\";\n const random = generateRunId(\"interrupt\");\n\n return `${ctx.agent.name}.${session}.${ctx.tripIndex}.${random}`;\n}\n\n/**\n * Build the {@link ApprovalRequest} a human rules on, from the tool\n * context and the policy-derived tags.\n */\nfunction buildRequest(\n ctx: MiddlewareToolContext,\n interruptId: string,\n tags: string[] | undefined,\n): ApprovalRequest {\n return {\n interruptId,\n toolName: ctx.tool.name,\n toolDescription: ctx.tool.description,\n args: ctx.request.input,\n context: {\n agentName: ctx.agent.name,\n tripIndex: ctx.tripIndex,\n sessionId: ctx.options?.sessionId,\n originalInput: ctx.input,\n ...(tags ? { tags } : {}),\n },\n requestedAt: new Date().toISOString(),\n };\n}\n\n/**\n * Synthesize a failed {@link ToolInvokeResult} carrying a typed error.\n *\n * The approval middleware returns this from `tool.before` to\n * **short-circuit** the real tool without throwing: the pipeline treats a\n * defined return as the tool's result, the agent records a failed\n * `ToolCall`, and the model sees `{ error }` on the next trip — exactly\n * the existing tool-error feedback path. Used for both `reject`\n * (`ApprovalRejectedError`) and durable suspend (`InterruptSuspendedError`).\n */\nfunction failedResult(error: AIError, toolName: string): ToolInvokeResult<unknown> {\n const runId = generateRunId(\"tool\");\n const nowIso = new Date().toISOString();\n\n const report: BaseReport = {\n runId,\n rootRunId: runId,\n name: toolName,\n type: \"tool\",\n status: \"failed\",\n startedAt: nowIso,\n endedAt: nowIso,\n duration: 0,\n usage: ZERO_USAGE,\n children: [],\n };\n\n return { error, usage: ZERO_USAGE, report };\n}\n\n/**\n * Human-in-the-loop approval gate for an agent's tool calls — the\n * middleware behind `ai.human.approval(options)`.\n *\n * **Role.** Pauses *before a specific tool call* and routes it to a human\n * who can **approve** (run the real tool unchanged), **reject** (the model\n * sees a typed error and self-corrects), or **edit** (run the tool with\n * reviewer-replaced args). The dangerous subset is chosen by an\n * {@link import(\"./contracts\").InterruptPolicy} (allowlist / denylist /\n * predicate); every other call passes through untouched.\n *\n * **One hook.** Declares only `tool.before`. On each tool dispatch it:\n * 1. evaluates the policy — not gated → returns `void`, the real tool runs;\n * 2. for a gated call, builds an {@link ApprovalRequest} and calls the\n * {@link import(\"./contracts\").ApprovalHandler};\n * 3. applies the returned {@link ApprovalDecision}:\n * - `approve` → returns `void`, the real tool runs;\n * - `reject` → short-circuits a failed `ToolInvokeResult` carrying an\n * {@link ApprovalRejectedError} (the reviewer's `reason` reaches the\n * model);\n * - `edit` → rewrites `ctx.request.input` to the reviewer's args and\n * returns `void`, so the real tool runs with the edited args (schema\n * validation still applies — bad edits surface as a tool error).\n *\n * **Durable mode.** When a `store` is configured and the handler throws\n * {@link InterruptSuspendedError} (after persisting the interrupt\n * out-of-band), the middleware catches its **own** sentinel and\n * short-circuits a failed result carrying it — so the caller reads\n * `result.error.interruptId` and later calls\n * `ai.human.resume(interruptId, decision)`. The middleware **never throws\n * out of the pipeline**: every outcome (skip, approve, reject, edit,\n * suspend) returns normally; only a *handler bug* (a non-sentinel throw)\n * propagates, and even then the agent dispatch funnels it onto\n * `result.error` — `execute()` still never throws.\n *\n * @param options - Policy, handler, optional durable store, optional name.\n * @returns An {@link AgentMiddleware} declaring a single `tool.before` hook.\n *\n * @example\n * const support = ai.agent({\n * model,\n * tools: [refundCustomer],\n * middleware: [\n * humanApproval({\n * policy: { type: \"allowlist\", tools: [\"refundCustomer\"], tags: () => [\"money\"] },\n * handler: async (req) => ui.prompt(req), // { type: \"edit\", args: { amount: 5 } }\n * }),\n * ],\n * });\n */\nexport function humanApproval(options: HumanApprovalOptions): AgentMiddleware {\n const name = options.name ?? DEFAULT_NAME;\n const { policy, handler } = options;\n\n return {\n name,\n tool: {\n async before(\n ctx: MiddlewareToolContext,\n ): Promise<ToolInvokeResult<unknown> | void> {\n const verdict = evaluatePolicy(policy, toPolicyContext(ctx));\n\n // Not gated — let the real tool run unchanged.\n if (!verdict.requiresApproval) {\n return;\n }\n\n const interruptId = makeInterruptId(ctx);\n const request = buildRequest(ctx, interruptId, verdict.tags);\n\n // Durable resume: `ai.human.resume(...)` re-runs this same agent\n // with the human's decision pre-seeded (keyed by agent name). On a\n // hit we replay the seeded decision exactly once and skip the\n // author's handler entirely — the gated call resolves to the\n // ruling instead of pausing again.\n const seeded = takeSeededDecision(ctx.agent.name);\n\n let decision: ApprovalDecision;\n\n if (seeded !== undefined) {\n decision = seeded;\n } else {\n try {\n decision = await handler(request);\n } catch (thrown) {\n // A durable handler signals suspension by throwing our OWN\n // sentinel after persisting the interrupt. Recognize it and\n // short-circuit a failed result carrying it — the caller reads\n // `error.interruptId` and resumes later. Any OTHER throw is a\n // handler bug; re-throw so the agent dispatch funnels it onto\n // `result.error` (we never swallow a bug into silent approval).\n if (thrown instanceof InterruptSuspendedError) {\n return failedResult(thrown, ctx.tool.name);\n }\n\n throw thrown;\n }\n }\n\n if (decision.type === \"approve\") {\n // Run the real tool with the model's original args.\n return;\n }\n\n if (decision.type === \"reject\") {\n const error = new ApprovalRejectedError(\n `Tool call \"${ctx.tool.name}\" rejected by reviewer — ${decision.reason}`,\n { reason: decision.reason, toolName: ctx.tool.name },\n );\n\n return failedResult(error, ctx.tool.name);\n }\n\n // `edit` — rewrite the pending args, then let the real tool run.\n // The agent dispatch reads `request.input` (this same object) when\n // it invokes the tool after this hook returns, so the reassignment\n // takes effect. Bad edits still fail the tool's own schema check.\n (ctx.request as unknown as MutableToolRequest).input = decision.args;\n\n return;\n },\n },\n };\n}\n"],"mappings":";;;;;;;AAkBA,MAAM,eAAe;;AAGrB,MAAM,aAAoB,OAAO,OAAO;CAAE,OAAO;CAAG,QAAQ;CAAG,OAAO;AAAE,CAAC;;;;;AAmBzE,SAAS,gBAAgB,KAA2C;CAClE,OAAO;EACL,UAAU,IAAI,KAAK;EACnB,iBAAiB,IAAI,KAAK;EAC1B,MAAM,IAAI,QAAQ;EAClB,WAAW,IAAI,MAAM;EACrB,WAAW,IAAI;EACf,WAAW,IAAI,SAAS;CAC1B;AACF;;;;;;;AAQA,SAAS,gBAAgB,KAAoC;CAC3D,MAAM,UAAU,IAAI,SAAS,aAAa;CAC1C,MAAM,SAAS,cAAc,WAAW;CAExC,OAAO,GAAG,IAAI,MAAM,KAAK,GAAG,QAAQ,GAAG,IAAI,UAAU,GAAG;AAC1D;;;;;AAMA,SAAS,aACP,KACA,aACA,MACiB;CACjB,OAAO;EACL;EACA,UAAU,IAAI,KAAK;EACnB,iBAAiB,IAAI,KAAK;EAC1B,MAAM,IAAI,QAAQ;EAClB,SAAS;GACP,WAAW,IAAI,MAAM;GACrB,WAAW,IAAI;GACf,WAAW,IAAI,SAAS;GACxB,eAAe,IAAI;GACnB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EACzB;EACA,8BAAa,IAAI,KAAK,EAAC,CAAC,YAAY;CACtC;AACF;;;;;;;;;;;AAYA,SAAS,aAAa,OAAgB,UAA6C;CACjF,MAAM,QAAQ,cAAc,MAAM;CAClC,MAAM,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;CAetC,OAAO;EAAE;EAAO,OAAO;EAAY;GAZjC;GACA,WAAW;GACX,MAAM;GACN,MAAM;GACN,QAAQ;GACR,WAAW;GACX,SAAS;GACT,UAAU;GACV,OAAO;GACP,UAAU,CAAC;EAG2B;CAAE;AAC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,SAAgB,cAAc,SAAgD;CAC5E,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,EAAE,QAAQ,YAAY;CAE5B,OAAO;EACL;EACA,MAAM,EACJ,MAAM,OACJ,KAC2C;GAC3C,MAAM,UAAU,eAAe,QAAQ,gBAAgB,GAAG,CAAC;GAG3D,IAAI,CAAC,QAAQ,kBACX;GAIF,MAAM,UAAU,aAAa,KADT,gBAAgB,GACQ,GAAG,QAAQ,IAAI;GAO3D,MAAM,SAAS,mBAAmB,IAAI,MAAM,IAAI;GAEhD,IAAI;GAEJ,IAAI,WAAW,QACb,WAAW;QAEX,IAAI;IACF,WAAW,MAAM,QAAQ,OAAO;GAClC,SAAS,QAAQ;IAOf,IAAI,kBAAkB,yBACpB,OAAO,aAAa,QAAQ,IAAI,KAAK,IAAI;IAG3C,MAAM;GACR;GAGF,IAAI,SAAS,SAAS,WAEpB;GAGF,IAAI,SAAS,SAAS,UAMpB,OAAO,aAAa,IALF,sBAChB,cAAc,IAAI,KAAK,KAAK,2BAA2B,SAAS,UAChE;IAAE,QAAQ,SAAS;IAAQ,UAAU,IAAI,KAAK;GAAK,CAG7B,GAAG,IAAI,KAAK,IAAI;GAO1C,AAAC,IAAI,QAA0C,QAAQ,SAAS;EAGlE,EACF;CACF;AACF"}