@warlock.js/core 4.4.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (846) hide show
  1. package/CHANGELOG.md +45 -5
  2. package/README.md +47 -11
  3. package/esm/ai/src/agent/agent-input-builder.mjs +132 -0
  4. package/esm/ai/src/agent/agent-input-builder.mjs.map +1 -0
  5. package/esm/ai/src/agent/agent-log-event.mjs +101 -0
  6. package/esm/ai/src/agent/agent-log-event.mjs.map +1 -0
  7. package/esm/ai/src/agent/agent-stream.mjs +82 -0
  8. package/esm/ai/src/agent/agent-stream.mjs.map +1 -0
  9. package/esm/ai/src/agent/agent-to-stream-event.mjs +86 -0
  10. package/esm/ai/src/agent/agent-to-stream-event.mjs.map +1 -0
  11. package/esm/ai/src/agent/agent.mjs +1157 -0
  12. package/esm/ai/src/agent/agent.mjs.map +1 -0
  13. package/esm/ai/src/agent/index.mjs +5 -0
  14. package/esm/ai/src/agent/json-stream-guard.mjs +400 -0
  15. package/esm/ai/src/agent/json-stream-guard.mjs.map +1 -0
  16. package/esm/ai/src/agent/spawn-sub-agent.mjs +68 -0
  17. package/esm/ai/src/agent/spawn-sub-agent.mjs.map +1 -0
  18. package/esm/ai/src/ai.mjs +155 -0
  19. package/esm/ai/src/ai.mjs.map +1 -0
  20. package/esm/ai/src/batch/batch.mjs +198 -0
  21. package/esm/ai/src/batch/batch.mjs.map +1 -0
  22. package/esm/ai/src/batch/index.mjs +3 -0
  23. package/esm/ai/src/batch/run-batch-item.mjs +100 -0
  24. package/esm/ai/src/batch/run-batch-item.mjs.map +1 -0
  25. package/esm/ai/src/batch/run-with-concurrency.mjs +39 -0
  26. package/esm/ai/src/batch/run-with-concurrency.mjs.map +1 -0
  27. package/esm/ai/src/checkpoint/memory.mjs +0 -0
  28. package/esm/ai/src/checkpoint/memory.mjs.map +1 -0
  29. package/esm/ai/src/checkpoint/pg.mjs +265 -0
  30. package/esm/ai/src/checkpoint/pg.mjs.map +1 -0
  31. package/esm/ai/src/checkpoint/redis.mjs +200 -0
  32. package/esm/ai/src/checkpoint/redis.mjs.map +1 -0
  33. package/esm/ai/src/config.mjs +59 -0
  34. package/esm/ai/src/config.mjs.map +1 -0
  35. package/esm/ai/src/contracts/end.type.mjs +47 -0
  36. package/esm/ai/src/contracts/end.type.mjs.map +1 -0
  37. package/esm/ai/src/errors/agent-cancelled-error.mjs +43 -0
  38. package/esm/ai/src/errors/agent-cancelled-error.mjs.map +1 -0
  39. package/esm/ai/src/errors/agent-execution-error.mjs +35 -0
  40. package/esm/ai/src/errors/agent-execution-error.mjs.map +1 -0
  41. package/esm/ai/src/errors/agent-max-trips-error.mjs +41 -0
  42. package/esm/ai/src/errors/agent-max-trips-error.mjs.map +1 -0
  43. package/esm/ai/src/errors/ai-error.mjs +68 -0
  44. package/esm/ai/src/errors/ai-error.mjs.map +1 -0
  45. package/esm/ai/src/errors/budget-exceeded-error.mjs +31 -0
  46. package/esm/ai/src/errors/budget-exceeded-error.mjs.map +1 -0
  47. package/esm/ai/src/errors/content-filter-error.mjs +28 -0
  48. package/esm/ai/src/errors/content-filter-error.mjs.map +1 -0
  49. package/esm/ai/src/errors/context-length-exceeded-error.mjs +31 -0
  50. package/esm/ai/src/errors/context-length-exceeded-error.mjs.map +1 -0
  51. package/esm/ai/src/errors/guardrail-violation-error.mjs +41 -0
  52. package/esm/ai/src/errors/guardrail-violation-error.mjs.map +1 -0
  53. package/esm/ai/src/errors/index.mjs +37 -0
  54. package/esm/ai/src/errors/invalid-request-error.mjs +31 -0
  55. package/esm/ai/src/errors/invalid-request-error.mjs.map +1 -0
  56. package/esm/ai/src/errors/max-iterations-error.mjs +32 -0
  57. package/esm/ai/src/errors/max-iterations-error.mjs.map +1 -0
  58. package/esm/ai/src/errors/max-steps-exceeded-error.mjs +21 -0
  59. package/esm/ai/src/errors/max-steps-exceeded-error.mjs.map +1 -0
  60. package/esm/ai/src/errors/orchestrator-cancelled-error.mjs +31 -0
  61. package/esm/ai/src/errors/orchestrator-cancelled-error.mjs.map +1 -0
  62. package/esm/ai/src/errors/orchestrator-config-error.mjs +30 -0
  63. package/esm/ai/src/errors/orchestrator-config-error.mjs.map +1 -0
  64. package/esm/ai/src/errors/orchestrator-drift-error.mjs +37 -0
  65. package/esm/ai/src/errors/orchestrator-drift-error.mjs.map +1 -0
  66. package/esm/ai/src/errors/orchestrator-failed-error.mjs +36 -0
  67. package/esm/ai/src/errors/orchestrator-failed-error.mjs.map +1 -0
  68. package/esm/ai/src/errors/outbound-policy-error.mjs +32 -0
  69. package/esm/ai/src/errors/outbound-policy-error.mjs.map +1 -0
  70. package/esm/ai/src/errors/planner-cancelled-error.mjs +29 -0
  71. package/esm/ai/src/errors/planner-cancelled-error.mjs.map +1 -0
  72. package/esm/ai/src/errors/planner-failed-error.mjs +37 -0
  73. package/esm/ai/src/errors/planner-failed-error.mjs.map +1 -0
  74. package/esm/ai/src/errors/planner-plan-invalid-error.mjs +25 -0
  75. package/esm/ai/src/errors/planner-plan-invalid-error.mjs.map +1 -0
  76. package/esm/ai/src/errors/provider-auth-error.mjs +26 -0
  77. package/esm/ai/src/errors/provider-auth-error.mjs.map +1 -0
  78. package/esm/ai/src/errors/provider-error.mjs +42 -0
  79. package/esm/ai/src/errors/provider-error.mjs.map +1 -0
  80. package/esm/ai/src/errors/provider-rate-limit-error.mjs +31 -0
  81. package/esm/ai/src/errors/provider-rate-limit-error.mjs.map +1 -0
  82. package/esm/ai/src/errors/provider-timeout-error.mjs +26 -0
  83. package/esm/ai/src/errors/provider-timeout-error.mjs.map +1 -0
  84. package/esm/ai/src/errors/quota-exceeded-error.mjs +40 -0
  85. package/esm/ai/src/errors/quota-exceeded-error.mjs.map +1 -0
  86. package/esm/ai/src/errors/routing-error.mjs +23 -0
  87. package/esm/ai/src/errors/routing-error.mjs.map +1 -0
  88. package/esm/ai/src/errors/schema-validation-error.mjs +37 -0
  89. package/esm/ai/src/errors/schema-validation-error.mjs.map +1 -0
  90. package/esm/ai/src/errors/step-failed-error.mjs +19 -0
  91. package/esm/ai/src/errors/step-failed-error.mjs.map +1 -0
  92. package/esm/ai/src/errors/supervisor-cancelled-error.mjs +29 -0
  93. package/esm/ai/src/errors/supervisor-cancelled-error.mjs.map +1 -0
  94. package/esm/ai/src/errors/supervisor-drift-error.mjs +30 -0
  95. package/esm/ai/src/errors/supervisor-drift-error.mjs.map +1 -0
  96. package/esm/ai/src/errors/supervisor-failed-error.mjs +43 -0
  97. package/esm/ai/src/errors/supervisor-failed-error.mjs.map +1 -0
  98. package/esm/ai/src/errors/supervisor-routing-error.mjs +39 -0
  99. package/esm/ai/src/errors/supervisor-routing-error.mjs.map +1 -0
  100. package/esm/ai/src/errors/tool-execution-error.mjs +32 -0
  101. package/esm/ai/src/errors/tool-execution-error.mjs.map +1 -0
  102. package/esm/ai/src/errors/workflow-cancelled-error.mjs +23 -0
  103. package/esm/ai/src/errors/workflow-cancelled-error.mjs.map +1 -0
  104. package/esm/ai/src/errors/workflow-drift-error.mjs +24 -0
  105. package/esm/ai/src/errors/workflow-drift-error.mjs.map +1 -0
  106. package/esm/ai/src/errors/workflow-error.mjs +18 -0
  107. package/esm/ai/src/errors/workflow-error.mjs.map +1 -0
  108. package/esm/ai/src/eval/dataset.mjs +112 -0
  109. package/esm/ai/src/eval/dataset.mjs.map +1 -0
  110. package/esm/ai/src/eval/eval-runner.mjs +135 -0
  111. package/esm/ai/src/eval/eval-runner.mjs.map +1 -0
  112. package/esm/ai/src/eval/index.mjs +48 -0
  113. package/esm/ai/src/eval/index.mjs.map +1 -0
  114. package/esm/ai/src/eval/judge-scorer.mjs +87 -0
  115. package/esm/ai/src/eval/judge-scorer.mjs.map +1 -0
  116. package/esm/ai/src/eval/regression.mjs +51 -0
  117. package/esm/ai/src/eval/regression.mjs.map +1 -0
  118. package/esm/ai/src/eval/report-json.mjs +33 -0
  119. package/esm/ai/src/eval/report-json.mjs.map +1 -0
  120. package/esm/ai/src/eval/report-junit.mjs +60 -0
  121. package/esm/ai/src/eval/report-junit.mjs.map +1 -0
  122. package/esm/ai/src/eval/scorers.mjs +101 -0
  123. package/esm/ai/src/eval/scorers.mjs.map +1 -0
  124. package/esm/ai/src/guard/detectors/index.mjs +6 -0
  125. package/esm/ai/src/guard/detectors/injection.mjs +254 -0
  126. package/esm/ai/src/guard/detectors/injection.mjs.map +1 -0
  127. package/esm/ai/src/guard/detectors/moderation.mjs +134 -0
  128. package/esm/ai/src/guard/detectors/moderation.mjs.map +1 -0
  129. package/esm/ai/src/guard/detectors/pii.mjs +199 -0
  130. package/esm/ai/src/guard/detectors/pii.mjs.map +1 -0
  131. package/esm/ai/src/guard/detectors/topic.mjs +99 -0
  132. package/esm/ai/src/guard/detectors/topic.mjs.map +1 -0
  133. package/esm/ai/src/guard/errors.mjs +18 -0
  134. package/esm/ai/src/guard/errors.mjs.map +1 -0
  135. package/esm/ai/src/guard/guard.mjs +209 -0
  136. package/esm/ai/src/guard/guard.mjs.map +1 -0
  137. package/esm/ai/src/guard/guardrail.mjs +22 -0
  138. package/esm/ai/src/guard/guardrail.mjs.map +1 -0
  139. package/esm/ai/src/human/errors.mjs +60 -0
  140. package/esm/ai/src/human/errors.mjs.map +1 -0
  141. package/esm/ai/src/human/human-approval.mjs +170 -0
  142. package/esm/ai/src/human/human-approval.mjs.map +1 -0
  143. package/esm/ai/src/human/policy.mjs +67 -0
  144. package/esm/ai/src/human/policy.mjs.map +1 -0
  145. package/esm/ai/src/human/register.mjs +37 -0
  146. package/esm/ai/src/human/register.mjs.map +1 -0
  147. package/esm/ai/src/human/resume-seed.mjs +53 -0
  148. package/esm/ai/src/human/resume-seed.mjs.map +1 -0
  149. package/esm/ai/src/human/resume.mjs +121 -0
  150. package/esm/ai/src/human/resume.mjs.map +1 -0
  151. package/esm/ai/src/human/stores/index.mjs +5 -0
  152. package/esm/ai/src/human/stores/memory.mjs +91 -0
  153. package/esm/ai/src/human/stores/memory.mjs.map +1 -0
  154. package/esm/ai/src/human/stores/pg.mjs +220 -0
  155. package/esm/ai/src/human/stores/pg.mjs.map +1 -0
  156. package/esm/ai/src/human/stores/redis.mjs +201 -0
  157. package/esm/ai/src/human/stores/redis.mjs.map +1 -0
  158. package/esm/ai/src/index.mjs +174 -0
  159. package/esm/ai/src/memory/derive-id.mjs +24 -0
  160. package/esm/ai/src/memory/derive-id.mjs.map +1 -0
  161. package/esm/ai/src/memory/episodic-memory.mjs +106 -0
  162. package/esm/ai/src/memory/episodic-memory.mjs.map +1 -0
  163. package/esm/ai/src/memory/memory.mjs +166 -0
  164. package/esm/ai/src/memory/memory.mjs.map +1 -0
  165. package/esm/ai/src/memory/procedural-memory.mjs +103 -0
  166. package/esm/ai/src/memory/procedural-memory.mjs.map +1 -0
  167. package/esm/ai/src/memory/semantic-memory.mjs +80 -0
  168. package/esm/ai/src/memory/semantic-memory.mjs.map +1 -0
  169. package/esm/ai/src/memory/working-memory.mjs +62 -0
  170. package/esm/ai/src/memory/working-memory.mjs.map +1 -0
  171. package/esm/ai/src/middleware/builtins/budget.mjs +219 -0
  172. package/esm/ai/src/middleware/builtins/budget.mjs.map +1 -0
  173. package/esm/ai/src/middleware/builtins/guardrail.mjs +76 -0
  174. package/esm/ai/src/middleware/builtins/guardrail.mjs.map +1 -0
  175. package/esm/ai/src/middleware/builtins/semantic-cache.mjs +149 -0
  176. package/esm/ai/src/middleware/builtins/semantic-cache.mjs.map +1 -0
  177. package/esm/ai/src/middleware/helpers/compose.mjs +52 -0
  178. package/esm/ai/src/middleware/helpers/compose.mjs.map +1 -0
  179. package/esm/ai/src/middleware/helpers/for-tool.mjs +80 -0
  180. package/esm/ai/src/middleware/helpers/for-tool.mjs.map +1 -0
  181. package/esm/ai/src/middleware/index.mjs +10 -0
  182. package/esm/ai/src/middleware/pipeline.mjs +100 -0
  183. package/esm/ai/src/middleware/pipeline.mjs.map +1 -0
  184. package/esm/ai/src/middleware/utils/extract-user-text.mjs +47 -0
  185. package/esm/ai/src/middleware/utils/extract-user-text.mjs.map +1 -0
  186. package/esm/ai/src/middleware/utils/namespaced-state.mjs +60 -0
  187. package/esm/ai/src/middleware/utils/namespaced-state.mjs.map +1 -0
  188. package/esm/ai/src/mock/index.mjs +4 -0
  189. package/esm/ai/src/mock/mock-agent.mjs +3 -0
  190. package/esm/ai/src/mock/mock-router.mjs +58 -0
  191. package/esm/ai/src/mock/mock-router.mjs.map +1 -0
  192. package/esm/ai/src/model/fallback-model.mjs +218 -0
  193. package/esm/ai/src/model/fallback-model.mjs.map +1 -0
  194. package/esm/ai/src/model/index.mjs +3 -0
  195. package/esm/ai/src/object-stream/index.mjs +4 -0
  196. package/esm/ai/src/object-stream/parse-partial-json.mjs +78 -0
  197. package/esm/ai/src/object-stream/parse-partial-json.mjs.map +1 -0
  198. package/esm/ai/src/object-stream/stream-object.mjs +97 -0
  199. package/esm/ai/src/object-stream/stream-object.mjs.map +1 -0
  200. package/esm/ai/src/observe/index.mjs +4 -0
  201. package/esm/ai/src/observe/observer-registry.mjs +35 -0
  202. package/esm/ai/src/observe/observer-registry.mjs.map +1 -0
  203. package/esm/ai/src/observe/resolve-observers.mjs +73 -0
  204. package/esm/ai/src/observe/resolve-observers.mjs.map +1 -0
  205. package/esm/ai/src/orchestrator/as-tool.mjs +98 -0
  206. package/esm/ai/src/orchestrator/as-tool.mjs.map +1 -0
  207. package/esm/ai/src/orchestrator/checkpoint.mjs +75 -0
  208. package/esm/ai/src/orchestrator/checkpoint.mjs.map +1 -0
  209. package/esm/ai/src/orchestrator/commands.mjs +34 -0
  210. package/esm/ai/src/orchestrator/commands.mjs.map +1 -0
  211. package/esm/ai/src/orchestrator/compaction.mjs +206 -0
  212. package/esm/ai/src/orchestrator/compaction.mjs.map +1 -0
  213. package/esm/ai/src/orchestrator/dispatch.mjs +171 -0
  214. package/esm/ai/src/orchestrator/dispatch.mjs.map +1 -0
  215. package/esm/ai/src/orchestrator/emitter.mjs +85 -0
  216. package/esm/ai/src/orchestrator/emitter.mjs.map +1 -0
  217. package/esm/ai/src/orchestrator/execution.mjs +395 -0
  218. package/esm/ai/src/orchestrator/execution.mjs.map +1 -0
  219. package/esm/ai/src/orchestrator/index.mjs +11 -0
  220. package/esm/ai/src/orchestrator/load.mjs +49 -0
  221. package/esm/ai/src/orchestrator/load.mjs.map +1 -0
  222. package/esm/ai/src/orchestrator/lock.mjs +75 -0
  223. package/esm/ai/src/orchestrator/lock.mjs.map +1 -0
  224. package/esm/ai/src/orchestrator/memory.mjs +141 -0
  225. package/esm/ai/src/orchestrator/memory.mjs.map +1 -0
  226. package/esm/ai/src/orchestrator/orchestrator-stream.mjs +98 -0
  227. package/esm/ai/src/orchestrator/orchestrator-stream.mjs.map +1 -0
  228. package/esm/ai/src/orchestrator/orchestrator.mjs +206 -0
  229. package/esm/ai/src/orchestrator/orchestrator.mjs.map +1 -0
  230. package/esm/ai/src/orchestrator/resume.mjs +74 -0
  231. package/esm/ai/src/orchestrator/resume.mjs.map +1 -0
  232. package/esm/ai/src/orchestrator/session-lock.mjs +83 -0
  233. package/esm/ai/src/orchestrator/session-lock.mjs.map +1 -0
  234. package/esm/ai/src/orchestrator/signature.mjs +120 -0
  235. package/esm/ai/src/orchestrator/signature.mjs.map +1 -0
  236. package/esm/ai/src/orchestrator/window.mjs +56 -0
  237. package/esm/ai/src/orchestrator/window.mjs.map +1 -0
  238. package/esm/ai/src/planner/dag-scheduler.mjs +97 -0
  239. package/esm/ai/src/planner/dag-scheduler.mjs.map +1 -0
  240. package/esm/ai/src/planner/index.mjs +6 -0
  241. package/esm/ai/src/planner/plan-prompt.mjs +31 -0
  242. package/esm/ai/src/planner/plan-prompt.mjs.map +1 -0
  243. package/esm/ai/src/planner/plan-schema.mjs +120 -0
  244. package/esm/ai/src/planner/plan-schema.mjs.map +1 -0
  245. package/esm/ai/src/planner/planner-run.mjs +614 -0
  246. package/esm/ai/src/planner/planner-run.mjs.map +1 -0
  247. package/esm/ai/src/planner/planner.mjs +120 -0
  248. package/esm/ai/src/planner/planner.mjs.map +1 -0
  249. package/esm/ai/src/planner/signature.mjs +27 -0
  250. package/esm/ai/src/planner/signature.mjs.map +1 -0
  251. package/esm/ai/src/prompt/errors.mjs +73 -0
  252. package/esm/ai/src/prompt/errors.mjs.map +1 -0
  253. package/esm/ai/src/prompt/index.mjs +4 -0
  254. package/esm/ai/src/prompt/prompt-langfuse-sync.mjs +104 -0
  255. package/esm/ai/src/prompt/prompt-langfuse-sync.mjs.map +1 -0
  256. package/esm/ai/src/prompt/prompt-validate.mjs +170 -0
  257. package/esm/ai/src/prompt/prompt-validate.mjs.map +1 -0
  258. package/esm/ai/src/prompt/prompt.mjs +218 -0
  259. package/esm/ai/src/prompt/prompt.mjs.map +1 -0
  260. package/esm/ai/src/prompts/index.mjs +3 -0
  261. package/esm/ai/src/prompts/prompts-manager.mjs +410 -0
  262. package/esm/ai/src/prompts/prompts-manager.mjs.map +1 -0
  263. package/esm/ai/src/prompts/prompts-validate.mjs +200 -0
  264. package/esm/ai/src/prompts/prompts-validate.mjs.map +1 -0
  265. package/esm/ai/src/rag/as-tool.mjs +48 -0
  266. package/esm/ai/src/rag/as-tool.mjs.map +1 -0
  267. package/esm/ai/src/rag/chunk/chunk.mjs +44 -0
  268. package/esm/ai/src/rag/chunk/chunk.mjs.map +1 -0
  269. package/esm/ai/src/rag/chunk/fixed.mjs +32 -0
  270. package/esm/ai/src/rag/chunk/fixed.mjs.map +1 -0
  271. package/esm/ai/src/rag/chunk/markdown.mjs +75 -0
  272. package/esm/ai/src/rag/chunk/markdown.mjs.map +1 -0
  273. package/esm/ai/src/rag/chunk/recursive.mjs +132 -0
  274. package/esm/ai/src/rag/chunk/recursive.mjs.map +1 -0
  275. package/esm/ai/src/rag/chunk/sentence.mjs +73 -0
  276. package/esm/ai/src/rag/chunk/sentence.mjs.map +1 -0
  277. package/esm/ai/src/rag/index.mjs +7 -0
  278. package/esm/ai/src/rag/rag.mjs +126 -0
  279. package/esm/ai/src/rag/rag.mjs.map +1 -0
  280. package/esm/ai/src/rag/rerank/keyword-reranker.mjs +58 -0
  281. package/esm/ai/src/rag/rerank/keyword-reranker.mjs.map +1 -0
  282. package/esm/ai/src/rag/rerank/llm-reranker.mjs +85 -0
  283. package/esm/ai/src/rag/rerank/llm-reranker.mjs.map +1 -0
  284. package/esm/ai/src/rag/retrieve.mjs +68 -0
  285. package/esm/ai/src/rag/retrieve.mjs.map +1 -0
  286. package/esm/ai/src/rag/store/cache-vector-store.mjs +48 -0
  287. package/esm/ai/src/rag/store/cache-vector-store.mjs.map +1 -0
  288. package/esm/ai/src/security/index.mjs +5 -0
  289. package/esm/ai/src/security/outbound-policy.mjs +187 -0
  290. package/esm/ai/src/security/outbound-policy.mjs.map +1 -0
  291. package/esm/ai/src/security/private-ip.mjs +48 -0
  292. package/esm/ai/src/security/private-ip.mjs.map +1 -0
  293. package/esm/ai/src/security/redact.mjs +60 -0
  294. package/esm/ai/src/security/redact.mjs.map +1 -0
  295. package/esm/ai/src/serve/serve.mjs +90 -0
  296. package/esm/ai/src/serve/serve.mjs.map +1 -0
  297. package/esm/ai/src/serve/sse.mjs +25 -0
  298. package/esm/ai/src/serve/sse.mjs.map +1 -0
  299. package/esm/ai/src/serve/stream-to-sse.mjs +37 -0
  300. package/esm/ai/src/serve/stream-to-sse.mjs.map +1 -0
  301. package/esm/ai/src/skills/catalog.mjs +140 -0
  302. package/esm/ai/src/skills/catalog.mjs.map +1 -0
  303. package/esm/ai/src/skills/index.mjs +11 -0
  304. package/esm/ai/src/skills/load-skill-tool.mjs +65 -0
  305. package/esm/ai/src/skills/load-skill-tool.mjs.map +1 -0
  306. package/esm/ai/src/skills/save-skill-tool.mjs +65 -0
  307. package/esm/ai/src/skills/save-skill-tool.mjs.map +1 -0
  308. package/esm/ai/src/skills/skills.mjs +109 -0
  309. package/esm/ai/src/skills/skills.mjs.map +1 -0
  310. package/esm/ai/src/skills/sources/directory-source.mjs +108 -0
  311. package/esm/ai/src/skills/sources/directory-source.mjs.map +1 -0
  312. package/esm/ai/src/skills/sources/index.mjs +27 -0
  313. package/esm/ai/src/skills/sources/index.mjs.map +1 -0
  314. package/esm/ai/src/skills/sources/parse-frontmatter.mjs +46 -0
  315. package/esm/ai/src/skills/sources/parse-frontmatter.mjs.map +1 -0
  316. package/esm/ai/src/skills/sources/store-source.mjs +15 -0
  317. package/esm/ai/src/skills/sources/store-source.mjs.map +1 -0
  318. package/esm/ai/src/skills/sources/url-source.mjs +117 -0
  319. package/esm/ai/src/skills/sources/url-source.mjs.map +1 -0
  320. package/esm/ai/src/snapshot/memory.mjs +81 -0
  321. package/esm/ai/src/snapshot/memory.mjs.map +1 -0
  322. package/esm/ai/src/snapshot/pg.mjs +146 -0
  323. package/esm/ai/src/snapshot/pg.mjs.map +1 -0
  324. package/esm/ai/src/snapshot/redis.mjs +101 -0
  325. package/esm/ai/src/snapshot/redis.mjs.map +1 -0
  326. package/esm/ai/src/supervisor/as-tool.mjs +74 -0
  327. package/esm/ai/src/supervisor/as-tool.mjs.map +1 -0
  328. package/esm/ai/src/supervisor/cancellation.mjs +22 -0
  329. package/esm/ai/src/supervisor/cancellation.mjs.map +1 -0
  330. package/esm/ai/src/supervisor/decide.mjs +272 -0
  331. package/esm/ai/src/supervisor/decide.mjs.map +1 -0
  332. package/esm/ai/src/supervisor/emitter.mjs +47 -0
  333. package/esm/ai/src/supervisor/emitter.mjs.map +1 -0
  334. package/esm/ai/src/supervisor/entries.mjs +206 -0
  335. package/esm/ai/src/supervisor/entries.mjs.map +1 -0
  336. package/esm/ai/src/supervisor/execution.mjs +1921 -0
  337. package/esm/ai/src/supervisor/execution.mjs.map +1 -0
  338. package/esm/ai/src/supervisor/fan-out.mjs +65 -0
  339. package/esm/ai/src/supervisor/fan-out.mjs.map +1 -0
  340. package/esm/ai/src/supervisor/index.mjs +14 -0
  341. package/esm/ai/src/supervisor/router-factory.mjs +141 -0
  342. package/esm/ai/src/supervisor/router-factory.mjs.map +1 -0
  343. package/esm/ai/src/supervisor/router-prompt.mjs +52 -0
  344. package/esm/ai/src/supervisor/router-prompt.mjs.map +1 -0
  345. package/esm/ai/src/supervisor/signature.mjs +89 -0
  346. package/esm/ai/src/supervisor/signature.mjs.map +1 -0
  347. package/esm/ai/src/supervisor/snapshot.mjs +69 -0
  348. package/esm/ai/src/supervisor/snapshot.mjs.map +1 -0
  349. package/esm/ai/src/supervisor/supervisor-stream.mjs +89 -0
  350. package/esm/ai/src/supervisor/supervisor-stream.mjs.map +1 -0
  351. package/esm/ai/src/supervisor/supervisor.mjs +144 -0
  352. package/esm/ai/src/supervisor/supervisor.mjs.map +1 -0
  353. package/esm/ai/src/system-prompt/index.mjs +6 -0
  354. package/esm/ai/src/system-prompt/instruction.mjs +57 -0
  355. package/esm/ai/src/system-prompt/instruction.mjs.map +1 -0
  356. package/esm/ai/src/system-prompt/persona.mjs +57 -0
  357. package/esm/ai/src/system-prompt/persona.mjs.map +1 -0
  358. package/esm/ai/src/system-prompt/render-placeholders.mjs +58 -0
  359. package/esm/ai/src/system-prompt/render-placeholders.mjs.map +1 -0
  360. package/esm/ai/src/system-prompt/system-prompt.mjs +267 -0
  361. package/esm/ai/src/system-prompt/system-prompt.mjs.map +1 -0
  362. package/esm/ai/src/team/gates.mjs +48 -0
  363. package/esm/ai/src/team/gates.mjs.map +1 -0
  364. package/esm/ai/src/team/index.mjs +3 -0
  365. package/esm/ai/src/team/team.mjs +94 -0
  366. package/esm/ai/src/team/team.mjs.map +1 -0
  367. package/esm/ai/src/tool/executable-as-tool.mjs +81 -0
  368. package/esm/ai/src/tool/executable-as-tool.mjs.map +1 -0
  369. package/esm/ai/src/tool/index.mjs +4 -0
  370. package/esm/ai/src/tool/tool.mjs +185 -0
  371. package/esm/ai/src/tool/tool.mjs.map +1 -0
  372. package/esm/ai/src/utils/compute-cost.mjs +112 -0
  373. package/esm/ai/src/utils/compute-cost.mjs.map +1 -0
  374. package/esm/ai/src/utils/extract-json-lenient.mjs +97 -0
  375. package/esm/ai/src/utils/extract-json-lenient.mjs.map +1 -0
  376. package/esm/ai/src/utils/extract-json-payload.mjs +39 -0
  377. package/esm/ai/src/utils/extract-json-payload.mjs.map +1 -0
  378. package/esm/ai/src/utils/generate-run-id.mjs +23 -0
  379. package/esm/ai/src/utils/generate-run-id.mjs.map +1 -0
  380. package/esm/ai/src/utils/index.mjs +12 -0
  381. package/esm/ai/src/utils/json-schema.mjs +89 -0
  382. package/esm/ai/src/utils/json-schema.mjs.map +1 -0
  383. package/esm/ai/src/utils/prepare-attachment-part.mjs +232 -0
  384. package/esm/ai/src/utils/prepare-attachment-part.mjs.map +1 -0
  385. package/esm/ai/src/utils/resolve-attachment.mjs +74 -0
  386. package/esm/ai/src/utils/resolve-attachment.mjs.map +1 -0
  387. package/esm/ai/src/utils/run-context.mjs +89 -0
  388. package/esm/ai/src/utils/run-context.mjs.map +1 -0
  389. package/esm/ai/src/utils/safe-json-parse.mjs +22 -0
  390. package/esm/ai/src/utils/safe-json-parse.mjs.map +1 -0
  391. package/esm/ai/src/utils/stamp-report-lineage.mjs +45 -0
  392. package/esm/ai/src/utils/stamp-report-lineage.mjs.map +1 -0
  393. package/esm/ai/src/vcr/cassette-io.mjs +57 -0
  394. package/esm/ai/src/vcr/cassette-io.mjs.map +1 -0
  395. package/esm/ai/src/vcr/errors.mjs +37 -0
  396. package/esm/ai/src/vcr/errors.mjs.map +1 -0
  397. package/esm/ai/src/vcr/hash-request.mjs +118 -0
  398. package/esm/ai/src/vcr/hash-request.mjs.map +1 -0
  399. package/esm/ai/src/vcr/index.mjs +5 -0
  400. package/esm/ai/src/vcr/vcr.mjs +248 -0
  401. package/esm/ai/src/vcr/vcr.mjs.map +1 -0
  402. package/esm/ai/src/workflow/as-tool.mjs +49 -0
  403. package/esm/ai/src/workflow/as-tool.mjs.map +1 -0
  404. package/esm/ai/src/workflow/cancellation.mjs +44 -0
  405. package/esm/ai/src/workflow/cancellation.mjs.map +1 -0
  406. package/esm/ai/src/workflow/emitter.mjs +40 -0
  407. package/esm/ai/src/workflow/emitter.mjs.map +1 -0
  408. package/esm/ai/src/workflow/engine.mjs +363 -0
  409. package/esm/ai/src/workflow/engine.mjs.map +1 -0
  410. package/esm/ai/src/workflow/index.mjs +5 -0
  411. package/esm/ai/src/workflow/retry.mjs +32 -0
  412. package/esm/ai/src/workflow/retry.mjs.map +1 -0
  413. package/esm/ai/src/workflow/router.mjs +56 -0
  414. package/esm/ai/src/workflow/router.mjs.map +1 -0
  415. package/esm/ai/src/workflow/run-scoped-emitter.mjs +32 -0
  416. package/esm/ai/src/workflow/run-scoped-emitter.mjs.map +1 -0
  417. package/esm/ai/src/workflow/signature.mjs +34 -0
  418. package/esm/ai/src/workflow/signature.mjs.map +1 -0
  419. package/esm/ai/src/workflow/snapshot.mjs +77 -0
  420. package/esm/ai/src/workflow/snapshot.mjs.map +1 -0
  421. package/esm/ai/src/workflow/state.mjs +37 -0
  422. package/esm/ai/src/workflow/state.mjs.map +1 -0
  423. package/esm/ai/src/workflow/step-runner.mjs +370 -0
  424. package/esm/ai/src/workflow/step-runner.mjs.map +1 -0
  425. package/esm/ai/src/workflow/step.mjs +37 -0
  426. package/esm/ai/src/workflow/step.mjs.map +1 -0
  427. package/esm/ai/src/workflow/workflow.mjs +122 -0
  428. package/esm/ai/src/workflow/workflow.mjs.map +1 -0
  429. package/esm/ai-openai/src/embedder.mjs +4 -0
  430. package/esm/ai-openai/src/index.mjs +4 -0
  431. package/esm/ai-openai/src/model.mjs +5 -0
  432. package/esm/ai-openai/src/sdk.mjs +6 -0
  433. package/esm/ai-openai/src/utils/index.mjs +4 -0
  434. package/esm/ai-openai/src/utils/to-openai-tools.mjs +3 -0
  435. package/esm/ai-openai/src/utils/wrap-openai-error.mjs +4 -0
  436. package/esm/cli/commands/dev-server.command.mjs +1 -1
  437. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  438. package/esm/cli/commands/generate/templates/stubs.mjs +3 -4
  439. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  440. package/esm/connectors/ai-connector.d.mts +43 -0
  441. package/esm/connectors/ai-connector.d.mts.map +1 -0
  442. package/esm/connectors/ai-connector.mjs +56 -0
  443. package/esm/connectors/ai-connector.mjs.map +1 -0
  444. package/esm/connectors/cache-connector.d.mts +5 -0
  445. package/esm/connectors/cache-connector.d.mts.map +1 -1
  446. package/esm/connectors/cache-connector.mjs +7 -0
  447. package/esm/connectors/cache-connector.mjs.map +1 -1
  448. package/esm/connectors/connectors-manager.d.mts +6 -2
  449. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  450. package/esm/connectors/connectors-manager.mjs +8 -2
  451. package/esm/connectors/connectors-manager.mjs.map +1 -1
  452. package/esm/connectors/http-connector.mjs.map +1 -1
  453. package/esm/connectors/index.d.mts +1 -0
  454. package/esm/connectors/index.mjs +1 -0
  455. package/esm/connectors/socket-connector.d.mts +16 -1
  456. package/esm/connectors/socket-connector.d.mts.map +1 -1
  457. package/esm/connectors/socket-connector.mjs +28 -5
  458. package/esm/connectors/socket-connector.mjs.map +1 -1
  459. package/esm/connectors/storage.connector.d.mts +7 -0
  460. package/esm/connectors/storage.connector.d.mts.map +1 -1
  461. package/esm/connectors/storage.connector.mjs +7 -0
  462. package/esm/connectors/storage.connector.mjs.map +1 -1
  463. package/esm/connectors/types.d.mts +3 -2
  464. package/esm/connectors/types.d.mts.map +1 -1
  465. package/esm/connectors/types.mjs +1 -0
  466. package/esm/connectors/types.mjs.map +1 -1
  467. package/esm/dev-server/development-server.mjs +2 -14
  468. package/esm/dev-server/development-server.mjs.map +1 -1
  469. package/esm/dev-server/file-event-handler.mjs +15 -3
  470. package/esm/dev-server/file-event-handler.mjs.map +1 -1
  471. package/esm/generations/add-command.action.mjs +61 -12
  472. package/esm/generations/add-command.action.mjs.map +1 -1
  473. package/esm/generations/stubs.mjs +31 -1
  474. package/esm/generations/stubs.mjs.map +1 -1
  475. package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
  476. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  477. package/esm/http/middleware/cache-response-middleware.mjs +15 -6
  478. package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
  479. package/esm/http/middleware/concurrency-limit.middleware.mjs +2 -0
  480. package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
  481. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  482. package/esm/http/middleware/idempotency.middleware.mjs +4 -1
  483. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  484. package/esm/http/middleware/maintenance.middleware.mjs +2 -1
  485. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  486. package/esm/http/request.d.mts +9 -2
  487. package/esm/http/request.d.mts.map +1 -1
  488. package/esm/http/request.mjs +15 -3
  489. package/esm/http/request.mjs.map +1 -1
  490. package/esm/http/response.d.mts +12 -0
  491. package/esm/http/response.d.mts.map +1 -1
  492. package/esm/http/response.mjs +19 -2
  493. package/esm/http/response.mjs.map +1 -1
  494. package/esm/http/server.d.mts.map +1 -1
  495. package/esm/http/server.mjs +1 -1
  496. package/esm/http/server.mjs.map +1 -1
  497. package/esm/index.d.mts +6 -2
  498. package/esm/index.mjs +5 -1
  499. package/esm/node_modules/langfuse/lib/index.mjs +1827 -0
  500. package/esm/node_modules/langfuse/lib/index.mjs.map +1 -0
  501. package/esm/node_modules/langfuse-core/lib/index.mjs +1770 -0
  502. package/esm/node_modules/langfuse-core/lib/index.mjs.map +1 -0
  503. package/esm/node_modules/mustache/mustache.mjs +587 -0
  504. package/esm/node_modules/mustache/mustache.mjs.map +1 -0
  505. package/esm/node_modules/openai/_vendor/partial-json-parser/parser.mjs +180 -0
  506. package/esm/node_modules/openai/_vendor/partial-json-parser/parser.mjs.map +1 -0
  507. package/esm/node_modules/openai/auth/workload-identity-auth.mjs +80 -0
  508. package/esm/node_modules/openai/auth/workload-identity-auth.mjs.map +1 -0
  509. package/esm/node_modules/openai/azure.mjs +82 -0
  510. package/esm/node_modules/openai/azure.mjs.map +1 -0
  511. package/esm/node_modules/openai/client.mjs +638 -0
  512. package/esm/node_modules/openai/client.mjs.map +1 -0
  513. package/esm/node_modules/openai/core/api-promise.mjs +75 -0
  514. package/esm/node_modules/openai/core/api-promise.mjs.map +1 -0
  515. package/esm/node_modules/openai/core/error.mjs +110 -0
  516. package/esm/node_modules/openai/core/error.mjs.map +1 -0
  517. package/esm/node_modules/openai/core/pagination.mjs +160 -0
  518. package/esm/node_modules/openai/core/pagination.mjs.map +1 -0
  519. package/esm/node_modules/openai/core/resource.mjs +10 -0
  520. package/esm/node_modules/openai/core/resource.mjs.map +1 -0
  521. package/esm/node_modules/openai/core/streaming.mjs +238 -0
  522. package/esm/node_modules/openai/core/streaming.mjs.map +1 -0
  523. package/esm/node_modules/openai/index.mjs +8 -0
  524. package/esm/node_modules/openai/internal/decoders/line.mjs +91 -0
  525. package/esm/node_modules/openai/internal/decoders/line.mjs.map +1 -0
  526. package/esm/node_modules/openai/internal/detect-platform.mjs +123 -0
  527. package/esm/node_modules/openai/internal/detect-platform.mjs.map +1 -0
  528. package/esm/node_modules/openai/internal/errors.mjs +26 -0
  529. package/esm/node_modules/openai/internal/errors.mjs.map +1 -0
  530. package/esm/node_modules/openai/internal/headers.mjs +65 -0
  531. package/esm/node_modules/openai/internal/headers.mjs.map +1 -0
  532. package/esm/node_modules/openai/internal/parse.mjs +41 -0
  533. package/esm/node_modules/openai/internal/parse.mjs.map +1 -0
  534. package/esm/node_modules/openai/internal/qs/formats.mjs +12 -0
  535. package/esm/node_modules/openai/internal/qs/formats.mjs.map +1 -0
  536. package/esm/node_modules/openai/internal/qs/stringify.mjs +179 -0
  537. package/esm/node_modules/openai/internal/qs/stringify.mjs.map +1 -0
  538. package/esm/node_modules/openai/internal/qs/utils.mjs +65 -0
  539. package/esm/node_modules/openai/internal/qs/utils.mjs.map +1 -0
  540. package/esm/node_modules/openai/internal/request-options.mjs +11 -0
  541. package/esm/node_modules/openai/internal/request-options.mjs.map +1 -0
  542. package/esm/node_modules/openai/internal/shims.mjs +77 -0
  543. package/esm/node_modules/openai/internal/shims.mjs.map +1 -0
  544. package/esm/node_modules/openai/internal/to-file.mjs +63 -0
  545. package/esm/node_modules/openai/internal/to-file.mjs.map +1 -0
  546. package/esm/node_modules/openai/internal/tslib.mjs +16 -0
  547. package/esm/node_modules/openai/internal/tslib.mjs.map +1 -0
  548. package/esm/node_modules/openai/internal/uploads.mjs +94 -0
  549. package/esm/node_modules/openai/internal/uploads.mjs.map +1 -0
  550. package/esm/node_modules/openai/internal/utils/base64.mjs +22 -0
  551. package/esm/node_modules/openai/internal/utils/base64.mjs.map +1 -0
  552. package/esm/node_modules/openai/internal/utils/bytes.mjs +26 -0
  553. package/esm/node_modules/openai/internal/utils/bytes.mjs.map +1 -0
  554. package/esm/node_modules/openai/internal/utils/env.mjs +16 -0
  555. package/esm/node_modules/openai/internal/utils/env.mjs.map +1 -0
  556. package/esm/node_modules/openai/internal/utils/log.mjs +58 -0
  557. package/esm/node_modules/openai/internal/utils/log.mjs.map +1 -0
  558. package/esm/node_modules/openai/internal/utils/path.mjs +62 -0
  559. package/esm/node_modules/openai/internal/utils/path.mjs.map +1 -0
  560. package/esm/node_modules/openai/internal/utils/query.mjs +10 -0
  561. package/esm/node_modules/openai/internal/utils/query.mjs.map +1 -0
  562. package/esm/node_modules/openai/internal/utils/sleep.mjs +6 -0
  563. package/esm/node_modules/openai/internal/utils/sleep.mjs.map +1 -0
  564. package/esm/node_modules/openai/internal/utils/uuid.mjs +18 -0
  565. package/esm/node_modules/openai/internal/utils/uuid.mjs.map +1 -0
  566. package/esm/node_modules/openai/internal/utils/values.mjs +41 -0
  567. package/esm/node_modules/openai/internal/utils/values.mjs.map +1 -0
  568. package/esm/node_modules/openai/lib/AbstractChatCompletionRunner.mjs +247 -0
  569. package/esm/node_modules/openai/lib/AbstractChatCompletionRunner.mjs.map +1 -0
  570. package/esm/node_modules/openai/lib/AssistantStream.mjs +472 -0
  571. package/esm/node_modules/openai/lib/AssistantStream.mjs.map +1 -0
  572. package/esm/node_modules/openai/lib/ChatCompletionRunner.mjs +26 -0
  573. package/esm/node_modules/openai/lib/ChatCompletionRunner.mjs.map +1 -0
  574. package/esm/node_modules/openai/lib/ChatCompletionStream.mjs +423 -0
  575. package/esm/node_modules/openai/lib/ChatCompletionStream.mjs.map +1 -0
  576. package/esm/node_modules/openai/lib/ChatCompletionStreamingRunner.mjs +26 -0
  577. package/esm/node_modules/openai/lib/ChatCompletionStreamingRunner.mjs.map +1 -0
  578. package/esm/node_modules/openai/lib/EventStream.mjs +163 -0
  579. package/esm/node_modules/openai/lib/EventStream.mjs.map +1 -0
  580. package/esm/node_modules/openai/lib/ResponsesParser.mjs +94 -0
  581. package/esm/node_modules/openai/lib/ResponsesParser.mjs.map +1 -0
  582. package/esm/node_modules/openai/lib/RunnableFunction.mjs +8 -0
  583. package/esm/node_modules/openai/lib/RunnableFunction.mjs.map +1 -0
  584. package/esm/node_modules/openai/lib/Util.mjs +19 -0
  585. package/esm/node_modules/openai/lib/Util.mjs.map +1 -0
  586. package/esm/node_modules/openai/lib/chatCompletionUtils.mjs +11 -0
  587. package/esm/node_modules/openai/lib/chatCompletionUtils.mjs.map +1 -0
  588. package/esm/node_modules/openai/lib/parser.mjs +88 -0
  589. package/esm/node_modules/openai/lib/parser.mjs.map +1 -0
  590. package/esm/node_modules/openai/lib/responses/ResponseStream.mjs +231 -0
  591. package/esm/node_modules/openai/lib/responses/ResponseStream.mjs.map +1 -0
  592. package/esm/node_modules/openai/resources/admin/admin.mjs +15 -0
  593. package/esm/node_modules/openai/resources/admin/admin.mjs.map +1 -0
  594. package/esm/node_modules/openai/resources/admin/organization/admin-api-keys.mjs +81 -0
  595. package/esm/node_modules/openai/resources/admin/organization/admin-api-keys.mjs.map +1 -0
  596. package/esm/node_modules/openai/resources/admin/organization/audit-logs.mjs +31 -0
  597. package/esm/node_modules/openai/resources/admin/organization/audit-logs.mjs.map +1 -0
  598. package/esm/node_modules/openai/resources/admin/organization/certificates.mjs +153 -0
  599. package/esm/node_modules/openai/resources/admin/organization/certificates.mjs.map +1 -0
  600. package/esm/node_modules/openai/resources/admin/organization/data-retention.mjs +42 -0
  601. package/esm/node_modules/openai/resources/admin/organization/data-retention.mjs.map +1 -0
  602. package/esm/node_modules/openai/resources/admin/organization/groups/groups.mjs +106 -0
  603. package/esm/node_modules/openai/resources/admin/organization/groups/groups.mjs.map +1 -0
  604. package/esm/node_modules/openai/resources/admin/organization/groups/roles.mjs +88 -0
  605. package/esm/node_modules/openai/resources/admin/organization/groups/roles.mjs.map +1 -0
  606. package/esm/node_modules/openai/resources/admin/organization/groups/users.mjs +88 -0
  607. package/esm/node_modules/openai/resources/admin/organization/groups/users.mjs.map +1 -0
  608. package/esm/node_modules/openai/resources/admin/organization/invites.mjs +83 -0
  609. package/esm/node_modules/openai/resources/admin/organization/invites.mjs.map +1 -0
  610. package/esm/node_modules/openai/resources/admin/organization/organization.mjs +45 -0
  611. package/esm/node_modules/openai/resources/admin/organization/organization.mjs.map +1 -0
  612. package/esm/node_modules/openai/resources/admin/organization/projects/api-keys.mjs +72 -0
  613. package/esm/node_modules/openai/resources/admin/organization/projects/api-keys.mjs.map +1 -0
  614. package/esm/node_modules/openai/resources/admin/organization/projects/certificates.mjs +78 -0
  615. package/esm/node_modules/openai/resources/admin/organization/projects/certificates.mjs.map +1 -0
  616. package/esm/node_modules/openai/resources/admin/organization/projects/data-retention.mjs +46 -0
  617. package/esm/node_modules/openai/resources/admin/organization/projects/data-retention.mjs.map +1 -0
  618. package/esm/node_modules/openai/resources/admin/organization/projects/groups/groups.mjs +95 -0
  619. package/esm/node_modules/openai/resources/admin/organization/projects/groups/groups.mjs.map +1 -0
  620. package/esm/node_modules/openai/resources/admin/organization/projects/groups/roles.mjs +91 -0
  621. package/esm/node_modules/openai/resources/admin/organization/projects/groups/roles.mjs.map +1 -0
  622. package/esm/node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs +45 -0
  623. package/esm/node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs.map +1 -0
  624. package/esm/node_modules/openai/resources/admin/organization/projects/model-permissions.mjs +63 -0
  625. package/esm/node_modules/openai/resources/admin/organization/projects/model-permissions.mjs.map +1 -0
  626. package/esm/node_modules/openai/resources/admin/organization/projects/projects.mjs +137 -0
  627. package/esm/node_modules/openai/resources/admin/organization/projects/projects.mjs.map +1 -0
  628. package/esm/node_modules/openai/resources/admin/organization/projects/rate-limits.mjs +51 -0
  629. package/esm/node_modules/openai/resources/admin/organization/projects/rate-limits.mjs.map +1 -0
  630. package/esm/node_modules/openai/resources/admin/organization/projects/roles.mjs +108 -0
  631. package/esm/node_modules/openai/resources/admin/organization/projects/roles.mjs.map +1 -0
  632. package/esm/node_modules/openai/resources/admin/organization/projects/service-accounts.mjs +112 -0
  633. package/esm/node_modules/openai/resources/admin/organization/projects/service-accounts.mjs.map +1 -0
  634. package/esm/node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs +106 -0
  635. package/esm/node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs.map +1 -0
  636. package/esm/node_modules/openai/resources/admin/organization/projects/users/roles.mjs +91 -0
  637. package/esm/node_modules/openai/resources/admin/organization/projects/users/roles.mjs.map +1 -0
  638. package/esm/node_modules/openai/resources/admin/organization/projects/users/users.mjs +118 -0
  639. package/esm/node_modules/openai/resources/admin/organization/projects/users/users.mjs.map +1 -0
  640. package/esm/node_modules/openai/resources/admin/organization/roles.mjs +96 -0
  641. package/esm/node_modules/openai/resources/admin/organization/roles.mjs.map +1 -0
  642. package/esm/node_modules/openai/resources/admin/organization/spend-alerts.mjs +97 -0
  643. package/esm/node_modules/openai/resources/admin/organization/spend-alerts.mjs.map +1 -0
  644. package/esm/node_modules/openai/resources/admin/organization/usage.mjs +207 -0
  645. package/esm/node_modules/openai/resources/admin/organization/usage.mjs.map +1 -0
  646. package/esm/node_modules/openai/resources/admin/organization/users/roles.mjs +88 -0
  647. package/esm/node_modules/openai/resources/admin/organization/users/roles.mjs.map +1 -0
  648. package/esm/node_modules/openai/resources/admin/organization/users/users.mjs +82 -0
  649. package/esm/node_modules/openai/resources/admin/organization/users/users.mjs.map +1 -0
  650. package/esm/node_modules/openai/resources/audio/audio.mjs +21 -0
  651. package/esm/node_modules/openai/resources/audio/audio.mjs.map +1 -0
  652. package/esm/node_modules/openai/resources/audio/speech.mjs +39 -0
  653. package/esm/node_modules/openai/resources/audio/speech.mjs.map +1 -0
  654. package/esm/node_modules/openai/resources/audio/transcriptions.mjs +22 -0
  655. package/esm/node_modules/openai/resources/audio/transcriptions.mjs.map +1 -0
  656. package/esm/node_modules/openai/resources/audio/translations.mjs +21 -0
  657. package/esm/node_modules/openai/resources/audio/translations.mjs.map +1 -0
  658. package/esm/node_modules/openai/resources/batches.mjs +54 -0
  659. package/esm/node_modules/openai/resources/batches.mjs.map +1 -0
  660. package/esm/node_modules/openai/resources/beta/assistants.mjs +78 -0
  661. package/esm/node_modules/openai/resources/beta/assistants.mjs.map +1 -0
  662. package/esm/node_modules/openai/resources/beta/beta.mjs +24 -0
  663. package/esm/node_modules/openai/resources/beta/beta.mjs.map +1 -0
  664. package/esm/node_modules/openai/resources/beta/chatkit/chatkit.mjs +18 -0
  665. package/esm/node_modules/openai/resources/beta/chatkit/chatkit.mjs.map +1 -0
  666. package/esm/node_modules/openai/resources/beta/chatkit/sessions.mjs +49 -0
  667. package/esm/node_modules/openai/resources/beta/chatkit/sessions.mjs.map +1 -0
  668. package/esm/node_modules/openai/resources/beta/chatkit/threads.mjs +85 -0
  669. package/esm/node_modules/openai/resources/beta/chatkit/threads.mjs.map +1 -0
  670. package/esm/node_modules/openai/resources/beta/realtime/realtime.mjs +21 -0
  671. package/esm/node_modules/openai/resources/beta/realtime/realtime.mjs.map +1 -0
  672. package/esm/node_modules/openai/resources/beta/realtime/sessions.mjs +33 -0
  673. package/esm/node_modules/openai/resources/beta/realtime/sessions.mjs.map +1 -0
  674. package/esm/node_modules/openai/resources/beta/realtime/transcription-sessions.mjs +33 -0
  675. package/esm/node_modules/openai/resources/beta/realtime/transcription-sessions.mjs.map +1 -0
  676. package/esm/node_modules/openai/resources/beta/threads/messages.mjs +83 -0
  677. package/esm/node_modules/openai/resources/beta/threads/messages.mjs.map +1 -0
  678. package/esm/node_modules/openai/resources/beta/threads/runs/runs.mjs +183 -0
  679. package/esm/node_modules/openai/resources/beta/threads/runs/runs.mjs.map +1 -0
  680. package/esm/node_modules/openai/resources/beta/threads/runs/steps.mjs +45 -0
  681. package/esm/node_modules/openai/resources/beta/threads/runs/steps.mjs.map +1 -0
  682. package/esm/node_modules/openai/resources/beta/threads/threads.mjs +101 -0
  683. package/esm/node_modules/openai/resources/beta/threads/threads.mjs.map +1 -0
  684. package/esm/node_modules/openai/resources/chat/chat.mjs +15 -0
  685. package/esm/node_modules/openai/resources/chat/chat.mjs.map +1 -0
  686. package/esm/node_modules/openai/resources/chat/completions/completions.mjs +123 -0
  687. package/esm/node_modules/openai/resources/chat/completions/completions.mjs.map +1 -0
  688. package/esm/node_modules/openai/resources/chat/completions/index.mjs +7 -0
  689. package/esm/node_modules/openai/resources/chat/completions/messages.mjs +35 -0
  690. package/esm/node_modules/openai/resources/chat/completions/messages.mjs.map +1 -0
  691. package/esm/node_modules/openai/resources/chat/index.mjs +5 -0
  692. package/esm/node_modules/openai/resources/completions.mjs +20 -0
  693. package/esm/node_modules/openai/resources/completions.mjs.map +1 -0
  694. package/esm/node_modules/openai/resources/containers/containers.mjs +57 -0
  695. package/esm/node_modules/openai/resources/containers/containers.mjs.map +1 -0
  696. package/esm/node_modules/openai/resources/containers/files/content.mjs +23 -0
  697. package/esm/node_modules/openai/resources/containers/files/content.mjs.map +1 -0
  698. package/esm/node_modules/openai/resources/containers/files/files.mjs +63 -0
  699. package/esm/node_modules/openai/resources/containers/files/files.mjs.map +1 -0
  700. package/esm/node_modules/openai/resources/conversations/conversations.mjs +57 -0
  701. package/esm/node_modules/openai/resources/conversations/conversations.mjs.map +1 -0
  702. package/esm/node_modules/openai/resources/conversations/items.mjs +57 -0
  703. package/esm/node_modules/openai/resources/conversations/items.mjs.map +1 -0
  704. package/esm/node_modules/openai/resources/embeddings.mjs +48 -0
  705. package/esm/node_modules/openai/resources/embeddings.mjs.map +1 -0
  706. package/esm/node_modules/openai/resources/evals/evals.mjs +73 -0
  707. package/esm/node_modules/openai/resources/evals/evals.mjs.map +1 -0
  708. package/esm/node_modules/openai/resources/evals/runs/output-items.mjs +35 -0
  709. package/esm/node_modules/openai/resources/evals/runs/output-items.mjs.map +1 -0
  710. package/esm/node_modules/openai/resources/evals/runs/runs.mjs +72 -0
  711. package/esm/node_modules/openai/resources/evals/runs/runs.mjs.map +1 -0
  712. package/esm/node_modules/openai/resources/files.mjs +111 -0
  713. package/esm/node_modules/openai/resources/files.mjs.map +1 -0
  714. package/esm/node_modules/openai/resources/fine-tuning/alpha/alpha.mjs +15 -0
  715. package/esm/node_modules/openai/resources/fine-tuning/alpha/alpha.mjs.map +1 -0
  716. package/esm/node_modules/openai/resources/fine-tuning/alpha/graders.mjs +60 -0
  717. package/esm/node_modules/openai/resources/fine-tuning/alpha/graders.mjs.map +1 -0
  718. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs +15 -0
  719. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs.map +1 -0
  720. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs +102 -0
  721. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs.map +1 -0
  722. package/esm/node_modules/openai/resources/fine-tuning/fine-tuning.mjs +24 -0
  723. package/esm/node_modules/openai/resources/fine-tuning/fine-tuning.mjs.map +1 -0
  724. package/esm/node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs +34 -0
  725. package/esm/node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs.map +1 -0
  726. package/esm/node_modules/openai/resources/fine-tuning/jobs/jobs.mjs +148 -0
  727. package/esm/node_modules/openai/resources/fine-tuning/jobs/jobs.mjs.map +1 -0
  728. package/esm/node_modules/openai/resources/fine-tuning/methods.mjs +8 -0
  729. package/esm/node_modules/openai/resources/fine-tuning/methods.mjs.map +1 -0
  730. package/esm/node_modules/openai/resources/graders/grader-models.mjs +8 -0
  731. package/esm/node_modules/openai/resources/graders/grader-models.mjs.map +1 -0
  732. package/esm/node_modules/openai/resources/graders/graders.mjs +15 -0
  733. package/esm/node_modules/openai/resources/graders/graders.mjs.map +1 -0
  734. package/esm/node_modules/openai/resources/images.mjs +46 -0
  735. package/esm/node_modules/openai/resources/images.mjs.map +1 -0
  736. package/esm/node_modules/openai/resources/index.mjs +27 -0
  737. package/esm/node_modules/openai/resources/models.mjs +44 -0
  738. package/esm/node_modules/openai/resources/models.mjs.map +1 -0
  739. package/esm/node_modules/openai/resources/moderations.mjs +23 -0
  740. package/esm/node_modules/openai/resources/moderations.mjs.map +1 -0
  741. package/esm/node_modules/openai/resources/realtime/calls.mjs +79 -0
  742. package/esm/node_modules/openai/resources/realtime/calls.mjs.map +1 -0
  743. package/esm/node_modules/openai/resources/realtime/client-secrets.mjs +39 -0
  744. package/esm/node_modules/openai/resources/realtime/client-secrets.mjs.map +1 -0
  745. package/esm/node_modules/openai/resources/realtime/realtime.mjs +18 -0
  746. package/esm/node_modules/openai/resources/realtime/realtime.mjs.map +1 -0
  747. package/esm/node_modules/openai/resources/responses/input-items.mjs +31 -0
  748. package/esm/node_modules/openai/resources/responses/input-items.mjs.map +1 -0
  749. package/esm/node_modules/openai/resources/responses/input-tokens.mjs +27 -0
  750. package/esm/node_modules/openai/resources/responses/input-tokens.mjs.map +1 -0
  751. package/esm/node_modules/openai/resources/responses/responses.mjs +110 -0
  752. package/esm/node_modules/openai/resources/responses/responses.mjs.map +1 -0
  753. package/esm/node_modules/openai/resources/skills/content.mjs +22 -0
  754. package/esm/node_modules/openai/resources/skills/content.mjs.map +1 -0
  755. package/esm/node_modules/openai/resources/skills/skills.mjs +69 -0
  756. package/esm/node_modules/openai/resources/skills/skills.mjs.map +1 -0
  757. package/esm/node_modules/openai/resources/skills/versions/content.mjs +23 -0
  758. package/esm/node_modules/openai/resources/skills/versions/content.mjs.map +1 -0
  759. package/esm/node_modules/openai/resources/skills/versions/versions.mjs +58 -0
  760. package/esm/node_modules/openai/resources/skills/versions/versions.mjs.map +1 -0
  761. package/esm/node_modules/openai/resources/uploads/parts.mjs +34 -0
  762. package/esm/node_modules/openai/resources/uploads/parts.mjs.map +1 -0
  763. package/esm/node_modules/openai/resources/uploads/uploads.mjs +84 -0
  764. package/esm/node_modules/openai/resources/uploads/uploads.mjs.map +1 -0
  765. package/esm/node_modules/openai/resources/vector-stores/file-batches.mjs +126 -0
  766. package/esm/node_modules/openai/resources/vector-stores/file-batches.mjs.map +1 -0
  767. package/esm/node_modules/openai/resources/vector-stores/files.mjs +147 -0
  768. package/esm/node_modules/openai/resources/vector-stores/files.mjs.map +1 -0
  769. package/esm/node_modules/openai/resources/vector-stores/vector-stores.mjs +87 -0
  770. package/esm/node_modules/openai/resources/vector-stores/vector-stores.mjs.map +1 -0
  771. package/esm/node_modules/openai/resources/videos.mjs +115 -0
  772. package/esm/node_modules/openai/resources/videos.mjs.map +1 -0
  773. package/esm/node_modules/openai/resources/webhooks/index.mjs +3 -0
  774. package/esm/node_modules/openai/resources/webhooks/webhooks.mjs +69 -0
  775. package/esm/node_modules/openai/resources/webhooks/webhooks.mjs.map +1 -0
  776. package/esm/node_modules/openai/resources/webhooks.mjs +4 -0
  777. package/esm/node_modules/openai/streaming.mjs +3 -0
  778. package/esm/node_modules/openai/version.mjs +6 -0
  779. package/esm/node_modules/openai/version.mjs.map +1 -0
  780. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +9 -0
  781. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  782. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +32 -5
  783. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
  784. package/esm/repositories/adapters/cascade/filter-applicator.mjs +17 -3
  785. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  786. package/esm/repositories/repository.manager.d.mts +11 -1
  787. package/esm/repositories/repository.manager.d.mts.map +1 -1
  788. package/esm/repositories/repository.manager.mjs +79 -25
  789. package/esm/repositories/repository.manager.mjs.map +1 -1
  790. package/esm/router/route-registry.mjs +19 -10
  791. package/esm/router/route-registry.mjs.map +1 -1
  792. package/esm/router/router.d.mts.map +1 -1
  793. package/esm/router/router.mjs +7 -4
  794. package/esm/router/router.mjs.map +1 -1
  795. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  796. package/esm/storage/drivers/cloud-driver.mjs +48 -12
  797. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  798. package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
  799. package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
  800. package/esm/storage/drivers/local-driver.d.mts +8 -0
  801. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  802. package/esm/storage/drivers/local-driver.mjs +19 -4
  803. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  804. package/esm/storage/drivers/r2-driver.mjs +1 -1
  805. package/esm/storage/drivers/r2-driver.mjs.map +1 -1
  806. package/esm/storage/drivers/s3-driver.mjs +1 -1
  807. package/esm/storage/drivers/s3-driver.mjs.map +1 -1
  808. package/esm/storage/index.d.mts +4 -1
  809. package/esm/storage/index.mjs +3 -0
  810. package/esm/storage/scoped-storage.d.mts +8 -4
  811. package/esm/storage/scoped-storage.d.mts.map +1 -1
  812. package/esm/storage/scoped-storage.mjs +21 -6
  813. package/esm/storage/scoped-storage.mjs.map +1 -1
  814. package/esm/storage/storage.d.mts +12 -4
  815. package/esm/storage/storage.d.mts.map +1 -1
  816. package/esm/storage/storage.mjs +23 -9
  817. package/esm/storage/storage.mjs.map +1 -1
  818. package/esm/storage/types.d.mts +33 -5
  819. package/esm/storage/types.d.mts.map +1 -1
  820. package/esm/storage/utils/contain-path.d.mts +23 -0
  821. package/esm/storage/utils/contain-path.d.mts.map +1 -0
  822. package/esm/storage/utils/contain-path.mjs +35 -0
  823. package/esm/storage/utils/contain-path.mjs.map +1 -0
  824. package/esm/storage/utils/safe-fetch.d.mts +68 -0
  825. package/esm/storage/utils/safe-fetch.d.mts.map +1 -0
  826. package/esm/storage/utils/safe-fetch.mjs +205 -0
  827. package/esm/storage/utils/safe-fetch.mjs.map +1 -0
  828. package/esm/storage/utils/storage-error.d.mts +35 -0
  829. package/esm/storage/utils/storage-error.d.mts.map +1 -0
  830. package/esm/storage/utils/storage-error.mjs +17 -0
  831. package/esm/storage/utils/storage-error.mjs.map +1 -0
  832. package/esm/use-cases/use-case-pipeline.mjs +4 -1
  833. package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
  834. package/esm/use-cases/use-case.mjs +12 -4
  835. package/esm/use-cases/use-case.mjs.map +1 -1
  836. package/esm/use-cases/use-cases-registry.d.mts +12 -4
  837. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  838. package/esm/use-cases/use-cases-registry.mjs +13 -3
  839. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  840. package/esm/utils/npm-registry.d.mts +1 -1
  841. package/esm/utils/npm-registry.mjs +2 -2
  842. package/esm/utils/npm-registry.mjs.map +1 -1
  843. package/llms-full.txt +29 -1
  844. package/package.json +9 -9
  845. package/skills/add-connector/SKILL.md +6 -1
  846. package/skills/configure-app/SKILL.md +23 -0
