langchain 0.2.17 → 0.2.19

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.
@@ -364,10 +364,17 @@ class AgentExecutor extends base_js_1.BaseChain {
364
364
  writable: true,
365
365
  value: false
366
366
  });
367
+ Object.defineProperty(this, "handleToolRuntimeErrors", {
368
+ enumerable: true,
369
+ configurable: true,
370
+ writable: true,
371
+ value: void 0
372
+ });
367
373
  this.agent = agent;
368
374
  this.tools = input.tools;
369
375
  this.handleParsingErrors =
370
376
  input.handleParsingErrors ?? this.handleParsingErrors;
377
+ this.handleToolRuntimeErrors = input.handleToolRuntimeErrors;
371
378
  this.returnOnlyOutputs = returnOnlyOutputs;
372
379
  if (this.agent._agentActionType() === "multi") {
373
380
  for (const tool of this.tools) {
@@ -481,6 +488,7 @@ class AgentExecutor extends base_js_1.BaseChain {
481
488
  if (typeof observation !== "string") {
482
489
  throw new Error("Received unsupported non-string response from tool call.");
483
490
  }
491
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
484
492
  }
485
493
  catch (e) {
486
494
  // eslint-disable-next-line no-instanceof/no-instanceof
@@ -501,6 +509,9 @@ class AgentExecutor extends base_js_1.BaseChain {
501
509
  observation = await new ExceptionTool().call(observation, runManager?.getChild());
502
510
  return { action, observation: observation ?? "" };
503
511
  }
512
+ else if (this.handleToolRuntimeErrors !== undefined) {
513
+ observation = this.handleToolRuntimeErrors(e);
514
+ }
504
515
  }
505
516
  return { action, observation: observation ?? "" };
506
517
  }));
@@ -86,6 +86,7 @@ export interface AgentExecutorInput extends ChainInputs {
86
86
  maxIterations?: number;
87
87
  earlyStoppingMethod?: StoppingMethod;
88
88
  handleParsingErrors?: boolean | string | ((e: OutputParserException | ToolInputParsingException) => string);
89
+ handleToolRuntimeErrors?: (e: Error) => string;
89
90
  }
90
91
  export type AgentExecutorOutput = ChainValues;
91
92
  /**
@@ -135,6 +136,7 @@ export declare class AgentExecutor extends BaseChain<ChainValues, AgentExecutorO
135
136
  as an observation.
136
137
  */
137
138
  handleParsingErrors: boolean | string | ((e: OutputParserException | ToolInputParsingException) => string);
139
+ handleToolRuntimeErrors?: (e: Error) => string;
138
140
  get inputKeys(): string[];
139
141
  get outputKeys(): string[];
140
142
  constructor(input: AgentExecutorInput);
@@ -359,10 +359,17 @@ export class AgentExecutor extends BaseChain {
359
359
  writable: true,
360
360
  value: false
361
361
  });
362
+ Object.defineProperty(this, "handleToolRuntimeErrors", {
363
+ enumerable: true,
364
+ configurable: true,
365
+ writable: true,
366
+ value: void 0
367
+ });
362
368
  this.agent = agent;
363
369
  this.tools = input.tools;
364
370
  this.handleParsingErrors =
365
371
  input.handleParsingErrors ?? this.handleParsingErrors;
372
+ this.handleToolRuntimeErrors = input.handleToolRuntimeErrors;
366
373
  this.returnOnlyOutputs = returnOnlyOutputs;
367
374
  if (this.agent._agentActionType() === "multi") {
368
375
  for (const tool of this.tools) {
@@ -476,6 +483,7 @@ export class AgentExecutor extends BaseChain {
476
483
  if (typeof observation !== "string") {
477
484
  throw new Error("Received unsupported non-string response from tool call.");
478
485
  }
486
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
479
487
  }
480
488
  catch (e) {
481
489
  // eslint-disable-next-line no-instanceof/no-instanceof
@@ -496,6 +504,9 @@ export class AgentExecutor extends BaseChain {
496
504
  observation = await new ExceptionTool().call(observation, runManager?.getChild());
497
505
  return { action, observation: observation ?? "" };
498
506
  }
507
+ else if (this.handleToolRuntimeErrors !== undefined) {
508
+ observation = this.handleToolRuntimeErrors(e);
509
+ }
499
510
  }
500
511
  return { action, observation: observation ?? "" };
501
512
  }));
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReActSingleInputOutputParser = void 0;
4
4
  const prompts_1 = require("@langchain/core/prompts");
