@langchain/core 0.1.14 → 0.1.16

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.
@@ -3,7 +3,7 @@ import { CallbackManager, } from "../callbacks/manager.js";
3
3
  import { LogStreamCallbackHandler, RunLogPatch, } from "../tracers/log_stream.js";
4
4
  import { Serializable } from "../load/serializable.js";
5
5
  import { IterableReadableStream, concat, atee, pipeGeneratorWithSetup, } from "../utils/stream.js";
6
- import { DEFAULT_RECURSION_LIMIT, getCallbackManagerForConfig, mergeConfigs, } from "./config.js";
6
+ import { DEFAULT_RECURSION_LIMIT, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, } from "./config.js";
7
7
  import { AsyncCaller } from "../utils/async_caller.js";
8
8
  import { RootListenersTracer } from "../tracers/root_listener.js";
9
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -105,14 +105,15 @@ export class Runnable extends Serializable {
105
105
  if (options.length !== length) {
106
106
  throw new Error(`Passed "options" must be an array with the same length as the inputs, but got ${options.length} options for ${length} inputs`);
107
107
  }
108
- return options;
108
+ return options.map(ensureConfig);
109
109
  }
110
- return Array.from({ length }, () => options);
110
+ return Array.from({ length }, () => ensureConfig(options));
111
111
  }
