@warlock.js/core 4.4.0 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (997) hide show
  1. package/CHANGELOG.md +72 -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 +1276 -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/signature.mjs +57 -0
  17. package/esm/ai/src/agent/signature.mjs.map +1 -0
  18. package/esm/ai/src/agent/snapshot.mjs +101 -0
  19. package/esm/ai/src/agent/snapshot.mjs.map +1 -0
  20. package/esm/ai/src/agent/spawn-sub-agent.mjs +68 -0
  21. package/esm/ai/src/agent/spawn-sub-agent.mjs.map +1 -0
  22. package/esm/ai/src/ai.mjs +191 -0
  23. package/esm/ai/src/ai.mjs.map +1 -0
  24. package/esm/ai/src/batch/batch.mjs +198 -0
  25. package/esm/ai/src/batch/batch.mjs.map +1 -0
  26. package/esm/ai/src/batch/index.mjs +3 -0
  27. package/esm/ai/src/batch/run-batch-item.mjs +100 -0
  28. package/esm/ai/src/batch/run-batch-item.mjs.map +1 -0
  29. package/esm/ai/src/batch/run-with-concurrency.mjs +39 -0
  30. package/esm/ai/src/batch/run-with-concurrency.mjs.map +1 -0
  31. package/esm/ai/src/checkpoint/memory.mjs +0 -0
  32. package/esm/ai/src/checkpoint/memory.mjs.map +1 -0
  33. package/esm/ai/src/checkpoint/pg.mjs +265 -0
  34. package/esm/ai/src/checkpoint/pg.mjs.map +1 -0
  35. package/esm/ai/src/checkpoint/redis.mjs +200 -0
  36. package/esm/ai/src/checkpoint/redis.mjs.map +1 -0
  37. package/esm/ai/src/config.mjs +59 -0
  38. package/esm/ai/src/config.mjs.map +1 -0
  39. package/esm/ai/src/contracts/end.type.mjs +47 -0
  40. package/esm/ai/src/contracts/end.type.mjs.map +1 -0
  41. package/esm/ai/src/errors/agent-cancelled-error.mjs +43 -0
  42. package/esm/ai/src/errors/agent-cancelled-error.mjs.map +1 -0
  43. package/esm/ai/src/errors/agent-drift-error.mjs +31 -0
  44. package/esm/ai/src/errors/agent-drift-error.mjs.map +1 -0
  45. package/esm/ai/src/errors/agent-execution-error.mjs +35 -0
  46. package/esm/ai/src/errors/agent-execution-error.mjs.map +1 -0
  47. package/esm/ai/src/errors/agent-max-trips-error.mjs +41 -0
  48. package/esm/ai/src/errors/agent-max-trips-error.mjs.map +1 -0
  49. package/esm/ai/src/errors/ai-error.mjs +68 -0
  50. package/esm/ai/src/errors/ai-error.mjs.map +1 -0
  51. package/esm/ai/src/errors/budget-exceeded-error.mjs +31 -0
  52. package/esm/ai/src/errors/budget-exceeded-error.mjs.map +1 -0
  53. package/esm/ai/src/errors/content-filter-error.mjs +28 -0
  54. package/esm/ai/src/errors/content-filter-error.mjs.map +1 -0
  55. package/esm/ai/src/errors/context-length-exceeded-error.mjs +31 -0
  56. package/esm/ai/src/errors/context-length-exceeded-error.mjs.map +1 -0
  57. package/esm/ai/src/errors/guardrail-violation-error.mjs +41 -0
  58. package/esm/ai/src/errors/guardrail-violation-error.mjs.map +1 -0
  59. package/esm/ai/src/errors/index.mjs +39 -0
  60. package/esm/ai/src/errors/invalid-request-error.mjs +31 -0
  61. package/esm/ai/src/errors/invalid-request-error.mjs.map +1 -0
  62. package/esm/ai/src/errors/max-iterations-error.mjs +32 -0
  63. package/esm/ai/src/errors/max-iterations-error.mjs.map +1 -0
  64. package/esm/ai/src/errors/max-steps-exceeded-error.mjs +21 -0
  65. package/esm/ai/src/errors/max-steps-exceeded-error.mjs.map +1 -0
  66. package/esm/ai/src/errors/orchestrator-cancelled-error.mjs +31 -0
  67. package/esm/ai/src/errors/orchestrator-cancelled-error.mjs.map +1 -0
  68. package/esm/ai/src/errors/orchestrator-config-error.mjs +30 -0
  69. package/esm/ai/src/errors/orchestrator-config-error.mjs.map +1 -0
  70. package/esm/ai/src/errors/orchestrator-drift-error.mjs +37 -0
  71. package/esm/ai/src/errors/orchestrator-drift-error.mjs.map +1 -0
  72. package/esm/ai/src/errors/orchestrator-failed-error.mjs +36 -0
  73. package/esm/ai/src/errors/orchestrator-failed-error.mjs.map +1 -0
  74. package/esm/ai/src/errors/outbound-policy-error.mjs +32 -0
  75. package/esm/ai/src/errors/outbound-policy-error.mjs.map +1 -0
  76. package/esm/ai/src/errors/planner-cancelled-error.mjs +29 -0
  77. package/esm/ai/src/errors/planner-cancelled-error.mjs.map +1 -0
  78. package/esm/ai/src/errors/planner-drift-error.mjs +33 -0
  79. package/esm/ai/src/errors/planner-drift-error.mjs.map +1 -0
  80. package/esm/ai/src/errors/planner-failed-error.mjs +37 -0
  81. package/esm/ai/src/errors/planner-failed-error.mjs.map +1 -0
  82. package/esm/ai/src/errors/planner-plan-invalid-error.mjs +25 -0
  83. package/esm/ai/src/errors/planner-plan-invalid-error.mjs.map +1 -0
  84. package/esm/ai/src/errors/provider-auth-error.mjs +26 -0
  85. package/esm/ai/src/errors/provider-auth-error.mjs.map +1 -0
  86. package/esm/ai/src/errors/provider-error.mjs +42 -0
  87. package/esm/ai/src/errors/provider-error.mjs.map +1 -0
  88. package/esm/ai/src/errors/provider-rate-limit-error.mjs +31 -0
  89. package/esm/ai/src/errors/provider-rate-limit-error.mjs.map +1 -0
  90. package/esm/ai/src/errors/provider-timeout-error.mjs +26 -0
  91. package/esm/ai/src/errors/provider-timeout-error.mjs.map +1 -0
  92. package/esm/ai/src/errors/quota-exceeded-error.mjs +40 -0
  93. package/esm/ai/src/errors/quota-exceeded-error.mjs.map +1 -0
  94. package/esm/ai/src/errors/routing-error.mjs +23 -0
  95. package/esm/ai/src/errors/routing-error.mjs.map +1 -0
  96. package/esm/ai/src/errors/schema-validation-error.mjs +37 -0
  97. package/esm/ai/src/errors/schema-validation-error.mjs.map +1 -0
  98. package/esm/ai/src/errors/step-failed-error.mjs +19 -0
  99. package/esm/ai/src/errors/step-failed-error.mjs.map +1 -0
  100. package/esm/ai/src/errors/supervisor-cancelled-error.mjs +29 -0
  101. package/esm/ai/src/errors/supervisor-cancelled-error.mjs.map +1 -0
  102. package/esm/ai/src/errors/supervisor-drift-error.mjs +30 -0
  103. package/esm/ai/src/errors/supervisor-drift-error.mjs.map +1 -0
  104. package/esm/ai/src/errors/supervisor-failed-error.mjs +43 -0
  105. package/esm/ai/src/errors/supervisor-failed-error.mjs.map +1 -0
  106. package/esm/ai/src/errors/supervisor-routing-error.mjs +39 -0
  107. package/esm/ai/src/errors/supervisor-routing-error.mjs.map +1 -0
  108. package/esm/ai/src/errors/tool-execution-error.mjs +32 -0
  109. package/esm/ai/src/errors/tool-execution-error.mjs.map +1 -0
  110. package/esm/ai/src/errors/workflow-cancelled-error.mjs +23 -0
  111. package/esm/ai/src/errors/workflow-cancelled-error.mjs.map +1 -0
  112. package/esm/ai/src/errors/workflow-drift-error.mjs +24 -0
  113. package/esm/ai/src/errors/workflow-drift-error.mjs.map +1 -0
  114. package/esm/ai/src/errors/workflow-error.mjs +18 -0
  115. package/esm/ai/src/errors/workflow-error.mjs.map +1 -0
  116. package/esm/ai/src/eval/dataset.mjs +112 -0
  117. package/esm/ai/src/eval/dataset.mjs.map +1 -0
  118. package/esm/ai/src/eval/eval-runner.mjs +135 -0
  119. package/esm/ai/src/eval/eval-runner.mjs.map +1 -0
  120. package/esm/ai/src/eval/index.mjs +48 -0
  121. package/esm/ai/src/eval/index.mjs.map +1 -0
  122. package/esm/ai/src/eval/judge-scorer.mjs +87 -0
  123. package/esm/ai/src/eval/judge-scorer.mjs.map +1 -0
  124. package/esm/ai/src/eval/regression.mjs +51 -0
  125. package/esm/ai/src/eval/regression.mjs.map +1 -0
  126. package/esm/ai/src/eval/report-json.mjs +33 -0
  127. package/esm/ai/src/eval/report-json.mjs.map +1 -0
  128. package/esm/ai/src/eval/report-junit.mjs +60 -0
  129. package/esm/ai/src/eval/report-junit.mjs.map +1 -0
  130. package/esm/ai/src/eval/scorers.mjs +101 -0
  131. package/esm/ai/src/eval/scorers.mjs.map +1 -0
  132. package/esm/ai/src/guard/detectors/index.mjs +6 -0
  133. package/esm/ai/src/guard/detectors/injection.mjs +254 -0
  134. package/esm/ai/src/guard/detectors/injection.mjs.map +1 -0
  135. package/esm/ai/src/guard/detectors/moderation.mjs +134 -0
  136. package/esm/ai/src/guard/detectors/moderation.mjs.map +1 -0
  137. package/esm/ai/src/guard/detectors/pii.mjs +199 -0
  138. package/esm/ai/src/guard/detectors/pii.mjs.map +1 -0
  139. package/esm/ai/src/guard/detectors/topic.mjs +99 -0
  140. package/esm/ai/src/guard/detectors/topic.mjs.map +1 -0
  141. package/esm/ai/src/guard/errors.mjs +18 -0
  142. package/esm/ai/src/guard/errors.mjs.map +1 -0
  143. package/esm/ai/src/guard/guard.mjs +209 -0
  144. package/esm/ai/src/guard/guard.mjs.map +1 -0
  145. package/esm/ai/src/guard/guardrail.mjs +22 -0
  146. package/esm/ai/src/guard/guardrail.mjs.map +1 -0
  147. package/esm/ai/src/human/errors.mjs +60 -0
  148. package/esm/ai/src/human/errors.mjs.map +1 -0
  149. package/esm/ai/src/human/human-approval.mjs +170 -0
  150. package/esm/ai/src/human/human-approval.mjs.map +1 -0
  151. package/esm/ai/src/human/policy.mjs +67 -0
  152. package/esm/ai/src/human/policy.mjs.map +1 -0
  153. package/esm/ai/src/human/register.mjs +37 -0
  154. package/esm/ai/src/human/register.mjs.map +1 -0
  155. package/esm/ai/src/human/resume-seed.mjs +53 -0
  156. package/esm/ai/src/human/resume-seed.mjs.map +1 -0
  157. package/esm/ai/src/human/resume.mjs +121 -0
  158. package/esm/ai/src/human/resume.mjs.map +1 -0
  159. package/esm/ai/src/human/stores/index.mjs +5 -0
  160. package/esm/ai/src/human/stores/memory.mjs +91 -0
  161. package/esm/ai/src/human/stores/memory.mjs.map +1 -0
  162. package/esm/ai/src/human/stores/pg.mjs +220 -0
  163. package/esm/ai/src/human/stores/pg.mjs.map +1 -0
  164. package/esm/ai/src/human/stores/redis.mjs +201 -0
  165. package/esm/ai/src/human/stores/redis.mjs.map +1 -0
  166. package/esm/ai/src/image/image-cost.mjs +55 -0
  167. package/esm/ai/src/image/image-cost.mjs.map +1 -0
  168. package/esm/ai/src/image/image.mjs +112 -0
  169. package/esm/ai/src/image/image.mjs.map +1 -0
  170. package/esm/ai/src/image/index.mjs +4 -0
  171. package/esm/ai/src/index.mjs +194 -0
  172. package/esm/ai/src/memory/derive-id.mjs +24 -0
  173. package/esm/ai/src/memory/derive-id.mjs.map +1 -0
  174. package/esm/ai/src/memory/episodic-memory.mjs +106 -0
  175. package/esm/ai/src/memory/episodic-memory.mjs.map +1 -0
  176. package/esm/ai/src/memory/memory.mjs +166 -0
  177. package/esm/ai/src/memory/memory.mjs.map +1 -0
  178. package/esm/ai/src/memory/procedural-memory.mjs +103 -0
  179. package/esm/ai/src/memory/procedural-memory.mjs.map +1 -0
  180. package/esm/ai/src/memory/semantic-memory.mjs +80 -0
  181. package/esm/ai/src/memory/semantic-memory.mjs.map +1 -0
  182. package/esm/ai/src/memory/working-memory.mjs +62 -0
  183. package/esm/ai/src/memory/working-memory.mjs.map +1 -0
  184. package/esm/ai/src/middleware/builtins/budget.mjs +219 -0
  185. package/esm/ai/src/middleware/builtins/budget.mjs.map +1 -0
  186. package/esm/ai/src/middleware/builtins/guardrail.mjs +76 -0
  187. package/esm/ai/src/middleware/builtins/guardrail.mjs.map +1 -0
  188. package/esm/ai/src/middleware/builtins/semantic-cache.mjs +149 -0
  189. package/esm/ai/src/middleware/builtins/semantic-cache.mjs.map +1 -0
  190. package/esm/ai/src/middleware/helpers/compose.mjs +52 -0
  191. package/esm/ai/src/middleware/helpers/compose.mjs.map +1 -0
  192. package/esm/ai/src/middleware/helpers/for-tool.mjs +80 -0
  193. package/esm/ai/src/middleware/helpers/for-tool.mjs.map +1 -0
  194. package/esm/ai/src/middleware/index.mjs +10 -0
  195. package/esm/ai/src/middleware/pipeline.mjs +100 -0
  196. package/esm/ai/src/middleware/pipeline.mjs.map +1 -0
  197. package/esm/ai/src/middleware/utils/extract-user-text.mjs +47 -0
  198. package/esm/ai/src/middleware/utils/extract-user-text.mjs.map +1 -0
  199. package/esm/ai/src/middleware/utils/namespaced-state.mjs +60 -0
  200. package/esm/ai/src/middleware/utils/namespaced-state.mjs.map +1 -0
  201. package/esm/ai/src/mock/index.mjs +4 -0
  202. package/esm/ai/src/mock/mock-agent.mjs +3 -0
  203. package/esm/ai/src/mock/mock-router.mjs +58 -0
  204. package/esm/ai/src/mock/mock-router.mjs.map +1 -0
  205. package/esm/ai/src/model/fallback-model.mjs +218 -0
  206. package/esm/ai/src/model/fallback-model.mjs.map +1 -0
  207. package/esm/ai/src/model/index.mjs +3 -0
  208. package/esm/ai/src/object-stream/index.mjs +4 -0
  209. package/esm/ai/src/object-stream/parse-partial-json.mjs +78 -0
  210. package/esm/ai/src/object-stream/parse-partial-json.mjs.map +1 -0
  211. package/esm/ai/src/object-stream/stream-object.mjs +97 -0
  212. package/esm/ai/src/object-stream/stream-object.mjs.map +1 -0
  213. package/esm/ai/src/observe/index.mjs +4 -0
  214. package/esm/ai/src/observe/observer-registry.mjs +35 -0
  215. package/esm/ai/src/observe/observer-registry.mjs.map +1 -0
  216. package/esm/ai/src/observe/resolve-observers.mjs +73 -0
  217. package/esm/ai/src/observe/resolve-observers.mjs.map +1 -0
  218. package/esm/ai/src/orchestrator/as-tool.mjs +98 -0
  219. package/esm/ai/src/orchestrator/as-tool.mjs.map +1 -0
  220. package/esm/ai/src/orchestrator/checkpoint.mjs +75 -0
  221. package/esm/ai/src/orchestrator/checkpoint.mjs.map +1 -0
  222. package/esm/ai/src/orchestrator/commands.mjs +34 -0
  223. package/esm/ai/src/orchestrator/commands.mjs.map +1 -0
  224. package/esm/ai/src/orchestrator/compaction.mjs +206 -0
  225. package/esm/ai/src/orchestrator/compaction.mjs.map +1 -0
  226. package/esm/ai/src/orchestrator/dispatch.mjs +171 -0
  227. package/esm/ai/src/orchestrator/dispatch.mjs.map +1 -0
  228. package/esm/ai/src/orchestrator/emitter.mjs +85 -0
  229. package/esm/ai/src/orchestrator/emitter.mjs.map +1 -0
  230. package/esm/ai/src/orchestrator/execution.mjs +395 -0
  231. package/esm/ai/src/orchestrator/execution.mjs.map +1 -0
  232. package/esm/ai/src/orchestrator/index.mjs +11 -0
  233. package/esm/ai/src/orchestrator/load.mjs +49 -0
  234. package/esm/ai/src/orchestrator/load.mjs.map +1 -0
  235. package/esm/ai/src/orchestrator/lock.mjs +75 -0
  236. package/esm/ai/src/orchestrator/lock.mjs.map +1 -0
  237. package/esm/ai/src/orchestrator/memory.mjs +141 -0
  238. package/esm/ai/src/orchestrator/memory.mjs.map +1 -0
  239. package/esm/ai/src/orchestrator/orchestrator-stream.mjs +98 -0
  240. package/esm/ai/src/orchestrator/orchestrator-stream.mjs.map +1 -0
  241. package/esm/ai/src/orchestrator/orchestrator.mjs +206 -0
  242. package/esm/ai/src/orchestrator/orchestrator.mjs.map +1 -0
  243. package/esm/ai/src/orchestrator/resume.mjs +74 -0
  244. package/esm/ai/src/orchestrator/resume.mjs.map +1 -0
  245. package/esm/ai/src/orchestrator/session-lock.mjs +83 -0
  246. package/esm/ai/src/orchestrator/session-lock.mjs.map +1 -0
  247. package/esm/ai/src/orchestrator/signature.mjs +120 -0
  248. package/esm/ai/src/orchestrator/signature.mjs.map +1 -0
  249. package/esm/ai/src/orchestrator/window.mjs +56 -0
  250. package/esm/ai/src/orchestrator/window.mjs.map +1 -0
  251. package/esm/ai/src/planner/dag-scheduler.mjs +97 -0
  252. package/esm/ai/src/planner/dag-scheduler.mjs.map +1 -0
  253. package/esm/ai/src/planner/index.mjs +6 -0
  254. package/esm/ai/src/planner/plan-prompt.mjs +31 -0
  255. package/esm/ai/src/planner/plan-prompt.mjs.map +1 -0
  256. package/esm/ai/src/planner/plan-schema.mjs +120 -0
  257. package/esm/ai/src/planner/plan-schema.mjs.map +1 -0
  258. package/esm/ai/src/planner/planner-run.mjs +769 -0
  259. package/esm/ai/src/planner/planner-run.mjs.map +1 -0
  260. package/esm/ai/src/planner/planner.mjs +144 -0
  261. package/esm/ai/src/planner/planner.mjs.map +1 -0
  262. package/esm/ai/src/planner/signature.mjs +27 -0
  263. package/esm/ai/src/planner/signature.mjs.map +1 -0
  264. package/esm/ai/src/planner/snapshot.mjs +95 -0
  265. package/esm/ai/src/planner/snapshot.mjs.map +1 -0
  266. package/esm/ai/src/prompt/errors.mjs +73 -0
  267. package/esm/ai/src/prompt/errors.mjs.map +1 -0
  268. package/esm/ai/src/prompt/index.mjs +4 -0
  269. package/esm/ai/src/prompt/prompt-langfuse-sync.mjs +104 -0
  270. package/esm/ai/src/prompt/prompt-langfuse-sync.mjs.map +1 -0
  271. package/esm/ai/src/prompt/prompt-validate.mjs +170 -0
  272. package/esm/ai/src/prompt/prompt-validate.mjs.map +1 -0
  273. package/esm/ai/src/prompt/prompt.mjs +218 -0
  274. package/esm/ai/src/prompt/prompt.mjs.map +1 -0
  275. package/esm/ai/src/prompts/index.mjs +3 -0
  276. package/esm/ai/src/prompts/prompts-manager.mjs +410 -0
  277. package/esm/ai/src/prompts/prompts-manager.mjs.map +1 -0
  278. package/esm/ai/src/prompts/prompts-validate.mjs +200 -0
  279. package/esm/ai/src/prompts/prompts-validate.mjs.map +1 -0
  280. package/esm/ai/src/rag/as-tool.mjs +48 -0
  281. package/esm/ai/src/rag/as-tool.mjs.map +1 -0
  282. package/esm/ai/src/rag/chunk/chunk.mjs +44 -0
  283. package/esm/ai/src/rag/chunk/chunk.mjs.map +1 -0
  284. package/esm/ai/src/rag/chunk/fixed.mjs +32 -0
  285. package/esm/ai/src/rag/chunk/fixed.mjs.map +1 -0
  286. package/esm/ai/src/rag/chunk/markdown.mjs +75 -0
  287. package/esm/ai/src/rag/chunk/markdown.mjs.map +1 -0
  288. package/esm/ai/src/rag/chunk/recursive.mjs +132 -0
  289. package/esm/ai/src/rag/chunk/recursive.mjs.map +1 -0
  290. package/esm/ai/src/rag/chunk/sentence.mjs +73 -0
  291. package/esm/ai/src/rag/chunk/sentence.mjs.map +1 -0
  292. package/esm/ai/src/rag/hybrid/bm25.mjs +51 -0
  293. package/esm/ai/src/rag/hybrid/bm25.mjs.map +1 -0
  294. package/esm/ai/src/rag/hybrid/hybrid-rank.mjs +29 -0
  295. package/esm/ai/src/rag/hybrid/hybrid-rank.mjs.map +1 -0
  296. package/esm/ai/src/rag/hybrid/rrf.mjs +30 -0
  297. package/esm/ai/src/rag/hybrid/rrf.mjs.map +1 -0
  298. package/esm/ai/src/rag/index.mjs +18 -0
  299. package/esm/ai/src/rag/loaders/errors.mjs +25 -0
  300. package/esm/ai/src/rag/loaders/errors.mjs.map +1 -0
  301. package/esm/ai/src/rag/loaders/index.mjs +7 -0
  302. package/esm/ai/src/rag/loaders/load-html.mjs +138 -0
  303. package/esm/ai/src/rag/loaders/load-html.mjs.map +1 -0
  304. package/esm/ai/src/rag/loaders/load-pdf.mjs +150 -0
  305. package/esm/ai/src/rag/loaders/load-pdf.mjs.map +1 -0
  306. package/esm/ai/src/rag/loaders/load-text.mjs +60 -0
  307. package/esm/ai/src/rag/loaders/load-text.mjs.map +1 -0
  308. package/esm/ai/src/rag/loaders/load-web.mjs +89 -0
  309. package/esm/ai/src/rag/loaders/load-web.mjs.map +1 -0
  310. package/esm/ai/src/rag/rag.mjs +126 -0
  311. package/esm/ai/src/rag/rag.mjs.map +1 -0
  312. package/esm/ai/src/rag/rerank/keyword-reranker.mjs +58 -0
  313. package/esm/ai/src/rag/rerank/keyword-reranker.mjs.map +1 -0
  314. package/esm/ai/src/rag/rerank/llm-reranker.mjs +85 -0
  315. package/esm/ai/src/rag/rerank/llm-reranker.mjs.map +1 -0
  316. package/esm/ai/src/rag/retrieve.mjs +68 -0
  317. package/esm/ai/src/rag/retrieve.mjs.map +1 -0
  318. package/esm/ai/src/rag/store/cache-vector-store.mjs +48 -0
  319. package/esm/ai/src/rag/store/cache-vector-store.mjs.map +1 -0
  320. package/esm/ai/src/rag/store/pg-vector-store.mjs +328 -0
  321. package/esm/ai/src/rag/store/pg-vector-store.mjs.map +1 -0
  322. package/esm/ai/src/rag/transforms/multi-query.mjs +41 -0
  323. package/esm/ai/src/rag/transforms/multi-query.mjs.map +1 -0
  324. package/esm/ai/src/security/index.mjs +5 -0
  325. package/esm/ai/src/security/outbound-policy.mjs +187 -0
  326. package/esm/ai/src/security/outbound-policy.mjs.map +1 -0
  327. package/esm/ai/src/security/private-ip.mjs +48 -0
  328. package/esm/ai/src/security/private-ip.mjs.map +1 -0
  329. package/esm/ai/src/security/redact.mjs +60 -0
  330. package/esm/ai/src/security/redact.mjs.map +1 -0
  331. package/esm/ai/src/serve/serve.mjs +90 -0
  332. package/esm/ai/src/serve/serve.mjs.map +1 -0
  333. package/esm/ai/src/serve/sse.mjs +25 -0
  334. package/esm/ai/src/serve/sse.mjs.map +1 -0
  335. package/esm/ai/src/serve/stream-to-sse.mjs +37 -0
  336. package/esm/ai/src/serve/stream-to-sse.mjs.map +1 -0
  337. package/esm/ai/src/skills/catalog.mjs +140 -0
  338. package/esm/ai/src/skills/catalog.mjs.map +1 -0
  339. package/esm/ai/src/skills/index.mjs +11 -0
  340. package/esm/ai/src/skills/load-skill-tool.mjs +65 -0
  341. package/esm/ai/src/skills/load-skill-tool.mjs.map +1 -0
  342. package/esm/ai/src/skills/save-skill-tool.mjs +65 -0
  343. package/esm/ai/src/skills/save-skill-tool.mjs.map +1 -0
  344. package/esm/ai/src/skills/skills.mjs +109 -0
  345. package/esm/ai/src/skills/skills.mjs.map +1 -0
  346. package/esm/ai/src/skills/sources/directory-source.mjs +108 -0
  347. package/esm/ai/src/skills/sources/directory-source.mjs.map +1 -0
  348. package/esm/ai/src/skills/sources/index.mjs +27 -0
  349. package/esm/ai/src/skills/sources/index.mjs.map +1 -0
  350. package/esm/ai/src/skills/sources/parse-frontmatter.mjs +46 -0
  351. package/esm/ai/src/skills/sources/parse-frontmatter.mjs.map +1 -0
  352. package/esm/ai/src/skills/sources/store-source.mjs +15 -0
  353. package/esm/ai/src/skills/sources/store-source.mjs.map +1 -0
  354. package/esm/ai/src/skills/sources/url-source.mjs +117 -0
  355. package/esm/ai/src/skills/sources/url-source.mjs.map +1 -0
  356. package/esm/ai/src/snapshot/memory.mjs +81 -0
  357. package/esm/ai/src/snapshot/memory.mjs.map +1 -0
  358. package/esm/ai/src/snapshot/pg.mjs +146 -0
  359. package/esm/ai/src/snapshot/pg.mjs.map +1 -0
  360. package/esm/ai/src/snapshot/redis.mjs +101 -0
  361. package/esm/ai/src/snapshot/redis.mjs.map +1 -0
  362. package/esm/ai/src/speech/index.mjs +3 -0
  363. package/esm/ai/src/speech/speech.mjs +122 -0
  364. package/esm/ai/src/speech/speech.mjs.map +1 -0
  365. package/esm/ai/src/supervisor/as-tool.mjs +74 -0
  366. package/esm/ai/src/supervisor/as-tool.mjs.map +1 -0
  367. package/esm/ai/src/supervisor/cancellation.mjs +22 -0
  368. package/esm/ai/src/supervisor/cancellation.mjs.map +1 -0
  369. package/esm/ai/src/supervisor/decide.mjs +272 -0
  370. package/esm/ai/src/supervisor/decide.mjs.map +1 -0
  371. package/esm/ai/src/supervisor/emitter.mjs +47 -0
  372. package/esm/ai/src/supervisor/emitter.mjs.map +1 -0
  373. package/esm/ai/src/supervisor/entries.mjs +206 -0
  374. package/esm/ai/src/supervisor/entries.mjs.map +1 -0
  375. package/esm/ai/src/supervisor/execution.mjs +1921 -0
  376. package/esm/ai/src/supervisor/execution.mjs.map +1 -0
  377. package/esm/ai/src/supervisor/fan-out.mjs +65 -0
  378. package/esm/ai/src/supervisor/fan-out.mjs.map +1 -0
  379. package/esm/ai/src/supervisor/index.mjs +14 -0
  380. package/esm/ai/src/supervisor/router-factory.mjs +141 -0
  381. package/esm/ai/src/supervisor/router-factory.mjs.map +1 -0
  382. package/esm/ai/src/supervisor/router-prompt.mjs +52 -0
  383. package/esm/ai/src/supervisor/router-prompt.mjs.map +1 -0
  384. package/esm/ai/src/supervisor/signature.mjs +89 -0
  385. package/esm/ai/src/supervisor/signature.mjs.map +1 -0
  386. package/esm/ai/src/supervisor/snapshot.mjs +69 -0
  387. package/esm/ai/src/supervisor/snapshot.mjs.map +1 -0
  388. package/esm/ai/src/supervisor/supervisor-stream.mjs +89 -0
  389. package/esm/ai/src/supervisor/supervisor-stream.mjs.map +1 -0
  390. package/esm/ai/src/supervisor/supervisor.mjs +144 -0
  391. package/esm/ai/src/supervisor/supervisor.mjs.map +1 -0
  392. package/esm/ai/src/system-prompt/index.mjs +6 -0
  393. package/esm/ai/src/system-prompt/instruction.mjs +57 -0
  394. package/esm/ai/src/system-prompt/instruction.mjs.map +1 -0
  395. package/esm/ai/src/system-prompt/persona.mjs +57 -0
  396. package/esm/ai/src/system-prompt/persona.mjs.map +1 -0
  397. package/esm/ai/src/system-prompt/render-placeholders.mjs +58 -0
  398. package/esm/ai/src/system-prompt/render-placeholders.mjs.map +1 -0
  399. package/esm/ai/src/system-prompt/system-prompt.mjs +267 -0
  400. package/esm/ai/src/system-prompt/system-prompt.mjs.map +1 -0
  401. package/esm/ai/src/team/gates.mjs +48 -0
  402. package/esm/ai/src/team/gates.mjs.map +1 -0
  403. package/esm/ai/src/team/index.mjs +3 -0
  404. package/esm/ai/src/team/team.mjs +94 -0
  405. package/esm/ai/src/team/team.mjs.map +1 -0
  406. package/esm/ai/src/tool/executable-as-tool.mjs +81 -0
  407. package/esm/ai/src/tool/executable-as-tool.mjs.map +1 -0
  408. package/esm/ai/src/tool/index.mjs +4 -0
  409. package/esm/ai/src/tool/tool.mjs +185 -0
  410. package/esm/ai/src/tool/tool.mjs.map +1 -0
  411. package/esm/ai/src/transcribe/audio-input.mjs +84 -0
  412. package/esm/ai/src/transcribe/audio-input.mjs.map +1 -0
  413. package/esm/ai/src/transcribe/index.mjs +4 -0
  414. package/esm/ai/src/transcribe/transcribe.mjs +127 -0
  415. package/esm/ai/src/transcribe/transcribe.mjs.map +1 -0
  416. package/esm/ai/src/utils/compute-cost.mjs +112 -0
  417. package/esm/ai/src/utils/compute-cost.mjs.map +1 -0
  418. package/esm/ai/src/utils/extract-json-lenient.mjs +97 -0
  419. package/esm/ai/src/utils/extract-json-lenient.mjs.map +1 -0
  420. package/esm/ai/src/utils/extract-json-payload.mjs +39 -0
  421. package/esm/ai/src/utils/extract-json-payload.mjs.map +1 -0
  422. package/esm/ai/src/utils/generate-run-id.mjs +23 -0
  423. package/esm/ai/src/utils/generate-run-id.mjs.map +1 -0
  424. package/esm/ai/src/utils/index.mjs +12 -0
  425. package/esm/ai/src/utils/json-schema.mjs +89 -0
  426. package/esm/ai/src/utils/json-schema.mjs.map +1 -0
  427. package/esm/ai/src/utils/prepare-attachment-part.mjs +232 -0
  428. package/esm/ai/src/utils/prepare-attachment-part.mjs.map +1 -0
  429. package/esm/ai/src/utils/resolve-attachment.mjs +74 -0
  430. package/esm/ai/src/utils/resolve-attachment.mjs.map +1 -0
  431. package/esm/ai/src/utils/run-context.mjs +89 -0
  432. package/esm/ai/src/utils/run-context.mjs.map +1 -0
  433. package/esm/ai/src/utils/safe-json-parse.mjs +22 -0
  434. package/esm/ai/src/utils/safe-json-parse.mjs.map +1 -0
  435. package/esm/ai/src/utils/stamp-report-lineage.mjs +45 -0
  436. package/esm/ai/src/utils/stamp-report-lineage.mjs.map +1 -0
  437. package/esm/ai/src/vcr/cassette-io.mjs +57 -0
  438. package/esm/ai/src/vcr/cassette-io.mjs.map +1 -0
  439. package/esm/ai/src/vcr/errors.mjs +37 -0
  440. package/esm/ai/src/vcr/errors.mjs.map +1 -0
  441. package/esm/ai/src/vcr/hash-request.mjs +118 -0
  442. package/esm/ai/src/vcr/hash-request.mjs.map +1 -0
  443. package/esm/ai/src/vcr/index.mjs +5 -0
  444. package/esm/ai/src/vcr/vcr.mjs +248 -0
  445. package/esm/ai/src/vcr/vcr.mjs.map +1 -0
  446. package/esm/ai/src/workflow/as-tool.mjs +49 -0
  447. package/esm/ai/src/workflow/as-tool.mjs.map +1 -0
  448. package/esm/ai/src/workflow/cancellation.mjs +44 -0
  449. package/esm/ai/src/workflow/cancellation.mjs.map +1 -0
  450. package/esm/ai/src/workflow/emitter.mjs +40 -0
  451. package/esm/ai/src/workflow/emitter.mjs.map +1 -0
  452. package/esm/ai/src/workflow/engine.mjs +363 -0
  453. package/esm/ai/src/workflow/engine.mjs.map +1 -0
  454. package/esm/ai/src/workflow/index.mjs +5 -0
  455. package/esm/ai/src/workflow/retry.mjs +32 -0
  456. package/esm/ai/src/workflow/retry.mjs.map +1 -0
  457. package/esm/ai/src/workflow/router.mjs +56 -0
  458. package/esm/ai/src/workflow/router.mjs.map +1 -0
  459. package/esm/ai/src/workflow/run-scoped-emitter.mjs +32 -0
  460. package/esm/ai/src/workflow/run-scoped-emitter.mjs.map +1 -0
  461. package/esm/ai/src/workflow/signature.mjs +34 -0
  462. package/esm/ai/src/workflow/signature.mjs.map +1 -0
  463. package/esm/ai/src/workflow/snapshot.mjs +77 -0
  464. package/esm/ai/src/workflow/snapshot.mjs.map +1 -0
  465. package/esm/ai/src/workflow/state.mjs +37 -0
  466. package/esm/ai/src/workflow/state.mjs.map +1 -0
  467. package/esm/ai/src/workflow/step-runner.mjs +370 -0
  468. package/esm/ai/src/workflow/step-runner.mjs.map +1 -0
  469. package/esm/ai/src/workflow/step.mjs +37 -0
  470. package/esm/ai/src/workflow/step.mjs.map +1 -0
  471. package/esm/ai/src/workflow/workflow.mjs +122 -0
  472. package/esm/ai/src/workflow/workflow.mjs.map +1 -0
  473. package/esm/ai-openai/src/embedder.mjs +4 -0
  474. package/esm/ai-openai/src/image.mjs +5 -0
  475. package/esm/ai-openai/src/index.mjs +7 -0
  476. package/esm/ai-openai/src/model.mjs +5 -0
  477. package/esm/ai-openai/src/sdk.mjs +9 -0
  478. package/esm/ai-openai/src/speech.mjs +5 -0
  479. package/esm/ai-openai/src/transcription.mjs +6 -0
  480. package/esm/ai-openai/src/utils/index.mjs +5 -0
  481. package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
  482. package/esm/ai-openai/src/utils/to-openai-tools.mjs +3 -0
  483. package/esm/ai-openai/src/utils/wrap-openai-error.mjs +4 -0
  484. package/esm/cli/commands/dev-server.command.mjs +1 -1
  485. package/esm/cli/commands/dev-server.command.mjs.map +1 -1
  486. package/esm/cli/commands/doctor/checks/config.check.mjs +42 -0
  487. package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -0
  488. package/esm/cli/commands/doctor/checks/connectors.check.mjs +28 -0
  489. package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -0
  490. package/esm/cli/commands/doctor/checks/health.check.mjs +35 -0
  491. package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -0
  492. package/esm/cli/commands/doctor/checks/index.mjs +25 -0
  493. package/esm/cli/commands/doctor/checks/index.mjs.map +1 -0
  494. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +90 -0
  495. package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -0
  496. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +69 -0
  497. package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -0
  498. package/esm/cli/commands/doctor/checks/routes.check.mjs +30 -0
  499. package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -0
  500. package/esm/cli/commands/doctor/doctor-command.action.mjs +28 -0
  501. package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -0
  502. package/esm/cli/commands/doctor/format-report.mjs +44 -0
  503. package/esm/cli/commands/doctor/format-report.mjs.map +1 -0
  504. package/esm/cli/commands/doctor/run-checks.mjs +50 -0
  505. package/esm/cli/commands/doctor/run-checks.mjs.map +1 -0
  506. package/esm/cli/commands/doctor.command.mjs +29 -0
  507. package/esm/cli/commands/doctor.command.mjs.map +1 -0
  508. package/esm/cli/commands/generate/templates/stubs.mjs +9 -12
  509. package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
  510. package/esm/cli/commands/routes/format-routes-table.mjs +129 -0
  511. package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -0
  512. package/esm/cli/commands/routes/route-row.mjs +92 -0
  513. package/esm/cli/commands/routes/route-row.mjs.map +1 -0
  514. package/esm/cli/commands/routes/routes-command.action.mjs +43 -0
  515. package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -0
  516. package/esm/cli/commands/routes.command.mjs +51 -0
  517. package/esm/cli/commands/routes.command.mjs.map +1 -0
  518. package/esm/cli/commands/seed.command.mjs +5 -0
  519. package/esm/cli/commands/seed.command.mjs.map +1 -1
  520. package/esm/cli/framework-cli-commands.mjs +4 -0
  521. package/esm/cli/framework-cli-commands.mjs.map +1 -1
  522. package/esm/config/config-getter.mjs +5 -5
  523. package/esm/config/config-getter.mjs.map +1 -1
  524. package/esm/config/config-loader.mjs +2 -2
  525. package/esm/config/config-loader.mjs.map +1 -1
  526. package/esm/connectors/access-connector.mjs +2 -2
  527. package/esm/connectors/access-connector.mjs.map +1 -1
  528. package/esm/connectors/ai-connector.d.mts +43 -0
  529. package/esm/connectors/ai-connector.d.mts.map +1 -0
  530. package/esm/connectors/ai-connector.mjs +56 -0
  531. package/esm/connectors/ai-connector.mjs.map +1 -0
  532. package/esm/connectors/cache-connector.d.mts +5 -0
  533. package/esm/connectors/cache-connector.d.mts.map +1 -1
  534. package/esm/connectors/cache-connector.mjs +9 -2
  535. package/esm/connectors/cache-connector.mjs.map +1 -1
  536. package/esm/connectors/connectors-manager.d.mts +6 -2
  537. package/esm/connectors/connectors-manager.d.mts.map +1 -1
  538. package/esm/connectors/connectors-manager.mjs +8 -2
  539. package/esm/connectors/connectors-manager.mjs.map +1 -1
  540. package/esm/connectors/database-connector.mjs +2 -2
  541. package/esm/connectors/database-connector.mjs.map +1 -1
  542. package/esm/connectors/herald-connector.mjs +2 -2
  543. package/esm/connectors/herald-connector.mjs.map +1 -1
  544. package/esm/connectors/http-connector.d.mts.map +1 -1
  545. package/esm/connectors/http-connector.mjs +9 -7
  546. package/esm/connectors/http-connector.mjs.map +1 -1
  547. package/esm/connectors/index.d.mts +1 -0
  548. package/esm/connectors/index.mjs +1 -0
  549. package/esm/connectors/logger-connector.mjs +2 -2
  550. package/esm/connectors/logger-connector.mjs.map +1 -1
  551. package/esm/connectors/mail-connector.mjs +2 -2
  552. package/esm/connectors/mail-connector.mjs.map +1 -1
  553. package/esm/connectors/notifications-connector.mjs +2 -2
  554. package/esm/connectors/notifications-connector.mjs.map +1 -1
  555. package/esm/connectors/socket-connector.d.mts +16 -1
  556. package/esm/connectors/socket-connector.d.mts.map +1 -1
  557. package/esm/connectors/socket-connector.mjs +31 -8
  558. package/esm/connectors/socket-connector.mjs.map +1 -1
  559. package/esm/connectors/storage.connector.d.mts +7 -0
  560. package/esm/connectors/storage.connector.d.mts.map +1 -1
  561. package/esm/connectors/storage.connector.mjs +7 -0
  562. package/esm/connectors/storage.connector.mjs.map +1 -1
  563. package/esm/connectors/types.d.mts +3 -2
  564. package/esm/connectors/types.d.mts.map +1 -1
  565. package/esm/connectors/types.mjs +1 -0
  566. package/esm/connectors/types.mjs.map +1 -1
  567. package/esm/database/index.d.mts +2 -1
  568. package/esm/database/index.mjs +1 -0
  569. package/esm/database/seed-command-action.mjs +44 -4
  570. package/esm/database/seed-command-action.mjs.map +1 -1
  571. package/esm/database/seeds/seed-records-table-migration.mjs +36 -0
  572. package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -0
  573. package/esm/database/seeds/seeder.d.mts +22 -5
  574. package/esm/database/seeds/seeder.d.mts.map +1 -1
  575. package/esm/database/seeds/seeder.errors.d.mts +22 -0
  576. package/esm/database/seeds/seeder.errors.d.mts.map +1 -0
  577. package/esm/database/seeds/seeder.errors.mjs +29 -0
  578. package/esm/database/seeds/seeder.errors.mjs.map +1 -0
  579. package/esm/database/seeds/seeder.mjs.map +1 -1
  580. package/esm/database/seeds/seeders.manager.mjs +90 -11
  581. package/esm/database/seeds/seeders.manager.mjs.map +1 -1
  582. package/esm/database/seeds/types.d.mts +117 -1
  583. package/esm/database/seeds/types.d.mts.map +1 -1
  584. package/esm/database/seeds/utils.mjs +6 -1
  585. package/esm/database/seeds/utils.mjs.map +1 -1
  586. package/esm/dev-server/development-server.mjs +2 -14
  587. package/esm/dev-server/development-server.mjs.map +1 -1
  588. package/esm/dev-server/file-event-handler.mjs +15 -3
  589. package/esm/dev-server/file-event-handler.mjs.map +1 -1
  590. package/esm/dev-server/module-loader.d.mts +12 -0
  591. package/esm/dev-server/module-loader.d.mts.map +1 -1
  592. package/esm/dev-server/module-loader.mjs +30 -2
  593. package/esm/dev-server/module-loader.mjs.map +1 -1
  594. package/esm/generations/add-command.action.mjs +61 -12
  595. package/esm/generations/add-command.action.mjs.map +1 -1
  596. package/esm/generations/stubs.mjs +31 -1
  597. package/esm/generations/stubs.mjs.map +1 -1
  598. package/esm/http/config.mjs +2 -2
  599. package/esm/http/config.mjs.map +1 -1
  600. package/esm/http/createHttpApplication.mjs +2 -2
  601. package/esm/http/createHttpApplication.mjs.map +1 -1
  602. package/esm/http/health.d.mts +14 -0
  603. package/esm/http/health.d.mts.map +1 -1
  604. package/esm/http/health.mjs +16 -0
  605. package/esm/http/health.mjs.map +1 -1
  606. package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
  607. package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
  608. package/esm/http/middleware/cache-response-middleware.mjs +15 -6
  609. package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
  610. package/esm/http/middleware/concurrency-limit.middleware.mjs +2 -0
  611. package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
  612. package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
  613. package/esm/http/middleware/idempotency.middleware.mjs +9 -6
  614. package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
  615. package/esm/http/middleware/inject-request-context.mjs +2 -2
  616. package/esm/http/middleware/inject-request-context.mjs.map +1 -1
  617. package/esm/http/middleware/maintenance.middleware.mjs +6 -5
  618. package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
  619. package/esm/http/plugins.mjs +9 -9
  620. package/esm/http/plugins.mjs.map +1 -1
  621. package/esm/http/request.d.mts +9 -2
  622. package/esm/http/request.d.mts.map +1 -1
  623. package/esm/http/request.mjs +15 -3
  624. package/esm/http/request.mjs.map +1 -1
  625. package/esm/http/response.d.mts +12 -0
  626. package/esm/http/response.d.mts.map +1 -1
  627. package/esm/http/response.mjs +24 -7
  628. package/esm/http/response.mjs.map +1 -1
  629. package/esm/http/server.d.mts.map +1 -1
  630. package/esm/http/server.mjs +4 -4
  631. package/esm/http/server.mjs.map +1 -1
  632. package/esm/index.d.mts +9 -4
  633. package/esm/index.mjs +6 -1
  634. package/esm/node_modules/langfuse/lib/index.mjs +1827 -0
  635. package/esm/node_modules/langfuse/lib/index.mjs.map +1 -0
  636. package/esm/node_modules/langfuse-core/lib/index.mjs +1770 -0
  637. package/esm/node_modules/langfuse-core/lib/index.mjs.map +1 -0
  638. package/esm/node_modules/mustache/mustache.mjs +587 -0
  639. package/esm/node_modules/mustache/mustache.mjs.map +1 -0
  640. package/esm/node_modules/openai/_vendor/partial-json-parser/parser.mjs +180 -0
  641. package/esm/node_modules/openai/_vendor/partial-json-parser/parser.mjs.map +1 -0
  642. package/esm/node_modules/openai/auth/workload-identity-auth.mjs +80 -0
  643. package/esm/node_modules/openai/auth/workload-identity-auth.mjs.map +1 -0
  644. package/esm/node_modules/openai/azure.mjs +82 -0
  645. package/esm/node_modules/openai/azure.mjs.map +1 -0
  646. package/esm/node_modules/openai/client.mjs +638 -0
  647. package/esm/node_modules/openai/client.mjs.map +1 -0
  648. package/esm/node_modules/openai/core/api-promise.mjs +75 -0
  649. package/esm/node_modules/openai/core/api-promise.mjs.map +1 -0
  650. package/esm/node_modules/openai/core/error.mjs +110 -0
  651. package/esm/node_modules/openai/core/error.mjs.map +1 -0
  652. package/esm/node_modules/openai/core/pagination.mjs +160 -0
  653. package/esm/node_modules/openai/core/pagination.mjs.map +1 -0
  654. package/esm/node_modules/openai/core/resource.mjs +10 -0
  655. package/esm/node_modules/openai/core/resource.mjs.map +1 -0
  656. package/esm/node_modules/openai/core/streaming.mjs +238 -0
  657. package/esm/node_modules/openai/core/streaming.mjs.map +1 -0
  658. package/esm/node_modules/openai/index.mjs +8 -0
  659. package/esm/node_modules/openai/internal/decoders/line.mjs +91 -0
  660. package/esm/node_modules/openai/internal/decoders/line.mjs.map +1 -0
  661. package/esm/node_modules/openai/internal/detect-platform.mjs +123 -0
  662. package/esm/node_modules/openai/internal/detect-platform.mjs.map +1 -0
  663. package/esm/node_modules/openai/internal/errors.mjs +26 -0
  664. package/esm/node_modules/openai/internal/errors.mjs.map +1 -0
  665. package/esm/node_modules/openai/internal/headers.mjs +65 -0
  666. package/esm/node_modules/openai/internal/headers.mjs.map +1 -0
  667. package/esm/node_modules/openai/internal/parse.mjs +41 -0
  668. package/esm/node_modules/openai/internal/parse.mjs.map +1 -0
  669. package/esm/node_modules/openai/internal/qs/formats.mjs +12 -0
  670. package/esm/node_modules/openai/internal/qs/formats.mjs.map +1 -0
  671. package/esm/node_modules/openai/internal/qs/stringify.mjs +179 -0
  672. package/esm/node_modules/openai/internal/qs/stringify.mjs.map +1 -0
  673. package/esm/node_modules/openai/internal/qs/utils.mjs +65 -0
  674. package/esm/node_modules/openai/internal/qs/utils.mjs.map +1 -0
  675. package/esm/node_modules/openai/internal/request-options.mjs +11 -0
  676. package/esm/node_modules/openai/internal/request-options.mjs.map +1 -0
  677. package/esm/node_modules/openai/internal/shims.mjs +77 -0
  678. package/esm/node_modules/openai/internal/shims.mjs.map +1 -0
  679. package/esm/node_modules/openai/internal/to-file.mjs +63 -0
  680. package/esm/node_modules/openai/internal/to-file.mjs.map +1 -0
  681. package/esm/node_modules/openai/internal/tslib.mjs +16 -0
  682. package/esm/node_modules/openai/internal/tslib.mjs.map +1 -0
  683. package/esm/node_modules/openai/internal/uploads.mjs +94 -0
  684. package/esm/node_modules/openai/internal/uploads.mjs.map +1 -0
  685. package/esm/node_modules/openai/internal/utils/base64.mjs +22 -0
  686. package/esm/node_modules/openai/internal/utils/base64.mjs.map +1 -0
  687. package/esm/node_modules/openai/internal/utils/bytes.mjs +26 -0
  688. package/esm/node_modules/openai/internal/utils/bytes.mjs.map +1 -0
  689. package/esm/node_modules/openai/internal/utils/env.mjs +16 -0
  690. package/esm/node_modules/openai/internal/utils/env.mjs.map +1 -0
  691. package/esm/node_modules/openai/internal/utils/log.mjs +58 -0
  692. package/esm/node_modules/openai/internal/utils/log.mjs.map +1 -0
  693. package/esm/node_modules/openai/internal/utils/path.mjs +62 -0
  694. package/esm/node_modules/openai/internal/utils/path.mjs.map +1 -0
  695. package/esm/node_modules/openai/internal/utils/query.mjs +10 -0
  696. package/esm/node_modules/openai/internal/utils/query.mjs.map +1 -0
  697. package/esm/node_modules/openai/internal/utils/sleep.mjs +6 -0
  698. package/esm/node_modules/openai/internal/utils/sleep.mjs.map +1 -0
  699. package/esm/node_modules/openai/internal/utils/uuid.mjs +18 -0
  700. package/esm/node_modules/openai/internal/utils/uuid.mjs.map +1 -0
  701. package/esm/node_modules/openai/internal/utils/values.mjs +41 -0
  702. package/esm/node_modules/openai/internal/utils/values.mjs.map +1 -0
  703. package/esm/node_modules/openai/lib/AbstractChatCompletionRunner.mjs +247 -0
  704. package/esm/node_modules/openai/lib/AbstractChatCompletionRunner.mjs.map +1 -0
  705. package/esm/node_modules/openai/lib/AssistantStream.mjs +472 -0
  706. package/esm/node_modules/openai/lib/AssistantStream.mjs.map +1 -0
  707. package/esm/node_modules/openai/lib/ChatCompletionRunner.mjs +26 -0
  708. package/esm/node_modules/openai/lib/ChatCompletionRunner.mjs.map +1 -0
  709. package/esm/node_modules/openai/lib/ChatCompletionStream.mjs +423 -0
  710. package/esm/node_modules/openai/lib/ChatCompletionStream.mjs.map +1 -0
  711. package/esm/node_modules/openai/lib/ChatCompletionStreamingRunner.mjs +26 -0
  712. package/esm/node_modules/openai/lib/ChatCompletionStreamingRunner.mjs.map +1 -0
  713. package/esm/node_modules/openai/lib/EventStream.mjs +163 -0
  714. package/esm/node_modules/openai/lib/EventStream.mjs.map +1 -0
  715. package/esm/node_modules/openai/lib/ResponsesParser.mjs +94 -0
  716. package/esm/node_modules/openai/lib/ResponsesParser.mjs.map +1 -0
  717. package/esm/node_modules/openai/lib/RunnableFunction.mjs +8 -0
  718. package/esm/node_modules/openai/lib/RunnableFunction.mjs.map +1 -0
  719. package/esm/node_modules/openai/lib/Util.mjs +19 -0
  720. package/esm/node_modules/openai/lib/Util.mjs.map +1 -0
  721. package/esm/node_modules/openai/lib/chatCompletionUtils.mjs +11 -0
  722. package/esm/node_modules/openai/lib/chatCompletionUtils.mjs.map +1 -0
  723. package/esm/node_modules/openai/lib/parser.mjs +88 -0
  724. package/esm/node_modules/openai/lib/parser.mjs.map +1 -0
  725. package/esm/node_modules/openai/lib/responses/ResponseStream.mjs +231 -0
  726. package/esm/node_modules/openai/lib/responses/ResponseStream.mjs.map +1 -0
  727. package/esm/node_modules/openai/resources/admin/admin.mjs +15 -0
  728. package/esm/node_modules/openai/resources/admin/admin.mjs.map +1 -0
  729. package/esm/node_modules/openai/resources/admin/organization/admin-api-keys.mjs +81 -0
  730. package/esm/node_modules/openai/resources/admin/organization/admin-api-keys.mjs.map +1 -0
  731. package/esm/node_modules/openai/resources/admin/organization/audit-logs.mjs +31 -0
  732. package/esm/node_modules/openai/resources/admin/organization/audit-logs.mjs.map +1 -0
  733. package/esm/node_modules/openai/resources/admin/organization/certificates.mjs +153 -0
  734. package/esm/node_modules/openai/resources/admin/organization/certificates.mjs.map +1 -0
  735. package/esm/node_modules/openai/resources/admin/organization/data-retention.mjs +42 -0
  736. package/esm/node_modules/openai/resources/admin/organization/data-retention.mjs.map +1 -0
  737. package/esm/node_modules/openai/resources/admin/organization/groups/groups.mjs +106 -0
  738. package/esm/node_modules/openai/resources/admin/organization/groups/groups.mjs.map +1 -0
  739. package/esm/node_modules/openai/resources/admin/organization/groups/roles.mjs +88 -0
  740. package/esm/node_modules/openai/resources/admin/organization/groups/roles.mjs.map +1 -0
  741. package/esm/node_modules/openai/resources/admin/organization/groups/users.mjs +88 -0
  742. package/esm/node_modules/openai/resources/admin/organization/groups/users.mjs.map +1 -0
  743. package/esm/node_modules/openai/resources/admin/organization/invites.mjs +83 -0
  744. package/esm/node_modules/openai/resources/admin/organization/invites.mjs.map +1 -0
  745. package/esm/node_modules/openai/resources/admin/organization/organization.mjs +45 -0
  746. package/esm/node_modules/openai/resources/admin/organization/organization.mjs.map +1 -0
  747. package/esm/node_modules/openai/resources/admin/organization/projects/api-keys.mjs +72 -0
  748. package/esm/node_modules/openai/resources/admin/organization/projects/api-keys.mjs.map +1 -0
  749. package/esm/node_modules/openai/resources/admin/organization/projects/certificates.mjs +78 -0
  750. package/esm/node_modules/openai/resources/admin/organization/projects/certificates.mjs.map +1 -0
  751. package/esm/node_modules/openai/resources/admin/organization/projects/data-retention.mjs +46 -0
  752. package/esm/node_modules/openai/resources/admin/organization/projects/data-retention.mjs.map +1 -0
  753. package/esm/node_modules/openai/resources/admin/organization/projects/groups/groups.mjs +95 -0
  754. package/esm/node_modules/openai/resources/admin/organization/projects/groups/groups.mjs.map +1 -0
  755. package/esm/node_modules/openai/resources/admin/organization/projects/groups/roles.mjs +91 -0
  756. package/esm/node_modules/openai/resources/admin/organization/projects/groups/roles.mjs.map +1 -0
  757. package/esm/node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs +45 -0
  758. package/esm/node_modules/openai/resources/admin/organization/projects/hosted-tool-permissions.mjs.map +1 -0
  759. package/esm/node_modules/openai/resources/admin/organization/projects/model-permissions.mjs +63 -0
  760. package/esm/node_modules/openai/resources/admin/organization/projects/model-permissions.mjs.map +1 -0
  761. package/esm/node_modules/openai/resources/admin/organization/projects/projects.mjs +137 -0
  762. package/esm/node_modules/openai/resources/admin/organization/projects/projects.mjs.map +1 -0
  763. package/esm/node_modules/openai/resources/admin/organization/projects/rate-limits.mjs +51 -0
  764. package/esm/node_modules/openai/resources/admin/organization/projects/rate-limits.mjs.map +1 -0
  765. package/esm/node_modules/openai/resources/admin/organization/projects/roles.mjs +108 -0
  766. package/esm/node_modules/openai/resources/admin/organization/projects/roles.mjs.map +1 -0
  767. package/esm/node_modules/openai/resources/admin/organization/projects/service-accounts.mjs +112 -0
  768. package/esm/node_modules/openai/resources/admin/organization/projects/service-accounts.mjs.map +1 -0
  769. package/esm/node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs +106 -0
  770. package/esm/node_modules/openai/resources/admin/organization/projects/spend-alerts.mjs.map +1 -0
  771. package/esm/node_modules/openai/resources/admin/organization/projects/users/roles.mjs +91 -0
  772. package/esm/node_modules/openai/resources/admin/organization/projects/users/roles.mjs.map +1 -0
  773. package/esm/node_modules/openai/resources/admin/organization/projects/users/users.mjs +118 -0
  774. package/esm/node_modules/openai/resources/admin/organization/projects/users/users.mjs.map +1 -0
  775. package/esm/node_modules/openai/resources/admin/organization/roles.mjs +96 -0
  776. package/esm/node_modules/openai/resources/admin/organization/roles.mjs.map +1 -0
  777. package/esm/node_modules/openai/resources/admin/organization/spend-alerts.mjs +97 -0
  778. package/esm/node_modules/openai/resources/admin/organization/spend-alerts.mjs.map +1 -0
  779. package/esm/node_modules/openai/resources/admin/organization/usage.mjs +207 -0
  780. package/esm/node_modules/openai/resources/admin/organization/usage.mjs.map +1 -0
  781. package/esm/node_modules/openai/resources/admin/organization/users/roles.mjs +88 -0
  782. package/esm/node_modules/openai/resources/admin/organization/users/roles.mjs.map +1 -0
  783. package/esm/node_modules/openai/resources/admin/organization/users/users.mjs +82 -0
  784. package/esm/node_modules/openai/resources/admin/organization/users/users.mjs.map +1 -0
  785. package/esm/node_modules/openai/resources/audio/audio.mjs +21 -0
  786. package/esm/node_modules/openai/resources/audio/audio.mjs.map +1 -0
  787. package/esm/node_modules/openai/resources/audio/speech.mjs +39 -0
  788. package/esm/node_modules/openai/resources/audio/speech.mjs.map +1 -0
  789. package/esm/node_modules/openai/resources/audio/transcriptions.mjs +22 -0
  790. package/esm/node_modules/openai/resources/audio/transcriptions.mjs.map +1 -0
  791. package/esm/node_modules/openai/resources/audio/translations.mjs +21 -0
  792. package/esm/node_modules/openai/resources/audio/translations.mjs.map +1 -0
  793. package/esm/node_modules/openai/resources/batches.mjs +54 -0
  794. package/esm/node_modules/openai/resources/batches.mjs.map +1 -0
  795. package/esm/node_modules/openai/resources/beta/assistants.mjs +78 -0
  796. package/esm/node_modules/openai/resources/beta/assistants.mjs.map +1 -0
  797. package/esm/node_modules/openai/resources/beta/beta.mjs +24 -0
  798. package/esm/node_modules/openai/resources/beta/beta.mjs.map +1 -0
  799. package/esm/node_modules/openai/resources/beta/chatkit/chatkit.mjs +18 -0
  800. package/esm/node_modules/openai/resources/beta/chatkit/chatkit.mjs.map +1 -0
  801. package/esm/node_modules/openai/resources/beta/chatkit/sessions.mjs +49 -0
  802. package/esm/node_modules/openai/resources/beta/chatkit/sessions.mjs.map +1 -0
  803. package/esm/node_modules/openai/resources/beta/chatkit/threads.mjs +85 -0
  804. package/esm/node_modules/openai/resources/beta/chatkit/threads.mjs.map +1 -0
  805. package/esm/node_modules/openai/resources/beta/realtime/realtime.mjs +21 -0
  806. package/esm/node_modules/openai/resources/beta/realtime/realtime.mjs.map +1 -0
  807. package/esm/node_modules/openai/resources/beta/realtime/sessions.mjs +33 -0
  808. package/esm/node_modules/openai/resources/beta/realtime/sessions.mjs.map +1 -0
  809. package/esm/node_modules/openai/resources/beta/realtime/transcription-sessions.mjs +33 -0
  810. package/esm/node_modules/openai/resources/beta/realtime/transcription-sessions.mjs.map +1 -0
  811. package/esm/node_modules/openai/resources/beta/threads/messages.mjs +83 -0
  812. package/esm/node_modules/openai/resources/beta/threads/messages.mjs.map +1 -0
  813. package/esm/node_modules/openai/resources/beta/threads/runs/runs.mjs +183 -0
  814. package/esm/node_modules/openai/resources/beta/threads/runs/runs.mjs.map +1 -0
  815. package/esm/node_modules/openai/resources/beta/threads/runs/steps.mjs +45 -0
  816. package/esm/node_modules/openai/resources/beta/threads/runs/steps.mjs.map +1 -0
  817. package/esm/node_modules/openai/resources/beta/threads/threads.mjs +101 -0
  818. package/esm/node_modules/openai/resources/beta/threads/threads.mjs.map +1 -0
  819. package/esm/node_modules/openai/resources/chat/chat.mjs +15 -0
  820. package/esm/node_modules/openai/resources/chat/chat.mjs.map +1 -0
  821. package/esm/node_modules/openai/resources/chat/completions/completions.mjs +123 -0
  822. package/esm/node_modules/openai/resources/chat/completions/completions.mjs.map +1 -0
  823. package/esm/node_modules/openai/resources/chat/completions/index.mjs +7 -0
  824. package/esm/node_modules/openai/resources/chat/completions/messages.mjs +35 -0
  825. package/esm/node_modules/openai/resources/chat/completions/messages.mjs.map +1 -0
  826. package/esm/node_modules/openai/resources/chat/index.mjs +5 -0
  827. package/esm/node_modules/openai/resources/completions.mjs +20 -0
  828. package/esm/node_modules/openai/resources/completions.mjs.map +1 -0
  829. package/esm/node_modules/openai/resources/containers/containers.mjs +57 -0
  830. package/esm/node_modules/openai/resources/containers/containers.mjs.map +1 -0
  831. package/esm/node_modules/openai/resources/containers/files/content.mjs +23 -0
  832. package/esm/node_modules/openai/resources/containers/files/content.mjs.map +1 -0
  833. package/esm/node_modules/openai/resources/containers/files/files.mjs +63 -0
  834. package/esm/node_modules/openai/resources/containers/files/files.mjs.map +1 -0
  835. package/esm/node_modules/openai/resources/conversations/conversations.mjs +57 -0
  836. package/esm/node_modules/openai/resources/conversations/conversations.mjs.map +1 -0
  837. package/esm/node_modules/openai/resources/conversations/items.mjs +57 -0
  838. package/esm/node_modules/openai/resources/conversations/items.mjs.map +1 -0
  839. package/esm/node_modules/openai/resources/embeddings.mjs +48 -0
  840. package/esm/node_modules/openai/resources/embeddings.mjs.map +1 -0
  841. package/esm/node_modules/openai/resources/evals/evals.mjs +73 -0
  842. package/esm/node_modules/openai/resources/evals/evals.mjs.map +1 -0
  843. package/esm/node_modules/openai/resources/evals/runs/output-items.mjs +35 -0
  844. package/esm/node_modules/openai/resources/evals/runs/output-items.mjs.map +1 -0
  845. package/esm/node_modules/openai/resources/evals/runs/runs.mjs +72 -0
  846. package/esm/node_modules/openai/resources/evals/runs/runs.mjs.map +1 -0
  847. package/esm/node_modules/openai/resources/files.mjs +111 -0
  848. package/esm/node_modules/openai/resources/files.mjs.map +1 -0
  849. package/esm/node_modules/openai/resources/fine-tuning/alpha/alpha.mjs +15 -0
  850. package/esm/node_modules/openai/resources/fine-tuning/alpha/alpha.mjs.map +1 -0
  851. package/esm/node_modules/openai/resources/fine-tuning/alpha/graders.mjs +60 -0
  852. package/esm/node_modules/openai/resources/fine-tuning/alpha/graders.mjs.map +1 -0
  853. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs +15 -0
  854. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/checkpoints.mjs.map +1 -0
  855. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs +102 -0
  856. package/esm/node_modules/openai/resources/fine-tuning/checkpoints/permissions.mjs.map +1 -0
  857. package/esm/node_modules/openai/resources/fine-tuning/fine-tuning.mjs +24 -0
  858. package/esm/node_modules/openai/resources/fine-tuning/fine-tuning.mjs.map +1 -0
  859. package/esm/node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs +34 -0
  860. package/esm/node_modules/openai/resources/fine-tuning/jobs/checkpoints.mjs.map +1 -0
  861. package/esm/node_modules/openai/resources/fine-tuning/jobs/jobs.mjs +148 -0
  862. package/esm/node_modules/openai/resources/fine-tuning/jobs/jobs.mjs.map +1 -0
  863. package/esm/node_modules/openai/resources/fine-tuning/methods.mjs +8 -0
  864. package/esm/node_modules/openai/resources/fine-tuning/methods.mjs.map +1 -0
  865. package/esm/node_modules/openai/resources/graders/grader-models.mjs +8 -0
  866. package/esm/node_modules/openai/resources/graders/grader-models.mjs.map +1 -0
  867. package/esm/node_modules/openai/resources/graders/graders.mjs +15 -0
  868. package/esm/node_modules/openai/resources/graders/graders.mjs.map +1 -0
  869. package/esm/node_modules/openai/resources/images.mjs +46 -0
  870. package/esm/node_modules/openai/resources/images.mjs.map +1 -0
  871. package/esm/node_modules/openai/resources/index.mjs +27 -0
  872. package/esm/node_modules/openai/resources/models.mjs +44 -0
  873. package/esm/node_modules/openai/resources/models.mjs.map +1 -0
  874. package/esm/node_modules/openai/resources/moderations.mjs +23 -0
  875. package/esm/node_modules/openai/resources/moderations.mjs.map +1 -0
  876. package/esm/node_modules/openai/resources/realtime/calls.mjs +79 -0
  877. package/esm/node_modules/openai/resources/realtime/calls.mjs.map +1 -0
  878. package/esm/node_modules/openai/resources/realtime/client-secrets.mjs +39 -0
  879. package/esm/node_modules/openai/resources/realtime/client-secrets.mjs.map +1 -0
  880. package/esm/node_modules/openai/resources/realtime/realtime.mjs +18 -0
  881. package/esm/node_modules/openai/resources/realtime/realtime.mjs.map +1 -0
  882. package/esm/node_modules/openai/resources/responses/input-items.mjs +31 -0
  883. package/esm/node_modules/openai/resources/responses/input-items.mjs.map +1 -0
  884. package/esm/node_modules/openai/resources/responses/input-tokens.mjs +27 -0
  885. package/esm/node_modules/openai/resources/responses/input-tokens.mjs.map +1 -0
  886. package/esm/node_modules/openai/resources/responses/responses.mjs +110 -0
  887. package/esm/node_modules/openai/resources/responses/responses.mjs.map +1 -0
  888. package/esm/node_modules/openai/resources/skills/content.mjs +22 -0
  889. package/esm/node_modules/openai/resources/skills/content.mjs.map +1 -0
  890. package/esm/node_modules/openai/resources/skills/skills.mjs +69 -0
  891. package/esm/node_modules/openai/resources/skills/skills.mjs.map +1 -0
  892. package/esm/node_modules/openai/resources/skills/versions/content.mjs +23 -0
  893. package/esm/node_modules/openai/resources/skills/versions/content.mjs.map +1 -0
  894. package/esm/node_modules/openai/resources/skills/versions/versions.mjs +58 -0
  895. package/esm/node_modules/openai/resources/skills/versions/versions.mjs.map +1 -0
  896. package/esm/node_modules/openai/resources/uploads/parts.mjs +34 -0
  897. package/esm/node_modules/openai/resources/uploads/parts.mjs.map +1 -0
  898. package/esm/node_modules/openai/resources/uploads/uploads.mjs +84 -0
  899. package/esm/node_modules/openai/resources/uploads/uploads.mjs.map +1 -0
  900. package/esm/node_modules/openai/resources/vector-stores/file-batches.mjs +126 -0
  901. package/esm/node_modules/openai/resources/vector-stores/file-batches.mjs.map +1 -0
  902. package/esm/node_modules/openai/resources/vector-stores/files.mjs +147 -0
  903. package/esm/node_modules/openai/resources/vector-stores/files.mjs.map +1 -0
  904. package/esm/node_modules/openai/resources/vector-stores/vector-stores.mjs +87 -0
  905. package/esm/node_modules/openai/resources/vector-stores/vector-stores.mjs.map +1 -0
  906. package/esm/node_modules/openai/resources/videos.mjs +115 -0
  907. package/esm/node_modules/openai/resources/videos.mjs.map +1 -0
  908. package/esm/node_modules/openai/resources/webhooks/index.mjs +3 -0
  909. package/esm/node_modules/openai/resources/webhooks/webhooks.mjs +69 -0
  910. package/esm/node_modules/openai/resources/webhooks/webhooks.mjs.map +1 -0
  911. package/esm/node_modules/openai/resources/webhooks.mjs +4 -0
  912. package/esm/node_modules/openai/streaming.mjs +3 -0
  913. package/esm/node_modules/openai/version.mjs +6 -0
  914. package/esm/node_modules/openai/version.mjs.map +1 -0
  915. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +37 -1
  916. package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
  917. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +71 -5
  918. package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
  919. package/esm/repositories/adapters/cascade/filter-applicator.mjs +17 -3
  920. package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
  921. package/esm/repositories/contracts/index.d.mts +1 -1
  922. package/esm/repositories/contracts/query-builder.contract.d.mts +87 -1
  923. package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
  924. package/esm/repositories/index.d.mts +1 -1
  925. package/esm/repositories/repository.manager.d.mts +110 -2
  926. package/esm/repositories/repository.manager.d.mts.map +1 -1
  927. package/esm/repositories/repository.manager.mjs +207 -25
  928. package/esm/repositories/repository.manager.mjs.map +1 -1
  929. package/esm/router/route-registry.mjs +19 -10
  930. package/esm/router/route-registry.mjs.map +1 -1
  931. package/esm/router/router.d.mts +9 -0
  932. package/esm/router/router.d.mts.map +1 -1
  933. package/esm/router/router.mjs +28 -5
  934. package/esm/router/router.mjs.map +1 -1
  935. package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
  936. package/esm/storage/drivers/cloud-driver.mjs +48 -12
  937. package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
  938. package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
  939. package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
  940. package/esm/storage/drivers/local-driver.d.mts +8 -0
  941. package/esm/storage/drivers/local-driver.d.mts.map +1 -1
  942. package/esm/storage/drivers/local-driver.mjs +19 -4
  943. package/esm/storage/drivers/local-driver.mjs.map +1 -1
  944. package/esm/storage/drivers/r2-driver.mjs +1 -1
  945. package/esm/storage/drivers/r2-driver.mjs.map +1 -1
  946. package/esm/storage/drivers/s3-driver.mjs +1 -1
  947. package/esm/storage/drivers/s3-driver.mjs.map +1 -1
  948. package/esm/storage/index.d.mts +4 -1
  949. package/esm/storage/index.mjs +3 -0
  950. package/esm/storage/scoped-storage.d.mts +8 -4
  951. package/esm/storage/scoped-storage.d.mts.map +1 -1
  952. package/esm/storage/scoped-storage.mjs +21 -6
  953. package/esm/storage/scoped-storage.mjs.map +1 -1
  954. package/esm/storage/storage.d.mts +12 -4
  955. package/esm/storage/storage.d.mts.map +1 -1
  956. package/esm/storage/storage.mjs +23 -9
  957. package/esm/storage/storage.mjs.map +1 -1
  958. package/esm/storage/types.d.mts +33 -5
  959. package/esm/storage/types.d.mts.map +1 -1
  960. package/esm/storage/utils/contain-path.d.mts +23 -0
  961. package/esm/storage/utils/contain-path.d.mts.map +1 -0
  962. package/esm/storage/utils/contain-path.mjs +35 -0
  963. package/esm/storage/utils/contain-path.mjs.map +1 -0
  964. package/esm/storage/utils/safe-fetch.d.mts +68 -0
  965. package/esm/storage/utils/safe-fetch.d.mts.map +1 -0
  966. package/esm/storage/utils/safe-fetch.mjs +205 -0
  967. package/esm/storage/utils/safe-fetch.mjs.map +1 -0
  968. package/esm/storage/utils/storage-error.d.mts +35 -0
  969. package/esm/storage/utils/storage-error.d.mts.map +1 -0
  970. package/esm/storage/utils/storage-error.mjs +17 -0
  971. package/esm/storage/utils/storage-error.mjs.map +1 -0
  972. package/esm/use-cases/use-case-pipeline.mjs +4 -1
  973. package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
  974. package/esm/use-cases/use-case.mjs +12 -4
  975. package/esm/use-cases/use-case.mjs.map +1 -1
  976. package/esm/use-cases/use-cases-registry.d.mts +12 -4
  977. package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
  978. package/esm/use-cases/use-cases-registry.mjs +13 -3
  979. package/esm/use-cases/use-cases-registry.mjs.map +1 -1
  980. package/esm/utils/npm-registry.d.mts +1 -1
  981. package/esm/utils/npm-registry.mjs +2 -2
  982. package/esm/utils/npm-registry.mjs.map +1 -1
  983. package/esm/utils/paths.mjs +2 -2
  984. package/esm/utils/paths.mjs.map +1 -1
  985. package/esm/validation/validateAll.mjs +2 -2
  986. package/esm/validation/validateAll.mjs.map +1 -1
  987. package/llms-full.txt +456 -46
  988. package/llms.txt +4 -2
  989. package/package.json +9 -9
  990. package/skills/README.md +65 -0
  991. package/skills/add-connector/SKILL.md +6 -1
  992. package/skills/configure-app/SKILL.md +23 -0
  993. package/skills/health-checks/SKILL.md +13 -0
  994. package/skills/use-repository/SKILL.md +38 -1
  995. package/skills/warlock-doctor/SKILL.md +135 -0
  996. package/skills/warlock-routes/SKILL.md +91 -0
  997. package/skills/write-seeder/SKILL.md +143 -45
