langchain 1.5.4 → 1.5.6

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 (360) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/agents/ReactAgent.cjs +6 -6
  3. package/dist/agents/ReactAgent.cjs.map +1 -1
  4. package/dist/agents/ReactAgent.d.cts +1 -1
  5. package/dist/agents/ReactAgent.d.cts.map +1 -1
  6. package/dist/agents/ReactAgent.d.ts +1 -1
  7. package/dist/agents/ReactAgent.d.ts.map +1 -1
  8. package/dist/agents/ReactAgent.js +6 -5
  9. package/dist/agents/ReactAgent.js.map +1 -1
  10. package/dist/agents/RunnableCallable.cjs +0 -1
  11. package/dist/agents/RunnableCallable.cjs.map +1 -1
  12. package/dist/agents/RunnableCallable.js.map +1 -1
  13. package/dist/agents/annotation.cjs +0 -1
  14. package/dist/agents/annotation.cjs.map +1 -1
  15. package/dist/agents/annotation.js.map +1 -1
  16. package/dist/agents/constants.d.cts +1 -1
  17. package/dist/agents/constants.d.cts.map +1 -1
  18. package/dist/agents/constants.d.ts +1 -1
  19. package/dist/agents/constants.d.ts.map +1 -1
  20. package/dist/agents/errors.cjs +6 -1
  21. package/dist/agents/errors.cjs.map +1 -1
  22. package/dist/agents/errors.d.cts +2 -1
  23. package/dist/agents/errors.d.cts.map +1 -1
  24. package/dist/agents/errors.d.ts +2 -1
  25. package/dist/agents/errors.d.ts.map +1 -1
  26. package/dist/agents/errors.js +6 -0
  27. package/dist/agents/errors.js.map +1 -1
  28. package/dist/agents/index.cjs +21 -7
  29. package/dist/agents/index.cjs.map +1 -1
  30. package/dist/agents/index.d.cts +2 -2
  31. package/dist/agents/index.d.cts.map +1 -1
  32. package/dist/agents/index.d.ts +2 -2
  33. package/dist/agents/index.d.ts.map +1 -1
  34. package/dist/agents/index.js +8 -8
  35. package/dist/agents/index.js.map +1 -1
  36. package/dist/agents/middleware/constants.cjs +3 -1
  37. package/dist/agents/middleware/constants.cjs.map +1 -1
  38. package/dist/agents/middleware/constants.js +3 -1
  39. package/dist/agents/middleware/constants.js.map +1 -1
  40. package/dist/agents/middleware/contextEditing.cjs +0 -1
  41. package/dist/agents/middleware/contextEditing.cjs.map +1 -1
  42. package/dist/agents/middleware/contextEditing.d.cts +1 -3
  43. package/dist/agents/middleware/contextEditing.d.cts.map +1 -1
  44. package/dist/agents/middleware/contextEditing.d.ts +1 -3
  45. package/dist/agents/middleware/contextEditing.d.ts.map +1 -1
  46. package/dist/agents/middleware/contextEditing.js.map +1 -1
  47. package/dist/agents/middleware/dynamicSystemPrompt.cjs +0 -1
  48. package/dist/agents/middleware/dynamicSystemPrompt.cjs.map +1 -1
  49. package/dist/agents/middleware/dynamicSystemPrompt.d.cts +1 -3
  50. package/dist/agents/middleware/dynamicSystemPrompt.d.cts.map +1 -1
  51. package/dist/agents/middleware/dynamicSystemPrompt.d.ts +1 -3
  52. package/dist/agents/middleware/dynamicSystemPrompt.d.ts.map +1 -1
  53. package/dist/agents/middleware/dynamicSystemPrompt.js.map +1 -1
  54. package/dist/agents/middleware/error.cjs +0 -1
  55. package/dist/agents/middleware/error.cjs.map +1 -1
  56. package/dist/agents/middleware/error.js.map +1 -1
  57. package/dist/agents/middleware/hitl.cjs +0 -1
  58. package/dist/agents/middleware/hitl.cjs.map +1 -1
  59. package/dist/agents/middleware/hitl.d.cts +1 -3
  60. package/dist/agents/middleware/hitl.d.cts.map +1 -1
  61. package/dist/agents/middleware/hitl.d.ts +1 -3
  62. package/dist/agents/middleware/hitl.d.ts.map +1 -1
  63. package/dist/agents/middleware/hitl.js.map +1 -1
  64. package/dist/agents/middleware/index.cjs +51 -20
  65. package/dist/agents/middleware/index.d.cts +2 -1
  66. package/dist/agents/middleware/index.d.ts +2 -1
  67. package/dist/agents/middleware/index.js +21 -21
  68. package/dist/agents/middleware/llmToolSelector.cjs +3 -1
  69. package/dist/agents/middleware/llmToolSelector.cjs.map +1 -1
  70. package/dist/agents/middleware/llmToolSelector.d.cts +9 -12
  71. package/dist/agents/middleware/llmToolSelector.d.cts.map +1 -1
  72. package/dist/agents/middleware/llmToolSelector.d.ts +9 -12
  73. package/dist/agents/middleware/llmToolSelector.d.ts.map +1 -1
  74. package/dist/agents/middleware/llmToolSelector.js +3 -1
  75. package/dist/agents/middleware/llmToolSelector.js.map +1 -1
  76. package/dist/agents/middleware/modelCallLimit.cjs +0 -1
  77. package/dist/agents/middleware/modelCallLimit.cjs.map +1 -1
  78. package/dist/agents/middleware/modelCallLimit.d.cts +1 -3
  79. package/dist/agents/middleware/modelCallLimit.d.cts.map +1 -1
  80. package/dist/agents/middleware/modelCallLimit.d.ts +1 -3
  81. package/dist/agents/middleware/modelCallLimit.d.ts.map +1 -1
  82. package/dist/agents/middleware/modelCallLimit.js.map +1 -1
  83. package/dist/agents/middleware/modelFallback.cjs.map +1 -1
  84. package/dist/agents/middleware/modelFallback.d.cts +1 -3
  85. package/dist/agents/middleware/modelFallback.d.cts.map +1 -1
  86. package/dist/agents/middleware/modelFallback.d.ts +1 -3
  87. package/dist/agents/middleware/modelFallback.d.ts.map +1 -1
  88. package/dist/agents/middleware/modelFallback.js.map +1 -1
  89. package/dist/agents/middleware/modelRetry.cjs +1 -1
  90. package/dist/agents/middleware/modelRetry.cjs.map +1 -1
  91. package/dist/agents/middleware/modelRetry.d.cts +2 -4
  92. package/dist/agents/middleware/modelRetry.d.cts.map +1 -1
  93. package/dist/agents/middleware/modelRetry.d.ts +2 -4
  94. package/dist/agents/middleware/modelRetry.d.ts.map +1 -1
  95. package/dist/agents/middleware/modelRetry.js +1 -1
  96. package/dist/agents/middleware/modelRetry.js.map +1 -1
  97. package/dist/agents/middleware/pii.cjs +2 -1
  98. package/dist/agents/middleware/pii.cjs.map +1 -1
  99. package/dist/agents/middleware/pii.d.cts +2 -4
  100. package/dist/agents/middleware/pii.d.cts.map +1 -1
  101. package/dist/agents/middleware/pii.d.ts +2 -4
  102. package/dist/agents/middleware/pii.d.ts.map +1 -1
  103. package/dist/agents/middleware/pii.js +2 -0
  104. package/dist/agents/middleware/pii.js.map +1 -1
  105. package/dist/agents/middleware/piiRedaction.cjs +0 -1
  106. package/dist/agents/middleware/piiRedaction.cjs.map +1 -1
  107. package/dist/agents/middleware/piiRedaction.d.cts +1 -3
  108. package/dist/agents/middleware/piiRedaction.d.cts.map +1 -1
  109. package/dist/agents/middleware/piiRedaction.d.ts +1 -3
  110. package/dist/agents/middleware/piiRedaction.d.ts.map +1 -1
  111. package/dist/agents/middleware/piiRedaction.js.map +1 -1
  112. package/dist/agents/middleware/provider/anthropic/promptCaching.cjs +0 -1
  113. package/dist/agents/middleware/provider/anthropic/promptCaching.cjs.map +1 -1
  114. package/dist/agents/middleware/provider/anthropic/promptCaching.d.cts +1 -3
  115. package/dist/agents/middleware/provider/anthropic/promptCaching.d.cts.map +1 -1
  116. package/dist/agents/middleware/provider/anthropic/promptCaching.d.ts +1 -3
  117. package/dist/agents/middleware/provider/anthropic/promptCaching.d.ts.map +1 -1
  118. package/dist/agents/middleware/provider/anthropic/promptCaching.js.map +1 -1
  119. package/dist/agents/middleware/provider/aws/promptCaching.cjs +0 -1
  120. package/dist/agents/middleware/provider/aws/promptCaching.cjs.map +1 -1
  121. package/dist/agents/middleware/provider/aws/promptCaching.d.cts +1 -3
  122. package/dist/agents/middleware/provider/aws/promptCaching.d.cts.map +1 -1
  123. package/dist/agents/middleware/provider/aws/promptCaching.d.ts +1 -3
  124. package/dist/agents/middleware/provider/aws/promptCaching.d.ts.map +1 -1
  125. package/dist/agents/middleware/provider/aws/promptCaching.js.map +1 -1
  126. package/dist/agents/middleware/provider/openai/moderation.cjs +1 -1
  127. package/dist/agents/middleware/provider/openai/moderation.cjs.map +1 -1
  128. package/dist/agents/middleware/provider/openai/moderation.d.cts +0 -4
  129. package/dist/agents/middleware/provider/openai/moderation.d.cts.map +1 -1
  130. package/dist/agents/middleware/provider/openai/moderation.d.ts +0 -4
  131. package/dist/agents/middleware/provider/openai/moderation.d.ts.map +1 -1
  132. package/dist/agents/middleware/provider/openai/moderation.js +1 -1
  133. package/dist/agents/middleware/provider/openai/moderation.js.map +1 -1
  134. package/dist/agents/middleware/providerToolSearch.cjs +0 -1
  135. package/dist/agents/middleware/providerToolSearch.cjs.map +1 -1
  136. package/dist/agents/middleware/providerToolSearch.d.cts +1 -2
  137. package/dist/agents/middleware/providerToolSearch.d.cts.map +1 -1
  138. package/dist/agents/middleware/providerToolSearch.d.ts +1 -2
  139. package/dist/agents/middleware/providerToolSearch.d.ts.map +1 -1
  140. package/dist/agents/middleware/providerToolSearch.js.map +1 -1
  141. package/dist/agents/middleware/summarization.cjs +8 -5
  142. package/dist/agents/middleware/summarization.cjs.map +1 -1
  143. package/dist/agents/middleware/summarization.d.cts +16 -20
  144. package/dist/agents/middleware/summarization.d.cts.map +1 -1
  145. package/dist/agents/middleware/summarization.d.ts +16 -20
  146. package/dist/agents/middleware/summarization.d.ts.map +1 -1
  147. package/dist/agents/middleware/summarization.js +8 -5
  148. package/dist/agents/middleware/summarization.js.map +1 -1
  149. package/dist/agents/middleware/todoListMiddleware.cjs +0 -1
  150. package/dist/agents/middleware/todoListMiddleware.cjs.map +1 -1
  151. package/dist/agents/middleware/todoListMiddleware.d.cts +2 -5
  152. package/dist/agents/middleware/todoListMiddleware.d.cts.map +1 -1
  153. package/dist/agents/middleware/todoListMiddleware.d.ts +2 -5
  154. package/dist/agents/middleware/todoListMiddleware.d.ts.map +1 -1
  155. package/dist/agents/middleware/todoListMiddleware.js.map +1 -1
  156. package/dist/agents/middleware/toolCallLimit.cjs +0 -1
  157. package/dist/agents/middleware/toolCallLimit.cjs.map +1 -1
  158. package/dist/agents/middleware/toolCallLimit.d.cts +2 -4
  159. package/dist/agents/middleware/toolCallLimit.d.cts.map +1 -1
  160. package/dist/agents/middleware/toolCallLimit.d.ts +2 -4
  161. package/dist/agents/middleware/toolCallLimit.d.ts.map +1 -1
  162. package/dist/agents/middleware/toolCallLimit.js.map +1 -1
  163. package/dist/agents/middleware/toolEmulator.cjs +8 -2
  164. package/dist/agents/middleware/toolEmulator.cjs.map +1 -1
  165. package/dist/agents/middleware/toolEmulator.d.cts +0 -1
  166. package/dist/agents/middleware/toolEmulator.d.cts.map +1 -1
  167. package/dist/agents/middleware/toolEmulator.d.ts +0 -1
  168. package/dist/agents/middleware/toolEmulator.d.ts.map +1 -1
  169. package/dist/agents/middleware/toolEmulator.js +8 -1
  170. package/dist/agents/middleware/toolEmulator.js.map +1 -1
  171. package/dist/agents/middleware/toolError.cjs +0 -1
  172. package/dist/agents/middleware/toolError.cjs.map +1 -1
  173. package/dist/agents/middleware/toolError.d.cts +0 -1
  174. package/dist/agents/middleware/toolError.d.cts.map +1 -1
  175. package/dist/agents/middleware/toolError.d.ts +0 -1
  176. package/dist/agents/middleware/toolError.d.ts.map +1 -1
  177. package/dist/agents/middleware/toolError.js.map +1 -1
  178. package/dist/agents/middleware/toolRetry.cjs +1 -1
  179. package/dist/agents/middleware/toolRetry.cjs.map +1 -1
  180. package/dist/agents/middleware/toolRetry.d.cts +1 -2
  181. package/dist/agents/middleware/toolRetry.d.cts.map +1 -1
  182. package/dist/agents/middleware/toolRetry.d.ts +1 -2
  183. package/dist/agents/middleware/toolRetry.d.ts.map +1 -1
  184. package/dist/agents/middleware/toolRetry.js +1 -1
  185. package/dist/agents/middleware/toolRetry.js.map +1 -1
  186. package/dist/agents/middleware/types.cjs.map +1 -1
  187. package/dist/agents/middleware/types.d.cts +1 -2
  188. package/dist/agents/middleware/types.d.cts.map +1 -1
  189. package/dist/agents/middleware/types.d.ts +1 -2
  190. package/dist/agents/middleware/types.d.ts.map +1 -1
  191. package/dist/agents/middleware/types.js.map +1 -1
  192. package/dist/agents/middleware/utils.cjs +0 -1
  193. package/dist/agents/middleware/utils.cjs.map +1 -1
  194. package/dist/agents/middleware/utils.d.cts +2 -1
  195. package/dist/agents/middleware/utils.d.cts.map +1 -1
  196. package/dist/agents/middleware/utils.d.ts +2 -1
  197. package/dist/agents/middleware/utils.d.ts.map +1 -1
  198. package/dist/agents/middleware/utils.js.map +1 -1
  199. package/dist/agents/middleware.cjs.map +1 -1
  200. package/dist/agents/middleware.d.cts +0 -1
  201. package/dist/agents/middleware.d.cts.map +1 -1
  202. package/dist/agents/middleware.d.ts +0 -1
  203. package/dist/agents/middleware.d.ts.map +1 -1
  204. package/dist/agents/middleware.js.map +1 -1
  205. package/dist/agents/model.cjs.map +1 -1
  206. package/dist/agents/model.d.cts +0 -1
  207. package/dist/agents/model.d.cts.map +1 -1
  208. package/dist/agents/model.d.ts +0 -1
  209. package/dist/agents/model.d.ts.map +1 -1
  210. package/dist/agents/model.js.map +1 -1
  211. package/dist/agents/nodes/AfterAgentNode.cjs +1 -0
  212. package/dist/agents/nodes/AfterAgentNode.cjs.map +1 -1
  213. package/dist/agents/nodes/AfterAgentNode.js +1 -0
  214. package/dist/agents/nodes/AfterAgentNode.js.map +1 -1
  215. package/dist/agents/nodes/AfterModelNode.cjs +1 -0
  216. package/dist/agents/nodes/AfterModelNode.cjs.map +1 -1
  217. package/dist/agents/nodes/AfterModelNode.js +1 -0
  218. package/dist/agents/nodes/AfterModelNode.js.map +1 -1
  219. package/dist/agents/nodes/AgentNode.cjs +0 -1
  220. package/dist/agents/nodes/AgentNode.cjs.map +1 -1
  221. package/dist/agents/nodes/AgentNode.js.map +1 -1
  222. package/dist/agents/nodes/BeforeAgentNode.cjs +1 -0
  223. package/dist/agents/nodes/BeforeAgentNode.cjs.map +1 -1
  224. package/dist/agents/nodes/BeforeAgentNode.js +1 -0
  225. package/dist/agents/nodes/BeforeAgentNode.js.map +1 -1
  226. package/dist/agents/nodes/BeforeModelNode.cjs +1 -0
  227. package/dist/agents/nodes/BeforeModelNode.cjs.map +1 -1
  228. package/dist/agents/nodes/BeforeModelNode.js +1 -0
  229. package/dist/agents/nodes/BeforeModelNode.js.map +1 -1
  230. package/dist/agents/nodes/ToolNode.cjs +2 -1
  231. package/dist/agents/nodes/ToolNode.cjs.map +1 -1
  232. package/dist/agents/nodes/ToolNode.js +2 -1
  233. package/dist/agents/nodes/ToolNode.js.map +1 -1
  234. package/dist/agents/nodes/middleware.cjs +0 -1
  235. package/dist/agents/nodes/middleware.cjs.map +1 -1
  236. package/dist/agents/nodes/middleware.js.map +1 -1
  237. package/dist/agents/nodes/types.d.cts +0 -1
  238. package/dist/agents/nodes/types.d.cts.map +1 -1
  239. package/dist/agents/nodes/types.d.ts +0 -1
  240. package/dist/agents/nodes/types.d.ts.map +1 -1
  241. package/dist/agents/nodes/utils.cjs +0 -1
  242. package/dist/agents/nodes/utils.cjs.map +1 -1
  243. package/dist/agents/nodes/utils.js.map +1 -1
  244. package/dist/agents/responses.cjs +11 -5
  245. package/dist/agents/responses.cjs.map +1 -1
  246. package/dist/agents/responses.d.cts +3 -3
  247. package/dist/agents/responses.d.cts.map +1 -1
  248. package/dist/agents/responses.d.ts +3 -3
  249. package/dist/agents/responses.d.ts.map +1 -1
  250. package/dist/agents/responses.js +11 -5
  251. package/dist/agents/responses.js.map +1 -1
  252. package/dist/agents/runtime.d.cts +2 -2
  253. package/dist/agents/runtime.d.cts.map +1 -1
  254. package/dist/agents/runtime.d.ts +2 -2
  255. package/dist/agents/runtime.d.ts.map +1 -1
  256. package/dist/agents/tests/utils.cjs +0 -1
  257. package/dist/agents/tests/utils.cjs.map +1 -1
  258. package/dist/agents/tests/utils.d.cts +2 -9
  259. package/dist/agents/tests/utils.d.cts.map +1 -1
  260. package/dist/agents/tests/utils.d.ts +2 -9
  261. package/dist/agents/tests/utils.d.ts.map +1 -1
  262. package/dist/agents/tests/utils.js.map +1 -1
  263. package/dist/agents/transformers/index.cjs +4 -2
  264. package/dist/agents/transformers/index.d.cts +2 -1
  265. package/dist/agents/transformers/index.d.ts +2 -1
  266. package/dist/agents/transformers/index.js +3 -3
  267. package/dist/agents/transformers/subagent.cjs +0 -1
  268. package/dist/agents/transformers/subagent.cjs.map +1 -1
  269. package/dist/agents/transformers/subagent.d.cts +0 -1
  270. package/dist/agents/transformers/subagent.d.cts.map +1 -1
  271. package/dist/agents/transformers/subagent.d.ts +0 -1
  272. package/dist/agents/transformers/subagent.d.ts.map +1 -1
  273. package/dist/agents/transformers/subagent.js.map +1 -1
  274. package/dist/agents/transformers/tool-call.cjs +0 -1
  275. package/dist/agents/transformers/tool-call.cjs.map +1 -1
  276. package/dist/agents/transformers/tool-call.d.cts +0 -1
  277. package/dist/agents/transformers/tool-call.d.cts.map +1 -1
  278. package/dist/agents/transformers/tool-call.d.ts +0 -1
  279. package/dist/agents/transformers/tool-call.d.ts.map +1 -1
  280. package/dist/agents/transformers/tool-call.js.map +1 -1
  281. package/dist/agents/transformers/types.d.cts +3 -3
  282. package/dist/agents/transformers/types.d.cts.map +1 -1
  283. package/dist/agents/transformers/types.d.ts +3 -3
  284. package/dist/agents/transformers/types.d.ts.map +1 -1
  285. package/dist/agents/types.d.cts +1 -2
  286. package/dist/agents/types.d.cts.map +1 -1
  287. package/dist/agents/types.d.ts +1 -2
  288. package/dist/agents/types.d.ts.map +1 -1
  289. package/dist/agents/utils.cjs +0 -1
  290. package/dist/agents/utils.cjs.map +1 -1
  291. package/dist/agents/utils.js.map +1 -1
  292. package/dist/agents/withAgentName.cjs +0 -1
  293. package/dist/agents/withAgentName.cjs.map +1 -1
  294. package/dist/agents/withAgentName.js.map +1 -1
  295. package/dist/browser.d.cts +2 -1
  296. package/dist/browser.d.ts +2 -1
  297. package/dist/chat_models/universal.cjs.map +1 -1
  298. package/dist/chat_models/universal.d.cts +0 -1
  299. package/dist/chat_models/universal.d.cts.map +1 -1
  300. package/dist/chat_models/universal.d.ts +0 -1
  301. package/dist/chat_models/universal.d.ts.map +1 -1
  302. package/dist/chat_models/universal.js.map +1 -1
  303. package/dist/hub/base.cjs +0 -1
  304. package/dist/hub/base.cjs.map +1 -1
  305. package/dist/hub/base.d.cts +1 -0
  306. package/dist/hub/base.d.cts.map +1 -1
  307. package/dist/hub/base.d.ts +1 -0
  308. package/dist/hub/base.d.ts.map +1 -1
  309. package/dist/hub/base.js.map +1 -1
  310. package/dist/hub/index.cjs.map +1 -1
  311. package/dist/hub/index.d.cts +0 -1
  312. package/dist/hub/index.d.cts.map +1 -1
  313. package/dist/hub/index.d.ts +0 -1
  314. package/dist/hub/index.d.ts.map +1 -1
  315. package/dist/hub/index.js.map +1 -1
  316. package/dist/hub/node.cjs.map +1 -1
  317. package/dist/hub/node.d.cts +0 -1
  318. package/dist/hub/node.d.cts.map +1 -1
  319. package/dist/hub/node.d.ts +0 -1
  320. package/dist/hub/node.d.ts.map +1 -1
  321. package/dist/hub/node.js.map +1 -1
  322. package/dist/index.d.cts +2 -1
  323. package/dist/index.d.ts +2 -1
  324. package/dist/load/import_constants.cjs.map +1 -1
  325. package/dist/load/import_constants.js.map +1 -1
  326. package/dist/load/import_map.cjs +56 -0
  327. package/dist/load/import_map.cjs.map +1 -1
  328. package/dist/load/import_map.js +1 -1
  329. package/dist/load/import_map.js.map +1 -1
  330. package/dist/load/import_type.d.cts.map +1 -1
  331. package/dist/load/import_type.d.ts.map +1 -1
  332. package/dist/load/index.cjs +0 -1
  333. package/dist/load/index.cjs.map +1 -1
  334. package/dist/load/index.d.cts +0 -1
  335. package/dist/load/index.d.cts.map +1 -1
  336. package/dist/load/index.d.ts +0 -1
  337. package/dist/load/index.d.ts.map +1 -1
  338. package/dist/load/index.js.map +1 -1
  339. package/dist/storage/encoder_backed.cjs.map +1 -1
  340. package/dist/storage/encoder_backed.d.cts +0 -1
  341. package/dist/storage/encoder_backed.d.cts.map +1 -1
  342. package/dist/storage/encoder_backed.d.ts +0 -1
  343. package/dist/storage/encoder_backed.d.ts.map +1 -1
  344. package/dist/storage/encoder_backed.js.map +1 -1
  345. package/dist/storage/file_system.cjs +4 -3
  346. package/dist/storage/file_system.cjs.map +1 -1
  347. package/dist/storage/file_system.d.cts +20 -1
  348. package/dist/storage/file_system.d.cts.map +1 -1
  349. package/dist/storage/file_system.d.ts +20 -1
  350. package/dist/storage/file_system.d.ts.map +1 -1
  351. package/dist/storage/file_system.js +4 -3
  352. package/dist/storage/file_system.js.map +1 -1
  353. package/dist/tools/headless.cjs +0 -1
  354. package/dist/tools/headless.cjs.map +1 -1
  355. package/dist/tools/headless.d.cts +5 -3
  356. package/dist/tools/headless.d.cts.map +1 -1
  357. package/dist/tools/headless.d.ts +5 -3
  358. package/dist/tools/headless.d.ts.map +1 -1
  359. package/dist/tools/headless.js.map +1 -1
  360. package/package.json +14 -14
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/load/index.ts"],"mappings":";;;;;AAyBA;;;;;;;;;;;;;;;;;;iBAAsB,IAAA,GAAA,CACpB,IAAA,UAEA,UAAA,GAAY,MAAA,eAEZ,kBAAA,GAAoB,iBAAA,GAAoB,MAAA,eAExC,oBAAA,GAAsB,MAAA,eACtB,cAAA,aACC,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../../src/load/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;iBAyBsB,KAAK,GACzB,cAEA,aAAY,qBAEZ,qBAAoB,oBAAoB,qBAExC,uBAAsB,qBACtB,2BACC,QAAQ"}
@@ -1,5 +1,4 @@
1
1
  import { OptionalImportMap } from "./import_type.js";
