@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,89 @@
1
+ import { OutboundPolicy } from "../../security/outbound-policy.type.mjs";
2
+ import { RagDocument } from "../contracts/rag-document.type.mjs";
3
+
4
+ //#region ../@warlock.js/ai/src/rag/loaders/loader.type.d.ts
5
+ /**
6
+ * The shape every loader emits — the **exact** {@link RagDocument} (or array
7
+ * of them) that `ai.rag(config).index()` consumes, so a load result is fed
8
+ * straight in with no adapter:
9
+ *
10
+ * @example
11
+ * const kb = ai.rag({ embedder, store });
12
+ * await kb.index(await ai.rag.loadWeb("https://example.com/guide"));
13
+ *
14
+ * A loader may emit one document (the common case for a single file / page)
15
+ * or several (e.g. one document per PDF page), so the result is uniformly an
16
+ * **array** — `index()` accepts an array, so callers never branch on arity.
17
+ */
18
+ type RagLoaderResult = RagDocument[];
19
+ /**
20
+ * Metadata keys loaders attach to every {@link RagDocument} they emit, on
21
+ * top of any caller-supplied `metadata`. Each is optional and only present
22
+ * when the loader could determine it. These keys round-trip through
23
+ * chunking onto the final citation, so a retrieved chunk can be traced back
24
+ * to its `source` URL / `title` / `page`.
25
+ */
26
+ type RagLoaderMetadata = {
27
+ /**
28
+ * Where the document came from — a URL (web loader), a logical name, or
29
+ * the caller-supplied `id`. Always a string when present.
30
+ */
31
+ source?: string; /** Human-readable title, e.g. an HTML `<title>` or PDF document title. */
32
+ title?: string; /** Discriminator for the loader that produced the document. */
33
+ loader?: RagLoaderType; /** 1-based page number — set by {@link loadPdf} on per-page documents. */
34
+ page?: number; /** Total page count of the source — set by {@link loadPdf}. */
35
+ pageCount?: number; /** MIME content-type reported by the server — set by the web loader. */
36
+ contentType?: string;
37
+ };
38
+ /** Discriminator identifying which loader produced a {@link RagDocument}. */
39
+ type RagLoaderType = "text" | "html" | "web" | "pdf";
40
+ /**
41
+ * Shared options every loader accepts. The `id` and `metadata` flow onto
42
+ * the emitted {@link RagDocument} verbatim (loader-derived metadata is
43
+ * merged UNDER the caller's, so an explicit `metadata.title` always wins),
44
+ * and `tags` propagate to every chunk for `retrieve({ tags })` filtering.
45
+ */
46
+ type RagLoaderOptions = {
47
+ /**
48
+ * Stable source id for the emitted document(s). Falls back to a
49
+ * loader-specific default (the URL for the web loader, `"document"`
50
+ * otherwise). Multi-document loaders suffix this (e.g. `"<id>#p3"`).
51
+ */
52
+ id?: string;
53
+ /**
54
+ * Extra metadata merged onto every emitted document. Caller keys take
55
+ * precedence over the loader's derived keys (`source`, `title`, …).
56
+ */
57
+ metadata?: Record<string, unknown>; /** Tags applied to every chunk written from the emitted document(s). */
58
+ tags?: string[];
59
+ };
60
+ /** Options for the HTML loader — {@link RagLoaderOptions} only. */
61
+ type LoadHtmlOptions = RagLoaderOptions;
62
+ /** Options for the plain-text loader — {@link RagLoaderOptions} only. */
63
+ type LoadTextOptions = RagLoaderOptions;
64
+ /** Options for the PDF loader. */
65
+ type LoadPdfOptions = RagLoaderOptions & {
66
+ /**
67
+ * Emit one {@link RagDocument} per page (each tagged with `page` /
68
+ * `pageCount` metadata) instead of a single concatenated document.
69
+ * Per-page documents keep citations page-precise. Default `false`.
70
+ */
71
+ perPage?: boolean;
72
+ };
73
+ /**
74
+ * Options for the web loader. Extends {@link RagLoaderOptions} with an
75
+ * {@link OutboundPolicy} — the SSRF-safe fetch policy the loader hands to
76
+ * `guardedFetch`. Omit it and the strict defaults apply (https-only,
77
+ * private-IP deny on, 10s timeout, 5 MiB cap).
78
+ */
79
+ type LoadWebOptions = RagLoaderOptions & {
80
+ /**
81
+ * The {@link OutboundPolicy} governing the fetch. The web loader NEVER
82
+ * issues a raw `fetch` — every request goes through the policy's
83
+ * `guardedFetch`, so an SSRF / oversized-body guard always applies.
84
+ */
85
+ policy?: OutboundPolicy;
86
+ };
87
+ //#endregion
88
+ export { LoadHtmlOptions, LoadPdfOptions, LoadTextOptions, LoadWebOptions, RagLoaderMetadata, RagLoaderOptions, RagLoaderResult, RagLoaderType };
89
+ //# sourceMappingURL=loader.type.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.type.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/loaders/loader.type.ts"],"mappings":";;;;;;AAgBA;;;;AAAyC;AASzC;;;;;;KATY,eAAA,GAAkB,WAAW;;;;;;AAwB5B;AAIb;KAnBY,iBAAA;;;AAmBa;AAQzB;EAtBE,MAAA;EAEA,KAAA,WA0BA;EAxBA,MAAA,GAAS,aAAa,EA6BX;EA3BX,IAAA,WA6BI;EA3BJ,SAAA,WA+BU;EA7BV,WAAA;AAAA;;KAIU,aAAA;AA4BZ;;;;AAA8C;AAG9C;AAHA,KApBY,gBAAA;;;AA6BH;AAST;;EAhCE,EAAA;EAsCuB;;;;EAjCvB,QAAA,GAAW,MAAM,mBAiCM;EA/BvB,IAAA;AAAA;;KAIU,eAAA,GAAkB,gBAAgB;;KAGlC,eAAA,GAAkB,gBAAgB;;KAGlC,cAAA,GAAiB,gBAAgB;;;;;;EAM3C,OAAO;AAAA;;;;;;;KASG,cAAA,GAAiB,gBAAA;;;;;;EAM3B,MAAA,GAAS,cAAc;AAAA"}
@@ -0,0 +1,38 @@
1
+ import { Rag, RagConfig } from "./contracts/rag-config.type.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/rag/rag.d.ts
4
+ /**
5
+ * Create a RAG pipeline: **chunk → embed → vector store → retrieve →
6
+ * rerank → cite**, reusing the app's `ai.embedder` for embedding, a
7
+ * `@warlock.js/cache` `CacheDriver` as the vector store, and the
8
+ * composite-as-tool engine to expose retrieval as a tool.
9
+ *
10
+ * Resolution is loud at construction (mirroring `memory()`):
11
+ * - `embedder` is required — a provider with no embedder must be caught
12
+ * here, not at first index.
13
+ * - `store` falls back to `ai.config({ defaultStore })`; if neither
14
+ * resolves, construction throws.
15
+ *
16
+ * `retrieve()` is return-only — it never auto-injects into a prompt; the
17
+ * caller formats the cited chunks (or uses `asTool()` for the agent loop).
18
+ * The reranker is OFF by default (cosine-only) unless `config.reranker`
19
+ * is set.
20
+ *
21
+ * @example
22
+ * import { ai } from "@warlock.js/ai";
23
+ * import { MemoryCacheDriver } from "@warlock.js/cache";
24
+ *
25
+ * const kb = ai.rag({
26
+ * name: "docs",
27
+ * embedder: openai.embedder({ name: "text-embedding-3-small" }),
28
+ * store: new MemoryCacheDriver(),
29
+ * chunk: { type: "markdown", size: 800, overlap: 120 },
30
+ * });
31
+ *
32
+ * await kb.index([{ id: "guide", text: longMarkdown, metadata: { url: "/guide" } }]);
33
+ * const { chunks } = await kb.retrieve("how do I configure caching?", { topK: 4 });
34
+ */
35
+ declare function rag(config: RagConfig): Rag;
36
+ //#endregion
37
+ export { rag };
38
+ //# sourceMappingURL=rag.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/rag/rag.ts"],"mappings":";;;;;AAyDA;;;;;;;;AAA2C;;;;;;;;;;;;;;;;;;;;;iBAA3B,GAAA,CAAI,MAAA,EAAQ,SAAA,GAAY,GAAG"}
@@ -0,0 +1,126 @@
1
+ import { resolveDefaultStore } from "../config.mjs";
2
+ import { chunk } from "./chunk/chunk.mjs";
3
+ import { ragAsTool } from "./as-tool.mjs";
4
+ import { retrieve } from "./retrieve.mjs";
5
+ import { cacheVectorStore } from "./store/cache-vector-store.mjs";
6
+
7
+ //#region ../@warlock.js/ai/src/rag/rag.ts
8
+ const DEFAULT_NAME = "rag";
9
+ const DEFAULT_NAMESPACE_PREFIX = "ai.rag";
10
+ /**
11
+ * Max chunk texts embedded per `embedder.embedMany()` call. One call is
12
+ * one provider request, so a giant document is sub-batched to stay under
13
+ * the provider's per-request token cap (the design's "chunk larger than
14
+ * provider per-request cap" guard).
15
+ */
16
+ const DEFAULT_MAX_BATCH = 96;
17
+ /**
18
+ * Create a RAG pipeline: **chunk → embed → vector store → retrieve →
19
+ * rerank → cite**, reusing the app's `ai.embedder` for embedding, a
20
+ * `@warlock.js/cache` `CacheDriver` as the vector store, and the
21
+ * composite-as-tool engine to expose retrieval as a tool.
22
+ *
23
+ * Resolution is loud at construction (mirroring `memory()`):
24
+ * - `embedder` is required — a provider with no embedder must be caught
25
+ * here, not at first index.
26
+ * - `store` falls back to `ai.config({ defaultStore })`; if neither
27
+ * resolves, construction throws.
28
+ *
29
+ * `retrieve()` is return-only — it never auto-injects into a prompt; the
30
+ * caller formats the cited chunks (or uses `asTool()` for the agent loop).
31
+ * The reranker is OFF by default (cosine-only) unless `config.reranker`
32
+ * is set.
33
+ *
34
+ * @example
35
+ * import { ai } from "@warlock.js/ai";
36
+ * import { MemoryCacheDriver } from "@warlock.js/cache";
37
+ *
38
+ * const kb = ai.rag({
39
+ * name: "docs",
40
+ * embedder: openai.embedder({ name: "text-embedding-3-small" }),
41
+ * store: new MemoryCacheDriver(),
42
+ * chunk: { type: "markdown", size: 800, overlap: 120 },
43
+ * });
44
+ *
45
+ * await kb.index([{ id: "guide", text: longMarkdown, metadata: { url: "/guide" } }]);
46
+ * const { chunks } = await kb.retrieve("how do I configure caching?", { topK: 4 });
47
+ */
48
+ function rag(config) {
49
+ const name = config.name ?? DEFAULT_NAME;
50
+ if (!config.embedder) throw new Error(`rag("${name}"): an \`embedder\` is required — pass one from a provider that supports embeddings (e.g. openai.embedder({ name: "text-embedding-3-small" }))`);
51
+ const driver = config.store ?? resolveDefaultStore();
52
+ if (!driver) throw new Error(`rag("${name}"): no store — pass \`store\` (a vector-capable @warlock.js/cache CacheDriver) or call \`ai.config({ defaultStore })\` at app boot before constructing the rag`);
53
+ const store = cacheVectorStore(driver);
54
+ const namespace = config.namespace ?? `${DEFAULT_NAMESPACE_PREFIX}.${name}`;
55
+ const embedder = config.embedder;
56
+ let indexedDimensions;
57
+ const instance = {
58
+ name,
59
+ async index(docs, chunkOverride) {
60
+ const chunkOptions = chunkOverride ?? config.chunk;
61
+ const limits = config.limits;
62
+ if (limits?.maxDocuments !== void 0 && docs.length > limits.maxDocuments) throw new Error(`rag("${name}"): index() received ${docs.length} documents, exceeding the configured maxDocuments of ${limits.maxDocuments}`);
63
+ if (limits?.maxBytes !== void 0) {
64
+ const totalBytes = docs.reduce((sum, doc) => sum + Buffer.byteLength(doc.text ?? ""), 0);
65
+ if (totalBytes > limits.maxBytes) throw new Error(`rag("${name}"): index() received ${totalBytes} bytes of document text, exceeding the configured maxBytes of ${limits.maxBytes}`);
66
+ }
67
+ const records = [];
68
+ for (const doc of docs) {
69
+ const pieces = chunk(doc.text, chunkOptions);
70
+ for (const piece of pieces) {
71
+ const value = {
72
+ sourceId: doc.id,
73
+ chunkIndex: piece.index,
74
+ span: piece.span,
75
+ text: piece.text,
76
+ metadata: doc.metadata
77
+ };
78
+ records.push({
79
+ key: keyFor(namespace, doc.id, piece.index),
80
+ value,
81
+ text: piece.text,
82
+ tags: doc.tags
83
+ });
84
+ }
85
+ }
86
+ if (records.length === 0) return { chunks: 0 };
87
+ if (limits?.maxChunks !== void 0 && records.length > limits.maxChunks) throw new Error(`rag("${name}"): index() produced ${records.length} chunks, exceeding the configured maxChunks of ${limits.maxChunks}`);
88
+ for (let offset = 0; offset < records.length; offset += DEFAULT_MAX_BATCH) {
89
+ const batch = records.slice(offset, offset + DEFAULT_MAX_BATCH);
90
+ const { vectors, dimensions } = await embedder.embedMany(batch.map((record) => record.text));
91
+ if (indexedDimensions === void 0 && dimensions !== 0) indexedDimensions = dimensions;
92
+ await Promise.all(batch.map((record, position) => store.upsert(record.key, record.value, vectors[position], record.tags)));
93
+ }
94
+ return { chunks: records.length };
95
+ },
96
+ async retrieve(query, options) {
97
+ return retrieve(query, {
98
+ embedder,
99
+ store,
100
+ namespace,
101
+ reranker: config.reranker,
102
+ defaults: config.retrieve,
103
+ indexedDimensions
104
+ }, options);
105
+ },
106
+ async clear() {
107
+ await store.removeNamespace(namespace);
108
+ },
109
+ asTool(options) {
110
+ return ragAsTool(name, (query, retrieveOptions) => instance.retrieve(query, retrieveOptions), options);
111
+ }
112
+ };
113
+ return instance;
114
+ }
115
+ /**
116
+ * Namespaced key for a stored chunk. Uses the `.` separator (matching
117
+ * `SemanticMemory.keyFor`) so namespace-prefix filtering on the returned
118
+ * `hit.key` stays aligned with the cache's `parseKey` normalization.
119
+ */
120
+ function keyFor(namespace, sourceId, chunkIndex) {
121
+ return `${namespace}.${sourceId}.${chunkIndex}`;
122
+ }
123
+
124
+ //#endregion
125
+ export { rag };
126
+ //# sourceMappingURL=rag.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rag.mjs","names":["chunkText","runRetrieve"],"sources":["../../../../../../../@warlock.js/ai/src/rag/rag.ts"],"sourcesContent":["import { resolveDefaultStore } from \"../config\";\nimport { chunk as chunkText } from \"./chunk/chunk\";\nimport type { ChunkOptions } from \"./contracts/chunk-options.type\";\nimport type { RetrieveOptions, RetrieveResult } from \"./contracts/citation.type\";\nimport type {\n Rag,\n RagAsToolOptions,\n RagConfig,\n} from \"./contracts/rag-config.type\";\nimport type { RagDocument } from \"./contracts/rag-document.type\";\nimport { ragAsTool } from \"./as-tool\";\nimport { retrieve as runRetrieve, type StoredChunk } from \"./retrieve\";\nimport { cacheVectorStore } from \"./store/cache-vector-store\";\nimport type { VectorStore } from \"./store/vector-store.contract\";\n\nconst DEFAULT_NAME = \"rag\";\nconst DEFAULT_NAMESPACE_PREFIX = \"ai.rag\";\n\n/**\n * Max chunk texts embedded per `embedder.embedMany()` call. One call is\n * one provider request, so a giant document is sub-batched to stay under\n * the provider's per-request token cap (the design's \"chunk larger than\n * provider per-request cap\" guard).\n */\nconst DEFAULT_MAX_BATCH = 96;\n\n/**\n * Create a RAG pipeline: **chunk → embed → vector store → retrieve →\n * rerank → cite**, reusing the app's `ai.embedder` for embedding, a\n * `@warlock.js/cache` `CacheDriver` as the vector store, and the\n * composite-as-tool engine to expose retrieval as a tool.\n *\n * Resolution is loud at construction (mirroring `memory()`):\n * - `embedder` is required — a provider with no embedder must be caught\n * here, not at first index.\n * - `store` falls back to `ai.config({ defaultStore })`; if neither\n * resolves, construction throws.\n *\n * `retrieve()` is return-only — it never auto-injects into a prompt; the\n * caller formats the cited chunks (or uses `asTool()` for the agent loop).\n * The reranker is OFF by default (cosine-only) unless `config.reranker`\n * is set.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n * import { MemoryCacheDriver } from \"@warlock.js/cache\";\n *\n * const kb = ai.rag({\n * name: \"docs\",\n * embedder: openai.embedder({ name: \"text-embedding-3-small\" }),\n * store: new MemoryCacheDriver(),\n * chunk: { type: \"markdown\", size: 800, overlap: 120 },\n * });\n *\n * await kb.index([{ id: \"guide\", text: longMarkdown, metadata: { url: \"/guide\" } }]);\n * const { chunks } = await kb.retrieve(\"how do I configure caching?\", { topK: 4 });\n */\nexport function rag(config: RagConfig): Rag {\n const name = config.name ?? DEFAULT_NAME;\n\n if (!config.embedder) {\n throw new Error(\n `rag(\"${name}\"): an \\`embedder\\` is required — pass one from a provider that supports embeddings (e.g. openai.embedder({ name: \"text-embedding-3-small\" }))`,\n );\n }\n\n const driver = config.store ?? resolveDefaultStore();\n\n if (!driver) {\n throw new Error(\n `rag(\"${name}\"): no store — pass \\`store\\` (a vector-capable @warlock.js/cache CacheDriver) or call \\`ai.config({ defaultStore })\\` at app boot before constructing the rag`,\n );\n }\n\n const store: VectorStore = cacheVectorStore(driver);\n const namespace = config.namespace ?? `${DEFAULT_NAMESPACE_PREFIX}.${name}`;\n const embedder = config.embedder;\n\n // Captured at first index for the dimension-mismatch guard in retrieve().\n let indexedDimensions: number | undefined;\n\n const instance: Rag = {\n name,\n\n async index(\n docs: RagDocument[],\n chunkOverride?: ChunkOptions,\n ): Promise<{ chunks: number }> {\n const chunkOptions = chunkOverride ?? config.chunk;\n\n // Ingestion guardrails (D5) — fail BEFORE any embedding spend.\n const limits = config.limits;\n if (limits?.maxDocuments !== undefined && docs.length > limits.maxDocuments) {\n throw new Error(\n `rag(\"${name}\"): index() received ${docs.length} documents, exceeding the configured maxDocuments of ${limits.maxDocuments}`,\n );\n }\n if (limits?.maxBytes !== undefined) {\n const totalBytes = docs.reduce(\n (sum, doc) => sum + Buffer.byteLength(doc.text ?? \"\"),\n 0,\n );\n if (totalBytes > limits.maxBytes) {\n throw new Error(\n `rag(\"${name}\"): index() received ${totalBytes} bytes of document text, exceeding the configured maxBytes of ${limits.maxBytes}`,\n );\n }\n }\n\n // Flatten every document into stored-chunk records + their texts,\n // preserving document order so a single batched embed maps back 1:1.\n const records: { key: string; value: StoredChunk; text: string; tags?: string[] }[] = [];\n\n for (const doc of docs) {\n const pieces = chunkText(doc.text, chunkOptions);\n\n for (const piece of pieces) {\n const value: StoredChunk = {\n sourceId: doc.id,\n chunkIndex: piece.index,\n span: piece.span,\n text: piece.text,\n metadata: doc.metadata,\n };\n\n records.push({\n key: keyFor(namespace, doc.id, piece.index),\n value,\n text: piece.text,\n tags: doc.tags,\n });\n }\n }\n\n // Empty / whitespace-only documents yield zero chunks — write\n // nothing and never embed an empty batch.\n if (records.length === 0) {\n return { chunks: 0 };\n }\n\n // Chunk cap (D5) — checked after chunking, still before embedding.\n if (limits?.maxChunks !== undefined && records.length > limits.maxChunks) {\n throw new Error(\n `rag(\"${name}\"): index() produced ${records.length} chunks, exceeding the configured maxChunks of ${limits.maxChunks}`,\n );\n }\n\n // Sub-batch the embed calls so one giant document does not blow the\n // provider's per-request token cap.\n for (let offset = 0; offset < records.length; offset += DEFAULT_MAX_BATCH) {\n const batch = records.slice(offset, offset + DEFAULT_MAX_BATCH);\n const { vectors, dimensions } = await embedder.embedMany(\n batch.map((record) => record.text),\n );\n\n if (indexedDimensions === undefined && dimensions !== 0) {\n indexedDimensions = dimensions;\n }\n\n await Promise.all(\n batch.map((record, position) =>\n store.upsert(record.key, record.value, vectors[position], record.tags),\n ),\n );\n }\n\n return { chunks: records.length };\n },\n\n async retrieve(query: string, options?: RetrieveOptions): Promise<RetrieveResult> {\n return runRetrieve(\n query,\n {\n embedder,\n store,\n namespace,\n reranker: config.reranker,\n defaults: config.retrieve,\n indexedDimensions,\n },\n options,\n );\n },\n\n async clear(): Promise<void> {\n await store.removeNamespace(namespace);\n },\n\n asTool(options?: RagAsToolOptions) {\n return ragAsTool(name, (query, retrieveOptions) => instance.retrieve(query, retrieveOptions), options);\n },\n };\n\n return instance;\n}\n\n/**\n * Namespaced key for a stored chunk. Uses the `.` separator (matching\n * `SemanticMemory.keyFor`) so namespace-prefix filtering on the returned\n * `hit.key` stays aligned with the cache's `parseKey` normalization.\n */\nfunction keyFor(namespace: string, sourceId: string, chunkIndex: number): string {\n return `${namespace}.${sourceId}.${chunkIndex}`;\n}\n"],"mappings":";;;;;;;AAeA,MAAM,eAAe;AACrB,MAAM,2BAA2B;;;;;;;AAQjC,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiC1B,SAAgB,IAAI,QAAwB;CAC1C,MAAM,OAAO,OAAO,QAAQ;CAE5B,IAAI,CAAC,OAAO,UACV,MAAM,IAAI,MACR,QAAQ,KAAK,+IACf;CAGF,MAAM,SAAS,OAAO,SAAS,oBAAoB;CAEnD,IAAI,CAAC,QACH,MAAM,IAAI,MACR,QAAQ,KAAK,+JACf;CAGF,MAAM,QAAqB,iBAAiB,MAAM;CAClD,MAAM,YAAY,OAAO,aAAa,GAAG,yBAAyB,GAAG;CACrE,MAAM,WAAW,OAAO;CAGxB,IAAI;CAEJ,MAAM,WAAgB;EACpB;EAEA,MAAM,MACJ,MACA,eAC6B;GAC7B,MAAM,eAAe,iBAAiB,OAAO;GAG7C,MAAM,SAAS,OAAO;GACtB,IAAI,QAAQ,iBAAiB,UAAa,KAAK,SAAS,OAAO,cAC7D,MAAM,IAAI,MACR,QAAQ,KAAK,uBAAuB,KAAK,OAAO,uDAAuD,OAAO,cAChH;GAEF,IAAI,QAAQ,aAAa,QAAW;IAClC,MAAM,aAAa,KAAK,QACrB,KAAK,QAAQ,MAAM,OAAO,WAAW,IAAI,QAAQ,EAAE,GACpD,CACF;IACA,IAAI,aAAa,OAAO,UACtB,MAAM,IAAI,MACR,QAAQ,KAAK,uBAAuB,WAAW,gEAAgE,OAAO,UACxH;GAEJ;GAIA,MAAM,UAAgF,CAAC;GAEvF,KAAK,MAAM,OAAO,MAAM;IACtB,MAAM,SAASA,MAAU,IAAI,MAAM,YAAY;IAE/C,KAAK,MAAM,SAAS,QAAQ;KAC1B,MAAM,QAAqB;MACzB,UAAU,IAAI;MACd,YAAY,MAAM;MAClB,MAAM,MAAM;MACZ,MAAM,MAAM;MACZ,UAAU,IAAI;KAChB;KAEA,QAAQ,KAAK;MACX,KAAK,OAAO,WAAW,IAAI,IAAI,MAAM,KAAK;MAC1C;MACA,MAAM,MAAM;MACZ,MAAM,IAAI;KACZ,CAAC;IACH;GACF;GAIA,IAAI,QAAQ,WAAW,GACrB,OAAO,EAAE,QAAQ,EAAE;GAIrB,IAAI,QAAQ,cAAc,UAAa,QAAQ,SAAS,OAAO,WAC7D,MAAM,IAAI,MACR,QAAQ,KAAK,uBAAuB,QAAQ,OAAO,iDAAiD,OAAO,WAC7G;GAKF,KAAK,IAAI,SAAS,GAAG,SAAS,QAAQ,QAAQ,UAAU,mBAAmB;IACzE,MAAM,QAAQ,QAAQ,MAAM,QAAQ,SAAS,iBAAiB;IAC9D,MAAM,EAAE,SAAS,eAAe,MAAM,SAAS,UAC7C,MAAM,KAAK,WAAW,OAAO,IAAI,CACnC;IAEA,IAAI,sBAAsB,UAAa,eAAe,GACpD,oBAAoB;IAGtB,MAAM,QAAQ,IACZ,MAAM,KAAK,QAAQ,aACjB,MAAM,OAAO,OAAO,KAAK,OAAO,OAAO,QAAQ,WAAW,OAAO,IAAI,CACvE,CACF;GACF;GAEA,OAAO,EAAE,QAAQ,QAAQ,OAAO;EAClC;EAEA,MAAM,SAAS,OAAe,SAAoD;GAChF,OAAOC,SACL,OACA;IACE;IACA;IACA;IACA,UAAU,OAAO;IACjB,UAAU,OAAO;IACjB;GACF,GACA,OACF;EACF;EAEA,MAAM,QAAuB;GAC3B,MAAM,MAAM,gBAAgB,SAAS;EACvC;EAEA,OAAO,SAA4B;GACjC,OAAO,UAAU,OAAO,OAAO,oBAAoB,SAAS,SAAS,OAAO,eAAe,GAAG,OAAO;EACvG;CACF;CAEA,OAAO;AACT;;;;;;AAOA,SAAS,OAAO,WAAmB,UAAkB,YAA4B;CAC/E,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG;AACrC"}
@@ -0,0 +1,32 @@
1
+ import { RagReranker } from "./reranker.contract.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/rag/rerank/keyword-reranker.d.ts
4
+ /** Options for the {@link keywordReranker}. */
5
+ type KeywordRerankerOptions = {
6
+ /**
7
+ * Weight of the lexical-overlap signal blended with the original cosine
8
+ * score, in `[0, 1]`. `1` ranks purely by keyword overlap; `0` keeps the
9
+ * cosine order. Default `0.5`.
10
+ */
11
+ weight?: number;
12
+ };
13
+ /**
14
+ * Zero-dependency lexical reranker (a BM25-lite, IDF-free keyword overlap).
15
+ *
16
+ * For each candidate it computes the fraction of distinct query terms that
17
+ * appear in the chunk, blends that with the candidate's original cosine
18
+ * score by `weight`, and sorts descending. A pure-lexical pass costs
19
+ * nothing beyond string splits — no peer, no model — so it is the
20
+ * recommended opt-in reranker when an embedding-only ranking surfaces a
21
+ * keyword-rich chunk too low.
22
+ *
23
+ * Ties (equal blended score) preserve the incoming order, so the cosine
24
+ * ranking breaks ties deterministically.
25
+ *
26
+ * @example
27
+ * const kb = ai.rag({ embedder, store, reranker: ai.rag.keywordReranker() });
28
+ */
29
+ declare function keywordReranker(options?: KeywordRerankerOptions): RagReranker;
30
+ //#endregion
31
+ export { KeywordRerankerOptions, keywordReranker };
32
+ //# sourceMappingURL=keyword-reranker.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyword-reranker.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/rerank/keyword-reranker.ts"],"mappings":";;;;KAIY,sBAAA;EAAA;;;;AAMJ;EAAN,MAAM;AAAA;;;;;;;AA2B0E;;;;;;;;;;iBAAlE,eAAA,CAAgB,OAAA,GAAS,sBAAA,GAA8B,WAAW"}
@@ -0,0 +1,58 @@
1
+ //#region ../@warlock.js/ai/src/rag/rerank/keyword-reranker.ts
2
+ /** Splits text into lowercase alphanumeric terms. */
3
+ function tokenize(text) {
4
+ return text.toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 0);
5
+ }
6
+ /**
7
+ * Zero-dependency lexical reranker (a BM25-lite, IDF-free keyword overlap).
8
+ *
9
+ * For each candidate it computes the fraction of distinct query terms that
10
+ * appear in the chunk, blends that with the candidate's original cosine
11
+ * score by `weight`, and sorts descending. A pure-lexical pass costs
12
+ * nothing beyond string splits — no peer, no model — so it is the
13
+ * recommended opt-in reranker when an embedding-only ranking surfaces a
14
+ * keyword-rich chunk too low.
15
+ *
16
+ * Ties (equal blended score) preserve the incoming order, so the cosine
17
+ * ranking breaks ties deterministically.
18
+ *
19
+ * @example
20
+ * const kb = ai.rag({ embedder, store, reranker: ai.rag.keywordReranker() });
21
+ */
22
+ function keywordReranker(options = {}) {
23
+ const weight = options.weight ?? .5;
24
+ return {
25
+ name: "keyword",
26
+ async rerank(query, candidates) {
27
+ if (candidates.length === 0) return [];
28
+ const queryTerms = new Set(tokenize(query));
29
+ if (queryTerms.size === 0) return [...candidates];
30
+ const scored = candidates.map((candidate, position) => {
31
+ const chunkTerms = new Set(tokenize(candidate.text));
32
+ let overlap = 0;
33
+ for (const term of queryTerms) if (chunkTerms.has(term)) overlap += 1;
34
+ return {
35
+ candidate,
36
+ blended: weight * (overlap / queryTerms.size) + (1 - weight) * candidate.score,
37
+ position
38
+ };
39
+ });
40
+ scored.sort((first, second) => {
41
+ if (second.blended !== first.blended) return second.blended - first.blended;
42
+ return first.position - second.position;
43
+ });
44
+ return scored.map((entry) => ({
45
+ ...entry.candidate,
46
+ score: entry.blended,
47
+ citation: {
48
+ ...entry.candidate.citation,
49
+ score: entry.blended
50
+ }
51
+ }));
52
+ }
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ export { keywordReranker };
58
+ //# sourceMappingURL=keyword-reranker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyword-reranker.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/rerank/keyword-reranker.ts"],"sourcesContent":["import type { RetrievedChunk } from \"../contracts/citation.type\";\nimport type { RagReranker } from \"./reranker.contract\";\n\n/** Options for the {@link keywordReranker}. */\nexport type KeywordRerankerOptions = {\n /**\n * Weight of the lexical-overlap signal blended with the original cosine\n * score, in `[0, 1]`. `1` ranks purely by keyword overlap; `0` keeps the\n * cosine order. Default `0.5`.\n */\n weight?: number;\n};\n\n/** Splits text into lowercase alphanumeric terms. */\nfunction tokenize(text: string): string[] {\n return text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((term) => term.length > 0);\n}\n\n/**\n * Zero-dependency lexical reranker (a BM25-lite, IDF-free keyword overlap).\n *\n * For each candidate it computes the fraction of distinct query terms that\n * appear in the chunk, blends that with the candidate's original cosine\n * score by `weight`, and sorts descending. A pure-lexical pass costs\n * nothing beyond string splits — no peer, no model — so it is the\n * recommended opt-in reranker when an embedding-only ranking surfaces a\n * keyword-rich chunk too low.\n *\n * Ties (equal blended score) preserve the incoming order, so the cosine\n * ranking breaks ties deterministically.\n *\n * @example\n * const kb = ai.rag({ embedder, store, reranker: ai.rag.keywordReranker() });\n */\nexport function keywordReranker(options: KeywordRerankerOptions = {}): RagReranker {\n const weight = options.weight ?? 0.5;\n\n return {\n name: \"keyword\",\n async rerank(query: string, candidates: RetrievedChunk[]): Promise<RetrievedChunk[]> {\n if (candidates.length === 0) {\n return [];\n }\n\n const queryTerms = new Set(tokenize(query));\n\n if (queryTerms.size === 0) {\n return [...candidates];\n }\n\n const scored = candidates.map((candidate, position) => {\n const chunkTerms = new Set(tokenize(candidate.text));\n\n let overlap = 0;\n for (const term of queryTerms) {\n if (chunkTerms.has(term)) {\n overlap += 1;\n }\n }\n\n const lexical = overlap / queryTerms.size;\n const blended = weight * lexical + (1 - weight) * candidate.score;\n\n return { candidate, blended, position };\n });\n\n scored.sort((first, second) => {\n if (second.blended !== first.blended) {\n return second.blended - first.blended;\n }\n\n // Stable on ties: keep the incoming (cosine) order.\n return first.position - second.position;\n });\n\n return scored.map((entry) => ({\n ...entry.candidate,\n score: entry.blended,\n citation: { ...entry.candidate.citation, score: entry.blended },\n }));\n },\n };\n}\n"],"mappings":";;AAcA,SAAS,SAAS,MAAwB;CACxC,OAAO,KACJ,YAAY,CAAC,CACb,MAAM,YAAY,CAAC,CACnB,QAAQ,SAAS,KAAK,SAAS,CAAC;AACrC;;;;;;;;;;;;;;;;;AAkBA,SAAgB,gBAAgB,UAAkC,CAAC,GAAgB;CACjF,MAAM,SAAS,QAAQ,UAAU;CAEjC,OAAO;EACL,MAAM;EACN,MAAM,OAAO,OAAe,YAAyD;GACnF,IAAI,WAAW,WAAW,GACxB,OAAO,CAAC;GAGV,MAAM,aAAa,IAAI,IAAI,SAAS,KAAK,CAAC;GAE1C,IAAI,WAAW,SAAS,GACtB,OAAO,CAAC,GAAG,UAAU;GAGvB,MAAM,SAAS,WAAW,KAAK,WAAW,aAAa;IACrD,MAAM,aAAa,IAAI,IAAI,SAAS,UAAU,IAAI,CAAC;IAEnD,IAAI,UAAU;IACd,KAAK,MAAM,QAAQ,YACjB,IAAI,WAAW,IAAI,IAAI,GACrB,WAAW;IAOf,OAAO;KAAE;KAAW,SAFJ,UADA,UAAU,WAAW,SACD,IAAI,UAAU,UAAU;KAE/B;IAAS;GACxC,CAAC;GAED,OAAO,MAAM,OAAO,WAAW;IAC7B,IAAI,OAAO,YAAY,MAAM,SAC3B,OAAO,OAAO,UAAU,MAAM;IAIhC,OAAO,MAAM,WAAW,OAAO;GACjC,CAAC;GAED,OAAO,OAAO,KAAK,WAAW;IAC5B,GAAG,MAAM;IACT,OAAO,MAAM;IACb,UAAU;KAAE,GAAG,MAAM,UAAU;KAAU,OAAO,MAAM;IAAQ;GAChE,EAAE;EACJ;CACF;AACF"}
@@ -0,0 +1,36 @@
1
+ import { ModelContract } from "../../contracts/model.contract.mjs";
2
+ import { RagReranker } from "./reranker.contract.mjs";
3
+
4
+ //#region ../@warlock.js/ai/src/rag/rerank/llm-reranker.d.ts
5
+ /** Options for the {@link llmReranker}. */
6
+ type LlmRerankerOptions = {
7
+ /** The model used to score candidate relevance. Required. */model: ModelContract;
8
+ /**
9
+ * How many candidates to score per model call. Larger batches mean
10
+ * fewer round-trips but a longer prompt. Default `10`.
11
+ */
12
+ batchSize?: number;
13
+ };
14
+ /**
15
+ * Optional model-backed reranker.
16
+ *
17
+ * Asks an LLM to grade each over-fetched candidate's relevance to the
18
+ * query on a `0..1` scale, then sorts descending by the model's score.
19
+ * Candidates the model does not score keep their original cosine score, so
20
+ * a partial/garbled reply degrades gracefully rather than dropping hits.
21
+ * Scoring is batched (`batchSize`) to bound prompt length.
22
+ *
23
+ * Unlike {@link keywordReranker}, this costs one or more model calls per
24
+ * retrieval — opt in only when precision matters more than latency/cost.
25
+ *
26
+ * @example
27
+ * const kb = ai.rag({
28
+ * embedder,
29
+ * store,
30
+ * reranker: ai.rag.llmReranker({ model: openai.model({ name: "gpt-4o-mini" }) }),
31
+ * });
32
+ */
33
+ declare function llmReranker(options: LlmRerankerOptions): RagReranker;
34
+ //#endregion
35
+ export { LlmRerankerOptions, llmReranker };
36
+ //# sourceMappingURL=llm-reranker.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-reranker.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/rerank/llm-reranker.ts"],"mappings":";;;;;KAMY,kBAAA;EAAA,6DAEV,KAAA,EAAO,aAAa;;;;;EAKpB,SAAA;AAAA;AAAS;AA8FX;;;;;;;;AAAqE;;;;;;;;;;AA9F1D,iBA8FK,WAAA,CAAY,OAAA,EAAS,kBAAA,GAAqB,WAAW"}
@@ -0,0 +1,85 @@
1
+ //#region ../@warlock.js/ai/src/rag/rerank/llm-reranker.ts
2
+ /**
3
+ * Build the scoring prompt — the model rates each candidate's relevance to
4
+ * the query on a `0..1` scale and replies with one `index: score` line per
5
+ * candidate. Kept terse and JSON-light so any chat model can answer.
6
+ */
7
+ function buildPrompt(query, candidates) {
8
+ return [{
9
+ role: "system",
10
+ content: "You are a relevance grader. For each numbered passage, rate how well it answers the query on a scale from 0 (irrelevant) to 1 (fully relevant). Reply with ONLY a JSON array of objects like [{\"index\":0,\"score\":0.9}], one entry per passage, no prose."
11
+ }, {
12
+ role: "user",
13
+ content: `Query: ${query}\n\nPassages:\n${candidates.map((candidate, index) => `[${index}] ${candidate.text}`).join("\n\n")}`
14
+ }];
15
+ }
16
+ /**
17
+ * Parse the model's reply into a score map. Tolerant of surrounding prose:
18
+ * extracts the first JSON array and reads `{ index, score }` entries.
19
+ * Returns an empty map when nothing parseable is found, so the caller can
20
+ * fall back to the original order.
21
+ */
22
+ function parseScores(reply) {
23
+ const scores = /* @__PURE__ */ new Map();
24
+ const start = reply.indexOf("[");
25
+ const end = reply.lastIndexOf("]");
26
+ if (start === -1 || end === -1 || end <= start) return scores;
27
+ let parsed;
28
+ try {
29
+ parsed = JSON.parse(reply.slice(start, end + 1));
30
+ } catch {
31
+ return scores;
32
+ }
33
+ if (!Array.isArray(parsed)) return scores;
34
+ for (const entry of parsed) if (entry && typeof entry.index === "number" && typeof entry.score === "number" && Number.isFinite(entry.score)) scores.set(entry.index, Math.max(0, Math.min(1, entry.score)));
35
+ return scores;
36
+ }
37
+ /**
38
+ * Optional model-backed reranker.
39
+ *
40
+ * Asks an LLM to grade each over-fetched candidate's relevance to the
41
+ * query on a `0..1` scale, then sorts descending by the model's score.
42
+ * Candidates the model does not score keep their original cosine score, so
43
+ * a partial/garbled reply degrades gracefully rather than dropping hits.
44
+ * Scoring is batched (`batchSize`) to bound prompt length.
45
+ *
46
+ * Unlike {@link keywordReranker}, this costs one or more model calls per
47
+ * retrieval — opt in only when precision matters more than latency/cost.
48
+ *
49
+ * @example
50
+ * const kb = ai.rag({
51
+ * embedder,
52
+ * store,
53
+ * reranker: ai.rag.llmReranker({ model: openai.model({ name: "gpt-4o-mini" }) }),
54
+ * });
55
+ */
56
+ function llmReranker(options) {
57
+ const batchSize = options.batchSize ?? 10;
58
+ return {
59
+ name: "llm",
60
+ async rerank(query, candidates) {
61
+ if (candidates.length === 0) return [];
62
+ const rescored = [];
63
+ for (let offset = 0; offset < candidates.length; offset += batchSize) {
64
+ const batch = candidates.slice(offset, offset + batchSize);
65
+ const scores = parseScores((await options.model.complete(buildPrompt(query, batch))).content);
66
+ batch.forEach((candidate, index) => {
67
+ const score = scores.has(index) ? scores.get(index) : candidate.score;
68
+ rescored.push({
69
+ ...candidate,
70
+ score,
71
+ citation: {
72
+ ...candidate.citation,
73
+ score
74
+ }
75
+ });
76
+ });
77
+ }
78
+ return rescored.sort((first, second) => second.score - first.score);
79
+ }
80
+ };
81
+ }
82
+
83
+ //#endregion
84
+ export { llmReranker };
85
+ //# sourceMappingURL=llm-reranker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-reranker.mjs","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/rerank/llm-reranker.ts"],"sourcesContent":["import type { Message } from \"../../contracts/conversation-message.type\";\nimport type { ModelContract } from \"../../contracts/model.contract\";\nimport type { RetrievedChunk } from \"../contracts/citation.type\";\nimport type { RagReranker } from \"./reranker.contract\";\n\n/** Options for the {@link llmReranker}. */\nexport type LlmRerankerOptions = {\n /** The model used to score candidate relevance. Required. */\n model: ModelContract;\n /**\n * How many candidates to score per model call. Larger batches mean\n * fewer round-trips but a longer prompt. Default `10`.\n */\n batchSize?: number;\n};\n\n/**\n * A single relevance score the model returns for a candidate, in `[0, 1]`,\n * keyed by the candidate's position in the batch.\n */\ntype ScoreLine = {\n index: number;\n score: number;\n};\n\n/**\n * Build the scoring prompt — the model rates each candidate's relevance to\n * the query on a `0..1` scale and replies with one `index: score` line per\n * candidate. Kept terse and JSON-light so any chat model can answer.\n */\nfunction buildPrompt(query: string, candidates: RetrievedChunk[]): Message[] {\n const lines = candidates\n .map((candidate, index) => `[${index}] ${candidate.text}`)\n .join(\"\\n\\n\");\n\n return [\n {\n role: \"system\",\n content:\n \"You are a relevance grader. For each numbered passage, rate how well it answers the query on a scale from 0 (irrelevant) to 1 (fully relevant). Reply with ONLY a JSON array of objects like [{\\\"index\\\":0,\\\"score\\\":0.9}], one entry per passage, no prose.\",\n },\n {\n role: \"user\",\n content: `Query: ${query}\\n\\nPassages:\\n${lines}`,\n },\n ];\n}\n\n/**\n * Parse the model's reply into a score map. Tolerant of surrounding prose:\n * extracts the first JSON array and reads `{ index, score }` entries.\n * Returns an empty map when nothing parseable is found, so the caller can\n * fall back to the original order.\n */\nfunction parseScores(reply: string): Map<number, number> {\n const scores = new Map<number, number>();\n const start = reply.indexOf(\"[\");\n const end = reply.lastIndexOf(\"]\");\n\n if (start === -1 || end === -1 || end <= start) {\n return scores;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(reply.slice(start, end + 1));\n } catch {\n return scores;\n }\n\n if (!Array.isArray(parsed)) {\n return scores;\n }\n\n for (const entry of parsed as ScoreLine[]) {\n if (\n entry &&\n typeof entry.index === \"number\" &&\n typeof entry.score === \"number\" &&\n Number.isFinite(entry.score)\n ) {\n scores.set(entry.index, Math.max(0, Math.min(1, entry.score)));\n }\n }\n\n return scores;\n}\n\n/**\n * Optional model-backed reranker.\n *\n * Asks an LLM to grade each over-fetched candidate's relevance to the\n * query on a `0..1` scale, then sorts descending by the model's score.\n * Candidates the model does not score keep their original cosine score, so\n * a partial/garbled reply degrades gracefully rather than dropping hits.\n * Scoring is batched (`batchSize`) to bound prompt length.\n *\n * Unlike {@link keywordReranker}, this costs one or more model calls per\n * retrieval — opt in only when precision matters more than latency/cost.\n *\n * @example\n * const kb = ai.rag({\n * embedder,\n * store,\n * reranker: ai.rag.llmReranker({ model: openai.model({ name: \"gpt-4o-mini\" }) }),\n * });\n */\nexport function llmReranker(options: LlmRerankerOptions): RagReranker {\n const batchSize = options.batchSize ?? 10;\n\n return {\n name: \"llm\",\n async rerank(query: string, candidates: RetrievedChunk[]): Promise<RetrievedChunk[]> {\n if (candidates.length === 0) {\n return [];\n }\n\n const rescored: RetrievedChunk[] = [];\n\n for (let offset = 0; offset < candidates.length; offset += batchSize) {\n const batch = candidates.slice(offset, offset + batchSize);\n const response = await options.model.complete(buildPrompt(query, batch));\n const scores = parseScores(response.content);\n\n batch.forEach((candidate, index) => {\n const score = scores.has(index) ? (scores.get(index) as number) : candidate.score;\n\n rescored.push({\n ...candidate,\n score,\n citation: { ...candidate.citation, score },\n });\n });\n }\n\n return rescored.sort((first, second) => second.score - first.score);\n },\n };\n}\n"],"mappings":";;;;;;AA8BA,SAAS,YAAY,OAAe,YAAyC;CAK3E,OAAO,CACL;EACE,MAAM;EACN,SACE;CACJ,GACA;EACE,MAAM;EACN,SAAS,UAAU,MAAM,iBAZf,WACX,KAAK,WAAW,UAAU,IAAI,MAAM,IAAI,UAAU,MAAM,CAAC,CACzD,KAAK,MAU0C;CAChD,CACF;AACF;;;;;;;AAQA,SAAS,YAAY,OAAoC;CACvD,MAAM,yBAAS,IAAI,IAAoB;CACvC,MAAM,QAAQ,MAAM,QAAQ,GAAG;CAC/B,MAAM,MAAM,MAAM,YAAY,GAAG;CAEjC,IAAI,UAAU,MAAM,QAAQ,MAAM,OAAO,OACvC,OAAO;CAGT,IAAI;CACJ,IAAI;EACF,SAAS,KAAK,MAAM,MAAM,MAAM,OAAO,MAAM,CAAC,CAAC;CACjD,QAAQ;EACN,OAAO;CACT;CAEA,IAAI,CAAC,MAAM,QAAQ,MAAM,GACvB,OAAO;CAGT,KAAK,MAAM,SAAS,QAClB,IACE,SACA,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,UAAU,YACvB,OAAO,SAAS,MAAM,KAAK,GAE3B,OAAO,IAAI,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC;CAIjE,OAAO;AACT;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,YAAY,SAA0C;CACpE,MAAM,YAAY,QAAQ,aAAa;CAEvC,OAAO;EACL,MAAM;EACN,MAAM,OAAO,OAAe,YAAyD;GACnF,IAAI,WAAW,WAAW,GACxB,OAAO,CAAC;GAGV,MAAM,WAA6B,CAAC;GAEpC,KAAK,IAAI,SAAS,GAAG,SAAS,WAAW,QAAQ,UAAU,WAAW;IACpE,MAAM,QAAQ,WAAW,MAAM,QAAQ,SAAS,SAAS;IAEzD,MAAM,SAAS,aAAY,MADJ,QAAQ,MAAM,SAAS,YAAY,OAAO,KAAK,CAAC,EACpC,CAAC,OAAO;IAE3C,MAAM,SAAS,WAAW,UAAU;KAClC,MAAM,QAAQ,OAAO,IAAI,KAAK,IAAK,OAAO,IAAI,KAAK,IAAe,UAAU;KAE5E,SAAS,KAAK;MACZ,GAAG;MACH;MACA,UAAU;OAAE,GAAG,UAAU;OAAU;MAAM;KAC3C,CAAC;IACH,CAAC;GACH;GAEA,OAAO,SAAS,MAAM,OAAO,WAAW,OAAO,QAAQ,MAAM,KAAK;EACpE;CACF;AACF"}
@@ -0,0 +1,28 @@
1
+ import { RetrievedChunk } from "../contracts/citation.type.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/rag/rerank/reranker.contract.d.ts
4
+ /**
5
+ * Reranks an over-fetched candidate set against the query before the
6
+ * pipeline slices to `topK`. Optional — when no reranker is configured the
7
+ * raw cosine order from the vector store is kept.
8
+ *
9
+ * A reranker receives the candidates already scored by cosine similarity
10
+ * and returns them reordered (and typically re-scored). The pipeline does
11
+ * NOT trust the input order; it relies entirely on the returned order. A
12
+ * reranker that throws is caught by the pipeline, which falls back to the
13
+ * cosine order — so an implementation may throw to opt out of a given
14
+ * query rather than returning garbage.
15
+ */
16
+ interface RagReranker {
17
+ /** Stable name for logs / diagnostics. */
18
+ readonly name: string;
19
+ /**
20
+ * Reorder (and optionally re-score) `candidates` by relevance to
21
+ * `query`. Returns the reranked list; the pipeline slices `topK` from
22
+ * the front.
23
+ */
24
+ rerank(query: string, candidates: RetrievedChunk[]): Promise<RetrievedChunk[]>;
25
+ }
26
+ //#endregion
27
+ export { RagReranker };
28
+ //# sourceMappingURL=reranker.contract.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reranker.contract.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/ai/src/rag/rerank/reranker.contract.ts"],"mappings":";;;;;AAcA;;;;;;;;;;UAAiB,WAAA;EAQmB;EAAA,SANzB,IAAA;EAM4C;;;AAAsB;;EAA3E,MAAA,CAAO,KAAA,UAAe,UAAA,EAAY,cAAA,KAAmB,OAAA,CAAQ,cAAA;AAAA"}
@@ -0,0 +1,68 @@
1
+ //#region ../@warlock.js/ai/src/rag/retrieve.ts
2
+ /** Default number of chunks returned after reranking. */
3
+ const DEFAULT_TOP_K = 5;
4
+ /** Default cosine floor applied at the vector-store stage. */
5
+ const DEFAULT_THRESHOLD = .5;
6
+ /**
7
+ * The cite pipeline: embed the query → over-fetch candidates from the
8
+ * store → filter to this rag's namespace → map to {@link RetrievedChunk}s
9
+ * with a {@link Citation} → optionally rerank → slice `topK`.
10
+ *
11
+ * Behavior matches the design's failure modes:
12
+ * - No hits clearing the threshold → `{ query, chunks: [] }`, never throws.
13
+ * - Namespace-prefix filtering keeps two rags sharing one driver isolated.
14
+ * - A reranker that throws is caught; the raw cosine order is used instead.
15
+ * - A dimension mismatch (indexed with model A, queried with model B)
16
+ * throws a clear error rather than returning garbage hits.
17
+ */
18
+ async function retrieve(query, deps, options = {}) {
19
+ const topK = options.topK ?? deps.defaults?.topK ?? 5;
20
+ const threshold = options.threshold ?? deps.defaults?.threshold ?? .5;
21
+ const tags = options.tags ?? deps.defaults?.tags;
22
+ const candidates = options.candidates ?? deps.defaults?.candidates ?? Math.max(topK * 4, topK);
23
+ const { vector, dimensions } = await deps.embedder.embed(query);
24
+ if (deps.indexedDimensions !== void 0 && dimensions !== 0 && deps.indexedDimensions !== 0 && dimensions !== deps.indexedDimensions) throw new Error(`rag.retrieve(): query embedder dimensions (${dimensions}) do not match the dimensions captured at index time (${deps.indexedDimensions}); index and query must use the same embedding model`);
25
+ const hits = await deps.store.query(vector, {
26
+ topK: candidates,
27
+ threshold,
28
+ tags
29
+ });
30
+ const prefix = `${deps.namespace}.`;
31
+ let retrieved = hits.filter((hit) => hit.key.startsWith(prefix)).map((hit) => toRetrievedChunk(hit.value, hit.score));
32
+ retrieved = await applyReranker(query, retrieved, deps.reranker);
33
+ return {
34
+ query,
35
+ chunks: retrieved.slice(0, topK)
36
+ };
37
+ }
38
+ /** Build a cited {@link RetrievedChunk} from a stored chunk + its cosine score. */
39
+ function toRetrievedChunk(stored, score) {
40
+ const citation = {
41
+ sourceId: stored.sourceId,
42
+ chunkIndex: stored.chunkIndex,
43
+ span: stored.span,
44
+ score,
45
+ metadata: stored.metadata
46
+ };
47
+ return {
48
+ text: stored.text,
49
+ score,
50
+ citation
51
+ };
52
+ }
53
+ /**
54
+ * Run the optional reranker, degrading to the raw cosine order if it
55
+ * throws — a flaky optional reranker must never fail the whole retrieval.
56
+ */
57
+ async function applyReranker(query, candidates, reranker) {
58
+ if (!reranker) return candidates;
59
+ try {
60
+ return await reranker.rerank(query, candidates);
61
+ } catch {
62
+ return candidates;
63
+ }
64
+ }
65
+
66
+ //#endregion
67
+ export { retrieve };
68
+ //# sourceMappingURL=retrieve.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrieve.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/rag/retrieve.ts"],"sourcesContent":["import type { EmbedderContract } from \"../contracts/embedder.contract\";\nimport type {\n Citation,\n RetrievedChunk,\n RetrieveOptions,\n RetrieveResult,\n} from \"./contracts/citation.type\";\nimport type { RagReranker } from \"./rerank/reranker.contract\";\nimport type { VectorStore } from \"./store/vector-store.contract\";\n\n/** Default number of chunks returned after reranking. */\nexport const DEFAULT_TOP_K = 5;\n\n/** Default cosine floor applied at the vector-store stage. */\nexport const DEFAULT_THRESHOLD = 0.5;\n\n/**\n * Shape persisted per chunk in the vector store. The vector itself is held\n * by the driver's own index (passed via `set({ vector })`), so it is not\n * duplicated here.\n */\nexport type StoredChunk = {\n sourceId: string;\n chunkIndex: number;\n span: [start: number, end: number];\n text: string;\n metadata?: Record<string, unknown>;\n};\n\n/** Dependencies the retrieve pipeline needs, resolved once by `rag()`. */\nexport type RetrieveDeps = {\n embedder: EmbedderContract;\n store: VectorStore;\n /** Namespace prefix every stored key carries (e.g. `\"ai.rag.docs\"`). */\n namespace: string;\n /** Optional reranker; when absent the cosine order is kept. */\n reranker?: RagReranker;\n /** Pipeline-level retrieval defaults. */\n defaults?: RetrieveOptions;\n /**\n * Dimension count captured at first index for the mismatch guard. When\n * set, the query embedder's `dimensions` must equal it.\n */\n indexedDimensions?: number;\n};\n\n/**\n * The cite pipeline: embed the query → over-fetch candidates from the\n * store → filter to this rag's namespace → map to {@link RetrievedChunk}s\n * with a {@link Citation} → optionally rerank → slice `topK`.\n *\n * Behavior matches the design's failure modes:\n * - No hits clearing the threshold → `{ query, chunks: [] }`, never throws.\n * - Namespace-prefix filtering keeps two rags sharing one driver isolated.\n * - A reranker that throws is caught; the raw cosine order is used instead.\n * - A dimension mismatch (indexed with model A, queried with model B)\n * throws a clear error rather than returning garbage hits.\n */\nexport async function retrieve(\n query: string,\n deps: RetrieveDeps,\n options: RetrieveOptions = {},\n): Promise<RetrieveResult> {\n const topK = options.topK ?? deps.defaults?.topK ?? DEFAULT_TOP_K;\n const threshold = options.threshold ?? deps.defaults?.threshold ?? DEFAULT_THRESHOLD;\n const tags = options.tags ?? deps.defaults?.tags;\n const candidates = options.candidates ?? deps.defaults?.candidates ?? Math.max(topK * 4, topK);\n\n const { vector, dimensions } = await deps.embedder.embed(query);\n\n if (\n deps.indexedDimensions !== undefined &&\n dimensions !== 0 &&\n deps.indexedDimensions !== 0 &&\n dimensions !== deps.indexedDimensions\n ) {\n throw new Error(\n `rag.retrieve(): query embedder dimensions (${dimensions}) do not match the dimensions captured at index time (${deps.indexedDimensions}); index and query must use the same embedding model`,\n );\n }\n\n const hits = await deps.store.query<StoredChunk>(vector, {\n topK: candidates,\n threshold,\n tags,\n });\n\n const prefix = `${deps.namespace}.`;\n\n let retrieved: RetrievedChunk[] = hits\n .filter((hit) => hit.key.startsWith(prefix))\n .map((hit) => toRetrievedChunk(hit.value, hit.score));\n\n retrieved = await applyReranker(query, retrieved, deps.reranker);\n\n return { query, chunks: retrieved.slice(0, topK) };\n}\n\n/** Build a cited {@link RetrievedChunk} from a stored chunk + its cosine score. */\nfunction toRetrievedChunk(stored: StoredChunk, score: number): RetrievedChunk {\n const citation: Citation = {\n sourceId: stored.sourceId,\n chunkIndex: stored.chunkIndex,\n span: stored.span,\n score,\n metadata: stored.metadata,\n };\n\n return { text: stored.text, score, citation };\n}\n\n/**\n * Run the optional reranker, degrading to the raw cosine order if it\n * throws — a flaky optional reranker must never fail the whole retrieval.\n */\nasync function applyReranker(\n query: string,\n candidates: RetrievedChunk[],\n reranker: RagReranker | undefined,\n): Promise<RetrievedChunk[]> {\n if (!reranker) {\n return candidates;\n }\n\n try {\n return await reranker.rerank(query, candidates);\n } catch {\n // Logged at the call site in a richer build; here we degrade silently\n // to vector-only ranking rather than aborting the retrieval.\n return candidates;\n }\n}\n"],"mappings":";;AAWA,MAAa,gBAAgB;;AAG7B,MAAa,oBAAoB;;;;;;;;;;;;;AA4CjC,eAAsB,SACpB,OACA,MACA,UAA2B,CAAC,GACH;CACzB,MAAM,OAAO,QAAQ,QAAQ,KAAK,UAAU;CAC5C,MAAM,YAAY,QAAQ,aAAa,KAAK,UAAU;CACtD,MAAM,OAAO,QAAQ,QAAQ,KAAK,UAAU;CAC5C,MAAM,aAAa,QAAQ,cAAc,KAAK,UAAU,cAAc,KAAK,IAAI,OAAO,GAAG,IAAI;CAE7F,MAAM,EAAE,QAAQ,eAAe,MAAM,KAAK,SAAS,MAAM,KAAK;CAE9D,IACE,KAAK,sBAAsB,UAC3B,eAAe,KACf,KAAK,sBAAsB,KAC3B,eAAe,KAAK,mBAEpB,MAAM,IAAI,MACR,8CAA8C,WAAW,wDAAwD,KAAK,kBAAkB,qDAC1I;CAGF,MAAM,OAAO,MAAM,KAAK,MAAM,MAAmB,QAAQ;EACvD,MAAM;EACN;EACA;CACF,CAAC;CAED,MAAM,SAAS,GAAG,KAAK,UAAU;CAEjC,IAAI,YAA8B,KAC/B,QAAQ,QAAQ,IAAI,IAAI,WAAW,MAAM,CAAC,CAAC,CAC3C,KAAK,QAAQ,iBAAiB,IAAI,OAAO,IAAI,KAAK,CAAC;CAEtD,YAAY,MAAM,cAAc,OAAO,WAAW,KAAK,QAAQ;CAE/D,OAAO;EAAE;EAAO,QAAQ,UAAU,MAAM,GAAG,IAAI;CAAE;AACnD;;AAGA,SAAS,iBAAiB,QAAqB,OAA+B;CAC5E,MAAM,WAAqB;EACzB,UAAU,OAAO;EACjB,YAAY,OAAO;EACnB,MAAM,OAAO;EACb;EACA,UAAU,OAAO;CACnB;CAEA,OAAO;EAAE,MAAM,OAAO;EAAM;EAAO;CAAS;AAC9C;;;;;AAMA,eAAe,cACb,OACA,YACA,UAC2B;CAC3B,IAAI,CAAC,UACH,OAAO;CAGT,IAAI;EACF,OAAO,MAAM,SAAS,OAAO,OAAO,UAAU;CAChD,QAAQ;EAGN,OAAO;CACT;AACF"}