@@ -43,7 +43,7 @@ var DOSpacesDriver = class extends CloudDriver {
43
43
  * Note: DO Spaces includes automatic CDN with the `.cdn.` subdomain
44
44
  */
45
45
  url(location) {
46
- if (this.options.urlPrefix) location = `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
46
+ if (this.options.urlPrefix) return `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
47
47
  return `https://${this.options.bucket}.${this.options.region}.cdn.digitaloceanspaces.com/${location}`;
48
48
  }
49
49
  };
@@ -1 +1 @@
1
- {"version":3,"file":"do-spaces-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/do-spaces-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { CloudStorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * DigitalOcean Spaces Storage Driver\n *\n * Spaces is S3-compatible with a different URL structure.\n *\n * URL Patterns:\n * - With urlPrefix: {urlPrefix}/{key}\n * - CDN URL: https://{bucket}.{region}.cdn.digitaloceanspaces.com/{key}\n * - Origin URL: https://{bucket}.{region}.digitaloceanspaces.com/{key}\n *\n * Regions: nyc3, sfo3, ams3, sgp1, fra1, etc.\n *\n * @example\n * ```typescript\n * const driver = new DOSpacesDriver({\n * bucket: \"my-space\",\n * region: \"nyc3\",\n * accessKeyId: process.env.DO_SPACES_KEY,\n * secretAccessKey: process.env.DO_SPACES_SECRET,\n * });\n * ```\n */\nexport class DOSpacesDriver extends CloudDriver<CloudStorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"spaces\";\n\n /**\n * Get Spaces endpoint URL\n *\n * Spaces endpoint format: https://{region}.digitaloceanspaces.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.region}.digitaloceanspaces.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Note: DO Spaces includes automatic CDN with the `.cdn.` subdomain\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n location = `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Default Spaces CDN URL\n return `https://${this.options.bucket}.${this.options.region}.cdn.digitaloceanspaces.com/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,iBAAb,cAAoC,YAAuC;;;cAIlD;;;;;;;CAOvB,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,OAAO;CACjE;;;;;;CAOA,AAAO,IAAI,UAA0B;EAEnC,IAAI,KAAK,QAAQ,WAEf,WAAW,GADI,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACnC,EAAE,GAAG,MAAM,UAAU,GAAG;EAI7C,OAAO,WAAW,KAAK,QAAQ,OAAO,GAAG,KAAK,QAAQ,OAAO,8BAA8B;CAC7F;AACF"}
1
+ {"version":3,"file":"do-spaces-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/do-spaces-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { CloudStorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * DigitalOcean Spaces Storage Driver\n *\n * Spaces is S3-compatible with a different URL structure.\n *\n * URL Patterns:\n * - With urlPrefix: {urlPrefix}/{key}\n * - CDN URL: https://{bucket}.{region}.cdn.digitaloceanspaces.com/{key}\n * - Origin URL: https://{bucket}.{region}.digitaloceanspaces.com/{key}\n *\n * Regions: nyc3, sfo3, ams3, sgp1, fra1, etc.\n *\n * @example\n * ```typescript\n * const driver = new DOSpacesDriver({\n * bucket: \"my-space\",\n * region: \"nyc3\",\n * accessKeyId: process.env.DO_SPACES_KEY,\n * secretAccessKey: process.env.DO_SPACES_SECRET,\n * });\n * ```\n */\nexport class DOSpacesDriver extends CloudDriver<CloudStorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"spaces\";\n\n /**\n * Get Spaces endpoint URL\n *\n * Spaces endpoint format: https://{region}.digitaloceanspaces.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.region}.digitaloceanspaces.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Note: DO Spaces includes automatic CDN with the `.cdn.` subdomain\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured — return it directly so the CDN-host\n // URL below is NOT appended (which would yield a double-host URL).\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n return `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Default Spaces CDN URL\n return `https://${this.options.bucket}.${this.options.region}.cdn.digitaloceanspaces.com/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,iBAAb,cAAoC,YAAuC;;;cAIlD;;;;;;;CAOvB,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,OAAO;CACjE;;;;;;CAOA,AAAO,IAAI,UAA0B;EAGnC,IAAI,KAAK,QAAQ,WAEf,OAAO,GADQ,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACvC,EAAE,GAAG,MAAM,UAAU,GAAG;EAIzC,OAAO,WAAW,KAAK,QAAQ,OAAO,GAAG,KAAK,QAAQ,OAAO,8BAA8B;CAC7F;AACF"}
@@ -75,6 +75,10 @@ declare class LocalDriver implements StorageDriverContract {
75
75
  deleteMany(locations: string[]): Promise<DeleteManyResult[]>;
76
76
  /**
77
77
  * Delete directory
78
+ *
79
+ * The directory path is resolved through {@link getAbsolutePath} so it is
80
+ * contained within the storage root — the raw, caller-supplied argument is
81
+ * never handed to the filesystem (preventing `../` traversal deletes).
78
82
  */
79
83
  deleteDirectory(directoryPath: string): Promise<boolean>;
80
84
  /**
@@ -137,6 +141,10 @@ declare class LocalDriver implements StorageDriverContract {
137
141
  getRoot(): string;
138
142
  /**
139
143
  * Get absolute file path
144
+ *
145
+ * Routes through {@link resolveWithinRoot} so a location can never escape
146
+ * the configured storage root via `..` traversal, an absolute path, or a
147
+ * prefix breakout.
140
148
  */
141
149
  protected getAbsolutePath(location: string): string;
142
150
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"local-driver.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/local-driver.ts"],"mappings":";;;;;;;;AAyCA;;;;;;cAAa,WAAA,YAAuB,qBAAA;EA+BR,OAAA,EAAS,yBAAA;EAgD3B;;;EAAA,SA3EQ,IAAA,EAAM,iBAAA;EA8EnB;;;EAAA,UAzEO,IAAA;EAuGP;;;EAAA,UAlGO,SAAA;EA2IgC;;;EAAA,UAtIhC,kBAAA;EAuLwC;;;EAAA,UAlLxC,YAAA;EA4P0C;;;EAAA,UAvP1C,SAAA,EAAS,GAAA,SAAA,eAAA;cAEO,OAAA,GAAS,yBAAA;EA0WU;;;;;;;;;EAtVtC,WAAA,CAAY,QAAA;EAuea;;;EA5cnB,GAAA,CACX,IAAA,EAAM,MAAA,YAAkB,YAAA,EACxB,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EAlFuB;;;EA4GrB,SAAA,CACX,MAAA,EAAQ,QAAA,EACR,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EA5GW;;;EAwIT,GAAA,CAAI,QAAA,WAAmB,OAAA,CAAQ,MAAA;EApHlC;;;EAiIG,SAAA,CAAU,QAAA,WAAmB,OAAA,CAAQ,QAAA;;;;EAarC,MAAA,CAAO,QAAA,WAAmB,OAAA;EAnHpB;;;EAiIN,UAAA,CAAW,SAAA,aAAsB,OAAA,CAAQ,gBAAA;EArGpD;;;EA2HW,eAAA,CAAgB,aAAA,WAAqB,OAAA;EAxH/C;;;EAiIU,MAAA,CAAO,QAAA,WAAmB,OAAA;EAtGrC;;;EAkHK,GAAA,CAAI,QAAA;EA/GR;;;;;;;EA0HU,YAAA,CAAa,QAAA,UAAkB,SAAA,YAAmB,OAAA;EAjFrB;;;;;;EAmGnC,oBAAA,CAAqB,QAAA,UAAkB,SAAA;EAxEA;;;;;;EAgGjC,sBAAA,CAAuB,KAAA,WAAgB,OAAA,CAAQ,wBAAA;EAjErB;;;EA6I1B,QAAA,CAAS,QAAA,WAAmB,OAAA,CAAQ,eAAA;EAtHvB;;;EAmJb,IAAA,CAAK,QAAA,WAAmB,OAAA;EAjIT;;;EA6If,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EArHD;;;EAiJvC,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EArEZ;;;EAiG5B,IAAA,CAAK,SAAA,UAAmB,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,eAAA;EApEhC;;;EAoH9B,IAAA,CAAK,QAAA;EAxGiC;;;EA+GtC,OAAA;EAnFyB;;;EAAA,UA8FtB,eAAA,CAAgB,QAAA;EAlER;;;EAAA,UA0EF,QAAA,CAAS,IAAA,EAAM,MAAA,YAAkB,YAAA,GAAe,OAAA,CAAQ,MAAA;EA1EH;;;EAAA,UAyF3D,aAAA,CAAc,MAAA,EAAQ,MAAA;EAvBtB;;;EAAA,UA8BA,aAAA,CAAc,QAAA;AAAA"}
1
+ {"version":3,"file":"local-driver.d.mts","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/local-driver.ts"],"mappings":";;;;;;;;AA0CA;;;;;;cAAa,WAAA,YAAuB,qBAAA;EA+BR,OAAA,EAAS,yBAAA;EAmD3B;;;EAAA,SA9EQ,IAAA,EAAM,iBAAA;EAiFnB;;;EAAA,UA5EO,IAAA;EA6GP;;;EAAA,UAxGO,SAAA;EAoJgC;;;EAAA,UA/IhC,kBAAA;EAwMwC;;;EAAA,UAnMxC,YAAA;EA+Q0C;;;EAAA,UA1Q1C,SAAA,EAAS,GAAA,SAAA,eAAA;cAEO,OAAA,GAAS,yBAAA;EA6XU;;;;;;;;;EAtWtC,WAAA,CAAY,QAAA;EAkgBa;;;EAvenB,GAAA,CACX,IAAA,EAAM,MAAA,YAAkB,YAAA,EACxB,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EArFuB;;;EAkHrB,SAAA,CACX,MAAA,EAAQ,QAAA,EACR,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EAlHW;;;EAiJT,GAAA,CAAI,QAAA,WAAmB,OAAA,CAAQ,MAAA;EA7HlC;;;EA0IG,SAAA,CAAU,QAAA,WAAmB,OAAA,CAAQ,QAAA;;;;EAarC,MAAA,CAAO,QAAA,WAAmB,OAAA;EAzHpB;;;EA2IN,UAAA,CAAW,SAAA,aAAsB,OAAA,CAAQ,gBAAA;EA/GpD;;;;;;;EAyIW,eAAA,CAAgB,aAAA,WAAqB,OAAA;EAxGhD;;;EAmHW,MAAA,CAAO,QAAA,WAAmB,OAAA;EAhHpC;;;EA4HI,GAAA,CAAI,QAAA;EA7FyB;;;;;;;EAwGvB,YAAA,CAAa,QAAA,UAAkB,SAAA,YAAmB,OAAA;EA9ExB;;;;;;EAgGhC,oBAAA,CAAqB,QAAA,UAAkB,SAAA;EApDI;;;;;;EA4ErC,sBAAA,CAAuB,KAAA,WAAgB,OAAA,CAAQ,wBAAA;EA1ClC;;;EAsHb,QAAA,CAAS,QAAA,WAAmB,OAAA,CAAQ,eAAA;EApGrB;;;EAiIf,IAAA,CAAK,QAAA,WAAmB,OAAA;EAzGe;;;EAqHvC,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EAzCZ;;;EAwE5B,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EA3ChB;;;EA2ExB,IAAA,CAAK,SAAA,UAAmB,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,eAAA;EA/DxB;;;EA+GtC,IAAA,CAAK,QAAA;EAhFoB;;;EAuFzB,OAAA;EAvDW;;;;;;;EAAA,UAsER,eAAA,CAAgB,QAAA;EAAhB;;;EAAA,UAQM,QAAA,CAAS,IAAA,EAAM,MAAA,YAAkB,YAAA,GAAe,OAAA,CAAQ,MAAA;EAAvB;;;EAAA,UAevC,aAAA,CAAc,MAAA,EAAQ,MAAA;EAAtB;;;EAAA,UAOA,aAAA,CAAc,QAAA;AAAA"}
@@ -2,7 +2,8 @@ import { storagePath } from "../../utils/paths.mjs";
2
2
  import { url } from "../../utils/urls.mjs";
