@langchain/core 0.3.55 → 0.3.57

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.
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StructuredPrompt = void 0;
4
+ const base_js_1 = require("../runnables/base.cjs");
4
5
  const chat_js_1 = require("./chat.cjs");
5
6
  function isWithStructuredOutput(x
6
7
  // eslint-disable-next-line @typescript-eslint/ban-types
@@ -54,15 +55,12 @@ class StructuredPrompt extends chat_js_1.ChatPromptTemplate {
54
55
  }
55
56
  if (isRunnableBinding(coerceable) &&
56
57
  isWithStructuredOutput(coerceable.bound)) {
57
- return super.pipe(this.method
58
- ? coerceable.bound
59
- .withStructuredOutput(this.schema, { method: this.method })
60
- .bind(coerceable.kwargs ?? {})
61
- .withConfig(coerceable.config)
62
- : coerceable.bound
63
- .withStructuredOutput(this.schema)
64
- .bind(coerceable.kwargs ?? {})
65
- .withConfig(coerceable.config));
58
+ return super.pipe(new base_js_1.RunnableBinding({
59
+ bound: coerceable.bound.withStructuredOutput(this.schema, ...(this.method ? [{ method: this.method }] : [])),
60
+ kwargs: coerceable.kwargs ?? {},
61
+ config: coerceable.config,
62
+ configFactories: coerceable.configFactories,
63
+ }));
66
64
  }
67
65
  throw new Error(`Structured prompts need to be piped to a language model that supports the "withStructuredOutput()" method.`);
68
66
  }
@@ -1,3 +1,4 @@
1
+ import { RunnableBinding } from "../runnables/base.js";
1
2
  import { ChatPromptTemplate, } from "./chat.js";
2
3
  function isWithStructuredOutput(x
3
4
  // eslint-disable-next-line @typescript-eslint/ban-types
@@ -51,15 +52,12 @@ export class StructuredPrompt extends ChatPromptTemplate {
51
52
  }
52
53
  if (isRunnableBinding(coerceable) &&
53
54
  isWithStructuredOutput(coerceable.bound)) {
54
- return super.pipe(this.method
55
- ? coerceable.bound
56
- .withStructuredOutput(this.schema, { method: this.method })
57
- .bind(coerceable.kwargs ?? {})
58
- .withConfig(coerceable.config)
59
- : coerceable.bound
60
- .withStructuredOutput(this.schema)
61
- .bind(coerceable.kwargs ?? {})
62
- .withConfig(coerceable.config));
55
+ return super.pipe(new RunnableBinding({
56
+ bound: coerceable.bound.withStructuredOutput(this.schema, ...(this.method ? [{ method: this.method }] : [])),
57
+ kwargs: coerceable.kwargs ?? {},
58
+ config: coerceable.config,
59
+ configFactories: coerceable.configFactories,
60
+ }));
63
61
  }
64
62
  throw new Error(`Structured prompts need to be piped to a language model that supports the "withStructuredOutput()" method.`);
65
63
  }