@@ -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,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,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,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"}
@@ -0,0 +1,48 @@
1
+ //#region ../@warlock.js/ai/src/rag/store/cache-vector-store.ts
2
+ /**
3
+ * Adapt any `@warlock.js/cache` `CacheDriver` to the {@link VectorStore}
4
+ * narrowing the RAG pipeline depends on. The cache driver IS the vector
5
+ * store — exactly as `SemanticMemory` and `semanticCache` already use it:
6
+ *
7
+ * - `upsert` → `driver.set(key, value, { vector, tags })`
8
+ * - `query` → `driver.similar<T>(vector, { topK, threshold, tags })`
9
+ * - `removeNamespace` → `driver.removeNamespace(namespace)`
10
+ *
11
+ * Drivers without similarity support throw `CacheUnsupportedError` from
12
+ * `set({ vector })` / `similar()`; the error surfaces unchanged so the
13
+ * caller sees the cache layer's own message (pointing at the `pg` /
14
+ * `redis` drivers for production-scale similarity).
15
+ *
16
+ * @example
17
+ * const store = cacheVectorStore(new MemoryCacheDriver());
18
+ * await store.upsert("ai.rag.docs.guide.0", { text: "…" }, vector);
19
+ * const hits = await store.query(queryVector, { topK: 5, threshold: 0.5 });
20
+ */
21
+ function cacheVectorStore(driver) {
22
+ return {
23
+ async upsert(key, value, vector, tags) {
24
+ await driver.set(key, value, tags && tags.length > 0 ? {
25
+ vector,
26
+ tags
27
+ } : { vector });
28
+ },
29
+ async query(vector, options) {
30
+ return (await driver.similar(vector, {
31
+ topK: options.topK,
32
+ threshold: options.threshold,
33
+ tags: options.tags
34
+ })).map((hit) => ({
35
+ key: hit.key,
36
+ value: hit.value,
37
+ score: hit.score
38
+ }));
39
+ },
40
+ async removeNamespace(namespace) {
41
+ await driver.removeNamespace(namespace);
42
+ }
43
+ };
44
+ }
45
+
46
+ //#endregion
47
+ export { cacheVectorStore };
48
+ //# sourceMappingURL=cache-vector-store.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache-vector-store.mjs","names":[],"sources":["../../../../../../../../../../@warlock.js/ai/src/rag/store/cache-vector-store.ts"],"sourcesContent":["import type { CacheDriver } from \"@warlock.js/cache\";\nimport type { VectorStore } from \"./vector-store.contract\";\n\n/**\n * Adapt any `@warlock.js/cache` `CacheDriver` to the {@link VectorStore}\n * narrowing the RAG pipeline depends on. The cache driver IS the vector\n * store — exactly as `SemanticMemory` and `semanticCache` already use it:\n *\n * - `upsert` → `driver.set(key, value, { vector, tags })`\n * - `query` → `driver.similar<T>(vector, { topK, threshold, tags })`\n * - `removeNamespace` → `driver.removeNamespace(namespace)`\n *\n * Drivers without similarity support throw `CacheUnsupportedError` from\n * `set({ vector })` / `similar()`; the error surfaces unchanged so the\n * caller sees the cache layer's own message (pointing at the `pg` /\n * `redis` drivers for production-scale similarity).\n *\n * @example\n * const store = cacheVectorStore(new MemoryCacheDriver());\n * await store.upsert(\"ai.rag.docs.guide.0\", { text: \"…\" }, vector);\n * const hits = await store.query(queryVector, { topK: 5, threshold: 0.5 });\n */\nexport function cacheVectorStore(driver: CacheDriver<any, any>): VectorStore {\n return {\n async upsert(\n key: string,\n value: unknown,\n vector: number[],\n tags?: string[],\n ): Promise<void> {\n await driver.set(key, value, tags && tags.length > 0 ? { vector, tags } : { vector });\n },\n\n async query<T>(\n vector: number[],\n options: { topK: number; threshold?: number; tags?: string[] },\n ): Promise<{ key: string; value: T; score: number }[]> {\n const hits = await driver.similar<T>(vector, {\n topK: options.topK,\n threshold: options.threshold,\n tags: options.tags,\n });\n\n return hits.map((hit: { key: string; value: T; score: number }) => ({\n key: hit.key,\n value: hit.value,\n score: hit.score,\n }));\n },\n\n async removeNamespace(namespace: string): Promise<void> {\n await driver.removeNamespace(namespace);\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,iBAAiB,QAA4C;CAC3E,OAAO;EACL,MAAM,OACJ,KACA,OACA,QACA,MACe;GACf,MAAM,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,SAAS,IAAI;IAAE;IAAQ;GAAK,IAAI,EAAE,OAAO,CAAC;EACtF;EAEA,MAAM,MACJ,QACA,SACqD;GAOrD,QAAO,MANY,OAAO,QAAW,QAAQ;IAC3C,MAAM,QAAQ;IACd,WAAW,QAAQ;IACnB,MAAM,QAAQ;GAChB,CAAC,EAEU,CAAC,KAAK,SAAmD;IAClE,KAAK,IAAI;IACT,OAAO,IAAI;IACX,OAAO,IAAI;GACb,EAAE;EACJ;EAEA,MAAM,gBAAgB,WAAkC;GACtD,MAAM,OAAO,gBAAgB,SAAS;EACxC;CACF;AACF"}
@@ -0,0 +1,5 @@
1
+ import { isPrivateOrReservedIp } from "./private-ip.mjs";
2
+ import { assertUrlAllowed, fetchTextWithPolicy, guardedFetch, readTextCapped, resolveOutboundPolicy } from "./outbound-policy.mjs";
3
+ import { DEFAULT_SENSITIVE_KEYS, redact } from "./redact.mjs";
4
+
5
+ export { };
@@ -0,0 +1,187 @@
1
+ import { OutboundPolicyError } from "../errors/outbound-policy-error.mjs";
2
+ import "../errors/index.mjs";
3
+ import { isPrivateOrReservedIp } from "./private-ip.mjs";
4
+ import { lookup } from "node:dns/promises";
5
+ import { isIP } from "node:net";
6
+
7
+ //#region ../@warlock.js/ai/src/security/outbound-policy.ts
8
+ /** 5 MiB — default cap on an outbound response body. */
9
+ const DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
10
+ /** 10s — default per-request timeout. */
11
+ const DEFAULT_TIMEOUT_MS = 1e4;
12
+ /**
13
+ * Fill an {@link OutboundPolicy} with strict defaults: https-only,
14
+ * private-IP deny on, 10s timeout, 5 MiB cap, global `fetch`. Idempotent
15
+ * — resolving an already-resolved policy yields the same shape.
16
+ */
17
+ function resolveOutboundPolicy(policy = {}) {
18
+ return {
19
+ allowedSchemes: policy.allowedSchemes ?? ["https"],
20
+ hostAllowlist: policy.hostAllowlist,
21
+ denyPrivateIPsAfterDNS: policy.denyPrivateIPsAfterDNS ?? true,
22
+ maxBytes: policy.maxBytes ?? DEFAULT_MAX_BYTES,
23
+ timeoutMs: policy.timeoutMs ?? DEFAULT_TIMEOUT_MS,
24
+ signal: policy.signal,
25
+ fetch: policy.fetch ?? globalThis.fetch
26
+ };
27
+ }
28
+ /** Strip the `[ ]` IPv6 brackets `URL.hostname` keeps. */
29
+ function stripBrackets(host) {
30
+ return host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host;
31
+ }
32
+ /** Whether `host` equals or is a subdomain of any allowlist entry. */
33
+ function hostAllowed(host, allowlist) {
34
+ const lower = host.toLowerCase();
35
+ return allowlist.some((entry) => {
36
+ const e = entry.toLowerCase();
37
+ return lower === e || lower.endsWith(`.${e}`);
38
+ });
39
+ }
40
+ /**
41
+ * Validate a URL against the policy BEFORE any network call: scheme
42
+ * allowlist, host allowlist, and (when enabled) a DNS resolution that
43
+ * rejects private / loopback / link-local / metadata addresses — the SSRF
44
+ * guard. Returns the parsed `URL` on success; throws
45
+ * {@link OutboundPolicyError} otherwise.
46
+ */
47
+ async function assertUrlAllowed(rawUrl, policy) {
48
+ let url;
49
+ try {
50
+ url = new URL(rawUrl);
51
+ } catch {
52
+ throw new OutboundPolicyError(`outbound request blocked — invalid URL: ${rawUrl}`, { context: { url: rawUrl } });
53
+ }
54
+ const scheme = url.protocol.replace(/:$/, "").toLowerCase();
55
+ if (!policy.allowedSchemes.some((s) => s.toLowerCase() === scheme)) throw new OutboundPolicyError(`outbound request blocked — scheme "${scheme}" is not allowed (allowed: ${policy.allowedSchemes.join(", ")})`, { context: {
56
+ url: rawUrl,
57
+ scheme
58
+ } });
59
+ const host = stripBrackets(url.hostname);
60
+ if (policy.hostAllowlist && !hostAllowed(host, policy.hostAllowlist)) throw new OutboundPolicyError(`outbound request blocked — host "${host}" is not in the allowlist`, { context: {
61
+ url: rawUrl,
62
+ host
63
+ } });
64
+ if (policy.denyPrivateIPsAfterDNS) await assertHostNotPrivate(host, rawUrl);
65
+ return url;
66
+ }
67
+ /**
68
+ * Reject when `host` is — or resolves to — a private / reserved address.
69
+ * IP literals are checked directly; hostnames are resolved via DNS and
70
+ * every returned address is checked (a public name pointing inward is
71
+ * caught). A resolution failure fails closed.
72
+ */
73
+ async function assertHostNotPrivate(host, rawUrl) {
74
+ if (isIP(host) !== 0) {
75
+ if (isPrivateOrReservedIp(host)) throw new OutboundPolicyError(`outbound request blocked — "${host}" is a private/reserved address`, { context: {
76
+ url: rawUrl,
77
+ address: host
78
+ } });
79
+ return;
80
+ }
81
+ let addresses;
82
+ try {
83
+ addresses = await lookup(host, { all: true });
84
+ } catch (cause) {
85
+ throw new OutboundPolicyError(`outbound request blocked — could not resolve host "${host}" to verify it is public`, {
86
+ cause,
87
+ context: {
88
+ url: rawUrl,
89
+ host
90
+ }
91
+ });
92
+ }
93
+ for (const { address } of addresses) if (isPrivateOrReservedIp(address)) throw new OutboundPolicyError(`outbound request blocked — host "${host}" resolves to a private/reserved address (${address})`, { context: {
94
+ url: rawUrl,
95
+ host,
96
+ address
97
+ } });
98
+ }
99
+ /** Merge the internal timeout signal with an optional caller signal. */
100
+ function mergeSignals(timeout, external) {
101
+ if (!external) return timeout;
102
+ const controller = new AbortController();
103
+ const abort = (from) => controller.abort(from.reason);
104
+ if (timeout.aborted) abort(timeout);
105
+ else timeout.addEventListener("abort", () => abort(timeout), { once: true });
106
+ if (external.aborted) abort(external);
107
+ else external.addEventListener("abort", () => abort(external), { once: true });
108
+ return controller.signal;
109
+ }
110
+ /**
111
+ * Policy-guarded `fetch`: validates the URL ({@link assertUrlAllowed}),
112
+ * then performs the request with the policy's timeout and (optional)
113
+ * caller signal merged. Returns the raw `Response` — read its body via
114
+ * {@link readTextCapped} to enforce `maxBytes`. Throws
115
+ * {@link OutboundPolicyError} on a policy violation or timeout.
116
+ */
117
+ async function guardedFetch(rawUrl, policyInput, init) {
118
+ const policy = resolveOutboundPolicy(policyInput);
119
+ const url = await assertUrlAllowed(rawUrl, policy);
120
+ const timeoutController = new AbortController();
121
+ const timer = setTimeout(() => {
122
+ timeoutController.abort(new OutboundPolicyError(`outbound request timed out after ${policy.timeoutMs}ms`, { context: {
123
+ url: rawUrl,
124
+ timeoutMs: policy.timeoutMs
125
+ } }));
126
+ }, policy.timeoutMs);
127
+ try {
128
+ return await policy.fetch(url, {
129
+ ...init,
130
+ signal: mergeSignals(timeoutController.signal, policy.signal)
131
+ });
132
+ } finally {
133
+ clearTimeout(timer);
134
+ }
135
+ }
136
+ /**
137
+ * Read a response body as UTF-8 text with a hard byte cap. A declared
138
+ * `content-length` over the cap fails fast; otherwise the stream is read
139
+ * chunk-by-chunk and aborted the moment the running total exceeds
140
+ * `maxBytes`. Throws {@link OutboundPolicyError} on overflow.
141
+ */
142
+ async function readTextCapped(response, maxBytes) {
143
+ const declared = Number(response.headers.get("content-length"));
144
+ if (Number.isFinite(declared) && declared > maxBytes) throw new OutboundPolicyError(`outbound response body too large — declared ${declared} bytes exceeds the ${maxBytes}-byte cap`, { context: {
145
+ declared,
146
+ maxBytes
147
+ } });
148
+ if (!response.body) {
149
+ const text = await response.text();
150
+ if (Buffer.byteLength(text) > maxBytes) throw new OutboundPolicyError(`outbound response body exceeded the ${maxBytes}-byte cap`, { context: { maxBytes } });
151
+ return text;
152
+ }
153
+ const reader = response.body.getReader();
154
+ const chunks = [];
155
+ let total = 0;
156
+ for (;;) {
157
+ const { done, value } = await reader.read();
158
+ if (done) break;
159
+ if (!value) continue;
160
+ total += value.byteLength;
161
+ if (total > maxBytes) {
162
+ await reader.cancel();
163
+ throw new OutboundPolicyError(`outbound response body exceeded the ${maxBytes}-byte cap`, { context: { maxBytes } });
164
+ }
165
+ chunks.push(value);
166
+ }
167
+ return Buffer.concat(chunks).toString("utf8");
168
+ }
169
+ /**
170
+ * Convenience: {@link guardedFetch} + {@link readTextCapped}. Returns the
171
+ * response status alongside the (capped) body text so callers can shape
172
+ * their own not-OK error. The body is only read when the response is OK.
173
+ */
174
+ async function fetchTextWithPolicy(rawUrl, policyInput, init) {
175
+ const policy = resolveOutboundPolicy(policyInput);
176
+ const response = await guardedFetch(rawUrl, policy, init);
177
+ return {
178
+ ok: response.ok,
179
+ status: response.status,
180
+ statusText: response.statusText,
181
+ text: response.ok ? await readTextCapped(response, policy.maxBytes) : ""
182
+ };
183
+ }
184
+
185
+ //#endregion
186
+ export { assertUrlAllowed, fetchTextWithPolicy, guardedFetch, readTextCapped, resolveOutboundPolicy };
187
+ //# sourceMappingURL=outbound-policy.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbound-policy.mjs","names":[],"sources":["../../../../../../../../../@warlock.js/ai/src/security/outbound-policy.ts"],"sourcesContent":["import { lookup } from \"node:dns/promises\";\nimport { isIP } from \"node:net\";\nimport { OutboundPolicyError } from \"../errors\";\nimport { isPrivateOrReservedIp } from \"./private-ip\";\nimport type {\n OutboundPolicy,\n ResolvedOutboundPolicy,\n} from \"./outbound-policy.type\";\n\n/** 5 MiB — default cap on an outbound response body. */\nconst DEFAULT_MAX_BYTES = 5 * 1024 * 1024;\n/** 10s — default per-request timeout. */\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\n/**\n * Fill an {@link OutboundPolicy} with strict defaults: https-only,\n * private-IP deny on, 10s timeout, 5 MiB cap, global `fetch`. Idempotent\n * — resolving an already-resolved policy yields the same shape.\n */\nexport function resolveOutboundPolicy(\n policy: OutboundPolicy = {},\n): ResolvedOutboundPolicy {\n return {\n allowedSchemes: policy.allowedSchemes ?? [\"https\"],\n hostAllowlist: policy.hostAllowlist,\n denyPrivateIPsAfterDNS: policy.denyPrivateIPsAfterDNS ?? true,\n maxBytes: policy.maxBytes ?? DEFAULT_MAX_BYTES,\n timeoutMs: policy.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n signal: policy.signal,\n fetch: policy.fetch ?? globalThis.fetch,\n };\n}\n\n/** Strip the `[ ]` IPv6 brackets `URL.hostname` keeps. */\nfunction stripBrackets(host: string): string {\n return host.startsWith(\"[\") && host.endsWith(\"]\") ? host.slice(1, -1) : host;\n}\n\n/** Whether `host` equals or is a subdomain of any allowlist entry. */\nfunction hostAllowed(host: string, allowlist: string[]): boolean {\n const lower = host.toLowerCase();\n return allowlist.some(entry => {\n const e = entry.toLowerCase();\n return lower === e || lower.endsWith(`.${e}`);\n });\n}\n\n/**\n * Validate a URL against the policy BEFORE any network call: scheme\n * allowlist, host allowlist, and (when enabled) a DNS resolution that\n * rejects private / loopback / link-local / metadata addresses — the SSRF\n * guard. Returns the parsed `URL` on success; throws\n * {@link OutboundPolicyError} otherwise.\n */\nexport async function assertUrlAllowed(\n rawUrl: string,\n policy: ResolvedOutboundPolicy,\n): Promise<URL> {\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n throw new OutboundPolicyError(`outbound request blocked — invalid URL: ${rawUrl}`, {\n context: { url: rawUrl },\n });\n }\n\n const scheme = url.protocol.replace(/:$/, \"\").toLowerCase();\n if (!policy.allowedSchemes.some(s => s.toLowerCase() === scheme)) {\n throw new OutboundPolicyError(\n `outbound request blocked — scheme \"${scheme}\" is not allowed (allowed: ${policy.allowedSchemes.join(\", \")})`,\n { context: { url: rawUrl, scheme } },\n );\n }\n\n const host = stripBrackets(url.hostname);\n\n if (policy.hostAllowlist && !hostAllowed(host, policy.hostAllowlist)) {\n throw new OutboundPolicyError(\n `outbound request blocked — host \"${host}\" is not in the allowlist`,\n { context: { url: rawUrl, host } },\n );\n }\n\n if (policy.denyPrivateIPsAfterDNS) {\n await assertHostNotPrivate(host, rawUrl);\n }\n\n return url;\n}\n\n/**\n * Reject when `host` is — or resolves to — a private / reserved address.\n * IP literals are checked directly; hostnames are resolved via DNS and\n * every returned address is checked (a public name pointing inward is\n * caught). A resolution failure fails closed.\n */\nasync function assertHostNotPrivate(host: string, rawUrl: string): Promise<void> {\n if (isIP(host) !== 0) {\n if (isPrivateOrReservedIp(host)) {\n throw new OutboundPolicyError(\n `outbound request blocked — \"${host}\" is a private/reserved address`,\n { context: { url: rawUrl, address: host } },\n );\n }\n return;\n }\n\n let addresses: Array<{ address: string }>;\n try {\n addresses = await lookup(host, { all: true });\n } catch (cause) {\n throw new OutboundPolicyError(\n `outbound request blocked — could not resolve host \"${host}\" to verify it is public`,\n { cause, context: { url: rawUrl, host } },\n );\n }\n\n for (const { address } of addresses) {\n if (isPrivateOrReservedIp(address)) {\n throw new OutboundPolicyError(\n `outbound request blocked — host \"${host}\" resolves to a private/reserved address (${address})`,\n { context: { url: rawUrl, host, address } },\n );\n }\n }\n}\n\n/** Merge the internal timeout signal with an optional caller signal. */\nfunction mergeSignals(\n timeout: AbortSignal,\n external?: AbortSignal,\n): AbortSignal {\n if (!external) return timeout;\n\n const controller = new AbortController();\n const abort = (from: AbortSignal) => controller.abort(from.reason);\n\n if (timeout.aborted) abort(timeout);\n else timeout.addEventListener(\"abort\", () => abort(timeout), { once: true });\n\n if (external.aborted) abort(external);\n else external.addEventListener(\"abort\", () => abort(external), { once: true });\n\n return controller.signal;\n}\n\n/**\n * Policy-guarded `fetch`: validates the URL ({@link assertUrlAllowed}),\n * then performs the request with the policy's timeout and (optional)\n * caller signal merged. Returns the raw `Response` — read its body via\n * {@link readTextCapped} to enforce `maxBytes`. Throws\n * {@link OutboundPolicyError} on a policy violation or timeout.\n */\nexport async function guardedFetch(\n rawUrl: string,\n policyInput: OutboundPolicy,\n init?: RequestInit,\n): Promise<Response> {\n const policy = resolveOutboundPolicy(policyInput);\n const url = await assertUrlAllowed(rawUrl, policy);\n\n const timeoutController = new AbortController();\n const timer = setTimeout(() => {\n timeoutController.abort(\n new OutboundPolicyError(\n `outbound request timed out after ${policy.timeoutMs}ms`,\n { context: { url: rawUrl, timeoutMs: policy.timeoutMs } },\n ),\n );\n }, policy.timeoutMs);\n\n try {\n return await policy.fetch(url, {\n ...init,\n signal: mergeSignals(timeoutController.signal, policy.signal),\n });\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Read a response body as UTF-8 text with a hard byte cap. A declared\n * `content-length` over the cap fails fast; otherwise the stream is read\n * chunk-by-chunk and aborted the moment the running total exceeds\n * `maxBytes`. Throws {@link OutboundPolicyError} on overflow.\n */\nexport async function readTextCapped(\n response: Response,\n maxBytes: number,\n): Promise<string> {\n const declared = Number(response.headers.get(\"content-length\"));\n if (Number.isFinite(declared) && declared > maxBytes) {\n throw new OutboundPolicyError(\n `outbound response body too large — declared ${declared} bytes exceeds the ${maxBytes}-byte cap`,\n { context: { declared, maxBytes } },\n );\n }\n\n if (!response.body) {\n const text = await response.text();\n if (Buffer.byteLength(text) > maxBytes) {\n throw new OutboundPolicyError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { maxBytes } },\n );\n }\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n if (!value) continue;\n\n total += value.byteLength;\n if (total > maxBytes) {\n await reader.cancel();\n throw new OutboundPolicyError(\n `outbound response body exceeded the ${maxBytes}-byte cap`,\n { context: { maxBytes } },\n );\n }\n chunks.push(value);\n }\n\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/**\n * Convenience: {@link guardedFetch} + {@link readTextCapped}. Returns the\n * response status alongside the (capped) body text so callers can shape\n * their own not-OK error. The body is only read when the response is OK.\n */\nexport async function fetchTextWithPolicy(\n rawUrl: string,\n policyInput: OutboundPolicy,\n init?: RequestInit,\n): Promise<{ ok: boolean; status: number; statusText: string; text: string }> {\n const policy = resolveOutboundPolicy(policyInput);\n const response = await guardedFetch(rawUrl, policy, init);\n\n return {\n ok: response.ok,\n status: response.status,\n statusText: response.statusText,\n text: response.ok ? await readTextCapped(response, policy.maxBytes) : \"\",\n };\n}\n"],"mappings":";;;;;;;;AAUA,MAAM,oBAAoB,IAAI,OAAO;;AAErC,MAAM,qBAAqB;;;;;;AAO3B,SAAgB,sBACd,SAAyB,CAAC,GACF;CACxB,OAAO;EACL,gBAAgB,OAAO,kBAAkB,CAAC,OAAO;EACjD,eAAe,OAAO;EACtB,wBAAwB,OAAO,0BAA0B;EACzD,UAAU,OAAO,YAAY;EAC7B,WAAW,OAAO,aAAa;EAC/B,QAAQ,OAAO;EACf,OAAO,OAAO,SAAS,WAAW;CACpC;AACF;;AAGA,SAAS,cAAc,MAAsB;CAC3C,OAAO,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI;AAC1E;;AAGA,SAAS,YAAY,MAAc,WAA8B;CAC/D,MAAM,QAAQ,KAAK,YAAY;CAC/B,OAAO,UAAU,MAAK,UAAS;EAC7B,MAAM,IAAI,MAAM,YAAY;EAC5B,OAAO,UAAU,KAAK,MAAM,SAAS,IAAI,GAAG;CAC9C,CAAC;AACH;;;;;;;;AASA,eAAsB,iBACpB,QACA,QACc;CACd,IAAI;CACJ,IAAI;EACF,MAAM,IAAI,IAAI,MAAM;CACtB,QAAQ;EACN,MAAM,IAAI,oBAAoB,2CAA2C,UAAU,EACjF,SAAS,EAAE,KAAK,OAAO,EACzB,CAAC;CACH;CAEA,MAAM,SAAS,IAAI,SAAS,QAAQ,MAAM,EAAE,CAAC,CAAC,YAAY;CAC1D,IAAI,CAAC,OAAO,eAAe,MAAK,MAAK,EAAE,YAAY,MAAM,MAAM,GAC7D,MAAM,IAAI,oBACR,sCAAsC,OAAO,6BAA6B,OAAO,eAAe,KAAK,IAAI,EAAE,IAC3G,EAAE,SAAS;EAAE,KAAK;EAAQ;CAAO,EAAE,CACrC;CAGF,MAAM,OAAO,cAAc,IAAI,QAAQ;CAEvC,IAAI,OAAO,iBAAiB,CAAC,YAAY,MAAM,OAAO,aAAa,GACjE,MAAM,IAAI,oBACR,oCAAoC,KAAK,4BACzC,EAAE,SAAS;EAAE,KAAK;EAAQ;CAAK,EAAE,CACnC;CAGF,IAAI,OAAO,wBACT,MAAM,qBAAqB,MAAM,MAAM;CAGzC,OAAO;AACT;;;;;;;AAQA,eAAe,qBAAqB,MAAc,QAA+B;CAC/E,IAAI,KAAK,IAAI,MAAM,GAAG;EACpB,IAAI,sBAAsB,IAAI,GAC5B,MAAM,IAAI,oBACR,+BAA+B,KAAK,kCACpC,EAAE,SAAS;GAAE,KAAK;GAAQ,SAAS;EAAK,EAAE,CAC5C;EAEF;CACF;CAEA,IAAI;CACJ,IAAI;EACF,YAAY,MAAM,OAAO,MAAM,EAAE,KAAK,KAAK,CAAC;CAC9C,SAAS,OAAO;EACd,MAAM,IAAI,oBACR,sDAAsD,KAAK,2BAC3D;GAAE;GAAO,SAAS;IAAE,KAAK;IAAQ;GAAK;EAAE,CAC1C;CACF;CAEA,KAAK,MAAM,EAAE,aAAa,WACxB,IAAI,sBAAsB,OAAO,GAC/B,MAAM,IAAI,oBACR,oCAAoC,KAAK,4CAA4C,QAAQ,IAC7F,EAAE,SAAS;EAAE,KAAK;EAAQ;EAAM;CAAQ,EAAE,CAC5C;AAGN;;AAGA,SAAS,aACP,SACA,UACa;CACb,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,SAAS,SAAsB,WAAW,MAAM,KAAK,MAAM;CAEjE,IAAI,QAAQ,SAAS,MAAM,OAAO;MAC7B,QAAQ,iBAAiB,eAAe,MAAM,OAAO,GAAG,EAAE,MAAM,KAAK,CAAC;CAE3E,IAAI,SAAS,SAAS,MAAM,QAAQ;MAC/B,SAAS,iBAAiB,eAAe,MAAM,QAAQ,GAAG,EAAE,MAAM,KAAK,CAAC;CAE7E,OAAO,WAAW;AACpB;;;;;;;;AASA,eAAsB,aACpB,QACA,aACA,MACmB;CACnB,MAAM,SAAS,sBAAsB,WAAW;CAChD,MAAM,MAAM,MAAM,iBAAiB,QAAQ,MAAM;CAEjD,MAAM,oBAAoB,IAAI,gBAAgB;CAC9C,MAAM,QAAQ,iBAAiB;EAC7B,kBAAkB,MAChB,IAAI,oBACF,oCAAoC,OAAO,UAAU,KACrD,EAAE,SAAS;GAAE,KAAK;GAAQ,WAAW,OAAO;EAAU,EAAE,CAC1D,CACF;CACF,GAAG,OAAO,SAAS;CAEnB,IAAI;EACF,OAAO,MAAM,OAAO,MAAM,KAAK;GAC7B,GAAG;GACH,QAAQ,aAAa,kBAAkB,QAAQ,OAAO,MAAM;EAC9D,CAAC;CACH,UAAU;EACR,aAAa,KAAK;CACpB;AACF;;;;;;;AAQA,eAAsB,eACpB,UACA,UACiB;CACjB,MAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,gBAAgB,CAAC;CAC9D,IAAI,OAAO,SAAS,QAAQ,KAAK,WAAW,UAC1C,MAAM,IAAI,oBACR,+CAA+C,SAAS,qBAAqB,SAAS,YACtF,EAAE,SAAS;EAAE;EAAU;CAAS,EAAE,CACpC;CAGF,IAAI,CAAC,SAAS,MAAM;EAClB,MAAM,OAAO,MAAM,SAAS,KAAK;EACjC,IAAI,OAAO,WAAW,IAAI,IAAI,UAC5B,MAAM,IAAI,oBACR,uCAAuC,SAAS,YAChD,EAAE,SAAS,EAAE,SAAS,EAAE,CAC1B;EAEF,OAAO;CACT;CAEA,MAAM,SAAS,SAAS,KAAK,UAAU;CACvC,MAAM,SAAuB,CAAC;CAC9B,IAAI,QAAQ;CAEZ,SAAS;EACP,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;EAC1C,IAAI,MAAM;EACV,IAAI,CAAC,OAAO;EAEZ,SAAS,MAAM;EACf,IAAI,QAAQ,UAAU;GACpB,MAAM,OAAO,OAAO;GACpB,MAAM,IAAI,oBACR,uCAAuC,SAAS,YAChD,EAAE,SAAS,EAAE,SAAS,EAAE,CAC1B;EACF;EACA,OAAO,KAAK,KAAK;CACnB;CAEA,OAAO,OAAO,OAAO,MAAM,CAAC,CAAC,SAAS,MAAM;AAC9C;;;;;;AAOA,eAAsB,oBACpB,QACA,aACA,MAC4E;CAC5E,MAAM,SAAS,sBAAsB,WAAW;CAChD,MAAM,WAAW,MAAM,aAAa,QAAQ,QAAQ,IAAI;CAExD,OAAO;EACL,IAAI,SAAS;EACb,QAAQ,SAAS;EACjB,YAAY,SAAS;EACrB,MAAM,SAAS,KAAK,MAAM,eAAe,UAAU,OAAO,QAAQ,IAAI;CACxE;AACF"}
@@ -0,0 +1,48 @@
1
+ import { isIP } from "node:net";
2
+
3
+ //#region ../@warlock.js/ai/src/security/private-ip.ts
4
+ /**
5
+ * True when `ip` is a private, loopback, link-local, unique-local,
6
+ * carrier-grade-NAT, unspecified, or otherwise non-public address — the
7
+ * set an SSRF guard must refuse. Accepts IPv4 and IPv6 literals (including
8
+ * IPv4-mapped IPv6 like `::ffff:169.254.169.254`). A non-IP string returns
9
+ * `false` (the caller resolves hostnames via DNS first).
10
+ *
11
+ * The cloud-metadata endpoint `169.254.169.254` is covered by the IPv4
12
+ * link-local range `169.254.0.0/16`.
13
+ */
14
+ function isPrivateOrReservedIp(ip) {
15
+ const family = isIP(ip);
16
+ if (family === 4) return isPrivateIpv4(ip);
17
+ if (family === 6) return isPrivateIpv6(ip);
18
+ return false;
19
+ }
20
+ /** Parse a dotted-quad into four octets, or `null` if malformed. */
21
+ function parseIpv4(ip) {
22
+ const parts = ip.split(".");
23
+ if (parts.length !== 4) return null;
24
+ const octets = parts.map((part) => Number(part));
25
+ if (octets.some((n) => !Number.isInteger(n) || n < 0 || n > 255)) return null;
26
+ return octets;
27
+ }
28
+ function isPrivateIpv4(ip) {
29
+ const octets = parseIpv4(ip);
30
+ if (!octets) return true;
31
+ const [a, b] = octets;
32
+ return a === 0 || a === 10 || a === 127 || a === 100 && b >= 64 && b <= 127 || a === 169 && b === 254 || a === 172 && b >= 16 && b <= 31 || a === 192 && b === 168 || a === 192 && b === 0 || a === 198 && (b === 18 || b === 19) || a === 198 && b === 51 || a === 203 && b === 0 || a >= 224;
33
+ }
34
+ function isPrivateIpv6(ip) {
35
+ const normalized = ip.toLowerCase().split("%")[0];
36
+ const v4 = normalized.match(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
37
+ if (v4) return isPrivateIpv4(v4[1]);
38
+ if (normalized === "::1" || normalized === "::") return true;
39
+ const firstGroup = normalized.split(":")[0];
40
+ const head = firstGroup === "" ? 0 : Number.parseInt(firstGroup, 16);
41
+ if ((head & 65024) === 64512) return true;
42
+ if ((head & 65472) === 65152) return true;
43
+ return false;
44
+ }
45
+
46
+ //#endregion
47
+ export { isPrivateOrReservedIp };
48
+ //# sourceMappingURL=private-ip.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"private-ip.mjs","names":[],"sources":["../../../../../../../../../@warlock.js/ai/src/security/private-ip.ts"],"sourcesContent":["import { isIP } from \"node:net\";\n\n/**\n * True when `ip` is a private, loopback, link-local, unique-local,\n * carrier-grade-NAT, unspecified, or otherwise non-public address — the\n * set an SSRF guard must refuse. Accepts IPv4 and IPv6 literals (including\n * IPv4-mapped IPv6 like `::ffff:169.254.169.254`). A non-IP string returns\n * `false` (the caller resolves hostnames via DNS first).\n *\n * The cloud-metadata endpoint `169.254.169.254` is covered by the IPv4\n * link-local range `169.254.0.0/16`.\n */\nexport function isPrivateOrReservedIp(ip: string): boolean {\n const family = isIP(ip);\n if (family === 4) return isPrivateIpv4(ip);\n if (family === 6) return isPrivateIpv6(ip);\n return false;\n}\n\n/** Parse a dotted-quad into four octets, or `null` if malformed. */\nfunction parseIpv4(ip: string): [number, number, number, number] | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n\n const octets = parts.map(part => Number(part));\n if (octets.some(n => !Number.isInteger(n) || n < 0 || n > 255)) return null;\n\n return octets as [number, number, number, number];\n}\n\nfunction isPrivateIpv4(ip: string): boolean {\n const octets = parseIpv4(ip);\n if (!octets) return true; // unparseable → refuse, fail closed\n\n const [a, b] = octets;\n\n return (\n a === 0 || // 0.0.0.0/8 \"this network\"\n a === 10 || // 10.0.0.0/8 private\n a === 127 || // 127.0.0.0/8 loopback\n (a === 100 && b >= 64 && b <= 127) || // 100.64.0.0/10 CGNAT\n (a === 169 && b === 254) || // 169.254.0.0/16 link-local + metadata\n (a === 172 && b >= 16 && b <= 31) || // 172.16.0.0/12 private\n (a === 192 && b === 168) || // 192.168.0.0/16 private\n (a === 192 && b === 0) || // 192.0.0.0/24 + 192.0.2.0/24 (IETF/test)\n (a === 198 && (b === 18 || b === 19)) || // 198.18.0.0/15 benchmarking\n (a === 198 && b === 51) || // 198.51.100.0/24 test-net-2\n (a === 203 && b === 0) || // 203.0.113.0/24 test-net-3\n a >= 224 // 224.0.0.0/4 multicast + 240.0.0.0/4 reserved + 255.255.255.255\n );\n}\n\nfunction isPrivateIpv6(ip: string): boolean {\n const normalized = ip.toLowerCase().split(\"%\")[0]; // drop zone id\n\n // IPv4-mapped / -embedded (::ffff:a.b.c.d, ::a.b.c.d) — defer to the v4\n // check on the trailing dotted-quad so an inward-mapped address is caught.\n const v4 = normalized.match(/(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/);\n if (v4) {\n return isPrivateIpv4(v4[1]);\n }\n\n if (normalized === \"::1\" || normalized === \"::\") {\n return true; // loopback / unspecified\n }\n\n // Expand only the leading group enough to classify the reserved blocks.\n const firstGroup = normalized.split(\":\")[0];\n const head = firstGroup === \"\" ? 0 : Number.parseInt(firstGroup, 16);\n\n // fc00::/7 unique-local (fc.. / fd..)\n if ((head & 0xfe00) === 0xfc00) return true;\n // fe80::/10 link-local\n if ((head & 0xffc0) === 0xfe80) return true;\n\n return false;\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,SAAgB,sBAAsB,IAAqB;CACzD,MAAM,SAAS,KAAK,EAAE;CACtB,IAAI,WAAW,GAAG,OAAO,cAAc,EAAE;CACzC,IAAI,WAAW,GAAG,OAAO,cAAc,EAAE;CACzC,OAAO;AACT;;AAGA,SAAS,UAAU,IAAqD;CACtE,MAAM,QAAQ,GAAG,MAAM,GAAG;CAC1B,IAAI,MAAM,WAAW,GAAG,OAAO;CAE/B,MAAM,SAAS,MAAM,KAAI,SAAQ,OAAO,IAAI,CAAC;CAC7C,IAAI,OAAO,MAAK,MAAK,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,GAAG,GAAG,OAAO;CAEvE,OAAO;AACT;AAEA,SAAS,cAAc,IAAqB;CAC1C,MAAM,SAAS,UAAU,EAAE;CAC3B,IAAI,CAAC,QAAQ,OAAO;CAEpB,MAAM,CAAC,GAAG,KAAK;CAEf,OACE,MAAM,KACN,MAAM,MACN,MAAM,OACL,MAAM,OAAO,KAAK,MAAM,KAAK,OAC7B,MAAM,OAAO,MAAM,OACnB,MAAM,OAAO,KAAK,MAAM,KAAK,MAC7B,MAAM,OAAO,MAAM,OACnB,MAAM,OAAO,MAAM,KACnB,MAAM,QAAQ,MAAM,MAAM,MAAM,OAChC,MAAM,OAAO,MAAM,MACnB,MAAM,OAAO,MAAM,KACpB,KAAK;AAET;AAEA,SAAS,cAAc,IAAqB;CAC1C,MAAM,aAAa,GAAG,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;CAI/C,MAAM,KAAK,WAAW,MAAM,uCAAuC;CACnE,IAAI,IACF,OAAO,cAAc,GAAG,EAAE;CAG5B,IAAI,eAAe,SAAS,eAAe,MACzC,OAAO;CAIT,MAAM,aAAa,WAAW,MAAM,GAAG,CAAC,CAAC;CACzC,MAAM,OAAO,eAAe,KAAK,IAAI,OAAO,SAAS,YAAY,EAAE;CAGnE,KAAK,OAAO,WAAY,OAAQ,OAAO;CAEvC,KAAK,OAAO,WAAY,OAAQ,OAAO;CAEvC,OAAO;AACT"}