@langchain/core 0.1.48 → 0.1.50

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.
@@ -730,28 +730,28 @@ class RunnableBinding extends Runnable {
730
730
  });
731
731
  }
732
732
  async invoke(input, options) {
733
- return this.bound.invoke(input, await this._mergeConfig(options, this.kwargs));
733
+ return this.bound.invoke(input, await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs));
734
734
  }
735
735
  async batch(inputs, options, batchOptions) {
736
736
  const mergedOptions = Array.isArray(options)
737
- ? await Promise.all(options.map(async (individualOption) => this._mergeConfig(individualOption, this.kwargs)))
738
- : await this._mergeConfig(options, this.kwargs);
737
+ ? await Promise.all(options.map(async (individualOption) => this._mergeConfig((0, config_js_1.ensureConfig)(individualOption), this.kwargs)))
738
+ : await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs);
739
739
  return this.bound.batch(inputs, mergedOptions, batchOptions);
740
740
  }
741
741
  async *_streamIterator(input, options) {
742
- yield* this.bound._streamIterator(input, await this._mergeConfig(options, this.kwargs));
742
+ yield* this.bound._streamIterator(input, await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs));
743
743
  }
744
744
  async stream(input, options) {
745
- return this.bound.stream(input, await this._mergeConfig(options, this.kwargs));
745
+ return this.bound.stream(input, await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs));
746
746
  }
747
747
  async *transform(
748
748
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
749
749
  generator, options) {
750
- yield* this.bound.transform(generator, await this._mergeConfig(options, this.kwargs));
750
+ yield* this.bound.transform(generator, await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs));
751
751
  }
752
752
  async *streamEvents(input, options, streamOptions) {
753
753
  yield* this.bound.streamEvents(input, {
754
- ...(await this._mergeConfig(options, this.kwargs)),
754
+ ...(await this._mergeConfig((0, config_js_1.ensureConfig)(options), this.kwargs)),
755
755
  version: options.version,
756
756
  }, streamOptions);
757
757
  }
@@ -722,28 +722,28 @@ export class RunnableBinding extends Runnable {
722
722
  });
723
723
  }
724
724
  async invoke(input, options) {
725
- return this.bound.invoke(input, await this._mergeConfig(options, this.kwargs));
725
+ return this.bound.invoke(input, await this._mergeConfig(ensureConfig(options), this.kwargs));
726
726
  }
727
727
  async batch(inputs, options, batchOptions) {
728
728
  const mergedOptions = Array.isArray(options)
729
- ? await Promise.all(options.map(async (individualOption) => this._mergeConfig(individualOption, this.kwargs)))
730
- : await this._mergeConfig(options, this.kwargs);
729
+ ? await Promise.all(options.map(async (individualOption) => this._mergeConfig(ensureConfig(individualOption), this.kwargs)))
730
+ : await this._mergeConfig(ensureConfig(options), this.kwargs);
731
731
  return this.bound.batch(inputs, mergedOptions, batchOptions);
732
732
  }
733
733
  async *_streamIterator(input, options) {
734
- yield* this.bound._streamIterator(input, await this._mergeConfig(options, this.kwargs));
734
+ yield* this.bound._streamIterator(input, await this._mergeConfig(ensureConfig(options), this.kwargs));
735
735
  }
736
736
  async stream(input, options) {
737
- return this.bound.stream(input, await this._mergeConfig(options, this.kwargs));
737
+ return this.bound.stream(input, await this._mergeConfig(ensureConfig(options), this.kwargs));
738
738
  }
739
739
  async *transform(
740
740
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
741
741
  generator, options) {
742
- yield* this.bound.transform(generator, await this._mergeConfig(options, this.kwargs));
742
+ yield* this.bound.transform(generator, await this._mergeConfig(ensureConfig(options), this.kwargs));
743
743
  }
744
744
  async *streamEvents(input, options, streamOptions) {
745
745
  yield* this.bound.streamEvents(input, {
746
- ...(await this._mergeConfig(options, this.kwargs)),
746
+ ...(await this._mergeConfig(ensureConfig(options), this.kwargs)),
747
747
  version: options.version,
748
748
  }, streamOptions);
749
749
  }
@@ -9,15 +9,17 @@ async function getCallbackManagerForConfig(config) {
9
9
  }
10
10
  exports.getCallbackManagerForConfig = getCallbackManagerForConfig;