2
-
3
2
  //#region src/load/index.d.ts
4
3
  /**
5
4
  * Load a LangChain module from a serialized text representation.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/load/index.ts"],"mappings":";;;;;AAyBA;;;;;;;;;;;;;;;;;;iBAAsB,IAAA,GAAA,CACpB,IAAA,UAEA,UAAA,GAAY,MAAA,eAEZ,kBAAA,GAAoB,iBAAA,GAAoB,MAAA,eAExC,oBAAA,GAAsB,MAAA,eACtB,cAAA,aACC,OAAA,CAAQ,CAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/load/index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;iBAyBsB,KAAK,GACzB,cAEA,aAAY,qBAEZ,qBAAoB,oBAAoB,qBAExC,uBAAsB,qBACtB,2BACC,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["coreLoad","importMap"],"sources":["../../src/load/index.ts"],"sourcesContent":["import { load as coreLoad } from \"@langchain/core/load\";\nimport { optionalImportEntrypoints } from \"./import_constants.js\";\nimport * as importMap from \"./import_map.js\";\nimport { OptionalImportMap } from \"./import_type.js\";\n\n/**\n * Load a LangChain module from a serialized text representation.\n * NOTE: This functionality is currently in beta.\n * Loaded classes may change independently of semver.\n *\n * **WARNING — insecure deserialization risk.** This function instantiates\n * classes and invokes constructors based on the contents of `text`. Never\n * call this on untrusted or user-supplied input. Only deserialize data that\n * originates from a trusted source you control.\n *\n * See `@langchain/core/load` {@link LoadOptions} for detailed security\n * guidance on `secretsFromEnv`, `secretsMap`, and import maps.\n *\n * @param text Serialized text representation of the module.\n * @param secretsMap\n * @param optionalImportsMap\n * @param additionalImportsMap\n * @param secretsFromEnv\n * @returns A loaded instance of a LangChain module.\n */\nexport async function load<T>(\n text: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n secretsMap: Record<string, any> = {},\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n optionalImportsMap: OptionalImportMap & Record<string, any> = {},\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n additionalImportsMap: Record<string, any> = {},\n secretsFromEnv?: boolean\n): Promise<T> {\n return coreLoad(text, {\n secretsMap,\n optionalImportsMap,\n optionalImportEntrypoints,\n importMap: { ...importMap, ...additionalImportsMap },\n secretsFromEnv,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyBA,eAAsB,KACpB,MAEA,aAAkC,EAAE,EAEpC,qBAA8D,EAAE,EAEhE,uBAA4C,EAAE,EAC9C,gBACY;AACZ,QAAOA,OAAS,MAAM;EACpB;EACA;EACA;EACA,WAAW;GAAE,GAAGC;GAAW,GAAG;GAAsB;EACpD;EACD,CAAC"}
1
+ {"version":3,"file":"index.js","names":["coreLoad","importMap"],"sources":["../../src/load/index.ts"],"sourcesContent":["import { load as coreLoad } from \"@langchain/core/load\";\nimport { optionalImportEntrypoints } from \"./import_constants.js\";\nimport * as importMap from \"./import_map.js\";\nimport { OptionalImportMap } from \"./import_type.js\";\n\n/**\n * Load a LangChain module from a serialized text representation.\n * NOTE: This functionality is currently in beta.\n * Loaded classes may change independently of semver.\n *\n * **WARNING — insecure deserialization risk.** This function instantiates\n * classes and invokes constructors based on the contents of `text`. Never\n * call this on untrusted or user-supplied input. Only deserialize data that\n * originates from a trusted source you control.\n *\n * See `@langchain/core/load` {@link LoadOptions} for detailed security\n * guidance on `secretsFromEnv`, `secretsMap`, and import maps.\n *\n * @param text Serialized text representation of the module.\n * @param secretsMap\n * @param optionalImportsMap\n * @param additionalImportsMap\n * @param secretsFromEnv\n * @returns A loaded instance of a LangChain module.\n */\nexport async function load<T>(\n text: string,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n secretsMap: Record<string, any> = {},\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n optionalImportsMap: OptionalImportMap & Record<string, any> = {},\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n additionalImportsMap: Record<string, any> = {},\n secretsFromEnv?: boolean\n): Promise<T> {\n return coreLoad(text, {\n secretsMap,\n optionalImportsMap,\n optionalImportEntrypoints,\n importMap: { ...importMap, ...additionalImportsMap },\n secretsFromEnv,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAyBA,eAAsB,KACpB,MAEA,aAAkC,CAAC,GAEnC,qBAA8D,CAAC,GAE/D,uBAA4C,CAAC,GAC7C,gBACY;CACZ,OAAOA,OAAS,MAAM;EACpB;EACA;EACA;EACA,WAAW;GAAE,GAAGC;GAAW,GAAG;EAAqB;EACnD;CACF,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"encoder_backed.cjs","names":["BaseStore","Document"],"sources":["../../src/storage/encoder_backed.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * Class that provides a layer of abstraction over the base storage,\n * allowing for the encoding and decoding of keys and values. It extends\n * the BaseStore class.\n */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport class EncoderBackedStore<K, V, SerializedType = any> extends BaseStore<\n K,\n V\n> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n store: BaseStore<string, SerializedType>;\n\n keyEncoder: (key: K) => string;\n\n valueSerializer: (value: V) => SerializedType;\n\n valueDeserializer: (value: SerializedType) => V;\n\n constructor(fields: {\n store: BaseStore<string, SerializedType>;\n keyEncoder: (key: K) => string;\n valueSerializer: (value: V) => SerializedType;\n valueDeserializer: (value: SerializedType) => V;\n }) {\n super(fields);\n this.store = fields.store;\n this.keyEncoder = fields.keyEncoder;\n this.valueSerializer = fields.valueSerializer;\n this.valueDeserializer = fields.valueDeserializer;\n }\n\n /**\n * Method to get multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keys Array of keys to get\n * @returns Promise that resolves with an array of values or undefined for each key\n */\n async mget(keys: K[]): Promise<(V | undefined)[]> {\n const encodedKeys = keys.map(this.keyEncoder);\n const values = await this.store.mget(encodedKeys);\n return values.map((value) => {\n if (value === undefined) {\n return undefined;\n }\n return this.valueDeserializer(value);\n });\n }\n\n /**\n * Method to set multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keyValuePairs Array of key-value pairs to set\n * @returns Promise that resolves when the operation is complete\n */\n async mset(keyValuePairs: [K, V][]): Promise<void> {\n const encodedPairs: [string, SerializedType][] = keyValuePairs.map(\n ([key, value]) => [this.keyEncoder(key), this.valueSerializer(value)]\n );\n return this.store.mset(encodedPairs);\n }\n\n /**\n * Method to delete multiple keys at once. It works with the encoded keys.\n * @param keys Array of keys to delete\n * @returns Promise that resolves when the operation is complete\n */\n async mdelete(keys: K[]): Promise<void> {\n const encodedKeys = keys.map(this.keyEncoder);\n return this.store.mdelete(encodedKeys);\n }\n\n /**\n * Method to yield keys. It works with the encoded keys.\n * @param prefix Optional prefix to filter keys\n * @returns AsyncGenerator that yields keys\n */\n async *yieldKeys(prefix?: string | undefined): AsyncGenerator<string | K> {\n yield* this.store.yieldKeys(prefix);\n }\n}\n\nexport function createDocumentStoreFromByteStore(\n store: BaseStore<string, Uint8Array>\n) {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n return new EncoderBackedStore({\n store,\n keyEncoder: (key: string) => key,\n valueSerializer: (doc: Document) =>\n encoder.encode(\n JSON.stringify({ pageContent: doc.pageContent, metadata: doc.metadata })\n ),\n valueDeserializer: (bytes: Uint8Array) =>\n new Document(JSON.parse(decoder.decode(bytes))),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AASA,IAAa,qBAAb,cAAoEA,uBAAAA,UAGlE;CACA,eAAe,CAAC,aAAa,UAAU;CAEvC;CAEA;CAEA;CAEA;CAEA,YAAY,QAKT;AACD,QAAM,OAAO;AACb,OAAK,QAAQ,OAAO;AACpB,OAAK,aAAa,OAAO;AACzB,OAAK,kBAAkB,OAAO;AAC9B,OAAK,oBAAoB,OAAO;;;;;;;;CASlC,MAAM,KAAK,MAAuC;EAChD,MAAM,cAAc,KAAK,IAAI,KAAK,WAAW;AAE7C,UAAO,MADc,KAAK,MAAM,KAAK,YAAY,EACnC,KAAK,UAAU;AAC3B,OAAI,UAAU,KAAA,EACZ;AAEF,UAAO,KAAK,kBAAkB,MAAM;IACpC;;;;;;;;CASJ,MAAM,KAAK,eAAwC;EACjD,MAAM,eAA2C,cAAc,KAC5D,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW,IAAI,EAAE,KAAK,gBAAgB,MAAM,CAAC,CACtE;AACD,SAAO,KAAK,MAAM,KAAK,aAAa;;;;;;;CAQtC,MAAM,QAAQ,MAA0B;EACtC,MAAM,cAAc,KAAK,IAAI,KAAK,WAAW;AAC7C,SAAO,KAAK,MAAM,QAAQ,YAAY;;;;;;;CAQxC,OAAO,UAAU,QAAyD;AACxE,SAAO,KAAK,MAAM,UAAU,OAAO;;;AAIvC,SAAgB,iCACd,OACA;CACA,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,IAAI,mBAAmB;EAC5B;EACA,aAAa,QAAgB;EAC7B,kBAAkB,QAChB,QAAQ,OACN,KAAK,UAAU;GAAE,aAAa,IAAI;GAAa,UAAU,IAAI;GAAU,CAAC,CACzE;EACH,oBAAoB,UAClB,IAAIC,0BAAAA,SAAS,KAAK,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;EAClD,CAAC"}
1
+ {"version":3,"file":"encoder_backed.cjs","names":["BaseStore","Document"],"sources":["../../src/storage/encoder_backed.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * Class that provides a layer of abstraction over the base storage,\n * allowing for the encoding and decoding of keys and values. It extends\n * the BaseStore class.\n */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport class EncoderBackedStore<K, V, SerializedType = any> extends BaseStore<\n K,\n V\n> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n store: BaseStore<string, SerializedType>;\n\n keyEncoder: (key: K) => string;\n\n valueSerializer: (value: V) => SerializedType;\n\n valueDeserializer: (value: SerializedType) => V;\n\n constructor(fields: {\n store: BaseStore<string, SerializedType>;\n keyEncoder: (key: K) => string;\n valueSerializer: (value: V) => SerializedType;\n valueDeserializer: (value: SerializedType) => V;\n }) {\n super(fields);\n this.store = fields.store;\n this.keyEncoder = fields.keyEncoder;\n this.valueSerializer = fields.valueSerializer;\n this.valueDeserializer = fields.valueDeserializer;\n }\n\n /**\n * Method to get multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keys Array of keys to get\n * @returns Promise that resolves with an array of values or undefined for each key\n */\n async mget(keys: K[]): Promise<(V | undefined)[]> {\n const encodedKeys = keys.map(this.keyEncoder);\n const values = await this.store.mget(encodedKeys);\n return values.map((value) => {\n if (value === undefined) {\n return undefined;\n }\n return this.valueDeserializer(value);\n });\n }\n\n /**\n * Method to set multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keyValuePairs Array of key-value pairs to set\n * @returns Promise that resolves when the operation is complete\n */\n async mset(keyValuePairs: [K, V][]): Promise<void> {\n const encodedPairs: [string, SerializedType][] = keyValuePairs.map(\n ([key, value]) => [this.keyEncoder(key), this.valueSerializer(value)]\n );\n return this.store.mset(encodedPairs);\n }\n\n /**\n * Method to delete multiple keys at once. It works with the encoded keys.\n * @param keys Array of keys to delete\n * @returns Promise that resolves when the operation is complete\n */\n async mdelete(keys: K[]): Promise<void> {\n const encodedKeys = keys.map(this.keyEncoder);\n return this.store.mdelete(encodedKeys);\n }\n\n /**\n * Method to yield keys. It works with the encoded keys.\n * @param prefix Optional prefix to filter keys\n * @returns AsyncGenerator that yields keys\n */\n async *yieldKeys(prefix?: string | undefined): AsyncGenerator<string | K> {\n yield* this.store.yieldKeys(prefix);\n }\n}\n\nexport function createDocumentStoreFromByteStore(\n store: BaseStore<string, Uint8Array>\n) {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n return new EncoderBackedStore({\n store,\n keyEncoder: (key: string) => key,\n valueSerializer: (doc: Document) =>\n encoder.encode(\n JSON.stringify({ pageContent: doc.pageContent, metadata: doc.metadata })\n ),\n valueDeserializer: (bytes: Uint8Array) =>\n new Document(JSON.parse(decoder.decode(bytes))),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AASA,IAAa,qBAAb,cAAoEA,uBAAAA,UAGlE;CACA,eAAe,CAAC,aAAa,SAAS;CAEtC;CAEA;CAEA;CAEA;CAEA,YAAY,QAKT;EACD,MAAM,MAAM;EACZ,KAAK,QAAQ,OAAO;EACpB,KAAK,aAAa,OAAO;EACzB,KAAK,kBAAkB,OAAO;EAC9B,KAAK,oBAAoB,OAAO;CAClC;;;;;;;CAQA,MAAM,KAAK,MAAuC;EAChD,MAAM,cAAc,KAAK,IAAI,KAAK,UAAU;EAE5C,QAAO,MADc,KAAK,MAAM,KAAK,WAAW,EAAA,CAClC,KAAK,UAAU;GAC3B,IAAI,UAAU,KAAA,GACZ;GAEF,OAAO,KAAK,kBAAkB,KAAK;EACrC,CAAC;CACH;;;;;;;CAQA,MAAM,KAAK,eAAwC;EACjD,MAAM,eAA2C,cAAc,KAC5D,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW,GAAG,GAAG,KAAK,gBAAgB,KAAK,CAAC,CACtE;EACA,OAAO,KAAK,MAAM,KAAK,YAAY;CACrC;;;;;;CAOA,MAAM,QAAQ,MAA0B;EACtC,MAAM,cAAc,KAAK,IAAI,KAAK,UAAU;EAC5C,OAAO,KAAK,MAAM,QAAQ,WAAW;CACvC;;;;;;CAOA,OAAO,UAAU,QAAyD;EACxE,OAAO,KAAK,MAAM,UAAU,MAAM;CACpC;AACF;AAEA,SAAgB,iCACd,OACA;CACA,MAAM,UAAU,IAAI,YAAY;CAChC,MAAM,UAAU,IAAI,YAAY;CAChC,OAAO,IAAI,mBAAmB;EAC5B;EACA,aAAa,QAAgB;EAC7B,kBAAkB,QAChB,QAAQ,OACN,KAAK,UAAU;GAAE,aAAa,IAAI;GAAa,UAAU,IAAI;EAAS,CAAC,CACzE;EACF,oBAAoB,UAClB,IAAIC,0BAAAA,SAAS,KAAK,MAAM,QAAQ,OAAO,KAAK,CAAC,CAAC;CAClD,CAAC;AACH"}
@@ -1,6 +1,5 @@
1
1
  import { BaseStore } from "@langchain/core/stores";
2
2
  import { Document } from "@langchain/core/documents";
3
-
4
3
  //#region src/storage/encoder_backed.d.ts
5
4
  /**
6
5
  * Class that provides a layer of abstraction over the base storage,
@@ -1 +1 @@
1
- {"version":3,"file":"encoder_backed.d.cts","names":[],"sources":["../../src/storage/encoder_backed.ts"],"mappings":";;;;;;AASA;;;cAAa,kBAAA,qCAAuD,SAAA,CAClE,CAAA,EACA,CAAA;EAEA,YAAA;EAEA,KAAA,EAAO,SAAA,SAAkB,cAAA;EAEzB,UAAA,GAAa,GAAA,EAAK,CAAA;EAElB,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,cAAA;EAE/B,iBAAA,GAAoB,KAAA,EAAO,cAAA,KAAmB,CAAA;EAE9C,WAAA,CAAY,MAAA;IACV,KAAA,EAAO,SAAA,SAAkB,cAAA;IACzB,UAAA,GAAa,GAAA,EAAK,CAAA;IAClB,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,cAAA;IAC/B,iBAAA,GAAoB,KAAA,EAAO,cAAA,KAAmB,CAAA;EAAA;EADrB;;;;;;EAgBrB,IAAA,CAAK,IAAA,EAAM,CAAA,KAAM,OAAA,EAAS,CAAA;EAiBL;;;;;;EAArB,IAAA,CAAK,aAAA,GAAgB,CAAA,EAAG,CAAA,MAAO,OAAA;EAlD6B;;;;;EA8D5D,OAAA,CAAQ,IAAA,EAAM,CAAA,KAAM,OAAA;EA9DwC;;;;;EAwE3D,SAAA,CAAU,MAAA,wBAA8B,cAAA,UAAwB,CAAA;AAAA;AAAA,iBAKzD,gCAAA,CACd,KAAA,EAAO,SAAA,SAAkB,UAAA,IAAW,kBAAA,SAAA,QAAA,CAAA,MAAA,gBAAA,UAAA,CAAA,eAAA"}
1
+ {"version":3,"file":"encoder_backed.d.cts","names":[],"sources":["../../src/storage/encoder_backed.ts"],"mappings":";;;;;;;;cASa,mBAAmB,GAAG,GAAG,8BAA8B,UAClE,GACA;EAEA;EAEA,OAAO,kBAAkB;EAEzB,aAAa,KAAK;EAElB,kBAAkB,OAAO,MAAM;EAE/B,oBAAoB,OAAO,mBAAmB;EAE9C,YAAY;IACV,OAAO,kBAAkB;IACzB,aAAa,KAAK;IAClB,kBAAkB,OAAO,MAAM;IAC/B,oBAAoB,OAAO,mBAAmB;;;;;;;;EAe1C,KAAK,MAAM,MAAM,SAAS;;;;;;;EAiB1B,KAAK,gBAAgB,GAAG,OAAO;;;;;;EAY/B,QAAQ,MAAM,MAAM;;;;;;EAUnB,UAAU,8BAA8B,wBAAwB;;iBAKzD,iCACd,OAAO,kBAAkB,cAAW,2BAAA,SAAA,sBAAA,WAAA"}
@@ -1,6 +1,5 @@
1
1
  import { BaseStore } from "@langchain/core/stores";
2
2
  import { Document } from "@langchain/core/documents";
3
-
4
3
  //#region src/storage/encoder_backed.d.ts
5
4
  /**
6
5
  * Class that provides a layer of abstraction over the base storage,
@@ -1 +1 @@
1
- {"version":3,"file":"encoder_backed.d.ts","names":[],"sources":["../../src/storage/encoder_backed.ts"],"mappings":";;;;;;AASA;;;cAAa,kBAAA,qCAAuD,SAAA,CAClE,CAAA,EACA,CAAA;EAEA,YAAA;EAEA,KAAA,EAAO,SAAA,SAAkB,cAAA;EAEzB,UAAA,GAAa,GAAA,EAAK,CAAA;EAElB,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,cAAA;EAE/B,iBAAA,GAAoB,KAAA,EAAO,cAAA,KAAmB,CAAA;EAE9C,WAAA,CAAY,MAAA;IACV,KAAA,EAAO,SAAA,SAAkB,cAAA;IACzB,UAAA,GAAa,GAAA,EAAK,CAAA;IAClB,eAAA,GAAkB,KAAA,EAAO,CAAA,KAAM,cAAA;IAC/B,iBAAA,GAAoB,KAAA,EAAO,cAAA,KAAmB,CAAA;EAAA;EADrB;;;;;;EAgBrB,IAAA,CAAK,IAAA,EAAM,CAAA,KAAM,OAAA,EAAS,CAAA;EAiBL;;;;;;EAArB,IAAA,CAAK,aAAA,GAAgB,CAAA,EAAG,CAAA,MAAO,OAAA;EAlD6B;;;;;EA8D5D,OAAA,CAAQ,IAAA,EAAM,CAAA,KAAM,OAAA;EA9DwC;;;;;EAwE3D,SAAA,CAAU,MAAA,wBAA8B,cAAA,UAAwB,CAAA;AAAA;AAAA,iBAKzD,gCAAA,CACd,KAAA,EAAO,SAAA,SAAkB,UAAA,IAAW,kBAAA,SAAA,QAAA,CAAA,MAAA,gBAAA,UAAA,CAAA,eAAA"}
1
+ {"version":3,"file":"encoder_backed.d.ts","names":[],"sources":["../../src/storage/encoder_backed.ts"],"mappings":";;;;;;;;cASa,mBAAmB,GAAG,GAAG,8BAA8B,UAClE,GACA;EAEA;EAEA,OAAO,kBAAkB;EAEzB,aAAa,KAAK;EAElB,kBAAkB,OAAO,MAAM;EAE/B,oBAAoB,OAAO,mBAAmB;EAE9C,YAAY;IACV,OAAO,kBAAkB;IACzB,aAAa,KAAK;IAClB,kBAAkB,OAAO,MAAM;IAC/B,oBAAoB,OAAO,mBAAmB;;;;;;;;EAe1C,KAAK,MAAM,MAAM,SAAS;;;;;;;EAiB1B,KAAK,gBAAgB,GAAG,OAAO;;;;;;EAY/B,QAAQ,MAAM,MAAM;;;;;;EAUnB,UAAU,8BAA8B,wBAAwB;;iBAKzD,iCACd,OAAO,kBAAkB,cAAW,2BAAA,SAAA,sBAAA,WAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"encoder_backed.js","names":[],"sources":["../../src/storage/encoder_backed.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * Class that provides a layer of abstraction over the base storage,\n * allowing for the encoding and decoding of keys and values. It extends\n * the BaseStore class.\n */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport class EncoderBackedStore<K, V, SerializedType = any> extends BaseStore<\n K,\n V\n> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n store: BaseStore<string, SerializedType>;\n\n keyEncoder: (key: K) => string;\n\n valueSerializer: (value: V) => SerializedType;\n\n valueDeserializer: (value: SerializedType) => V;\n\n constructor(fields: {\n store: BaseStore<string, SerializedType>;\n keyEncoder: (key: K) => string;\n valueSerializer: (value: V) => SerializedType;\n valueDeserializer: (value: SerializedType) => V;\n }) {\n super(fields);\n this.store = fields.store;\n this.keyEncoder = fields.keyEncoder;\n this.valueSerializer = fields.valueSerializer;\n this.valueDeserializer = fields.valueDeserializer;\n }\n\n /**\n * Method to get multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keys Array of keys to get\n * @returns Promise that resolves with an array of values or undefined for each key\n */\n async mget(keys: K[]): Promise<(V | undefined)[]> {\n const encodedKeys = keys.map(this.keyEncoder);\n const values = await this.store.mget(encodedKeys);\n return values.map((value) => {\n if (value === undefined) {\n return undefined;\n }\n return this.valueDeserializer(value);\n });\n }\n\n /**\n * Method to set multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keyValuePairs Array of key-value pairs to set\n * @returns Promise that resolves when the operation is complete\n */\n async mset(keyValuePairs: [K, V][]): Promise<void> {\n const encodedPairs: [string, SerializedType][] = keyValuePairs.map(\n ([key, value]) => [this.keyEncoder(key), this.valueSerializer(value)]\n );\n return this.store.mset(encodedPairs);\n }\n\n /**\n * Method to delete multiple keys at once. It works with the encoded keys.\n * @param keys Array of keys to delete\n * @returns Promise that resolves when the operation is complete\n */\n async mdelete(keys: K[]): Promise<void> {\n const encodedKeys = keys.map(this.keyEncoder);\n return this.store.mdelete(encodedKeys);\n }\n\n /**\n * Method to yield keys. It works with the encoded keys.\n * @param prefix Optional prefix to filter keys\n * @returns AsyncGenerator that yields keys\n */\n async *yieldKeys(prefix?: string | undefined): AsyncGenerator<string | K> {\n yield* this.store.yieldKeys(prefix);\n }\n}\n\nexport function createDocumentStoreFromByteStore(\n store: BaseStore<string, Uint8Array>\n) {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n return new EncoderBackedStore({\n store,\n keyEncoder: (key: string) => key,\n valueSerializer: (doc: Document) =>\n encoder.encode(\n JSON.stringify({ pageContent: doc.pageContent, metadata: doc.metadata })\n ),\n valueDeserializer: (bytes: Uint8Array) =>\n new Document(JSON.parse(decoder.decode(bytes))),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AASA,IAAa,qBAAb,cAAoE,UAGlE;CACA,eAAe,CAAC,aAAa,UAAU;CAEvC;CAEA;CAEA;CAEA;CAEA,YAAY,QAKT;AACD,QAAM,OAAO;AACb,OAAK,QAAQ,OAAO;AACpB,OAAK,aAAa,OAAO;AACzB,OAAK,kBAAkB,OAAO;AAC9B,OAAK,oBAAoB,OAAO;;;;;;;;CASlC,MAAM,KAAK,MAAuC;EAChD,MAAM,cAAc,KAAK,IAAI,KAAK,WAAW;AAE7C,UAAO,MADc,KAAK,MAAM,KAAK,YAAY,EACnC,KAAK,UAAU;AAC3B,OAAI,UAAU,KAAA,EACZ;AAEF,UAAO,KAAK,kBAAkB,MAAM;IACpC;;;;;;;;CASJ,MAAM,KAAK,eAAwC;EACjD,MAAM,eAA2C,cAAc,KAC5D,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW,IAAI,EAAE,KAAK,gBAAgB,MAAM,CAAC,CACtE;AACD,SAAO,KAAK,MAAM,KAAK,aAAa;;;;;;;CAQtC,MAAM,QAAQ,MAA0B;EACtC,MAAM,cAAc,KAAK,IAAI,KAAK,WAAW;AAC7C,SAAO,KAAK,MAAM,QAAQ,YAAY;;;;;;;CAQxC,OAAO,UAAU,QAAyD;AACxE,SAAO,KAAK,MAAM,UAAU,OAAO;;;AAIvC,SAAgB,iCACd,OACA;CACA,MAAM,UAAU,IAAI,aAAa;CACjC,MAAM,UAAU,IAAI,aAAa;AACjC,QAAO,IAAI,mBAAmB;EAC5B;EACA,aAAa,QAAgB;EAC7B,kBAAkB,QAChB,QAAQ,OACN,KAAK,UAAU;GAAE,aAAa,IAAI;GAAa,UAAU,IAAI;GAAU,CAAC,CACzE;EACH,oBAAoB,UAClB,IAAI,SAAS,KAAK,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;EAClD,CAAC"}
1
+ {"version":3,"file":"encoder_backed.js","names":[],"sources":["../../src/storage/encoder_backed.ts"],"sourcesContent":["import { Document } from \"@langchain/core/documents\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * Class that provides a layer of abstraction over the base storage,\n * allowing for the encoding and decoding of keys and values. It extends\n * the BaseStore class.\n */\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport class EncoderBackedStore<K, V, SerializedType = any> extends BaseStore<\n K,\n V\n> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n store: BaseStore<string, SerializedType>;\n\n keyEncoder: (key: K) => string;\n\n valueSerializer: (value: V) => SerializedType;\n\n valueDeserializer: (value: SerializedType) => V;\n\n constructor(fields: {\n store: BaseStore<string, SerializedType>;\n keyEncoder: (key: K) => string;\n valueSerializer: (value: V) => SerializedType;\n valueDeserializer: (value: SerializedType) => V;\n }) {\n super(fields);\n this.store = fields.store;\n this.keyEncoder = fields.keyEncoder;\n this.valueSerializer = fields.valueSerializer;\n this.valueDeserializer = fields.valueDeserializer;\n }\n\n /**\n * Method to get multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keys Array of keys to get\n * @returns Promise that resolves with an array of values or undefined for each key\n */\n async mget(keys: K[]): Promise<(V | undefined)[]> {\n const encodedKeys = keys.map(this.keyEncoder);\n const values = await this.store.mget(encodedKeys);\n return values.map((value) => {\n if (value === undefined) {\n return undefined;\n }\n return this.valueDeserializer(value);\n });\n }\n\n /**\n * Method to set multiple keys at once. It works with the encoded keys and\n * serialized values.\n * @param keyValuePairs Array of key-value pairs to set\n * @returns Promise that resolves when the operation is complete\n */\n async mset(keyValuePairs: [K, V][]): Promise<void> {\n const encodedPairs: [string, SerializedType][] = keyValuePairs.map(\n ([key, value]) => [this.keyEncoder(key), this.valueSerializer(value)]\n );\n return this.store.mset(encodedPairs);\n }\n\n /**\n * Method to delete multiple keys at once. It works with the encoded keys.\n * @param keys Array of keys to delete\n * @returns Promise that resolves when the operation is complete\n */\n async mdelete(keys: K[]): Promise<void> {\n const encodedKeys = keys.map(this.keyEncoder);\n return this.store.mdelete(encodedKeys);\n }\n\n /**\n * Method to yield keys. It works with the encoded keys.\n * @param prefix Optional prefix to filter keys\n * @returns AsyncGenerator that yields keys\n */\n async *yieldKeys(prefix?: string | undefined): AsyncGenerator<string | K> {\n yield* this.store.yieldKeys(prefix);\n }\n}\n\nexport function createDocumentStoreFromByteStore(\n store: BaseStore<string, Uint8Array>\n) {\n const encoder = new TextEncoder();\n const decoder = new TextDecoder();\n return new EncoderBackedStore({\n store,\n keyEncoder: (key: string) => key,\n valueSerializer: (doc: Document) =>\n encoder.encode(\n JSON.stringify({ pageContent: doc.pageContent, metadata: doc.metadata })\n ),\n valueDeserializer: (bytes: Uint8Array) =>\n new Document(JSON.parse(decoder.decode(bytes))),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AASA,IAAa,qBAAb,cAAoE,UAGlE;CACA,eAAe,CAAC,aAAa,SAAS;CAEtC;CAEA;CAEA;CAEA;CAEA,YAAY,QAKT;EACD,MAAM,MAAM;EACZ,KAAK,QAAQ,OAAO;EACpB,KAAK,aAAa,OAAO;EACzB,KAAK,kBAAkB,OAAO;EAC9B,KAAK,oBAAoB,OAAO;CAClC;;;;;;;CAQA,MAAM,KAAK,MAAuC;EAChD,MAAM,cAAc,KAAK,IAAI,KAAK,UAAU;EAE5C,QAAO,MADc,KAAK,MAAM,KAAK,WAAW,EAAA,CAClC,KAAK,UAAU;GAC3B,IAAI,UAAU,KAAA,GACZ;GAEF,OAAO,KAAK,kBAAkB,KAAK;EACrC,CAAC;CACH;;;;;;;CAQA,MAAM,KAAK,eAAwC;EACjD,MAAM,eAA2C,cAAc,KAC5D,CAAC,KAAK,WAAW,CAAC,KAAK,WAAW,GAAG,GAAG,KAAK,gBAAgB,KAAK,CAAC,CACtE;EACA,OAAO,KAAK,MAAM,KAAK,YAAY;CACrC;;;;;;CAOA,MAAM,QAAQ,MAA0B;EACtC,MAAM,cAAc,KAAK,IAAI,KAAK,UAAU;EAC5C,OAAO,KAAK,MAAM,QAAQ,WAAW;CACvC;;;;;;CAOA,OAAO,UAAU,QAAyD;EACxE,OAAO,KAAK,MAAM,UAAU,MAAM;CACpC;AACF;AAEA,SAAgB,iCACd,OACA;CACA,MAAM,UAAU,IAAI,YAAY;CAChC,MAAM,UAAU,IAAI,YAAY;CAChC,OAAO,IAAI,mBAAmB;EAC5B;EACA,aAAa,QAAgB;EAC7B,kBAAkB,QAChB,QAAQ,OACN,KAAK,UAAU;GAAE,aAAa,IAAI;GAAa,UAAU,IAAI;EAAS,CAAC,CACzE;EACF,oBAAoB,UAClB,IAAI,SAAS,KAAK,MAAM,QAAQ,OAAO,KAAK,CAAC,CAAC;CAClD,CAAC;AACH"}
@@ -83,9 +83,10 @@ var LocalFileStore = class extends _langchain_core_stores.BaseStore {
83
83
  try {
84
84
  const keyAsTxtFile = `${key}.txt`;
85
85
  if (!/^[a-zA-Z0-9_.\-/]+$/.test(key)) throw new Error(`Invalid characters in key: ${key}`);
86
- const fullPath = node_path.resolve(this.rootPath, keyAsTxtFile);
87
- const commonPath = node_path.resolve(this.rootPath);
88
- if (!fullPath.startsWith(commonPath)) throw new Error(`Invalid key: ${key}. Key should be relative to the root path. Root path: ${this.rootPath}, Full path: ${fullPath}`);
86
+ const rootPath = node_path.resolve(this.rootPath);
87
+ const fullPath = node_path.resolve(rootPath, keyAsTxtFile);
88
+ const relativePath = node_path.relative(rootPath, fullPath);
89
+ if (relativePath === ".." || relativePath.startsWith(`..${node_path.sep}`) || node_path.isAbsolute(relativePath)) throw new Error(`Invalid key: ${key}. Key should be relative to the root path. Root path: ${this.rootPath}, Full path: ${fullPath}`);
89
90
  return fullPath;
90
91
  } catch (e) {
91
92
  throw new Error(`Error getting full path for key: ${key}.\nError: ${String(e)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"file_system.cjs","names":["BaseStore","fs","path"],"sources":["../../src/storage/file_system.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * File system implementation of the BaseStore using a dictionary. Used for\n * storing key-value pairs in the file system.\n * @example\n * ```typescript\n * const store = await LocalFileStore.fromPath(\"./messages\");\n * await store.mset(\n * Array.from({ length: 5 }).map((_, index) => [\n * `message:id:${index}`,\n * new TextEncoder().encode(\n * JSON.stringify(\n * index % 2 === 0\n * ? new AIMessage(\"ai stuff...\")\n * : new HumanMessage(\"human stuff...\"),\n * ),\n * ),\n * ]),\n * );\n * const retrievedMessages = await store.mget([\"message:id:0\", \"message:id:1\"]);\n * console.log(retrievedMessages.map((v) => new TextDecoder().decode(v)));\n * for await (const key of store.yieldKeys(\"message:id:\")) {\n * await store.mdelete([key]);\n * }\n * ```\n *\n * @security **Security Notice** This file store\n * can alter any text file in the provided directory and any subfolders.\n * Make sure that the path you specify when initializing the store is free\n * of other files.\n */\nexport class LocalFileStore extends BaseStore<string, Uint8Array> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n rootPath: string;\n\n private keyLocks: Map<string, Promise<void>> = new Map();\n\n constructor(fields: { rootPath: string }) {\n super(fields);\n this.rootPath = fields.rootPath;\n }\n\n /**\n * Read and parse the file at the given path.\n * @param key The key to read the file for.\n * @returns Promise that resolves to the parsed file content.\n */\n private async getParsedFile(key: string): Promise<Uint8Array | undefined> {\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_\\-:.]+$/.test(key)) {\n throw new Error(\n \"Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.\"\n );\n }\n try {\n const fileContent = await fs.readFile(this.getFullPath(key));\n if (!fileContent) {\n return undefined;\n }\n return fileContent;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n // File does not exist yet.\n if (\"code\" in e && e.code === \"ENOENT\") {\n return undefined;\n }\n throw new Error(\n `Error reading and parsing file at path: ${\n this.rootPath\n }.\\nError: ${JSON.stringify(e)}`\n );\n }\n }\n\n /**\n * Writes the given key-value pairs to the file at the given path.\n * @param fileContent An object with the key-value pairs to be written to the file.\n */\n private async setFileContent(content: Uint8Array, key: string) {\n await this.withKeyLock(key, async () => {\n const fullPath = this.getFullPath(key);\n try {\n await this.writeFileAtomically(content, fullPath);\n } catch (error) {\n throw new Error(\n `Error writing file at path: ${fullPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n });\n }\n\n /**\n * Returns the full path of the file where the value of the given key is stored.\n * @param key the key to get the full path for\n */\n private getFullPath(key: string): string {\n try {\n const keyAsTxtFile = `${key}.txt`;\n\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_.\\-/]+$/.test(key)) {\n throw new Error(`Invalid characters in key: ${key}`);\n }\n\n const fullPath = path.resolve(this.rootPath, keyAsTxtFile);\n const commonPath = path.resolve(this.rootPath);\n\n if (!fullPath.startsWith(commonPath)) {\n throw new Error(\n `Invalid key: ${key}. Key should be relative to the root path. ` +\n `Root path: ${this.rootPath}, Full path: ${fullPath}`\n );\n }\n\n return fullPath;\n } catch (e) {\n throw new Error(\n `Error getting full path for key: ${key}.\\nError: ${String(e)}`\n );\n }\n }\n\n /**\n * Retrieves the values associated with the given keys from the store.\n * @param keys Keys to retrieve values for.\n * @returns Array of values associated with the given keys.\n */\n async mget(keys: string[]) {\n const values: (Uint8Array | undefined)[] = [];\n for (const key of keys) {\n const fileContent = await this.getParsedFile(key);\n values.push(fileContent);\n }\n return values;\n }\n\n /**\n * Sets the values for the given keys in the store.\n * The last value for duplicate keys will be used.\n * @param keyValuePairs Array of key-value pairs to set in the store.\n * @returns Promise that resolves when all key-value pairs have been set.\n */\n async mset(keyValuePairs: [string, Uint8Array][]): Promise<void> {\n const deduped = new Map<string, Uint8Array>();\n for (const [key, value] of keyValuePairs) {\n deduped.set(key, value);\n }\n\n await Promise.all(\n Array.from(deduped.entries(), ([key, value]) =>\n this.setFileContent(value, key)\n )\n );\n }\n\n /**\n * Deletes the given keys and their associated values from the store.\n * @param keys Keys to delete from the store.\n * @returns Promise that resolves when all keys have been deleted.\n */\n async mdelete(keys: string[]): Promise<void> {\n await Promise.all(\n keys.map((key) =>\n this.withKeyLock(key, async () => {\n try {\n await fs.unlink(this.getFullPath(key));\n } catch (error) {\n // Ignore missing files so deletes remain idempotent.\n if (!error || (error as { code?: string }).code !== \"ENOENT\") {\n throw error;\n }\n }\n })\n )\n );\n }\n\n /**\n * Asynchronous generator that yields keys from the store. If a prefix is\n * provided, it only yields keys that start with the prefix.\n * @param prefix Optional prefix to filter keys.\n * @returns AsyncGenerator that yields keys from the store.\n */\n async *yieldKeys(prefix?: string): AsyncGenerator<string> {\n const allFiles: string[] = await fs.readdir(this.rootPath);\n const allKeys = allFiles\n .filter((file) => file.endsWith(\".txt\"))\n .map((file) => file.replace(/\\.txt$/, \"\"));\n for (const key of allKeys) {\n if (prefix === undefined || key.startsWith(prefix)) {\n yield key;\n }\n }\n }\n\n /**\n * Static method for initializing the class.\n * Preforms a check to see if the directory exists, and if not, creates it.\n * @param path Path to the directory.\n * @returns Promise that resolves to an instance of the class.\n */\n static async fromPath(rootPath: string): Promise<LocalFileStore> {\n try {\n // Verifies the directory exists at the provided path, and that it is readable and writable.\n await fs.access(rootPath, fs.constants.R_OK | fs.constants.W_OK);\n } catch {\n try {\n // Directory does not exist, create it.\n await fs.mkdir(rootPath, { recursive: true });\n } catch (error) {\n throw new Error(\n `An error occurred creating directory at: ${rootPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n }\n\n // Clean up orphaned temp files left by interrupted atomic writes.\n try {\n const entries = await fs.readdir(rootPath);\n await Promise.all(\n entries\n .filter((file) => file.endsWith(\".tmp\"))\n .map((tempFile) =>\n fs.unlink(path.join(rootPath, tempFile)).catch(() => {})\n )\n );\n } catch {\n // Ignore cleanup errors.\n }\n\n return new this({ rootPath });\n }\n\n /**\n * Ensures calls for the same key run sequentially by chaining promises.\n * @param key Key to serialize operations for.\n * @param fn Async work to execute while the lock is held.\n * @returns Promise resolving with the callback result once the lock releases.\n */\n private async withKeyLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.keyLocks.get(key) ?? Promise.resolve();\n const waitForPrevious = previous.catch(() => {});\n\n let resolveCurrent: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n resolveCurrent = resolve;\n });\n\n const tail = waitForPrevious.then(() => current);\n this.keyLocks.set(key, tail);\n\n await waitForPrevious;\n try {\n return await fn();\n } finally {\n resolveCurrent?.();\n if (this.keyLocks.get(key) === tail) {\n this.keyLocks.delete(key);\n }\n }\n }\n\n /**\n * Writes data to a temporary file before atomically renaming it into place.\n * @param content Serialized value to persist.\n * @param fullPath Destination path for the stored key.\n */\n private async writeFileAtomically(content: Uint8Array, fullPath: string) {\n const directory = path.dirname(fullPath);\n await fs.mkdir(directory, { recursive: true });\n\n const tempPath = `${fullPath}.${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}.tmp`;\n\n try {\n await fs.writeFile(tempPath, content);\n\n try {\n await fs.rename(tempPath, fullPath);\n } catch (renameError) {\n const code = (renameError as { code?: string }).code;\n if (renameError && (code === \"EPERM\" || code === \"EACCES\")) {\n // Fallback for Windows where replacing an existing file can fail if the\n // destination is locked by another process.\n await fs.writeFile(fullPath, content);\n await fs.unlink(tempPath).catch(() => {});\n } else {\n throw renameError;\n }\n }\n } catch (error) {\n await fs.unlink(tempPath).catch(() => {});\n throw error;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"file_system.cjs","names":["BaseStore","fs","path"],"sources":["../../src/storage/file_system.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * File system implementation of the BaseStore using a dictionary. Used for\n * storing key-value pairs in the file system.\n * @example\n * ```typescript\n * const store = await LocalFileStore.fromPath(\"./messages\");\n * await store.mset(\n * Array.from({ length: 5 }).map((_, index) => [\n * `message:id:${index}`,\n * new TextEncoder().encode(\n * JSON.stringify(\n * index % 2 === 0\n * ? new AIMessage(\"ai stuff...\")\n * : new HumanMessage(\"human stuff...\"),\n * ),\n * ),\n * ]),\n * );\n * const retrievedMessages = await store.mget([\"message:id:0\", \"message:id:1\"]);\n * console.log(retrievedMessages.map((v) => new TextDecoder().decode(v)));\n * for await (const key of store.yieldKeys(\"message:id:\")) {\n * await store.mdelete([key]);\n * }\n * ```\n *\n * @security **Security Notice** This file store\n * can alter any text file in the provided directory and any subfolders.\n * Make sure that the path you specify when initializing the store is free\n * of other files.\n */\nexport class LocalFileStore extends BaseStore<string, Uint8Array> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n rootPath: string;\n\n private keyLocks: Map<string, Promise<void>> = new Map();\n\n constructor(fields: { rootPath: string }) {\n super(fields);\n this.rootPath = fields.rootPath;\n }\n\n /**\n * Read and parse the file at the given path.\n * @param key The key to read the file for.\n * @returns Promise that resolves to the parsed file content.\n */\n private async getParsedFile(key: string): Promise<Uint8Array | undefined> {\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_\\-:.]+$/.test(key)) {\n throw new Error(\n \"Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.\"\n );\n }\n try {\n const fileContent = await fs.readFile(this.getFullPath(key));\n if (!fileContent) {\n return undefined;\n }\n return fileContent;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n // File does not exist yet.\n if (\"code\" in e && e.code === \"ENOENT\") {\n return undefined;\n }\n throw new Error(\n `Error reading and parsing file at path: ${\n this.rootPath\n }.\\nError: ${JSON.stringify(e)}`\n );\n }\n }\n\n /**\n * Writes the given key-value pairs to the file at the given path.\n * @param fileContent An object with the key-value pairs to be written to the file.\n */\n private async setFileContent(content: Uint8Array, key: string) {\n await this.withKeyLock(key, async () => {\n const fullPath = this.getFullPath(key);\n try {\n await this.writeFileAtomically(content, fullPath);\n } catch (error) {\n throw new Error(\n `Error writing file at path: ${fullPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n });\n }\n\n /**\n * Returns the full path of the file where the value of the given key is stored.\n * @param key the key to get the full path for\n */\n private getFullPath(key: string): string {\n try {\n const keyAsTxtFile = `${key}.txt`;\n\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_.\\-/]+$/.test(key)) {\n throw new Error(`Invalid characters in key: ${key}`);\n }\n\n const rootPath = path.resolve(this.rootPath);\n const fullPath = path.resolve(rootPath, keyAsTxtFile);\n const relativePath = path.relative(rootPath, fullPath);\n\n if (\n relativePath === \"..\" ||\n relativePath.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(\n `Invalid key: ${key}. Key should be relative to the root path. ` +\n `Root path: ${this.rootPath}, Full path: ${fullPath}`\n );\n }\n\n return fullPath;\n } catch (e) {\n throw new Error(\n `Error getting full path for key: ${key}.\\nError: ${String(e)}`\n );\n }\n }\n\n /**\n * Retrieves the values associated with the given keys from the store.\n * @param keys Keys to retrieve values for.\n * @returns Array of values associated with the given keys.\n */\n async mget(keys: string[]) {\n const values: (Uint8Array | undefined)[] = [];\n for (const key of keys) {\n const fileContent = await this.getParsedFile(key);\n values.push(fileContent);\n }\n return values;\n }\n\n /**\n * Sets the values for the given keys in the store.\n * The last value for duplicate keys will be used.\n * @param keyValuePairs Array of key-value pairs to set in the store.\n * @returns Promise that resolves when all key-value pairs have been set.\n */\n async mset(keyValuePairs: [string, Uint8Array][]): Promise<void> {\n const deduped = new Map<string, Uint8Array>();\n for (const [key, value] of keyValuePairs) {\n deduped.set(key, value);\n }\n\n await Promise.all(\n Array.from(deduped.entries(), ([key, value]) =>\n this.setFileContent(value, key)\n )\n );\n }\n\n /**\n * Deletes the given keys and their associated values from the store.\n * @param keys Keys to delete from the store.\n * @returns Promise that resolves when all keys have been deleted.\n */\n async mdelete(keys: string[]): Promise<void> {\n await Promise.all(\n keys.map((key) =>\n this.withKeyLock(key, async () => {\n try {\n await fs.unlink(this.getFullPath(key));\n } catch (error) {\n // Ignore missing files so deletes remain idempotent.\n if (!error || (error as { code?: string }).code !== \"ENOENT\") {\n throw error;\n }\n }\n })\n )\n );\n }\n\n /**\n * Asynchronous generator that yields keys from the store. If a prefix is\n * provided, it only yields keys that start with the prefix.\n * @param prefix Optional prefix to filter keys.\n * @returns AsyncGenerator that yields keys from the store.\n */\n async *yieldKeys(prefix?: string): AsyncGenerator<string> {\n const allFiles: string[] = await fs.readdir(this.rootPath);\n const allKeys = allFiles\n .filter((file) => file.endsWith(\".txt\"))\n .map((file) => file.replace(/\\.txt$/, \"\"));\n for (const key of allKeys) {\n if (prefix === undefined || key.startsWith(prefix)) {\n yield key;\n }\n }\n }\n\n /**\n * Static method for initializing the class.\n * Preforms a check to see if the directory exists, and if not, creates it.\n * @param path Path to the directory.\n * @returns Promise that resolves to an instance of the class.\n */\n static async fromPath(rootPath: string): Promise<LocalFileStore> {\n try {\n // Verifies the directory exists at the provided path, and that it is readable and writable.\n await fs.access(rootPath, fs.constants.R_OK | fs.constants.W_OK);\n } catch {\n try {\n // Directory does not exist, create it.\n await fs.mkdir(rootPath, { recursive: true });\n } catch (error) {\n throw new Error(\n `An error occurred creating directory at: ${rootPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n }\n\n // Clean up orphaned temp files left by interrupted atomic writes.\n try {\n const entries = await fs.readdir(rootPath);\n await Promise.all(\n entries\n .filter((file) => file.endsWith(\".tmp\"))\n .map((tempFile) =>\n fs.unlink(path.join(rootPath, tempFile)).catch(() => {})\n )\n );\n } catch {\n // Ignore cleanup errors.\n }\n\n return new this({ rootPath });\n }\n\n /**\n * Ensures calls for the same key run sequentially by chaining promises.\n * @param key Key to serialize operations for.\n * @param fn Async work to execute while the lock is held.\n * @returns Promise resolving with the callback result once the lock releases.\n */\n private async withKeyLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.keyLocks.get(key) ?? Promise.resolve();\n const waitForPrevious = previous.catch(() => {});\n\n let resolveCurrent: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n resolveCurrent = resolve;\n });\n\n const tail = waitForPrevious.then(() => current);\n this.keyLocks.set(key, tail);\n\n await waitForPrevious;\n try {\n return await fn();\n } finally {\n resolveCurrent?.();\n if (this.keyLocks.get(key) === tail) {\n this.keyLocks.delete(key);\n }\n }\n }\n\n /**\n * Writes data to a temporary file before atomically renaming it into place.\n * @param content Serialized value to persist.\n * @param fullPath Destination path for the stored key.\n */\n private async writeFileAtomically(content: Uint8Array, fullPath: string) {\n const directory = path.dirname(fullPath);\n await fs.mkdir(directory, { recursive: true });\n\n const tempPath = `${fullPath}.${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}.tmp`;\n\n try {\n await fs.writeFile(tempPath, content);\n\n try {\n await fs.rename(tempPath, fullPath);\n } catch (renameError) {\n const code = (renameError as { code?: string }).code;\n if (renameError && (code === \"EPERM\" || code === \"EACCES\")) {\n // Fallback for Windows where replacing an existing file can fail if the\n // destination is locked by another process.\n await fs.writeFile(fullPath, content);\n await fs.unlink(tempPath).catch(() => {});\n } else {\n throw renameError;\n }\n }\n } catch (error) {\n await fs.unlink(tempPath).catch(() => {});\n throw error;\n }\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { BaseStore } from "@langchain/core/stores";
2
-
3
2
  //#region src/storage/file_system.d.ts
4
3
  /**
5
4
  * File system implementation of the BaseStore using a dictionary. Used for
@@ -38,7 +37,16 @@ declare class LocalFileStore extends BaseStore<string, Uint8Array> {
38
37
  constructor(fields: {
39
38
  rootPath: string;
40
39
  });
40
+ /**
41
+ * Read and parse the file at the given path.
42
+ * @param key The key to read the file for.
43
+ * @returns Promise that resolves to the parsed file content.
44
+ */
41
45
  private getParsedFile;
46
+ /**
47
+ * Writes the given key-value pairs to the file at the given path.
48
+ * @param fileContent An object with the key-value pairs to be written to the file.
49
+ */
42
50
  private setFileContent;
43
51
  /**
44
52
  * Returns the full path of the file where the value of the given key is stored.
@@ -78,7 +86,18 @@ declare class LocalFileStore extends BaseStore<string, Uint8Array> {
78
86
  * @returns Promise that resolves to an instance of the class.
79
87
  */
80
88
  static fromPath(rootPath: string): Promise<LocalFileStore>;
89
+ /**
90
+ * Ensures calls for the same key run sequentially by chaining promises.
91
+ * @param key Key to serialize operations for.
92
+ * @param fn Async work to execute while the lock is held.
93
+ * @returns Promise resolving with the callback result once the lock releases.
94
+ */
81
95
  private withKeyLock;
96
+ /**
97
+ * Writes data to a temporary file before atomically renaming it into place.
98
+ * @param content Serialized value to persist.
99
+ * @param fullPath Destination path for the stored key.
100
+ */
82
101
  private writeFileAtomically;
83
102
  }
84
103
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"file_system.d.cts","names":[],"sources":["../../src/storage/file_system.ts"],"mappings":";;;;;AAkCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,cAAA,SAAuB,SAAA,SAAkB,UAAA;EACpD,YAAA;EAEA,QAAA;EAAA,QAEQ,QAAA;EAER,WAAA,CAAY,MAAA;IAAU,QAAA;EAAA;EAAA,QAUR,aAAA;EAAA,QA+BA,cAAA;EAoFA;;;;EAAA,QAjEN,WAAA;EA0GK;;;;;EA1EP,IAAA,CAAK,IAAA,aAAc,OAAA,EAAA,UAAA,CAAA,eAAA;EA8IQ;;;;;;EA/H3B,IAAA,CAAK,aAAA,WAAwB,UAAA,MAAgB,OAAA;;;;;;EAkB7C,OAAA,CAAQ,IAAA,aAAiB,OAAA;;;;;;;EAuBxB,SAAA,CAAU,MAAA,YAAkB,cAAA;;;;;;;SAkBtB,QAAA,CAAS,QAAA,WAAmB,OAAA,CAAQ,cAAA;EAAA,QAwCnC,WAAA;EAAA,QA4BA,mBAAA;AAAA"}
1
+ {"version":3,"file":"file_system.d.cts","names":[],"sources":["../../src/storage/file_system.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCa,uBAAuB,kBAAkB;EACpD;EAEA;UAEQ;EAER,YAAY;IAAU;;;;;;;UAUR;;;;;UA+BA;;;;;UAmBN;;;;;;EAqCF,KAAK,iBAAc,SAAA,WAAA;;;;;;;EAenB,KAAK,wBAAwB,gBAAgB;;;;;;EAkB7C,QAAQ,iBAAiB;;;;;;;EAuBxB,UAAU,kBAAkB;;;;;;;SAkBtB,SAAS,mBAAmB,QAAQ;;;;;;;UAwCnC;;;;;;UA4BA"}
@@ -1,5 +1,4 @@
1
1
  import { BaseStore } from "@langchain/core/stores";
2
-
3
2
  //#region src/storage/file_system.d.ts
4
3
  /**
5
4
  * File system implementation of the BaseStore using a dictionary. Used for
@@ -38,7 +37,16 @@ declare class LocalFileStore extends BaseStore<string, Uint8Array> {
38
37
  constructor(fields: {
39
38
  rootPath: string;
40
39
  });
40
+ /**
41
+ * Read and parse the file at the given path.
42
+ * @param key The key to read the file for.
43
+ * @returns Promise that resolves to the parsed file content.
44
+ */
41
45
  private getParsedFile;
46
+ /**
47
+ * Writes the given key-value pairs to the file at the given path.
48
+ * @param fileContent An object with the key-value pairs to be written to the file.
49
+ */
42
50
  private setFileContent;
43
51
  /**
44
52
  * Returns the full path of the file where the value of the given key is stored.
@@ -78,7 +86,18 @@ declare class LocalFileStore extends BaseStore<string, Uint8Array> {
78
86
  * @returns Promise that resolves to an instance of the class.
79
87
  */
80
88
  static fromPath(rootPath: string): Promise<LocalFileStore>;
89
+ /**
90
+ * Ensures calls for the same key run sequentially by chaining promises.
91
+ * @param key Key to serialize operations for.
92
+ * @param fn Async work to execute while the lock is held.
93
+ * @returns Promise resolving with the callback result once the lock releases.
94
+ */
81
95
  private withKeyLock;
96
+ /**
97
+ * Writes data to a temporary file before atomically renaming it into place.
98
+ * @param content Serialized value to persist.
99
+ * @param fullPath Destination path for the stored key.
100
+ */
82
101
  private writeFileAtomically;
83
102
  }
84
103
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"file_system.d.ts","names":[],"sources":["../../src/storage/file_system.ts"],"mappings":";;;;;AAkCA;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAa,cAAA,SAAuB,SAAA,SAAkB,UAAA;EACpD,YAAA;EAEA,QAAA;EAAA,QAEQ,QAAA;EAER,WAAA,CAAY,MAAA;IAAU,QAAA;EAAA;EAAA,QAUR,aAAA;EAAA,QA+BA,cAAA;EAoFA;;;;EAAA,QAjEN,WAAA;EA0GK;;;;;EA1EP,IAAA,CAAK,IAAA,aAAc,OAAA,EAAA,UAAA,CAAA,eAAA;EA8IQ;;;;;;EA/H3B,IAAA,CAAK,aAAA,WAAwB,UAAA,MAAgB,OAAA;;;;;;EAkB7C,OAAA,CAAQ,IAAA,aAAiB,OAAA;;;;;;;EAuBxB,SAAA,CAAU,MAAA,YAAkB,cAAA;;;;;;;SAkBtB,QAAA,CAAS,QAAA,WAAmB,OAAA,CAAQ,cAAA;EAAA,QAwCnC,WAAA;EAAA,QA4BA,mBAAA;AAAA"}
1
+ {"version":3,"file":"file_system.d.ts","names":[],"sources":["../../src/storage/file_system.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkCa,uBAAuB,kBAAkB;EACpD;EAEA;UAEQ;EAER,YAAY;IAAU;;;;;;;UAUR;;;;;UA+BA;;;;;UAmBN;;;;;;EAqCF,KAAK,iBAAc,SAAA,WAAA;;;;;;;EAenB,KAAK,wBAAwB,gBAAgB;;;;;;EAkB7C,QAAQ,iBAAiB;;;;;;;EAuBxB,UAAU,kBAAkB;;;;;;;SAkBtB,SAAS,mBAAmB,QAAQ;;;;;;;UAwCnC;;;;;;UA4BA"}
@@ -80,9 +80,10 @@ var LocalFileStore = class extends BaseStore {
80
80
  try {
81
81
  const keyAsTxtFile = `${key}.txt`;
82
82
  if (!/^[a-zA-Z0-9_.\-/]+$/.test(key)) throw new Error(`Invalid characters in key: ${key}`);
83
- const fullPath = path.resolve(this.rootPath, keyAsTxtFile);
84
- const commonPath = path.resolve(this.rootPath);
85
- if (!fullPath.startsWith(commonPath)) throw new Error(`Invalid key: ${key}. Key should be relative to the root path. Root path: ${this.rootPath}, Full path: ${fullPath}`);
83
+ const rootPath = path.resolve(this.rootPath);
84
+ const fullPath = path.resolve(rootPath, keyAsTxtFile);
85
+ const relativePath = path.relative(rootPath, fullPath);
86
+ if (relativePath === ".." || relativePath.startsWith(`..${path.sep}`) || path.isAbsolute(relativePath)) throw new Error(`Invalid key: ${key}. Key should be relative to the root path. Root path: ${this.rootPath}, Full path: ${fullPath}`);
86
87
  return fullPath;
87
88
  } catch (e) {
88
89
  throw new Error(`Error getting full path for key: ${key}.\nError: ${String(e)}`);
@@ -1 +1 @@
1
- {"version":3,"file":"file_system.js","names":[],"sources":["../../src/storage/file_system.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * File system implementation of the BaseStore using a dictionary. Used for\n * storing key-value pairs in the file system.\n * @example\n * ```typescript\n * const store = await LocalFileStore.fromPath(\"./messages\");\n * await store.mset(\n * Array.from({ length: 5 }).map((_, index) => [\n * `message:id:${index}`,\n * new TextEncoder().encode(\n * JSON.stringify(\n * index % 2 === 0\n * ? new AIMessage(\"ai stuff...\")\n * : new HumanMessage(\"human stuff...\"),\n * ),\n * ),\n * ]),\n * );\n * const retrievedMessages = await store.mget([\"message:id:0\", \"message:id:1\"]);\n * console.log(retrievedMessages.map((v) => new TextDecoder().decode(v)));\n * for await (const key of store.yieldKeys(\"message:id:\")) {\n * await store.mdelete([key]);\n * }\n * ```\n *\n * @security **Security Notice** This file store\n * can alter any text file in the provided directory and any subfolders.\n * Make sure that the path you specify when initializing the store is free\n * of other files.\n */\nexport class LocalFileStore extends BaseStore<string, Uint8Array> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n rootPath: string;\n\n private keyLocks: Map<string, Promise<void>> = new Map();\n\n constructor(fields: { rootPath: string }) {\n super(fields);\n this.rootPath = fields.rootPath;\n }\n\n /**\n * Read and parse the file at the given path.\n * @param key The key to read the file for.\n * @returns Promise that resolves to the parsed file content.\n */\n private async getParsedFile(key: string): Promise<Uint8Array | undefined> {\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_\\-:.]+$/.test(key)) {\n throw new Error(\n \"Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.\"\n );\n }\n try {\n const fileContent = await fs.readFile(this.getFullPath(key));\n if (!fileContent) {\n return undefined;\n }\n return fileContent;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n // File does not exist yet.\n if (\"code\" in e && e.code === \"ENOENT\") {\n return undefined;\n }\n throw new Error(\n `Error reading and parsing file at path: ${\n this.rootPath\n }.\\nError: ${JSON.stringify(e)}`\n );\n }\n }\n\n /**\n * Writes the given key-value pairs to the file at the given path.\n * @param fileContent An object with the key-value pairs to be written to the file.\n */\n private async setFileContent(content: Uint8Array, key: string) {\n await this.withKeyLock(key, async () => {\n const fullPath = this.getFullPath(key);\n try {\n await this.writeFileAtomically(content, fullPath);\n } catch (error) {\n throw new Error(\n `Error writing file at path: ${fullPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n });\n }\n\n /**\n * Returns the full path of the file where the value of the given key is stored.\n * @param key the key to get the full path for\n */\n private getFullPath(key: string): string {\n try {\n const keyAsTxtFile = `${key}.txt`;\n\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_.\\-/]+$/.test(key)) {\n throw new Error(`Invalid characters in key: ${key}`);\n }\n\n const fullPath = path.resolve(this.rootPath, keyAsTxtFile);\n const commonPath = path.resolve(this.rootPath);\n\n if (!fullPath.startsWith(commonPath)) {\n throw new Error(\n `Invalid key: ${key}. Key should be relative to the root path. ` +\n `Root path: ${this.rootPath}, Full path: ${fullPath}`\n );\n }\n\n return fullPath;\n } catch (e) {\n throw new Error(\n `Error getting full path for key: ${key}.\\nError: ${String(e)}`\n );\n }\n }\n\n /**\n * Retrieves the values associated with the given keys from the store.\n * @param keys Keys to retrieve values for.\n * @returns Array of values associated with the given keys.\n */\n async mget(keys: string[]) {\n const values: (Uint8Array | undefined)[] = [];\n for (const key of keys) {\n const fileContent = await this.getParsedFile(key);\n values.push(fileContent);\n }\n return values;\n }\n\n /**\n * Sets the values for the given keys in the store.\n * The last value for duplicate keys will be used.\n * @param keyValuePairs Array of key-value pairs to set in the store.\n * @returns Promise that resolves when all key-value pairs have been set.\n */\n async mset(keyValuePairs: [string, Uint8Array][]): Promise<void> {\n const deduped = new Map<string, Uint8Array>();\n for (const [key, value] of keyValuePairs) {\n deduped.set(key, value);\n }\n\n await Promise.all(\n Array.from(deduped.entries(), ([key, value]) =>\n this.setFileContent(value, key)\n )\n );\n }\n\n /**\n * Deletes the given keys and their associated values from the store.\n * @param keys Keys to delete from the store.\n * @returns Promise that resolves when all keys have been deleted.\n */\n async mdelete(keys: string[]): Promise<void> {\n await Promise.all(\n keys.map((key) =>\n this.withKeyLock(key, async () => {\n try {\n await fs.unlink(this.getFullPath(key));\n } catch (error) {\n // Ignore missing files so deletes remain idempotent.\n if (!error || (error as { code?: string }).code !== \"ENOENT\") {\n throw error;\n }\n }\n })\n )\n );\n }\n\n /**\n * Asynchronous generator that yields keys from the store. If a prefix is\n * provided, it only yields keys that start with the prefix.\n * @param prefix Optional prefix to filter keys.\n * @returns AsyncGenerator that yields keys from the store.\n */\n async *yieldKeys(prefix?: string): AsyncGenerator<string> {\n const allFiles: string[] = await fs.readdir(this.rootPath);\n const allKeys = allFiles\n .filter((file) => file.endsWith(\".txt\"))\n .map((file) => file.replace(/\\.txt$/, \"\"));\n for (const key of allKeys) {\n if (prefix === undefined || key.startsWith(prefix)) {\n yield key;\n }\n }\n }\n\n /**\n * Static method for initializing the class.\n * Preforms a check to see if the directory exists, and if not, creates it.\n * @param path Path to the directory.\n * @returns Promise that resolves to an instance of the class.\n */\n static async fromPath(rootPath: string): Promise<LocalFileStore> {\n try {\n // Verifies the directory exists at the provided path, and that it is readable and writable.\n await fs.access(rootPath, fs.constants.R_OK | fs.constants.W_OK);\n } catch {\n try {\n // Directory does not exist, create it.\n await fs.mkdir(rootPath, { recursive: true });\n } catch (error) {\n throw new Error(\n `An error occurred creating directory at: ${rootPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n }\n\n // Clean up orphaned temp files left by interrupted atomic writes.\n try {\n const entries = await fs.readdir(rootPath);\n await Promise.all(\n entries\n .filter((file) => file.endsWith(\".tmp\"))\n .map((tempFile) =>\n fs.unlink(path.join(rootPath, tempFile)).catch(() => {})\n )\n );\n } catch {\n // Ignore cleanup errors.\n }\n\n return new this({ rootPath });\n }\n\n /**\n * Ensures calls for the same key run sequentially by chaining promises.\n * @param key Key to serialize operations for.\n * @param fn Async work to execute while the lock is held.\n * @returns Promise resolving with the callback result once the lock releases.\n */\n private async withKeyLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.keyLocks.get(key) ?? Promise.resolve();\n const waitForPrevious = previous.catch(() => {});\n\n let resolveCurrent: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n resolveCurrent = resolve;\n });\n\n const tail = waitForPrevious.then(() => current);\n this.keyLocks.set(key, tail);\n\n await waitForPrevious;\n try {\n return await fn();\n } finally {\n resolveCurrent?.();\n if (this.keyLocks.get(key) === tail) {\n this.keyLocks.delete(key);\n }\n }\n }\n\n /**\n * Writes data to a temporary file before atomically renaming it into place.\n * @param content Serialized value to persist.\n * @param fullPath Destination path for the stored key.\n */\n private async writeFileAtomically(content: Uint8Array, fullPath: string) {\n const directory = path.dirname(fullPath);\n await fs.mkdir(directory, { recursive: true });\n\n const tempPath = `${fullPath}.${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}.tmp`;\n\n try {\n await fs.writeFile(tempPath, content);\n\n try {\n await fs.rename(tempPath, fullPath);\n } catch (renameError) {\n const code = (renameError as { code?: string }).code;\n if (renameError && (code === \"EPERM\" || code === \"EACCES\")) {\n // Fallback for Windows where replacing an existing file can fail if the\n // destination is locked by another process.\n await fs.writeFile(fullPath, content);\n await fs.unlink(tempPath).catch(() => {});\n } else {\n throw renameError;\n }\n }\n } catch (error) {\n await fs.unlink(tempPath).catch(() => {});\n throw error;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"file_system.js","names":[],"sources":["../../src/storage/file_system.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { BaseStore } from \"@langchain/core/stores\";\n\n/**\n * File system implementation of the BaseStore using a dictionary. Used for\n * storing key-value pairs in the file system.\n * @example\n * ```typescript\n * const store = await LocalFileStore.fromPath(\"./messages\");\n * await store.mset(\n * Array.from({ length: 5 }).map((_, index) => [\n * `message:id:${index}`,\n * new TextEncoder().encode(\n * JSON.stringify(\n * index % 2 === 0\n * ? new AIMessage(\"ai stuff...\")\n * : new HumanMessage(\"human stuff...\"),\n * ),\n * ),\n * ]),\n * );\n * const retrievedMessages = await store.mget([\"message:id:0\", \"message:id:1\"]);\n * console.log(retrievedMessages.map((v) => new TextDecoder().decode(v)));\n * for await (const key of store.yieldKeys(\"message:id:\")) {\n * await store.mdelete([key]);\n * }\n * ```\n *\n * @security **Security Notice** This file store\n * can alter any text file in the provided directory and any subfolders.\n * Make sure that the path you specify when initializing the store is free\n * of other files.\n */\nexport class LocalFileStore extends BaseStore<string, Uint8Array> {\n lc_namespace = [\"langchain\", \"storage\"];\n\n rootPath: string;\n\n private keyLocks: Map<string, Promise<void>> = new Map();\n\n constructor(fields: { rootPath: string }) {\n super(fields);\n this.rootPath = fields.rootPath;\n }\n\n /**\n * Read and parse the file at the given path.\n * @param key The key to read the file for.\n * @returns Promise that resolves to the parsed file content.\n */\n private async getParsedFile(key: string): Promise<Uint8Array | undefined> {\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_\\-:.]+$/.test(key)) {\n throw new Error(\n \"Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.\"\n );\n }\n try {\n const fileContent = await fs.readFile(this.getFullPath(key));\n if (!fileContent) {\n return undefined;\n }\n return fileContent;\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n // File does not exist yet.\n if (\"code\" in e && e.code === \"ENOENT\") {\n return undefined;\n }\n throw new Error(\n `Error reading and parsing file at path: ${\n this.rootPath\n }.\\nError: ${JSON.stringify(e)}`\n );\n }\n }\n\n /**\n * Writes the given key-value pairs to the file at the given path.\n * @param fileContent An object with the key-value pairs to be written to the file.\n */\n private async setFileContent(content: Uint8Array, key: string) {\n await this.withKeyLock(key, async () => {\n const fullPath = this.getFullPath(key);\n try {\n await this.writeFileAtomically(content, fullPath);\n } catch (error) {\n throw new Error(\n `Error writing file at path: ${fullPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n });\n }\n\n /**\n * Returns the full path of the file where the value of the given key is stored.\n * @param key the key to get the full path for\n */\n private getFullPath(key: string): string {\n try {\n const keyAsTxtFile = `${key}.txt`;\n\n // Validate the key to prevent path traversal\n if (!/^[a-zA-Z0-9_.\\-/]+$/.test(key)) {\n throw new Error(`Invalid characters in key: ${key}`);\n }\n\n const rootPath = path.resolve(this.rootPath);\n const fullPath = path.resolve(rootPath, keyAsTxtFile);\n const relativePath = path.relative(rootPath, fullPath);\n\n if (\n relativePath === \"..\" ||\n relativePath.startsWith(`..${path.sep}`) ||\n path.isAbsolute(relativePath)\n ) {\n throw new Error(\n `Invalid key: ${key}. Key should be relative to the root path. ` +\n `Root path: ${this.rootPath}, Full path: ${fullPath}`\n );\n }\n\n return fullPath;\n } catch (e) {\n throw new Error(\n `Error getting full path for key: ${key}.\\nError: ${String(e)}`\n );\n }\n }\n\n /**\n * Retrieves the values associated with the given keys from the store.\n * @param keys Keys to retrieve values for.\n * @returns Array of values associated with the given keys.\n */\n async mget(keys: string[]) {\n const values: (Uint8Array | undefined)[] = [];\n for (const key of keys) {\n const fileContent = await this.getParsedFile(key);\n values.push(fileContent);\n }\n return values;\n }\n\n /**\n * Sets the values for the given keys in the store.\n * The last value for duplicate keys will be used.\n * @param keyValuePairs Array of key-value pairs to set in the store.\n * @returns Promise that resolves when all key-value pairs have been set.\n */\n async mset(keyValuePairs: [string, Uint8Array][]): Promise<void> {\n const deduped = new Map<string, Uint8Array>();\n for (const [key, value] of keyValuePairs) {\n deduped.set(key, value);\n }\n\n await Promise.all(\n Array.from(deduped.entries(), ([key, value]) =>\n this.setFileContent(value, key)\n )\n );\n }\n\n /**\n * Deletes the given keys and their associated values from the store.\n * @param keys Keys to delete from the store.\n * @returns Promise that resolves when all keys have been deleted.\n */\n async mdelete(keys: string[]): Promise<void> {\n await Promise.all(\n keys.map((key) =>\n this.withKeyLock(key, async () => {\n try {\n await fs.unlink(this.getFullPath(key));\n } catch (error) {\n // Ignore missing files so deletes remain idempotent.\n if (!error || (error as { code?: string }).code !== \"ENOENT\") {\n throw error;\n }\n }\n })\n )\n );\n }\n\n /**\n * Asynchronous generator that yields keys from the store. If a prefix is\n * provided, it only yields keys that start with the prefix.\n * @param prefix Optional prefix to filter keys.\n * @returns AsyncGenerator that yields keys from the store.\n */\n async *yieldKeys(prefix?: string): AsyncGenerator<string> {\n const allFiles: string[] = await fs.readdir(this.rootPath);\n const allKeys = allFiles\n .filter((file) => file.endsWith(\".txt\"))\n .map((file) => file.replace(/\\.txt$/, \"\"));\n for (const key of allKeys) {\n if (prefix === undefined || key.startsWith(prefix)) {\n yield key;\n }\n }\n }\n\n /**\n * Static method for initializing the class.\n * Preforms a check to see if the directory exists, and if not, creates it.\n * @param path Path to the directory.\n * @returns Promise that resolves to an instance of the class.\n */\n static async fromPath(rootPath: string): Promise<LocalFileStore> {\n try {\n // Verifies the directory exists at the provided path, and that it is readable and writable.\n await fs.access(rootPath, fs.constants.R_OK | fs.constants.W_OK);\n } catch {\n try {\n // Directory does not exist, create it.\n await fs.mkdir(rootPath, { recursive: true });\n } catch (error) {\n throw new Error(\n `An error occurred creating directory at: ${rootPath}.\\nError: ${JSON.stringify(\n error\n )}`\n );\n }\n }\n\n // Clean up orphaned temp files left by interrupted atomic writes.\n try {\n const entries = await fs.readdir(rootPath);\n await Promise.all(\n entries\n .filter((file) => file.endsWith(\".tmp\"))\n .map((tempFile) =>\n fs.unlink(path.join(rootPath, tempFile)).catch(() => {})\n )\n );\n } catch {\n // Ignore cleanup errors.\n }\n\n return new this({ rootPath });\n }\n\n /**\n * Ensures calls for the same key run sequentially by chaining promises.\n * @param key Key to serialize operations for.\n * @param fn Async work to execute while the lock is held.\n * @returns Promise resolving with the callback result once the lock releases.\n */\n private async withKeyLock<T>(key: string, fn: () => Promise<T>): Promise<T> {\n const previous = this.keyLocks.get(key) ?? Promise.resolve();\n const waitForPrevious = previous.catch(() => {});\n\n let resolveCurrent: (() => void) | undefined;\n const current = new Promise<void>((resolve) => {\n resolveCurrent = resolve;\n });\n\n const tail = waitForPrevious.then(() => current);\n this.keyLocks.set(key, tail);\n\n await waitForPrevious;\n try {\n return await fn();\n } finally {\n resolveCurrent?.();\n if (this.keyLocks.get(key) === tail) {\n this.keyLocks.delete(key);\n }\n }\n }\n\n /**\n * Writes data to a temporary file before atomically renaming it into place.\n * @param content Serialized value to persist.\n * @param fullPath Destination path for the stored key.\n */\n private async writeFileAtomically(content: Uint8Array, fullPath: string) {\n const directory = path.dirname(fullPath);\n await fs.mkdir(directory, { recursive: true });\n\n const tempPath = `${fullPath}.${Date.now()}-${Math.random()\n .toString(16)\n .slice(2)}.tmp`;\n\n try {\n await fs.writeFile(tempPath, content);\n\n try {\n await fs.rename(tempPath, fullPath);\n } catch (renameError) {\n const code = (renameError as { code?: string }).code;\n if (renameError && (code === \"EPERM\" || code === \"EACCES\")) {\n // Fallback for Windows where replacing an existing file can fail if the\n // destination is locked by another process.\n await fs.writeFile(fullPath, content);\n await fs.unlink(tempPath).catch(() => {});\n } else {\n throw renameError;\n }\n }\n } catch (error) {\n await fs.unlink(tempPath).catch(() => {});\n throw error;\n }\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,3 @@
1
- require("../_virtual/_rolldown/runtime.cjs");
2
1
  let _langchain_core_tools = require("@langchain/core/tools");
3
2
  //#region src/tools/headless.ts
4
3
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"headless.cjs","names":[],"sources":["../../src/tools/headless.ts"],"sourcesContent":["/**\n * Unified Tool Primitive for LangChain Agents\n *\n * This module re-exports the `tool` primitive from `@langchain/core/tools` with\n * an additional overload: when called without an implementation function, it\n * creates a **headless tool** that interrupts agent execution and delegates the\n * implementation to the client (e.g. via `useStream({ tools: [...] })`).\n *\n * @module\n */\n\nimport {\n tool as coreTool,\n DynamicStructuredTool,\n type ToolRunnableConfig,\n} from \"@langchain/core/tools\";\nimport type {\n InteropZodObject,\n InferInteropZodInput,\n InferInteropZodOutput,\n} from \"@langchain/core/utils/types\";\n\n/**\n * Configuration fields for creating a headless tool.\n */\nexport type HeadlessToolFields<\n SchemaT extends InteropZodObject,\n NameT extends string = string,\n> = {\n /** The name of the tool. Used by the client to match implementations. */\n name: NameT;\n /** Description of what the tool does. */\n description: string;\n /** The Zod schema defining the tool's input. */\n schema: SchemaT;\n};\n\n/**\n * A tool implementation that pairs a headless tool with its execution function.\n *\n * Created by calling `.implement()` on a {@link HeadlessTool}.\n * Pass to `useStream({ tools: [...] })` on the client side.\n */\nexport type HeadlessToolImplementation<\n SchemaT extends InteropZodObject = InteropZodObject,\n OutputT = unknown,\n NameT extends string = string,\n> = {\n tool: HeadlessTool<SchemaT, NameT>;\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>;\n};\n\n/**\n * A headless tool that always interrupts agent execution on the server.\n *\n * The implementation is provided separately on the client via\n * `useStream({ tools: [...] })` using `.implement()`.\n */\nexport type HeadlessTool<\n SchemaT extends InteropZodObject = InteropZodObject,\n NameT extends string = string,\n> = DynamicStructuredTool<\n SchemaT,\n InferInteropZodOutput<SchemaT>,\n InferInteropZodInput<SchemaT>,\n unknown,\n unknown,\n NameT\n> & {\n /**\n * Pairs this headless tool with a client-side implementation.\n *\n * The returned object should be passed to `useStream({ tools: [...] })`.\n * The SDK matches the implementation to the tool by name and calls\n * `execute` with the typed arguments from the interrupt payload.\n *\n * @param execute - The function that implements the tool on the client\n */\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ) => HeadlessToolImplementation<SchemaT, OutputT, NameT>;\n};\n\nfunction createHeadlessTool<\n SchemaT extends InteropZodObject,\n NameT extends string,\n>(fields: HeadlessToolFields<SchemaT, NameT>): HeadlessTool<SchemaT, NameT> {\n const { name, description, schema } = fields;\n\n const wrappedTool = coreTool(\n async (\n args: InferInteropZodOutput<SchemaT>,\n config?: ToolRunnableConfig\n ) => {\n const { interrupt } = await import(\"@langchain/langgraph\");\n return interrupt({\n type: \"tool\",\n toolCall: {\n id: config?.toolCall?.id,\n name,\n args,\n },\n });\n },\n {\n name,\n description,\n schema,\n metadata: {\n headlessTool: true,\n },\n }\n );\n\n const headlessTool: HeadlessTool<SchemaT, NameT> = Object.assign(\n wrappedTool,\n {\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ): HeadlessToolImplementation<SchemaT, OutputT, NameT> => ({\n tool: headlessTool,\n execute,\n }),\n }\n ) as HeadlessTool<SchemaT, NameT>;\n\n return headlessTool;\n}\n\n/**\n * The headless overload signature added to the core `tool` function.\n *\n * When called **without** an implementation function — just `tool({ name, description, schema })` —\n * returns a {@link HeadlessTool} that interrupts on every agent invocation.\n * The client provides the implementation via `useStream({ tools: [...] })`.\n */\ntype HeadlessToolOverload = {\n <SchemaT extends InteropZodObject, NameT extends string>(\n fields: HeadlessToolFields<SchemaT, NameT>\n ): HeadlessTool<SchemaT, NameT>;\n};\n\n/**\n * Unified tool primitive for LangChain agents.\n *\n * Enhances the `tool` function from `@langchain/core/tools` with a headless\n * overload: when called **without** an implementation function, the tool\n * interrupts agent execution and lets the client supply the implementation.\n *\n * ---\n *\n * **Normal tool** — pass an implementation function as the first argument:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * const getWeather = tool(\n * async ({ city }) => `The weather in ${city} is sunny.`,\n * {\n * name: \"get_weather\",\n * description: \"Get the weather for a city\",\n * schema: z.object({ city: z.string() }),\n * }\n * );\n * ```\n *\n * ---\n *\n * **Headless tool** — omit the implementation; the client provides it later:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * // Server: define the tool shape — no implementation needed\n * export const getLocation = tool({\n * name: \"get_location\",\n * description: \"Get the user's current GPS location\",\n * schema: z.object({\n * highAccuracy: z.boolean().optional().describe(\"Request high accuracy GPS\"),\n * }),\n * });\n *\n * // Server: register with the agent\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [getLocation],\n * });\n *\n * // Client: provide the implementation in useStream\n * const stream = useStream({\n * assistantId: \"agent\",\n * tools: [\n * getLocation.implement(async ({ highAccuracy }) => {\n * return new Promise((resolve, reject) => {\n * navigator.geolocation.getCurrentPosition(\n * (pos) => resolve({\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * }),\n * (err) => reject(new Error(err.message)),\n * { enableHighAccuracy: highAccuracy }\n * );\n * });\n * }),\n * ],\n * });\n * ```\n */\nexport const tool: HeadlessToolOverload & typeof coreTool = ((\n funcOrFields: unknown,\n fields?: unknown\n) => {\n if (typeof funcOrFields !== \"function\") {\n return createHeadlessTool(\n funcOrFields as HeadlessToolFields<InteropZodObject, string>\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (coreTool as any)(funcOrFields, fields);\n}) as HeadlessToolOverload & typeof coreTool;\n"],"mappings":";;;;;;;;;;;;;AAmFA,SAAS,mBAGP,QAA0E;CAC1E,MAAM,EAAE,MAAM,aAAa,WAAW;CAEtC,MAAM,eAAA,GAAA,sBAAA,MACJ,OACE,MACA,WACG;EACH,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,SAAO,UAAU;GACf,MAAM;GACN,UAAU;IACR,IAAI,QAAQ,UAAU;IACtB;IACA;IACD;GACF,CAAC;IAEJ;EACE;EACA;EACA;EACA,UAAU,EACR,cAAc,MACf;EACF,CACF;CAED,MAAM,eAA6C,OAAO,OACxD,aACA,EACE,YACE,aACyD;EACzD,MAAM;EACN;EACD,GACF,CACF;AAED,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFT,MAAa,SACX,cACA,WACG;AACH,KAAI,OAAO,iBAAiB,WAC1B,QAAO,mBACL,aACD;AAGH,SAAA,GAAA,sBAAA,MAAyB,cAAc,OAAO"}
1
+ {"version":3,"file":"headless.cjs","names":[],"sources":["../../src/tools/headless.ts"],"sourcesContent":["/**\n * Unified Tool Primitive for LangChain Agents\n *\n * This module re-exports the `tool` primitive from `@langchain/core/tools` with\n * an additional overload: when called without an implementation function, it\n * creates a **headless tool** that interrupts agent execution and delegates the\n * implementation to the client (e.g. via `useStream({ tools: [...] })`).\n *\n * @module\n */\n\nimport {\n tool as coreTool,\n DynamicStructuredTool,\n type ToolRunnableConfig,\n} from \"@langchain/core/tools\";\nimport type {\n InteropZodObject,\n InferInteropZodInput,\n InferInteropZodOutput,\n} from \"@langchain/core/utils/types\";\n\n/**\n * Configuration fields for creating a headless tool.\n */\nexport type HeadlessToolFields<\n SchemaT extends InteropZodObject,\n NameT extends string = string,\n> = {\n /** The name of the tool. Used by the client to match implementations. */\n name: NameT;\n /** Description of what the tool does. */\n description: string;\n /** The Zod schema defining the tool's input. */\n schema: SchemaT;\n};\n\n/**\n * A tool implementation that pairs a headless tool with its execution function.\n *\n * Created by calling `.implement()` on a {@link HeadlessTool}.\n * Pass to `useStream({ tools: [...] })` on the client side.\n */\nexport type HeadlessToolImplementation<\n SchemaT extends InteropZodObject = InteropZodObject,\n OutputT = unknown,\n NameT extends string = string,\n> = {\n tool: HeadlessTool<SchemaT, NameT>;\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>;\n};\n\n/**\n * A headless tool that always interrupts agent execution on the server.\n *\n * The implementation is provided separately on the client via\n * `useStream({ tools: [...] })` using `.implement()`.\n */\nexport type HeadlessTool<\n SchemaT extends InteropZodObject = InteropZodObject,\n NameT extends string = string,\n> = DynamicStructuredTool<\n SchemaT,\n InferInteropZodOutput<SchemaT>,\n InferInteropZodInput<SchemaT>,\n unknown,\n unknown,\n NameT\n> & {\n /**\n * Pairs this headless tool with a client-side implementation.\n *\n * The returned object should be passed to `useStream({ tools: [...] })`.\n * The SDK matches the implementation to the tool by name and calls\n * `execute` with the typed arguments from the interrupt payload.\n *\n * @param execute - The function that implements the tool on the client\n */\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ) => HeadlessToolImplementation<SchemaT, OutputT, NameT>;\n};\n\nfunction createHeadlessTool<\n SchemaT extends InteropZodObject,\n NameT extends string,\n>(fields: HeadlessToolFields<SchemaT, NameT>): HeadlessTool<SchemaT, NameT> {\n const { name, description, schema } = fields;\n\n const wrappedTool = coreTool(\n async (\n args: InferInteropZodOutput<SchemaT>,\n config?: ToolRunnableConfig\n ) => {\n const { interrupt } = await import(\"@langchain/langgraph\");\n return interrupt({\n type: \"tool\",\n toolCall: {\n id: config?.toolCall?.id,\n name,\n args,\n },\n });\n },\n {\n name,\n description,\n schema,\n metadata: {\n headlessTool: true,\n },\n }\n );\n\n const headlessTool: HeadlessTool<SchemaT, NameT> = Object.assign(\n wrappedTool,\n {\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ): HeadlessToolImplementation<SchemaT, OutputT, NameT> => ({\n tool: headlessTool,\n execute,\n }),\n }\n ) as HeadlessTool<SchemaT, NameT>;\n\n return headlessTool;\n}\n\n/**\n * The headless overload signature added to the core `tool` function.\n *\n * When called **without** an implementation function — just `tool({ name, description, schema })` —\n * returns a {@link HeadlessTool} that interrupts on every agent invocation.\n * The client provides the implementation via `useStream({ tools: [...] })`.\n */\ntype HeadlessToolOverload = {\n <SchemaT extends InteropZodObject, NameT extends string>(\n fields: HeadlessToolFields<SchemaT, NameT>\n ): HeadlessTool<SchemaT, NameT>;\n};\n\n/**\n * Unified tool primitive for LangChain agents.\n *\n * Enhances the `tool` function from `@langchain/core/tools` with a headless\n * overload: when called **without** an implementation function, the tool\n * interrupts agent execution and lets the client supply the implementation.\n *\n * ---\n *\n * **Normal tool** — pass an implementation function as the first argument:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * const getWeather = tool(\n * async ({ city }) => `The weather in ${city} is sunny.`,\n * {\n * name: \"get_weather\",\n * description: \"Get the weather for a city\",\n * schema: z.object({ city: z.string() }),\n * }\n * );\n * ```\n *\n * ---\n *\n * **Headless tool** — omit the implementation; the client provides it later:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * // Server: define the tool shape — no implementation needed\n * export const getLocation = tool({\n * name: \"get_location\",\n * description: \"Get the user's current GPS location\",\n * schema: z.object({\n * highAccuracy: z.boolean().optional().describe(\"Request high accuracy GPS\"),\n * }),\n * });\n *\n * // Server: register with the agent\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [getLocation],\n * });\n *\n * // Client: provide the implementation in useStream\n * const stream = useStream({\n * assistantId: \"agent\",\n * tools: [\n * getLocation.implement(async ({ highAccuracy }) => {\n * return new Promise((resolve, reject) => {\n * navigator.geolocation.getCurrentPosition(\n * (pos) => resolve({\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * }),\n * (err) => reject(new Error(err.message)),\n * { enableHighAccuracy: highAccuracy }\n * );\n * });\n * }),\n * ],\n * });\n * ```\n */\nexport const tool: HeadlessToolOverload & typeof coreTool = ((\n funcOrFields: unknown,\n fields?: unknown\n) => {\n if (typeof funcOrFields !== \"function\") {\n return createHeadlessTool(\n funcOrFields as HeadlessToolFields<InteropZodObject, string>\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (coreTool as any)(funcOrFields, fields);\n}) as HeadlessToolOverload & typeof coreTool;\n"],"mappings":";;;;;;;;;;;;AAmFA,SAAS,mBAGP,QAA0E;CAC1E,MAAM,EAAE,MAAM,aAAa,WAAW;CAEtC,MAAM,eAAA,GAAA,sBAAA,KAAA,CACJ,OACE,MACA,WACG;EACH,MAAM,EAAE,cAAc,MAAM,OAAO;EACnC,OAAO,UAAU;GACf,MAAM;GACN,UAAU;IACR,IAAI,QAAQ,UAAU;IACtB;IACA;GACF;EACF,CAAC;CACH,GACA;EACE;EACA;EACA;EACA,UAAU,EACR,cAAc,KAChB;CACF,CACF;CAEA,MAAM,eAA6C,OAAO,OACxD,aACA,EACE,YACE,aACyD;EACzD,MAAM;EACN;CACF,GACF,CACF;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,MAAa,SACX,cACA,WACG;CACH,IAAI,OAAO,iBAAiB,YAC1B,OAAO,mBACL,YACF;CAGF,QAAA,GAAA,sBAAA,KAAA,CAAyB,cAAc,MAAM;AAC/C"}
@@ -1,13 +1,15 @@
1
1
  import { DynamicStructuredTool, tool } from "@langchain/core/tools";
2
2
  import { InferInteropZodInput, InferInteropZodOutput, InteropZodObject } from "@langchain/core/utils/types";
3
-
4
3
  //#region src/tools/headless.d.ts
5
4
  /**
6
5
  * Configuration fields for creating a headless tool.
7
6
  */
8
7
  type HeadlessToolFields<SchemaT extends InteropZodObject, NameT extends string = string> = {
9
- /** The name of the tool. Used by the client to match implementations. */name: NameT; /** Description of what the tool does. */
10
- description: string; /** The Zod schema defining the tool's input. */
8
+ /** The name of the tool. Used by the client to match implementations. */
9
+ name: NameT;
10
+ /** Description of what the tool does. */
11
+ description: string;
12
+ /** The Zod schema defining the tool's input. */
11
13
  schema: SchemaT;
12
14
  };
13
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"headless.d.cts","names":[],"sources":["../../src/tools/headless.ts"],"mappings":";;;;;;;KAyBY,kBAAA,iBACM,gBAAA;EAIV,yEAAN,IAAA,EAAM,KAAA,EAIN;EAFA,WAAA,UAEe;EAAf,MAAA,EAAQ,OAAA;AAAA;;;;;;;KASE,0BAAA,iBACM,gBAAA,GAAmB,gBAAA;EAInC,IAAA,EAAM,YAAA,CAAa,OAAA,EAAS,KAAA;EAC5B,OAAA,GAAU,IAAA,EAAM,qBAAA,CAAsB,OAAA,MAAa,OAAA,CAAQ,OAAA;AAAA;;;;;;;KASjD,YAAA,iBACM,gBAAA,GAAmB,gBAAA,mCAEjC,qBAAA,CACF,OAAA,EACA,qBAAA,CAAsB,OAAA,GACtB,oBAAA,CAAqB,OAAA,qBAGrB,KAAA;EArBA;;;;;;;;;EAgCA,SAAA,YACE,OAAA,GAAU,IAAA,EAAM,qBAAA,CAAsB,OAAA,MAAa,OAAA,CAAQ,OAAA,MACxD,0BAAA,CAA2B,OAAA,EAAS,OAAA,EAAS,KAAA;AAAA;;;AAtBpD;;;;;KA8EK,oBAAA;EAAA,iBACc,gBAAA,wBACf,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,KAAA,IACnC,YAAA,CAAa,OAAA,EAAS,KAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA1DzB;;;;;;;;;;;;;;;;;;;;;;;;AAiIF;;;;;cAAa,MAAA,EAAM,oBAAA,UAA8B,IAAA"}
1
+ {"version":3,"file":"headless.d.cts","names":[],"sources":["../../src/tools/headless.ts"],"mappings":";;;;;;KAyBY,mBACV,gBAAgB,kBAChB;;EAGA,MAAM;;EAEN;;EAEA,QAAQ;;;;;;;;KASE,2BACV,gBAAgB,mBAAmB,kBACnC,mBACA;EAEA,MAAM,aAAa,SAAS;EAC5B,UAAU,MAAM,sBAAsB,aAAa,QAAQ;;;;;;;;KASjD,aACV,gBAAgB,mBAAmB,kBACnC,iCACE,sBACF,SACA,sBAAsB,UACtB,qBAAqB,4BAGrB;;;;;;;;;;EAWA,YAAY,SACV,UAAU,MAAM,sBAAsB,aAAa,QAAQ,aACxD,2BAA2B,SAAS,SAAS;;;;;;;;;KAwD/C;GACF,gBAAgB,kBAAkB,sBACjC,QAAQ,mBAAmB,SAAS,SACnC,aAAa,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuEd,QAAM,8BAA8B"}
@@ -1,13 +1,15 @@
1
1
  import { DynamicStructuredTool, tool } from "@langchain/core/tools";
2
2
  import { InferInteropZodInput, InferInteropZodOutput, InteropZodObject } from "@langchain/core/utils/types";
3
-
4
3
  //#region src/tools/headless.d.ts
5
4
  /**
6
5
  * Configuration fields for creating a headless tool.
7
6
  */
8
7
  type HeadlessToolFields<SchemaT extends InteropZodObject, NameT extends string = string> = {
9
- /** The name of the tool. Used by the client to match implementations. */name: NameT; /** Description of what the tool does. */
10
- description: string; /** The Zod schema defining the tool's input. */
8
+ /** The name of the tool. Used by the client to match implementations. */
9
+ name: NameT;
10
+ /** Description of what the tool does. */
11
+ description: string;
12
+ /** The Zod schema defining the tool's input. */
11
13
  schema: SchemaT;
12
14
  };
13
15
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"headless.d.ts","names":[],"sources":["../../src/tools/headless.ts"],"mappings":";;;;;;;KAyBY,kBAAA,iBACM,gBAAA;EAIV,yEAAN,IAAA,EAAM,KAAA,EAIN;EAFA,WAAA,UAEe;EAAf,MAAA,EAAQ,OAAA;AAAA;;;;;;;KASE,0BAAA,iBACM,gBAAA,GAAmB,gBAAA;EAInC,IAAA,EAAM,YAAA,CAAa,OAAA,EAAS,KAAA;EAC5B,OAAA,GAAU,IAAA,EAAM,qBAAA,CAAsB,OAAA,MAAa,OAAA,CAAQ,OAAA;AAAA;;;;;;;KASjD,YAAA,iBACM,gBAAA,GAAmB,gBAAA,mCAEjC,qBAAA,CACF,OAAA,EACA,qBAAA,CAAsB,OAAA,GACtB,oBAAA,CAAqB,OAAA,qBAGrB,KAAA;EArBA;;;;;;;;;EAgCA,SAAA,YACE,OAAA,GAAU,IAAA,EAAM,qBAAA,CAAsB,OAAA,MAAa,OAAA,CAAQ,OAAA,MACxD,0BAAA,CAA2B,OAAA,EAAS,OAAA,EAAS,KAAA;AAAA;;;AAtBpD;;;;;KA8EK,oBAAA;EAAA,iBACc,gBAAA,wBACf,MAAA,EAAQ,kBAAA,CAAmB,OAAA,EAAS,KAAA,IACnC,YAAA,CAAa,OAAA,EAAS,KAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA1DzB;;;;;;;;;;;;;;;;;;;;;;;;AAiIF;;;;;cAAa,MAAA,EAAM,oBAAA,UAA8B,IAAA"}
1
+ {"version":3,"file":"headless.d.ts","names":[],"sources":["../../src/tools/headless.ts"],"mappings":";;;;;;KAyBY,mBACV,gBAAgB,kBAChB;;EAGA,MAAM;;EAEN;;EAEA,QAAQ;;;;;;;;KASE,2BACV,gBAAgB,mBAAmB,kBACnC,mBACA;EAEA,MAAM,aAAa,SAAS;EAC5B,UAAU,MAAM,sBAAsB,aAAa,QAAQ;;;;;;;;KASjD,aACV,gBAAgB,mBAAmB,kBACnC,iCACE,sBACF,SACA,sBAAsB,UACtB,qBAAqB,4BAGrB;;;;;;;;;;EAWA,YAAY,SACV,UAAU,MAAM,sBAAsB,aAAa,QAAQ,aACxD,2BAA2B,SAAS,SAAS;;;;;;;;;KAwD/C;GACF,gBAAgB,kBAAkB,sBACjC,QAAQ,mBAAmB,SAAS,SACnC,aAAa,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuEd,QAAM,8BAA8B"}
@@ -1 +1 @@
1
- {"version":3,"file":"headless.js","names":["coreTool","tool"],"sources":["../../src/tools/headless.ts"],"sourcesContent":["/**\n * Unified Tool Primitive for LangChain Agents\n *\n * This module re-exports the `tool` primitive from `@langchain/core/tools` with\n * an additional overload: when called without an implementation function, it\n * creates a **headless tool** that interrupts agent execution and delegates the\n * implementation to the client (e.g. via `useStream({ tools: [...] })`).\n *\n * @module\n */\n\nimport {\n tool as coreTool,\n DynamicStructuredTool,\n type ToolRunnableConfig,\n} from \"@langchain/core/tools\";\nimport type {\n InteropZodObject,\n InferInteropZodInput,\n InferInteropZodOutput,\n} from \"@langchain/core/utils/types\";\n\n/**\n * Configuration fields for creating a headless tool.\n */\nexport type HeadlessToolFields<\n SchemaT extends InteropZodObject,\n NameT extends string = string,\n> = {\n /** The name of the tool. Used by the client to match implementations. */\n name: NameT;\n /** Description of what the tool does. */\n description: string;\n /** The Zod schema defining the tool's input. */\n schema: SchemaT;\n};\n\n/**\n * A tool implementation that pairs a headless tool with its execution function.\n *\n * Created by calling `.implement()` on a {@link HeadlessTool}.\n * Pass to `useStream({ tools: [...] })` on the client side.\n */\nexport type HeadlessToolImplementation<\n SchemaT extends InteropZodObject = InteropZodObject,\n OutputT = unknown,\n NameT extends string = string,\n> = {\n tool: HeadlessTool<SchemaT, NameT>;\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>;\n};\n\n/**\n * A headless tool that always interrupts agent execution on the server.\n *\n * The implementation is provided separately on the client via\n * `useStream({ tools: [...] })` using `.implement()`.\n */\nexport type HeadlessTool<\n SchemaT extends InteropZodObject = InteropZodObject,\n NameT extends string = string,\n> = DynamicStructuredTool<\n SchemaT,\n InferInteropZodOutput<SchemaT>,\n InferInteropZodInput<SchemaT>,\n unknown,\n unknown,\n NameT\n> & {\n /**\n * Pairs this headless tool with a client-side implementation.\n *\n * The returned object should be passed to `useStream({ tools: [...] })`.\n * The SDK matches the implementation to the tool by name and calls\n * `execute` with the typed arguments from the interrupt payload.\n *\n * @param execute - The function that implements the tool on the client\n */\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ) => HeadlessToolImplementation<SchemaT, OutputT, NameT>;\n};\n\nfunction createHeadlessTool<\n SchemaT extends InteropZodObject,\n NameT extends string,\n>(fields: HeadlessToolFields<SchemaT, NameT>): HeadlessTool<SchemaT, NameT> {\n const { name, description, schema } = fields;\n\n const wrappedTool = coreTool(\n async (\n args: InferInteropZodOutput<SchemaT>,\n config?: ToolRunnableConfig\n ) => {\n const { interrupt } = await import(\"@langchain/langgraph\");\n return interrupt({\n type: \"tool\",\n toolCall: {\n id: config?.toolCall?.id,\n name,\n args,\n },\n });\n },\n {\n name,\n description,\n schema,\n metadata: {\n headlessTool: true,\n },\n }\n );\n\n const headlessTool: HeadlessTool<SchemaT, NameT> = Object.assign(\n wrappedTool,\n {\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ): HeadlessToolImplementation<SchemaT, OutputT, NameT> => ({\n tool: headlessTool,\n execute,\n }),\n }\n ) as HeadlessTool<SchemaT, NameT>;\n\n return headlessTool;\n}\n\n/**\n * The headless overload signature added to the core `tool` function.\n *\n * When called **without** an implementation function — just `tool({ name, description, schema })` —\n * returns a {@link HeadlessTool} that interrupts on every agent invocation.\n * The client provides the implementation via `useStream({ tools: [...] })`.\n */\ntype HeadlessToolOverload = {\n <SchemaT extends InteropZodObject, NameT extends string>(\n fields: HeadlessToolFields<SchemaT, NameT>\n ): HeadlessTool<SchemaT, NameT>;\n};\n\n/**\n * Unified tool primitive for LangChain agents.\n *\n * Enhances the `tool` function from `@langchain/core/tools` with a headless\n * overload: when called **without** an implementation function, the tool\n * interrupts agent execution and lets the client supply the implementation.\n *\n * ---\n *\n * **Normal tool** — pass an implementation function as the first argument:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * const getWeather = tool(\n * async ({ city }) => `The weather in ${city} is sunny.`,\n * {\n * name: \"get_weather\",\n * description: \"Get the weather for a city\",\n * schema: z.object({ city: z.string() }),\n * }\n * );\n * ```\n *\n * ---\n *\n * **Headless tool** — omit the implementation; the client provides it later:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * // Server: define the tool shape — no implementation needed\n * export const getLocation = tool({\n * name: \"get_location\",\n * description: \"Get the user's current GPS location\",\n * schema: z.object({\n * highAccuracy: z.boolean().optional().describe(\"Request high accuracy GPS\"),\n * }),\n * });\n *\n * // Server: register with the agent\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [getLocation],\n * });\n *\n * // Client: provide the implementation in useStream\n * const stream = useStream({\n * assistantId: \"agent\",\n * tools: [\n * getLocation.implement(async ({ highAccuracy }) => {\n * return new Promise((resolve, reject) => {\n * navigator.geolocation.getCurrentPosition(\n * (pos) => resolve({\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * }),\n * (err) => reject(new Error(err.message)),\n * { enableHighAccuracy: highAccuracy }\n * );\n * });\n * }),\n * ],\n * });\n * ```\n */\nexport const tool: HeadlessToolOverload & typeof coreTool = ((\n funcOrFields: unknown,\n fields?: unknown\n) => {\n if (typeof funcOrFields !== \"function\") {\n return createHeadlessTool(\n funcOrFields as HeadlessToolFields<InteropZodObject, string>\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (coreTool as any)(funcOrFields, fields);\n}) as HeadlessToolOverload & typeof coreTool;\n"],"mappings":";;;;;;;;;;;;AAmFA,SAAS,mBAGP,QAA0E;CAC1E,MAAM,EAAE,MAAM,aAAa,WAAW;CAEtC,MAAM,cAAcA,KAClB,OACE,MACA,WACG;EACH,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,SAAO,UAAU;GACf,MAAM;GACN,UAAU;IACR,IAAI,QAAQ,UAAU;IACtB;IACA;IACD;GACF,CAAC;IAEJ;EACE;EACA;EACA;EACA,UAAU,EACR,cAAc,MACf;EACF,CACF;CAED,MAAM,eAA6C,OAAO,OACxD,aACA,EACE,YACE,aACyD;EACzD,MAAM;EACN;EACD,GACF,CACF;AAED,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFT,MAAaC,WACX,cACA,WACG;AACH,KAAI,OAAO,iBAAiB,WAC1B,QAAO,mBACL,aACD;AAGH,QAAQD,KAAiB,cAAc,OAAO"}
1
+ {"version":3,"file":"headless.js","names":["coreTool","tool"],"sources":["../../src/tools/headless.ts"],"sourcesContent":["/**\n * Unified Tool Primitive for LangChain Agents\n *\n * This module re-exports the `tool` primitive from `@langchain/core/tools` with\n * an additional overload: when called without an implementation function, it\n * creates a **headless tool** that interrupts agent execution and delegates the\n * implementation to the client (e.g. via `useStream({ tools: [...] })`).\n *\n * @module\n */\n\nimport {\n tool as coreTool,\n DynamicStructuredTool,\n type ToolRunnableConfig,\n} from \"@langchain/core/tools\";\nimport type {\n InteropZodObject,\n InferInteropZodInput,\n InferInteropZodOutput,\n} from \"@langchain/core/utils/types\";\n\n/**\n * Configuration fields for creating a headless tool.\n */\nexport type HeadlessToolFields<\n SchemaT extends InteropZodObject,\n NameT extends string = string,\n> = {\n /** The name of the tool. Used by the client to match implementations. */\n name: NameT;\n /** Description of what the tool does. */\n description: string;\n /** The Zod schema defining the tool's input. */\n schema: SchemaT;\n};\n\n/**\n * A tool implementation that pairs a headless tool with its execution function.\n *\n * Created by calling `.implement()` on a {@link HeadlessTool}.\n * Pass to `useStream({ tools: [...] })` on the client side.\n */\nexport type HeadlessToolImplementation<\n SchemaT extends InteropZodObject = InteropZodObject,\n OutputT = unknown,\n NameT extends string = string,\n> = {\n tool: HeadlessTool<SchemaT, NameT>;\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>;\n};\n\n/**\n * A headless tool that always interrupts agent execution on the server.\n *\n * The implementation is provided separately on the client via\n * `useStream({ tools: [...] })` using `.implement()`.\n */\nexport type HeadlessTool<\n SchemaT extends InteropZodObject = InteropZodObject,\n NameT extends string = string,\n> = DynamicStructuredTool<\n SchemaT,\n InferInteropZodOutput<SchemaT>,\n InferInteropZodInput<SchemaT>,\n unknown,\n unknown,\n NameT\n> & {\n /**\n * Pairs this headless tool with a client-side implementation.\n *\n * The returned object should be passed to `useStream({ tools: [...] })`.\n * The SDK matches the implementation to the tool by name and calls\n * `execute` with the typed arguments from the interrupt payload.\n *\n * @param execute - The function that implements the tool on the client\n */\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ) => HeadlessToolImplementation<SchemaT, OutputT, NameT>;\n};\n\nfunction createHeadlessTool<\n SchemaT extends InteropZodObject,\n NameT extends string,\n>(fields: HeadlessToolFields<SchemaT, NameT>): HeadlessTool<SchemaT, NameT> {\n const { name, description, schema } = fields;\n\n const wrappedTool = coreTool(\n async (\n args: InferInteropZodOutput<SchemaT>,\n config?: ToolRunnableConfig\n ) => {\n const { interrupt } = await import(\"@langchain/langgraph\");\n return interrupt({\n type: \"tool\",\n toolCall: {\n id: config?.toolCall?.id,\n name,\n args,\n },\n });\n },\n {\n name,\n description,\n schema,\n metadata: {\n headlessTool: true,\n },\n }\n );\n\n const headlessTool: HeadlessTool<SchemaT, NameT> = Object.assign(\n wrappedTool,\n {\n implement: <OutputT>(\n execute: (args: InferInteropZodOutput<SchemaT>) => Promise<OutputT>\n ): HeadlessToolImplementation<SchemaT, OutputT, NameT> => ({\n tool: headlessTool,\n execute,\n }),\n }\n ) as HeadlessTool<SchemaT, NameT>;\n\n return headlessTool;\n}\n\n/**\n * The headless overload signature added to the core `tool` function.\n *\n * When called **without** an implementation function — just `tool({ name, description, schema })` —\n * returns a {@link HeadlessTool} that interrupts on every agent invocation.\n * The client provides the implementation via `useStream({ tools: [...] })`.\n */\ntype HeadlessToolOverload = {\n <SchemaT extends InteropZodObject, NameT extends string>(\n fields: HeadlessToolFields<SchemaT, NameT>\n ): HeadlessTool<SchemaT, NameT>;\n};\n\n/**\n * Unified tool primitive for LangChain agents.\n *\n * Enhances the `tool` function from `@langchain/core/tools` with a headless\n * overload: when called **without** an implementation function, the tool\n * interrupts agent execution and lets the client supply the implementation.\n *\n * ---\n *\n * **Normal tool** — pass an implementation function as the first argument:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * const getWeather = tool(\n * async ({ city }) => `The weather in ${city} is sunny.`,\n * {\n * name: \"get_weather\",\n * description: \"Get the weather for a city\",\n * schema: z.object({ city: z.string() }),\n * }\n * );\n * ```\n *\n * ---\n *\n * **Headless tool** — omit the implementation; the client provides it later:\n *\n * ```typescript\n * import { tool } from \"langchain/tools\";\n * import { z } from \"zod\";\n *\n * // Server: define the tool shape — no implementation needed\n * export const getLocation = tool({\n * name: \"get_location\",\n * description: \"Get the user's current GPS location\",\n * schema: z.object({\n * highAccuracy: z.boolean().optional().describe(\"Request high accuracy GPS\"),\n * }),\n * });\n *\n * // Server: register with the agent\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [getLocation],\n * });\n *\n * // Client: provide the implementation in useStream\n * const stream = useStream({\n * assistantId: \"agent\",\n * tools: [\n * getLocation.implement(async ({ highAccuracy }) => {\n * return new Promise((resolve, reject) => {\n * navigator.geolocation.getCurrentPosition(\n * (pos) => resolve({\n * latitude: pos.coords.latitude,\n * longitude: pos.coords.longitude,\n * }),\n * (err) => reject(new Error(err.message)),\n * { enableHighAccuracy: highAccuracy }\n * );\n * });\n * }),\n * ],\n * });\n * ```\n */\nexport const tool: HeadlessToolOverload & typeof coreTool = ((\n funcOrFields: unknown,\n fields?: unknown\n) => {\n if (typeof funcOrFields !== \"function\") {\n return createHeadlessTool(\n funcOrFields as HeadlessToolFields<InteropZodObject, string>\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (coreTool as any)(funcOrFields, fields);\n}) as HeadlessToolOverload & typeof coreTool;\n"],"mappings":";;;;;;;;;;;;AAmFA,SAAS,mBAGP,QAA0E;CAC1E,MAAM,EAAE,MAAM,aAAa,WAAW;CAEtC,MAAM,cAAcA,KAClB,OACE,MACA,WACG;EACH,MAAM,EAAE,cAAc,MAAM,OAAO;EACnC,OAAO,UAAU;GACf,MAAM;GACN,UAAU;IACR,IAAI,QAAQ,UAAU;IACtB;IACA;GACF;EACF,CAAC;CACH,GACA;EACE;EACA;EACA;EACA,UAAU,EACR,cAAc,KAChB;CACF,CACF;CAEA,MAAM,eAA6C,OAAO,OACxD,aACA,EACE,YACE,aACyD;EACzD,MAAM;EACN;CACF,GACF,CACF;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,MAAaC,WACX,cACA,WACG;CACH,IAAI,OAAO,iBAAiB,YAC1B,OAAO,mBACL,YACF;CAGF,OAAQD,KAAiB,cAAc,MAAM;AAC/C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langchain",
3
- "version": "1.5.4",
3
+ "version": "1.5.6",
4
4
  "description": "Typescript bindings for langchain",
5
5
  "author": "LangChain",
6
6
  "license": "MIT",
@@ -32,39 +32,39 @@
32
32
  },
33
33
  "homepage": "https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain/",
34
34
  "devDependencies": {
35
- "@hono/node-server": "^2.0.10",
36
- "@langchain/langgraph-api": "^1.4.1",
37
- "@langchain/langgraph-sdk": "^1.9.25",
35
+ "@hono/node-server": "^2.0.12",
36
+ "@langchain/langgraph-api": "^1.4.3",
37
+ "@langchain/langgraph-sdk": "^1.9.28",
38
38
  "@tsconfig/recommended": "^1.0.2",
39
39
  "@types/js-yaml": "^4",
40
40
  "@types/jsdom": "^28.0.3",
41
41
  "@types/ws": "^8",
42
- "@vitest/coverage-v8": "^4.1.9",
42
+ "@vitest/coverage-v8": "^4.1.10",
43
43
  "cheerio": "1.2.0",
44
44
  "dotenv": "^17.4.0",
45
45
  "dpdm": "^3.14.0",
46
- "hono": "^4.12.25",
46
+ "hono": "^4.12.33",
47
47
  "openai": "^6.41.0",
48
48
  "peggy": "^5.1.0",
49
49
  "reflect-metadata": "^0.2.2",
50
50
  "rimraf": "^6.1.3",
51
- "tinybench": "^6.0.2",
51
+ "tinybench": "^6.1.2",
52
52
  "typeorm": "^1.1.0",
53
- "typescript": "~6.0.3",
53
+ "typescript": "~7.0.2",
54
54
  "vitest": "^4.1.8",
55
55
  "yaml": "^2.9.0",
56
- "@langchain/anthropic": "1.5.2",
56
+ "@langchain/anthropic": "1.5.4",
57
57
  "@langchain/aws": "1.4.3",
58
- "@langchain/core": "^1.2.3",
59
- "@langchain/fireworks": "0.2.5",
60
- "@langchain/openai": "1.5.5",
58
+ "@langchain/core": "^1.2.6",
59
+ "@langchain/fireworks": "0.2.7",
60
+ "@langchain/openai": "1.5.7",
61
61
  "@langchain/tsconfig": "0.0.1"
62
62
  },
63
63
  "peerDependencies": {
64
- "@langchain/core": "^1.2.3"
64
+ "@langchain/core": "^1.2.6"
65
65
  },
66
66
  "dependencies": {
67
- "@langchain/langgraph": "^1.4.7",
67
+ "@langchain/langgraph": "^1.4.8",
68
68
  "@langchain/langgraph-checkpoint": "^1.1.3",
69
69
  "langsmith": ">=0.5.0 <1.0.0",
70
70
  "zod": "^3.25.76 || ^4"