@langchain/core 0.1.14 → 0.1.15

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.
@@ -50,7 +50,7 @@ export declare abstract class BaseCallbackManager {
50
50
  */
51
51
  declare class BaseRunManager {
52
52
  readonly runId: string;
53
- protected readonly handlers: BaseCallbackHandler[];
53
+ readonly handlers: BaseCallbackHandler[];
54
54
  protected readonly inheritableHandlers: BaseCallbackHandler[];
55
55
  protected readonly tags: string[];
56
56
  protected readonly inheritableTags: string[];
@@ -3,7 +3,7 @@ import { type BaseCache } from "../caches.js";
3
3
  import { type BasePromptValueInterface } from "../prompt_values.js";
4
4
  import { type BaseMessage, type BaseMessageLike, type MessageContent } from "../messages/index.js";
5
5
  import { type LLMResult } from "../outputs.js";
6
- import { BaseCallbackConfig, CallbackManager, Callbacks } from "../callbacks/manager.js";
6
+ import { CallbackManager, Callbacks } from "../callbacks/manager.js";
7
7
  import { AsyncCaller, AsyncCallerParams } from "../utils/async_caller.js";
8
8
  import { Runnable, type RunnableInterface } from "../runnables/base.js";
9
9
  import { RunnableConfig } from "../runnables/config.js";
@@ -53,7 +53,7 @@ export interface BaseLanguageModelParams extends AsyncCallerParams, BaseLangChai
53
53
  callbackManager?: CallbackManager;
54
54
  cache?: BaseCache | boolean;
55
55
  }
56
- export interface BaseLanguageModelCallOptions extends BaseCallbackConfig {
56
+ export interface BaseLanguageModelCallOptions extends RunnableConfig {
57
57
  /**
58
58
  * Stop tokens to use for this call.
59
59
  * If not provided, the default stop tokens for the model will be used.
@@ -117,8 +117,9 @@ class Runnable extends serializable_js_1.Serializable {
117
117
  }
118
118
  async batch(inputs, options, batchOptions) {
119
119
  const configList = this._getOptionsList(options ?? {}, inputs.length);
120
+ const maxConcurrency = configList[0]?.maxConcurrency ?? batchOptions?.maxConcurrency;
120
121
  const caller = new async_caller_js_1.AsyncCaller({
121
- maxConcurrency: batchOptions?.maxConcurrency,
122
+ maxConcurrency,
122
123
  onFailedAttempt: (e) => {
123
124
  throw e;
124
125
  },
@@ -244,7 +245,13 @@ class Runnable extends serializable_js_1.Serializable {
244
245
  try {
245
246
  const pipe = await (0, stream_js_1.pipeGeneratorWithSetup)(transformer, wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, undefined, options?.runType, undefined, undefined, options?.runName ?? this.getName()), options);
246
247
  runManager = pipe.setup;
247
- 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) {
248
255
  yield chunk;
249
256
  if (finalOutputSupported) {
250
257
  if (finalOutput === undefined) {
@@ -271,21 +278,6 @@ class Runnable extends serializable_js_1.Serializable {
271
278
  }
272
279
  await runManager?.handleChainEnd(finalOutput ?? {}, undefined, undefined, undefined, { inputs: _coerceToDict(finalInput, "input") });
273
280
  }
274
- _patchConfig(config = {}, callbackManager = undefined, recursionLimit = undefined) {
275
- const newConfig = { ...config };
276
- if (callbackManager !== undefined) {
277
- /**
278
- * If we're replacing callbacks we need to unset runName
279
- * since that should apply only to the same run as the original callbacks
280
- */
281
- delete newConfig.runName;
282
- return { ...newConfig, callbacks: callbackManager };
283
- }
284
- if (recursionLimit !== undefined) {
285
- newConfig.recursionLimit = recursionLimit;
286
- }
287
- return newConfig;
288
- }
289
281
  /**
290
282
  * Create a new runnable sequence that runs each individual runnable in series,
291
283
  * piping the output of one runnable into another runnable or runnable-like.
@@ -612,7 +604,7 @@ class RunnableEach extends Runnable {
612
604
  }
613
605
  /**
614
606
  * Binds the runnable with the specified arguments.
615
- * @param args The arguments to bind the runnable with.
607
+ * @param kwargs The arguments to bind the runnable with.
616
608
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
617
609
  */
618
610
  bind(kwargs) {
@@ -636,7 +628,7 @@ class RunnableEach extends Runnable {
636
628
  * @returns A promise that resolves to the output of the runnable.
637
629
  */
638
630
  async _invoke(inputs, config, runManager) {
639
- return this.bound.batch(inputs, this._patchConfig(config, runManager?.getChild()));
631
+ return this.bound.batch(inputs, (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild() }));
640
632
  }
641
633
  /**
642
634
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -690,7 +682,7 @@ class RunnableRetry extends RunnableBinding {
690
682
  }
691
683
  _patchConfigForRetry(attempt, config, runManager) {
692
684
  const tag = attempt > 1 ? `retry:attempt:${attempt}` : undefined;
693
- return this._patchConfig(config, runManager?.getChild(tag));
685
+ return (0, config_js_1.patchConfig)(config, { callbacks: runManager?.getChild(tag) });
694
686
  }
695
687
  async _invoke(input, config, runManager) {
696
688
  return (0, p_retry_1.default)((attemptNumber) => super.invoke(input, this._patchConfigForRetry(attemptNumber, config, runManager)), {
@@ -828,10 +820,14 @@ class RunnableSequence extends Runnable {
828
820
  const initialSteps = [this.first, ...this.middle];
829
821
  for (let i = 0; i < initialSteps.length; i += 1) {
830
822
  const step = initialSteps[i];
831
- nextStepInput = await step.invoke(nextStepInput, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
823
+ nextStepInput = await step.invoke(nextStepInput, (0, config_js_1.patchConfig)(options, {
824
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
825
+ }));
832
826
  }
833
827
  // TypeScript can't detect that the last output of the sequence returns RunOutput, so call it out of the loop here
834
- finalOutput = await this.last.invoke(nextStepInput, this._patchConfig(options, runManager?.getChild(`seq:step:${this.steps.length}`)));
828
+ finalOutput = await this.last.invoke(nextStepInput, (0, config_js_1.patchConfig)(options, {
829
+ callbacks: runManager?.getChild(`seq:step:${this.steps.length}`),
830
+ }));
835
831
  }
836
832
  catch (e) {
837
833
  await runManager?.handleChainError(e);
@@ -846,21 +842,21 @@ class RunnableSequence extends Runnable {
846
842
  const runManagers = await Promise.all(callbackManagers.map((callbackManager, i) => callbackManager?.handleChainStart(this.toJSON(), _coerceToDict(inputs[i], "input"), undefined, undefined, undefined, undefined, configList[i].runName)));
847
843
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
848
844
  let nextStepInputs = inputs;
849
- let finalOutputs;
850
845
  try {
851
- const initialSteps = [this.first, ...this.middle];
852
- for (let i = 0; i < initialSteps.length; i += 1) {
853
- const step = initialSteps[i];
854
- nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => this._patchConfig(configList[j], runManager?.getChild(`seq:step:${i + 1}`))), batchOptions);
846
+ for (let i = 0; i < this.steps.length; i += 1) {
847
+ const step = this.steps[i];
848
+ nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => {
849
+ const childRunManager = runManager?.getChild(`seq:step:${i + 1}`);
850
+ return (0, config_js_1.patchConfig)(configList[j], { callbacks: childRunManager });
851
+ }), batchOptions);
855
852
  }
856
- finalOutputs = await this.last.batch(nextStepInputs, runManagers.map((runManager) => this._patchConfig(configList[this.steps.length - 1], runManager?.getChild(`seq:step:${this.steps.length}`))), batchOptions);
857
853
  }
858
854
  catch (e) {
859
855
  await Promise.all(runManagers.map((runManager) => runManager?.handleChainError(e)));
860
856
  throw e;
861
857
  }
862
- await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(finalOutputs[i], "output"))));
863
- return finalOutputs;
858
+ await Promise.all(runManagers.map((runManager) => runManager?.handleChainEnd(_coerceToDict(nextStepInputs, "output"))));
859
+ return nextStepInputs;
864
860
  }
865
861
  async *_streamIterator(input, options) {
866
862
  const callbackManager_ = await (0, config_js_1.getCallbackManagerForConfig)(options);
@@ -872,10 +868,14 @@ class RunnableSequence extends Runnable {
872
868
  yield input;
873
869
  }
874
870
  try {
875
- let finalGenerator = steps[0].transform(inputGenerator(), this._patchConfig(options, runManager?.getChild(`seq:step:1`)));
871
+ let finalGenerator = steps[0].transform(inputGenerator(), (0, config_js_1.patchConfig)(options, {
872
+ callbacks: runManager?.getChild(`seq:step:1`),
873
+ }));
876
874
  for (let i = 1; i < steps.length; i += 1) {
877
875
  const step = steps[i];
878
- finalGenerator = await step.transform(finalGenerator, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
876
+ finalGenerator = await step.transform(finalGenerator, (0, config_js_1.patchConfig)(options, {
877
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
878
+ }));
879
879
  }
880
880
  for await (const chunk of finalGenerator) {
881
881
  yield chunk;
@@ -999,7 +999,9 @@ class RunnableMap extends Runnable {
999
999
  const output = {};
1000
1000
  try {
1001
1001
  await Promise.all(Object.entries(this.steps).map(async ([key, runnable]) => {
1002
- output[key] = await runnable.invoke(input, this._patchConfig(options, runManager?.getChild(`map:key:${key}`)));
1002
+ output[key] = await runnable.invoke(input, (0, config_js_1.patchConfig)(options, {
1003
+ callbacks: runManager?.getChild(`map:key:${key}`),
1004
+ }));
1003
1005
  }));
1004
1006
  }
1005
1007
  catch (e) {
@@ -1016,7 +1018,9 @@ class RunnableMap extends Runnable {
1016
1018
  const inputCopies = (0, stream_js_1.atee)(generator, Object.keys(steps).length);
1017
1019
  // start the first iteration of each output iterator
1018
1020
  const tasks = new Map(Object.entries(steps).map(([key, runnable], i) => {
1019
- const gen = runnable.transform(inputCopies[i], this._patchConfig(options, runManager?.getChild(`map:key:${key}`)));
1021
+ const gen = runnable.transform(inputCopies[i], (0, config_js_1.patchConfig)(options, {
1022
+ callbacks: runManager?.getChild(`map:key:${key}`),
1023
+ }));
1020
1024
  return [key, gen.next().then((result) => ({ key, gen, result }))];
1021
1025
  }));
1022
1026
  // yield chunks as they become available,
@@ -1076,7 +1080,10 @@ class RunnableLambda extends Runnable {
1076
1080
  if (config?.recursionLimit === 0) {
1077
1081
  throw new Error("Recursion limit reached.");
1078
1082
  }
1079
- output = await output.invoke(input, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? config_js_1.DEFAULT_RECURSION_LIMIT) - 1));
1083
+ output = await output.invoke(input, (0, config_js_1.patchConfig)(config, {
1084
+ callbacks: runManager?.getChild(),
1085
+ recursionLimit: (config?.recursionLimit ?? config_js_1.DEFAULT_RECURSION_LIMIT) - 1,
1086
+ }));
1080
1087
  }
1081
1088
  return output;
1082
1089
  }
@@ -1105,7 +1112,10 @@ class RunnableLambda extends Runnable {
1105
1112
  if (config?.recursionLimit === 0) {
1106
1113
  throw new Error("Recursion limit reached.");
1107
1114
  }
1108
- const stream = await output.stream(finalChunk, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? config_js_1.DEFAULT_RECURSION_LIMIT) - 1));
1115
+ const stream = await output.stream(finalChunk, (0, config_js_1.patchConfig)(config, {
1116
+ callbacks: runManager?.getChild(),
1117
+ recursionLimit: (config?.recursionLimit ?? config_js_1.DEFAULT_RECURSION_LIMIT) - 1,
1118
+ }));
1109
1119
  for await (const chunk of stream) {
1110
1120
  yield chunk;
1111
1121
  }
@@ -1176,7 +1186,7 @@ class RunnableWithFallbacks extends Runnable {
1176
1186
  let firstError;
1177
1187
  for (const runnable of this.runnables()) {
1178
1188
  try {
1179
- const output = await runnable.invoke(input, this._patchConfig(options, runManager?.getChild()));
1189
+ const output = await runnable.invoke(input, (0, config_js_1.patchConfig)(options, { callbacks: runManager?.getChild() }));
1180
1190
  await runManager?.handleChainEnd(_coerceToDict(output, "output"));
1181
1191
  return output;
1182
1192
  }
@@ -1203,7 +1213,9 @@ class RunnableWithFallbacks extends Runnable {
1203
1213
  let firstError;
1204
1214
  for (const runnable of this.runnables()) {
1205
1215
  try {
1206
- const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => this._patchConfig(configList[j], runManager?.getChild())), batchOptions);
1216
+ const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => (0, config_js_1.patchConfig)(configList[j], {
1217
+ callbacks: runManager?.getChild(),
1218
+ })), batchOptions);
1207
1219
  await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(outputs[i], "output"))));
1208
1220
  return outputs;
1209
1221
  }
@@ -1290,7 +1302,7 @@ class RunnableAssign extends Runnable {
1290
1302
  // create two input gens, one for the mapper, one for the input
1291
1303
  const [forPassthrough, forMapper] = (0, stream_js_1.atee)(generator);
1292
1304
  // create mapper output gen
1293
- const mapperOutput = this.mapper.transform(forMapper, this._patchConfig(options, runManager?.getChild()));
1305
+ const mapperOutput = this.mapper.transform(forMapper, (0, config_js_1.patchConfig)(options, { callbacks: runManager?.getChild() }));
1294
1306
  // start the mapper
1295
1307
  const firstMapperChunkPromise = mapperOutput.next();
1296
1308
  // yield the passthrough
@@ -1,4 +1,4 @@
1
- import { CallbackManager, CallbackManagerForChainRun } from "../callbacks/manager.js";
1
+ import { CallbackManagerForChainRun } from "../callbacks/manager.js";
2
2
  import { LogStreamCallbackHandlerInput, RunLogPatch } from "../tracers/log_stream.js";
3
3
  import { Serializable } from "../load/serializable.js";
4
4
  import { IterableReadableStream, type IterableReadableStreamInterface } from "../utils/stream.js";
@@ -33,6 +33,7 @@ export type RunnableMapLike<RunInput, RunOutput> = {
33
33
  };
34
34
  export type RunnableLike<RunInput = any, RunOutput = any> = RunnableInterface<RunInput, RunOutput> | RunnableFunc<RunInput, RunOutput> | RunnableMapLike<RunInput, RunOutput>;
35
35
  export type RunnableBatchOptions = {
36
+ /** @deprecated Pass in via the standard runnable config object instead */
36
37
  maxConcurrency?: number;
37
38
  returnExceptions?: boolean;
38
39
  };
@@ -89,7 +90,6 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
89
90
  * Subclasses should override this method if they can batch more efficiently.
90
91
  * @param inputs Array of inputs to each batch call.
91
92
  * @param options Either a single call options object to apply to each batch call or an array for each call.
92
- * @param batchOptions.maxConcurrency Maximum number of calls to run at once.
93
93
  * @param batchOptions.returnExceptions Whether to return errors rather than throwing on the first one
94
94
  * @returns An array of RunOutputs, or mixed RunOutputs and errors if batchOptions.returnExceptions is set
95
95
  */
@@ -140,7 +140,6 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
140
140
  protected _transformStreamWithConfig<I extends RunInput, O extends RunOutput>(inputGenerator: AsyncGenerator<I>, transformer: (generator: AsyncGenerator<I>, runManager?: CallbackManagerForChainRun, options?: Partial<CallOptions>) => AsyncGenerator<O>, options?: CallOptions & {
141
141
  runType?: string;
142
142
  }): AsyncGenerator<O>;
143
- _patchConfig(config?: Partial<CallOptions>, callbackManager?: CallbackManager | undefined, recursionLimit?: number | undefined): Partial<CallOptions>;
144
143
  /**
145
144
  * Create a new runnable sequence that runs each individual runnable in series,
146
145
  * piping the output of one runnable into another runnable or runnable-like.
@@ -263,7 +262,7 @@ export declare class RunnableEach<RunInputItem, RunOutputItem, CallOptions exten
263
262
  });
264
263
  /**
265
264
  * Binds the runnable with the specified arguments.
266
- * @param args The arguments to bind the runnable with.
265
+ * @param kwargs The arguments to bind the runnable with.
267
266
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
268
267
  */
269
268
  bind(kwargs: Partial<CallOptions>): RunnableEach<RunInputItem, RunOutputItem, CallOptions>;
@@ -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, 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
@@ -111,8 +111,9 @@ export class Runnable extends Serializable {
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
  },
@@ -238,7 +239,13 @@ export class Runnable extends Serializable {
238
239
  try {
239
240
  const pipe = await pipeGeneratorWithSetup(transformer, wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, undefined, options?.runType, undefined, undefined, options?.runName ?? this.getName()), options);
240
241
  runManager = pipe.setup;
241
- for await (const chunk of pipe.output) {
242
+ const isLogStreamHandler = (handler) => handler.name === "log_stream_tracer";
243
+ const streamLogHandler = runManager?.handlers.find(isLogStreamHandler);
244
+ let iterator = pipe.output;
245
+ if (streamLogHandler !== undefined && runManager !== undefined) {
246
+ iterator = await streamLogHandler.tapOutputIterable(runManager.runId, pipe.output);
247
+ }
248
+ for await (const chunk of iterator) {
242
249
  yield chunk;
243
250
  if (finalOutputSupported) {
244
251
  if (finalOutput === undefined) {
@@ -265,21 +272,6 @@ export class Runnable extends Serializable {
265
272
  }
266
273
  await runManager?.handleChainEnd(finalOutput ?? {}, undefined, undefined, undefined, { inputs: _coerceToDict(finalInput, "input") });
267
274
  }
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
275
  /**
284
276
  * Create a new runnable sequence that runs each individual runnable in series,
285
277
  * piping the output of one runnable into another runnable or runnable-like.
@@ -604,7 +596,7 @@ export class RunnableEach extends Runnable {
604
596
  }
605
597
  /**
606
598
  * Binds the runnable with the specified arguments.
607
- * @param args The arguments to bind the runnable with.
599
+ * @param kwargs The arguments to bind the runnable with.
608
600
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
609
601
  */
610
602
  bind(kwargs) {
@@ -628,7 +620,7 @@ export class RunnableEach extends Runnable {
628
620
  * @returns A promise that resolves to the output of the runnable.
629
621
  */
630
622
  async _invoke(inputs, config, runManager) {
631
- return this.bound.batch(inputs, this._patchConfig(config, runManager?.getChild()));
623
+ return this.bound.batch(inputs, patchConfig(config, { callbacks: runManager?.getChild() }));
632
624
  }
633
625
  /**
634
626
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -681,7 +673,7 @@ export class RunnableRetry extends RunnableBinding {
681
673
  }
682
674
  _patchConfigForRetry(attempt, config, runManager) {
683
675
  const tag = attempt > 1 ? `retry:attempt:${attempt}` : undefined;
684
- return this._patchConfig(config, runManager?.getChild(tag));
676
+ return patchConfig(config, { callbacks: runManager?.getChild(tag) });
685
677
  }
686
678
  async _invoke(input, config, runManager) {
687
679
  return pRetry((attemptNumber) => super.invoke(input, this._patchConfigForRetry(attemptNumber, config, runManager)), {
@@ -818,10 +810,14 @@ export class RunnableSequence extends Runnable {
818
810
  const initialSteps = [this.first, ...this.middle];
819
811
  for (let i = 0; i < initialSteps.length; i += 1) {
820
812
  const step = initialSteps[i];
821
- nextStepInput = await step.invoke(nextStepInput, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
813
+ nextStepInput = await step.invoke(nextStepInput, patchConfig(options, {
814
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
815
+ }));
822
816
  }
823
817
  // 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}`)));
818
+ finalOutput = await this.last.invoke(nextStepInput, patchConfig(options, {
819
+ callbacks: runManager?.getChild(`seq:step:${this.steps.length}`),
820
+ }));
825
821
  }
826
822
  catch (e) {
827
823
  await runManager?.handleChainError(e);
@@ -836,21 +832,21 @@ export class RunnableSequence extends Runnable {
836
832
  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
833
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
838
834
  let nextStepInputs = inputs;
839
- let finalOutputs;
840
835
  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);
836
+ for (let i = 0; i < this.steps.length; i += 1) {
837
+ const step = this.steps[i];
838
+ nextStepInputs = await step.batch(nextStepInputs, runManagers.map((runManager, j) => {
839
+ const childRunManager = runManager?.getChild(`seq:step:${i + 1}`);
840
+ return patchConfig(configList[j], { callbacks: childRunManager });
841
+ }), batchOptions);
845
842
  }
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
843
  }
848
844
  catch (e) {
849
845
  await Promise.all(runManagers.map((runManager) => runManager?.handleChainError(e)));
850
846
  throw e;
851
847
  }
852
- await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(finalOutputs[i], "output"))));
853
- return finalOutputs;
848
+ await Promise.all(runManagers.map((runManager) => runManager?.handleChainEnd(_coerceToDict(nextStepInputs, "output"))));
849
+ return nextStepInputs;
854
850
  }
855
851
  async *_streamIterator(input, options) {
856
852
  const callbackManager_ = await getCallbackManagerForConfig(options);
@@ -862,10 +858,14 @@ export class RunnableSequence extends Runnable {
862
858
  yield input;
863
859
  }
864
860
  try {
865
- let finalGenerator = steps[0].transform(inputGenerator(), this._patchConfig(options, runManager?.getChild(`seq:step:1`)));
861
+ let finalGenerator = steps[0].transform(inputGenerator(), patchConfig(options, {
862
+ callbacks: runManager?.getChild(`seq:step:1`),
863
+ }));
866
864
  for (let i = 1; i < steps.length; i += 1) {
867
865
  const step = steps[i];
868
- finalGenerator = await step.transform(finalGenerator, this._patchConfig(options, runManager?.getChild(`seq:step:${i + 1}`)));
866
+ finalGenerator = await step.transform(finalGenerator, patchConfig(options, {
867
+ callbacks: runManager?.getChild(`seq:step:${i + 1}`),
868
+ }));
869
869
  }
870
870
  for await (const chunk of finalGenerator) {
871
871
  yield chunk;
@@ -988,7 +988,9 @@ export class RunnableMap extends Runnable {
988
988
  const output = {};
989
989
  try {
990
990
  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}`)));
991
+ output[key] = await runnable.invoke(input, patchConfig(options, {
992
+ callbacks: runManager?.getChild(`map:key:${key}`),
993
+ }));
992
994
  }));
993
995
  }
994
996
  catch (e) {
@@ -1005,7 +1007,9 @@ export class RunnableMap extends Runnable {
1005
1007
  const inputCopies = atee(generator, Object.keys(steps).length);
1006
1008
  // start the first iteration of each output iterator
1007
1009
  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}`)));
1010
+ const gen = runnable.transform(inputCopies[i], patchConfig(options, {
1011
+ callbacks: runManager?.getChild(`map:key:${key}`),
1012
+ }));
1009
1013
  return [key, gen.next().then((result) => ({ key, gen, result }))];
1010
1014
  }));
1011
1015
  // yield chunks as they become available,
@@ -1064,7 +1068,10 @@ export class RunnableLambda extends Runnable {
1064
1068
  if (config?.recursionLimit === 0) {
1065
1069
  throw new Error("Recursion limit reached.");
1066
1070
  }
1067
- output = await output.invoke(input, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1));
1071
+ output = await output.invoke(input, patchConfig(config, {
1072
+ callbacks: runManager?.getChild(),
1073
+ recursionLimit: (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1,
1074
+ }));
1068
1075
  }
1069
1076
  return output;
1070
1077
  }
@@ -1093,7 +1100,10 @@ export class RunnableLambda extends Runnable {
1093
1100
  if (config?.recursionLimit === 0) {
1094
1101
  throw new Error("Recursion limit reached.");
1095
1102
  }
1096
- const stream = await output.stream(finalChunk, this._patchConfig(config, runManager?.getChild(), (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1));
1103
+ const stream = await output.stream(finalChunk, patchConfig(config, {
1104
+ callbacks: runManager?.getChild(),
1105
+ recursionLimit: (config?.recursionLimit ?? DEFAULT_RECURSION_LIMIT) - 1,
1106
+ }));
1097
1107
  for await (const chunk of stream) {
1098
1108
  yield chunk;
1099
1109
  }
@@ -1162,7 +1172,7 @@ export class RunnableWithFallbacks extends Runnable {
1162
1172
  let firstError;
1163
1173
  for (const runnable of this.runnables()) {
1164
1174
  try {
1165
- const output = await runnable.invoke(input, this._patchConfig(options, runManager?.getChild()));
1175
+ const output = await runnable.invoke(input, patchConfig(options, { callbacks: runManager?.getChild() }));
1166
1176
  await runManager?.handleChainEnd(_coerceToDict(output, "output"));
1167
1177
  return output;
1168
1178
  }
@@ -1189,7 +1199,9 @@ export class RunnableWithFallbacks extends Runnable {
1189
1199
  let firstError;
1190
1200
  for (const runnable of this.runnables()) {
1191
1201
  try {
1192
- const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => this._patchConfig(configList[j], runManager?.getChild())), batchOptions);
1202
+ const outputs = await runnable.batch(inputs, runManagers.map((runManager, j) => patchConfig(configList[j], {
1203
+ callbacks: runManager?.getChild(),
1204
+ })), batchOptions);
1193
1205
  await Promise.all(runManagers.map((runManager, i) => runManager?.handleChainEnd(_coerceToDict(outputs[i], "output"))));
1194
1206
  return outputs;
1195
1207
  }
@@ -1274,7 +1286,7 @@ export class RunnableAssign extends Runnable {
1274
1286
  // create two input gens, one for the mapper, one for the input
1275
1287
  const [forPassthrough, forMapper] = atee(generator);
1276
1288
  // create mapper output gen
1277
- const mapperOutput = this.mapper.transform(forMapper, this._patchConfig(options, runManager?.getChild()));
1289
+ const mapperOutput = this.mapper.transform(forMapper, patchConfig(options, { callbacks: runManager?.getChild() }));
1278
1290
  // start the mapper
1279
1291
  const firstMapperChunkPromise = mapperOutput.next();
1280
1292
  // 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,6 +1,6 @@
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) {
@@ -79,3 +79,44 @@ options) {
79
79
  return copy;
80
80
  }
81
81
  exports.mergeConfigs = mergeConfigs;
82
+ /**
83
+ * Ensure that a passed config is an object with all required keys present.
84
+ */
85
+ function ensureConfig(config) {
86
+ return {
87
+ tags: [],
88
+ metadata: {},
89
+ callbacks: undefined,
90
+ recursionLimit: 25,
91
+ ...config,
92
+ };
93
+ }
94
+ exports.ensureConfig = ensureConfig;
95
+ /**
96
+ * Helper function that patches runnable configs with updated properties.
97
+ */
98
+ function patchConfig(config = {}, { callbacks, maxConcurrency, recursionLimit, runName, configurable, } = {}) {
99
+ const newConfig = ensureConfig(config);
100
+ if (callbacks !== undefined) {
101
+ /**
102
+ * If we're replacing callbacks we need to unset runName
103
+ * since that should apply only to the same run as the original callbacks
104
+ */
105
+ delete newConfig.runName;
106
+ newConfig.callbacks = callbacks;
107
+ }
108
+ if (recursionLimit !== undefined) {
109
+ newConfig.recursionLimit = recursionLimit;
110
+ }
111
+ if (maxConcurrency !== undefined) {
112
+ newConfig.maxConcurrency = maxConcurrency;
113
+ }
114
+ if (runName !== undefined) {
115
+ newConfig.runName = runName;
116
+ }
117
+ if (configurable !== undefined) {
118
+ newConfig.configurable = { ...newConfig.configurable, ...configurable };
119
+ }
120
+ return newConfig;
121
+ }
122
+ 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
17
  export declare function mergeConfigs<CallOptions extends RunnableConfig>(config: RunnableConfig, options?: Record<string, any>): 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): Partial<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>;
@@ -74,3 +74,42 @@ options) {
74
74
  }
75
75
  return copy;
76
76
  }
77
+ /**
78
+ * Ensure that a passed config is an object with all required keys present.
79
+ */
80
+ export function ensureConfig(config) {
81
+ return {
82
+ tags: [],
83
+ metadata: {},
84
+ callbacks: undefined,
85
+ recursionLimit: 25,
86
+ ...config,
87
+ };
88
+ }
89
+ /**
90
+ * Helper function that patches runnable configs with updated properties.
91
+ */
92
+ export function patchConfig(config = {}, { callbacks, maxConcurrency, recursionLimit, runName, configurable, } = {}) {
93
+ const newConfig = ensureConfig(config);
94
+ if (callbacks !== undefined) {
95
+ /**
96
+ * If we're replacing callbacks we need to unset runName
97
+ * since that should apply only to the same run as the original callbacks
98
+ */
99
+ delete newConfig.runName;
100
+ newConfig.callbacks = callbacks;
101
+ }
102
+ if (recursionLimit !== undefined) {
103
+ newConfig.recursionLimit = recursionLimit;
104
+ }
105
+ if (maxConcurrency !== undefined) {
106
+ newConfig.maxConcurrency = maxConcurrency;
107
+ }
108
+ if (runName !== undefined) {
109
+ newConfig.runName = runName;
110
+ }
111
+ if (configurable !== undefined) {
112
+ newConfig.configurable = { ...newConfig.configurable, ...configurable };
113
+ }
114
+ return newConfig;
115
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RunnableWithMessageHistory = exports.RunnableBranch = exports.RouterRunnable = exports.RunnablePassthrough = exports.getCallbackManagerForConfig = exports._coerceToRunnable = exports.RunnablePick = exports.RunnableAssign = exports.RunnableWithFallbacks = exports.RunnableLambda = exports.RunnableParallel = exports.RunnableMap = exports.RunnableSequence = exports.RunnableRetry = exports.RunnableEach = exports.RunnableBinding = exports.Runnable = void 0;
3
+ exports.RunnableWithMessageHistory = exports.RunnableBranch = exports.RouterRunnable = exports.RunnablePassthrough = exports.patchConfig = exports.getCallbackManagerForConfig = exports._coerceToRunnable = exports.RunnablePick = exports.RunnableAssign = exports.RunnableWithFallbacks = exports.RunnableLambda = exports.RunnableParallel = exports.RunnableMap = exports.RunnableSequence = exports.RunnableRetry = exports.RunnableEach = exports.RunnableBinding = exports.Runnable = void 0;
4
4
  var base_js_1 = require("./base.cjs");
5
5
  Object.defineProperty(exports, "Runnable", { enumerable: true, get: function () { return base_js_1.Runnable; } });
6
6
  Object.defineProperty(exports, "RunnableBinding", { enumerable: true, get: function () { return base_js_1.RunnableBinding; } });
@@ -16,6 +16,7 @@ Object.defineProperty(exports, "RunnablePick", { enumerable: true, get: function
16
16
  Object.defineProperty(exports, "_coerceToRunnable", { enumerable: true, get: function () { return base_js_1._coerceToRunnable; } });
17
17
  var config_js_1 = require("./config.cjs");
18
18
  Object.defineProperty(exports, "getCallbackManagerForConfig", { enumerable: true, get: function () { return config_js_1.getCallbackManagerForConfig; } });
19
+ Object.defineProperty(exports, "patchConfig", { enumerable: true, get: function () { return config_js_1.patchConfig; } });
19
20
  var passthrough_js_1 = require("./passthrough.cjs");
20
21
  Object.defineProperty(exports, "RunnablePassthrough", { enumerable: true, get: function () { return passthrough_js_1.RunnablePassthrough; } });
21
22
  var router_js_1 = require("./router.cjs");
@@ -1,5 +1,5 @@
1
1
  export { type RunnableFunc, type RunnableLike, type RunnableBatchOptions, type RunnableRetryFailedAttemptHandler, Runnable, type RunnableInterface, type RunnableBindingArgs, RunnableBinding, RunnableEach, RunnableRetry, RunnableSequence, RunnableMap, RunnableParallel, RunnableLambda, RunnableWithFallbacks, RunnableAssign, RunnablePick, _coerceToRunnable, } from "./base.js";
2
- export { type RunnableConfig, getCallbackManagerForConfig } from "./config.js";
2
+ export { type RunnableConfig, getCallbackManagerForConfig, patchConfig, } from "./config.js";
3
3
  export { RunnablePassthrough } from "./passthrough.js";
4
4
  export { type RouterInput, RouterRunnable } from "./router.js";
5
5
  export { RunnableBranch, type Branch, type BranchLike } from "./branch.js";
@@ -1,5 +1,5 @@
1
1
  export { Runnable, RunnableBinding, RunnableEach, RunnableRetry, RunnableSequence, RunnableMap, RunnableParallel, RunnableLambda, RunnableWithFallbacks, RunnableAssign, RunnablePick, _coerceToRunnable, } from "./base.js";
2
- export { getCallbackManagerForConfig } from "./config.js";
2
+ export { getCallbackManagerForConfig, patchConfig, } from "./config.js";
3
3
  export { RunnablePassthrough } from "./passthrough.js";
4
4
  export { RouterRunnable } from "./router.js";
5
5
  export { RunnableBranch } from "./branch.js";
@@ -49,9 +49,8 @@ class RouterRunnable extends base_js_1.Runnable {
49
49
  }
50
50
  const runnables = keys.map((key) => this.runnables[key]);
51
51
  const optionsList = this._getOptionsList(options ?? {}, inputs.length);
52
- const batchSize = batchOptions?.maxConcurrency && batchOptions.maxConcurrency > 0
53
- ? batchOptions?.maxConcurrency
54
- : inputs.length;
52
+ const maxConcurrency = optionsList[0]?.maxConcurrency ?? batchOptions?.maxConcurrency;
53
+ const batchSize = maxConcurrency && maxConcurrency > 0 ? maxConcurrency : inputs.length;
55
54
  const batchResults = [];
56
55
  for (let i = 0; i < actualInputs.length; i += batchSize) {
57
56
  const batchPromises = actualInputs
@@ -46,9 +46,8 @@ export class RouterRunnable extends Runnable {
46
46
  }
47
47
  const runnables = keys.map((key) => this.runnables[key]);
48
48
  const optionsList = this._getOptionsList(options ?? {}, inputs.length);
49
- const batchSize = batchOptions?.maxConcurrency && batchOptions.maxConcurrency > 0
50
- ? batchOptions?.maxConcurrency
51
- : inputs.length;
49
+ const maxConcurrency = optionsList[0]?.maxConcurrency ?? batchOptions?.maxConcurrency;
50
+ const batchSize = maxConcurrency && maxConcurrency > 0 ? maxConcurrency : inputs.length;
52
51
  const batchResults = [];
53
52
  for (let i = 0; i < actualInputs.length; i += batchSize) {
54
53
  const batchPromises = actualInputs
@@ -47,9 +47,16 @@ class BaseTracer extends base_js_1.BaseCallbackHandler {
47
47
  ].join(".");
48
48
  }
49
49
  else {
50
- console.warn(`Parent run with UUID ${storedRun.parent_run_id} not found.`);
50
+ // This can happen naturally for callbacks added within a run
51
+ // console.debug(`Parent run with UUID ${storedRun.parent_run_id} has no dotted order.`);
51
52
  }
52
53
  }
54
+ else {
55
+ // This can happen naturally for callbacks added within a run
56
+ // console.debug(
57
+ // `Parent run with UUID ${storedRun.parent_run_id} not found.`
58
+ // );
59
+ }
53
60
  }
54
61
  else {
55
62
  storedRun.trace_id = storedRun.id;
@@ -44,9 +44,16 @@ export class BaseTracer extends BaseCallbackHandler {
44
44
  ].join(".");
45
45
  }
46
46
  else {
47
- console.warn(`Parent run with UUID ${storedRun.parent_run_id} not found.`);
47
+ // This can happen naturally for callbacks added within a run
48
+ // console.debug(`Parent run with UUID ${storedRun.parent_run_id} has no dotted order.`);
48
49
  }
49
50
  }
51
+ else {
52
+ // This can happen naturally for callbacks added within a run
53
+ // console.debug(
54
+ // `Parent run with UUID ${storedRun.parent_run_id} not found.`
55
+ // );
56
+ }
50
57
  }
51
58
  else {
52
59
  storedRun.trace_id = storedRun.id;
@@ -101,6 +101,12 @@ class LogStreamCallbackHandler extends base_js_1.BaseTracer {
101
101
  writable: true,
102
102
  value: void 0
103
103
  });
104
+ Object.defineProperty(this, "rootId", {
105
+ enumerable: true,
106
+ configurable: true,
107
+ writable: true,
108
+ value: void 0
109
+ });
104
110
  Object.defineProperty(this, "keyMapByRunId", {
105
111
  enumerable: true,
106
112
  configurable: true,
@@ -156,7 +162,7 @@ class LogStreamCallbackHandler extends base_js_1.BaseTracer {
156
162
  // and is therefore not useful here
157
163
  }
158
164
  _includeRun(run) {
159
- if (run.parent_run_id === undefined) {
165
+ if (run.id === this.rootId) {
160
166
  return false;
161
167
  }
162
168
  const runTags = run.tags ?? [];
@@ -186,8 +192,32 @@ class LogStreamCallbackHandler extends base_js_1.BaseTracer {
186
192
  }
187
193
  return include;
188
194
  }
195
+ async *tapOutputIterable(runId, output) {
196
+ // Tap an output async iterator to stream its values to the log.
197
+ for await (const chunk of output) {
198
+ // root run is handled in .streamLog()
199
+ if (runId !== this.rootId) {
200
+ // if we can't find the run silently ignore
201
+ // eg. because this run wasn't included in the log
202
+ const key = this.keyMapByRunId[runId];
203
+ if (key) {
204
+ await this.writer.write(new RunLogPatch({
205
+ ops: [
206
+ {
207
+ op: "add",
208
+ path: `/logs/${key}/streamed_output/-`,
209
+ value: chunk,
210
+ },
211
+ ],
212
+ }));
213
+ }
214
+ }
215
+ yield chunk;
216
+ }
217
+ }
189
218
  async onRunCreate(run) {
190
- if (run.parent_run_id === undefined) {
219
+ if (this.rootId === undefined) {
220
+ this.rootId = run.id;
191
221
  await this.writer.write(new RunLogPatch({
192
222
  ops: [
193
223
  {
@@ -220,6 +250,7 @@ class LogStreamCallbackHandler extends base_js_1.BaseTracer {
220
250
  tags: run.tags ?? [],
221
251
  metadata: run.extra?.metadata ?? {},
222
252
  start_time: new Date(run.start_time).toISOString(),
253
+ streamed_output: [],
223
254
  streamed_output_str: [],
224
255
  final_output: undefined,
225
256
  end_time: undefined,
@@ -258,7 +289,7 @@ class LogStreamCallbackHandler extends base_js_1.BaseTracer {
258
289
  await this.writer.write(patch);
259
290
  }
260
291
  finally {
261
- if (run.parent_run_id === undefined) {
292
+ if (run.id === this.rootId) {
262
293
  const patch = new RunLogPatch({
263
294
  ops: [
264
295
  {
@@ -19,6 +19,8 @@ export type LogEntry = {
19
19
  metadata: Record<string, any>;
20
20
  /** ISO-8601 timestamp of when the run started. */
21
21
  start_time: string;
22
+ /** List of general output chunks streamed by this run. */
23
+ streamed_output: any[];
22
24
  /** List of LLM tokens streamed by this run, if applicable. */
23
25
  streamed_output_str: string[];
24
26
  /** Final output of this run. Only available after the run has finished successfully. */
@@ -84,6 +86,7 @@ export declare class LogStreamCallbackHandler extends BaseTracer {
84
86
  protected excludeNames?: string[];
85
87
  protected excludeTypes?: string[];
86
88
  protected excludeTags?: string[];
89
+ protected rootId?: string;
87
90
  private keyMapByRunId;
88
91
  private counterMapByRunName;
89
92
  protected transformStream: TransformStream;
@@ -94,6 +97,7 @@ export declare class LogStreamCallbackHandler extends BaseTracer {
94
97
  [Symbol.asyncIterator](): IterableReadableStream<RunLogPatch>;
95
98
  protected persistRun(_run: Run): Promise<void>;
96
99
  _includeRun(run: Run): boolean;
100
+ tapOutputIterable<T>(runId: string, output: AsyncGenerator<T>): AsyncGenerator<T>;
97
101
  onRunCreate(run: Run): Promise<void>;
98
102
  onRunUpdate(run: Run): Promise<void>;
99
103
  onLLMNewToken(run: Run, token: string): Promise<void>;
@@ -96,6 +96,12 @@ export class LogStreamCallbackHandler extends BaseTracer {
96
96
  writable: true,
97
97
  value: void 0
98
98
  });
99
+ Object.defineProperty(this, "rootId", {
100
+ enumerable: true,
101
+ configurable: true,
102
+ writable: true,
103
+ value: void 0
104
+ });
99
105
  Object.defineProperty(this, "keyMapByRunId", {
100
106
  enumerable: true,
101
107
  configurable: true,
@@ -151,7 +157,7 @@ export class LogStreamCallbackHandler extends BaseTracer {
151
157
  // and is therefore not useful here
152
158
  }
153
159
  _includeRun(run) {
154
- if (run.parent_run_id === undefined) {
160
+ if (run.id === this.rootId) {
155
161
  return false;
156
162
  }
157
163
  const runTags = run.tags ?? [];
@@ -181,8 +187,32 @@ export class LogStreamCallbackHandler extends BaseTracer {
181
187
  }
182
188
  return include;
183
189
  }
190
+ async *tapOutputIterable(runId, output) {
191
+ // Tap an output async iterator to stream its values to the log.
192
+ for await (const chunk of output) {
193
+ // root run is handled in .streamLog()
194
+ if (runId !== this.rootId) {
195
+ // if we can't find the run silently ignore
196
+ // eg. because this run wasn't included in the log
197
+ const key = this.keyMapByRunId[runId];
198
+ if (key) {
199
+ await this.writer.write(new RunLogPatch({
200
+ ops: [
201
+ {
202
+ op: "add",
203
+ path: `/logs/${key}/streamed_output/-`,
204
+ value: chunk,
205
+ },
206
+ ],
207
+ }));
208
+ }
209
+ }
210
+ yield chunk;
211
+ }
212
+ }
184
213
  async onRunCreate(run) {
185
- if (run.parent_run_id === undefined) {
214
+ if (this.rootId === undefined) {
215
+ this.rootId = run.id;
186
216
  await this.writer.write(new RunLogPatch({
187
217
  ops: [
188
218
  {
@@ -215,6 +245,7 @@ export class LogStreamCallbackHandler extends BaseTracer {
215
245
  tags: run.tags ?? [],
216
246
  metadata: run.extra?.metadata ?? {},
217
247
  start_time: new Date(run.start_time).toISOString(),
248
+ streamed_output: [],
218
249
  streamed_output_str: [],
219
250
  final_output: undefined,
220
251
  end_time: undefined,
@@ -253,7 +284,7 @@ export class LogStreamCallbackHandler extends BaseTracer {
253
284
  await this.writer.write(patch);
254
285
  }
255
286
  finally {
256
- if (run.parent_run_id === undefined) {
287
+ if (run.id === this.rootId) {
257
288
  const patch = new RunLogPatch({
258
289
  ops: [
259
290
  {
@@ -99,16 +99,27 @@ class FakeStreamingLLM extends llms_js_1.LLM {
99
99
  writable: true,
100
100
  value: 50
101
101
  });
102
+ Object.defineProperty(this, "responses", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: void 0
107
+ });
102
108
  this.sleep = fields.sleep ?? this.sleep;
109
+ this.responses = fields.responses;
103
110
  }
104
111
  _llmType() {
105
112
  return "fake";
106
113
  }
107
114
  async _call(prompt) {
108
- return prompt;
115
+ const response = this.responses?.[0];
116
+ this.responses = this.responses?.slice(1);
117
+ return response ?? prompt;
109
118
  }
110
119
  async *_streamResponseChunks(input) {
111
- for (const c of input) {
120
+ const response = this.responses?.[0];
121
+ this.responses = this.responses?.slice(1);
122
+ for (const c of response ?? input) {
112
123
  await new Promise((resolve) => setTimeout(resolve, this.sleep));
113
124
  yield { text: c, generationInfo: {} };
114
125
  }
@@ -40,8 +40,10 @@ export declare class FakeLLM extends LLM {
40
40
  }
41
41
  export declare class FakeStreamingLLM extends LLM {
42
42
  sleep?: number;
43
+ responses?: string[];
43
44
  constructor(fields: {
44
45
  sleep?: number;
46
+ responses?: string[];
45
47
  } & BaseLLMParams);
46
48
  _llmType(): string;
47
49
  _call(prompt: string): Promise<string>;
@@ -93,16 +93,27 @@ export class FakeStreamingLLM extends LLM {
93
93
  writable: true,
94
94
  value: 50
95
95
  });
96
+ Object.defineProperty(this, "responses", {
97
+ enumerable: true,
98
+ configurable: true,
99
+ writable: true,
100
+ value: void 0
101
+ });
96
102
  this.sleep = fields.sleep ?? this.sleep;
103
+ this.responses = fields.responses;
97
104
  }
98
105
  _llmType() {
99
106
  return "fake";
100
107
  }
101
108
  async _call(prompt) {
102
- return prompt;
109
+ const response = this.responses?.[0];
110
+ this.responses = this.responses?.slice(1);
111
+ return response ?? prompt;
103
112
  }
104
113
  async *_streamResponseChunks(input) {
105
- for (const c of input) {
114
+ const response = this.responses?.[0];
115
+ this.responses = this.responses?.slice(1);
116
+ for (const c of response ?? input) {
106
117
  await new Promise((resolve) => setTimeout(resolve, this.sleep));
107
118
  yield { text: c, generationInfo: {} };
108
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {
@@ -18,7 +18,7 @@
18
18
  "build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && node scripts/move-cjs-to-dist.js && rimraf dist-cjs",
19
19
  "build:watch": "node scripts/create-entrypoints.js && tsc --outDir dist/ --watch",
20
20
  "build:scripts": "node scripts/create-entrypoints.js && node scripts/check-tree-shaking.js",
21
- "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint src",
21
+ "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
22
22
  "lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
23
23
  "lint": "yarn lint:eslint && yarn lint:dpdm",
24
24
  "lint:fix": "yarn lint:eslint --fix && yarn lint:dpdm",