@langchain/core 0.2.0 → 0.2.1

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 (113) hide show
  1. package/dist/callbacks/tests/callbacks.test.d.ts +1 -0
  2. package/dist/callbacks/tests/callbacks.test.js +492 -0
  3. package/dist/callbacks/tests/manager.int.test.d.ts +1 -0
  4. package/dist/callbacks/tests/manager.int.test.js +29 -0
  5. package/dist/callbacks/tests/run_collector.test.d.ts +1 -0
  6. package/dist/callbacks/tests/run_collector.test.js +58 -0
  7. package/dist/chat_history.cjs +13 -0
  8. package/dist/chat_history.d.ts +9 -0
  9. package/dist/chat_history.js +13 -0
  10. package/dist/language_models/chat_models.d.ts +2 -2
  11. package/dist/language_models/tests/chat_models.test.d.ts +1 -0
  12. package/dist/language_models/tests/chat_models.test.js +154 -0
  13. package/dist/language_models/tests/count_tokens.test.d.ts +1 -0
  14. package/dist/language_models/tests/count_tokens.test.js +19 -0
  15. package/dist/language_models/tests/llms.test.d.ts +1 -0
  16. package/dist/language_models/tests/llms.test.js +39 -0
  17. package/dist/messages/tests/base_message.test.d.ts +1 -0
  18. package/dist/messages/tests/base_message.test.js +97 -0
  19. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.d.ts +1 -0
  20. package/dist/output_parsers/openai_tools/tests/json_output_tools_parser.test.js +81 -0
  21. package/dist/output_parsers/tests/json.test.d.ts +1 -0
  22. package/dist/output_parsers/tests/json.test.js +427 -0
  23. package/dist/output_parsers/tests/output_parser.test.d.ts +1 -0
  24. package/dist/output_parsers/tests/output_parser.test.js +78 -0
  25. package/dist/output_parsers/tests/string.test.d.ts +1 -0
  26. package/dist/output_parsers/tests/string.test.js +68 -0
  27. package/dist/output_parsers/tests/structured.test.d.ts +1 -0
  28. package/dist/output_parsers/tests/structured.test.js +166 -0
  29. package/dist/output_parsers/tests/xml.test.d.ts +1 -0
  30. package/dist/output_parsers/tests/xml.test.js +81 -0
  31. package/dist/prompts/tests/chat.mustache.test.d.ts +1 -0
  32. package/dist/prompts/tests/chat.mustache.test.js +61 -0
  33. package/dist/prompts/tests/chat.test.d.ts +1 -0
  34. package/dist/prompts/tests/chat.test.js +507 -0
  35. package/dist/prompts/tests/few_shot.test.d.ts +1 -0
  36. package/dist/prompts/tests/few_shot.test.js +224 -0
  37. package/dist/prompts/tests/pipeline.test.d.ts +1 -0
  38. package/dist/prompts/tests/pipeline.test.js +101 -0
  39. package/dist/prompts/tests/prompt.mustache.test.d.ts +1 -0
  40. package/dist/prompts/tests/prompt.mustache.test.js +85 -0
  41. package/dist/prompts/tests/prompt.test.d.ts +1 -0
  42. package/dist/prompts/tests/prompt.test.js +78 -0
  43. package/dist/prompts/tests/structured.test.d.ts +1 -0
  44. package/dist/prompts/tests/structured.test.js +37 -0
  45. package/dist/prompts/tests/template.test.d.ts +1 -0
  46. package/dist/prompts/tests/template.test.js +24 -0
  47. package/dist/runnables/base.cjs +87 -6
  48. package/dist/runnables/base.d.ts +45 -26
  49. package/dist/runnables/base.js +87 -6
  50. package/dist/runnables/history.cjs +87 -32
  51. package/dist/runnables/history.d.ts +1 -1
  52. package/dist/runnables/history.js +87 -32
  53. package/dist/runnables/remote.cjs +2 -2
  54. package/dist/runnables/remote.d.ts +3 -3
  55. package/dist/runnables/remote.js +2 -2
  56. package/dist/runnables/tests/runnable.test.d.ts +1 -0
  57. package/dist/runnables/tests/runnable.test.js +491 -0
  58. package/dist/runnables/tests/runnable_binding.test.d.ts +1 -0
  59. package/dist/runnables/tests/runnable_binding.test.js +46 -0
  60. package/dist/runnables/tests/runnable_branch.test.d.ts +1 -0
  61. package/dist/runnables/tests/runnable_branch.test.js +116 -0
  62. package/dist/runnables/tests/runnable_graph.test.d.ts +1 -0
  63. package/dist/runnables/tests/runnable_graph.test.js +84 -0
  64. package/dist/runnables/tests/runnable_history.test.d.ts +1 -0
  65. package/dist/runnables/tests/runnable_history.test.js +177 -0
  66. package/dist/runnables/tests/runnable_interface.test.d.ts +1 -0
  67. package/dist/runnables/tests/runnable_interface.test.js +209 -0
  68. package/dist/runnables/tests/runnable_map.test.d.ts +1 -0
  69. package/dist/runnables/tests/runnable_map.test.js +238 -0
  70. package/dist/runnables/tests/runnable_passthrough.test.d.ts +1 -0
  71. package/dist/runnables/tests/runnable_passthrough.test.js +96 -0
  72. package/dist/runnables/tests/runnable_remote.int.test.d.ts +1 -0
  73. package/dist/runnables/tests/runnable_remote.int.test.js +138 -0
  74. package/dist/runnables/tests/runnable_remote.test.d.ts +1 -0
  75. package/dist/runnables/tests/runnable_remote.test.js +200 -0
  76. package/dist/runnables/tests/runnable_retry.test.d.ts +1 -0
  77. package/dist/runnables/tests/runnable_retry.test.js +125 -0
  78. package/dist/runnables/tests/runnable_stream_events.test.d.ts +1 -0
  79. package/dist/runnables/tests/runnable_stream_events.test.js +1013 -0
  80. package/dist/runnables/tests/runnable_stream_events_v2.test.d.ts +1 -0
  81. package/dist/runnables/tests/runnable_stream_events_v2.test.js +973 -0
  82. package/dist/runnables/tests/runnable_stream_log.test.d.ts +1 -0
  83. package/dist/runnables/tests/runnable_stream_log.test.js +282 -0
  84. package/dist/runnables/tests/runnable_tracing.int.test.d.ts +1 -0
  85. package/dist/runnables/tests/runnable_tracing.int.test.js +37 -0
  86. package/dist/runnables/tests/runnable_with_fallbacks.test.d.ts +1 -0
  87. package/dist/runnables/tests/runnable_with_fallbacks.test.js +36 -0
  88. package/dist/runnables/utils.d.ts +1 -1
  89. package/dist/singletons/tests/async_local_storage.test.d.ts +1 -0
  90. package/dist/singletons/tests/async_local_storage.test.js +120 -0
  91. package/dist/structured_query/tests/utils.test.d.ts +1 -0
  92. package/dist/structured_query/tests/utils.test.js +47 -0
  93. package/dist/tracers/event_stream.cjs +493 -0
  94. package/dist/tracers/event_stream.d.ts +137 -0
  95. package/dist/tracers/event_stream.js +489 -0
  96. package/dist/tracers/log_stream.d.ts +2 -77
  97. package/dist/tracers/tests/langchain_tracer.int.test.d.ts +1 -0
  98. package/dist/tracers/tests/langchain_tracer.int.test.js +74 -0
  99. package/dist/tracers/tests/tracer.test.d.ts +1 -0
  100. package/dist/tracers/tests/tracer.test.js +378 -0
  101. package/dist/utils/testing/tests/chatfake.test.d.ts +1 -0
  102. package/dist/utils/testing/tests/chatfake.test.js +112 -0
  103. package/dist/utils/tests/async_caller.test.d.ts +1 -0
  104. package/dist/utils/tests/async_caller.test.js +27 -0
  105. package/dist/utils/tests/enviroment.test.d.ts +1 -0
  106. package/dist/utils/tests/enviroment.test.js +6 -0
  107. package/dist/utils/tests/function_calling.test.d.ts +1 -0
  108. package/dist/utils/tests/function_calling.test.js +107 -0
  109. package/dist/utils/tests/math_utils.test.d.ts +1 -0
  110. package/dist/utils/tests/math_utils.test.js +139 -0
  111. package/dist/utils/tests/polyfill_stream.test.d.ts +1 -0
  112. package/dist/utils/tests/polyfill_stream.test.js +15 -0
  113. package/package.json +6 -6
