@langchain/core 0.2.18 → 0.2.20

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 (155) hide show
  1. package/dist/callbacks/manager.cjs +94 -19
  2. package/dist/callbacks/manager.d.ts +3 -1
  3. package/dist/callbacks/manager.js +94 -19
  4. package/dist/language_models/base.d.ts +0 -10
  5. package/dist/language_models/chat_models.cjs +5 -6
  6. package/dist/language_models/chat_models.d.ts +9 -10
  7. package/dist/language_models/chat_models.js +5 -6
  8. package/dist/language_models/llms.cjs +5 -6
  9. package/dist/language_models/llms.d.ts +10 -12
  10. package/dist/language_models/llms.js +5 -6
  11. package/dist/messages/base.cjs +16 -1
  12. package/dist/messages/base.d.ts +9 -0
  13. package/dist/messages/base.js +14 -0
  14. package/dist/messages/tool.cjs +23 -0
  15. package/dist/messages/tool.d.ts +15 -0
  16. package/dist/messages/tool.js +24 -1
  17. package/dist/messages/utils.cjs +1 -1
  18. package/dist/messages/utils.js +1 -1
  19. package/dist/output_parsers/string.cjs +1 -0
  20. package/dist/output_parsers/string.js +1 -0
  21. package/dist/runnables/base.cjs +35 -12
  22. package/dist/runnables/base.js +35 -12
  23. package/dist/runnables/config.cjs +41 -0
  24. package/dist/runnables/config.js +41 -0
  25. package/dist/runnables/remote.cjs +17 -14
  26. package/dist/runnables/remote.js +17 -14
  27. package/dist/runnables/types.d.ts +10 -0
  28. package/dist/tools/index.cjs +15 -6
  29. package/dist/tools/index.d.ts +21 -12
  30. package/dist/tools/index.js +15 -6
  31. package/dist/utils/math.cjs +6 -4
  32. package/dist/utils/math.js +6 -4
  33. package/dist/utils/ml-distance/distances.cjs +18 -0
  34. package/dist/utils/ml-distance/distances.d.ts +8 -0
  35. package/dist/utils/ml-distance/distances.js +14 -0
  36. package/dist/utils/ml-distance/similarities.cjs +21 -0
  37. package/dist/utils/ml-distance/similarities.d.ts +7 -0
  38. package/dist/utils/ml-distance/similarities.js +17 -0
  39. package/dist/utils/ml-distance-euclidean/euclidean.cjs +15 -0
  40. package/dist/utils/ml-distance-euclidean/euclidean.d.ts +2 -0
  41. package/dist/utils/ml-distance-euclidean/euclidean.js +10 -0
  42. package/dist/utils/signal.cjs +28 -0
  43. package/dist/utils/signal.d.ts +1 -0
  44. package/dist/utils/signal.js +24 -0
  45. package/dist/utils/stream.cjs +19 -4
  46. package/dist/utils/stream.d.ts +3 -1
  47. package/dist/utils/stream.js +19 -4
  48. package/dist/utils/testing/index.cjs +168 -4
  49. package/dist/utils/testing/index.d.ts +100 -6
  50. package/dist/utils/testing/index.js +167 -4
  51. package/package.json +4 -4
  52. package/dist/caches/tests/in_memory_cache.test.d.ts +0 -1
  53. package/dist/caches/tests/in_memory_cache.test.js +0 -33
  54. package/dist/callbacks/tests/callbacks.test.d.ts +0 -1
  55. package/dist/callbacks/tests/callbacks.test.js +0 -495
  56. package/dist/callbacks/tests/manager.int.test.d.ts +0 -1
  57. package/dist/callbacks/tests/manager.int.test.js +0 -29
  58. package/dist/callbacks/tests/run_collector.test.d.ts +0 -1
  59. package/dist/callbacks/tests/run_collector.test.js +0 -58
  60. package/dist/language_models/tests/chat_models.test.d.ts +0 -1
  61. package/dist/language_models/tests/chat_models.test.js +0 -204
  62. package/dist/language_models/tests/count_tokens.test.d.ts +0 -1
  63. package/dist/language_models/tests/count_tokens.test.js +0 -19
  64. package/dist/language_models/tests/llms.test.d.ts +0 -1
  65. package/dist/language_models/tests/llms.test.js +0 -52
  66. package/dist/messages/tests/base_message.test.d.ts +0 -1
  67. package/dist/messages/tests/base_message.test.js +0 -245
  68. package/dist/messages/tests/message_utils.test.d.ts +0 -1
  69. package/dist/messages/tests/message_utils.test.js +0 -434
  70. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +0 -1
  71. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +0 -81
  72. package/dist/output_parsers/tests/json.test.d.ts +0 -1
  73. package/dist/output_parsers/tests/json.test.js +0 -427
  74. package/dist/output_parsers/tests/output_parser.test.d.ts +0 -1
  75. package/dist/output_parsers/tests/output_parser.test.js +0 -78
  76. package/dist/output_parsers/tests/string.test.d.ts +0 -1
  77. package/dist/output_parsers/tests/string.test.js +0 -68
  78. package/dist/output_parsers/tests/structured.test.d.ts +0 -1
  79. package/dist/output_parsers/tests/structured.test.js +0 -166
  80. package/dist/output_parsers/tests/xml.test.d.ts +0 -1
  81. package/dist/output_parsers/tests/xml.test.js +0 -81
  82. package/dist/prompts/tests/chat.mustache.test.d.ts +0 -1
  83. package/dist/prompts/tests/chat.mustache.test.js +0 -129
  84. package/dist/prompts/tests/chat.test.d.ts +0 -1
  85. package/dist/prompts/tests/chat.test.js +0 -557
  86. package/dist/prompts/tests/few_shot.test.d.ts +0 -1
  87. package/dist/prompts/tests/few_shot.test.js +0 -224
  88. package/dist/prompts/tests/pipeline.test.d.ts +0 -1
  89. package/dist/prompts/tests/pipeline.test.js +0 -101
  90. package/dist/prompts/tests/prompt.mustache.test.d.ts +0 -1
  91. package/dist/prompts/tests/prompt.mustache.test.js +0 -105
  92. package/dist/prompts/tests/prompt.test.d.ts +0 -1
  93. package/dist/prompts/tests/prompt.test.js +0 -78
  94. package/dist/prompts/tests/structured.test.d.ts +0 -1
  95. package/dist/prompts/tests/structured.test.js +0 -37
  96. package/dist/prompts/tests/template.test.d.ts +0 -1
  97. package/dist/prompts/tests/template.test.js +0 -24
  98. package/dist/runnables/tests/runnable.test.d.ts +0 -1
  99. package/dist/runnables/tests/runnable.test.js +0 -491
  100. package/dist/runnables/tests/runnable_binding.test.d.ts +0 -1
  101. package/dist/runnables/tests/runnable_binding.test.js +0 -46
  102. package/dist/runnables/tests/runnable_branch.test.d.ts +0 -1
  103. package/dist/runnables/tests/runnable_branch.test.js +0 -116
  104. package/dist/runnables/tests/runnable_graph.test.d.ts +0 -1
  105. package/dist/runnables/tests/runnable_graph.test.js +0 -100
  106. package/dist/runnables/tests/runnable_history.test.d.ts +0 -1
  107. package/dist/runnables/tests/runnable_history.test.js +0 -177
  108. package/dist/runnables/tests/runnable_interface.test.d.ts +0 -1
  109. package/dist/runnables/tests/runnable_interface.test.js +0 -209
  110. package/dist/runnables/tests/runnable_map.test.d.ts +0 -1
  111. package/dist/runnables/tests/runnable_map.test.js +0 -238
  112. package/dist/runnables/tests/runnable_passthrough.test.d.ts +0 -1
  113. package/dist/runnables/tests/runnable_passthrough.test.js +0 -96
  114. package/dist/runnables/tests/runnable_remote.int.test.d.ts +0 -1
  115. package/dist/runnables/tests/runnable_remote.int.test.js +0 -138
  116. package/dist/runnables/tests/runnable_remote.test.d.ts +0 -1
  117. package/dist/runnables/tests/runnable_remote.test.js +0 -200
  118. package/dist/runnables/tests/runnable_retry.test.d.ts +0 -1
  119. package/dist/runnables/tests/runnable_retry.test.js +0 -125
  120. package/dist/runnables/tests/runnable_stream_events.test.d.ts +0 -1
  121. package/dist/runnables/tests/runnable_stream_events.test.js +0 -1013
  122. package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +0 -1
  123. package/dist/runnables/tests/runnable_stream_events_v2.test.js +0 -2022
  124. package/dist/runnables/tests/runnable_stream_log.test.d.ts +0 -1
  125. package/dist/runnables/tests/runnable_stream_log.test.js +0 -71
  126. package/dist/runnables/tests/runnable_tools.test.d.ts +0 -1
  127. package/dist/runnables/tests/runnable_tools.test.js +0 -149
  128. package/dist/runnables/tests/runnable_tracing.int.test.d.ts +0 -1
  129. package/dist/runnables/tests/runnable_tracing.int.test.js +0 -37
  130. package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +0 -1
  131. package/dist/runnables/tests/runnable_with_fallbacks.test.js +0 -36
  132. package/dist/singletons/tests/async_local_storage.test.d.ts +0 -1
  133. package/dist/singletons/tests/async_local_storage.test.js +0 -153
  134. package/dist/structured_query/tests/utils.test.d.ts +0 -1
  135. package/dist/structured_query/tests/utils.test.js +0 -47
  136. package/dist/tools/tests/tools.test.d.ts +0 -1
  137. package/dist/tools/tests/tools.test.js +0 -85
  138. package/dist/tracers/tests/langchain_tracer.int.test.d.ts +0 -1
  139. package/dist/tracers/tests/langchain_tracer.int.test.js +0 -74
  140. package/dist/tracers/tests/langsmith_interop.test.d.ts +0 -1
  141. package/dist/tracers/tests/langsmith_interop.test.js +0 -551
  142. package/dist/tracers/tests/tracer.test.d.ts +0 -1
  143. package/dist/tracers/tests/tracer.test.js +0 -378
  144. package/dist/utils/testing/tests/chatfake.test.d.ts +0 -1
  145. package/dist/utils/testing/tests/chatfake.test.js +0 -112
  146. package/dist/utils/tests/async_caller.test.d.ts +0 -1
  147. package/dist/utils/tests/async_caller.test.js +0 -27
  148. package/dist/utils/tests/enviroment.test.d.ts +0 -1
  149. package/dist/utils/tests/enviroment.test.js +0 -6
  150. package/dist/utils/tests/function_calling.test.d.ts +0 -1
  151. package/dist/utils/tests/function_calling.test.js +0 -107
  152. package/dist/utils/tests/math_utils.test.d.ts +0 -1
  153. package/dist/utils/tests/math_utils.test.js +0 -139
  154. package/dist/utils/tests/polyfill_stream.test.d.ts +0 -1
  155. package/dist/utils/tests/polyfill_stream.test.js +0 -15