11
11
  function mergeConfigs(...configs) {
12
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
- const copy = ensureConfig();
12
+ // We do not want to call ensureConfig on the empty state here as this may cause
13
+ // double loading of callbacks if async local storage is being used.
14
+ const copy = {};
14
15
  for (const options of configs.filter((c) => !!c)) {
15
16
  for (const key of Object.keys(options)) {
16
17
  if (key === "metadata") {
17
18
  copy[key] = { ...copy[key], ...options[key] };
18
19
  }
19
20
  else if (key === "tags") {
20
- copy[key] = [...new Set(copy[key].concat(options[key] ?? []))];
21
+ const baseKeys = copy[key] ?? [];
22
+ copy[key] = [...new Set(baseKeys.concat(options[key] ?? []))];
21
23
  }
22
24
  else if (key === "configurable") {
23
25
  copy[key] = { ...copy[key], ...options[key] };
@@ -5,15 +5,17 @@ export async function getCallbackManagerForConfig(config) {
5
5
  return CallbackManager.configure(config?.callbacks, undefined, config?.tags, undefined, config?.metadata);
6
6
  }
7
7
  export function mergeConfigs(...configs) {
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- const copy = ensureConfig();
8
+ // We do not want to call ensureConfig on the empty state here as this may cause
9
+ // double loading of callbacks if async local storage is being used.
10
+ const copy = {};
10
11
  for (const options of configs.filter((c) => !!c)) {
11
12
  for (const key of Object.keys(options)) {
12
13
  if (key === "metadata") {
13
14
  copy[key] = { ...copy[key], ...options[key] };
14
15
  }
15
16
  else if (key === "tags") {
16
- copy[key] = [...new Set(copy[key].concat(options[key] ?? []))];
17
+ const baseKeys = copy[key] ?? [];
18
+ copy[key] = [...new Set(baseKeys.concat(options[key] ?? []))];
17
19
  }
18
20
  else if (key === "configurable") {
19
21
  copy[key] = { ...copy[key], ...options[key] };
@@ -268,6 +268,9 @@ class RemoteRunnable extends base_js_1.Runnable {
268
268
  config: removeCallbacks(config),
269
269
  kwargs: kwargs ?? {},
270
270
  });
271
+ if (!response.ok) {
272
+ throw new Error(`${response.status} Error: ${await response.text()}`);
273
+ }
271
274
  return revive((await response.json()).output);
272
275
  }
273
276
  async _batch(inputs, options, _, batchOptions) {
@@ -286,6 +289,9 @@ class RemoteRunnable extends base_js_1.Runnable {
286
289
  .map((config) => ({ ...config, ...batchOptions })),
287
290
  kwargs,
288
291
  });
292
+ if (!response.ok) {
293
+ throw new Error(`${response.status} Error: ${await response.text()}`);
294
+ }
289
295
  const body = await response.json();
290
296
  if (!body.output)
291
297
  throw new Error("Invalid response from remote runnable");
@@ -315,21 +321,13 @@ class RemoteRunnable extends base_js_1.Runnable {
315
321
  if (!body) {
316
322
  throw new Error("Could not begin remote stream. Please check the given URL and try again.");
317
323
  }
318
- const stream = new ReadableStream({
319
- async start(controller) {
320
- const enqueueLine = (0, event_source_parse_js_1.getMessages)((msg) => {
321
- if (msg.data)
322
- controller.enqueue(deserialize(msg.data));
323
- });
324
- const onLine = (line, fieldLength, flush) => {
325
- enqueueLine(line, fieldLength, flush);
326
- if (flush)
327
- controller.close();
328
- };
329
- await (0, event_source_parse_js_1.getBytes)(body, (0, event_source_parse_js_1.getLines)(onLine));
330
- },
331
- });
332
- return stream_js_1.IterableReadableStream.fromReadableStream(stream);
324
+ const runnableStream = (0, event_source_parse_js_1.convertEventStreamToIterableReadableDataStream)(body);
325
+ async function* wrapper() {
326
+ for await (const chunk of runnableStream) {
327
+ yield deserialize(chunk);
328
+ }
329
+ }
330
+ return stream_js_1.IterableReadableStream.fromAsyncGenerator(wrapper());
333
331
  }
334
332
  async *streamLog(input, options, streamOptions) {
335
333
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
@@ -365,7 +363,10 @@ class RemoteRunnable extends base_js_1.Runnable {
365
363
  ...camelCaseStreamOptions,
366
364
  diff: false,
367
365
  });
368
- const { body } = response;
366
+ const { body, ok } = response;
367
+ if (!ok) {
368
+ throw new Error(`${response.status} Error: ${await response.text()}`);
369
+ }
369
370
  if (!body) {
370
371
  throw new Error("Could not begin remote stream log. Please check the given URL and try again.");
371
372
  }
@@ -375,5 +376,46 @@ class RemoteRunnable extends base_js_1.Runnable {
375
376
  yield new log_stream_js_1.RunLogPatch({ ops: chunk.ops });
376
377
  }
377
378
  }
379
+ async *streamEvents(input, options, streamOptions) {
380
+ if (options?.version !== "v1") {
381
+ throw new Error(`Only version "v1" of the events schema is currently supported.`);
382
+ }
383
+ const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
384
+ // The type is in camelCase but the API only accepts snake_case.
385
+ const camelCaseStreamOptions = {
386
+ include_names: streamOptions?.includeNames,
387
+ include_types: streamOptions?.includeTypes,
388
+ include_tags: streamOptions?.includeTags,
389
+ exclude_names: streamOptions?.excludeNames,
390
+ exclude_types: streamOptions?.excludeTypes,
391
+ exclude_tags: streamOptions?.excludeTags,
392
+ };
393
+ const response = await this.post("/stream_events", {
394
+ input,
395
+ config: removeCallbacks(config),
396
+ kwargs,
397
+ ...camelCaseStreamOptions,
398
+ diff: false,
399
+ });
400
+ const { body, ok } = response;
401
+ if (!ok) {
402
+ throw new Error(`${response.status} Error: ${await response.text()}`);
403
+ }
404
+ if (!body) {
405
+ throw new Error("Could not begin remote stream events. Please check the given URL and try again.");
406
+ }
407
+ const runnableStream = (0, event_source_parse_js_1.convertEventStreamToIterableReadableDataStream)(body);
408
+ for await (const log of runnableStream) {
409
+ const chunk = revive(JSON.parse(log));
410
+ yield {
411
+ event: chunk.event,
412
+ name: chunk.name,
413
+ run_id: chunk.id,
414
+ tags: chunk.tags,
415
+ metadata: chunk.metadata,
416
+ data: chunk.data,
417
+ };
418
+ }
419
+ }
378
420
  }
379
421
  exports.RemoteRunnable = RemoteRunnable;
@@ -1,7 +1,7 @@
1
1
  import { Runnable, RunnableBatchOptions } from "./base.js";
2
2
  import type { RunnableConfig } from "./config.js";
3
3
  import { CallbackManagerForChainRun } from "../callbacks/manager.js";
4
- import { RunLogPatch, type LogStreamCallbackHandlerInput } from "../tracers/log_stream.js";
4
+ import { RunLogPatch, type LogStreamCallbackHandlerInput, type StreamEvent } from "../tracers/log_stream.js";
5
5
  import { IterableReadableStream } from "../utils/stream.js";
6
6
  type RemoteRunnableOptions = {
7
7
  timeout?: number;
@@ -27,5 +27,8 @@ export declare class RemoteRunnable<RunInput, RunOutput, CallOptions extends Run
27
27
  batch(inputs: RunInput[], options?: Partial<CallOptions> | Partial<CallOptions>[], batchOptions?: RunnableBatchOptions): Promise<(RunOutput | Error)[]>;
28
28
  stream(input: RunInput, options?: Partial<CallOptions>): Promise<IterableReadableStream<RunOutput>>;
29
29
  streamLog(input: RunInput, options?: Partial<CallOptions>, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): AsyncGenerator<RunLogPatch>;
30
+ streamEvents(input: RunInput, options: Partial<CallOptions> & {
31
+ version: "v1";
32
+ }, streamOptions?: Omit<LogStreamCallbackHandlerInput, "autoClose">): AsyncGenerator<StreamEvent>;
30
33
  }
31
34
  export {};
@@ -4,7 +4,7 @@ import { ChatPromptValue, StringPromptValue } from "../prompt_values.js";
4
4
  import { LogStreamCallbackHandler, RunLogPatch, } from "../tracers/log_stream.js";
5
5
  import { AIMessage, AIMessageChunk, ChatMessage, ChatMessageChunk, FunctionMessage, FunctionMessageChunk, HumanMessage, HumanMessageChunk, SystemMessage, SystemMessageChunk, ToolMessage, ToolMessageChunk, isBaseMessage, } from "../messages/index.js";
6
6
  import { GenerationChunk, ChatGenerationChunk, RUN_KEY } from "../outputs.js";
7
- import { getBytes, getLines, getMessages, convertEventStreamToIterableReadableDataStream, } from "../utils/event_source_parse.js";
7
+ import { convertEventStreamToIterableReadableDataStream } from "../utils/event_source_parse.js";
8
8
  import { IterableReadableStream } from "../utils/stream.js";
9
9
  function isSuperset(set, subset) {
10
10
  for (const elem of subset) {
@@ -265,6 +265,9 @@ export class RemoteRunnable extends Runnable {
265
265
  config: removeCallbacks(config),
266
266
  kwargs: kwargs ?? {},
267
267
  });
268
+ if (!response.ok) {
269
+ throw new Error(`${response.status} Error: ${await response.text()}`);
270
+ }
268
271
  return revive((await response.json()).output);
269
272
  }
270
273
  async _batch(inputs, options, _, batchOptions) {
@@ -283,6 +286,9 @@ export class RemoteRunnable extends Runnable {
283
286
  .map((config) => ({ ...config, ...batchOptions })),
284
287
  kwargs,
285
288
  });
289
+ if (!response.ok) {
290
+ throw new Error(`${response.status} Error: ${await response.text()}`);
291
+ }
286
292
  const body = await response.json();
287
293
  if (!body.output)
288
294
  throw new Error("Invalid response from remote runnable");
@@ -312,21 +318,13 @@ export class RemoteRunnable extends Runnable {
312
318
  if (!body) {
313
319
  throw new Error("Could not begin remote stream. Please check the given URL and try again.");
314
320
  }
315
- const stream = new ReadableStream({
316
- async start(controller) {
317
- const enqueueLine = getMessages((msg) => {
318
- if (msg.data)
319
- controller.enqueue(deserialize(msg.data));
320
- });
321
- const onLine = (line, fieldLength, flush) => {
322
- enqueueLine(line, fieldLength, flush);
323
- if (flush)
324
- controller.close();
325
- };
326
- await getBytes(body, getLines(onLine));
327
- },
328
- });
329
- return IterableReadableStream.fromReadableStream(stream);
321
+ const runnableStream = convertEventStreamToIterableReadableDataStream(body);
322
+ async function* wrapper() {
323
+ for await (const chunk of runnableStream) {
324
+ yield deserialize(chunk);
325
+ }
326
+ }
327
+ return IterableReadableStream.fromAsyncGenerator(wrapper());
330
328
  }
331
329
  async *streamLog(input, options, streamOptions) {
332
330
  const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
@@ -362,7 +360,10 @@ export class RemoteRunnable extends Runnable {
362
360
  ...camelCaseStreamOptions,
363
361
  diff: false,
364
362
  });
365
- const { body } = response;
363
+ const { body, ok } = response;
364
+ if (!ok) {
365
+ throw new Error(`${response.status} Error: ${await response.text()}`);
366
+ }
366
367
  if (!body) {
367
368
  throw new Error("Could not begin remote stream log. Please check the given URL and try again.");
368
369
  }
@@ -372,4 +373,45 @@ export class RemoteRunnable extends Runnable {
372
373
  yield new RunLogPatch({ ops: chunk.ops });
373
374
  }
374
375
  }
376
+ async *streamEvents(input, options, streamOptions) {
377
+ if (options?.version !== "v1") {
378
+ throw new Error(`Only version "v1" of the events schema is currently supported.`);
379
+ }
380
+ const [config, kwargs] = this._separateRunnableConfigFromCallOptions(options);
381
+ // The type is in camelCase but the API only accepts snake_case.
382
+ const camelCaseStreamOptions = {
383
+ include_names: streamOptions?.includeNames,
384
+ include_types: streamOptions?.includeTypes,
385
+ include_tags: streamOptions?.includeTags,
386
+ exclude_names: streamOptions?.excludeNames,
387
+ exclude_types: streamOptions?.excludeTypes,
388
+ exclude_tags: streamOptions?.excludeTags,
389
+ };
390
+ const response = await this.post("/stream_events", {
391
+ input,
392
+ config: removeCallbacks(config),
393
+ kwargs,
394
+ ...camelCaseStreamOptions,
395
+ diff: false,
396
+ });
397
+ const { body, ok } = response;
398
+ if (!ok) {
399
+ throw new Error(`${response.status} Error: ${await response.text()}`);
400
+ }
401
+ if (!body) {
402
+ throw new Error("Could not begin remote stream events. Please check the given URL and try again.");
403
+ }
404
+ const runnableStream = convertEventStreamToIterableReadableDataStream(body);
405
+ for await (const log of runnableStream) {
406
+ const chunk = revive(JSON.parse(log));
407
+ yield {
408
+ event: chunk.event,
409
+ name: chunk.name,
410
+ run_id: chunk.id,
411
+ tags: chunk.tags,
412
+ metadata: chunk.metadata,
413
+ data: chunk.data,
414
+ };
415
+ }
416
+ }
375
417
  }
@@ -184,12 +184,20 @@ function newMessage() {
184
184
  retry: undefined,
185
185
  };
186
186
  }
187
- function convertEventStreamToIterableReadableDataStream(stream) {
187
+ function convertEventStreamToIterableReadableDataStream(stream, onMetadataEvent) {
188
188
  const dataStream = new ReadableStream({
189
189
  async start(controller) {
190
190
  const enqueueLine = getMessages((msg) => {
191
- if (msg.data)
192
- controller.enqueue(msg.data);
191
+ if (msg.event === "error") {
192
+ throw new Error(msg.data ?? "Unspecified event streaming error.");
193
+ }
194
+ else if (msg.event === "metadata") {
195
+ onMetadataEvent?.(msg);
196
+ }
197
+ else {
198
+ if (msg.data)
199
+ controller.enqueue(msg.data);
200
+ }
193
201
  });
194
202
  const onLine = (line, fieldLength, flush) => {
195
203
  enqueueLine(line, fieldLength, flush);
@@ -36,4 +36,4 @@ export declare function getLines(onLine: (line: Uint8Array, fieldLength: number,
36
36
  * @returns A function that should be called for each incoming line buffer.
37
37
  */
38
38
  export declare function getMessages(onMessage?: (msg: EventSourceMessage) => void, onId?: (id: string) => void, onRetry?: (retry: number) => void): (line: Uint8Array, fieldLength: number, flush?: boolean) => void;
39
- export declare function convertEventStreamToIterableReadableDataStream(stream: ReadableStream): IterableReadableStream<any>;
39
+ export declare function convertEventStreamToIterableReadableDataStream(stream: ReadableStream, onMetadataEvent?: (e: unknown) => unknown): IterableReadableStream<any>;
@@ -178,12 +178,20 @@ function newMessage() {
178
178
  retry: undefined,
179
179
  };
180
180
  }
181
- export function convertEventStreamToIterableReadableDataStream(stream) {
181
+ export function convertEventStreamToIterableReadableDataStream(stream, onMetadataEvent) {
182
182
  const dataStream = new ReadableStream({
183
183
  async start(controller) {
184
184
  const enqueueLine = getMessages((msg) => {
185
- if (msg.data)
186
- controller.enqueue(msg.data);
185
+ if (msg.event === "error") {
186
+ throw new Error(msg.data ?? "Unspecified event streaming error.");
187
+ }
188
+ else if (msg.event === "metadata") {
189
+ onMetadataEvent?.(msg);
190
+ }
191
+ else {
192
+ if (msg.data)
193
+ controller.enqueue(msg.data);
194
+ }
187
195
  });
188
196
  const onLine = (line, fieldLength, flush) => {
189
197
  enqueueLine(line, fieldLength, flush);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "homepage": "https://github.com/langchain-ai/langchainjs/tree/main/langchain-core/",
16
16
  "scripts": {
17
- "build": "yarn clean && yarn build:esm && yarn build:cjs && yarn run build:scripts",
17
+ "build": "yarn build:deps && yarn clean && yarn build:esm && yarn build:cjs && yarn run build:scripts",
18
+ "build:deps": "yarn turbo:command build --filter=@langchain/scripts",
18
19
  "build:esm": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist/ && rimraf dist/tests dist/**/tests",
19
20
  "build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && yarn move-cjs-to-dist && rimraf dist-cjs",
20
21
  "build:watch": "yarn create-entrypoints && tsc --outDir dist/ --watch",