@@ -6,8 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.RunnablePick = exports.RunnableAssign = exports._coerceToRunnable = exports.RunnableWithFallbacks = exports.RunnableParallel = exports.RunnableLambda = exports.RunnableMap = exports.RunnableSequence = exports.RunnableRetry = exports.RunnableEach = exports.RunnableBinding = exports.Runnable = exports._coerceToDict = void 0;
7
7
  const zod_1 = require("zod");
8
8
  const p_retry_1 = __importDefault(require("p-retry"));
9
+ const uuid_1 = require("uuid");
9
10
  const manager_js_1 = require("../callbacks/manager.cjs");
10
11
  const log_stream_js_1 = require("../tracers/log_stream.cjs");
12
+ const event_stream_js_1 = require("../tracers/event_stream.cjs");
11
13
  const serializable_js_1 = require("../load/serializable.cjs");
12
14
  const stream_js_1 = require("../utils/stream.cjs");
13
15
  const config_js_1 = require("./config.cjs");
@@ -285,11 +287,16 @@ class Runnable extends serializable_js_1.Serializable {
285
287
  const pipe = await (0, stream_js_1.pipeGeneratorWithSetup)(transformer.bind(this), wrapInputForTracing(), async () => callbackManager_?.handleChainStart(this.toJSON(), { input: "" }, config.runId, config.runType, undefined, undefined, config.runName ?? this.getName()), config);
286
288
  delete config.runId;
287
289
  runManager = pipe.setup;
290
+ const isStreamEventsHandler = (handler) => handler.name === "event_stream_tracer";
291
+ const streamEventsHandler = runManager?.handlers.find(isStreamEventsHandler);
292
+ let iterator = pipe.output;
293
+ if (streamEventsHandler !== undefined && runManager !== undefined) {
294
+ iterator = streamEventsHandler.tapOutputIterable(runManager.runId, iterator);
295
+ }
288
296
  const isLogStreamHandler = (handler) => handler.name === "log_stream_tracer";
289
297
  const streamLogHandler = runManager?.handlers.find(isLogStreamHandler);
290
- let iterator = pipe.output;
291
298
  if (streamLogHandler !== undefined && runManager !== undefined) {
292
- iterator = await streamLogHandler.tapOutputIterable(runManager.runId, pipe.output);
299
+ iterator = streamLogHandler.tapOutputIterable(runManager.runId, iterator);
293
300
  }
294
301
  for await (const chunk of iterator) {
295
302
  yield chunk;
@@ -455,7 +462,16 @@ class Runnable extends serializable_js_1.Serializable {
455
462
  }
456
463
  }
457
464
  streamEvents(input, options, streamOptions) {
458
- const stream = this._streamEvents(input, options, streamOptions);
465
+ let stream;
466
+ if (options.version === "v1") {
467
+ stream = this._streamEventsV1(input, options, streamOptions);
468
+ }
469
+ else if (options.version === "v2") {
470
+ stream = this._streamEventsV2(input, options, streamOptions);
471
+ }
472
+ else {
473
+ throw new Error(`Only versions "v1" and "v2" of the schema are currently supported.`);
474
+ }
459
475
  if (options.encoding === "text/event-stream") {
460
476
  return (0, wrappers_js_1.convertToHttpEventStream)(stream);
461
477
  }
@@ -463,10 +479,75 @@ class Runnable extends serializable_js_1.Serializable {
463
479
  return stream_js_1.IterableReadableStream.fromAsyncGenerator(stream);
464
480
  }
465
481
  }
466
- async *_streamEvents(input, options, streamOptions) {
467
- if (options.version !== "v1") {
468
- throw new Error(`Only version "v1" of the events schema is currently supported.`);
482
+ async *_streamEventsV2(input, options, streamOptions) {
483
+ const eventStreamer = new event_stream_js_1.EventStreamCallbackHandler({
484
+ ...streamOptions,
485
+ autoClose: false,
486
+ });
487
+ const config = (0, config_js_1.ensureConfig)(options);
488
+ const runId = config.runId ?? (0, uuid_1.v4)();
489
+ config.runId = runId;
490
+ const callbacks = config.callbacks;
491
+ if (callbacks === undefined) {
492
+ config.callbacks = [eventStreamer];
493
+ }
494
+ else if (Array.isArray(callbacks)) {
495
+ config.callbacks = callbacks.concat(eventStreamer);
496
+ }
497
+ else {
498
+ const copiedCallbacks = callbacks.copy();
499
+ copiedCallbacks.inheritableHandlers.push(eventStreamer);
500
+ // eslint-disable-next-line no-param-reassign
501
+ config.callbacks = copiedCallbacks;
502
+ }
503
+ // Call the runnable in streaming mode,
504
+ // add each chunk to the output stream
505
+ const outerThis = this;
506
+ async function consumeRunnableStream() {
507
+ try {
508
+ const runnableStream = await outerThis.stream(input, config);
509
+ const tappedStream = eventStreamer.tapOutputIterable(runId, runnableStream);
510
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
511
+ for await (const _ of tappedStream) {
512
+ // Just iterate so that the callback handler picks up events
513
+ }
514
+ }
515
+ finally {
516
+ await eventStreamer.writer.close();
517
+ }
518
+ }
519
+ const runnableStreamConsumePromise = consumeRunnableStream();
520
+ let firstEventSent = false;
521
+ let firstEventRunId;
522
+ try {
523
+ for await (const event of eventStreamer) {
524
+ // This is a work-around an issue where the inputs into the
525
+ // chain are not available until the entire input is consumed.
526
+ // As a temporary solution, we'll modify the input to be the input
527
+ // that was passed into the chain.
528
+ if (!firstEventSent) {
529
+ event.data.input = input;
530
+ firstEventSent = true;
531
+ firstEventRunId = event.run_id;
532
+ yield event;
533
+ continue;
534
+ }
535
+ if (event.run_id === firstEventRunId && event.event.endsWith("_end")) {
536
+ // If it's the end event corresponding to the root runnable
537
+ // we dont include the input in the event since it's guaranteed
538
+ // to be included in the first event.
539
+ if (event.data?.input) {
540
+ delete event.data.input;
541
+ }
542
+ }
543
+ yield event;
544
+ }
469
545
  }
546
+ finally {
547
+ await runnableStreamConsumePromise;
548
+ }
549
+ }
550
+ async *_streamEventsV1(input, options, streamOptions) {
470
551
  let runLog;
471
552
  let hasEncounteredStartEvent = false;
472
553
  const config = (0, config_js_1.ensureConfig)(options);
@@ -1,6 +1,7 @@
1
1
  import type { RunnableInterface, RunnableBatchOptions } from "./types.js";
2
2
  import { CallbackManagerForChainRun } from "../callbacks/manager.js";
3
- import { LogStreamCallbackHandler, LogStreamCallbackHandlerInput, RunLogPatch, StreamEvent } from "../tracers/log_stream.js";
3
+ import { LogStreamCallbackHandler, LogStreamCallbackHandlerInput, RunLogPatch } from "../tracers/log_stream.js";
4
+ import { EventStreamCallbackHandlerInput, StreamEvent } from "../tracers/event_stream.js";
4
5
  import { Serializable } from "../load/serializable.js";
5
6
  import { IterableReadableStream } from "../utils/stream.js";
6
7
  import { RunnableConfig } from "./config.js";
@@ -179,33 +180,51 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
179
180
  * chains. Metadata fields have been omitted from the table for brevity.
180
181
  * Chain definitions have been included after the table.
181
182
  *
182
- * | event | name | chunk | input | output |
183
- * |----------------------|------------------|------------------------------------|-----------------------------------------------|-------------------------------------------------|
184
- * | on_llm_start | [model name] | | {'input': 'hello'} | |
185
- * | on_llm_stream | [model name] | 'Hello' OR AIMessageChunk("hello") | | |
186
- * | on_llm_end | [model name] | | 'Hello human!' |
187
- * | on_chain_start | format_docs | | | |
188
- * | on_chain_stream | format_docs | "hello world!, goodbye world!" | | |
189
- * | on_chain_end | format_docs | | [Document(...)] | "hello world!, goodbye world!" |
190
- * | on_tool_start | some_tool | | {"x": 1, "y": "2"} | |
191
- * | on_tool_stream | some_tool | {"x": 1, "y": "2"} | | |
192
- * | on_tool_end | some_tool | | | {"x": 1, "y": "2"} |
193
- * | on_retriever_start | [retriever name] | | {"query": "hello"} | |
194
- * | on_retriever_chunk | [retriever name] | {documents: [...]} | | |
195
- * | on_retriever_end | [retriever name] | | {"query": "hello"} | {documents: [...]} |
196
- * | on_prompt_start | [template_name] | | {"question": "hello"} | |
197
- * | on_prompt_end | [template_name] | | {"question": "hello"} | ChatPromptValue(messages: [SystemMessage, ...]) |
183
+ * **ATTENTION** This reference table is for the V2 version of the schema.
184
+ *
185
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
186
+ * | event | name | chunk | input | output |
187
+ * +======================+==================+=================================+===============================================+=================================================+
188
+ * | on_chat_model_start | [model name] | | {"messages": [[SystemMessage, HumanMessage]]} | |
189
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
190
+ * | on_chat_model_stream | [model name] | AIMessageChunk(content="hello") | | |
191
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
192
+ * | on_chat_model_end | [model name] | | {"messages": [[SystemMessage, HumanMessage]]} | AIMessageChunk(content="hello world") |
193
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
194
+ * | on_llm_start | [model name] | | {'input': 'hello'} | |
195
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
196
+ * | on_llm_stream | [model name] | 'Hello' | | |
197
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
198
+ * | on_llm_end | [model name] | | 'Hello human!' | |
199
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
200
+ * | on_chain_start | format_docs | | | |
201
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
202
+ * | on_chain_stream | format_docs | "hello world!, goodbye world!" | | |
203
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
204
+ * | on_chain_end | format_docs | | [Document(...)] | "hello world!, goodbye world!" |
205
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
206
+ * | on_tool_start | some_tool | | {"x": 1, "y": "2"} | |
207
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
208
+ * | on_tool_end | some_tool | | | {"x": 1, "y": "2"} |
209
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
210
+ * | on_retriever_start | [retriever name] | | {"query": "hello"} | |
211
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
212
+ * | on_retriever_end | [retriever name] | | {"query": "hello"} | [Document(...), ..] |
213
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
214
+ * | on_prompt_start | [template_name] | | {"question": "hello"} | |
215
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
216
+ * | on_prompt_end | [template_name] | | {"question": "hello"} | ChatPromptValue(messages: [SystemMessage, ...]) |
217
+ * +----------------------+------------------+---------------------------------+-----------------------------------------------+-------------------------------------------------+
198
218
  */
199
219
  streamEvents(input: RunInput, options: Partial<CallOptions> & {
200
- version: "v1";
201
- }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<StreamEvent>;
220
+ version: "v1" | "v2";
221
+ }, streamOptions?: Omit<EventStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<StreamEvent>;
202
222
  streamEvents(input: RunInput, options: Partial<CallOptions> & {
203
- version: "v1";
223
+ version: "v1" | "v2";
204
224
  encoding: "text/event-stream";
205
- }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<Uint8Array>;
206
- _streamEvents(input: RunInput, options: Partial<CallOptions> & {
207
- version: "v1";
208
- }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): AsyncGenerator<StreamEvent>;
225
+ }, streamOptions?: Omit<EventStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<Uint8Array>;
226
+ private _streamEventsV2;
227
+ private _streamEventsV1;
209
228
  static isRunnable(thing: any): thing is Runnable;
210
229
  /**
211
230
  * Bind lifecycle listeners to a Runnable, returning a new Runnable.
@@ -262,10 +281,10 @@ export declare class RunnableBinding<RunInput, RunOutput, CallOptions extends Ru
262
281
  stream(input: RunInput, options?: Partial<CallOptions> | undefined): Promise<IterableReadableStream<RunOutput>>;
263
282
  transform(generator: AsyncGenerator<RunInput>, options: Partial<CallOptions>): AsyncGenerator<RunOutput>;
264
283
  streamEvents(input: RunInput, options: Partial<CallOptions> & {
265
- version: "v1";
284
+ version: "v1" | "v2";
266
285
  }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<StreamEvent>;
267
286
  streamEvents(input: RunInput, options: Partial<CallOptions> & {
268
- version: "v1";
287
+ version: "v1" | "v2";
269
288
  encoding: "text/event-stream";
270
289
  }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): IterableReadableStream<Uint8Array>;
271
290
  static isRunnableBinding(thing: any): thing is RunnableBinding<any, any, any>;
@@ -1,7 +1,9 @@
1
1
  import { z } from "zod";
2
2
  import pRetry from "p-retry";
3
+ import { v4 as uuidv4 } from "uuid";
3
4
  import { CallbackManager, } from "../callbacks/manager.js";
4
5
  import { LogStreamCallbackHandler, RunLog, RunLogPatch, } from "../tracers/log_stream.js";
6
+ import { EventStreamCallbackHandler, } from "../tracers/event_stream.js";
5
7
  import { Serializable } from "../load/serializable.js";
6
8
  import { IterableReadableStream, concat, atee, pipeGeneratorWithSetup, AsyncGeneratorWithSetup, } from "../utils/stream.js";
7
9
  import { DEFAULT_RECURSION_LIMIT, ensureConfig, getCallbackManagerForConfig, mergeConfigs, patchConfig, } from "./config.js";
@@ -278,11 +280,16 @@ export class Runnable extends Serializable {
278
280
  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);
279
281
  delete config.runId;
280
282
  runManager = pipe.setup;
283
+ const isStreamEventsHandler = (handler) => handler.name === "event_stream_tracer";
284
+ const streamEventsHandler = runManager?.handlers.find(isStreamEventsHandler);
285
+ let iterator = pipe.output;
286
+ if (streamEventsHandler !== undefined && runManager !== undefined) {
287
+ iterator = streamEventsHandler.tapOutputIterable(runManager.runId, iterator);
288
+ }
281
289
  const isLogStreamHandler = (handler) => handler.name === "log_stream_tracer";
282
290
  const streamLogHandler = runManager?.handlers.find(isLogStreamHandler);
283
- let iterator = pipe.output;
284
291
  if (streamLogHandler !== undefined && runManager !== undefined) {
285
- iterator = await streamLogHandler.tapOutputIterable(runManager.runId, pipe.output);
292
+ iterator = streamLogHandler.tapOutputIterable(runManager.runId, iterator);
286
293
  }
287
294
  for await (const chunk of iterator) {
288
295
  yield chunk;
@@ -448,7 +455,16 @@ export class Runnable extends Serializable {
448
455
  }
449
456
  }
450
457
  streamEvents(input, options, streamOptions) {
451
- const stream = this._streamEvents(input, options, streamOptions);
458
+ let stream;
459
+ if (options.version === "v1") {
460
+ stream = this._streamEventsV1(input, options, streamOptions);
461
+ }
462
+ else if (options.version === "v2") {
463
+ stream = this._streamEventsV2(input, options, streamOptions);
464
+ }
465
+ else {
466
+ throw new Error(`Only versions "v1" and "v2" of the schema are currently supported.`);
467
+ }
452
468
  if (options.encoding === "text/event-stream") {
453
469
  return convertToHttpEventStream(stream);
454
470
  }
@@ -456,10 +472,75 @@ export class Runnable extends Serializable {
456
472
  return IterableReadableStream.fromAsyncGenerator(stream);
457
473
  }
458
474
  }
459
- async *_streamEvents(input, options, streamOptions) {
460
- if (options.version !== "v1") {
461
- throw new Error(`Only version "v1" of the events schema is currently supported.`);
475
+ async *_streamEventsV2(input, options, streamOptions) {
476
+ const eventStreamer = new EventStreamCallbackHandler({
477
+ ...streamOptions,
478
+ autoClose: false,
479
+ });
480
+ const config = ensureConfig(options);
481
+ const runId = config.runId ?? uuidv4();
482
+ config.runId = runId;
483
+ const callbacks = config.callbacks;
484
+ if (callbacks === undefined) {
485
+ config.callbacks = [eventStreamer];
486
+ }
487
+ else if (Array.isArray(callbacks)) {
488
+ config.callbacks = callbacks.concat(eventStreamer);
489
+ }
490
+ else {
491
+ const copiedCallbacks = callbacks.copy();
492
+ copiedCallbacks.inheritableHandlers.push(eventStreamer);
493
+ // eslint-disable-next-line no-param-reassign
494
+ config.callbacks = copiedCallbacks;
495
+ }
496
+ // Call the runnable in streaming mode,
497
+ // add each chunk to the output stream
498
+ const outerThis = this;
499
+ async function consumeRunnableStream() {
500
+ try {
501
+ const runnableStream = await outerThis.stream(input, config);
502
+ const tappedStream = eventStreamer.tapOutputIterable(runId, runnableStream);
503
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
504
+ for await (const _ of tappedStream) {
505
+ // Just iterate so that the callback handler picks up events
506
+ }
507
+ }
508
+ finally {
509
+ await eventStreamer.writer.close();
510
+ }
511
+ }
512
+ const runnableStreamConsumePromise = consumeRunnableStream();
513
+ let firstEventSent = false;
514
+ let firstEventRunId;
515
+ try {
516
+ for await (const event of eventStreamer) {
517
+ // This is a work-around an issue where the inputs into the
518
+ // chain are not available until the entire input is consumed.
519
+ // As a temporary solution, we'll modify the input to be the input
520
+ // that was passed into the chain.
521
+ if (!firstEventSent) {
522
+ event.data.input = input;
523
+ firstEventSent = true;
524
+ firstEventRunId = event.run_id;
525
+ yield event;
526
+ continue;
527
+ }
528
+ if (event.run_id === firstEventRunId && event.event.endsWith("_end")) {
529
+ // If it's the end event corresponding to the root runnable
530
+ // we dont include the input in the event since it's guaranteed
531
+ // to be included in the first event.
532
+ if (event.data?.input) {
533
+ delete event.data.input;
534
+ }
535
+ }
536
+ yield event;
537
+ }
462
538
  }
539
+ finally {
540
+ await runnableStreamConsumePromise;
541
+ }
542
+ }
543
+ async *_streamEventsV1(input, options, streamOptions) {
463
544
  let runLog;
464
545
  let hasEncounteredStartEvent = false;
465
546
  const config = ensureConfig(options);
@@ -126,68 +126,123 @@ class RunnableWithMessageHistory extends base_js_1.RunnableBinding {
126
126
  this.outputMessagesKey = fields.outputMessagesKey;
127
127
  this.historyMessagesKey = fields.historyMessagesKey;
128
128
  }
129
- _getInputMessages(inputValue) {
130
- if (typeof inputValue === "string") {
131
- return [new index_js_1.HumanMessage(inputValue)];
129
+ _getInputMessages(
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ inputValue) {
132
+ let parsedInputValue;
133
+ if (typeof inputValue === "object" &&
134
+ !Array.isArray(inputValue) &&
135
+ !(0, index_js_1.isBaseMessage)(inputValue)) {
136
+ let key;
137
+ if (this.inputMessagesKey) {
138
+ key = this.inputMessagesKey;
139
+ }
140
+ else if (Object.keys(inputValue).length === 1) {
141
+ key = Object.keys(inputValue)[0];
142
+ }
143
+ else {
144
+ key = "input";
145
+ }
146
+ if (Array.isArray(inputValue[key]) && Array.isArray(inputValue[key][0])) {
147
+ parsedInputValue = inputValue[key][0];
148
+ }
149
+ else {
150
+ parsedInputValue = inputValue[key];
151
+ }
152
+ }
153
+ else {
154
+ parsedInputValue = inputValue;
155
+ }
156
+ if (typeof parsedInputValue === "string") {
157
+ return [new index_js_1.HumanMessage(parsedInputValue)];
132
158
  }
133
- else if (Array.isArray(inputValue)) {
134
- return inputValue;
159
+ else if (Array.isArray(parsedInputValue)) {
160
+ return parsedInputValue;
161
+ }
162
+ else if ((0, index_js_1.isBaseMessage)(parsedInputValue)) {
163
+ return [parsedInputValue];
135
164
  }
136
165
  else {
137
- return [inputValue];
166
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages.\nGot ${JSON.stringify(parsedInputValue, null, 2)}`);
138
167
  }
139
168
  }
140
169
  _getOutputMessages(
141
170
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
171
  outputValue) {
143
- let newOutputValue = outputValue;
172
+ let parsedOutputValue;
144
173
  if (!Array.isArray(outputValue) &&
145
174
  !(0, index_js_1.isBaseMessage)(outputValue) &&
146
175
  typeof outputValue !== "string") {
147
- newOutputValue = outputValue[this.outputMessagesKey ?? "output"];
176
+ let key;
177
+ if (this.outputMessagesKey !== undefined) {
178
+ key = this.outputMessagesKey;
179
+ }
180
+ else if (Object.keys(outputValue).length === 1) {
181
+ key = Object.keys(outputValue)[0];
182
+ }
183
+ else {
184
+ key = "output";
185
+ }
186
+ // If you are wrapping a chat model directly
187
+ // The output is actually this weird generations object
188
+ if (outputValue.generations !== undefined) {
189
+ parsedOutputValue = outputValue.generations[0][0].message;
190
+ }
191
+ else {
192
+ parsedOutputValue = outputValue[key];
193
+ }
194
+ }
195
+ else {
196
+ parsedOutputValue = outputValue;
148
197
  }
149
- if (typeof newOutputValue === "string") {
150
- return [new index_js_1.AIMessage(newOutputValue)];
198
+ if (typeof parsedOutputValue === "string") {
199
+ return [new index_js_1.AIMessage(parsedOutputValue)];
151
200
  }
152
- else if (Array.isArray(newOutputValue)) {
153
- return newOutputValue;
201
+ else if (Array.isArray(parsedOutputValue)) {
202
+ return parsedOutputValue;
154
203
  }
155
- else if ((0, index_js_1.isBaseMessage)(newOutputValue)) {
156
- return [newOutputValue];
204
+ else if ((0, index_js_1.isBaseMessage)(parsedOutputValue)) {
205
+ return [parsedOutputValue];
206
+ }
207
+ else {
208
+ throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(parsedOutputValue, null, 2)}`);
157
209
  }
158
- throw new Error(`Expected a string, BaseMessage, or array of BaseMessages. Received: ${JSON.stringify(newOutputValue, null, 2)}`);
159
210
  }
160
211
  async _enterHistory(
161
212
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
162
213
  input, kwargs) {
163
214
  const history = kwargs?.config?.configurable?.messageHistory;
164
- if (this.historyMessagesKey) {
165
- return history.getMessages();
166
- }
167
- const inputVal = input ||
168
- (this.inputMessagesKey ? input[this.inputMessagesKey] : undefined);
169
- const historyMessages = history ? await history.getMessages() : [];
170
- const returnType = [
171
- ...historyMessages,
172
- ...this._getInputMessages(inputVal),
173
- ];
174
- return returnType;
215
+ const messages = await history.getMessages();
216
+ if (this.historyMessagesKey === undefined) {
217
+ return messages.concat(this._getInputMessages(input));
218
+ }
219
+ return messages;
175
220
  }
176
221
  async _exitHistory(run, config) {
177
222
  const history = config.configurable?.messageHistory;
178
223
  // Get input messages
179
- const { inputs } = run;
180
- const inputValue = inputs[this.inputMessagesKey ?? "input"];
181
- const inputMessages = this._getInputMessages(inputValue);
224
+ let inputs;
225
+ // Chat model inputs are nested arrays
226
+ if (Array.isArray(run.inputs) && Array.isArray(run.inputs[0])) {
227
+ inputs = run.inputs[0];
228
+ }
229
+ else {
230
+ inputs = run.inputs;
231
+ }
232
+ let inputMessages = this._getInputMessages(inputs);
233
+ // If historic messages were prepended to the input messages, remove them to
234
+ // avoid adding duplicate messages to history.
235
+ if (this.historyMessagesKey === undefined) {
236
+ const existingMessages = await history.getMessages();
237
+ inputMessages = inputMessages.slice(existingMessages.length);
238
+ }
182
239
  // Get output messages
183
240
  const outputValue = run.outputs;
184
241
  if (!outputValue) {
185
242
  throw new Error(`Output values from 'Run' undefined. Run: ${JSON.stringify(run, null, 2)}`);
186
243
  }
187
244
  const outputMessages = this._getOutputMessages(outputValue);
188
- for await (const message of [...inputMessages, ...outputMessages]) {
189
- await history.addMessage(message);
190
- }
245
+ await history.addMessages([...inputMessages, ...outputMessages]);
191
246
  }
192
247
  async _mergeConfig(...configs) {
193
248
  const config = await super._mergeConfig(...configs);
@@ -83,7 +83,7 @@ export declare class RunnableWithMessageHistory<RunInput, RunOutput> extends Run
83
83
  historyMessagesKey?: string;
84
84
  getMessageHistory: GetSessionHistoryCallable;
85
85
  constructor(fields: RunnableWithMessageHistoryInputs<RunInput, RunOutput>);
86
- _getInputMessages(inputValue: string | BaseMessage | Array<BaseMessage>): Array<BaseMessage>;
86
+ _getInputMessages(inputValue: string | BaseMessage | Array<BaseMessage> | Record<string, any>): Array<BaseMessage>;
87
87
  _getOutputMessages(outputValue: string | BaseMessage | Array<BaseMessage> | Record<string, any>): Array<BaseMessage>;
88
88
  _enterHistory(input: any, kwargs?: {
89
89
  config?: RunnableConfig;