112
112
  async batch(inputs, options, batchOptions) {
113
113
  const configList = this._getOptionsList(options ?? {}, inputs.length);
114
+ const maxConcurrency = configList[0]?.maxConcurrency ?? batchOptions?.maxConcurrency;
114
115
  const caller = new AsyncCaller({
115
- maxConcurrency: batchOptions?.maxConcurrency,
116
+ maxConcurrency,
116
117
  onFailedAttempt: (e) => {
117
118
  throw e;
118
119
  },
@@ -150,27 +151,32 @@ export class Runnable extends Serializable {
150
151
  return IterableReadableStream.fromAsyncGenerator(this._streamIterator(input, options));
151
152
  }
152
153
  _separateRunnableConfigFromCallOptions(options = {}) {
153
- const runnableConfig = {
154
+ const runnableConfig = ensureConfig({
154
155
  callbacks: options.callbacks,
155
156
  tags: options.tags,
156
157
  metadata: options.metadata,
157
158
  runName: options.runName,
158
159
  configurable: options.configurable,
159
- };
160
+ recursionLimit: options.recursionLimit,
161
+ maxConcurrency: options.maxConcurrency,
162
+ });
160
163
  const callOptions = { ...options };
161
164
  delete callOptions.callbacks;
162
165
  delete callOptions.tags;
163
166
  delete callOptions.metadata;
164
167
  delete callOptions.runName;
165
168
  delete callOptions.configurable;
169
+ delete callOptions.recursionLimit;
170
+ delete callOptions.maxConcurrency;
166
171
  return [runnableConfig, callOptions];
167
172
  }
168
173
  async _callWithConfig(func, input, options) {
169
- const callbackManager_ = await getCallbackManagerForConfig(options);
170
- const runManager = await callbackManager_?.handleChainStart(this.toJSON(), _coerceToDict(input, "input"), undefined, options?.runType, undefined, undefined, options?.runName ?? this.getName());
174
+ const config = ensureConfig(options);
175
+ const callbackManager_ = await getCallbackManagerForConfig(config);
176
+ const runManager = await callbackManager_?.handleChainStart(this.toJSON(), _coerceToDict(input, "input"), undefined, config?.runType, undefined, undefined, config?.runName ?? this.getName());
171
177
  let output;
172
178
  try {
173
- output = await func.bind(this)(input, options, runManager);
179
+ output = await func.call(this, input, config, runManager);
174
180
  }
175
181
  catch (e) {
176
182
  await runManager?.handleChainError(e);
@@ -194,7 +200,7 @@ export class Runnable extends Serializable {
194
200
  const runManagers = await Promise.all(callbackManagers.map((callbackManager, i) => callbackManager?.handleChainStart(this.toJSON(), _coerceToDict(inputs[i], "input"), undefined, optionsList[i].runType, undefined, undefined, optionsList[i].runName ?? this.getName())));
195
201
  let outputs;
196
202
  try {
197
- outputs = await func(inputs, optionsList, runManagers, batchOptions);
203
+ outputs = await func.call(this, inputs, optionsList, runManagers, batchOptions);
198
204
  }
199
205
  catch (e) {
200
206
  await Promise.all(runManagers.map((runManager) => runManager?.handleChainError(e)));
@@ -213,7 +219,8 @@ export class Runnable extends Serializable {
213
219
  let finalInputSupported = true;
214
220
  let finalOutput;
215
221
  let finalOutputSupported = true;
216
- const callbackManager_ = await getCallbackManagerForConfig(options);
222
+ const config = ensureConfig(options);
223
+ const callbackManager_ = await getCallbackManagerForConfig(config);
217
224
  async function* wrapInputForTracing() {
218
225
  for await (const chunk of inputGenerator) {
219
226
  if (finalInputSupported) {
@@ -236,9 +243,15 @@ export class Runnable extends Serializable {
236
243
  }
237
244
  let runManager;
238
245
  try {
239
- const pipe = await pipeGeneratorWithSetup(transformer, wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, undefined, options?.runType, undefined, undefined, options?.runName ?? this.getName()), options);
246
+ const pipe = await pipeGeneratorWithSetup(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, undefined, config?.runType, undefined, undefined, config?.runName ?? this.getName()), config);
240
247
  runManager = pipe.setup;
241
- for await (const chunk of pipe.output) {
248
+ const isLogStreamHandler = (handler) => handler.name === "log_stream_tracer";
249
+ const streamLogHandler = runManager?.handlers.find(isLogStreamHandler);
250
+ let iterator = pipe.output;
251
+ if (streamLogHandler !== undefined && runManager !== undefined) {
252
+ iterator = await streamLogHandler.tapOutputIterable(runManager.runId, pipe.output);
253
+ }
254
+ for await (const chunk of iterator) {
242
255
  yield chunk;
243
256
  if (finalOutputSupported) {
244
257
  if (finalOutput === undefined) {
@@ -265,21 +278,6 @@ export class Runnable extends Serializable {
265
278
  }
266
279
  await runManager?.handleChainEnd(finalOutput ?? {}, undefined, undefined, undefined, { inputs: _coerceToDict(finalInput, "input") });
267
280
  }
268
- _patchConfig(config = {}, callbackManager = undefined, recursionLimit = undefined) {
269
- const newConfig = { ...config };
270
- if (callbackManager !== undefined) {
271
- /**
272
- * If we're replacing callbacks we need to unset runName
273
- * since that should apply only to the same run as the original callbacks
274
- */
275
- delete newConfig.runName;
276
- return { ...newConfig, callbacks: callbackManager };
277
- }
278
- if (recursionLimit !== undefined) {
279
- newConfig.recursionLimit = recursionLimit;
280
- }
281
- return newConfig;
282
- }
283
281
  /**
284
282
  * Create a new runnable sequence that runs each individual runnable in series,
285
283
  * piping the output of one runnable into another runnable or runnable-like.
@@ -348,7 +346,7 @@ export class Runnable extends Serializable {
348
346
  ...streamOptions,
349
347
  autoClose: false,
350
348
  });
351
- const config = options ?? {};
349
+ const config = ensureConfig(options);
352
350
  const { callbacks } = config;
353
351
  if (callbacks === undefined) {
354
352
  config.callbacks = [stream];
@@ -479,10 +477,8 @@ export class RunnableBinding extends Runnable {
479
477
  getName(suffix) {
480
478
  return this.bound.getName(suffix);
481
479
  }
482
- async _mergeConfig(
483
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
484
- options) {
485
- const config = mergeConfigs(this.config, options);
480
+ async _mergeConfig(...options) {
481
+ const config = mergeConfigs(this.config, ...options);
486
482
  return mergeConfigs(config, ...(this.configFactories
487
483
  ? await Promise.all(this.configFactories.map(async (configFactory) => await configFactory(config)))
488
484
  : []));
@@ -512,27 +508,24 @@ export class RunnableBinding extends Runnable {
512
508
  });
513
509
  }
514
510
  async invoke(input, options) {
515
- return this.bound.invoke(input, await this._mergeConfig({ ...options, ...this.kwargs }));
511
+ return this.bound.invoke(input, await this._mergeConfig(options, this.kwargs));
516
512
  }
517
513
  async batch(inputs, options, batchOptions) {
518
514
  const mergedOptions = Array.isArray(options)
519
- ? await Promise.all(options.map(async (individualOption) => this._mergeConfig({
520
- ...individualOption,
521
- ...this.kwargs,
522
- })))
523
- : await this._mergeConfig({ ...options, ...this.kwargs });
515
+ ? await Promise.all(options.map(async (individualOption) => this._mergeConfig(individualOption, this.kwargs)))
516
+ : await this._mergeConfig(options, this.kwargs);
524
517
  return this.bound.batch(inputs, mergedOptions, batchOptions);
525
518
  }
526
519
  async *_streamIterator(input, options) {
527
- yield* this.bound._streamIterator(input, await this._mergeConfig({ ...options, ...this.kwargs }));
520
+ yield* this.bound._streamIterator(input, await this._mergeConfig(options, this.kwargs));
528
521
  }
529
522
  async stream(input, options) {
530
- return this.bound.stream(input, await this._mergeConfig({ ...options, ...this.kwargs }));
523
+ return this.bound.stream(input, await this._mergeConfig(options, this.kwargs));
531
524
  }
532
525
  async *transform(
533
526
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
534
527
  generator, options) {
535
- yield* this.bound.transform(generator, await this._mergeConfig({ ...options, ...this.kwargs }));
528
+ yield* this.bound.transform(generator, await this._mergeConfig(options, this.kwargs));
536
529
  }
537
530
  static isRunnableBinding(
538
531
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -604,7 +597,7 @@ export class RunnableEach extends Runnable {
604
597
  }
605
598
  /**
606
599
  * Binds the runnable with the specified arguments.
607
- * @param args The arguments to bind the runnable with.
600
+ * @param kwargs The arguments to bind the runnable with.
608
601
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
609
602
  */
610
603
  bind(kwargs) {
@@ -628,7 +621,7 @@ export class RunnableEach extends Runnable {
628
621
  * @returns A promise that resolves to the output of the runnable.
629
622
  */
630
623
  async _invoke(inputs, config, runManager) {
631
- return this.bound.batch(inputs, this._patchConfig(config, runManager?.getChild()));
624
+ return this.bound.batch(inputs, patchConfig(config, { callbacks: runManager?.getChild() }));
632
625
  }
633
626
  /**
634
627
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -681,7 +674,7 @@ export class RunnableRetry extends RunnableBinding {
681
674
  }
682
675
  _patchConfigForRetry(attempt, config, runManager) {
683
676
  const tag = attempt > 1 ? `retry:attempt:${attempt}` : undefined;
684
- return this._patchConfig(config, runManager?.getChild(tag));
677
+ return patchConfig(config, { callbacks: runManager?.getChild(tag) });
685
678
  }
686
679
  async _invoke(input, config, runManager) {
687
680
  return pRetry((attemptNumber) => super.invoke(input, this._patchConfigForRetry(attemptNumber, config, runManager)), {
@@ -818,10 +811,14 @@ export class RunnableSequence extends Runnable {
818
811
  const initialSteps = [this.first, ...this.middle];
819
812
  for (let i = 0; i < initialSteps.length; i += 1) {
820
813
  const step = initialSteps[i];
821
- nextStepInput = await step.invoke(nextStepInput, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
814
+ nextStepInput = await step.invoke(nextStepInput, patchConfig(options, {
815
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
816
+ }));
822
817
  }
823
818
  // TypeScript can't detect that the last output of the sequence returns RunOutput, so call it out of the loop here
824
- finalOutput = await this.last.invoke(nextStepInput, this._patchConfig(options, runManager?.getChild(`seq:step:${this.steps.length}`)));
819
+ finalOutput = await this.last.invoke(nextStepInput, patchConfig(options, {
820
+ callbacks: runManager?.getChild(`seq:step:${this.steps.length}`),
821
+ }));
825
822
  }
826
823
  catch (e) {
827
824
  await runManager?.handleChainError(e);
@@ -836,21 +833,21 @@ export class RunnableSequence extends Runnable {
836
833
  const runManagers = await Promise.all(callbackManagers.map((callbackManager, i) => callbackManager?.handleChainStart(this.toJSON(), _coerceToDict(inputs[i], "input"), undefined, undefined, undefined, undefined, configList[i].runName)));
837
834
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
838
835
  let nextStepInputs = inputs;
839
- let finalOutputs;
840
836
  try {
841
- const initialSteps = [this.first, ...this.middle];
842
- for (let i = 0; i < initialSteps.length; i += 1) {
843
- const step = initialSteps[i];
844
- nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => this._patchConfig(configList[j], runManager?.getChild(`seq:step:${i + 1}`))), batchOptions);
837
+ for (let i = 0; i < this.steps.length; i += 1) {
838
+ const step = this.steps[i];
839
+ nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => {
840
+ const childRunManager = runManager?.getChild(`seq:step:${i + 1}`);
841
+ return patchConfig(configList[j], { callbacks: childRunManager });
842
+ }), batchOptions);
845
843
  }
846
- finalOutputs = await this.last.batch(nextStepInputs, runManagers.map((runManager) => this._patchConfig(configList[this.steps.length - 1], runManager?.getChild(`seq:step:${this.steps.length}`))), batchOptions);
847
844
  }
848
845
  catch (e) {
849
846
  await Promise.all(runManagers.map((runManager) => runManager?.handleChainError(e)));
850
847
  throw e;
851
848
  }
852
- await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(finalOutputs[i], "output"))));
853
- return finalOutputs;
849
+ await Promise.all(runManagers.map((runManager) => runManager?.handleChainEnd(_coerceToDict(nextStepInputs, "output"))));
850
+ return nextStepInputs;
854
851
  }
855
852
  async *_streamIterator(input, options) {
856
853
  const callbackManager_ = await getCallbackManagerForConfig(options);
@@ -862,10 +859,14 @@ export class RunnableSequence extends Runnable {
862
859
  yield input;
863
860
  }
864
861
  try {
865
- let finalGenerator = steps[0].transform(inputGenerator(), this._patchConfig(options, runManager?.getChild(`seq:step:1`)));
862
+ let finalGenerator = steps[0].transform(inputGenerator(), patchConfig(options, {
863
+ callbacks: runManager?.getChild(`seq:step:1`),
864
+ }));
866
865
  for (let i = 1; i < steps.length; i += 1) {
867
866
  const step = steps[i];
868
- finalGenerator = await step.transform(finalGenerator, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
867
+ finalGenerator = await step.transform(finalGenerator, patchConfig(options, {
868
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
869
+ }));
869
870
  }
870
871
  for await (const chunk of finalGenerator) {
871
872
  yield chunk;
@@ -988,7 +989,9 @@ export class RunnableMap extends Runnable {
988
989
  const output = {};
989
990
  try {
990
991
  await Promise.all(Object.entries(this.steps).map(async ([key, runnable]) => {
991
- output[key] = await runnable.invoke(input, this._patchConfig(options, runManager?.getChild(`map:key:${key}`)));
992
+ output[key] = await runnable.invoke(input, patchConfig(options, {
993
+ callbacks: runManager?.getChild(`map:key:${key}`),
994
+ }));
992
995
  }));
993
996
  }
994
997
  catch (e) {
@@ -1005,7 +1008,9 @@ export class RunnableMap extends Runnable {
1005
1008
  const inputCopies = atee(generator, Object.keys(steps).length);
1006
1009
  // start the first iteration of each output iterator
1007
1010
  const tasks = new Map(Object.entries(steps).map(([key, runnable], i) => {
1008
- const gen = runnable.transform(inputCopies[i], this._patchConfig(options, runManager?.getChild(`map:key:${key}`)));
1011
+ const gen = runnable.transform(inputCopies[i], patchConfig(options, {
1012
+ callbacks: runManager?.getChild(`map:key:${key}`),
1013
+ }));
1009
1014
  return [key, gen.next().then((result) => ({ key, gen, result }))];
1010
1015
  }));
1011
1016
  // yield chunks as they become available,
@@ -1064,7 +1069,10 @@ export class RunnableLambda extends Runnable {
1064
1069
  if (config?.recursionLimit === 0) {
1065
1070
  throw new Error("Recursion limit reached.");
1066
1071
  }
1067
- output = await output.invoke(input, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1));
1072
+ output = await output.invoke(input, patchConfig(config, {
1073
+ callbacks: runManager?.getChild(),
1074
+ recursionLimit: (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1,
1075
+ }));
1068
1076
  }
1069
1077
  return output;
1070
1078
  }
@@ -1093,7 +1101,10 @@ export class RunnableLambda extends Runnable {
1093
1101
  if (config?.recursionLimit === 0) {
1094
1102
  throw new Error("Recursion limit reached.");
1095
1103
  }
1096
- const stream = await output.stream(finalChunk, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1));
1104
+ const stream = await output.stream(finalChunk, patchConfig(config, {
1105
+ callbacks: runManager?.getChild(),
1106
+ recursionLimit: (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1,
1107
+ }));
1097
1108
  for await (const chunk of stream) {
1098
1109
  yield chunk;
1099
1110
  }
@@ -1162,7 +1173,7 @@ export class RunnableWithFallbacks extends Runnable {
1162
1173
  let firstError;
1163
1174
  for (const runnable of this.runnables()) {
1164
1175
  try {
1165
- const output = await runnable.invoke(input, this._patchConfig(options, runManager?.getChild()));
1176
+ const output = await runnable.invoke(input, patchConfig(options, { callbacks: runManager?.getChild() }));
1166
1177
  await runManager?.handleChainEnd(_coerceToDict(output, "output"));
1167
1178
  return output;
1168
1179
  }
@@ -1189,7 +1200,9 @@ export class RunnableWithFallbacks extends Runnable {
1189
1200
  let firstError;
1190
1201
  for (const runnable of this.runnables()) {
1191
1202
  try {
1192
- const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => this._patchConfig(configList[j], runManager?.getChild())), batchOptions);
1203
+ const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => patchConfig(configList[j], {
1204
+ callbacks: runManager?.getChild(),
1205
+ })), batchOptions);
1193
1206
  await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(outputs[i], "output"))));
1194
1207
  return outputs;
1195
1208
  }
@@ -1274,7 +1287,7 @@ export class RunnableAssign extends Runnable {
1274
1287
  // create two input gens, one for the mapper, one for the input
1275
1288
  const [forPassthrough, forMapper] = atee(generator);
1276
1289
  // create mapper output gen
1277
- const mapperOutput = this.mapper.transform(forMapper, this._patchConfig(options, runManager?.getChild()));
1290
+ const mapperOutput = this.mapper.transform(forMapper, patchConfig(options, { callbacks: runManager?.getChild() }));
1278
1291
  // start the mapper
1279
1292
  const firstMapperChunkPromise = mapperOutput.next();
1280
1293
  // yield the passthrough
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RunnableBranch = void 0;
4
4
  const base_js_1 = require("./base.cjs");
5
+ const config_js_1 = require("./config.cjs");
5
6
  /**
6
7
  * Class that represents a runnable branch. The RunnableBranch is
7
8
  * initialized with an array of branches and a default branch. When invoked,
@@ -116,14 +117,20 @@ class RunnableBranch extends base_js_1.Runnable {
116
117
  let result;
117
118
  for (let i = 0; i < this.branches.length; i += 1) {
118
119
  const [condition, branchRunnable] = this.branches[i];
119
- const conditionValue = await condition.invoke(input, this._patchConfig(config, runManager?.getChild(`condition:${i + 1}`)));
120
+ const conditionValue = await condition.invoke(input, (0, config_js_1.patchConfig)(config, {
121
+ callbacks: runManager?.getChild(`condition:${i + 1}`),
122
+ }));
120
123
  if (conditionValue) {
121
- result = await branchRunnable.invoke(input, this._patchConfig(config, runManager?.getChild(`branch:${i + 1}`)));
124
+ result = await branchRunnable.invoke(input, (0, config_js_1.patchConfig)(config, {
125
+ callbacks: runManager?.getChild(`branch:${i + 1}`),
126
+ }));
122
127
  break;
123
128
  }
124
129
  }
125
130
  if (!result) {
126
- result = await this.default.invoke(input, this._patchConfig(config, runManager?.getChild("default")));
131
+ result = await this.default.invoke(input, (0, config_js_1.patchConfig)(config, {
132
+ callbacks: runManager?.getChild("default"),
133
+ }));
127
134
  }
128
135
  return result;
129
136
  }
@@ -1,4 +1,5 @@
1
1
  import { Runnable, _coerceToRunnable } from "./base.js";
2
+ import { patchConfig } from "./config.js";
2
3
  /**
3
4
  * Class that represents a runnable branch. The RunnableBranch is
4
5
  * initialized with an array of branches and a default branch. When invoked,
@@ -113,14 +114,20 @@ export class RunnableBranch extends Runnable {
113
114
  let result;
114
115
  for (let i = 0; i < this.branches.length; i += 1) {
115
116
  const [condition, branchRunnable] = this.branches[i];
116
- const conditionValue = await condition.invoke(input, this._patchConfig(config, runManager?.getChild(`condition:${i + 1}`)));
117
+ const conditionValue = await condition.invoke(input, patchConfig(config, {
118
+ callbacks: runManager?.getChild(`condition:${i + 1}`),
119
+ }));
117
120
  if (conditionValue) {
118
- result = await branchRunnable.invoke(input, this._patchConfig(config, runManager?.getChild(`branch:${i + 1}`)));
121
+ result = await branchRunnable.invoke(input, patchConfig(config, {
122
+ callbacks: runManager?.getChild(`branch:${i + 1}`),
123
+ }));
119
124
  break;
120
125
  }
121
126
  }
122
127
  if (!result) {
123
- result = await this.default.invoke(input, this._patchConfig(config, runManager?.getChild("default")));
128
+ result = await this.default.invoke(input, patchConfig(config, {
129
+ callbacks: runManager?.getChild("default"),
130
+ }));
124
131
  }
125
132
  return result;
126
133
  }
@@ -1,31 +1,29 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mergeConfigs = exports.getCallbackManagerForConfig = exports.DEFAULT_RECURSION_LIMIT = void 0;
3
+ exports.patchConfig = exports.ensureConfig = exports.mergeConfigs = exports.getCallbackManagerForConfig = exports.DEFAULT_RECURSION_LIMIT = void 0;
4
4
  const manager_js_1 = require("../callbacks/manager.cjs");
5
5
  exports.DEFAULT_RECURSION_LIMIT = 25;
6
6
  async function getCallbackManagerForConfig(config) {
7
7
  return manager_js_1.CallbackManager.configure(config?.callbacks, undefined, config?.tags, undefined, config?.metadata);
8
8
  }
9
9
  exports.getCallbackManagerForConfig = getCallbackManagerForConfig;
10
- function mergeConfigs(config,
11
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
- options) {
10
+ function mergeConfigs(...configs) {
13
11
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- const copy = { ...config };
15
- if (options) {
12
+ const copy = ensureConfig();
13
+ for (const options of configs.filter((c) => !!c)) {
16
14
  for (const key of Object.keys(options)) {
17
15
  if (key === "metadata") {
18
16
  copy[key] = { ...copy[key], ...options[key] };
19
17
  }
20
18
  else if (key === "tags") {
21
- copy[key] = (copy[key] ?? []).concat(options[key] ?? []);
19
+ copy[key] = [...new Set(copy[key].concat(options[key] ?? []))];
22
20
  }
23
21
  else if (key === "configurable") {
24
22
  copy[key] = { ...copy[key], ...options[key] };
25
23
  }
26
24
  else if (key === "callbacks") {
27
25
  const baseCallbacks = copy.callbacks;
28
- const providedCallbacks = options.callbacks ?? config.callbacks;
26
+ const providedCallbacks = options.callbacks;
29
27
  // callbacks can be either undefined, Array<handler> or manager
30
28
  // so merging two callbacks values has 6 cases
31
29
  if (Array.isArray(providedCallbacks)) {
@@ -39,7 +37,7 @@ options) {
39
37
  // baseCallbacks is a manager
40
38
  const manager = baseCallbacks.copy();
41
39
  for (const callback of providedCallbacks) {
42
- manager.addHandler(callback, true);
40
+ manager.addHandler((0, manager_js_1.ensureHandler)(callback), true);
43
41
  }
44
42
  copy.callbacks = manager;
45
43
  }
@@ -52,13 +50,13 @@ options) {
52
50
  else if (Array.isArray(baseCallbacks)) {
53
51
  const manager = providedCallbacks.copy();
54
52
  for (const callback of baseCallbacks) {
55
- manager.addHandler(callback, true);
53
+ manager.addHandler((0, manager_js_1.ensureHandler)(callback), true);
56
54
  }
57
55
  copy.callbacks = manager;
58
56
  }
59
57
  else {
60
58
  // baseCallbacks is also a manager
61
- copy.callbacks = new manager_js_1.CallbackManager(providedCallbacks.parentRunId, {
59
+ copy.callbacks = new manager_js_1.CallbackManager(providedCallbacks._parentRunId, {
62
60
  handlers: baseCallbacks.handlers.concat(providedCallbacks.handlers),
63
61
  inheritableHandlers: baseCallbacks.inheritableHandlers.concat(providedCallbacks.inheritableHandlers),
64
62
  tags: Array.from(new Set(baseCallbacks.tags.concat(providedCallbacks.tags))),
@@ -72,10 +70,67 @@ options) {
72
70
  }
73
71
  }
74
72
  else {
75
- copy[key] = options[key] ?? copy[key];
73
+ const typedKey = key;
74
+ copy[typedKey] = options[typedKey] ?? copy[typedKey];
76
75
  }
77
76
  }
78
77
  }
79
78
  return copy;
80
79
  }
81
80
  exports.mergeConfigs = mergeConfigs;
81
+ const PRIMITIVES = new Set(["string", "number", "boolean"]);
82
+ /**
83
+ * Ensure that a passed config is an object with all required keys present.
84
+ */
85
+ function ensureConfig(config) {
86
+ let empty = {
87
+ tags: [],
88
+ metadata: {},
89
+ callbacks: undefined,
90
+ recursionLimit: 25,
91
+ };
92
+ if (config) {
93
+ empty = { ...empty, ...config };
94
+ }
95
+ if (config?.configurable) {
96
+ for (const key of Object.keys(config.configurable)) {
97
+ if (PRIMITIVES.has(typeof config.configurable[key]) &&
98
+ !empty.metadata?.[key]) {
99
+ if (!empty.metadata) {
100
+ empty.metadata = {};
101
+ }
102
+ empty.metadata[key] = config.configurable[key];
103
+ }
104
+ }
105
+ }
106
+ return empty;
107
+ }
108
+ exports.ensureConfig = ensureConfig;
109
+ /**
110
+ * Helper function that patches runnable configs with updated properties.
111
+ */
112
+ function patchConfig(config = {}, { callbacks, maxConcurrency, recursionLimit, runName, configurable, } = {}) {
113
+ const newConfig = ensureConfig(config);
114
+ if (callbacks !== undefined) {
115
+ /**
116
+ * If we're replacing callbacks we need to unset runName
117
+ * since that should apply only to the same run as the original callbacks
118
+ */
119
+ delete newConfig.runName;
120
+ newConfig.callbacks = callbacks;
121
+ }
122
+ if (recursionLimit !== undefined) {
123
+ newConfig.recursionLimit = recursionLimit;
124
+ }
125
+ if (maxConcurrency !== undefined) {
126
+ newConfig.maxConcurrency = maxConcurrency;
127
+ }
128
+ if (runName !== undefined) {
129
+ newConfig.runName = runName;
130
+ }
131
+ if (configurable !== undefined) {
132
+ newConfig.configurable = { ...newConfig.configurable, ...configurable };
133
+ }
134
+ return newConfig;
135
+ }
136
+ exports.patchConfig = patchConfig;
@@ -10,6 +10,16 @@ export interface RunnableConfig extends BaseCallbackConfig {
10
10
  * Maximum number of times a call can recurse. If not provided, defaults to 25.
11
11
  */
12
12
  recursionLimit?: number;
13
+ /** Maximum number of parallel calls to make. */
14
+ maxConcurrency?: number;
13
15
  }
14
16
  export declare function getCallbackManagerForConfig(config?: RunnableConfig): Promise<CallbackManager | undefined>;
15
- export declare function mergeConfigs<CallOptions extends RunnableConfig>(config: RunnableConfig, options?: Record<string, any>): Partial<CallOptions>;
17
+ export declare function mergeConfigs<CallOptions extends RunnableConfig>(...configs: (CallOptions | RunnableConfig | undefined | null)[]): Partial<CallOptions>;
18
+ /**
19
+ * Ensure that a passed config is an object with all required keys present.
20
+ */
21
+ export declare function ensureConfig<CallOptions extends RunnableConfig>(config?: CallOptions): CallOptions;
22
+ /**
23
+ * Helper function that patches runnable configs with updated properties.
24
+ */
25
+ export declare function patchConfig<CallOptions extends RunnableConfig>(config?: Partial<CallOptions>, { callbacks, maxConcurrency, recursionLimit, runName, configurable, }?: RunnableConfig): Partial<CallOptions>;