@@ -63,6 +63,8 @@ class Runnable extends serializable_js_1.Serializable {
63
63
  * Bind arguments to a Runnable, returning a new Runnable.
64
64
  * @param kwargs
65
65
  * @returns A new RunnableBinding that, when invoked, will apply the bound args.
66
+ *
67
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
66
68
  */
67
69
  bind(kwargs) {
68
70
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
@@ -71,6 +73,8 @@ class Runnable extends serializable_js_1.Serializable {
71
73
  /**
72
74
  * Return a new Runnable that maps a list of inputs to a list of outputs,
73
75
  * by calling invoke() with each input.
76
+ *
77
+ * @deprecated This will be removed in the next breaking release.
74
78
  */
75
79
  map() {
76
80
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
@@ -78,7 +82,8 @@ class Runnable extends serializable_js_1.Serializable {
78
82
  }
79
83
  /**
80
84
  * Add retry logic to an existing runnable.
81
- * @param kwargs
85
+ * @param fields.stopAfterAttempt The number of attempts to retry.
86
+ * @param fields.onFailedAttempt A function that is called when a retry fails.
82
87
  * @returns A new RunnableRetry that, when invoked, will retry according to the parameters.
83
88
  */
84
89
  withRetry(fields) {
@@ -774,7 +779,8 @@ class Runnable extends serializable_js_1.Serializable {
774
779
  }
775
780
  exports.Runnable = Runnable;
776
781
  /**
777
- * A runnable that delegates calls to another runnable with a set of kwargs.
782
+ * Wraps a runnable and applies partial config upon invocation.
783
+ *
778
784
  * @example
779
785
  * ```typescript
780
786
  * import {
@@ -869,8 +875,14 @@ class RunnableBinding extends Runnable {
869
875
  ? await Promise.all(this.configFactories.map(async (configFactory) => await configFactory(config)))
870
876
  : []));
871
877
  }
878
+ /**
879
+ * Binds the runnable with the specified arguments.
880
+ * @param kwargs The arguments to bind the runnable with.
881
+ * @returns A new instance of the `RunnableBinding` class that is bound with the specified arguments.
882
+ *
883
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
884
+ */
872
885
  bind(kwargs) {
873
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
874
886
  return new this.constructor({
875
887
  bound: this.bound,
876
888
  kwargs: { ...this.kwargs, ...kwargs },
@@ -878,7 +890,6 @@ class RunnableBinding extends Runnable {
878
890
  });
879
891
  }
880
892
  withConfig(config) {
881
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
882
893
  return new this.constructor({
883
894
  bound: this.bound,
884
895
  kwargs: this.kwargs,
@@ -886,11 +897,13 @@ class RunnableBinding extends Runnable {
886
897
  });
887
898
  }
888
899
  withRetry(fields) {
889
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
890
- return new this.constructor({
891
- bound: this.bound.withRetry(fields),
900
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
901
+ return new RunnableRetry({
902
+ bound: this.bound,
892
903
  kwargs: this.kwargs,
893
904
  config: this.config,
905
+ maxAttemptNumber: fields?.stopAfterAttempt,
906
+ ...fields,
894
907
  });
895
908
  }
896
909
  async invoke(input, options) {
@@ -982,6 +995,8 @@ exports.RunnableBinding = RunnableBinding;
982
995
  *
983
996
  * // ["Hello, ALICE!", "Hello, BOB!", "Hello, CAROL!"]
984
997
  * ```
998
+ *
999
+ * @deprecated This will be removed in the next breaking release.
985
1000
  */
986
1001
  class RunnableEach extends Runnable {
987
1002
  static lc_name() {
@@ -1013,6 +1028,8 @@ class RunnableEach extends Runnable {
1013
1028
  * Binds the runnable with the specified arguments.
1014
1029
  * @param kwargs The arguments to bind the runnable with.
1015
1030
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
1031
+ *
1032
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
1016
1033
  */
1017
1034
  bind(kwargs) {
1018
1035
  return new RunnableEach({
@@ -30,16 +30,21 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
30
30
  * Bind arguments to a Runnable, returning a new Runnable.
31
31
  * @param kwargs
32
32
  * @returns A new RunnableBinding that, when invoked, will apply the bound args.
33
+ *
34
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
33
35
  */
34
36
  bind(kwargs: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
35
37
  /**
36
38
  * Return a new Runnable that maps a list of inputs to a list of outputs,
37
39
  * by calling invoke() with each input.
40
+ *
41
+ * @deprecated This will be removed in the next breaking release.
38
42
  */
39
43
  map(): Runnable<RunInput[], RunOutput[], CallOptions>;
40
44
  /**
41
45
  * Add retry logic to an existing runnable.
42
- * @param kwargs
46
+ * @param fields.stopAfterAttempt The number of attempts to retry.
47
+ * @param fields.onFailedAttempt A function that is called when a retry fails.
43
48
  * @returns A new RunnableRetry that, when invoked, will retry according to the parameters.
44
49
  */
45
50
  withRetry(fields?: {
@@ -310,12 +315,16 @@ export declare abstract class Runnable<RunInput = any, RunOutput = any, CallOpti
310
315
  }
311
316
  export type RunnableBindingArgs<RunInput, RunOutput, CallOptions extends RunnableConfig = RunnableConfig> = {
312
317
  bound: Runnable<RunInput, RunOutput, CallOptions>;
318
+ /**
319
+ * @deprecated use {@link config} instead
320
+ */
313
321
  kwargs?: Partial<CallOptions>;
314
322
  config: RunnableConfig;
315
- configFactories?: Array<(config: RunnableConfig) => RunnableConfig>;
323
+ configFactories?: Array<(config: RunnableConfig) => RunnableConfig | Promise<RunnableConfig>>;
316
324
  };
317
325
  /**
318
- * A runnable that delegates calls to another runnable with a set of kwargs.
326
+ * Wraps a runnable and applies partial config upon invocation.
327
+ *
319
328
  * @example
320
329
  * ```typescript
321
330
  * import {
@@ -365,8 +374,15 @@ export declare class RunnableBinding<RunInput, RunOutput, CallOptions extends Ru
365
374
  constructor(fields: RunnableBindingArgs<RunInput, RunOutput, CallOptions>);
366
375
  getName(suffix?: string | undefined): string;
367
376
  _mergeConfig(...options: (Partial<CallOptions> | RunnableConfig | undefined)[]): Promise<Partial<CallOptions>>;
377
+ /**
378
+ * Binds the runnable with the specified arguments.
379
+ * @param kwargs The arguments to bind the runnable with.
380
+ * @returns A new instance of the `RunnableBinding` class that is bound with the specified arguments.
381
+ *
382
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
383
+ */
368
384
  bind(kwargs: Partial<CallOptions>): RunnableBinding<RunInput, RunOutput, CallOptions>;
369
- withConfig(config: RunnableConfig): Runnable<RunInput, RunOutput, CallOptions>;
385
+ withConfig(config: Partial<CallOptions>): Runnable<RunInput, RunOutput, CallOptions>;
370
386
  withRetry(fields?: {
371
387
  stopAfterAttempt?: number;
372
388
  onFailedAttempt?: RunnableRetryFailedAttemptHandler;
@@ -428,6 +444,8 @@ export declare class RunnableBinding<RunInput, RunOutput, CallOptions extends Ru
428
444
  *
429
445
  * // ["Hello, ALICE!", "Hello, BOB!", "Hello, CAROL!"]
430
446
  * ```
447
+ *
448
+ * @deprecated This will be removed in the next breaking release.
431
449
  */
432
450
  export declare class RunnableEach<RunInputItem, RunOutputItem, CallOptions extends RunnableConfig> extends Runnable<RunInputItem[], RunOutputItem[], CallOptions> {
433
451
  static lc_name(): string;
@@ -441,6 +459,8 @@ export declare class RunnableEach<RunInputItem, RunOutputItem, CallOptions exten
441
459
  * Binds the runnable with the specified arguments.
442
460
  * @param kwargs The arguments to bind the runnable with.
443
461
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
462
+ *
463
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
444
464
  */
445
465
  bind(kwargs: Partial<CallOptions>): RunnableEach<RunInputItem, RunOutputItem, CallOptions>;
446
466
  /**
@@ -56,6 +56,8 @@ export class Runnable extends Serializable {
56
56
  * Bind arguments to a Runnable, returning a new Runnable.
57
57
  * @param kwargs
58
58
  * @returns A new RunnableBinding that, when invoked, will apply the bound args.
59
+ *
60
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
59
61
  */
60
62
  bind(kwargs) {
61
63
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
@@ -64,6 +66,8 @@ export class Runnable extends Serializable {
64
66
  /**
65
67
  * Return a new Runnable that maps a list of inputs to a list of outputs,
66
68
  * by calling invoke() with each input.
69
+ *
70
+ * @deprecated This will be removed in the next breaking release.
67
71
  */
68
72
  map() {
69
73
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
@@ -71,7 +75,8 @@ export class Runnable extends Serializable {
71
75
  }
72
76
  /**
73
77
  * Add retry logic to an existing runnable.
74
- * @param kwargs
78
+ * @param fields.stopAfterAttempt The number of attempts to retry.
79
+ * @param fields.onFailedAttempt A function that is called when a retry fails.
75
80
  * @returns A new RunnableRetry that, when invoked, will retry according to the parameters.
76
81
  */
77
82
  withRetry(fields) {
@@ -766,7 +771,8 @@ export class Runnable extends Serializable {
766
771
  }
767
772
  }
768
773
  /**
769
- * A runnable that delegates calls to another runnable with a set of kwargs.
774
+ * Wraps a runnable and applies partial config upon invocation.
775
+ *
770
776
  * @example
771
777
  * ```typescript
772
778
  * import {
@@ -861,8 +867,14 @@ export class RunnableBinding extends Runnable {
861
867
  ? await Promise.all(this.configFactories.map(async (configFactory) => await configFactory(config)))
862
868
  : []));
863
869
  }
870
+ /**
871
+ * Binds the runnable with the specified arguments.
872
+ * @param kwargs The arguments to bind the runnable with.
873
+ * @returns A new instance of the `RunnableBinding` class that is bound with the specified arguments.
874
+ *
875
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
876
+ */
864
877
  bind(kwargs) {
865
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
866
878
  return new this.constructor({
867
879
  bound: this.bound,
868
880
  kwargs: { ...this.kwargs, ...kwargs },
@@ -870,7 +882,6 @@ export class RunnableBinding extends Runnable {
870
882
  });
871
883
  }
872
884
  withConfig(config) {
873
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
874
885
  return new this.constructor({
875
886
  bound: this.bound,
876
887
  kwargs: this.kwargs,
@@ -878,11 +889,13 @@ export class RunnableBinding extends Runnable {
878
889
  });
879
890
  }
880
891
  withRetry(fields) {
881
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
882
- return new this.constructor({
883
- bound: this.bound.withRetry(fields),
892
+ // eslint-disable-next-line @typescript-eslint/no-use-before-define
893
+ return new RunnableRetry({
894
+ bound: this.bound,
884
895
  kwargs: this.kwargs,
885
896
  config: this.config,
897
+ maxAttemptNumber: fields?.stopAfterAttempt,
898
+ ...fields,
886
899
  });
887
900
  }
888
901
  async invoke(input, options) {
@@ -973,6 +986,8 @@ export class RunnableBinding extends Runnable {
973
986
  *
974
987
  * // ["Hello, ALICE!", "Hello, BOB!", "Hello, CAROL!"]
975
988
  * ```
989
+ *
990
+ * @deprecated This will be removed in the next breaking release.
976
991
  */
977
992
  export class RunnableEach extends Runnable {
978
993
  static lc_name() {
@@ -1004,6 +1019,8 @@ export class RunnableEach extends Runnable {
1004
1019
  * Binds the runnable with the specified arguments.
1005
1020
  * @param kwargs The arguments to bind the runnable with.
1006
1021
  * @returns A new instance of the `RunnableEach` class that is bound with the specified arguments.
1022
+ *
1023
+ * @deprecated Use {@link withConfig} instead. This will be removed in the next breaking release.
1007
1024
  */
1008
1025
  bind(kwargs) {
1009
1026
  return new RunnableEach({
@@ -112,7 +112,7 @@ class RunnablePassthrough extends base_js_1.Runnable {
112
112
  * schema: async () => db.getTableInfo(),
113
113
  * }),
114
114
  * prompt,
115
- * new ChatOpenAI({}).bind({ stop: ["\nSQLResult:"] }),
115
+ * new ChatOpenAI({}).withConfig({ stop: ["\nSQLResult:"] }),
116
116
  * new StringOutputParser(),
117
117
  * ]);
118
118
  * const result = await sqlQueryGeneratorChain.invoke({
@@ -57,7 +57,7 @@ export declare class RunnablePassthrough<RunInput = any> extends Runnable<RunInp
57
57
  * schema: async () => db.getTableInfo(),
58
58
  * }),
59
59
  * prompt,
60
- * new ChatOpenAI({}).bind({ stop: ["\nSQLResult:"] }),
60
+ * new ChatOpenAI({}).withConfig({ stop: ["\nSQLResult:"] }),
61
61
  * new StringOutputParser(),
62
62
  * ]);
63
63
  * const result = await sqlQueryGeneratorChain.invoke({
@@ -109,7 +109,7 @@ export class RunnablePassthrough extends Runnable {
109
109
  * schema: async () => db.getTableInfo(),
110
110
  * }),
111
111
  * prompt,
112
- * new ChatOpenAI({}).bind({ stop: ["\nSQLResult:"] }),
112
+ * new ChatOpenAI({}).withConfig({ stop: ["\nSQLResult:"] }),
113
113
  * new StringOutputParser(),
114
114
  * ]);
115
115
  * const result = await sqlQueryGeneratorChain.invoke({
@@ -239,6 +239,8 @@ function serialize(input) {
239
239
  * `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
240
240
  * other runnables support.
241
241
  *
242
+ * @deprecated LangServe is no longer actively developed - please consider using LangGraph Platform.
243
+ *
242
244
  * @param url - The base URL of the LangServe endpoint.
243
245
  * @param options - Optional configuration for the remote runnable, including timeout and headers.
244
246
  * @param fetch - Optional custom fetch implementation.
@@ -15,6 +15,8 @@ type RemoteRunnableOptions = {
15
15
  * `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
16
16
  * other runnables support.
17
17
  *
18
+ * @deprecated LangServe is no longer actively developed - please consider using LangGraph Platform.
19
+ *
18
20
  * @param url - The base URL of the LangServe endpoint.
19
21
  * @param options - Optional configuration for the remote runnable, including timeout and headers.
20
22
  * @param fetch - Optional custom fetch implementation.
@@ -236,6 +236,8 @@ function serialize(input) {
236
236
  * `.invoke()`, `.stream()`, `.streamEvents()`, etc. methods that
237
237
  * other runnables support.
238
238
  *
239
+ * @deprecated LangServe is no longer actively developed - please consider using LangGraph Platform.
240
+ *
239
241
  * @param url - The base URL of the LangServe endpoint.
240
242
  * @param options - Optional configuration for the remote runnable, including timeout and headers.
241
243
  * @param fetch - Optional custom fetch implementation.
@@ -426,7 +426,7 @@ function _formatToolOutput(params) {
426
426
  }
427
427
  function _stringify(content) {
428
428
  try {
429
- return JSON.stringify(content, null, 2);
429
+ return JSON.stringify(content, null, 2) ?? "";
430
430
  }
431
431
  catch (_noOp) {
432
432
  return `${content}`;
@@ -413,7 +413,7 @@ function _formatToolOutput(params) {
413
413
  }
414
414
  function _stringify(content) {
415
415
  try {
416
- return JSON.stringify(content, null, 2);
416
+ return JSON.stringify(content, null, 2) ?? "";
417
417
  }
418
418
  catch (_noOp) {
419
419
  return `${content}`;
@@ -151,7 +151,10 @@ class LangChainTracer extends base_js_1.BaseTracer {
151
151
  }
152
152
  static getTraceableRunTree() {
153
153
  try {
154
- return (0, traceable_1.getCurrentRunTree)();
154
+ return (
155
+ // The type cast here provides forward compatibility. Old versions of LangSmith will just
156
+ // ignore the permitAbsentRunTree arg.
157
+ traceable_1.getCurrentRunTree(true));
155
158
  }
156
159
  catch {
157
160
  return undefined;
@@ -148,7 +148,10 @@ export class LangChainTracer extends BaseTracer {
148
148
  }
149
149
  static getTraceableRunTree() {
150
150
  try {
151
- return getCurrentRunTree();
151
+ return (
152
+ // The type cast here provides forward compatibility. Old versions of LangSmith will just
153
+ // ignore the permitAbsentRunTree arg.
154
+ getCurrentRunTree(true));
152
155
  }
153
156
  catch {
154
157
  return undefined;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.charChunks = void 0;
4
+ const index_js_1 = require("../../messages/index.cjs");
5
+ /** Tiny helper to convert string into char chunk. For eg: Turn `"Hi!"` into `[AIMessageChunk("H"), AIMessageChunk("i"), AIMessageChunk("!")] */
6
+ const charChunks = (text) => [...text].map((c) => new index_js_1.AIMessageChunk({ content: c }));
7
+ exports.charChunks = charChunks;
@@ -0,0 +1,3 @@
1
+ import { AIMessageChunk } from "../../messages/index.js";
2
+ /** Tiny helper to convert string into char chunk. For eg: Turn `"Hi!"` into `[AIMessageChunk("H"), AIMessageChunk("i"), AIMessageChunk("!")] */
3
+ export declare const charChunks: (text: string) => AIMessageChunk[];
@@ -0,0 +1,3 @@
1
+ import { AIMessageChunk } from "../../messages/index.js";
2
+ /** Tiny helper to convert string into char chunk. For eg: Turn `"Hi!"` into `[AIMessageChunk("H"), AIMessageChunk("i"), AIMessageChunk("!")] */
3
+ export const charChunks = (text) => [...text].map((c) => new AIMessageChunk({ content: c }));
@@ -16,6 +16,7 @@ const base_js_2 = require("../../runnables/base.cjs");
16
16
  const index_js_3 = require("../../tools/index.cjs");
17
17
  const base_js_3 = require("../../tracers/base.cjs");
18
18
  const embeddings_js_1 = require("../../embeddings.cjs");
19
+ const json_schema_js_1 = require("../json_schema.cjs");
19
20
  const vectorstores_js_1 = require("../../vectorstores.cjs");
20
21
  const similarities_js_1 = require("../ml-distance/similarities.cjs");
21
22
  /**
@@ -186,8 +187,8 @@ class FakeChatModel extends chat_models_js_1.BaseChatModel {
186
187
  }
187
188
  exports.FakeChatModel = FakeChatModel;
188
189
  class FakeStreamingChatModel extends chat_models_js_1.BaseChatModel {
189
- constructor(fields) {
190
- super(fields);
190
+ constructor({ sleep = 50, responses = [], chunks = [], toolStyle = "openai", thrownErrorString, ...rest }) {
191
+ super(rest);
191
192
  Object.defineProperty(this, "sleep", {
192
193
  enumerable: true,
193
194
  configurable: true,
@@ -198,7 +199,19 @@ class FakeStreamingChatModel extends chat_models_js_1.BaseChatModel {
198
199
  enumerable: true,
199
200
  configurable: true,
200
201
  writable: true,
201
- value: void 0
202
+ value: []
203
+ });
204
+ Object.defineProperty(this, "chunks", {
205
+ enumerable: true,
206
+ configurable: true,
207
+ writable: true,
208
+ value: []
209
+ });
210
+ Object.defineProperty(this, "toolStyle", {
211
+ enumerable: true,
212
+ configurable: true,
213
+ writable: true,
214
+ value: "openai"
202
215
  });
203
216
  Object.defineProperty(this, "thrownErrorString", {
204
217
  enumerable: true,
@@ -206,54 +219,120 @@ class FakeStreamingChatModel extends chat_models_js_1.BaseChatModel {
206
219
  writable: true,
207
220
  value: void 0
208
221
  });
209
- this.sleep = fields.sleep ?? this.sleep;
210
- this.responses = fields.responses;
211
- this.thrownErrorString = fields.thrownErrorString;
222
+ Object.defineProperty(this, "tools", {
223
+ enumerable: true,
224
+ configurable: true,
225
+ writable: true,
226
+ value: []
227
+ });
228
+ this.sleep = sleep;
229
+ this.responses = responses;
230
+ this.chunks = chunks;
231
+ this.toolStyle = toolStyle;
232
+ this.thrownErrorString = thrownErrorString;
212
233
  }
213
234
  _llmType() {
214
235
  return "fake";
215
236
  }
237
+ bindTools(tools) {
238
+ const merged = [...this.tools, ...tools];
239
+ const toolDicts = merged.map((t) => {
240
+ switch (this.toolStyle) {
241
+ case "openai":
242
+ return {
243
+ type: "function",
244
+ function: {
245
+ name: t.name,
246
+ description: t.description,
247
+ parameters: (0, json_schema_js_1.toJsonSchema)(t.schema),
248
+ },
249
+ };
250
+ case "anthropic":
251
+ return {
252
+ name: t.name,
253
+ description: t.description,
254
+ input_schema: (0, json_schema_js_1.toJsonSchema)(t.schema),
255
+ };
256
+ case "bedrock":
257
+ return {
258
+ toolSpec: {
259
+ name: t.name,
260
+ description: t.description,
261
+ inputSchema: (0, json_schema_js_1.toJsonSchema)(t.schema),
262
+ },
263
+ };
264
+ case "google":
265
+ return {
266
+ name: t.name,
267
+ description: t.description,
268
+ parameters: (0, json_schema_js_1.toJsonSchema)(t.schema),
269
+ };
270
+ default:
271
+ throw new Error(`Unsupported tool style: ${this.toolStyle}`);
272
+ }
273
+ });
274
+ const wrapped = this.toolStyle === "google"
275
+ ? [{ functionDeclarations: toolDicts }]
276
+ : toolDicts;
277
+ /* creating a *new* instance – mirrors LangChain .bind semantics for type-safety and avoiding noise */
278
+ const next = new FakeStreamingChatModel({
279
+ sleep: this.sleep,
280
+ responses: this.responses,
281
+ chunks: this.chunks,
282
+ toolStyle: this.toolStyle,
283
+ thrownErrorString: this.thrownErrorString,
284
+ });
285
+ next.tools = merged;
286
+ return next.withConfig({ tools: wrapped });
287
+ }
216
288
  async _generate(messages, _options, _runManager) {
217
289
  if (this.thrownErrorString) {
218
290
  throw new Error(this.thrownErrorString);
219
291
  }
220
- const content = this.responses?.[0].content ?? messages[0].content;
292
+ const content = this.responses?.[0]?.content ?? messages[0].content ?? "";
221
293
  const generation = {
222
294
  generations: [
223
295
  {
224
296
  text: "",
225
297
  message: new index_js_1.AIMessage({
226
298
  content,
299
+ tool_calls: this.chunks?.[0]?.tool_calls,
227
300
  }),
228
301
  },
229
302
  ],
230
303
  };
231
304
  return generation;
232
305
  }
233
- async *_streamResponseChunks(messages, _options, _runManager) {
306
+ async *_streamResponseChunks(_messages, _options, runManager) {
234
307
  if (this.thrownErrorString) {
235
308
  throw new Error(this.thrownErrorString);
236
309
  }
237
- const content = this.responses?.[0].content ?? messages[0].content;
238
- if (typeof content !== "string") {
239
- for (const _ of this.responses ?? messages) {
240
- yield new outputs_js_1.ChatGenerationChunk({
241
- text: "",
310
+ if (this.chunks?.length) {
311
+ for (const msgChunk of this.chunks) {
312
+ const cg = new outputs_js_1.ChatGenerationChunk({
242
313
  message: new index_js_1.AIMessageChunk({
243
- content,
314
+ content: msgChunk.content,
315
+ tool_calls: msgChunk.tool_calls,
316
+ additional_kwargs: msgChunk.additional_kwargs ?? {},
244
317
  }),
318
+ text: msgChunk.content?.toString() ?? "",
245
319
  });
320
+ yield cg;
321
+ await runManager?.handleLLMNewToken(msgChunk.content, undefined, undefined, undefined, undefined, { chunk: cg });
246
322
  }
323
+ return;
247
324
  }
248
- else {
249
- for (const _ of this.responses ?? messages) {
250
- yield new outputs_js_1.ChatGenerationChunk({
251
- text: content,
252
- message: new index_js_1.AIMessageChunk({
253
- content,
254
- }),
255
- });
256
- }
325
+ const fallback = this.responses?.[0] ??
326
+ new index_js_1.AIMessage(typeof _messages[0].content === "string" ? _messages[0].content : "");
327
+ const text = typeof fallback.content === "string" ? fallback.content : "";
328
+ for (const ch of text) {
329
+ await new Promise((r) => setTimeout(r, this.sleep));
330
+ const cg = new outputs_js_1.ChatGenerationChunk({
331
+ message: new index_js_1.AIMessageChunk({ content: ch }),
332
+ text: ch,
333
+ });
334
+ yield cg;
335
+ await runManager?.handleLLMNewToken(ch, undefined, undefined, undefined, undefined, { chunk: cg });
257
336
  }
258
337
  }
259
338
  }
@@ -430,7 +509,13 @@ class FakeListChatModel extends chat_models_js_1.BaseChatModel {
430
509
  withStructuredOutput(_params, _config) {
431
510
  return base_js_2.RunnableLambda.from(async (input) => {
432
511
  const message = await this.invoke(input);
433
- return JSON.parse(message.content);
512
+ if (message.tool_calls?.[0]?.args) {
513
+ return message.tool_calls[0].args;
514
+ }
515
+ if (typeof message.content === "string") {
516
+ return JSON.parse(message.content);
517
+ }
518
+ throw new Error("No structured output found");
434
519
  });
435
520
  }
436
521
  }
@@ -4,7 +4,7 @@ import { BaseChatMessageHistory, BaseListChatMessageHistory } from "../../chat_h
4
4
  import { Document } from "../../documents/document.js";
5
5
  import { BaseChatModel, BaseChatModelCallOptions, BaseChatModelParams } from "../../language_models/chat_models.js";
6
6
  import { BaseLLMParams, LLM } from "../../language_models/llms.js";
7
- import { BaseMessage, AIMessage } from "../../messages/index.js";
7
+ import { BaseMessage, AIMessage, AIMessageChunk } from "../../messages/index.js";
8
8
  import { BaseOutputParser } from "../../output_parsers/base.js";
9
9
  import { GenerationChunk, type ChatResult, ChatGenerationChunk } from "../../outputs.js";
10
10
  import { BaseRetriever } from "../../retrievers/index.js";
@@ -60,18 +60,18 @@ export declare class FakeChatModel extends BaseChatModel {
60
60
  _llmType(): string;
61
61
  _generate(messages: BaseMessage[], options?: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
62
62
  }
63
- export declare class FakeStreamingChatModel extends BaseChatModel {
64
- sleep?: number;
65
- responses?: BaseMessage[];
63
+ export declare class FakeStreamingChatModel extends BaseChatModel<FakeStreamingChatModelCallOptions> {
64
+ sleep: number;
65
+ responses: BaseMessage[];
66
+ chunks: AIMessageChunk[];
67
+ toolStyle: "openai" | "anthropic" | "bedrock" | "google";
66
68
  thrownErrorString?: string;
67
- constructor(fields: {
68
- sleep?: number;
69
- responses?: BaseMessage[];
70
- thrownErrorString?: string;
71
- } & BaseLLMParams);
69
+ private tools;
70
+ constructor({ sleep, responses, chunks, toolStyle, thrownErrorString, ...rest }: FakeStreamingChatModelFields & BaseLLMParams);
72
71
  _llmType(): string;
72
+ bindTools(tools: (StructuredTool | ToolSpec)[]): Runnable<BaseLanguageModelInput, AIMessageChunk, FakeStreamingChatModelCallOptions>;
73
73
  _generate(messages: BaseMessage[], _options: this["ParsedCallOptions"], _runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
74
- _streamResponseChunks(messages: BaseMessage[], _options: this["ParsedCallOptions"], _runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
74
+ _streamResponseChunks(_messages: BaseMessage[], _options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
75
75
  }
76
76
  export declare class FakeRetriever extends BaseRetriever {
77
77
  lc_namespace: string[];
@@ -81,6 +81,32 @@ export declare class FakeRetriever extends BaseRetriever {
81
81
  });
82
82
  _getRelevantDocuments(_query: string): Promise<Document<Record<string, any>>[]>;
83
83
  }
84
+ /** Minimal shape actually needed by `bindTools` */
85
+ export interface ToolSpec {
86
+ name: string;
87
+ description?: string;
88
+ schema: z.ZodTypeAny | Record<string, unknown>;
89
+ }
90
+ /**
91
+ * Interface specific to the Fake Streaming Chat model.
92
+ */
93
+ export interface FakeStreamingChatModelCallOptions extends BaseChatModelCallOptions {
94
+ }
95
+ /**
96
+ * Interface for the Constructor-field specific to the Fake Streaming Chat model (all optional because we fill in defaults).
97
+ */
98
+ export interface FakeStreamingChatModelFields extends BaseChatModelParams {
99
+ /** Milliseconds to pause between fallback char-by-char chunks */
100
+ sleep?: number;
101
+ /** Full AI messages to fall back to when no `chunks` supplied */
102
+ responses?: BaseMessage[];
103
+ /** Exact chunks to emit (can include tool-call deltas) */
104
+ chunks?: AIMessageChunk[];
105
+ /** How tool specs are formatted in `bindTools` */
106
+ toolStyle?: "openai" | "anthropic" | "bedrock" | "google";
107
+ /** Throw this error instead of streaming (useful in tests) */
108
+ thrownErrorString?: string;
109
+ }
84
110
  /**
85
111
  * Interface for the input parameters specific to the Fake List Chat model.
86
112
  */
@@ -13,6 +13,7 @@ import { Runnable, RunnableLambda } from "../../runnables/base.js";
13
13
  import { StructuredTool } from "../../tools/index.js";
14
14
  import { BaseTracer } from "../../tracers/base.js";
15
15
  import { Embeddings, } from "../../embeddings.js";
16
+ import { toJsonSchema } from "../json_schema.js";
16
17
  import { VectorStore } from "../../vectorstores.js";
17
18
  import { cosine } from "../ml-distance/similarities.js";
18
19
  /**
@@ -178,8 +179,8 @@ export class FakeChatModel extends BaseChatModel {
178
179
  }
179
180
  }
180
181
  export class FakeStreamingChatModel extends BaseChatModel {
181
- constructor(fields) {
182
- super(fields);
182
+ constructor({ sleep = 50, responses = [], chunks = [], toolStyle = "openai", thrownErrorString, ...rest }) {
183
+ super(rest);
183
184
  Object.defineProperty(this, "sleep", {
184
185
  enumerable: true,
185
186
  configurable: true,
@@ -190,7 +191,19 @@ export class FakeStreamingChatModel extends BaseChatModel {
190
191
  enumerable: true,
191
192
  configurable: true,
192
193
  writable: true,
193
- value: void 0
194
+ value: []
195
+ });
196
+ Object.defineProperty(this, "chunks", {
197
+ enumerable: true,
198
+ configurable: true,
199
+ writable: true,
200
+ value: []
201
+ });
202
+ Object.defineProperty(this, "toolStyle", {
203
+ enumerable: true,
204
+ configurable: true,
205
+ writable: true,
206
+ value: "openai"
194
207
  });
195
208
  Object.defineProperty(this, "thrownErrorString", {
196
209
  enumerable: true,
@@ -198,54 +211,120 @@ export class FakeStreamingChatModel extends BaseChatModel {
198
211
  writable: true,
199
212
  value: void 0
200
213
  });
201
- this.sleep = fields.sleep ?? this.sleep;
202
- this.responses = fields.responses;
203
- this.thrownErrorString = fields.thrownErrorString;
214
+ Object.defineProperty(this, "tools", {
215
+ enumerable: true,
216
+ configurable: true,
217
+ writable: true,
218
+ value: []
219
+ });
220
+ this.sleep = sleep;
221
+ this.responses = responses;
222
+ this.chunks = chunks;
223
+ this.toolStyle = toolStyle;
224
+ this.thrownErrorString = thrownErrorString;
204
225
  }
205
226
  _llmType() {
206
227
  return "fake";
207
228
  }
229
+ bindTools(tools) {
230
+ const merged = [...this.tools, ...tools];
231
+ const toolDicts = merged.map((t) => {
232
+ switch (this.toolStyle) {
233
+ case "openai":
234
+ return {
235
+ type: "function",
236
+ function: {
237
+ name: t.name,
238
+ description: t.description,
239
+ parameters: toJsonSchema(t.schema),
240
+ },
241
+ };
242
+ case "anthropic":
243
+ return {
244
+ name: t.name,
245
+ description: t.description,
246
+ input_schema: toJsonSchema(t.schema),
247
+ };
248
+ case "bedrock":
249
+ return {
250
+ toolSpec: {
251
+ name: t.name,
252
+ description: t.description,
253
+ inputSchema: toJsonSchema(t.schema),
254
+ },
255
+ };
256
+ case "google":
257
+ return {
258
+ name: t.name,
259
+ description: t.description,
260
+ parameters: toJsonSchema(t.schema),
261
+ };
262
+ default:
263
+ throw new Error(`Unsupported tool style: ${this.toolStyle}`);
264
+ }
265
+ });
266
+ const wrapped = this.toolStyle === "google"
267
+ ? [{ functionDeclarations: toolDicts }]
268
+ : toolDicts;
269
+ /* creating a *new* instance – mirrors LangChain .bind semantics for type-safety and avoiding noise */
270
+ const next = new FakeStreamingChatModel({
271
+ sleep: this.sleep,
272
+ responses: this.responses,
273
+ chunks: this.chunks,
274
+ toolStyle: this.toolStyle,
275
+ thrownErrorString: this.thrownErrorString,
276
+ });
277
+ next.tools = merged;
278
+ return next.withConfig({ tools: wrapped });
279
+ }
208
280
  async _generate(messages, _options, _runManager) {
209
281
  if (this.thrownErrorString) {
210
282
  throw new Error(this.thrownErrorString);
211
283
  }
212
- const content = this.responses?.[0].content ?? messages[0].content;
284
+ const content = this.responses?.[0]?.content ?? messages[0].content ?? "";
213
285
  const generation = {
214
286
  generations: [
215
287
  {
216
288
  text: "",
217
289
  message: new AIMessage({
218
290
  content,
291
+ tool_calls: this.chunks?.[0]?.tool_calls,
219
292
  }),
220
293
  },
221
294
  ],
222
295
  };
223
296
  return generation;
224
297
  }
225
- async *_streamResponseChunks(messages, _options, _runManager) {
298
+ async *_streamResponseChunks(_messages, _options, runManager) {
226
299
  if (this.thrownErrorString) {
227
300
  throw new Error(this.thrownErrorString);
228
301
  }
229
- const content = this.responses?.[0].content ?? messages[0].content;
230
- if (typeof content !== "string") {
231
- for (const _ of this.responses ?? messages) {
232
- yield new ChatGenerationChunk({
233
- text: "",
302
+ if (this.chunks?.length) {
303
+ for (const msgChunk of this.chunks) {
304
+ const cg = new ChatGenerationChunk({
234
305
  message: new AIMessageChunk({
235
- content,
306
+ content: msgChunk.content,
307
+ tool_calls: msgChunk.tool_calls,
308
+ additional_kwargs: msgChunk.additional_kwargs ?? {},
236
309
  }),
310
+ text: msgChunk.content?.toString() ?? "",
237
311
  });
312
+ yield cg;
313
+ await runManager?.handleLLMNewToken(msgChunk.content, undefined, undefined, undefined, undefined, { chunk: cg });
238
314
  }
315
+ return;
239
316
  }
240
- else {
241
- for (const _ of this.responses ?? messages) {
242
- yield new ChatGenerationChunk({
243
- text: content,
244
- message: new AIMessageChunk({
245
- content,
246
- }),
247
- });
248
- }
317
+ const fallback = this.responses?.[0] ??
318
+ new AIMessage(typeof _messages[0].content === "string" ? _messages[0].content : "");
319
+ const text = typeof fallback.content === "string" ? fallback.content : "";
320
+ for (const ch of text) {
321
+ await new Promise((r) => setTimeout(r, this.sleep));
322
+ const cg = new ChatGenerationChunk({
323
+ message: new AIMessageChunk({ content: ch }),
324
+ text: ch,
325
+ });
326
+ yield cg;
327
+ await runManager?.handleLLMNewToken(ch, undefined, undefined, undefined, undefined, { chunk: cg });
249
328
  }
250
329
  }
251
330
  }
@@ -420,7 +499,13 @@ export class FakeListChatModel extends BaseChatModel {
420
499
  withStructuredOutput(_params, _config) {
421
500
  return RunnableLambda.from(async (input) => {
422
501
  const message = await this.invoke(input);
423
- return JSON.parse(message.content);
502
+ if (message.tool_calls?.[0]?.args) {
503
+ return message.tool_calls[0].args;
504
+ }
505
+ if (typeof message.content === "string") {
506
+ return JSON.parse(message.content);
507
+ }
508
+ throw new Error("No structured output found");
424
509
  });
425
510
  }
426
511
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/core",
3
- "version": "0.3.55",
3
+ "version": "0.3.57",
4
4
  "description": "Core LangChain.js abstractions and schemas",
5
5
  "type": "module",
6
6
  "engines": {
@@ -38,7 +38,7 @@
38
38
  "camelcase": "6",
39
39
  "decamelize": "1.2.0",
40
40
  "js-tiktoken": "^1.0.12",
41
- "langsmith": "^0.3.16",
41
+ "langsmith": "^0.3.29",
42
42
  "mustache": "^4.2.0",
43
43
  "p-queue": "^6.6.2",
44
44
  "p-retry": "4",