5
+ const output_parsers_1 = require("@langchain/core/output_parsers");
5
6
  const types_js_1 = require("../types.cjs");
6
7
  const prompt_js_1 = require("./prompt.cjs");
7
8
  const FINAL_ANSWER_ACTION = "Final Answer:";
@@ -74,7 +75,7 @@ class ReActSingleInputOutputParser extends types_js_1.AgentActionOutputParser {
74
75
  const actionMatch = text.match(regex);
75
76
  if (actionMatch) {
76
77
  if (includesAnswer) {
77
- throw new Error(`${FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: ${text}`);
78
+ throw new output_parsers_1.OutputParserException(`${FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: ${text}`);
78
79
  }
79
80
  const action = actionMatch[1];
80
81
  const actionInput = actionMatch[2];
@@ -94,7 +95,7 @@ class ReActSingleInputOutputParser extends types_js_1.AgentActionOutputParser {
94
95
  log: text,
95
96
  };
96
97
  }
97
- throw new Error(`Could not parse LLM output: ${text}`);
98
+ throw new output_parsers_1.OutputParserException(`Could not parse LLM output: ${text}`);
98
99
  }
99
100
  /**
100
101
  * Returns the format instructions as a string. If the 'raw' option is
@@ -1,4 +1,5 @@
1
1
  import { renderTemplate } from "@langchain/core/prompts";
2
+ import { OutputParserException } from "@langchain/core/output_parsers";
2
3
  import { AgentActionOutputParser } from "../types.js";
3
4
  import { FORMAT_INSTRUCTIONS } from "./prompt.js";
4
5
  const FINAL_ANSWER_ACTION = "Final Answer:";
@@ -71,7 +72,7 @@ export class ReActSingleInputOutputParser extends AgentActionOutputParser {
71
72
  const actionMatch = text.match(regex);
72
73
  if (actionMatch) {
73
74
  if (includesAnswer) {
74
- throw new Error(`${FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: ${text}`);
75
+ throw new OutputParserException(`${FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE}: ${text}`);
75
76
  }
76
77
  const action = actionMatch[1];
77
78
  const actionInput = actionMatch[2];
@@ -91,7 +92,7 @@ export class ReActSingleInputOutputParser extends AgentActionOutputParser {
91
92
  log: text,
92
93
  };
93
94
  }
94
- throw new Error(`Could not parse LLM output: ${text}`);
95
+ throw new OutputParserException(`Could not parse LLM output: ${text}`);
95
96
  }
96
97
  /**
97
98
  * Returns the format instructions as a string. If the 'raw' option is
@@ -13,7 +13,7 @@ Chat History:
13
13
  Follow Up Input: {question}
14
14
  Standalone question:`;
15
15
  /**
16
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
16
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
17
17
  * `createRetrievalChain`.
18
18
  *
19
19
  * Class for conducting conversational question-answering tasks with a
@@ -21,7 +21,7 @@ export interface ConversationalRetrievalQAChainInput extends ChainInputs {
21
21
  inputKey?: string;
22
22
  }
23
23
  /**
24
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
24
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
25
25
  * `createRetrievalChain`.
26
26
  *
27
27
  * Class for conducting conversational question-answering tasks with a
@@ -10,7 +10,7 @@ Chat History:
10
10
  Follow Up Input: {question}
11
11
  Standalone question:`;
12
12
  /**
13
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
13
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
14
14
  * `createRetrievalChain`.
15
15
  *
16
16
  * Class for conducting conversational question-answering tasks with a
@@ -29,7 +29,7 @@ function _getLanguageModel(llmLike) {
29
29
  }
30
30
  }
31
31
  /**
32
- * @deprecated This class will be removed in 0.3.0. Use the LangChain Expression Language (LCEL) instead.
32
+ * @deprecated This class will be removed in 1.0.0. Use the LangChain Expression Language (LCEL) instead.
33
33
  * See the example below for how to use LCEL with the LLMChain class:
34
34
  *
35
35
  * Chain to run queries against LLMs.
@@ -29,7 +29,7 @@ export interface LLMChainInput<T extends string | object = string, Model extends
29
29
  outputKey?: string;
30
30
  }
31
31
  /**
32
- * @deprecated This class will be removed in 0.3.0. Use the LangChain Expression Language (LCEL) instead.
32
+ * @deprecated This class will be removed in 1.0.0. Use the LangChain Expression Language (LCEL) instead.
33
33
  * See the example below for how to use LCEL with the LLMChain class:
34
34
  *
35
35
  * Chain to run queries against LLMs.
@@ -26,7 +26,7 @@ function _getLanguageModel(llmLike) {
26
26
  }
27
27
  }
28
28
  /**
29
- * @deprecated This class will be removed in 0.3.0. Use the LangChain Expression Language (LCEL) instead.
29
+ * @deprecated This class will be removed in 1.0.0. Use the LangChain Expression Language (LCEL) instead.
30
30
  * See the example below for how to use LCEL with the LLMChain class:
31
31
  *
32
32
  * Chain to run queries against LLMs.
@@ -133,7 +133,9 @@ function convertOpenAPISchemaToJSONSchema(schema, spec) {
133
133
  }
134
134
  // eslint-disable-next-line no-param-reassign
135
135
  jsonSchema.properties[propertyName] = convertOpenAPISchemaToJSONSchema(openAPIProperty, spec);
136
- if (openAPIProperty.required && jsonSchema.required !== undefined) {
136
+ if ((openAPIProperty.required ||
137
+ schema.required?.includes(propertyName)) &&
138
+ jsonSchema.required !== undefined) {
137
139
  jsonSchema.required.push(propertyName);
138
140
  }
139
141
  return jsonSchema;
@@ -130,7 +130,9 @@ export function convertOpenAPISchemaToJSONSchema(schema, spec) {
130
130
  }
131
131
  // eslint-disable-next-line no-param-reassign
132
132
  jsonSchema.properties[propertyName] = convertOpenAPISchemaToJSONSchema(openAPIProperty, spec);
133
- if (openAPIProperty.required && jsonSchema.required !== undefined) {
133
+ if ((openAPIProperty.required ||
134
+ schema.required?.includes(propertyName)) &&
135
+ jsonSchema.required !== undefined) {
134
136
  jsonSchema.required.push(propertyName);
135
137
  }
136
138
  return jsonSchema;
@@ -4,7 +4,7 @@ exports.RetrievalQAChain = void 0;
4
4
  const base_js_1 = require("./base.cjs");
5
5
  const load_js_1 = require("./question_answering/load.cjs");
6
6
  /**
7
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
7
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
8
8
  * `createRetrievalChain`:
9
9
  * Class representing a chain for performing question-answering tasks with
10
10
  * a retrieval component.
@@ -16,7 +16,7 @@ export interface RetrievalQAChainInput extends Omit<ChainInputs, "memory"> {
16
16
  returnSourceDocuments?: boolean;
17
17
  }
18
18
  /**
19
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
19
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
20
20
  * `createRetrievalChain`:
21
21
  * Class representing a chain for performing question-answering tasks with
22
22
  * a retrieval component.
@@ -1,7 +1,7 @@
1
1
  import { BaseChain } from "./base.js";
2
2
  import { loadQAStuffChain, } from "./question_answering/load.js";
3
3
  /**
4
- * @deprecated This class will be removed in 0.3.0. See below for an example implementation using
4
+ * @deprecated This class will be removed in 1.0.0. See below for an example implementation using
5
5
  * `createRetrievalChain`:
6
6
  * Class representing a chain for performing question-answering tasks with
7
7
  * a retrieval component.
@@ -51,6 +51,11 @@ const stores_1 = require("@langchain/core/stores");
51
51
  * await store.mdelete([key]);
52
52
  * }
53
53
  * ```
54
+ *
55
+ * @security **Security Notice** This file store
56
+ * can alter any text file in the provided directory and any subfolders.
57
+ * Make sure that the path you specify when initializing the store is free
58
+ * of other files.
54
59
  */