@@ -6,6 +6,7 @@ import { LogStreamCallbackHandler, RunLog, RunLogPatch, isLogStreamHandler, } fr
6
6
  import { EventStreamCallbackHandler, isStreamEventsHandler, } from "../tracers/event_stream.js";
7
7
  import { Serializable } from "../load/serializable.js";
8
8
  import { IterableReadableStream, concat, atee, pipeGeneratorWithSetup, AsyncGeneratorWithSetup, } from "../utils/stream.js";
9
+ import { raceWithSignal } from "../utils/signal.js";
9
10
  import { DEFAULT_RECURSION_LIMIT, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, } from "./config.js";
10
11
  import { AsyncCaller } from "../utils/async_caller.js";
11
12
  import { RootListenersTracer } from "../tracers/root_listener.js";
@@ -187,6 +188,8 @@ export class Runnable extends Serializable {
187
188
  recursionLimit: options.recursionLimit,
188
189
  maxConcurrency: options.maxConcurrency,
189
190
  runId: options.runId,
191
+ timeout: options.timeout,
192
+ signal: options.signal,
190
193
  });
191
194
  }
192
195
  const callOptions = { ...options };
@@ -198,6 +201,8 @@ export class Runnable extends Serializable {
198
201
  delete callOptions.recursionLimit;
199
202
  delete callOptions.maxConcurrency;
200
203
  delete callOptions.runId;
204
+ delete callOptions.timeout;
205
+ delete callOptions.signal;
201
206
  return [runnableConfig, callOptions];
202
207
  }
