langchain 1.2.24 → 1.2.25

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 (325) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/_virtual/{rolldown_runtime.cjs → _rolldown/runtime.cjs} +24 -13
  3. package/dist/_virtual/_rolldown/runtime.js +36 -0
  4. package/dist/agents/ReactAgent.cjs +52 -65
  5. package/dist/agents/ReactAgent.cjs.map +1 -1
  6. package/dist/agents/ReactAgent.d.cts.map +1 -1
  7. package/dist/agents/ReactAgent.d.ts.map +1 -1
  8. package/dist/agents/ReactAgent.js +11 -24
  9. package/dist/agents/ReactAgent.js.map +1 -1
  10. package/dist/agents/RunnableCallable.cjs +7 -7
  11. package/dist/agents/RunnableCallable.cjs.map +1 -1
  12. package/dist/agents/RunnableCallable.js.map +1 -1
  13. package/dist/agents/annotation.cjs +41 -37
  14. package/dist/agents/annotation.cjs.map +1 -1
  15. package/dist/agents/annotation.js +21 -17
  16. package/dist/agents/annotation.js.map +1 -1
  17. package/dist/agents/constants.d.cts.map +1 -1
  18. package/dist/agents/constants.d.ts.map +1 -1
  19. package/dist/agents/errors.cjs +3 -3
  20. package/dist/agents/errors.cjs.map +1 -1
  21. package/dist/agents/errors.d.cts.map +1 -1
  22. package/dist/agents/errors.d.ts.map +1 -1
  23. package/dist/agents/errors.js.map +1 -1
  24. package/dist/agents/index.cjs.map +1 -1
  25. package/dist/agents/index.d.cts +2 -2
  26. package/dist/agents/index.d.cts.map +1 -1
  27. package/dist/agents/index.d.ts +2 -2
  28. package/dist/agents/index.d.ts.map +1 -1
  29. package/dist/agents/index.js.map +1 -1
  30. package/dist/agents/middleware/constants.cjs +2 -2
  31. package/dist/agents/middleware/constants.cjs.map +1 -1
  32. package/dist/agents/middleware/constants.js.map +1 -1
  33. package/dist/agents/middleware/contextEditing.cjs +14 -27
  34. package/dist/agents/middleware/contextEditing.cjs.map +1 -1
  35. package/dist/agents/middleware/contextEditing.d.cts +2 -3
  36. package/dist/agents/middleware/contextEditing.d.cts.map +1 -1
  37. package/dist/agents/middleware/contextEditing.d.ts +2 -3
  38. package/dist/agents/middleware/contextEditing.d.ts.map +1 -1
  39. package/dist/agents/middleware/contextEditing.js +5 -18
  40. package/dist/agents/middleware/contextEditing.js.map +1 -1
  41. package/dist/agents/middleware/dynamicSystemPrompt.cjs +3 -4
  42. package/dist/agents/middleware/dynamicSystemPrompt.cjs.map +1 -1
  43. package/dist/agents/middleware/dynamicSystemPrompt.d.cts +2 -2
  44. package/dist/agents/middleware/dynamicSystemPrompt.d.cts.map +1 -1
  45. package/dist/agents/middleware/dynamicSystemPrompt.d.ts +2 -2
  46. package/dist/agents/middleware/dynamicSystemPrompt.d.ts.map +1 -1
  47. package/dist/agents/middleware/dynamicSystemPrompt.js +1 -2
  48. package/dist/agents/middleware/dynamicSystemPrompt.js.map +1 -1
  49. package/dist/agents/middleware/error.cjs +2 -2
  50. package/dist/agents/middleware/error.cjs.map +1 -1
  51. package/dist/agents/middleware/error.js.map +1 -1
  52. package/dist/agents/middleware/hitl.cjs +16 -26
  53. package/dist/agents/middleware/hitl.cjs.map +1 -1
  54. package/dist/agents/middleware/hitl.d.cts.map +1 -1
  55. package/dist/agents/middleware/hitl.d.ts.map +1 -1
  56. package/dist/agents/middleware/hitl.js +8 -18
  57. package/dist/agents/middleware/hitl.js.map +1 -1
  58. package/dist/agents/middleware/index.js +2 -0
  59. package/dist/agents/middleware/llmToolSelector.cjs +9 -10
  60. package/dist/agents/middleware/llmToolSelector.cjs.map +1 -1
  61. package/dist/agents/middleware/llmToolSelector.d.cts +4 -4
  62. package/dist/agents/middleware/llmToolSelector.d.cts.map +1 -1
  63. package/dist/agents/middleware/llmToolSelector.d.ts +4 -4
  64. package/dist/agents/middleware/llmToolSelector.d.ts.map +1 -1
  65. package/dist/agents/middleware/llmToolSelector.js +3 -4
  66. package/dist/agents/middleware/llmToolSelector.js.map +1 -1
  67. package/dist/agents/middleware/modelCallLimit.cjs +5 -5
  68. package/dist/agents/middleware/modelCallLimit.cjs.map +1 -1
  69. package/dist/agents/middleware/modelCallLimit.d.cts +2 -2
  70. package/dist/agents/middleware/modelCallLimit.d.cts.map +1 -1
  71. package/dist/agents/middleware/modelCallLimit.d.ts +2 -2
  72. package/dist/agents/middleware/modelCallLimit.d.ts.map +1 -1
  73. package/dist/agents/middleware/modelCallLimit.js.map +1 -1
  74. package/dist/agents/middleware/modelFallback.cjs.map +1 -1
  75. package/dist/agents/middleware/modelFallback.d.cts +0 -1
  76. package/dist/agents/middleware/modelFallback.d.cts.map +1 -1
  77. package/dist/agents/middleware/modelFallback.d.ts +0 -1
  78. package/dist/agents/middleware/modelFallback.d.ts.map +1 -1
  79. package/dist/agents/middleware/modelFallback.js.map +1 -1
  80. package/dist/agents/middleware/modelRetry.cjs +19 -17
  81. package/dist/agents/middleware/modelRetry.cjs.map +1 -1
  82. package/dist/agents/middleware/modelRetry.d.cts +0 -1
  83. package/dist/agents/middleware/modelRetry.d.cts.map +1 -1
  84. package/dist/agents/middleware/modelRetry.d.ts +0 -1
  85. package/dist/agents/middleware/modelRetry.d.ts.map +1 -1
  86. package/dist/agents/middleware/modelRetry.js +15 -13
  87. package/dist/agents/middleware/modelRetry.js.map +1 -1
  88. package/dist/agents/middleware/pii.cjs +21 -32
  89. package/dist/agents/middleware/pii.cjs.map +1 -1
  90. package/dist/agents/middleware/pii.d.cts +0 -1
  91. package/dist/agents/middleware/pii.d.cts.map +1 -1
  92. package/dist/agents/middleware/pii.d.ts +0 -1
  93. package/dist/agents/middleware/pii.d.ts.map +1 -1
  94. package/dist/agents/middleware/pii.js +10 -21
  95. package/dist/agents/middleware/pii.js.map +1 -1
  96. package/dist/agents/middleware/piiRedaction.cjs +22 -28
  97. package/dist/agents/middleware/piiRedaction.cjs.map +1 -1
  98. package/dist/agents/middleware/piiRedaction.d.cts +0 -1
  99. package/dist/agents/middleware/piiRedaction.d.cts.map +1 -1
  100. package/dist/agents/middleware/piiRedaction.d.ts +0 -1
  101. package/dist/agents/middleware/piiRedaction.d.ts.map +1 -1
  102. package/dist/agents/middleware/piiRedaction.js +8 -14
  103. package/dist/agents/middleware/piiRedaction.js.map +1 -1
  104. package/dist/agents/middleware/provider/anthropic/promptCaching.cjs +5 -8
  105. package/dist/agents/middleware/provider/anthropic/promptCaching.cjs.map +1 -1
  106. package/dist/agents/middleware/provider/anthropic/promptCaching.d.cts +2 -2
  107. package/dist/agents/middleware/provider/anthropic/promptCaching.d.cts.map +1 -1
  108. package/dist/agents/middleware/provider/anthropic/promptCaching.d.ts +2 -2
  109. package/dist/agents/middleware/provider/anthropic/promptCaching.d.ts.map +1 -1
  110. package/dist/agents/middleware/provider/anthropic/promptCaching.js +3 -6
  111. package/dist/agents/middleware/provider/anthropic/promptCaching.js.map +1 -1
  112. package/dist/agents/middleware/provider/openai/moderation.cjs +17 -22
  113. package/dist/agents/middleware/provider/openai/moderation.cjs.map +1 -1
  114. package/dist/agents/middleware/provider/openai/moderation.d.cts +0 -2
  115. package/dist/agents/middleware/provider/openai/moderation.d.cts.map +1 -1
  116. package/dist/agents/middleware/provider/openai/moderation.d.ts +0 -2
  117. package/dist/agents/middleware/provider/openai/moderation.d.ts.map +1 -1
  118. package/dist/agents/middleware/provider/openai/moderation.js +10 -15
  119. package/dist/agents/middleware/provider/openai/moderation.js.map +1 -1
  120. package/dist/agents/middleware/summarization.cjs +39 -62
  121. package/dist/agents/middleware/summarization.cjs.map +1 -1
  122. package/dist/agents/middleware/summarization.d.cts +2 -2
  123. package/dist/agents/middleware/summarization.d.cts.map +1 -1
  124. package/dist/agents/middleware/summarization.d.ts +2 -2
  125. package/dist/agents/middleware/summarization.d.ts.map +1 -1
  126. package/dist/agents/middleware/summarization.js +17 -40
  127. package/dist/agents/middleware/summarization.js.map +1 -1
  128. package/dist/agents/middleware/todoListMiddleware.cjs +21 -27
  129. package/dist/agents/middleware/todoListMiddleware.cjs.map +1 -1
  130. package/dist/agents/middleware/todoListMiddleware.d.cts +4 -4
  131. package/dist/agents/middleware/todoListMiddleware.d.cts.map +1 -1
  132. package/dist/agents/middleware/todoListMiddleware.d.ts +4 -4
  133. package/dist/agents/middleware/todoListMiddleware.d.ts.map +1 -1
  134. package/dist/agents/middleware/todoListMiddleware.js +12 -18
  135. package/dist/agents/middleware/todoListMiddleware.js.map +1 -1
  136. package/dist/agents/middleware/toolCallLimit.cjs +24 -46
  137. package/dist/agents/middleware/toolCallLimit.cjs.map +1 -1
  138. package/dist/agents/middleware/toolCallLimit.d.cts +2 -3
  139. package/dist/agents/middleware/toolCallLimit.d.cts.map +1 -1
  140. package/dist/agents/middleware/toolCallLimit.d.ts +2 -3
  141. package/dist/agents/middleware/toolCallLimit.d.ts.map +1 -1
  142. package/dist/agents/middleware/toolCallLimit.js +17 -39
  143. package/dist/agents/middleware/toolCallLimit.js.map +1 -1
  144. package/dist/agents/middleware/toolEmulator.cjs +8 -13
  145. package/dist/agents/middleware/toolEmulator.cjs.map +1 -1
  146. package/dist/agents/middleware/toolEmulator.d.cts +0 -1
  147. package/dist/agents/middleware/toolEmulator.d.cts.map +1 -1
  148. package/dist/agents/middleware/toolEmulator.d.ts +0 -1
  149. package/dist/agents/middleware/toolEmulator.d.ts.map +1 -1
  150. package/dist/agents/middleware/toolEmulator.js +5 -10
  151. package/dist/agents/middleware/toolEmulator.js.map +1 -1
  152. package/dist/agents/middleware/toolRetry.cjs +19 -17
  153. package/dist/agents/middleware/toolRetry.cjs.map +1 -1
  154. package/dist/agents/middleware/toolRetry.d.cts +0 -1
  155. package/dist/agents/middleware/toolRetry.d.cts.map +1 -1
  156. package/dist/agents/middleware/toolRetry.d.ts +0 -1
  157. package/dist/agents/middleware/toolRetry.d.ts.map +1 -1
  158. package/dist/agents/middleware/toolRetry.js +15 -13
  159. package/dist/agents/middleware/toolRetry.js.map +1 -1
  160. package/dist/agents/middleware/types.cjs.map +1 -1
  161. package/dist/agents/middleware/types.d.cts +33 -33
  162. package/dist/agents/middleware/types.d.cts.map +1 -1
  163. package/dist/agents/middleware/types.d.ts +33 -33
  164. package/dist/agents/middleware/types.d.ts.map +1 -1
  165. package/dist/agents/middleware/types.js.map +1 -1
  166. package/dist/agents/middleware/utils.cjs +8 -8
  167. package/dist/agents/middleware/utils.cjs.map +1 -1
  168. package/dist/agents/middleware/utils.d.cts +0 -1
  169. package/dist/agents/middleware/utils.d.cts.map +1 -1
  170. package/dist/agents/middleware/utils.d.ts +0 -1
  171. package/dist/agents/middleware/utils.d.ts.map +1 -1
  172. package/dist/agents/middleware/utils.js +3 -3
  173. package/dist/agents/middleware/utils.js.map +1 -1
  174. package/dist/agents/middleware.cjs +1 -2
  175. package/dist/agents/middleware.cjs.map +1 -1
  176. package/dist/agents/middleware.d.cts +0 -1
  177. package/dist/agents/middleware.d.cts.map +1 -1
  178. package/dist/agents/middleware.d.ts +0 -1
  179. package/dist/agents/middleware.d.ts.map +1 -1
  180. package/dist/agents/middleware.js +1 -2
  181. package/dist/agents/middleware.js.map +1 -1
  182. package/dist/agents/model.cjs.map +1 -1
  183. package/dist/agents/model.js.map +1 -1
  184. package/dist/agents/nodes/AfterAgentNode.cjs +1 -2
  185. package/dist/agents/nodes/AfterAgentNode.cjs.map +1 -1
  186. package/dist/agents/nodes/AfterAgentNode.js +1 -2
  187. package/dist/agents/nodes/AfterAgentNode.js.map +1 -1
  188. package/dist/agents/nodes/AfterModelNode.cjs +1 -2
  189. package/dist/agents/nodes/AfterModelNode.cjs.map +1 -1
  190. package/dist/agents/nodes/AfterModelNode.js +1 -2
  191. package/dist/agents/nodes/AfterModelNode.js.map +1 -1
  192. package/dist/agents/nodes/AgentNode.cjs +46 -58
  193. package/dist/agents/nodes/AgentNode.cjs.map +1 -1
  194. package/dist/agents/nodes/AgentNode.js +16 -28
  195. package/dist/agents/nodes/AgentNode.js.map +1 -1
  196. package/dist/agents/nodes/BeforeAgentNode.cjs +1 -2
  197. package/dist/agents/nodes/BeforeAgentNode.cjs.map +1 -1
  198. package/dist/agents/nodes/BeforeAgentNode.js +1 -2
  199. package/dist/agents/nodes/BeforeAgentNode.js.map +1 -1
  200. package/dist/agents/nodes/BeforeModelNode.cjs +1 -2
  201. package/dist/agents/nodes/BeforeModelNode.cjs.map +1 -1
  202. package/dist/agents/nodes/BeforeModelNode.js +1 -2
  203. package/dist/agents/nodes/BeforeModelNode.js.map +1 -1
  204. package/dist/agents/nodes/ToolNode.cjs +25 -25
  205. package/dist/agents/nodes/ToolNode.cjs.map +1 -1
  206. package/dist/agents/nodes/ToolNode.js +6 -6
  207. package/dist/agents/nodes/ToolNode.js.map +1 -1
  208. package/dist/agents/nodes/middleware.cjs +3 -3
  209. package/dist/agents/nodes/middleware.cjs.map +1 -1
  210. package/dist/agents/nodes/middleware.js.map +1 -1
  211. package/dist/agents/nodes/types.d.cts +0 -1
  212. package/dist/agents/nodes/types.d.cts.map +1 -1
  213. package/dist/agents/nodes/types.d.ts +0 -1
  214. package/dist/agents/nodes/types.d.ts.map +1 -1
  215. package/dist/agents/nodes/utils.cjs +16 -17
  216. package/dist/agents/nodes/utils.cjs.map +1 -1
  217. package/dist/agents/nodes/utils.js +2 -3
  218. package/dist/agents/nodes/utils.js.map +1 -1
  219. package/dist/agents/responses.cjs +20 -30
  220. package/dist/agents/responses.cjs.map +1 -1
  221. package/dist/agents/responses.d.cts +0 -1
  222. package/dist/agents/responses.d.cts.map +1 -1
  223. package/dist/agents/responses.d.ts +0 -1
  224. package/dist/agents/responses.d.ts.map +1 -1
  225. package/dist/agents/responses.js +12 -22
  226. package/dist/agents/responses.js.map +1 -1
  227. package/dist/agents/runtime.d.cts +0 -1
  228. package/dist/agents/runtime.d.cts.map +1 -1
  229. package/dist/agents/runtime.d.ts +0 -1
  230. package/dist/agents/runtime.d.ts.map +1 -1
  231. package/dist/agents/state.cjs +1 -2
  232. package/dist/agents/state.cjs.map +1 -1
  233. package/dist/agents/state.js +1 -2
  234. package/dist/agents/state.js.map +1 -1
  235. package/dist/agents/tests/utils.cjs +21 -26
  236. package/dist/agents/tests/utils.cjs.map +1 -1
  237. package/dist/agents/tests/utils.d.cts +0 -1
  238. package/dist/agents/tests/utils.d.cts.map +1 -1
  239. package/dist/agents/tests/utils.d.ts +0 -1
  240. package/dist/agents/tests/utils.d.ts.map +1 -1
  241. package/dist/agents/tests/utils.js +12 -17
  242. package/dist/agents/tests/utils.js.map +1 -1
  243. package/dist/agents/types.d.cts +4 -5
  244. package/dist/agents/types.d.cts.map +1 -1
  245. package/dist/agents/types.d.ts +4 -5
  246. package/dist/agents/types.d.ts.map +1 -1
  247. package/dist/agents/utils.cjs +32 -32
  248. package/dist/agents/utils.cjs.map +1 -1
  249. package/dist/agents/utils.js +6 -6
  250. package/dist/agents/utils.js.map +1 -1
  251. package/dist/agents/withAgentName.cjs +5 -5
  252. package/dist/agents/withAgentName.cjs.map +1 -1
  253. package/dist/agents/withAgentName.js.map +1 -1
  254. package/dist/chat_models/universal.cjs +34 -41
  255. package/dist/chat_models/universal.cjs.map +1 -1
  256. package/dist/chat_models/universal.d.cts.map +1 -1
  257. package/dist/chat_models/universal.d.ts.map +1 -1
  258. package/dist/chat_models/universal.js +21 -29
  259. package/dist/chat_models/universal.js.map +1 -1
  260. package/dist/hub/base.cjs +3 -4
  261. package/dist/hub/base.cjs.map +1 -1
  262. package/dist/hub/base.d.cts +0 -1
  263. package/dist/hub/base.d.cts.map +1 -1
  264. package/dist/hub/base.d.ts +0 -1
  265. package/dist/hub/base.d.ts.map +1 -1
  266. package/dist/hub/base.js +1 -2
  267. package/dist/hub/base.js.map +1 -1
  268. package/dist/hub/index.cjs +2 -2
  269. package/dist/hub/index.cjs.map +1 -1
  270. package/dist/hub/index.d.cts +0 -1
  271. package/dist/hub/index.d.cts.map +1 -1
  272. package/dist/hub/index.d.ts +0 -1
  273. package/dist/hub/index.d.ts.map +1 -1
  274. package/dist/hub/index.js +1 -2
  275. package/dist/hub/index.js.map +1 -1
  276. package/dist/hub/node.cjs +7 -13
  277. package/dist/hub/node.cjs.map +1 -1
  278. package/dist/hub/node.d.cts +0 -1
  279. package/dist/hub/node.d.cts.map +1 -1
  280. package/dist/hub/node.d.ts +0 -1
  281. package/dist/hub/node.d.ts.map +1 -1
  282. package/dist/hub/node.js +6 -13
  283. package/dist/hub/node.js.map +1 -1
  284. package/dist/index.cjs +48 -48
  285. package/dist/index.d.cts +2 -1
  286. package/dist/index.d.ts +2 -1
  287. package/dist/index.js +2 -3
  288. package/dist/load/import_constants.cjs.map +1 -1
  289. package/dist/load/import_constants.js.map +1 -1
  290. package/dist/load/import_map.cjs +46 -47
  291. package/dist/load/import_map.cjs.map +1 -1
  292. package/dist/load/import_map.js +2 -3
  293. package/dist/load/import_map.js.map +1 -1
  294. package/dist/load/import_type.d.cts.map +1 -1
  295. package/dist/load/import_type.d.ts.map +1 -1
  296. package/dist/load/index.cjs +13 -3
  297. package/dist/load/index.cjs.map +1 -1
  298. package/dist/load/index.d.cts +9 -1
  299. package/dist/load/index.d.cts.map +1 -1
  300. package/dist/load/index.d.ts +9 -1
  301. package/dist/load/index.d.ts.map +1 -1
  302. package/dist/load/index.js +9 -0
  303. package/dist/load/index.js.map +1 -1
  304. package/dist/load/serializable.cjs +7 -6
  305. package/dist/load/serializable.js +4 -4
  306. package/dist/storage/encoder_backed.cjs +9 -10
  307. package/dist/storage/encoder_backed.cjs.map +1 -1
  308. package/dist/storage/encoder_backed.d.cts +0 -1
  309. package/dist/storage/encoder_backed.d.cts.map +1 -1
  310. package/dist/storage/encoder_backed.d.ts +0 -1
  311. package/dist/storage/encoder_backed.d.ts.map +1 -1
  312. package/dist/storage/encoder_backed.js +4 -6
  313. package/dist/storage/encoder_backed.js.map +1 -1
  314. package/dist/storage/file_system.cjs +12 -11
  315. package/dist/storage/file_system.cjs.map +1 -1
  316. package/dist/storage/file_system.d.cts +0 -1
  317. package/dist/storage/file_system.d.cts.map +1 -1
  318. package/dist/storage/file_system.d.ts +0 -1
  319. package/dist/storage/file_system.d.ts.map +1 -1
  320. package/dist/storage/file_system.js +5 -7
  321. package/dist/storage/file_system.js.map +1 -1
  322. package/dist/storage/in_memory.cjs +5 -5
  323. package/dist/storage/in_memory.js +2 -3
  324. package/package.json +6 -6
  325. package/dist/_virtual/rolldown_runtime.js +0 -25