55
60
  class LocalFileStore extends stores_1.BaseStore {
56
61
  constructor(fields) {
@@ -75,6 +80,10 @@ class LocalFileStore extends stores_1.BaseStore {
75
80
  * @returns Promise that resolves to the parsed file content.
76
81
  */
77
82
  async getParsedFile(key) {
83
+ // Validate the key to prevent path traversal
84
+ if (!/^[a-zA-Z0-9_\-:.]+$/.test(key)) {
85
+ throw new Error("Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.");
86
+ }
78
87
  try {
79
88
  const fileContent = await fs.readFile(this.getFullPath(key));
80
89
  if (!fileContent) {
@@ -111,11 +120,20 @@ class LocalFileStore extends stores_1.BaseStore {
111
120
  getFullPath(key) {
112
121
  try {
113
122
  const keyAsTxtFile = `${key}.txt`;
114
- const fullPath = path.join(this.rootPath, keyAsTxtFile);
123
+ // Validate the key to prevent path traversal
124
+ if (!/^[a-zA-Z0-9_.\-/]+$/.test(key)) {
125
+ throw new Error(`Invalid characters in key: ${key}`);
126
+ }
127
+ const fullPath = path.resolve(this.rootPath, keyAsTxtFile);
128
+ const commonPath = path.resolve(this.rootPath);
129
+ if (!fullPath.startsWith(commonPath)) {
130
+ throw new Error(`Invalid key: ${key}. Key should be relative to the root path. ` +
131
+ `Root path: ${this.rootPath}, Full path: ${fullPath}`);
132
+ }
115
133
  return fullPath;
116
134
  }
117
135
  catch (e) {
118
- throw new Error(`Error getting full path for key: ${key}.\nError: ${JSON.stringify(e)}`);
136
+ throw new Error(`Error getting full path for key: ${key}.\nError: ${String(e)}`);
119
137
  }
120
138
  }
121
139
  /**
@@ -23,6 +23,11 @@ import { BaseStore } from "@langchain/core/stores";
23
23
  * await store.mdelete([key]);
24
24
  * }
25
25
  * ```
26
+ *
27
+ * @security **Security Notice** This file store
28
+ * can alter any text file in the provided directory and any subfolders.
29
+ * Make sure that the path you specify when initializing the store is free
30
+ * of other files.
26
31
  */
27
32
  export declare class LocalFileStore extends BaseStore<string, Uint8Array> {
28
33
  lc_namespace: string[];
@@ -25,6 +25,11 @@ import { BaseStore } from "@langchain/core/stores";
25
25
  * await store.mdelete([key]);
26
26
  * }
27
27
  * ```
28
+ *
29
+ * @security **Security Notice** This file store
30
+ * can alter any text file in the provided directory and any subfolders.
31
+ * Make sure that the path you specify when initializing the store is free
32
+ * of other files.
28
33
  */
29
34
  export class LocalFileStore extends BaseStore {
30
35
  constructor(fields) {
@@ -49,6 +54,10 @@ export class LocalFileStore extends BaseStore {
49
54
  * @returns Promise that resolves to the parsed file content.
50
55
  */
51
56
  async getParsedFile(key) {
57
+ // Validate the key to prevent path traversal
58
+ if (!/^[a-zA-Z0-9_\-:.]+$/.test(key)) {
59
+ throw new Error("Invalid key. Only alphanumeric characters, underscores, hyphens, colons, and periods are allowed.");
60
+ }
52
61
  try {
53
62
  const fileContent = await fs.readFile(this.getFullPath(key));
54
63
  if (!fileContent) {
@@ -85,11 +94,20 @@ export class LocalFileStore extends BaseStore {
85
94
  getFullPath(key) {
86
95
  try {
87
96
  const keyAsTxtFile = `${key}.txt`;
88
- const fullPath = path.join(this.rootPath, keyAsTxtFile);
97
+ // Validate the key to prevent path traversal
98
+ if (!/^[a-zA-Z0-9_.\-/]+$/.test(key)) {
99
+ throw new Error(`Invalid characters in key: ${key}`);
100
+ }
101
+ const fullPath = path.resolve(this.rootPath, keyAsTxtFile);
102
+ const commonPath = path.resolve(this.rootPath);
103
+ if (!fullPath.startsWith(commonPath)) {
104
+ throw new Error(`Invalid key: ${key}. Key should be relative to the root path. ` +
105
+ `Root path: ${this.rootPath}, Full path: ${fullPath}`);
106
+ }
89
107
  return fullPath;
90
108
  }
91
109
  catch (e) {
92
- throw new Error(`Error getting full path for key: ${key}.\nError: ${JSON.stringify(e)}`);
110
+ throw new Error(`Error getting full path for key: ${key}.\nError: ${String(e)}`);
93
111
  }
94
112
  }
95
113
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "langchain",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "description": "Typescript bindings for langchain",
5
5
  "type": "module",
6
6
  "engines": {
@@ -584,9 +584,9 @@
584
584
  "prepack": "yarn build",
585
585
  "release": "release-it --only-version --config .release-it.json",
586
586
  "test": "NODE_OPTIONS=--experimental-vm-modules jest --testPathIgnorePatterns=\\.int\\.test.ts --testTimeout 30000 --maxWorkers=50%",
587
- "test:watch": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
588
- "test:integration": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
589
- "test:single": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
587
+ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
588
+ "test:integration": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
589
+ "test:single": "NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
590
590
  "format": "prettier --config .prettierrc --write \"src\"",
591
591
  "format:check": "prettier --config .prettierrc --check \"src\""
592
592
  },
@@ -600,7 +600,7 @@
600
600
  "@aws-sdk/types": "^3.357.0",
601
601
  "@azure/storage-blob": "^12.15.0",
602
602
  "@browserbasehq/sdk": "^1.1.5",
603
- "@cloudflare/workers-types": "^4.20230922.0",
603
+ "@cloudflare/workers-types": "^4.20240909.0",
604
604
  "@faker-js/faker": "^7.6.0",
605
605
  "@gomomento/sdk": "^1.51.1",
606
606
  "@gomomento/sdk-core": "^1.51.1",
@@ -609,7 +609,7 @@
609
609
  "@langchain/aws": "^0.0.5",
610
610
  "@langchain/cohere": "^0.2.1",
611
611
  "@langchain/google-genai": "^0.0.26",
612
- "@langchain/google-vertexai": "^0.0.26",
612
+ "@langchain/google-vertexai": "~0.0",
613
613
  "@langchain/groq": "^0.0.15",
614
614
  "@langchain/mistralai": "^0.0.26",
615
615
  "@langchain/ollama": "^0.0.2",
@@ -670,7 +670,7 @@
670
670
  "playwright": "^1.32.1",
671
671
  "prettier": "^2.8.3",
672
672
  "puppeteer": "^22.0.0",
673
- "pyodide": "^0.24.1",
673
+ "pyodide": "^0.26.2",
674
674
  "redis": "^4.6.6",
675
675
  "release-it": "^17.6.0",
676
676
  "rimraf": "^5.0.1",
@@ -735,7 +735,7 @@
735
735
  "peggy": "^3.0.2",
736
736
  "playwright": "*",
737
737
  "puppeteer": "*",
738
- "pyodide": "^0.24.1",
738
+ "pyodide": ">=0.24.1 <0.27.0",
739
739
  "redis": "*",
740
740
  "sonix-speech-recognition": "*",
741
741
  "srt-parser-2": "*",