203
208
  async _callWithConfig(func, input, options) {
@@ -207,7 +212,8 @@ export class Runnable extends Serializable {
207
212
  delete config.runId;
208
213
  let output;
209
214
  try {
210
- output = await func.call(this, input, config, runManager);
215
+ const promise = func.call(this, input, config, runManager);
216
+ output = await raceWithSignal(promise, options?.signal);
211
217
  }
212
218
  catch (e) {
213
219
  await runManager?.handleChainError(e);
@@ -235,7 +241,8 @@ export class Runnable extends Serializable {
235
241
  }));
236
242
  let outputs;
237
243
  try {
238
- outputs = await func.call(this, inputs, optionsList, runManagers, batchOptions);
244
+ const promise = func.call(this, inputs, optionsList, runManagers, batchOptions);
245
+ outputs = await raceWithSignal(promise, optionsList?.[0]?.signal);
239
246
  }
240
247
  catch (e) {
241
248
  await Promise.all(runManagers.map((runManager) => runManager?.handleChainError(e)));
@@ -278,7 +285,7 @@ export class Runnable extends Serializable {
278
285
  }
279
286
  let runManager;
280
287
  try {
281
- const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, undefined, undefined, config.runName ?? this.getName()), config);
288
+ const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, undefined, undefined, config.runName ?? this.getName()), options?.signal, config);
282
289
  delete config.runId;
283
290
  runManager = pipe.setup;
284
291
  const streamEventsHandler = runManager?.handlers.find(isStreamEventsHandler);