@@ -2,12 +2,10 @@ import { AgentMiddleware } from "../../types.cjs";
2
2
  import { BaseChatModel } from "@langchain/core/language_models/chat_models";
3
3
 
4
4
  //#region src/agents/middleware/provider/openai/moderation.d.ts
5
-
6
5
  type ModerationModel = "omni-moderation-latest" | "omni-moderation-2024-09-26" | "text-moderation-latest" | "text-moderation-stable";
7
6
  /**
8
7
  * Error raised when OpenAI flags content and `exitBehavior` is set to `"error"`.
9
8
  */
10
-
11
9
  /**
12
10
  * Options for configuring the OpenAI Moderation middleware.
13
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"moderation.d.cts","names":["BaseChatModel","AgentMiddleware","ViolationStage","ModerationResult","Record","ModerationModel","OpenAIModerationError","content","stage","result","message","Error","OpenAIModerationMiddlewareOptions","openAIModerationMiddleware"],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.d.ts"],"sourcesContent":["import type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport type { AgentMiddleware } from \"../../types.js\";\n/**\n * Stage where a violation occurred.\n */\nexport type ViolationStage = \"input\" | \"output\" | \"tool\";\n/**\n * Result of moderation.\n * @see https://platform.openai.com/docs/api-reference/moderations/object\n */\ninterface ModerationResult {\n flagged: boolean;\n categories: Record<string, boolean>;\n category_scores: Record<string, number>;\n category_applied_input_types: Record<string, string[]>;\n}\ntype ModerationModel = \"omni-moderation-latest\" | \"omni-moderation-2024-09-26\" | \"text-moderation-latest\" | \"text-moderation-stable\";\n/**\n * Error raised when OpenAI flags content and `exitBehavior` is set to `\"error\"`.\n */\nexport declare class OpenAIModerationError extends Error {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n originalMessage: string;\n constructor({ content, stage, result, message }: {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n message: string;\n });\n}\n/**\n * Options for configuring the OpenAI Moderation middleware.\n */\nexport interface OpenAIModerationMiddlewareOptions {\n /**\n * OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @example\n * ```ts\n * const model = new ChatOpenAI({ model: \"gpt-4o-mini\" });\n * const middleware = openAIModerationMiddleware({ model });\n * const agent = createAgent({\n * model,\n * middleware: [middleware],\n * });\n * ```\n * @example\n * ```ts\n * const middleware = openAIModerationMiddleware({ model: \"gpt-4o-mini\" });\n * const agent = createAgent({\n * model: \"gpt-5\",\n * middleware: [middleware],\n * });\n * ```\n */\n model: string | BaseChatModel;\n /**\n * Moderation model to use.\n * @default \"omni-moderation-latest\"\n */\n moderationModel?: ModerationModel;\n /**\n * Whether to check user input messages.\n * @default true\n */\n checkInput?: boolean;\n /**\n * Whether to check model output messages.\n * @default true\n */\n checkOutput?: boolean;\n /**\n * Whether to check tool result messages.\n * @default false\n */\n checkToolResults?: boolean;\n /**\n * How to handle violations.\n * - `\"error\"`: Throw an error when content is flagged\n * - `\"end\"`: End the agent execution and return a violation message\n * - `\"replace\"`: Replace the flagged content with a violation message\n * @default \"end\"\n */\n exitBehavior?: \"error\" | \"end\" | \"replace\";\n /**\n * Custom template for violation messages.\n * Available placeholders: `{categories}`, `{category_scores}`, `{original_content}`\n */\n violationMessage?: string;\n}\n/**\n * Middleware that moderates agent traffic using OpenAI's moderation endpoint.\n *\n * This middleware checks messages for content policy violations at different stages:\n * - Input: User messages before they reach the model\n * - Output: AI model responses\n * - Tool results: Results returned from tool executions\n *\n * @param options - Configuration options for the middleware\n * @param options.model - OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @param options.moderationModel - Moderation model to use.\n * @param options.checkInput - Whether to check user input messages.\n * @param options.checkOutput - Whether to check model output messages.\n * @param options.checkToolResults - Whether to check tool result messages.\n * @param options.exitBehavior - How to handle violations.\n * @param options.violationMessage - Custom template for violation messages.\n * @returns Middleware function that can be used to moderate agent traffic.\n *\n * @example Using model instance\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Using model name\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * model: \"gpt-4o-mini\",\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Custom violation message\n * ```ts\n * const middleware = openAIModerationMiddleware({\n * violationMessage: \"Content flagged: {categories}. Scores: {category_scores}\"\n * });\n * ```\n */\nexport declare function openAIModerationMiddleware(options: OpenAIModerationMiddlewareOptions): AgentMiddleware;\nexport {};\n//# sourceMappingURL=moderation.d.ts.map"],"mappings":";;;;;KAgBKK,eAAAA;;;;;;;;UAmBYO,iCAAAA;;;;;;;;;;;;;;;;;;;;;kBAqBGZ;;;;;oBAKEK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FEQ,0BAAAA,UAAoCD,oCAAoCX"}
1
+ {"version":3,"file":"moderation.d.cts","names":[],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.ts"],"mappings":";;;;KA6FK,eAAA;;;;;;;UAsCY,iCAAA;;;;;;;;;;;;;;;;;;;;;EAqBf,KAAA,WAAgB,aAAA;;;;;EAMhB,eAAA,GAAkB,eAAA;;;;;EAMlB,UAAA;;;;;EAMA,WAAA;;;;;EAMA,gBAAA;;;;;;;;EASA,YAAA;;;;;EAMA,gBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+Dc,0BAAA,CACd,OAAA,EAAS,iCAAA,GACR,eAAA"}
@@ -2,12 +2,10 @@ import { AgentMiddleware } from "../../types.js";
2
2
  import { BaseChatModel } from "@langchain/core/language_models/chat_models";
3
3
 
4
4
  //#region src/agents/middleware/provider/openai/moderation.d.ts
5
-
6
5
  type ModerationModel = "omni-moderation-latest" | "omni-moderation-2024-09-26" | "text-moderation-latest" | "text-moderation-stable";
7
6
  /**
8
7
  * Error raised when OpenAI flags content and `exitBehavior` is set to `"error"`.
9
8
  */
10
-
11
9
  /**
12
10
  * Options for configuring the OpenAI Moderation middleware.
13
11
  */
@@ -1 +1 @@
1
- {"version":3,"file":"moderation.d.ts","names":["BaseChatModel","AgentMiddleware","ViolationStage","ModerationResult","Record","ModerationModel","OpenAIModerationError","content","stage","result","message","Error","OpenAIModerationMiddlewareOptions","openAIModerationMiddleware"],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.d.ts"],"sourcesContent":["import type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport type { AgentMiddleware } from \"../../types.js\";\n/**\n * Stage where a violation occurred.\n */\nexport type ViolationStage = \"input\" | \"output\" | \"tool\";\n/**\n * Result of moderation.\n * @see https://platform.openai.com/docs/api-reference/moderations/object\n */\ninterface ModerationResult {\n flagged: boolean;\n categories: Record<string, boolean>;\n category_scores: Record<string, number>;\n category_applied_input_types: Record<string, string[]>;\n}\ntype ModerationModel = \"omni-moderation-latest\" | \"omni-moderation-2024-09-26\" | \"text-moderation-latest\" | \"text-moderation-stable\";\n/**\n * Error raised when OpenAI flags content and `exitBehavior` is set to `\"error\"`.\n */\nexport declare class OpenAIModerationError extends Error {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n originalMessage: string;\n constructor({ content, stage, result, message }: {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n message: string;\n });\n}\n/**\n * Options for configuring the OpenAI Moderation middleware.\n */\nexport interface OpenAIModerationMiddlewareOptions {\n /**\n * OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @example\n * ```ts\n * const model = new ChatOpenAI({ model: \"gpt-4o-mini\" });\n * const middleware = openAIModerationMiddleware({ model });\n * const agent = createAgent({\n * model,\n * middleware: [middleware],\n * });\n * ```\n * @example\n * ```ts\n * const middleware = openAIModerationMiddleware({ model: \"gpt-4o-mini\" });\n * const agent = createAgent({\n * model: \"gpt-5\",\n * middleware: [middleware],\n * });\n * ```\n */\n model: string | BaseChatModel;\n /**\n * Moderation model to use.\n * @default \"omni-moderation-latest\"\n */\n moderationModel?: ModerationModel;\n /**\n * Whether to check user input messages.\n * @default true\n */\n checkInput?: boolean;\n /**\n * Whether to check model output messages.\n * @default true\n */\n checkOutput?: boolean;\n /**\n * Whether to check tool result messages.\n * @default false\n */\n checkToolResults?: boolean;\n /**\n * How to handle violations.\n * - `\"error\"`: Throw an error when content is flagged\n * - `\"end\"`: End the agent execution and return a violation message\n * - `\"replace\"`: Replace the flagged content with a violation message\n * @default \"end\"\n */\n exitBehavior?: \"error\" | \"end\" | \"replace\";\n /**\n * Custom template for violation messages.\n * Available placeholders: `{categories}`, `{category_scores}`, `{original_content}`\n */\n violationMessage?: string;\n}\n/**\n * Middleware that moderates agent traffic using OpenAI's moderation endpoint.\n *\n * This middleware checks messages for content policy violations at different stages:\n * - Input: User messages before they reach the model\n * - Output: AI model responses\n * - Tool results: Results returned from tool executions\n *\n * @param options - Configuration options for the middleware\n * @param options.model - OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @param options.moderationModel - Moderation model to use.\n * @param options.checkInput - Whether to check user input messages.\n * @param options.checkOutput - Whether to check model output messages.\n * @param options.checkToolResults - Whether to check tool result messages.\n * @param options.exitBehavior - How to handle violations.\n * @param options.violationMessage - Custom template for violation messages.\n * @returns Middleware function that can be used to moderate agent traffic.\n *\n * @example Using model instance\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Using model name\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * model: \"gpt-4o-mini\",\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Custom violation message\n * ```ts\n * const middleware = openAIModerationMiddleware({\n * violationMessage: \"Content flagged: {categories}. Scores: {category_scores}\"\n * });\n * ```\n */\nexport declare function openAIModerationMiddleware(options: OpenAIModerationMiddlewareOptions): AgentMiddleware;\nexport {};\n//# sourceMappingURL=moderation.d.ts.map"],"mappings":";;;;;KAgBKK,eAAAA;;;;;;;;UAmBYO,iCAAAA;;;;;;;;;;;;;;;;;;;;;kBAqBGZ;;;;;oBAKEK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA0FEQ,0BAAAA,UAAoCD,oCAAoCX"}
1
+ {"version":3,"file":"moderation.d.ts","names":[],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.ts"],"mappings":";;;;KA6FK,eAAA;;;;;;;UAsCY,iCAAA;;;;;;;;;;;;;;;;;;;;;EAqBf,KAAA,WAAgB,aAAA;;;;;EAMhB,eAAA,GAAkB,eAAA;;;;;EAMlB,UAAA;;;;;EAMA,WAAA;;;;;EAMA,gBAAA;;;;;;;;EASA,YAAA;;;;;EAMA,gBAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+Dc,0BAAA,CACd,OAAA,EAAS,iCAAA,GACR,eAAA"}
@@ -119,8 +119,7 @@ function openAIModerationMiddleware(options) {
119
119
  */
120
120
  const extractText = (message) => {
121
121
  if (message.content == null) return null;
122
- const text = message.text;
123
- return text || null;
122
+ return message.text || null;
124
123
  };
125
124
  /**
126
125
  * Find the last index of a message type in the messages array.
@@ -147,10 +146,9 @@ function openAIModerationMiddleware(options) {
147
146
  };
148
147
  function moderateContent(input, params) {
149
148
  const clientOptions = openaiModel?._getClientOptions?.();
150
- const moderationModel$1 = params?.model ?? "omni-moderation-latest";
151
149
  const moderationRequest = {
152
150
  input,
153
- model: moderationModel$1
151
+ model: params?.model ?? "omni-moderation-latest"
154
152
  };
155
153
  return openaiModel.client.moderations.create(moderationRequest, clientOptions);
156
154
  }
@@ -169,7 +167,7 @@ function openAIModerationMiddleware(options) {
169
167
  jumpTo: "end",
170
168
  messages: [new AIMessage({ content: violationText })]
171
169
  };
172
- if (index == null) return void 0;
170
+ if (index == null) return;
173
171
  /**
174
172
  * Replace the original message with a new message that contains the violation text.
175
173
  */
@@ -192,8 +190,7 @@ function openAIModerationMiddleware(options) {
192
190
  const text = extractText(message);
193
191
  if (!text) return null;
194
192
  await initModerationModel();
195
- const response = await moderateContent(text, { model: moderationModel });
196
- const flaggedResult = response.results.find((result) => result.flagged);
193
+ const flaggedResult = (await moderateContent(text, { model: moderationModel })).results.find((result) => result.flagged);
197
194
  if (!flaggedResult) return null;
198
195
  return applyViolation(messages, idx, "input", text, flaggedResult);
199
196
  };
@@ -211,8 +208,7 @@ function openAIModerationMiddleware(options) {
211
208
  const text = extractText(msg);
212
209
  if (!text) continue;
213
210
  await initModerationModel();
214
- const response = await moderateContent(text, { model: moderationModel });
215
- const flaggedResult = response.results.find((result) => result.flagged);
211
+ const flaggedResult = (await moderateContent(text, { model: moderationModel })).results.find((result) => result.flagged);
216
212
  if (!flaggedResult) continue;
217
213
  const action = applyViolation(working, idx, "tool", text, flaggedResult);
218
214
  if (action) {
@@ -236,8 +232,7 @@ function openAIModerationMiddleware(options) {
236
232
  const text = extractText(aiMessage);
237
233
  if (!text) return null;
238
234
  await initModerationModel();
239
- const response = await moderateContent(text, { model: moderationModel });
240
- const flaggedResult = response.results.find((result) => result.flagged);
235
+ const flaggedResult = (await moderateContent(text, { model: moderationModel })).results.find((result) => result.flagged);
241
236
  if (!flaggedResult) return null;
242
237
  return applyViolation(messages, lastAiIdx, "output", text, flaggedResult);
243
238
  };
@@ -274,18 +269,18 @@ function openAIModerationMiddleware(options) {
274
269
  name: "OpenAIModerationMiddleware",
275
270
  beforeModel: {
276
271
  hook: async (state) => {
277
- if (!checkInput && !checkToolResults) return void 0;
272
+ if (!checkInput && !checkToolResults) return;
278
273
  const messages = state.messages || [];
279
- if (messages.length === 0) return void 0;
274
+ if (messages.length === 0) return;
280
275
  return await moderateInputs(messages) ?? void 0;
281
276
  },
282
277
  canJumpTo: ["end"]
283
278
  },
284
279
  afterModel: {
285
280
  hook: async (state) => {
286
- if (!checkOutput) return void 0;
281
+ if (!checkOutput) return;
287
282
  const messages = state.messages || [];
288
- if (messages.length === 0) return void 0;
283
+ if (messages.length === 0) return;
289
284
  return await moderateOutput(messages) ?? void 0;
290
285
  },
291
286
  canJumpTo: ["end"]
@@ -1 +1 @@
1
- {"version":3,"file":"moderation.js","names":["model: unknown","options: OpenAIModerationMiddlewareOptions","openaiModel: OpenAIModel | undefined","message: BaseMessage","messages: BaseMessage[]","messageType: typeof AIMessage | typeof HumanMessage | typeof ToolMessage","content: string","result: ModerationResult","categories: string[]","input: string | string[]","params?: { model?: ModerationModel; options?: unknown }","moderationModel","index: number | null","stage: ViolationStage"],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\nimport { AIMessage, HumanMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { BaseLanguageModel } from \"@langchain/core/language_models/base\";\n\nimport { initChatModel } from \"../../../../chat_models/universal.js\";\nimport { createMiddleware } from \"../../../middleware.js\";\nimport type { MiddlewareResult, AgentMiddleware } from \"../../types.js\";\nimport type { AgentBuiltInState } from \"../../../runtime.js\";\n\n/**\n * OpenAI model interface.\n */\ninterface OpenAIModel extends BaseLanguageModel {\n getName: () => string;\n _getClientOptions: () => unknown;\n client: {\n moderations: {\n create: (\n input: {\n input: string | string[];\n model: string;\n },\n options?: unknown\n ) => Promise<ModerationResponse>;\n };\n };\n}\n\n/**\n * Check if the model is an OpenAI model that supports moderation.\n * @param model - The model to check.\n * @returns Whether the model is an OpenAI model that supports moderation.\n */\nfunction isOpenAIModel(model: unknown): model is OpenAIModel {\n if (\n !model ||\n typeof model !== \"object\" ||\n model === null ||\n !(\"client\" in model) ||\n !(\"_getClientOptions\" in model) ||\n typeof model._getClientOptions !== \"function\"\n ) {\n return false;\n }\n\n /**\n * client may not yet be initialized, so we need to check if the model has a _getClientOptions method.\n */\n model._getClientOptions();\n return (\n typeof model.client === \"object\" &&\n model.client !== null &&\n \"moderations\" in model.client &&\n typeof model.client.moderations === \"object\" &&\n model.client.moderations !== null &&\n \"create\" in model.client.moderations &&\n typeof model.client.moderations.create === \"function\"\n );\n}\n\n/**\n * Stage where a violation occurred.\n */\nexport type ViolationStage = \"input\" | \"output\" | \"tool\";\n\n/**\n * Default template for violation messages.\n */\nconst DEFAULT_VIOLATION_TEMPLATE =\n \"I'm sorry, but I can't comply with that request. It was flagged for {categories}.\";\n\n/**\n * Result of moderation.\n * @see https://platform.openai.com/docs/api-reference/moderations/object\n */\ninterface ModerationResult {\n flagged: boolean;\n categories: Record<string, boolean>;\n category_scores: Record<string, number>;\n category_applied_input_types: Record<string, string[]>;\n}\n\n/**\n * Moderation response.\n * @see https://platform.openai.com/docs/api-reference/moderations/create\n */\ninterface ModerationResponse {\n id: string;\n model: string;\n results: ModerationResult[];\n}\n\ntype ModerationModel =\n | \"omni-moderation-latest\"\n | \"omni-moderation-2024-09-26\"\n | \"text-moderation-latest\"\n | \"text-moderation-stable\";\n\n/**\n * Error raised when OpenAI flags content and `exitBehavior` is set to `\"error\"`.\n */\nexport class OpenAIModerationError extends Error {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n originalMessage: string;\n\n constructor({\n content,\n stage,\n result,\n message,\n }: {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n message: string;\n }) {\n super(message);\n this.name = \"OpenAIModerationError\";\n this.content = content;\n this.stage = stage;\n this.result = result;\n this.originalMessage = message;\n }\n}\n\n/**\n * Options for configuring the OpenAI Moderation middleware.\n */\nexport interface OpenAIModerationMiddlewareOptions {\n /**\n * OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @example\n * ```ts\n * const model = new ChatOpenAI({ model: \"gpt-4o-mini\" });\n * const middleware = openAIModerationMiddleware({ model });\n * const agent = createAgent({\n * model,\n * middleware: [middleware],\n * });\n * ```\n * @example\n * ```ts\n * const middleware = openAIModerationMiddleware({ model: \"gpt-4o-mini\" });\n * const agent = createAgent({\n * model: \"gpt-5\",\n * middleware: [middleware],\n * });\n * ```\n */\n model: string | BaseChatModel;\n\n /**\n * Moderation model to use.\n * @default \"omni-moderation-latest\"\n */\n moderationModel?: ModerationModel;\n\n /**\n * Whether to check user input messages.\n * @default true\n */\n checkInput?: boolean;\n\n /**\n * Whether to check model output messages.\n * @default true\n */\n checkOutput?: boolean;\n\n /**\n * Whether to check tool result messages.\n * @default false\n */\n checkToolResults?: boolean;\n\n /**\n * How to handle violations.\n * - `\"error\"`: Throw an error when content is flagged\n * - `\"end\"`: End the agent execution and return a violation message\n * - `\"replace\"`: Replace the flagged content with a violation message\n * @default \"end\"\n */\n exitBehavior?: \"error\" | \"end\" | \"replace\";\n\n /**\n * Custom template for violation messages.\n * Available placeholders: `{categories}`, `{category_scores}`, `{original_content}`\n */\n violationMessage?: string;\n}\n\n/**\n * Middleware that moderates agent traffic using OpenAI's moderation endpoint.\n *\n * This middleware checks messages for content policy violations at different stages:\n * - Input: User messages before they reach the model\n * - Output: AI model responses\n * - Tool results: Results returned from tool executions\n *\n * @param options - Configuration options for the middleware\n * @param options.model - OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @param options.moderationModel - Moderation model to use.\n * @param options.checkInput - Whether to check user input messages.\n * @param options.checkOutput - Whether to check model output messages.\n * @param options.checkToolResults - Whether to check tool result messages.\n * @param options.exitBehavior - How to handle violations.\n * @param options.violationMessage - Custom template for violation messages.\n * @returns Middleware function that can be used to moderate agent traffic.\n *\n * @example Using model instance\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Using model name\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * model: \"gpt-4o-mini\",\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Custom violation message\n * ```ts\n * const middleware = openAIModerationMiddleware({\n * violationMessage: \"Content flagged: {categories}. Scores: {category_scores}\"\n * });\n * ```\n */\nexport function openAIModerationMiddleware(\n options: OpenAIModerationMiddlewareOptions\n): AgentMiddleware {\n const {\n model,\n moderationModel = \"omni-moderation-latest\",\n checkInput = true,\n checkOutput = true,\n checkToolResults = false,\n exitBehavior = \"end\",\n violationMessage,\n } = options;\n\n let openaiModel: OpenAIModel | undefined;\n const initModerationModel = async (): Promise<OpenAIModel> => {\n if (openaiModel) {\n return openaiModel;\n }\n\n const resolvedModel =\n typeof model === \"string\" ? await initChatModel(model) : model;\n\n /**\n * Check if the model is an OpenAI model.\n */\n if (!resolvedModel.getName().includes(\"ChatOpenAI\")) {\n throw new Error(\n `Model must be an OpenAI model to use moderation middleware. Got: ${resolvedModel.getName()}`\n );\n }\n\n /**\n * check if OpenAI model package supports moderation.\n */\n if (!isOpenAIModel(resolvedModel)) {\n throw new Error(\n \"Model must support moderation to use moderation middleware.\"\n );\n }\n\n openaiModel = resolvedModel as unknown as OpenAIModel;\n return openaiModel;\n };\n\n /**\n * Extract text content from a message.\n */\n const extractText = (message: BaseMessage): string | null => {\n if (message.content == null) {\n return null;\n }\n const text = message.text;\n return text || null;\n };\n\n /**\n * Find the last index of a message type in the messages array.\n */\n const findLastIndex = (\n messages: BaseMessage[],\n messageType: typeof AIMessage | typeof HumanMessage | typeof ToolMessage\n ): number | null => {\n for (let idx = messages.length - 1; idx >= 0; idx--) {\n if (messageType.isInstance(messages[idx])) {\n return idx;\n }\n }\n return null;\n };\n\n /**\n * Format violation message from moderation result.\n */\n const formatViolationMessage = (\n content: string,\n result: ModerationResult\n ): string => {\n // Convert categories to array of flagged category names\n const categories: string[] = [];\n const categoriesObj = result.categories as unknown as Record<\n string,\n boolean\n >;\n for (const [name, flagged] of Object.entries(categoriesObj)) {\n if (flagged) {\n categories.push(name.replace(/_/g, \" \"));\n }\n }\n\n const categoryLabel =\n categories.length > 0\n ? categories.join(\", \")\n : \"OpenAI's safety policies\";\n\n const template = violationMessage || DEFAULT_VIOLATION_TEMPLATE;\n const scoresJson = JSON.stringify(\n result.category_scores as unknown as Record<string, number>,\n null,\n 2\n );\n\n try {\n return template\n .replace(\"{categories}\", categoryLabel)\n .replace(\"{category_scores}\", scoresJson)\n .replace(\"{original_content}\", content);\n } catch {\n return template;\n }\n };\n\n function moderateContent(\n input: string | string[],\n params?: { model?: ModerationModel; options?: unknown }\n ): Promise<ModerationResponse> {\n const clientOptions = openaiModel?._getClientOptions?.();\n const moderationModel = params?.model ?? \"omni-moderation-latest\";\n const moderationRequest = {\n input,\n model: moderationModel,\n };\n return openaiModel!.client.moderations.create(\n moderationRequest,\n clientOptions\n );\n }\n\n /**\n * Apply violation handling based on exit behavior.\n */\n const applyViolation = (\n messages: BaseMessage[],\n index: number | null,\n stage: ViolationStage,\n content: string,\n result: ModerationResult\n ): MiddlewareResult<Partial<AgentBuiltInState>> | undefined => {\n const violationText = formatViolationMessage(content, result);\n\n if (exitBehavior === \"error\") {\n throw new OpenAIModerationError({\n content,\n stage,\n result,\n message: violationText,\n });\n }\n\n if (exitBehavior === \"end\") {\n return {\n jumpTo: \"end\",\n messages: [new AIMessage({ content: violationText })],\n };\n }\n\n if (index == null) {\n return undefined;\n }\n\n /**\n * Replace the original message with a new message that contains the violation text.\n */\n const newMessages = [...messages];\n const original = newMessages[index];\n const MessageConstructor = Object.getPrototypeOf(original).constructor;\n newMessages[index] = new MessageConstructor({\n ...original,\n content: violationText,\n });\n\n return { messages: newMessages };\n };\n\n /**\n * Moderate user input messages.\n */\n const moderateUserMessage = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const idx = findLastIndex(messages, HumanMessage);\n if (idx == null) {\n return null;\n }\n\n const message = messages[idx];\n const text = extractText(message);\n if (!text) {\n return null;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n return null;\n }\n\n return applyViolation(messages, idx, \"input\", text, flaggedResult);\n };\n\n /**\n * Moderate tool result messages.\n */\n const moderateToolMessages = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const lastAiIdx = findLastIndex(messages, AIMessage);\n if (lastAiIdx == null) {\n return null;\n }\n\n const working = [...messages];\n let modified = false;\n\n for (let idx = lastAiIdx + 1; idx < working.length; idx++) {\n const msg = working[idx];\n if (!ToolMessage.isInstance(msg)) {\n continue;\n }\n\n const text = extractText(msg);\n if (!text) {\n continue;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n continue;\n }\n\n const action = applyViolation(working, idx, \"tool\", text, flaggedResult);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (modified) {\n return { messages: working };\n }\n\n return null;\n };\n\n /**\n * Moderate model output messages.\n */\n const moderateOutput = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const lastAiIdx = findLastIndex(messages, AIMessage);\n if (lastAiIdx == null) {\n return null;\n }\n\n const aiMessage = messages[lastAiIdx];\n const text = extractText(aiMessage);\n if (!text) {\n return null;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n return null;\n }\n\n return applyViolation(messages, lastAiIdx, \"output\", text, flaggedResult);\n };\n\n /**\n * Moderate inputs (user messages and tool results) before model call.\n */\n const moderateInputs = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const working = [...messages];\n let modified = false;\n\n if (checkToolResults) {\n const action = await moderateToolMessages(working);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (checkInput) {\n const action = await moderateUserMessage(working);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (modified) {\n return { messages: working };\n }\n\n return null;\n };\n\n return createMiddleware({\n name: \"OpenAIModerationMiddleware\",\n beforeModel: {\n hook: async (\n state\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | undefined> => {\n if (!checkInput && !checkToolResults) {\n return undefined;\n }\n\n const messages = state.messages || [];\n if (messages.length === 0) {\n return undefined;\n }\n\n return (await moderateInputs(messages)) ?? undefined;\n },\n canJumpTo: [\"end\"],\n },\n afterModel: {\n hook: async (\n state\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | undefined> => {\n if (!checkOutput) {\n return undefined;\n }\n\n const messages = state.messages || [];\n if (messages.length === 0) {\n return undefined;\n }\n\n return (await moderateOutput(messages)) ?? undefined;\n },\n canJumpTo: [\"end\"],\n },\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"moderation.js","names":[],"sources":["../../../../../src/agents/middleware/provider/openai/moderation.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\nimport { AIMessage, HumanMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { BaseLanguageModel } from \"@langchain/core/language_models/base\";\n\nimport { initChatModel } from \"../../../../chat_models/universal.js\";\nimport { createMiddleware } from \"../../../middleware.js\";\nimport type { MiddlewareResult, AgentMiddleware } from \"../../types.js\";\nimport type { AgentBuiltInState } from \"../../../runtime.js\";\n\n/**\n * OpenAI model interface.\n */\ninterface OpenAIModel extends BaseLanguageModel {\n getName: () => string;\n _getClientOptions: () => unknown;\n client: {\n moderations: {\n create: (\n input: {\n input: string | string[];\n model: string;\n },\n options?: unknown\n ) => Promise<ModerationResponse>;\n };\n };\n}\n\n/**\n * Check if the model is an OpenAI model that supports moderation.\n * @param model - The model to check.\n * @returns Whether the model is an OpenAI model that supports moderation.\n */\nfunction isOpenAIModel(model: unknown): model is OpenAIModel {\n if (\n !model ||\n typeof model !== \"object\" ||\n model === null ||\n !(\"client\" in model) ||\n !(\"_getClientOptions\" in model) ||\n typeof model._getClientOptions !== \"function\"\n ) {\n return false;\n }\n\n /**\n * client may not yet be initialized, so we need to check if the model has a _getClientOptions method.\n */\n model._getClientOptions();\n return (\n typeof model.client === \"object\" &&\n model.client !== null &&\n \"moderations\" in model.client &&\n typeof model.client.moderations === \"object\" &&\n model.client.moderations !== null &&\n \"create\" in model.client.moderations &&\n typeof model.client.moderations.create === \"function\"\n );\n}\n\n/**\n * Stage where a violation occurred.\n */\nexport type ViolationStage = \"input\" | \"output\" | \"tool\";\n\n/**\n * Default template for violation messages.\n */\nconst DEFAULT_VIOLATION_TEMPLATE =\n \"I'm sorry, but I can't comply with that request. It was flagged for {categories}.\";\n\n/**\n * Result of moderation.\n * @see https://platform.openai.com/docs/api-reference/moderations/object\n */\ninterface ModerationResult {\n flagged: boolean;\n categories: Record<string, boolean>;\n category_scores: Record<string, number>;\n category_applied_input_types: Record<string, string[]>;\n}\n\n/**\n * Moderation response.\n * @see https://platform.openai.com/docs/api-reference/moderations/create\n */\ninterface ModerationResponse {\n id: string;\n model: string;\n results: ModerationResult[];\n}\n\ntype ModerationModel =\n | \"omni-moderation-latest\"\n | \"omni-moderation-2024-09-26\"\n | \"text-moderation-latest\"\n | \"text-moderation-stable\";\n\n/**\n * Error raised when OpenAI flags content and `exitBehavior` is set to `\"error\"`.\n */\nexport class OpenAIModerationError extends Error {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n originalMessage: string;\n\n constructor({\n content,\n stage,\n result,\n message,\n }: {\n content: string;\n stage: ViolationStage;\n result: ModerationResult;\n message: string;\n }) {\n super(message);\n this.name = \"OpenAIModerationError\";\n this.content = content;\n this.stage = stage;\n this.result = result;\n this.originalMessage = message;\n }\n}\n\n/**\n * Options for configuring the OpenAI Moderation middleware.\n */\nexport interface OpenAIModerationMiddlewareOptions {\n /**\n * OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @example\n * ```ts\n * const model = new ChatOpenAI({ model: \"gpt-4o-mini\" });\n * const middleware = openAIModerationMiddleware({ model });\n * const agent = createAgent({\n * model,\n * middleware: [middleware],\n * });\n * ```\n * @example\n * ```ts\n * const middleware = openAIModerationMiddleware({ model: \"gpt-4o-mini\" });\n * const agent = createAgent({\n * model: \"gpt-5\",\n * middleware: [middleware],\n * });\n * ```\n */\n model: string | BaseChatModel;\n\n /**\n * Moderation model to use.\n * @default \"omni-moderation-latest\"\n */\n moderationModel?: ModerationModel;\n\n /**\n * Whether to check user input messages.\n * @default true\n */\n checkInput?: boolean;\n\n /**\n * Whether to check model output messages.\n * @default true\n */\n checkOutput?: boolean;\n\n /**\n * Whether to check tool result messages.\n * @default false\n */\n checkToolResults?: boolean;\n\n /**\n * How to handle violations.\n * - `\"error\"`: Throw an error when content is flagged\n * - `\"end\"`: End the agent execution and return a violation message\n * - `\"replace\"`: Replace the flagged content with a violation message\n * @default \"end\"\n */\n exitBehavior?: \"error\" | \"end\" | \"replace\";\n\n /**\n * Custom template for violation messages.\n * Available placeholders: `{categories}`, `{category_scores}`, `{original_content}`\n */\n violationMessage?: string;\n}\n\n/**\n * Middleware that moderates agent traffic using OpenAI's moderation endpoint.\n *\n * This middleware checks messages for content policy violations at different stages:\n * - Input: User messages before they reach the model\n * - Output: AI model responses\n * - Tool results: Results returned from tool executions\n *\n * @param options - Configuration options for the middleware\n * @param options.model - OpenAI model to use for moderation. Can be either a model name or a BaseChatModel instance.\n * @param options.moderationModel - Moderation model to use.\n * @param options.checkInput - Whether to check user input messages.\n * @param options.checkOutput - Whether to check model output messages.\n * @param options.checkToolResults - Whether to check tool result messages.\n * @param options.exitBehavior - How to handle violations.\n * @param options.violationMessage - Custom template for violation messages.\n * @returns Middleware function that can be used to moderate agent traffic.\n *\n * @example Using model instance\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Using model name\n * ```ts\n * import { createAgent, openAIModerationMiddleware } from \"langchain\";\n *\n * const middleware = openAIModerationMiddleware({\n * model: \"gpt-4o-mini\",\n * checkInput: true,\n * checkOutput: true,\n * exitBehavior: \"end\"\n * });\n *\n * const agent = createAgent({\n * model: \"openai:gpt-4o\",\n * tools: [...],\n * middleware: [middleware],\n * });\n * ```\n *\n * @example Custom violation message\n * ```ts\n * const middleware = openAIModerationMiddleware({\n * violationMessage: \"Content flagged: {categories}. Scores: {category_scores}\"\n * });\n * ```\n */\nexport function openAIModerationMiddleware(\n options: OpenAIModerationMiddlewareOptions\n): AgentMiddleware {\n const {\n model,\n moderationModel = \"omni-moderation-latest\",\n checkInput = true,\n checkOutput = true,\n checkToolResults = false,\n exitBehavior = \"end\",\n violationMessage,\n } = options;\n\n let openaiModel: OpenAIModel | undefined;\n const initModerationModel = async (): Promise<OpenAIModel> => {\n if (openaiModel) {\n return openaiModel;\n }\n\n const resolvedModel =\n typeof model === \"string\" ? await initChatModel(model) : model;\n\n /**\n * Check if the model is an OpenAI model.\n */\n if (!resolvedModel.getName().includes(\"ChatOpenAI\")) {\n throw new Error(\n `Model must be an OpenAI model to use moderation middleware. Got: ${resolvedModel.getName()}`\n );\n }\n\n /**\n * check if OpenAI model package supports moderation.\n */\n if (!isOpenAIModel(resolvedModel)) {\n throw new Error(\n \"Model must support moderation to use moderation middleware.\"\n );\n }\n\n openaiModel = resolvedModel as unknown as OpenAIModel;\n return openaiModel;\n };\n\n /**\n * Extract text content from a message.\n */\n const extractText = (message: BaseMessage): string | null => {\n if (message.content == null) {\n return null;\n }\n const text = message.text;\n return text || null;\n };\n\n /**\n * Find the last index of a message type in the messages array.\n */\n const findLastIndex = (\n messages: BaseMessage[],\n messageType: typeof AIMessage | typeof HumanMessage | typeof ToolMessage\n ): number | null => {\n for (let idx = messages.length - 1; idx >= 0; idx--) {\n if (messageType.isInstance(messages[idx])) {\n return idx;\n }\n }\n return null;\n };\n\n /**\n * Format violation message from moderation result.\n */\n const formatViolationMessage = (\n content: string,\n result: ModerationResult\n ): string => {\n // Convert categories to array of flagged category names\n const categories: string[] = [];\n const categoriesObj = result.categories as unknown as Record<\n string,\n boolean\n >;\n for (const [name, flagged] of Object.entries(categoriesObj)) {\n if (flagged) {\n categories.push(name.replace(/_/g, \" \"));\n }\n }\n\n const categoryLabel =\n categories.length > 0\n ? categories.join(\", \")\n : \"OpenAI's safety policies\";\n\n const template = violationMessage || DEFAULT_VIOLATION_TEMPLATE;\n const scoresJson = JSON.stringify(\n result.category_scores as unknown as Record<string, number>,\n null,\n 2\n );\n\n try {\n return template\n .replace(\"{categories}\", categoryLabel)\n .replace(\"{category_scores}\", scoresJson)\n .replace(\"{original_content}\", content);\n } catch {\n return template;\n }\n };\n\n function moderateContent(\n input: string | string[],\n params?: { model?: ModerationModel; options?: unknown }\n ): Promise<ModerationResponse> {\n const clientOptions = openaiModel?._getClientOptions?.();\n const moderationModel = params?.model ?? \"omni-moderation-latest\";\n const moderationRequest = {\n input,\n model: moderationModel,\n };\n return openaiModel!.client.moderations.create(\n moderationRequest,\n clientOptions\n );\n }\n\n /**\n * Apply violation handling based on exit behavior.\n */\n const applyViolation = (\n messages: BaseMessage[],\n index: number | null,\n stage: ViolationStage,\n content: string,\n result: ModerationResult\n ): MiddlewareResult<Partial<AgentBuiltInState>> | undefined => {\n const violationText = formatViolationMessage(content, result);\n\n if (exitBehavior === \"error\") {\n throw new OpenAIModerationError({\n content,\n stage,\n result,\n message: violationText,\n });\n }\n\n if (exitBehavior === \"end\") {\n return {\n jumpTo: \"end\",\n messages: [new AIMessage({ content: violationText })],\n };\n }\n\n if (index == null) {\n return undefined;\n }\n\n /**\n * Replace the original message with a new message that contains the violation text.\n */\n const newMessages = [...messages];\n const original = newMessages[index];\n const MessageConstructor = Object.getPrototypeOf(original).constructor;\n newMessages[index] = new MessageConstructor({\n ...original,\n content: violationText,\n });\n\n return { messages: newMessages };\n };\n\n /**\n * Moderate user input messages.\n */\n const moderateUserMessage = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const idx = findLastIndex(messages, HumanMessage);\n if (idx == null) {\n return null;\n }\n\n const message = messages[idx];\n const text = extractText(message);\n if (!text) {\n return null;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n return null;\n }\n\n return applyViolation(messages, idx, \"input\", text, flaggedResult);\n };\n\n /**\n * Moderate tool result messages.\n */\n const moderateToolMessages = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const lastAiIdx = findLastIndex(messages, AIMessage);\n if (lastAiIdx == null) {\n return null;\n }\n\n const working = [...messages];\n let modified = false;\n\n for (let idx = lastAiIdx + 1; idx < working.length; idx++) {\n const msg = working[idx];\n if (!ToolMessage.isInstance(msg)) {\n continue;\n }\n\n const text = extractText(msg);\n if (!text) {\n continue;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n continue;\n }\n\n const action = applyViolation(working, idx, \"tool\", text, flaggedResult);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (modified) {\n return { messages: working };\n }\n\n return null;\n };\n\n /**\n * Moderate model output messages.\n */\n const moderateOutput = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const lastAiIdx = findLastIndex(messages, AIMessage);\n if (lastAiIdx == null) {\n return null;\n }\n\n const aiMessage = messages[lastAiIdx];\n const text = extractText(aiMessage);\n if (!text) {\n return null;\n }\n\n await initModerationModel();\n const response = await moderateContent(text, {\n model: moderationModel,\n });\n const flaggedResult = response.results.find((result) => result.flagged);\n if (!flaggedResult) {\n return null;\n }\n\n return applyViolation(messages, lastAiIdx, \"output\", text, flaggedResult);\n };\n\n /**\n * Moderate inputs (user messages and tool results) before model call.\n */\n const moderateInputs = async (\n messages: BaseMessage[]\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | null> => {\n const working = [...messages];\n let modified = false;\n\n if (checkToolResults) {\n const action = await moderateToolMessages(working);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (checkInput) {\n const action = await moderateUserMessage(working);\n if (action) {\n if (\"jumpTo\" in action) {\n return action;\n }\n if (\"messages\" in action) {\n working.splice(\n 0,\n working.length,\n ...(action.messages as BaseMessage[])\n );\n modified = true;\n }\n }\n }\n\n if (modified) {\n return { messages: working };\n }\n\n return null;\n };\n\n return createMiddleware({\n name: \"OpenAIModerationMiddleware\",\n beforeModel: {\n hook: async (\n state\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | undefined> => {\n if (!checkInput && !checkToolResults) {\n return undefined;\n }\n\n const messages = state.messages || [];\n if (messages.length === 0) {\n return undefined;\n }\n\n return (await moderateInputs(messages)) ?? undefined;\n },\n canJumpTo: [\"end\"],\n },\n afterModel: {\n hook: async (\n state\n ): Promise<MiddlewareResult<Partial<AgentBuiltInState>> | undefined> => {\n if (!checkOutput) {\n return undefined;\n }\n\n const messages = state.messages || [];\n if (messages.length === 0) {\n return undefined;\n }\n\n return (await moderateOutput(messages)) ?? undefined;\n },\n canJumpTo: [\"end\"],\n },\n });\n}\n"],"mappings":";;;;;;;;;;AAkCA,SAAS,cAAc,OAAsC;AAC3D,KACE,CAAC,SACD,OAAO,UAAU,YACjB,UAAU,QACV,EAAE,YAAY,UACd,EAAE,uBAAuB,UACzB,OAAO,MAAM,sBAAsB,WAEnC,QAAO;;;;AAMT,OAAM,mBAAmB;AACzB,QACE,OAAO,MAAM,WAAW,YACxB,MAAM,WAAW,QACjB,iBAAiB,MAAM,UACvB,OAAO,MAAM,OAAO,gBAAgB,YACpC,MAAM,OAAO,gBAAgB,QAC7B,YAAY,MAAM,OAAO,eACzB,OAAO,MAAM,OAAO,YAAY,WAAW;;;;;AAY/C,MAAM,6BACJ;;;;AAgCF,IAAa,wBAAb,cAA2C,MAAM;CAC/C;CACA;CACA;CACA;CAEA,YAAY,EACV,SACA,OACA,QACA,WAMC;AACD,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,UAAU;AACf,OAAK,QAAQ;AACb,OAAK,SAAS;AACd,OAAK,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkI3B,SAAgB,2BACd,SACiB;CACjB,MAAM,EACJ,OACA,kBAAkB,0BAClB,aAAa,MACb,cAAc,MACd,mBAAmB,OACnB,eAAe,OACf,qBACE;CAEJ,IAAI;CACJ,MAAM,sBAAsB,YAAkC;AAC5D,MAAI,YACF,QAAO;EAGT,MAAM,gBACJ,OAAO,UAAU,WAAW,MAAM,cAAc,MAAM,GAAG;;;;AAK3D,MAAI,CAAC,cAAc,SAAS,CAAC,SAAS,aAAa,CACjD,OAAM,IAAI,MACR,oEAAoE,cAAc,SAAS,GAC5F;;;;AAMH,MAAI,CAAC,cAAc,cAAc,CAC/B,OAAM,IAAI,MACR,8DACD;AAGH,gBAAc;AACd,SAAO;;;;;CAMT,MAAM,eAAe,YAAwC;AAC3D,MAAI,QAAQ,WAAW,KACrB,QAAO;AAGT,SADa,QAAQ,QACN;;;;;CAMjB,MAAM,iBACJ,UACA,gBACkB;AAClB,OAAK,IAAI,MAAM,SAAS,SAAS,GAAG,OAAO,GAAG,MAC5C,KAAI,YAAY,WAAW,SAAS,KAAK,CACvC,QAAO;AAGX,SAAO;;;;;CAMT,MAAM,0BACJ,SACA,WACW;EAEX,MAAM,aAAuB,EAAE;EAC/B,MAAM,gBAAgB,OAAO;AAI7B,OAAK,MAAM,CAAC,MAAM,YAAY,OAAO,QAAQ,cAAc,CACzD,KAAI,QACF,YAAW,KAAK,KAAK,QAAQ,MAAM,IAAI,CAAC;EAI5C,MAAM,gBACJ,WAAW,SAAS,IAChB,WAAW,KAAK,KAAK,GACrB;EAEN,MAAM,WAAW,oBAAoB;EACrC,MAAM,aAAa,KAAK,UACtB,OAAO,iBACP,MACA,EACD;AAED,MAAI;AACF,UAAO,SACJ,QAAQ,gBAAgB,cAAc,CACtC,QAAQ,qBAAqB,WAAW,CACxC,QAAQ,sBAAsB,QAAQ;UACnC;AACN,UAAO;;;CAIX,SAAS,gBACP,OACA,QAC6B;EAC7B,MAAM,gBAAgB,aAAa,qBAAqB;EAExD,MAAM,oBAAoB;GACxB;GACA,OAHsB,QAAQ,SAAS;GAIxC;AACD,SAAO,YAAa,OAAO,YAAY,OACrC,mBACA,cACD;;;;;CAMH,MAAM,kBACJ,UACA,OACA,OACA,SACA,WAC6D;EAC7D,MAAM,gBAAgB,uBAAuB,SAAS,OAAO;AAE7D,MAAI,iBAAiB,QACnB,OAAM,IAAI,sBAAsB;GAC9B;GACA;GACA;GACA,SAAS;GACV,CAAC;AAGJ,MAAI,iBAAiB,MACnB,QAAO;GACL,QAAQ;GACR,UAAU,CAAC,IAAI,UAAU,EAAE,SAAS,eAAe,CAAC,CAAC;GACtD;AAGH,MAAI,SAAS,KACX;;;;EAMF,MAAM,cAAc,CAAC,GAAG,SAAS;EACjC,MAAM,WAAW,YAAY;EAC7B,MAAM,qBAAqB,OAAO,eAAe,SAAS,CAAC;AAC3D,cAAY,SAAS,IAAI,mBAAmB;GAC1C,GAAG;GACH,SAAS;GACV,CAAC;AAEF,SAAO,EAAE,UAAU,aAAa;;;;;CAMlC,MAAM,sBAAsB,OAC1B,aACiE;EACjE,MAAM,MAAM,cAAc,UAAU,aAAa;AACjD,MAAI,OAAO,KACT,QAAO;EAGT,MAAM,UAAU,SAAS;EACzB,MAAM,OAAO,YAAY,QAAQ;AACjC,MAAI,CAAC,KACH,QAAO;AAGT,QAAM,qBAAqB;EAK3B,MAAM,iBAJW,MAAM,gBAAgB,MAAM,EAC3C,OAAO,iBACR,CAAC,EAE6B,QAAQ,MAAM,WAAW,OAAO,QAAQ;AACvE,MAAI,CAAC,cACH,QAAO;AAGT,SAAO,eAAe,UAAU,KAAK,SAAS,MAAM,cAAc;;;;;CAMpE,MAAM,uBAAuB,OAC3B,aACiE;EACjE,MAAM,YAAY,cAAc,UAAU,UAAU;AACpD,MAAI,aAAa,KACf,QAAO;EAGT,MAAM,UAAU,CAAC,GAAG,SAAS;EAC7B,IAAI,WAAW;AAEf,OAAK,IAAI,MAAM,YAAY,GAAG,MAAM,QAAQ,QAAQ,OAAO;GACzD,MAAM,MAAM,QAAQ;AACpB,OAAI,CAAC,YAAY,WAAW,IAAI,CAC9B;GAGF,MAAM,OAAO,YAAY,IAAI;AAC7B,OAAI,CAAC,KACH;AAGF,SAAM,qBAAqB;GAI3B,MAAM,iBAHW,MAAM,gBAAgB,MAAM,EAC3C,OAAO,iBACR,CAAC,EAC6B,QAAQ,MAAM,WAAW,OAAO,QAAQ;AACvE,OAAI,CAAC,cACH;GAGF,MAAM,SAAS,eAAe,SAAS,KAAK,QAAQ,MAAM,cAAc;AACxE,OAAI,QAAQ;AACV,QAAI,YAAY,OACd,QAAO;AAET,QAAI,cAAc,QAAQ;AACxB,aAAQ,OACN,GACA,QAAQ,QACR,GAAI,OAAO,SACZ;AACD,gBAAW;;;;AAKjB,MAAI,SACF,QAAO,EAAE,UAAU,SAAS;AAG9B,SAAO;;;;;CAMT,MAAM,iBAAiB,OACrB,aACiE;EACjE,MAAM,YAAY,cAAc,UAAU,UAAU;AACpD,MAAI,aAAa,KACf,QAAO;EAGT,MAAM,YAAY,SAAS;EAC3B,MAAM,OAAO,YAAY,UAAU;AACnC,MAAI,CAAC,KACH,QAAO;AAGT,QAAM,qBAAqB;EAI3B,MAAM,iBAHW,MAAM,gBAAgB,MAAM,EAC3C,OAAO,iBACR,CAAC,EAC6B,QAAQ,MAAM,WAAW,OAAO,QAAQ;AACvE,MAAI,CAAC,cACH,QAAO;AAGT,SAAO,eAAe,UAAU,WAAW,UAAU,MAAM,cAAc;;;;;CAM3E,MAAM,iBAAiB,OACrB,aACiE;EACjE,MAAM,UAAU,CAAC,GAAG,SAAS;EAC7B,IAAI,WAAW;AAEf,MAAI,kBAAkB;GACpB,MAAM,SAAS,MAAM,qBAAqB,QAAQ;AAClD,OAAI,QAAQ;AACV,QAAI,YAAY,OACd,QAAO;AAET,QAAI,cAAc,QAAQ;AACxB,aAAQ,OACN,GACA,QAAQ,QACR,GAAI,OAAO,SACZ;AACD,gBAAW;;;;AAKjB,MAAI,YAAY;GACd,MAAM,SAAS,MAAM,oBAAoB,QAAQ;AACjD,OAAI,QAAQ;AACV,QAAI,YAAY,OACd,QAAO;AAET,QAAI,cAAc,QAAQ;AACxB,aAAQ,OACN,GACA,QAAQ,QACR,GAAI,OAAO,SACZ;AACD,gBAAW;;;;AAKjB,MAAI,SACF,QAAO,EAAE,UAAU,SAAS;AAG9B,SAAO;;AAGT,QAAO,iBAAiB;EACtB,MAAM;EACN,aAAa;GACX,MAAM,OACJ,UACsE;AACtE,QAAI,CAAC,cAAc,CAAC,iBAClB;IAGF,MAAM,WAAW,MAAM,YAAY,EAAE;AACrC,QAAI,SAAS,WAAW,EACtB;AAGF,WAAQ,MAAM,eAAe,SAAS,IAAK;;GAE7C,WAAW,CAAC,MAAM;GACnB;EACD,YAAY;GACV,MAAM,OACJ,UACsE;AACtE,QAAI,CAAC,YACH;IAGF,MAAM,WAAW,MAAM,YAAY,EAAE;AACrC,QAAI,SAAS,WAAW,EACtB;AAGF,WAAQ,MAAM,eAAe,SAAS,IAAK;;GAE7C,WAAW,CAAC,MAAM;GACnB;EACF,CAAC"}
@@ -1,16 +1,16 @@
1
- const require_rolldown_runtime = require('../../_virtual/rolldown_runtime.cjs');
1
+ const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
2
2
  const require_chat_models_universal = require('../../chat_models/universal.cjs');
3
3
  const require_utils = require('../utils.cjs');
4
4
  const require_utils$1 = require('./utils.cjs');
5
5
  const require_middleware = require('../middleware.cjs');
6
- const __langchain_core_messages = require_rolldown_runtime.__toESM(require("@langchain/core/messages"));
7
- const __langchain_core_runnables = require_rolldown_runtime.__toESM(require("@langchain/core/runnables"));
8
- const __langchain_langgraph = require_rolldown_runtime.__toESM(require("@langchain/langgraph"));
9
- const __langchain_core_utils_types = require_rolldown_runtime.__toESM(require("@langchain/core/utils/types"));
10
- const zod_v4 = require_rolldown_runtime.__toESM(require("zod/v4"));
11
- const zod_v3 = require_rolldown_runtime.__toESM(require("zod/v3"));
12
- const uuid = require_rolldown_runtime.__toESM(require("uuid"));
13
- const __langchain_core_language_models_base = require_rolldown_runtime.__toESM(require("@langchain/core/language_models/base"));
6
+ let _langchain_core_messages = require("@langchain/core/messages");
7
+ let _langchain_core_runnables = require("@langchain/core/runnables");
8
+ let _langchain_langgraph = require("@langchain/langgraph");
9
+ let _langchain_core_utils_types = require("@langchain/core/utils/types");
10
+ let zod_v4 = require("zod/v4");
11
+ let zod_v3 = require("zod/v3");
12
+ let uuid = require("uuid");
13
+ let _langchain_core_language_models_base = require("@langchain/core/language_models/base");
14
14
 
15
15
  //#region src/agents/middleware/summarization.ts
16
16
  const DEFAULT_SUMMARY_PROMPT = `<role>
@@ -51,24 +51,22 @@ const contextSizeSchema = zod_v3.z.object({
51
51
  tokens: zod_v3.z.number().positive("Tokens must be greater than 0").optional(),
52
52
  messages: zod_v3.z.number().int("Messages must be an integer").positive("Messages must be greater than 0").optional()
53
53
  }).refine((data) => {
54
- const count = [
54
+ return [
55
55
  data.fraction,
56
56
  data.tokens,
57
57
  data.messages
58
- ].filter((v) => v !== void 0).length;
59
- return count >= 1;
58
+ ].filter((v) => v !== void 0).length >= 1;
60
59
  }, { message: "At least one of fraction, tokens, or messages must be provided" });
61
60
  const keepSchema = zod_v3.z.object({
62
61
  fraction: zod_v3.z.number().min(0, "Messages must be non-negative").max(1, "Fraction must be less than or equal to 1").optional(),
63
62
  tokens: zod_v3.z.number().min(0, "Tokens must be greater than or equal to 0").optional(),
64
63
  messages: zod_v3.z.number().int("Messages must be an integer").min(0, "Messages must be non-negative").optional()
65
64
  }).refine((data) => {
66
- const count = [
65
+ return [
67
66
  data.fraction,
68
67
  data.tokens,
69
68
  data.messages
70
- ].filter((v) => v !== void 0).length;
71
- return count === 1;
69
+ ].filter((v) => v !== void 0).length === 1;
72
70
  }, { message: "Exactly one of fraction, tokens, or messages must be provided" });
73
71
  const contextSchema = zod_v3.z.object({
74
72
  model: zod_v3.z.custom(),
@@ -86,9 +84,8 @@ const contextSchema = zod_v3.z.object({
86
84
  */
87
85
  function getProfileLimits(input) {
88
86
  if ("profile" in input && typeof input.profile === "object" && input.profile && "maxInputTokens" in input.profile && (typeof input.profile.maxInputTokens === "number" || input.profile.maxInputTokens == null)) return input.profile.maxInputTokens ?? void 0;
89
- if ("model" in input && typeof input.model === "string") return (0, __langchain_core_language_models_base.getModelContextSize)(input.model);
90
- if ("modelName" in input && typeof input.modelName === "string") return (0, __langchain_core_language_models_base.getModelContextSize)(input.modelName);
91
- return void 0;
87
+ if ("model" in input && typeof input.model === "string") return (0, _langchain_core_language_models_base.getModelContextSize)(input.model);
88
+ if ("modelName" in input && typeof input.modelName === "string") return (0, _langchain_core_language_models_base.getModelContextSize)(input.modelName);
92
89
  }
93
90
  /**
94
91
  * Summarization middleware that automatically summarizes conversation history when token limits are approached.
@@ -140,7 +137,7 @@ function summarizationMiddleware(options) {
140
137
  /**
141
138
  * Parse user options to get their explicit values
142
139
  */
143
- const { data: userOptions, error } = (0, __langchain_core_utils_types.interopSafeParse)(contextSchema, options);
140
+ const { data: userOptions, error } = (0, _langchain_core_utils_types.interopSafeParse)(contextSchema, options);
144
141
  if (error) throw new Error(`Invalid summarization middleware options: ${zod_v4.z.prettifyError(error)}`);
145
142
  return require_middleware.createMiddleware({
146
143
  name: "SummarizationMiddleware",
@@ -198,20 +195,18 @@ function summarizationMiddleware(options) {
198
195
  ensureMessageIds(state.messages);
199
196
  const tokenCounter = runtime.context?.tokenCounter !== void 0 ? runtime.context.tokenCounter : userOptions.tokenCounter ?? require_utils$1.countTokensApproximately;
200
197
  const totalTokens = await tokenCounter(state.messages);
201
- const doSummarize = await shouldSummarize(state.messages, totalTokens, triggerConditions, model);
202
- if (!doSummarize) return;
198
+ if (!await shouldSummarize(state.messages, totalTokens, triggerConditions, model)) return;
203
199
  const { systemPrompt, conversationMessages } = splitSystemMessage(state.messages);
204
200
  const cutoffIndex = await determineCutoffIndex(conversationMessages, validatedKeep, tokenCounter, model);
205
201
  if (cutoffIndex <= 0) return;
206
202
  const { messagesToSummarize, preservedMessages } = partitionMessages(systemPrompt, conversationMessages, cutoffIndex);
207
- const summary = await createSummary(messagesToSummarize, model, summaryPrompt, tokenCounter, trimTokensToSummarize, runtime);
208
- const summaryMessage = new __langchain_core_messages.HumanMessage({
209
- content: `${summaryPrefix}\n\n${summary}`,
203
+ const summaryMessage = new _langchain_core_messages.HumanMessage({
204
+ content: `${summaryPrefix}\n\n${await createSummary(messagesToSummarize, model, summaryPrompt, tokenCounter, trimTokensToSummarize, runtime)}`,
210
205
  id: (0, uuid.v4)(),
211
206
  additional_kwargs: { lc_source: "summarization" }
212
207
  });
213
208
  return { messages: [
214
- new __langchain_core_messages.RemoveMessage({ id: __langchain_langgraph.REMOVE_ALL_MESSAGES }),
209
+ new _langchain_core_messages.RemoveMessage({ id: _langchain_langgraph.REMOVE_ALL_MESSAGES }),
215
210
  summaryMessage,
216
211
  ...preservedMessages
217
212
  ] };
@@ -228,7 +223,7 @@ function ensureMessageIds(messages) {
228
223
  * Separate system message from conversation messages
229
224
  */
230
225
  function splitSystemMessage(messages) {
231
- if (messages.length > 0 && __langchain_core_messages.SystemMessage.isInstance(messages[0])) return {
226
+ if (messages.length > 0 && _langchain_core_messages.SystemMessage.isInstance(messages[0])) return {
232
227
  systemPrompt: messages[0],
233
228
  conversationMessages: messages.slice(1)
234
229
  };
@@ -279,8 +274,7 @@ async function shouldSummarize(messages, totalTokens, triggerConditions, model)
279
274
  hasAnyProperty = true;
280
275
  const maxInputTokens = getProfileLimits(model);
281
276
  if (typeof maxInputTokens === "number") {
282
- const threshold = Math.floor(maxInputTokens * trigger.fraction);
283
- if (totalTokens < threshold) conditionMet = false;
277
+ if (totalTokens < Math.floor(maxInputTokens * trigger.fraction)) conditionMet = false;
284
278
  } else
285
279
  /**
286
280
  * If fraction is specified but we can't get model limits, skip this condition
@@ -324,8 +318,7 @@ async function findTokenBasedCutoff(messages, keep, tokenCounter, model) {
324
318
  } else if ("tokens" in keep && keep.tokens !== void 0) targetTokenCount = Math.floor(keep.tokens);
325
319
  else return;
326
320
  if (targetTokenCount <= 0) targetTokenCount = 1;
327
- const totalTokens = await tokenCounter(messages);
328
- if (totalTokens <= targetTokenCount) return 0;
321
+ if (await tokenCounter(messages) <= targetTokenCount) return 0;
329
322
  /**
330
323
  * Use binary search to identify the earliest message index that keeps the
331
324
  * suffix within the token budget.
@@ -337,8 +330,7 @@ async function findTokenBasedCutoff(messages, keep, tokenCounter, model) {
337
330
  for (let i = 0; i < maxIterations; i++) {
338
331
  if (left >= right) break;
339
332
  const mid = Math.floor((left + right) / 2);
340
- const suffixTokens = await tokenCounter(messages.slice(mid));
341
- if (suffixTokens <= targetTokenCount) {
333
+ if (await tokenCounter(messages.slice(mid)) <= targetTokenCount) {
342
334
  cutoffCandidate = mid;
343
335
  right = mid;
344
336
  } else left = mid + 1;
@@ -394,7 +386,7 @@ function isSafeCutoffPoint(messages, cutoffIndex) {
394
386
  /**
395
387
  * Prevent preserved messages from starting with AI message containing tool calls
396
388
  */
397
- if (cutoffIndex < messages.length && __langchain_core_messages.AIMessage.isInstance(messages[cutoffIndex]) && require_utils.hasToolCalls(messages[cutoffIndex])) return false;
389
+ if (cutoffIndex < messages.length && _langchain_core_messages.AIMessage.isInstance(messages[cutoffIndex]) && require_utils.hasToolCalls(messages[cutoffIndex])) return false;
398
390
  const searchStart = Math.max(0, cutoffIndex - SEARCH_RANGE_FOR_TOOL_PAIRS);
399
391
  const searchEnd = Math.min(messages.length, cutoffIndex + SEARCH_RANGE_FOR_TOOL_PAIRS);
400
392
  for (let i = searchStart; i < searchEnd; i++) {
@@ -426,17 +418,17 @@ function extractToolCallIds(aiMessage) {
426
418
  * `AIMessage` is found (edge case).
427
419
  */
428
420
  function findSafeCutoffPoint(messages, cutoffIndex) {
429
- if (cutoffIndex >= messages.length || !__langchain_core_messages.ToolMessage.isInstance(messages[cutoffIndex])) return cutoffIndex;
421
+ if (cutoffIndex >= messages.length || !_langchain_core_messages.ToolMessage.isInstance(messages[cutoffIndex])) return cutoffIndex;
430
422
  const toolCallIds = /* @__PURE__ */ new Set();
431
423
  let idx = cutoffIndex;
432
- while (idx < messages.length && __langchain_core_messages.ToolMessage.isInstance(messages[idx])) {
424
+ while (idx < messages.length && _langchain_core_messages.ToolMessage.isInstance(messages[idx])) {
433
425
  const toolMsg = messages[idx];
434
426
  if (toolMsg.tool_call_id) toolCallIds.add(toolMsg.tool_call_id);
435
427
  idx++;
436
428
  }
437
429
  for (let i = cutoffIndex - 1; i >= 0; i--) {
438
430
  const msg = messages[i];
439
- if (__langchain_core_messages.AIMessage.isInstance(msg) && require_utils.hasToolCalls(msg)) {
431
+ if (_langchain_core_messages.AIMessage.isInstance(msg) && require_utils.hasToolCalls(msg)) {
440
432
  const aiToolCallIds = extractToolCallIds(msg);
441
433
  for (const id of toolCallIds) if (aiToolCallIds.has(id)) return i;
442
434
  }
@@ -449,10 +441,8 @@ function findSafeCutoffPoint(messages, cutoffIndex) {
449
441
  function cutoffSeparatesToolPair(messages, aiMessageIndex, cutoffIndex, toolCallIds) {
450
442
  for (let j = aiMessageIndex + 1; j < messages.length; j++) {
451
443
  const message = messages[j];
452
- if (__langchain_core_messages.ToolMessage.isInstance(message) && toolCallIds.has(message.tool_call_id)) {
453
- const aiBeforeCutoff = aiMessageIndex < cutoffIndex;
454
- const toolBeforeCutoff = j < cutoffIndex;
455
- if (aiBeforeCutoff !== toolBeforeCutoff) return true;
444
+ if (_langchain_core_messages.ToolMessage.isInstance(message) && toolCallIds.has(message.tool_call_id)) {
445
+ if (aiMessageIndex < cutoffIndex !== j < cutoffIndex) return true;
456
446
  }
457
447
  }
458
448
  return false;
@@ -482,33 +472,20 @@ async function createSummary(messagesToSummarize, model, summaryPrompt, tokenCou
482
472
  * Tool: 72°F and sunny
483
473
  * ```
484
474
  */
485
- const formattedMessages = (0, __langchain_core_messages.getBufferString)(trimmedMessages);
475
+ const formattedMessages = (0, _langchain_core_messages.getBufferString)(trimmedMessages);
486
476
  try {
487
477
  const formattedPrompt = summaryPrompt.replace("{messages}", formattedMessages);
488
- /**
489
- * Merge parent runnable config with summarization metadata so LangGraph's
490
- * stream handlers (and other callback-based consumers) can properly track
491
- * and tag the summarization model call.
492
- */
493
- const baseConfig = (0, __langchain_core_runnables.pickRunnableConfigKeys)(runtime) ?? {};
494
- const config = (0, __langchain_core_runnables.mergeConfigs)(baseConfig, { metadata: { lc_source: "summarization" } });
495
- const response = await model.invoke(formattedPrompt, config);
496
- const content = response.content;
478
+ const config = (0, _langchain_core_runnables.mergeConfigs)((0, _langchain_core_runnables.pickRunnableConfigKeys)(runtime) ?? {}, { metadata: { lc_source: "summarization" } });
479
+ const content = (await model.invoke(formattedPrompt, config)).content;
497
480
  /**
498
481
  * Handle both string content and MessageContent array
499
482
  */
500
483
  if (typeof content === "string") return content.trim();
501
- else if (Array.isArray(content)) {
502
- /**
503
- * Extract text from MessageContent array
504
- */
505
- const textContent = content.map((item) => {
506
- if (typeof item === "string") return item;
507
- if (typeof item === "object" && item !== null && "text" in item) return item.text;
508
- return "";
509
- }).join("");
510
- return textContent.trim();
511
- }
484
+ else if (Array.isArray(content)) return content.map((item) => {
485
+ if (typeof item === "string") return item;
486
+ if (typeof item === "object" && item !== null && "text" in item) return item.text;
487
+ return "";
488
+ }).join("").trim();
512
489
  return "Error generating summary: Invalid response format";
513
490
  } catch (e) {
514
491
  return `Error generating summary: ${e}`;
@@ -520,7 +497,7 @@ async function createSummary(messagesToSummarize, model, summaryPrompt, tokenCou
520
497
  async function trimMessagesForSummary(messages, tokenCounter, trimTokensToSummarize) {
521
498
  if (trimTokensToSummarize === void 0) return messages;
522
499
  try {
523
- return await (0, __langchain_core_messages.trimMessages)(messages, {
500
+ return await (0, _langchain_core_messages.trimMessages)(messages, {
524
501
  maxTokens: trimTokensToSummarize,
525
502
  tokenCounter: async (msgs) => tokenCounter(msgs),
526
503
  strategy: "last",