3
3
  import { storageDriverContext } from "../context/storage-driver-context.mjs";
4
4
  import { getMimeType } from "../utils/mime.mjs";
5
- import { dirname, join } from "path";
5
+ import { resolveWithinRoot } from "../utils/contain-path.mjs";
6
+ import { dirname, join, resolve } from "path";
6
7
  import { ltrim } from "@mongez/reinforcements";
7
8
  import { directoryExistsAsync, ensureDirectoryAsync, fileExistsAsync, removeDirectoryAsync, unlinkAsync } from "@warlock.js/fs";
8
9
  import { createReadStream, createWriteStream } from "fs";
@@ -26,7 +27,7 @@ var LocalDriver = class {
26
27
  this.name = "local";
27
28
  this.urlPrefix = "";
28
29
  this._metadata = /* @__PURE__ */ new Map();
29
- this.root = options.root ?? storagePath();
30
+ this.root = resolve(options.root ?? storagePath());
30
31
  this.urlPrefix = options.urlPrefix ?? "";
31
32
  this.temporaryUrlPrefix = options.temporaryUrlPrefix ?? "/temp-files";
32
33
  this.signatureKey = options.signatureKey;
@@ -57,6 +58,7 @@ var LocalDriver = class {
57
58
  const fileBuffer = await this.toBuffer(file);
58
59
  const hash = this.calculateHash(fileBuffer);
59
60
  await writeFile(absolutePath, new Uint8Array(fileBuffer));
61
+ this._metadata.delete(location);
60
62
  const stats = await stat(absolutePath);
61
63
  const mimeType = options?.mimeType || this.guessMimeType(location);
62
64
  return {
@@ -75,6 +77,7 @@ var LocalDriver = class {
75
77
  const absolutePath = this.getAbsolutePath(location);
76
78
  await ensureDirectoryAsync(dirname(absolutePath));
77
79
  await pipeline(stream, createWriteStream(absolutePath));
80
+ this._metadata.delete(location);
78
81
  const fileBuffer = await readFile(absolutePath);
79
82
  const hash = this.calculateHash(fileBuffer);
80
83
  const stats = await stat(absolutePath);
@@ -111,6 +114,7 @@ var LocalDriver = class {
111
114
  const absolutePath = this.getAbsolutePath(location);
112
115
  if (!await fileExistsAsync(absolutePath)) return false;
113
116
  await unlinkAsync(absolutePath);
117
+ this._metadata.delete(location);
114
118
  return true;
115
119
  }
116
120
  /**
@@ -135,9 +139,13 @@ var LocalDriver = class {
135
139
  }
136
140
  /**
137
141
  * Delete directory
142
+ *
143
+ * The directory path is resolved through {@link getAbsolutePath} so it is
144
+ * contained within the storage root — the raw, caller-supplied argument is
145
+ * never handed to the filesystem (preventing `../` traversal deletes).
138
146
  */
139
147
  async deleteDirectory(directoryPath) {
140
- await removeDirectoryAsync(directoryPath);
148
+ await removeDirectoryAsync(this.getAbsolutePath(directoryPath));
141
149
  return true;
142
150
  }
143
151
  /**
@@ -273,6 +281,7 @@ var LocalDriver = class {
273
281
  if (!await fileExistsAsync(fromPath)) throw new Error(`Source file not found: ${from}`);
274
282
  await ensureDirectoryAsync(dirname(toPath));
275
283
  await copyFile(fromPath, toPath);
284
+ this._metadata.delete(to);
276
285
  const fileBuffer = await readFile(toPath);
277
286
  const hash = this.calculateHash(fileBuffer);
278
287
  const stats = await stat(toPath);
@@ -294,6 +303,8 @@ var LocalDriver = class {
294
303
  if (!await fileExistsAsync(fromPath)) throw new Error(`Source file not found: ${from}`);
295
304
  await ensureDirectoryAsync(dirname(toPath));
296
305
  await rename(fromPath, toPath);
306
+ this._metadata.delete(from);
307
+ this._metadata.delete(to);
297
308
  const fileBuffer = await readFile(toPath);
298
309
  const hash = this.calculateHash(fileBuffer);
299
310
  const stats = await stat(toPath);
@@ -347,10 +358,14 @@ var LocalDriver = class {
347
358
  }
348
359
  /**
349
360
  * Get absolute file path
361
+ *
362
+ * Routes through {@link resolveWithinRoot} so a location can never escape
363
+ * the configured storage root via `..` traversal, an absolute path, or a
364
+ * prefix breakout.
350
365
  */
351
366
  getAbsolutePath(location) {
352
367
  const prefixedLocation = this.applyPrefix(location);
353
- return join(this.root, prefixedLocation);
368
+ return resolveWithinRoot(this.root, prefixedLocation);
354
369
  }
355
370
  /**
356
371
  * Convert various input types to Buffer
@@ -1 +1 @@
1
- {"version":3,"file":"local-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/local-driver.ts"],"sourcesContent":["import {\r\n directoryExistsAsync,\r\n ensureDirectoryAsync,\r\n fileExistsAsync,\r\n removeDirectoryAsync,\r\n unlinkAsync,\r\n} from \"@warlock.js/fs\";\r\nimport { ltrim } from \"@mongez/reinforcements\";\r\nimport crypto from \"crypto\";\r\nimport { createReadStream, createWriteStream } from \"fs\";\r\nimport { copyFile, readFile, readdir, rename, stat, writeFile } from \"fs/promises\";\r\nimport { dirname, join } from \"path\";\r\nimport type { Readable } from \"stream\";\r\nimport { pipeline } from \"stream/promises\";\r\nimport { UploadedFile } from \"../../http\";\r\nimport { storagePath } from \"../../utils/paths\";\r\nimport { url } from \"../../utils/urls\";\r\nimport { storageDriverContext } from \"../context/storage-driver-context\";\r\nimport type {\r\n DeleteManyResult,\r\n ListOptions,\r\n LocalStorageDriverOptions,\r\n PutOptions,\r\n StorageDriverContract,\r\n StorageDriverType,\r\n StorageFileData,\r\n StorageFileInfo,\r\n TemporaryTokenPayload,\r\n TemporaryTokenValidation,\r\n} from \"../types\";\r\nimport { getMimeType } from \"../utils/mime\";\r\n\r\n/**\r\n * Local filesystem storage driver\r\n *\r\n * Stores files on the local filesystem with support for:\r\n * - File operations (put, get, delete, copy, move)\r\n * - Stream operations for large files\r\n * - Batch operations\r\n * - Signed temporary URLs\r\n */\r\nexport class LocalDriver implements StorageDriverContract {\r\n /**\r\n * Driver name\r\n */\r\n public readonly name: StorageDriverType = \"local\";\r\n\r\n /**\r\n * Root path for storage\r\n */\r\n protected root: string;\r\n\r\n /**\r\n * URL prefix for file URLs\r\n */\r\n protected urlPrefix: string = \"\";\r\n\r\n /**\r\n * URL prefix for temporary file URLs\r\n */\r\n protected temporaryUrlPrefix: string;\r\n\r\n /**\r\n * Secret key for signing temporary URLs\r\n */\r\n protected signatureKey?: string;\r\n\r\n /**\r\n * Cached Storage File Metadata\r\n */\r\n protected _metadata = new Map<string, StorageFileInfo>();\r\n\r\n public constructor(public options: LocalStorageDriverOptions = {}) {\r\n this.root = options.root ?? storagePath();\r\n this.urlPrefix = options.urlPrefix ?? \"\";\r\n this.temporaryUrlPrefix = options.temporaryUrlPrefix ?? \"/temp-files\";\r\n this.signatureKey = options.signatureKey;\r\n }\r\n\r\n // ============================================================\r\n // Prefix Operations\r\n // ============================================================\r\n\r\n /**\r\n * Apply prefix to location path\r\n *\r\n * Priority: context prefix > driver options prefix > no prefix\r\n * This allows multi-tenant scenarios where context overrides driver config.\r\n *\r\n * @param location - Original location path\r\n * @returns Location with prefix applied if one exists\r\n */\r\n public applyPrefix(location: string): string {\r\n // Check context prefix first (highest priority)\r\n const contextPrefix = storageDriverContext.getPrefix();\r\n const prefix = contextPrefix || this.options.prefix;\r\n\r\n if (!prefix) {\r\n return location;\r\n }\r\n\r\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\r\n const cleanLocation = location.replace(/^\\/+/, \"\");\r\n\r\n // Avoid double-prefixing\r\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\r\n return cleanLocation;\r\n }\r\n\r\n return `${cleanPrefix}/${cleanLocation}`;\r\n }\r\n\r\n // ============================================================\r\n // Core File Operations\r\n // ============================================================\r\n\r\n /**\r\n * Put file to local storage\r\n */\r\n public async put(\r\n file: Buffer | string | UploadedFile,\r\n location: string,\r\n options?: PutOptions,\r\n ): Promise<StorageFileData> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n await ensureDirectoryAsync(dirname(absolutePath));\r\n\r\n const fileBuffer = await this.toBuffer(file);\r\n const hash = this.calculateHash(fileBuffer);\r\n\r\n await writeFile(absolutePath, new Uint8Array(fileBuffer));\r\n\r\n const stats = await stat(absolutePath);\r\n const mimeType = options?.mimeType || this.guessMimeType(location);\r\n\r\n return {\r\n path: location,\r\n url: this.url(location),\r\n size: stats.size,\r\n hash,\r\n mimeType,\r\n driver: this.name,\r\n };\r\n }\r\n\r\n /**\r\n * Put file from a readable stream (for large files)\r\n */\r\n public async putStream(\r\n stream: Readable,\r\n location: string,\r\n options?: PutOptions,\r\n ): Promise<StorageFileData> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n await ensureDirectoryAsync(dirname(absolutePath));\r\n\r\n // Create write stream and pipe\r\n const writeStream = createWriteStream(absolutePath);\r\n await pipeline(stream, writeStream);\r\n\r\n // Calculate hash and get stats\r\n const fileBuffer = await readFile(absolutePath);\r\n const hash = this.calculateHash(fileBuffer);\r\n const stats = await stat(absolutePath);\r\n const mimeType = options?.mimeType || this.guessMimeType(location);\r\n\r\n return {\r\n path: location,\r\n url: this.url(location),\r\n size: stats.size,\r\n hash,\r\n mimeType,\r\n driver: this.name,\r\n };\r\n }\r\n\r\n /**\r\n * Get file contents as Buffer\r\n */\r\n public async get(location: string): Promise<Buffer> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n if (!(await fileExistsAsync(absolutePath))) {\r\n throw new Error(`File not found: ${location}`);\r\n }\r\n\r\n return readFile(absolutePath);\r\n }\r\n\r\n /**\r\n * Get file as a readable stream (for large files)\r\n */\r\n public async getStream(location: string): Promise<Readable> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n if (!(await fileExistsAsync(absolutePath))) {\r\n throw new Error(`File not found: ${location}`);\r\n }\r\n\r\n return createReadStream(absolutePath);\r\n }\r\n\r\n /**\r\n * Delete a file\r\n */\r\n public async delete(location: string): Promise<boolean> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n if (!(await fileExistsAsync(absolutePath))) {\r\n return false;\r\n }\r\n\r\n await unlinkAsync(absolutePath);\r\n return true;\r\n }\r\n\r\n /**\r\n * Delete multiple files at once\r\n */\r\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\r\n const results: DeleteManyResult[] = [];\r\n\r\n for (const location of locations) {\r\n try {\r\n const deleted = await this.delete(location);\r\n results.push({ location, deleted });\r\n } catch (error) {\r\n results.push({\r\n location,\r\n deleted: false,\r\n error: error instanceof Error ? error.message : \"Unknown error\",\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n /**\r\n * Delete directory\r\n */\r\n public async deleteDirectory(directoryPath: string) {\r\n await removeDirectoryAsync(directoryPath);\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Check if file exists\r\n */\r\n public async exists(location: string): Promise<boolean> {\r\n const absolutePath = this.getAbsolutePath(location);\r\n return Boolean(await fileExistsAsync(absolutePath));\r\n }\r\n\r\n // ============================================================\r\n // URL Operations\r\n // ============================================================\r\n\r\n /**\r\n * Get public URL for file\r\n */\r\n public url(location: string): string {\r\n return url(this.urlPrefix + \"/\" + ltrim(location, \"/\"));\r\n }\r\n\r\n /**\r\n * Get a temporary signed URL that expires\r\n * Returns a clean URL with encoded token: {temporaryUrlPrefix}/{token}\r\n *\r\n * @param location - File path\r\n * @param expiresIn - Seconds until expiration (default: 3600)\r\n */\r\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\r\n if (!this.signatureKey) {\r\n throw new Error(\r\n \"Temporary URLs require a signatureKey in LocalDriver options. \" +\r\n \"Configure storage.drivers.local.signatureKey in your config.\",\r\n );\r\n }\r\n\r\n const token = this.encodeTemporaryToken(location, expiresIn);\r\n return `${this.temporaryUrlPrefix}/${token}`;\r\n }\r\n\r\n /**\r\n * Encode a temporary token containing path, expiry, and signature\r\n *\r\n * @param location - File path\r\n * @param expiresIn - Seconds until expiration\r\n */\r\n public encodeTemporaryToken(location: string, expiresIn: number): string {\r\n if (!this.signatureKey) {\r\n throw new Error(\"Temporary tokens require a signatureKey\");\r\n }\r\n\r\n const exp = Math.floor(Date.now() / 1000) + expiresIn;\r\n const sig = crypto\r\n .createHmac(\"sha256\", this.signatureKey)\r\n .update(`${location}:${exp}`)\r\n .digest(\"hex\");\r\n\r\n const payload: TemporaryTokenPayload = { path: location, exp, sig };\r\n const json = JSON.stringify(payload);\r\n\r\n // Use base64url encoding (URL-safe base64)\r\n return Buffer.from(json).toString(\"base64url\");\r\n }\r\n\r\n /**\r\n * Validate a temporary URL token\r\n * Returns a result object with validation status, file info, and convenience methods\r\n *\r\n * @param token - The token from the URL\r\n */\r\n public async validateTemporaryToken(token: string): Promise<TemporaryTokenValidation> {\r\n // Check signature key\r\n if (!this.signatureKey) {\r\n return { valid: false, error: \"missing_key\" };\r\n }\r\n\r\n // Decode token\r\n let payload: TemporaryTokenPayload;\r\n try {\r\n const json = Buffer.from(token, \"base64url\").toString(\"utf-8\");\r\n payload = JSON.parse(json);\r\n } catch {\r\n return { valid: false, error: \"invalid_token\" };\r\n }\r\n\r\n // Validate payload structure\r\n if (!payload.path || !payload.exp || !payload.sig) {\r\n return { valid: false, error: \"invalid_token\" };\r\n }\r\n\r\n // Check expiration\r\n const now = Math.floor(Date.now() / 1000);\r\n if (payload.exp < now) {\r\n return { valid: false, error: \"expired\" };\r\n }\r\n\r\n // Verify signature\r\n const expectedSig = crypto\r\n .createHmac(\"sha256\", this.signatureKey)\r\n .update(`${payload.path}:${payload.exp}`)\r\n .digest(\"hex\");\r\n\r\n const sigBuffer = Buffer.from(payload.sig, \"hex\");\r\n const expectedBuffer = Buffer.from(expectedSig, \"hex\");\r\n\r\n if (sigBuffer.length !== expectedBuffer.length) {\r\n return { valid: false, error: \"invalid_signature\" };\r\n }\r\n\r\n const isValidSig = crypto.timingSafeEqual(\r\n new Uint8Array(sigBuffer),\r\n new Uint8Array(expectedBuffer),\r\n );\r\n\r\n if (!isValidSig) {\r\n return { valid: false, error: \"invalid_signature\" };\r\n }\r\n\r\n // Check file exists\r\n const absolutePath = this.getAbsolutePath(payload.path);\r\n if (!(await fileExistsAsync(absolutePath))) {\r\n return { valid: false, error: \"file_not_found\" };\r\n }\r\n\r\n // Build successful result with convenience methods\r\n const result: TemporaryTokenValidation = {\r\n valid: true,\r\n path: payload.path,\r\n absolutePath,\r\n expiresAt: new Date(payload.exp * 1000),\r\n mimeType: this.guessMimeType(payload.path),\r\n driver: this,\r\n getFile: () => this.get(payload.path),\r\n getStream: () => this.getStream(payload.path),\r\n };\r\n\r\n return result;\r\n }\r\n\r\n // ============================================================\r\n // Metadata Operations\r\n // ============================================================\r\n\r\n /**\r\n * Get file info/metadata without downloading\r\n */\r\n public async metadata(location: string): Promise<StorageFileInfo> {\r\n if (this._metadata.has(location)) {\r\n return this._metadata.get(location)!;\r\n }\r\n\r\n const absolutePath = this.getAbsolutePath(location);\r\n\r\n if (!(await fileExistsAsync(absolutePath))) {\r\n throw new Error(`File not found: ${absolutePath}`);\r\n }\r\n\r\n const stats = await stat(absolutePath);\r\n const name = location.split(\"/\").pop() || \"\";\r\n\r\n this._metadata.set(location, {\r\n path: location,\r\n name,\r\n size: stats.size,\r\n isDirectory: stats.isDirectory(),\r\n lastModified: stats.mtime,\r\n mimeType: this.guessMimeType(location),\r\n });\r\n\r\n return this._metadata.get(location)!;\r\n }\r\n\r\n /**\r\n * Get file size in bytes (shortcut for metadata().size)\r\n */\r\n public async size(location: string): Promise<number> {\r\n const metadata = await this.metadata(location);\r\n return metadata.size;\r\n }\r\n\r\n // ============================================================\r\n // File Operations\r\n // ============================================================\r\n\r\n /**\r\n * Copy file to a new location\r\n */\r\n public async copy(from: string, to: string): Promise<StorageFileData> {\r\n const fromPath = this.getAbsolutePath(from);\r\n const toPath = this.getAbsolutePath(to);\r\n\r\n if (!(await fileExistsAsync(fromPath))) {\r\n throw new Error(`Source file not found: ${from}`);\r\n }\r\n\r\n await ensureDirectoryAsync(dirname(toPath));\r\n await copyFile(fromPath, toPath);\r\n\r\n const fileBuffer = await readFile(toPath);\r\n const hash = this.calculateHash(fileBuffer);\r\n const stats = await stat(toPath);\r\n\r\n return {\r\n path: to,\r\n url: this.url(to),\r\n size: stats.size,\r\n hash,\r\n mimeType: this.guessMimeType(to),\r\n driver: this.name,\r\n };\r\n }\r\n\r\n /**\r\n * Move file to a new location\r\n */\r\n public async move(from: string, to: string): Promise<StorageFileData> {\r\n const fromPath = this.getAbsolutePath(from);\r\n const toPath = this.getAbsolutePath(to);\r\n\r\n if (!(await fileExistsAsync(fromPath))) {\r\n throw new Error(`Source file not found: ${from}`);\r\n }\r\n\r\n await ensureDirectoryAsync(dirname(toPath));\r\n await rename(fromPath, toPath);\r\n\r\n const fileBuffer = await readFile(toPath);\r\n const hash = this.calculateHash(fileBuffer);\r\n const stats = await stat(toPath);\r\n\r\n return {\r\n path: to,\r\n url: this.url(to),\r\n size: stats.size,\r\n hash,\r\n mimeType: this.guessMimeType(to),\r\n driver: this.name,\r\n };\r\n }\r\n\r\n /**\r\n * List files in a directory\r\n */\r\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\r\n const absolutePath = this.getAbsolutePath(directory);\r\n const files: StorageFileInfo[] = [];\r\n\r\n // A listing target is a DIRECTORY, so guard with `directoryExistsAsync`.\r\n // `fileExistsAsync` resolves `false` for a folder, which would make `list`\r\n // always return [] for a real, populated directory.\r\n if (!(await directoryExistsAsync(absolutePath))) {\r\n return files;\r\n }\r\n\r\n const entries = await readdir(absolutePath, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const entryPath = join(directory, entry.name);\r\n const entryStats = await stat(this.getAbsolutePath(entryPath));\r\n\r\n files.push({\r\n path: entryPath,\r\n name: entry.name,\r\n size: entryStats.size,\r\n isDirectory: entry.isDirectory(),\r\n lastModified: entryStats.mtime,\r\n mimeType: entry.isFile() ? this.guessMimeType(entry.name) : undefined,\r\n });\r\n\r\n // Recursively list subdirectories if requested\r\n if (options?.recursive && entry.isDirectory()) {\r\n const subFiles = await this.list(entryPath, options);\r\n files.push(...subFiles);\r\n }\r\n\r\n // Respect limit\r\n if (options?.limit && files.length >= options.limit) {\r\n break;\r\n }\r\n }\r\n\r\n return files;\r\n }\r\n\r\n // ============================================================\r\n // Path Operations\r\n // ============================================================\r\n\r\n /**\r\n * Get absolute filesystem path for a location\r\n */\r\n public path(location: string): string {\r\n return this.getAbsolutePath(location);\r\n }\r\n\r\n /**\r\n * Get the storage root directory\r\n */\r\n public getRoot(): string {\r\n return this.root;\r\n }\r\n\r\n // ============================================================\r\n // Utilities\r\n // ============================================================\r\n\r\n /**\r\n * Get absolute file path\r\n */\r\n protected getAbsolutePath(location: string): string {\r\n const prefixedLocation = this.applyPrefix(location);\r\n return join(this.root, prefixedLocation);\r\n }\r\n\r\n /**\r\n * Convert various input types to Buffer\r\n */\r\n protected async toBuffer(file: Buffer | string | UploadedFile): Promise<Buffer> {\r\n if (Buffer.isBuffer(file)) {\r\n return file;\r\n }\r\n\r\n if (typeof file === \"string\") {\r\n return readFile(file);\r\n }\r\n\r\n return file.buffer();\r\n }\r\n\r\n /**\r\n * Calculate SHA-256 hash\r\n */\r\n protected calculateHash(buffer: Buffer): string {\r\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\r\n }\r\n\r\n /**\r\n * Guess MIME type from file extension\r\n */\r\n protected guessMimeType(location: string): string {\r\n return getMimeType(location);\r\n }\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"local-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/local-driver.ts"],"sourcesContent":["import {\n directoryExistsAsync,\n ensureDirectoryAsync,\n fileExistsAsync,\n removeDirectoryAsync,\n unlinkAsync,\n} from \"@warlock.js/fs\";\nimport { ltrim } from \"@mongez/reinforcements\";\nimport crypto from \"crypto\";\nimport { createReadStream, createWriteStream } from \"fs\";\nimport { copyFile, readFile, readdir, rename, stat, writeFile } from \"fs/promises\";\nimport { dirname, join, resolve } from \"path\";\nimport type { Readable } from \"stream\";\nimport { pipeline } from \"stream/promises\";\nimport { UploadedFile } from \"../../http\";\nimport { storagePath } from \"../../utils/paths\";\nimport { url } from \"../../utils/urls\";\nimport { storageDriverContext } from \"../context/storage-driver-context\";\nimport { resolveWithinRoot } from \"../utils/contain-path\";\nimport type {\n DeleteManyResult,\n ListOptions,\n LocalStorageDriverOptions,\n PutOptions,\n StorageDriverContract,\n StorageDriverType,\n StorageFileData,\n StorageFileInfo,\n TemporaryTokenPayload,\n TemporaryTokenValidation,\n} from \"../types\";\nimport { getMimeType } from \"../utils/mime\";\n\n/**\n * Local filesystem storage driver\n *\n * Stores files on the local filesystem with support for:\n * - File operations (put, get, delete, copy, move)\n * - Stream operations for large files\n * - Batch operations\n * - Signed temporary URLs\n */\nexport class LocalDriver implements StorageDriverContract {\n /**\n * Driver name\n */\n public readonly name: StorageDriverType = \"local\";\n\n /**\n * Root path for storage\n */\n protected root: string;\n\n /**\n * URL prefix for file URLs\n */\n protected urlPrefix: string = \"\";\n\n /**\n * URL prefix for temporary file URLs\n */\n protected temporaryUrlPrefix: string;\n\n /**\n * Secret key for signing temporary URLs\n */\n protected signatureKey?: string;\n\n /**\n * Cached Storage File Metadata\n */\n protected _metadata = new Map<string, StorageFileInfo>();\n\n public constructor(public options: LocalStorageDriverOptions = {}) {\n // Resolve the root to an absolute, normalized path up front so the\n // path-traversal containment check (resolveWithinRoot) has a stable\n // anchor to compare resolved locations against.\n this.root = resolve(options.root ?? storagePath());\n this.urlPrefix = options.urlPrefix ?? \"\";\n this.temporaryUrlPrefix = options.temporaryUrlPrefix ?? \"/temp-files\";\n this.signatureKey = options.signatureKey;\n }\n\n // ============================================================\n // Prefix Operations\n // ============================================================\n\n /**\n * Apply prefix to location path\n *\n * Priority: context prefix > driver options prefix > no prefix\n * This allows multi-tenant scenarios where context overrides driver config.\n *\n * @param location - Original location path\n * @returns Location with prefix applied if one exists\n */\n public applyPrefix(location: string): string {\n // Check context prefix first (highest priority)\n const contextPrefix = storageDriverContext.getPrefix();\n const prefix = contextPrefix || this.options.prefix;\n\n if (!prefix) {\n return location;\n }\n\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\n const cleanLocation = location.replace(/^\\/+/, \"\");\n\n // Avoid double-prefixing\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\n return cleanLocation;\n }\n\n return `${cleanPrefix}/${cleanLocation}`;\n }\n\n // ============================================================\n // Core File Operations\n // ============================================================\n\n /**\n * Put file to local storage\n */\n public async put(\n file: Buffer | string | UploadedFile,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n const fileBuffer = await this.toBuffer(file);\n const hash = this.calculateHash(fileBuffer);\n\n await writeFile(absolutePath, new Uint8Array(fileBuffer));\n\n // Invalidate any stale cached metadata for this location.\n this._metadata.delete(location);\n\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: location,\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Put file from a readable stream (for large files)\n */\n public async putStream(\n stream: Readable,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n // Create write stream and pipe\n const writeStream = createWriteStream(absolutePath);\n await pipeline(stream, writeStream);\n\n // Invalidate any stale cached metadata for this location.\n this._metadata.delete(location);\n\n // Calculate hash and get stats\n const fileBuffer = await readFile(absolutePath);\n const hash = this.calculateHash(fileBuffer);\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: location,\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Get file contents as Buffer\n */\n public async get(location: string): Promise<Buffer> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return readFile(absolutePath);\n }\n\n /**\n * Get file as a readable stream (for large files)\n */\n public async getStream(location: string): Promise<Readable> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return createReadStream(absolutePath);\n }\n\n /**\n * Delete a file\n */\n public async delete(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n return false;\n }\n\n await unlinkAsync(absolutePath);\n\n // Invalidate any stale cached metadata for this location.\n this._metadata.delete(location);\n\n return true;\n }\n\n /**\n * Delete multiple files at once\n */\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\n const results: DeleteManyResult[] = [];\n\n for (const location of locations) {\n try {\n const deleted = await this.delete(location);\n results.push({ location, deleted });\n } catch (error) {\n results.push({\n location,\n deleted: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n\n return results;\n }\n\n /**\n * Delete directory\n *\n * The directory path is resolved through {@link getAbsolutePath} so it is\n * contained within the storage root — the raw, caller-supplied argument is\n * never handed to the filesystem (preventing `../` traversal deletes).\n */\n public async deleteDirectory(directoryPath: string) {\n const absolutePath = this.getAbsolutePath(directoryPath);\n\n await removeDirectoryAsync(absolutePath);\n\n return true;\n }\n\n /**\n * Check if file exists\n */\n public async exists(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n return Boolean(await fileExistsAsync(absolutePath));\n }\n\n // ============================================================\n // URL Operations\n // ============================================================\n\n /**\n * Get public URL for file\n */\n public url(location: string): string {\n return url(this.urlPrefix + \"/\" + ltrim(location, \"/\"));\n }\n\n /**\n * Get a temporary signed URL that expires\n * Returns a clean URL with encoded token: {temporaryUrlPrefix}/{token}\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration (default: 3600)\n */\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\n if (!this.signatureKey) {\n throw new Error(\n \"Temporary URLs require a signatureKey in LocalDriver options. \" +\n \"Configure storage.drivers.local.signatureKey in your config.\",\n );\n }\n\n const token = this.encodeTemporaryToken(location, expiresIn);\n return `${this.temporaryUrlPrefix}/${token}`;\n }\n\n /**\n * Encode a temporary token containing path, expiry, and signature\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration\n */\n public encodeTemporaryToken(location: string, expiresIn: number): string {\n if (!this.signatureKey) {\n throw new Error(\"Temporary tokens require a signatureKey\");\n }\n\n const exp = Math.floor(Date.now() / 1000) + expiresIn;\n const sig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${location}:${exp}`)\n .digest(\"hex\");\n\n const payload: TemporaryTokenPayload = { path: location, exp, sig };\n const json = JSON.stringify(payload);\n\n // Use base64url encoding (URL-safe base64)\n return Buffer.from(json).toString(\"base64url\");\n }\n\n /**\n * Validate a temporary URL token\n * Returns a result object with validation status, file info, and convenience methods\n *\n * @param token - The token from the URL\n */\n public async validateTemporaryToken(token: string): Promise<TemporaryTokenValidation> {\n // Check signature key\n if (!this.signatureKey) {\n return { valid: false, error: \"missing_key\" };\n }\n\n // Decode token\n let payload: TemporaryTokenPayload;\n try {\n const json = Buffer.from(token, \"base64url\").toString(\"utf-8\");\n payload = JSON.parse(json);\n } catch {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Validate payload structure\n if (!payload.path || !payload.exp || !payload.sig) {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (payload.exp < now) {\n return { valid: false, error: \"expired\" };\n }\n\n // Verify signature\n const expectedSig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${payload.path}:${payload.exp}`)\n .digest(\"hex\");\n\n const sigBuffer = Buffer.from(payload.sig, \"hex\");\n const expectedBuffer = Buffer.from(expectedSig, \"hex\");\n\n if (sigBuffer.length !== expectedBuffer.length) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n const isValidSig = crypto.timingSafeEqual(\n new Uint8Array(sigBuffer),\n new Uint8Array(expectedBuffer),\n );\n\n if (!isValidSig) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n // Check file exists\n const absolutePath = this.getAbsolutePath(payload.path);\n if (!(await fileExistsAsync(absolutePath))) {\n return { valid: false, error: \"file_not_found\" };\n }\n\n // Build successful result with convenience methods\n const result: TemporaryTokenValidation = {\n valid: true,\n path: payload.path,\n absolutePath,\n expiresAt: new Date(payload.exp * 1000),\n mimeType: this.guessMimeType(payload.path),\n driver: this,\n getFile: () => this.get(payload.path),\n getStream: () => this.getStream(payload.path),\n };\n\n return result;\n }\n\n // ============================================================\n // Metadata Operations\n // ============================================================\n\n /**\n * Get file info/metadata without downloading\n */\n public async metadata(location: string): Promise<StorageFileInfo> {\n if (this._metadata.has(location)) {\n return this._metadata.get(location)!;\n }\n\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${absolutePath}`);\n }\n\n const stats = await stat(absolutePath);\n const name = location.split(\"/\").pop() || \"\";\n\n this._metadata.set(location, {\n path: location,\n name,\n size: stats.size,\n isDirectory: stats.isDirectory(),\n lastModified: stats.mtime,\n mimeType: this.guessMimeType(location),\n });\n\n return this._metadata.get(location)!;\n }\n\n /**\n * Get file size in bytes (shortcut for metadata().size)\n */\n public async size(location: string): Promise<number> {\n const metadata = await this.metadata(location);\n return metadata.size;\n }\n\n // ============================================================\n // File Operations\n // ============================================================\n\n /**\n * Copy file to a new location\n */\n public async copy(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await copyFile(fromPath, toPath);\n\n // Invalidate any stale cached metadata for the destination.\n this._metadata.delete(to);\n\n const fileBuffer = await readFile(toPath);\n const hash = this.calculateHash(fileBuffer);\n const stats = await stat(toPath);\n\n return {\n path: to,\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * Move file to a new location\n */\n public async move(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await rename(fromPath, toPath);\n\n // Invalidate any stale cached metadata for both source and destination.\n this._metadata.delete(from);\n this._metadata.delete(to);\n\n const fileBuffer = await readFile(toPath);\n const hash = this.calculateHash(fileBuffer);\n const stats = await stat(toPath);\n\n return {\n path: to,\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * List files in a directory\n */\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\n const absolutePath = this.getAbsolutePath(directory);\n const files: StorageFileInfo[] = [];\n\n // A listing target is a DIRECTORY, so guard with `directoryExistsAsync`.\n // `fileExistsAsync` resolves `false` for a folder, which would make `list`\n // always return [] for a real, populated directory.\n if (!(await directoryExistsAsync(absolutePath))) {\n return files;\n }\n\n const entries = await readdir(absolutePath, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = join(directory, entry.name);\n const entryStats = await stat(this.getAbsolutePath(entryPath));\n\n files.push({\n path: entryPath,\n name: entry.name,\n size: entryStats.size,\n isDirectory: entry.isDirectory(),\n lastModified: entryStats.mtime,\n mimeType: entry.isFile() ? this.guessMimeType(entry.name) : undefined,\n });\n\n // Recursively list subdirectories if requested\n if (options?.recursive && entry.isDirectory()) {\n const subFiles = await this.list(entryPath, options);\n files.push(...subFiles);\n }\n\n // Respect limit\n if (options?.limit && files.length >= options.limit) {\n break;\n }\n }\n\n return files;\n }\n\n // ============================================================\n // Path Operations\n // ============================================================\n\n /**\n * Get absolute filesystem path for a location\n */\n public path(location: string): string {\n return this.getAbsolutePath(location);\n }\n\n /**\n * Get the storage root directory\n */\n public getRoot(): string {\n return this.root;\n }\n\n // ============================================================\n // Utilities\n // ============================================================\n\n /**\n * Get absolute file path\n *\n * Routes through {@link resolveWithinRoot} so a location can never escape\n * the configured storage root via `..` traversal, an absolute path, or a\n * prefix breakout.\n */\n protected getAbsolutePath(location: string): string {\n const prefixedLocation = this.applyPrefix(location);\n return resolveWithinRoot(this.root, prefixedLocation);\n }\n\n /**\n * Convert various input types to Buffer\n */\n protected async toBuffer(file: Buffer | string | UploadedFile): Promise<Buffer> {\n if (Buffer.isBuffer(file)) {\n return file;\n }\n\n if (typeof file === \"string\") {\n return readFile(file);\n }\n\n return file.buffer();\n }\n\n /**\n * Calculate SHA-256 hash\n */\n protected calculateHash(buffer: Buffer): string {\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\n }\n\n /**\n * Guess MIME type from file extension\n */\n protected guessMimeType(location: string): string {\n return getMimeType(location);\n }\n}\n"],"mappings":"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"}
@@ -47,7 +47,7 @@ var R2Driver = class extends CloudDriver {
47
47
  * - Or use a custom domain through Cloudflare
48
48
  */
49
49
  url(location) {
50
- if (this.options.urlPrefix) location = `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
50
+ if (this.options.urlPrefix) return `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
51
51
  if (this.options.publicDomain) return `${this.options.publicDomain.replace(/\/+$/, "")}/${location}`;
52
52
  return `https://pub-${this.options.accountId}.r2.dev/${location}`;
53
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"r2-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/r2-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { R2StorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * Cloudflare R2 Storage Driver\n *\n * R2 is S3-compatible but uses a different URL structure and doesn't require regions.\n *\n * URL Patterns:\n * - With publicDomain: https://{publicDomain}/{key}\n * - With urlPrefix: {urlPrefix}/{key}\n * - Default public bucket: https://pub-{accountId}.r2.dev/{key}\n *\n * @example\n * ```typescript\n * const driver = new R2Driver({\n * bucket: \"my-bucket\",\n * region: \"auto\", // R2 doesn't use traditional regions\n * accessKeyId: process.env.R2_ACCESS_KEY_ID,\n * secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,\n * accountId: process.env.R2_ACCOUNT_ID,\n * publicDomain: \"assets.example.com\", // Optional custom domain\n * });\n * ```\n */\nexport class R2Driver extends CloudDriver<R2StorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"r2\";\n\n /**\n * Get R2 endpoint URL\n *\n * R2 endpoint format: https://{accountId}.r2.cloudflarestorage.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.accountId}.r2.cloudflarestorage.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Priority: urlPrefix > publicDomain > default R2 URL\n *\n * Note: For R2 public access, you typically need to:\n * - Enable public access on the bucket\n * - Or use a custom domain through Cloudflare\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n location = `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Use publicDomain if configured\n if (this.options.publicDomain) {\n const domain = this.options.publicDomain.replace(/\\/+$/, \"\");\n return `${domain}/${location}`;\n }\n\n // 3. Fallback to R2 public bucket URL\n // Note: Public access must be enabled on the bucket for this to work\n return `https://pub-${this.options.accountId}.r2.dev/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,WAAb,cAA8B,YAAoC;;;cAIzC;;;;;;;CAOvB,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU;CACpE;;;;;;;;;;CAWA,AAAO,IAAI,UAA0B;EAEnC,IAAI,KAAK,QAAQ,WAEf,WAAW,GADI,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACnC,EAAE,GAAG,MAAM,UAAU,GAAG;EAI7C,IAAI,KAAK,QAAQ,cAEf,OAAO,GADQ,KAAK,QAAQ,aAAa,QAAQ,QAAQ,EAC1C,EAAE,GAAG;EAKtB,OAAO,eAAe,KAAK,QAAQ,UAAU,UAAU;CACzD;AACF"}
1
+ {"version":3,"file":"r2-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/r2-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { R2StorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * Cloudflare R2 Storage Driver\n *\n * R2 is S3-compatible but uses a different URL structure and doesn't require regions.\n *\n * URL Patterns:\n * - With publicDomain: https://{publicDomain}/{key}\n * - With urlPrefix: {urlPrefix}/{key}\n * - Default public bucket: https://pub-{accountId}.r2.dev/{key}\n *\n * @example\n * ```typescript\n * const driver = new R2Driver({\n * bucket: \"my-bucket\",\n * region: \"auto\", // R2 doesn't use traditional regions\n * accessKeyId: process.env.R2_ACCESS_KEY_ID,\n * secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,\n * accountId: process.env.R2_ACCOUNT_ID,\n * publicDomain: \"assets.example.com\", // Optional custom domain\n * });\n * ```\n */\nexport class R2Driver extends CloudDriver<R2StorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"r2\";\n\n /**\n * Get R2 endpoint URL\n *\n * R2 endpoint format: https://{accountId}.r2.cloudflarestorage.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.accountId}.r2.cloudflarestorage.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Priority: urlPrefix > publicDomain > default R2 URL\n *\n * Note: For R2 public access, you typically need to:\n * - Enable public access on the bucket\n * - Or use a custom domain through Cloudflare\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured — return it directly so the\n // publicDomain / default-host URLs below are NOT appended (which would\n // yield a double-host URL).\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n return `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Use publicDomain if configured\n if (this.options.publicDomain) {\n const domain = this.options.publicDomain.replace(/\\/+$/, \"\");\n return `${domain}/${location}`;\n }\n\n // 3. Fallback to R2 public bucket URL\n // Note: Public access must be enabled on the bucket for this to work\n return `https://pub-${this.options.accountId}.r2.dev/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,WAAb,cAA8B,YAAoC;;;cAIzC;;;;;;;CAOvB,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU;CACpE;;;;;;;;;;CAWA,AAAO,IAAI,UAA0B;EAInC,IAAI,KAAK,QAAQ,WAEf,OAAO,GADQ,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACvC,EAAE,GAAG,MAAM,UAAU,GAAG;EAIzC,IAAI,KAAK,QAAQ,cAEf,OAAO,GADQ,KAAK,QAAQ,aAAa,QAAQ,QAAQ,EAC1C,EAAE,GAAG;EAKtB,OAAO,eAAe,KAAK,QAAQ,UAAU,UAAU;CACzD;AACF"}
@@ -30,7 +30,7 @@ var S3Driver = class extends CloudDriver {
30
30
  * - Default: https://{bucket}.s3.{region}.amazonaws.com/{key}
31
31
  */
32
32
  url(location) {
33
- if (this.options.urlPrefix) location = `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
33
+ if (this.options.urlPrefix) return `${this.options.urlPrefix.replace(/\/+$/, "")}/${ltrim(location, "/")}`;
34
34
  return `https://${this.options.bucket}.s3.${this.options.region}.amazonaws.com/${location}`;
35
35
  }
36
36
  };
@@ -1 +1 @@
1
- {"version":3,"file":"s3-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/s3-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { CloudStorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * AWS S3 Storage Driver\n *\n * URL Pattern: https://{bucket}.s3.{region}.amazonaws.com/{key}\n *\n * @example\n * ```typescript\n * const driver = new S3Driver({\n * bucket: \"my-bucket\",\n * region: \"us-east-1\",\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n * ```\n */\nexport class S3Driver extends CloudDriver<CloudStorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"s3\";\n\n /**\n * Get public URL for file\n *\n * URL formats:\n * - With urlPrefix: {urlPrefix}/{key}\n * - Default: https://{bucket}.s3.{region}.amazonaws.com/{key}\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n location = `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Default S3 URL\n return `https://${this.options.bucket}.s3.${this.options.region}.amazonaws.com/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,WAAb,cAA8B,YAAuC;;;cAI5C;;;;;;;;;CASvB,AAAO,IAAI,UAA0B;EAEnC,IAAI,KAAK,QAAQ,WAEf,WAAW,GADI,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACnC,EAAE,GAAG,MAAM,UAAU,GAAG;EAI7C,OAAO,WAAW,KAAK,QAAQ,OAAO,MAAM,KAAK,QAAQ,OAAO,iBAAiB;CACnF;AACF"}
1
+ {"version":3,"file":"s3-driver.mjs","names":[],"sources":["../../../../../../../../@warlock.js/core/src/storage/drivers/s3-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { CloudStorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * AWS S3 Storage Driver\n *\n * URL Pattern: https://{bucket}.s3.{region}.amazonaws.com/{key}\n *\n * @example\n * ```typescript\n * const driver = new S3Driver({\n * bucket: \"my-bucket\",\n * region: \"us-east-1\",\n * accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n * secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n * });\n * ```\n */\nexport class S3Driver extends CloudDriver<CloudStorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"s3\";\n\n /**\n * Get public URL for file\n *\n * URL formats:\n * - With urlPrefix: {urlPrefix}/{key}\n * - Default: https://{bucket}.s3.{region}.amazonaws.com/{key}\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured (e.g. a CDN domain) — return it directly\n // so the bucket-host URL below is NOT appended (which would yield a\n // double-host URL like https://bucket.s3.../https://cdn.../key).\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n return `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Default S3 URL\n return `https://${this.options.bucket}.s3.${this.options.region}.amazonaws.com/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAmBA,IAAa,WAAb,cAA8B,YAAuC;;;cAI5C;;;;;;;;;CASvB,AAAO,IAAI,UAA0B;EAInC,IAAI,KAAK,QAAQ,WAEf,OAAO,GADQ,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACvC,EAAE,GAAG,MAAM,UAAU,GAAG;EAIzC,OAAO,WAAW,KAAK,QAAQ,OAAO,MAAM,KAAK,QAAQ,OAAO,iBAAiB;CACnF;AACF"}
@@ -1,10 +1,13 @@
1
1
  import { StorageFile } from "./storage-file.mjs";
2
- import { CloudStorageDriverContract, CloudStorageDriverOptions, CloudStorageFileData, DeleteManyResult, EventSubscription, FileVisibility, ListOptions, LocalStorageDriverOptions, PresignedOptions, PresignedUploadOptions, PutDirectoryOptions, PutDirectoryResult, PutOptions, R2StorageDriverOptions, ScopedStorageContract, StorageConfigurations, StorageCopyEventPayload, StorageDriverConfig, StorageDriverContract, StorageDriverName, StorageDriverRegistry, StorageDriverType, StorageEventHandler, StorageEventPayload, StorageEventType, StorageFileData, StorageFileInfo, StorageManagerContract, StoragePutEventPayload, TemporaryTokenError, TemporaryTokenPayload, TemporaryTokenValidation } from "./types.mjs";
2
+ import { CloudStorageDriverContract, CloudStorageDriverOptions, CloudStorageFileData, DeleteManyResult, EventSubscription, FileVisibility, ListOptions, LocalStorageDriverOptions, PresignedOptions, PresignedUploadOptions, PutDirectoryOptions, PutDirectoryResult, PutFromUrlOptions, PutOptions, R2StorageDriverOptions, ScopedStorageContract, StorageConfigurations, StorageCopyEventPayload, StorageDriverConfig, StorageDriverContract, StorageDriverName, StorageDriverRegistry, StorageDriverType, StorageEventHandler, StorageEventPayload, StorageEventType, StorageFileData, StorageFileInfo, StorageManagerContract, StoragePutEventPayload, TemporaryTokenError, TemporaryTokenPayload, TemporaryTokenValidation } from "./types.mjs";
3
3
  import { storageConfig, storageConfigurations } from "./config.mjs";
4
4
  import { ScopedStorage } from "./scoped-storage.mjs";
5
5
  import { Storage, storage } from "./storage.mjs";
6
6
  import { StorageDriverContextStore, storageDriverContext } from "./context/storage-driver-context.mjs";
7
+ import { resolveWithinRoot } from "./utils/contain-path.mjs";
7
8
  import { MimeTypes, getMimeType } from "./utils/mime.mjs";
9
+ import { SafeFetchOptions, SafeFetchResult, isPrivateOrReservedIp, safeFetchToBuffer } from "./utils/safe-fetch.mjs";
10
+ import { StorageError, StorageErrorOptions } from "./utils/storage-error.mjs";
8
11
  import { CloudDriver, loadS3 } from "./drivers/cloud-driver.mjs";
9
12
  import { DOSpacesDriver } from "./drivers/do-spaces-driver.mjs";
10
13
  import { LocalDriver } from "./drivers/local-driver.mjs";
@@ -1,10 +1,13 @@
1
1
  import { storageConfig, storageConfigurations } from "./config.mjs";
2
2
  import { StorageFile } from "./storage-file.mjs";
3
+ import { StorageError } from "./utils/storage-error.mjs";
4
+ import { isPrivateOrReservedIp, safeFetchToBuffer } from "./utils/safe-fetch.mjs";
3
5
  import { ScopedStorage } from "./scoped-storage.mjs";
4
6
  import { storageDriverContext } from "./context/storage-driver-context.mjs";
5
7
  import { MimeTypes, getMimeType } from "./utils/mime.mjs";
6
8
  import { CloudDriver, loadS3 } from "./drivers/cloud-driver.mjs";
7
9
  import { DOSpacesDriver } from "./drivers/do-spaces-driver.mjs";
10
+ import { resolveWithinRoot } from "./utils/contain-path.mjs";
8
11
  import { LocalDriver } from "./drivers/local-driver.mjs";
9
12
  import { R2Driver } from "./drivers/r2-driver.mjs";
10
13
  import { S3Driver } from "./drivers/s3-driver.mjs";
@@ -1,5 +1,5 @@
1
1
  import { StorageFile } from "./storage-file.mjs";
2
- import { DeleteManyResult, ListOptions, PutDirectoryOptions, PutDirectoryResult, PutOptions, ScopedStorageContract, StorageDriverContract, StorageDriverType, StorageFileInfo } from "./types.mjs";
2
+ import { DeleteManyResult, ListOptions, PutDirectoryOptions, PutDirectoryResult, PutFromUrlOptions, PutOptions, ScopedStorageContract, StorageDriverContract, StorageDriverType, StorageFileInfo } from "./types.mjs";
3
3
  import { UploadedFile } from "../http/uploaded-file.mjs";
4
4
  import { Readable } from "stream";
5
5
 
@@ -110,11 +110,15 @@ declare class ScopedStorage implements ScopedStorageContract {
110
110
  /**
111
111
  * Store a file from a URL
112
112
  *
113
- * Downloads the file from the URL and stores it.
113
+ * Downloads the file from the URL and stores it. The download is
114
+ * SSRF-guarded by default: the URL scheme must be https/http, the host
115
+ * must not resolve to a private / loopback / link-local / cloud-metadata
116
+ * address, the body is capped, and the request times out. Tune or relax
117
+ * via the {@link PutFromUrlOptions} guard fields.
114
118
  *
115
119
  * @param url - URL to download from
116
120
  * @param location - Destination path in storage
117
- * @param options - Optional storage options
121
+ * @param options - Storage + outbound-download guard options
118
122
  * @returns StorageFile instance
119
123
  *
120
124
  * @example
@@ -125,7 +129,7 @@ declare class ScopedStorage implements ScopedStorageContract {
125
129
  * );
126
130
  * ```
127
131
  */
128
- putFromUrl(url: string, location: string, options?: PutOptions): Promise<StorageFile>;
132
+ putFromUrl(url: string, location: string, options?: PutFromUrlOptions): Promise<StorageFile>;
129
133
  /**
130
134
  * Store a file from base64 data URL
131
135
  *
@@ -1 +1 @@
1
- {"version":3,"file":"scoped-storage.d.mts","names":[],"sources":["../../../../../../../@warlock.js/core/src/storage/scoped-storage.ts"],"mappings":"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"}
1
+ {"version":3,"file":"scoped-storage.d.mts","names":[],"sources":["../../../../../../../@warlock.js/core/src/storage/scoped-storage.ts"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { StorageFile } from "./storage-file.mjs";
2
+ import { safeFetchToBuffer } from "./utils/safe-fetch.mjs";
2
3
  import path from "path";
3
4
  import { fileExistsAsync } from "@warlock.js/fs";
4
5
  import { createReadStream } from "fs";
@@ -121,11 +122,15 @@ var ScopedStorage = class {
121
122
  /**
122
123
  * Store a file from a URL
123
124
  *
124
- * Downloads the file from the URL and stores it.
125
+ * Downloads the file from the URL and stores it. The download is
126
+ * SSRF-guarded by default: the URL scheme must be https/http, the host
127
+ * must not resolve to a private / loopback / link-local / cloud-metadata
128
+ * address, the body is capped, and the request times out. Tune or relax
129
+ * via the {@link PutFromUrlOptions} guard fields.
125
130
  *
126
131
  * @param url - URL to download from
127
132
  * @param location - Destination path in storage
128
- * @param options - Optional storage options
133
+ * @param options - Storage + outbound-download guard options
129
134
  * @returns StorageFile instance
130
135
  *
131
136
  * @example
@@ -137,10 +142,20 @@ var ScopedStorage = class {
137
142
  * ```
138
143
  */
139
144
  async putFromUrl(url, location, options) {
140
- const response = await fetch(url);
141
- if (!response.ok) throw new Error(`Failed to fetch file from ${url}: ${response.statusText}`);
142
- const buffer = Buffer.from(await response.arrayBuffer());
143
- return this.put(buffer, location, options);
145
+ const { allowPrivateHosts, maxBytes, timeoutMs, allowedSchemes, ...putOptions } = options ?? {};
146
+ const result = await safeFetchToBuffer(url, {
147
+ allowPrivateHosts,
148
+ maxBytes,
149
+ timeoutMs,
150
+ allowedSchemes
151
+ });
152
+ if (!result.ok) throw new Error(`Failed to fetch file from ${url}: ${result.statusText}`);
153
+ if (!result.contentType) throw new Error(`Failed to fetch file from ${url}: missing content-type header`);
154
+ const mimeType = putOptions.mimeType || result.contentType;
155
+ return this.put(result.buffer, location, {
156
+ ...putOptions,
157
+ mimeType
158
+ });
144
159
  }
145
160
  /**
146
161
  * Store a file from base64 data URL