@@ -826,9 +833,7 @@ export class RunnableBinding extends Runnable {
826
833
  async stream(input, options) {
827
834
  return this.bound.stream(input, await this._mergeConfig(ensureConfig(options), this.kwargs));
828
835
  }
829
- async *transform(
830
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
831
- generator, options) {
836
+ async *transform(generator, options) {
832
837
  yield* this.bound.transform(generator, await this._mergeConfig(ensureConfig(options), this.kwargs));
833
838
  }
834
839
  streamEvents(input, options, streamOptions) {
@@ -1132,11 +1137,15 @@ export class RunnableSequence extends Runnable {
1132
1137
  const initialSteps = [this.first, ...this.middle];
1133
1138
  for (let i = 0; i < initialSteps.length; i += 1) {
1134
1139
  const step = initialSteps[i];
1135
- nextStepInput = await step.invoke(nextStepInput, patchConfig(config, {
1140
+ const promise = step.invoke(nextStepInput, patchConfig(config, {
1136
1141
  callbacks: runManager?.getChild(`seq:step:${i + 1}`),
1137
1142
  }));
1143
+ nextStepInput = await raceWithSignal(promise, options?.signal);
1138
1144
  }
1139
1145
  // TypeScript can't detect that the last output of the sequence returns RunOutput, so call it out of the loop here
1146
+ if (options?.signal?.aborted) {
1147
+ throw new Error("Aborted");
1148
+ }
1140
1149
  finalOutput = await this.last.invoke(nextStepInput, patchConfig(config, {
1141
1150
  callbacks: runManager?.getChild(`seq:step:${this.steps.length}`),
1142
1151
  }));
@@ -1161,10 +1170,11 @@ export class RunnableSequence extends Runnable {
1161
1170
  try {
1162
1171
  for (let i = 0; i < this.steps.length; i += 1) {
1163
1172
  const step = this.steps[i];
1164
- nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => {
1173
+ const promise = step.batch(nextStepInputs, runManagers.map((runManager, j) => {
1165
1174
  const childRunManager = runManager?.getChild(`seq:step:${i + 1}`);
1166
1175
  return patchConfig(configList[j], { callbacks: childRunManager });
1167
1176
  }), batchOptions);
1177
+ nextStepInputs = await raceWithSignal(promise, configList[0]?.signal);
1168
1178
  }
1169
1179
  }
1170
1180
  catch (e) {
@@ -1195,6 +1205,7 @@ export class RunnableSequence extends Runnable {
1195
1205
  }));
1196
1206
  }
1197
1207
  for await (const chunk of finalGenerator) {
1208
+ options?.signal?.throwIfAborted();
1198
1209
  yield chunk;
1199
1210
  if (concatSupported) {
1200
1211
  if (finalOutput === undefined) {
@@ -1340,11 +1351,12 @@ export class RunnableMap extends Runnable {
1340
1351
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1341
1352
  const output = {};
1342
1353
  try {
1343
- await Promise.all(Object.entries(this.steps).map(async ([key, runnable]) => {
1354
+ const promises = Object.entries(this.steps).map(async ([key, runnable]) => {
1344
1355
  output[key] = await runnable.invoke(input, patchConfig(config, {
1345
1356
  callbacks: runManager?.getChild(`map:key:${key}`),
1346
1357
  }));
1347
- }));
1358
+ });
1359
+ await raceWithSignal(Promise.all(promises), options?.signal);
1348
1360
  }
1349
1361
  catch (e) {
1350
1362
  await runManager?.handleChainError(e);
@@ -1369,7 +1381,8 @@ export class RunnableMap extends Runnable {
1369
1381
  // starting new iterations as needed,
1370
1382
  // until all iterators are done
1371
1383
  while (tasks.size) {
1372
- const { key, result, gen } = await Promise.race(tasks.values());
1384
+ const promise = Promise.race(tasks.values());
1385
+ const { key, result, gen } = await raceWithSignal(promise, options?.signal);
1373
1386
  tasks.delete(key);
1374
1387
  if (!result.done) {
1375
1388
  yield { [key]: result.value };
@@ -1425,18 +1438,22 @@ export class RunnableTraceable extends Runnable {
1425
1438
  async invoke(input, options) {
1426
1439
  const [config] = this._getOptionsList(options ?? {}, 1);
1427
1440
  const callbacks = await getCallbackManagerForConfig(config);
1428
- return (await this.func(patchConfig(config, { callbacks }), input));
1441
+ const promise = this.func(patchConfig(config, { callbacks }), input);
1442
+ return raceWithSignal(promise, config?.signal);
1429
1443
  }
1430
1444
  async *_streamIterator(input, options) {
1445
+ const [config] = this._getOptionsList(options ?? {}, 1);
1431
1446
  const result = await this.invoke(input, options);
1432
1447
  if (isAsyncIterable(result)) {
1433
1448
  for await (const item of result) {
1449
+ config?.signal?.throwIfAborted();
1434
1450
  yield item;
1435
1451
  }
1436
1452
  return;
1437
1453
  }
1438
1454
  if (isIterator(result)) {
1439
1455
  while (true) {
1456
+ config?.signal?.throwIfAborted();
1440
1457
  const state = result.next();
1441
1458
  if (state.done)
1442
1459
  break;
@@ -1512,6 +1529,7 @@ export class RunnableLambda extends Runnable {
1512
1529
  else if (isAsyncIterable(output)) {
1513
1530
  let finalOutput;
1514
1531
  for await (const chunk of consumeAsyncIterableInContext(childConfig, output)) {
1532
+ config?.signal?.throwIfAborted();
1515
1533
  if (finalOutput === undefined) {
1516
1534
  finalOutput = chunk;
1517
1535
  }
@@ -1531,6 +1549,7 @@ export class RunnableLambda extends Runnable {
1531
1549
  else if (isIterableIterator(output)) {
1532
1550
  let finalOutput;
1533
1551
  for (const chunk of consumeIteratorInContext(childConfig, output)) {
1552
+ config?.signal?.throwIfAborted();
1534
1553
  if (finalOutput === undefined) {
1535
1554
  finalOutput = chunk;
1536
1555
  }
@@ -1604,11 +1623,13 @@ export class RunnableLambda extends Runnable {
1604
1623
  }
1605
1624
  else if (isAsyncIterable(output)) {
1606
1625
  for await (const chunk of consumeAsyncIterableInContext(childConfig, output)) {
1626
+ config?.signal?.throwIfAborted();
1607
1627
  yield chunk;
1608
1628
  }
1609
1629
  }
1610
1630
  else if (isIterableIterator(output)) {
1611
1631
  for (const chunk of consumeIteratorInContext(childConfig, output)) {
1632
+ config?.signal?.throwIfAborted();
1612
1633
  yield chunk;
1613
1634
  }
1614
1635
  }
@@ -1683,6 +1704,7 @@ export class RunnableWithFallbacks extends Runnable {
1683
1704
  const runManager = await callbackManager_?.handleChainStart(this.toJSON(), _coerceToDict(input, "input"), runId, undefined, undefined, undefined, otherConfigFields?.runName);
1684
1705
  let firstError;
1685
1706
  for (const runnable of this.runnables()) {
1707
+ config?.signal?.throwIfAborted();
1686
1708
  try {
1687
1709
  const output = await runnable.invoke(input, patchConfig(otherConfigFields, { callbacks: runManager?.getChild() }));
1688
1710
  await runManager?.handleChainEnd(_coerceToDict(output, "output"));
@@ -1714,6 +1736,7 @@ export class RunnableWithFallbacks extends Runnable {
1714
1736
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1715
1737
  let firstError;
1716
1738
  for (const runnable of this.runnables()) {
1739
+ configList[0].signal?.throwIfAborted();
1717
1740
  try {
1718
1741
  const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => patchConfig(configList[j], {
1719
1742
  callbacks: runManager?.getChild(),
@@ -24,6 +24,31 @@ function mergeConfigs(...configs) {
24
24
  else if (key === "configurable") {
25
25
  copy[key] = { ...copy[key], ...options[key] };
26
26
  }
27
+ else if (key === "timeout") {
28
+ if (copy.timeout === undefined) {
29
+ copy.timeout = options.timeout;
30
+ }
31
+ else if (options.timeout !== undefined) {
32
+ copy.timeout = Math.min(copy.timeout, options.timeout);
33
+ }
34
+ }
35
+ else if (key === "signal") {
36
+ if (copy.signal === undefined) {
37
+ copy.signal = options.signal;
38
+ }
39
+ else if (options.signal !== undefined) {
40
+ if ("any" in AbortSignal) {
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ copy.signal = AbortSignal.any([
43
+ copy.signal,
44
+ options.signal,
45
+ ]);
46
+ }
47
+ else {
48
+ copy.signal = options.signal;
49
+ }
50
+ }
51
+ }
27
52
  else if (key === "callbacks") {
28
53
  const baseCallbacks = copy.callbacks;
29
54
  const providedCallbacks = options.callbacks;
@@ -130,6 +155,22 @@ function ensureConfig(config) {
130
155
  }
131
156
  }
132
157
  }
158
+ if (empty.timeout !== undefined) {
159
+ if (empty.timeout <= 0) {
160
+ throw new Error("Timeout must be a positive number");
161
+ }
162
+ const timeoutSignal = AbortSignal.timeout(empty.timeout);
163
+ if (empty.signal !== undefined) {
164
+ if ("any" in AbortSignal) {
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ empty.signal = AbortSignal.any([empty.signal, timeoutSignal]);
167
+ }
168
+ }
169
+ else {
170
+ empty.signal = timeoutSignal;
171
+ }
172
+ delete empty.timeout;
173
+ }
133
174
  return empty;
134
175
  }
135
176
  exports.ensureConfig = ensureConfig;
@@ -20,6 +20,31 @@ export function mergeConfigs(...configs) {
20
20
  else if (key === "configurable") {
21
21
  copy[key] = { ...copy[key], ...options[key] };
22
22
  }
23
+ else if (key === "timeout") {
24
+ if (copy.timeout === undefined) {
25
+ copy.timeout = options.timeout;
26
+ }
27
+ else if (options.timeout !== undefined) {
28
+ copy.timeout = Math.min(copy.timeout, options.timeout);
29
+ }
30
+ }
31
+ else if (key === "signal") {
32
+ if (copy.signal === undefined) {
33
+ copy.signal = options.signal;
34
+ }
35
+ else if (options.signal !== undefined) {
36
+ if ("any" in AbortSignal) {
37
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
38
+ copy.signal = AbortSignal.any([
39
+ copy.signal,
40
+ options.signal,
41
+ ]);
42
+ }
43
+ else {
44
+ copy.signal = options.signal;
45
+ }
46
+ }
47
+ }
23
48
  else if (key === "callbacks") {
24
49
  const baseCallbacks = copy.callbacks;
25
50
  const providedCallbacks = options.callbacks;
@@ -125,6 +150,22 @@ export function ensureConfig(config) {
125
150
  }
126
151
  }
127
152
  }
153
+ if (empty.timeout !== undefined) {
154
+ if (empty.timeout <= 0) {
155
+ throw new Error("Timeout must be a positive number");
156
+ }
157
+ const timeoutSignal = AbortSignal.timeout(empty.timeout);
158
+ if (empty.signal !== undefined) {
159
+ if ("any" in AbortSignal) {
160
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
+ empty.signal = AbortSignal.any([empty.signal, timeoutSignal]);
162
+ }
163
+ }
164
+ else {
165
+ empty.signal = timeoutSignal;
166
+ }
167
+ delete empty.timeout;
168
+ }
128
169
  return empty;
129
170
  }
130
171
  /**
@@ -46,7 +46,7 @@ function revive(obj) {
46
46
  content: obj.content,
47
47
  });
48
48
  }
49
- if (obj.type === "ChatMessage" || obj.type === "chat") {
49
+ if (obj.type === "ChatMessage" || obj.type === "generic") {
50
50
  return new index_js_2.ChatMessage({
51
51
  content: obj.content,
52
52
  role: obj.role,
@@ -62,6 +62,7 @@ function revive(obj) {
62
62
  return new index_js_2.ToolMessage({
63
63
  content: obj.content,
64
64
  tool_call_id: obj.tool_call_id,
65
+ status: obj.status,
65
66
  });
66
67
  }
67
68
  if (obj.type === "AIMessage" || obj.type === "ai") {
@@ -95,6 +96,7 @@ function revive(obj) {
95
96
  return new index_js_2.ToolMessageChunk({
96
97
  content: obj.content,
97
98
  tool_call_id: obj.tool_call_id,
99
+ status: obj.status,
98
100
  });
99
101
  }
100
102
  if (obj.type === "AIMessageChunk") {
@@ -184,9 +186,10 @@ function deserialize(str) {
184
186
  const obj = JSON.parse(str);
185
187
  return revive(obj);
186
188
  }
187
- function removeCallbacks(options) {
189
+ function removeCallbacksAndSignal(options) {
188
190
  const rest = { ...options };
189
191
  delete rest.callbacks;
192
+ delete rest.signal;
190
193
  return rest;
191
194
  }
192
195
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -251,7 +254,7 @@ class RemoteRunnable extends base_js_1.Runnable {
251
254
  this.url = url.replace(/\/$/, ""); // remove trailing slash
252
255
  this.options = options;
253
256
  }
254
- async post(path, body) {
257
+ async post(path, body, signal) {
255
258
  return fetch(`${this.url}${path}`, {
256
259
  method: "POST",
257
260
  body: JSON.stringify(serialize(body)),
@@ -259,16 +262,16 @@ class RemoteRunnable extends base_js_1.Runnable {
259
262
  "Content-Type": "application/json",
260
263
  ...this.options?.headers,
261
264
  },
262
- signal: AbortSignal.timeout(this.options?.timeout ?? 60000),
265
+ signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
263
266
  });
264
267
  }
265
268
  async _invoke(input, options, _) {
266
269
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
267
270
  const response = await this.post("/invoke", {
268
271
  input,
269
- config: removeCallbacks(config),
272
+ config: removeCallbacksAndSignal(config),
270
273
  kwargs: kwargs ?? {},
271
- });
274
+ }, config.signal);
272
275
  if (!response.ok) {
273
276
  throw new Error(`${response.status} Error: ${await response.text()}`);
274
277
  }
@@ -289,10 +292,10 @@ class RemoteRunnable extends base_js_1.Runnable {
289
292
  const response = await this.post("/batch", {
290
293
  inputs,
291
294
  config: (configs ?? [])
292
- .map(removeCallbacks)
295
+ .map(removeCallbacksAndSignal)
293
296
  .map((config) => ({ ...config, ...batchOptions })),
294
297
  kwargs,
295
- });
298
+ }, options?.[0]?.signal);
296
299
  if (!response.ok) {
297
300
  throw new Error(`${response.status} Error: ${await response.text()}`);
298
301
  }
@@ -317,9 +320,9 @@ class RemoteRunnable extends base_js_1.Runnable {
317
320
  try {
318
321
  const response = await this.post("/stream", {
319
322
  input,
320
- config: removeCallbacks(config),
323
+ config: removeCallbacksAndSignal(config),
321
324
  kwargs,
322
- });
325
+ }, config.signal);
323
326
  if (!response.ok) {
324
327
  const json = await response.json();
325
328
  const error = new Error(`RemoteRunnable call failed with status code ${response.status}: ${json.message}`);
@@ -376,11 +379,11 @@ class RemoteRunnable extends base_js_1.Runnable {
376
379
  try {
377
380
  const response = await this.post("/stream_log", {
378
381
  input,
379
- config: removeCallbacks(config),
382
+ config: removeCallbacksAndSignal(config),
380
383
  kwargs,
381
384
  ...camelCaseStreamOptions,
382
385
  diff: false,
383
- });
386
+ }, config.signal);
384
387
  const { body, ok } = response;
385
388
  if (!ok) {
386
389
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -428,11 +431,11 @@ class RemoteRunnable extends base_js_1.Runnable {
428
431
  try {
429
432
  const response = await outerThis.post("/stream_events", {
430
433
  input,
431
- config: removeCallbacks(config),
434
+ config: removeCallbacksAndSignal(config),
432
435
  kwargs,
433
436
  ...camelCaseStreamOptions,
434
437
  diff: false,
435
- });
438
+ }, config.signal);
436
439
  const { body, ok } = response;
437
440
  if (!ok) {
438
441
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -43,7 +43,7 @@ function revive(obj) {
43
43
  content: obj.content,
44
44
  });
45
45
  }
46
- if (obj.type === "ChatMessage" || obj.type === "chat") {
46
+ if (obj.type === "ChatMessage" || obj.type === "generic") {
47
47
  return new ChatMessage({
48
48
  content: obj.content,
49
49
  role: obj.role,
@@ -59,6 +59,7 @@ function revive(obj) {
59
59
  return new ToolMessage({
60
60
  content: obj.content,
61
61
  tool_call_id: obj.tool_call_id,
62
+ status: obj.status,
62
63
  });
63
64
  }
64
65
  if (obj.type === "AIMessage" || obj.type === "ai") {
@@ -92,6 +93,7 @@ function revive(obj) {
92
93
  return new ToolMessageChunk({
93
94
  content: obj.content,
94
95
  tool_call_id: obj.tool_call_id,
96
+ status: obj.status,
95
97
  });
96
98
  }
97
99
  if (obj.type === "AIMessageChunk") {
@@ -181,9 +183,10 @@ function deserialize(str) {
181
183
  const obj = JSON.parse(str);
182
184
  return revive(obj);
183
185
  }
184
- function removeCallbacks(options) {
186
+ function removeCallbacksAndSignal(options) {
185
187
  const rest = { ...options };
186
188
  delete rest.callbacks;
189
+ delete rest.signal;
187
190
  return rest;
188
191
  }
189
192
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -248,7 +251,7 @@ export class RemoteRunnable extends Runnable {
248
251
  this.url = url.replace(/\/$/, ""); // remove trailing slash
249
252
  this.options = options;
250
253
  }
251
- async post(path, body) {
254
+ async post(path, body, signal) {
252
255
  return fetch(`${this.url}${path}`, {
253
256
  method: "POST",
254
257
  body: JSON.stringify(serialize(body)),
@@ -256,16 +259,16 @@ export class RemoteRunnable extends Runnable {
256
259
  "Content-Type": "application/json",
257
260
  ...this.options?.headers,
258
261
  },
259
- signal: AbortSignal.timeout(this.options?.timeout ?? 60000),
262
+ signal: signal ?? AbortSignal.timeout(this.options?.timeout ?? 60000),
260
263
  });
261
264
  }
262
265
  async _invoke(input, options, _) {
263
266
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
264
267
  const response = await this.post("/invoke", {
265
268
  input,
266
- config: removeCallbacks(config),
269
+ config: removeCallbacksAndSignal(config),
267
270
  kwargs: kwargs ?? {},
268
- });
271
+ }, config.signal);
269
272
  if (!response.ok) {
270
273
  throw new Error(`${response.status} Error: ${await response.text()}`);
271
274
  }
@@ -286,10 +289,10 @@ export class RemoteRunnable extends Runnable {
286
289
  const response = await this.post("/batch", {
287
290
  inputs,
288
291
  config: (configs ?? [])
289
- .map(removeCallbacks)
292
+ .map(removeCallbacksAndSignal)
290
293
  .map((config) => ({ ...config, ...batchOptions })),
291
294
  kwargs,
292
- });
295
+ }, options?.[0]?.signal);
293
296
  if (!response.ok) {
294
297
  throw new Error(`${response.status} Error: ${await response.text()}`);
295
298
  }
@@ -314,9 +317,9 @@ export class RemoteRunnable extends Runnable {
314
317
  try {
315
318
  const response = await this.post("/stream", {
316
319
  input,
317
- config: removeCallbacks(config),
320
+ config: removeCallbacksAndSignal(config),
318
321
  kwargs,
319
- });
322
+ }, config.signal);
320
323
  if (!response.ok) {
321
324
  const json = await response.json();
322
325
  const error = new Error(`RemoteRunnable call failed with status code ${response.status}: ${json.message}`);
@@ -373,11 +376,11 @@ export class RemoteRunnable extends Runnable {
373
376
  try {
374
377
  const response = await this.post("/stream_log", {
375
378
  input,
376
- config: removeCallbacks(config),
379
+ config: removeCallbacksAndSignal(config),
377
380
  kwargs,
378
381
  ...camelCaseStreamOptions,
379
382
  diff: false,
380
- });
383
+ }, config.signal);
381
384
  const { body, ok } = response;
382
385
  if (!ok) {
383
386
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -425,11 +428,11 @@ export class RemoteRunnable extends Runnable {
425
428
  try {
426
429
  const response = await outerThis.post("/stream_events", {
427
430
  input,
428
- config: removeCallbacks(config),
431
+ config: removeCallbacksAndSignal(config),
429
432
  kwargs,
430
433
  ...camelCaseStreamOptions,
431
434
  diff: false,
432
- });
435
+ }, config.signal);
433
436
  const { body, ok } = response;
434
437
  if (!ok) {
435
438
  throw new Error(`${response.status} Error: ${await response.text()}`);
@@ -53,4 +53,14 @@ export interface RunnableConfig extends BaseCallbackConfig {
53
53
  recursionLimit?: number;
54
54
  /** Maximum number of parallel calls to make. */
55
55
  maxConcurrency?: number;
56
+ /**
57
+ * Timeout for this call in milliseconds.
58
+ */
59
+ timeout?: number;
60
+ /**
61
+ * Abort signal for this call.
62
+ * If provided, the call will be aborted when the signal is aborted.
63
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
64
+ */
65
+ signal?: AbortSignal;
56
66
  }
@@ -9,6 +9,7 @@ const tool_js_1 = require("../messages/tool.cjs");
9
9
  const index_js_1 = require("../singletons/index.cjs");
10
10
  const utils_js_1 = require("./utils.cjs");
11
11
  Object.defineProperty(exports, "ToolInputParsingException", { enumerable: true, get: function () { return utils_js_1.ToolInputParsingException; } });
12
+ const is_zod_schema_js_1 = require("../utils/types/is_zod_schema.cjs");
12
13
  /**
13
14
  * Base class for Tools that accept input of any shape defined by a Zod schema.
14
15
  */
@@ -94,6 +95,7 @@ class StructuredTool extends base_js_1.BaseLangChain {
94
95
  let result;
95
96
  try {
96
97
  result = await this._call(parsed, runManager, config);
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
99
  }
98
100
  catch (e) {
99
101
  await runManager?.handleToolError(e);
@@ -210,6 +212,9 @@ exports.DynamicTool = DynamicTool;
210
212
  * description, designed to work with structured data. It extends the
211
213
  * StructuredTool class and overrides the _call method to execute the
212
214
  * provided function when the tool is called.
215
+ *
216
+ * Schema can be passed as Zod or JSON schema. The tool will not validate
217
+ * input if JSON schema is passed.
213
218
  */
214
219
  class DynamicStructuredTool extends StructuredTool {
215
220
  static lc_name() {
@@ -245,7 +250,7 @@ class DynamicStructuredTool extends StructuredTool {
245
250
  this.description = fields.description;
246
251
  this.func = fields.func;
247
252
  this.returnDirect = fields.returnDirect ?? this.returnDirect;
248
- this.schema = fields.schema;
253
+ this.schema = ((0, is_zod_schema_js_1.isZodSchema)(fields.schema) ? fields.schema : zod_1.z.object({}));
249
254
  }
250
255
  /**
251
256
  * @deprecated Use .invoke() instead. Will be removed in 0.3.0.
@@ -260,6 +265,7 @@ class DynamicStructuredTool extends StructuredTool {
260
265
  return super.call(arg, config, tags);
261
266
  }
262
267
  _call(arg, runManager, parentConfig) {
268
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
263
269
  return this.func(arg, runManager, parentConfig);
264
270
  }
265
271
  }
@@ -279,18 +285,20 @@ function tool(func, fields) {
279
285
  // If the schema is not provided, or it's a string schema, create a DynamicTool
280
286
  if (!fields.schema || !("shape" in fields.schema) || !fields.schema.shape) {
281
287
  return new DynamicTool({
282
- name: fields.name,
288
+ ...fields,
283
289
  description: fields.description ??
284
290
  fields.schema?.description ??
285
291
  `${fields.name} tool`,
286
- responseFormat: fields.responseFormat,
287
- func,
292
+ // TS doesn't restrict the type here based on the guard above
293
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
294
+ func: func,
288
295
  });
289
296
  }
290
297
  const description = fields.description ?? fields.schema.description ?? `${fields.name} tool`;
291
298
  return new DynamicStructuredTool({
292
- name: fields.name,
299
+ ...fields,
293
300
  description,
301
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
294
302
  schema: fields.schema,
295
303
  // TODO: Consider moving into DynamicStructuredTool constructor
296
304
  func: async (input, runManager, config) => {
@@ -300,6 +308,8 @@ function tool(func, fields) {
300
308
  });
301
309
  void index_js_1.AsyncLocalStorageProviderSingleton.getInstance().run(childConfig, async () => {
302
310
  try {
311
+ // TS doesn't restrict the type here based on the guard above
312
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
303
313
  resolve(func(input, childConfig));
304
314
  }
305
315
  catch (e) {
@@ -308,7 +318,6 @@ function tool(func, fields) {
308
318
  });
309
319
  });
310
320
  },
311
- responseFormat: fields.responseFormat,
312
321
  });
313
322
  }
314
323
  exports.tool = tool;