langchain 0.0.108 → 0.0.109

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,4 +1,4 @@
1
- import { KVMap, BaseRun } from "langchainplus-sdk/schemas";
1
+ import { KVMap, BaseRun } from "langsmith/schemas";
2
2
  import { AgentAction, AgentFinish, BaseMessage, ChainValues, LLMResult } from "../../schema/index.js";
3
3
  import { Serialized } from "../../load/serializable.js";
4
4
  import { BaseCallbackHandler, BaseCallbackHandlerInput, NewTokenIndices } from "../base.js";
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LangChainTracer = void 0;
4
- const langchainplus_sdk_1 = require("langchainplus-sdk");
4
+ const langsmith_1 = require("langsmith");
5
5
  const env_js_1 = require("../../util/env.cjs");
6
6
  const tracer_js_1 = require("./tracer.cjs");
7
7
  class LangChainTracer extends tracer_js_1.BaseTracer {
@@ -37,7 +37,7 @@ class LangChainTracer extends tracer_js_1.BaseTracer {
37
37
  (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_PROJECT") ??
38
38
  (0, env_js_1.getEnvironmentVariable)("LANGCHAIN_SESSION");
39
39
  this.exampleId = exampleId;
40
- this.client = client ?? new langchainplus_sdk_1.Client({});
40
+ this.client = client ?? new langsmith_1.Client({});
41
41
  }
42
42
  async _convertToCreate(run, example_id = undefined) {
43
43
  return {
@@ -1,5 +1,5 @@
1
- import { Client } from "langchainplus-sdk";
2
- import { BaseRun, RunUpdate as BaseRunUpdate } from "langchainplus-sdk/schemas";
1
+ import { Client } from "langsmith";
2
+ import { BaseRun, RunUpdate as BaseRunUpdate } from "langsmith/schemas";
3
3
  import { BaseTracer } from "./tracer.js";
4
4
  import { BaseCallbackHandlerInput } from "../base.js";
5
5
  export interface Run extends BaseRun {
@@ -1,4 +1,4 @@
1
- import { Client } from "langchainplus-sdk";
1
+ import { Client } from "langsmith";
2
2
  import { getEnvironmentVariable, getRuntimeEnvironment, } from "../../util/env.js";
3
3
  import { BaseTracer } from "./tracer.js";
4
4
  export class LangChainTracer extends BaseTracer {
@@ -589,6 +589,9 @@ class PromptLayerChatOpenAI extends ChatOpenAI {
589
589
  else if (message._getType() === "ai") {
590
590
  messageDict = { role: "assistant", content: message.content };
591
591
  }
592
+ else if (message._getType() === "function") {
593
+ messageDict = { role: "assistant", content: message.content };
594
+ }
592
595
  else if (message._getType() === "system") {
593
596
  messageDict = { role: "system", content: message.content };
594
597
  }
@@ -582,6 +582,9 @@ export class PromptLayerChatOpenAI extends ChatOpenAI {
582
582
  else if (message._getType() === "ai") {
583
583
  messageDict = { role: "assistant", content: message.content };
584
584
  }
585
+ else if (message._getType() === "function") {
586
+ messageDict = { role: "assistant", content: message.content };
587
+ }
585
588
  else if (message._getType() === "system") {
586
589
  messageDict = { role: "system", content: message.content };
587
590
  }
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runOnDataset = void 0;
4
- var langchainplus_js_1 = require("./langchainplus.cjs");
5
- Object.defineProperty(exports, "runOnDataset", { enumerable: true, get: function () { return langchainplus_js_1.runOnDataset; } });
4
+ var langsmith_js_1 = require("./langsmith.cjs");
5
+ Object.defineProperty(exports, "runOnDataset", { enumerable: true, get: function () { return langsmith_js_1.runOnDataset; } });
@@ -1 +1 @@
1
- export { DatasetRunResults, runOnDataset } from "./langchainplus.js";
1
+ export { DatasetRunResults, runOnDataset } from "./langsmith.js";
@@ -1 +1 @@
1
- export { runOnDataset } from "./langchainplus.js";
1
+ export { runOnDataset } from "./langsmith.js";
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runOnDataset = exports.isChain = exports.isChatModel = exports.isLLM = void 0;
7
7
  const p_queue_1 = __importDefault(require("p-queue"));
8
- const langchainplus_sdk_1 = require("langchainplus-sdk");
8
+ const langsmith_1 = require("langsmith");
9
9
  const tracer_langchain_js_1 = require("../callbacks/handlers/tracer_langchain.cjs");
10
10
  const utils_js_1 = require("../stores/message/utils.cjs");
11
11
  const stringifyError = (err) => {
@@ -86,7 +86,7 @@ const runChatModel = async (example, tracer, chatModel) => {
86
86
  const runOnDataset = async (datasetName, llmOrChainFactory, { maxConcurrency = 8, numRepetitions = 1, projectName, client, } = {}) => {
87
87
  const PQueue = "default" in p_queue_1.default ? p_queue_1.default.default : p_queue_1.default;
88
88
  const queue = new PQueue({ concurrency: maxConcurrency });
89
- const client_ = client ?? new langchainplus_sdk_1.Client({});
89
+ const client_ = client ?? new langsmith_1.Client({});
90
90
  const examples = await client_.listExamples({ datasetName });
91
91
  let projectName_;
92
92
  if (projectName === undefined) {
@@ -98,7 +98,7 @@ const runOnDataset = async (datasetName, llmOrChainFactory, { maxConcurrency = 8
98
98
  else {
99
99
  projectName_ = projectName;
100
100
  }
101
- await client_.createProject({ projectName: projectName_, mode: "eval" });
101
+ await client_.createProject({ projectName: projectName_ });
102
102
  const results = examples.reduce((acc, example) => ({ ...acc, [example.id]: [] }), {});
103
103
  const modelOrFactoryType = await getModelOrFactoryType(llmOrChainFactory);
104
104
  await Promise.all(Array.from({ length: numRepetitions })
@@ -1,4 +1,4 @@
1
- import { Client } from "langchainplus-sdk";
1
+ import { Client } from "langsmith";
2
2
  import { ChainValues, LLMResult } from "../schema/index.js";
3
3
  import { BaseLanguageModel } from "../base_language/index.js";
4
4
  import { BaseChain } from "../chains/base.js";
@@ -1,5 +1,5 @@
1
1
  import PQueueMod from "p-queue";
2
- import { Client } from "langchainplus-sdk";
2
+ import { Client } from "langsmith";
3
3
  import { LangChainTracer } from "../callbacks/handlers/tracer_langchain.js";
4
4
  import { mapStoredMessagesToChatMessages } from "../stores/message/utils.js";
5
5
  const stringifyError = (err) => {
@@ -89,7 +89,7 @@ export const runOnDataset = async (datasetName, llmOrChainFactory, { maxConcurre
89
89
  else {
90
90
  projectName_ = projectName;
91
91
  }
92
- await client_.createProject({ projectName: projectName_, mode: "eval" });
92
+ await client_.createProject({ projectName: projectName_ });
93
93
  const results = examples.reduce((acc, example) => ({ ...acc, [example.id]: [] }), {});
94
94
  const modelOrFactoryType = await getModelOrFactoryType(llmOrChainFactory);
95
95
  await Promise.all(Array.from({ length: numRepetitions })
@@ -1,5 +1,5 @@
1
- import { Example, Run } from "langchainplus-sdk";
2
- import { EvaluationResult, RunEvaluator } from "langchainplus-sdk/evaluation";
1
+ import { Example, Run } from "langsmith";
2
+ import { EvaluationResult, RunEvaluator } from "langsmith/evaluation";
3
3
  import { BaseOutputParser } from "../../schema/output_parser.js";
4
4
  import { LLMChain } from "../../chains/llm_chain.js";
5
5
  import { BaseChain } from "../../chains/base.js";
@@ -1,5 +1,5 @@
1
- import { Example, Run } from "langchainplus-sdk";
2
- import { EvaluationResult } from "langchainplus-sdk/evaluation";
1
+ import { Example, Run } from "langsmith";
2
+ import { EvaluationResult } from "langsmith/evaluation";
3
3
  import { RunEvaluatorInputMapper, RunEvaluatorChain, RunEvaluatorOutputParser } from "./base.js";
4
4
  import { PromptTemplate } from "../../prompts/prompt.js";
5
5
  import { BaseLanguageModel } from "../../base_language/index.js";
@@ -31,9 +31,16 @@ class TextSplitter extends document_js_2.BaseDocumentTransformer {
31
31
  writable: true,
32
32
  value: false
33
33
  });
34
+ Object.defineProperty(this, "lengthFunction", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: (text) => text.length
39
+ });
34
40
  this.chunkSize = fields?.chunkSize ?? this.chunkSize;
35
41
  this.chunkOverlap = fields?.chunkOverlap ?? this.chunkOverlap;
36
42
  this.keepSeparator = fields?.keepSeparator ?? this.keepSeparator;
43
+ this.lengthFunction = fields?.lengthFunction ?? ((text) => text.length);
37
44
  if (this.chunkOverlap >= this.chunkSize) {
38
45
  throw new Error("Cannot have chunkOverlap >= chunkSize");
39
46
  }
@@ -74,7 +81,7 @@ class TextSplitter extends document_js_2.BaseDocumentTransformer {
74
81
  let numberOfIntermediateNewLines = 0;
75
82
  if (prevChunk) {
76
83
  const indexChunk = text.indexOf(chunk);
77
- const indexEndPrevChunk = text.indexOf(prevChunk) + prevChunk.length;
84
+ const indexEndPrevChunk = text.indexOf(prevChunk) + this.lengthFunction(prevChunk);
78
85
  const removedNewlinesFromSplittingText = text.slice(indexEndPrevChunk, indexChunk);
79
86
  numberOfIntermediateNewLines = (removedNewlinesFromSplittingText.match(/\n/g) || []).length;
80
87
  if (appendChunkOverlapHeader) {
@@ -120,7 +127,7 @@ class TextSplitter extends document_js_2.BaseDocumentTransformer {
120
127
  const currentDoc = [];
121
128
  let total = 0;
122
129
  for (const d of splits) {
123
- const _len = d.length;
130
+ const _len = this.lengthFunction(d);
124
131
  if (total + _len + (currentDoc.length > 0 ? separator.length : 0) >
125
132
  this.chunkSize) {
126
133
  if (total > this.chunkSize) {
@@ -137,7 +144,7 @@ which is longer than the specified ${this.chunkSize}`);
137
144
  // - or if we still have any chunks and the length is long
138
145
  while (total > this.chunkOverlap ||
139
146
  (total + _len > this.chunkSize && total > 0)) {
140
- total -= currentDoc[0].length;
147
+ total -= this.lengthFunction(currentDoc[0]);
141
148
  currentDoc.shift();
142
149
  }
143
150
  }
@@ -224,7 +231,7 @@ class RecursiveCharacterTextSplitter extends TextSplitter {
224
231
  let goodSplits = [];
225
232
  const _separator = this.keepSeparator ? "" : separator;
226
233
  for (const s of splits) {
227
- if (s.length < this.chunkSize) {
234
+ if (this.lengthFunction(s) < this.chunkSize) {
228
235
  goodSplits.push(s);
229
236
  }
230
237
  else {
@@ -5,6 +5,7 @@ export interface TextSplitterParams {
5
5
  chunkSize: number;
6
6
  chunkOverlap: number;
7
7
  keepSeparator: boolean;
8
+ lengthFunction?: (text: string) => number;
8
9
  }
9
10
  export type TextSplitterChunkHeaderOptions = {
10
11
  chunkHeader?: string;
@@ -16,6 +17,7 @@ export declare abstract class TextSplitter extends BaseDocumentTransformer imple
16
17
  chunkSize: number;
17
18
  chunkOverlap: number;
18
19
  keepSeparator: boolean;
20
+ lengthFunction: (text: string) => number;
19
21
  constructor(fields?: Partial<TextSplitterParams>);
20
22
  transformDocuments(documents: Document[], chunkHeaderOptions?: TextSplitterChunkHeaderOptions): Promise<Document[]>;
21
23
  abstract splitText(text: string): Promise<string[]>;
@@ -28,9 +28,16 @@ export class TextSplitter extends BaseDocumentTransformer {
28
28
  writable: true,
29
29
  value: false
30
30
  });
31
+ Object.defineProperty(this, "lengthFunction", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: (text) => text.length
36
+ });
31
37
  this.chunkSize = fields?.chunkSize ?? this.chunkSize;
32
38
  this.chunkOverlap = fields?.chunkOverlap ?? this.chunkOverlap;
33
39
  this.keepSeparator = fields?.keepSeparator ?? this.keepSeparator;
40
+ this.lengthFunction = fields?.lengthFunction ?? ((text) => text.length);
34
41
  if (this.chunkOverlap >= this.chunkSize) {
35
42
  throw new Error("Cannot have chunkOverlap >= chunkSize");
36
43
  }
@@ -71,7 +78,7 @@ export class TextSplitter extends BaseDocumentTransformer {
71
78
  let numberOfIntermediateNewLines = 0;
72
79
  if (prevChunk) {
73
80
  const indexChunk = text.indexOf(chunk);
74
- const indexEndPrevChunk = text.indexOf(prevChunk) + prevChunk.length;
81
+ const indexEndPrevChunk = text.indexOf(prevChunk) + this.lengthFunction(prevChunk);
75
82
  const removedNewlinesFromSplittingText = text.slice(indexEndPrevChunk, indexChunk);
76
83
  numberOfIntermediateNewLines = (removedNewlinesFromSplittingText.match(/\n/g) || []).length;
77
84
  if (appendChunkOverlapHeader) {
@@ -117,7 +124,7 @@ export class TextSplitter extends BaseDocumentTransformer {
117
124
  const currentDoc = [];
118
125
  let total = 0;
119
126
  for (const d of splits) {
120
- const _len = d.length;
127
+ const _len = this.lengthFunction(d);
121
128
  if (total + _len + (currentDoc.length > 0 ? separator.length : 0) >
122
129
  this.chunkSize) {
123
130
  if (total > this.chunkSize) {
@@ -134,7 +141,7 @@ which is longer than the specified ${this.chunkSize}`);
134
141
  // - or if we still have any chunks and the length is long
135
142
  while (total > this.chunkOverlap ||
136
143
  (total + _len > this.chunkSize && total > 0)) {
137
- total -= currentDoc[0].length;
144
+ total -= this.lengthFunction(currentDoc[0]);
138
145
  currentDoc.shift();
139
146
  }
140
147
  }
@@ -219,7 +226,7 @@ export class RecursiveCharacterTextSplitter extends TextSplitter {
219
226
  let goodSplits = [];
220
227
  const _separator = this.keepSeparator ? "" : separator;
221
228
  for (const s of splits) {
222
- if (s.length < this.chunkSize) {
229
+ if (this.lengthFunction(s) < this.chunkSize) {
223
230
  goodSplits.push(s);
224
231
  }
225
232
  else {
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DataForSeoAPISearch = void 0;
4
+ const env_js_1 = require("../util/env.cjs");
5
+ const base_js_1 = require("./base.cjs");
6
+ /**
7
+ * @class DataForSeoAPISearch
8
+ * @extends {Tool}
9
+ * @description Represents a wrapper class to work with DataForSEO SERP API.
10
+ */
11
+ class DataForSeoAPISearch extends base_js_1.Tool {
12
+ /**
13
+ * @constructor
14
+ * @param {DataForSeoApiConfig} config
15
+ * @description Sets up the class, throws an error if the API login/password isn't provided.
16
+ */
17
+ constructor(config = {}) {
18
+ super();
19
+ Object.defineProperty(this, "name", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: "dataforseo-api-wrapper"
24
+ });
25
+ Object.defineProperty(this, "description", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: "A robust Google Search API provided by DataForSeo. This tool is handy when you need information about trending topics or current events."
30
+ });
31
+ Object.defineProperty(this, "apiLogin", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ Object.defineProperty(this, "apiPassword", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: void 0
42
+ });
43
+ /**
44
+ * @property defaultParams
45
+ * @type {Record<string, string | number | boolean>}
46
+ * @description These are the default parameters to be used when making an API request.
47
+ */
48
+ Object.defineProperty(this, "defaultParams", {
49
+ enumerable: true,
50
+ configurable: true,
51
+ writable: true,
52
+ value: {
53
+ location_name: "United States",
54
+ language_code: "en",
55
+ depth: 10,
56
+ se_name: "google",
57
+ se_type: "organic",
58
+ }
59
+ });
60
+ Object.defineProperty(this, "params", {
61
+ enumerable: true,
62
+ configurable: true,
63
+ writable: true,
64
+ value: {}
65
+ });
66
+ Object.defineProperty(this, "jsonResultTypes", {
67
+ enumerable: true,
68
+ configurable: true,
69
+ writable: true,
70
+ value: void 0
71
+ });
72
+ Object.defineProperty(this, "jsonResultFields", {
73
+ enumerable: true,
74
+ configurable: true,
75
+ writable: true,
76
+ value: void 0
77
+ });
78
+ Object.defineProperty(this, "topCount", {
79
+ enumerable: true,
80
+ configurable: true,
81
+ writable: true,
82
+ value: void 0
83
+ });
84
+ Object.defineProperty(this, "useJsonOutput", {
85
+ enumerable: true,
86
+ configurable: true,
87
+ writable: true,
88
+ value: false
89
+ });
90
+ const apiLogin = config.apiLogin ?? (0, env_js_1.getEnvironmentVariable)("DATAFORSEO_LOGIN");
91
+ const apiPassword = config.apiPassword ?? (0, env_js_1.getEnvironmentVariable)("DATAFORSEO_PASSWORD");
92
+ const params = config.params ?? {};
93
+ if (!apiLogin || !apiPassword) {
94
+ throw new Error("DataForSEO login or password not set. You can set it as DATAFORSEO_LOGIN and DATAFORSEO_PASSWORD in your .env file, or pass it to DataForSeoAPISearch.");
95
+ }
96
+ this.params = { ...this.defaultParams, ...params };
97
+ this.apiLogin = apiLogin;
98
+ this.apiPassword = apiPassword;
99
+ this.jsonResultTypes = config.jsonResultTypes;
100
+ this.jsonResultFields = config.jsonResultFields;
101
+ this.useJsonOutput = config.useJsonOutput ?? false;
102
+ this.topCount = config.topCount;
103
+ }
104
+ /**
105
+ * @method _call
106
+ * @param {string} keyword
107
+ * @returns {Promise<string>}
108
+ * @description Initiates a call to the API and processes the response.
109
+ */
110
+ async _call(keyword) {
111
+ return this.useJsonOutput
112
+ ? JSON.stringify(await this.results(keyword))
113
+ : this.processResponse(await this.getResponseJson(keyword));
114
+ }
115
+ /**
116
+ * @method results
117
+ * @param {string} keyword
118
+ * @returns {Promise<Array<any>>}
119
+ * @description Fetches the results from the API for the given keyword.
120
+ */
121
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
+ async results(keyword) {
123
+ const res = await this.getResponseJson(keyword);
124
+ return this.filterResults(res, this.jsonResultTypes);
125
+ }
126
+ /**
127
+ * @method prepareRequest
128
+ * @param {string} keyword
129
+ * @returns {{url: string; headers: HeadersInit; data: BodyInit}}
130
+ * @description Prepares the request details for the API call.
131
+ */
132
+ prepareRequest(keyword) {
133
+ if (this.apiLogin === undefined || this.apiPassword === undefined) {
134
+ throw new Error("api_login or api_password is not provided");
135
+ }
136
+ const credentials = Buffer.from(`${this.apiLogin}:${this.apiPassword}`, "utf-8").toString("base64");
137
+ const headers = {
138
+ Authorization: `Basic ${credentials}`,
139
+ "Content-Type": "application/json",
140
+ };
141
+ const params = { ...this.params };
142
+ params.keyword ??= keyword;
143
+ const data = [params];
144
+ return {
145
+ url: `https://api.dataforseo.com/v3/serp/${params.se_name}/${params.se_type}/live/advanced`,
146
+ headers,
147
+ data: JSON.stringify(data),
148
+ };
149
+ }
150
+ /**
151
+ * @method getResponseJson
152
+ * @param {string} keyword
153
+ * @returns {Promise<ApiResponse>}
154
+ * @description Executes a POST request to the provided URL and returns a parsed JSON response.
155
+ */
156
+ async getResponseJson(keyword) {
157
+ const requestDetails = this.prepareRequest(keyword);
158
+ const response = await fetch(requestDetails.url, {
159
+ method: "POST",
160
+ headers: requestDetails.headers,
161
+ body: requestDetails.data,
162
+ });
163
+ if (!response.ok) {
164
+ throw new Error(`Got ${response.status} error from DataForSEO: ${response.statusText}`);
165
+ }
166
+ const result = await response.json();
167
+ return this.checkResponse(result);
168
+ }
169
+ /**
170
+ * @method checkResponse
171
+ * @param {ApiResponse} response
172
+ * @returns {ApiResponse}
173
+ * @description Checks the response status code.
174
+ */
175
+ checkResponse(response) {
176
+ if (response.status_code !== 20000) {
177
+ throw new Error(`Got error from DataForSEO SERP API: ${response.status_message}`);
178
+ }
179
+ for (const task of response.tasks) {
180
+ if (task.status_code !== 20000) {
181
+ throw new Error(`Got error from DataForSEO SERP API: ${task.status_message}`);
182
+ }
183
+ }
184
+ return response;
185
+ }
186
+ /* eslint-disable @typescript-eslint/no-explicit-any */
187
+ /**
188
+ * @method filterResults
189
+ * @param {ApiResponse} res
190
+ * @param {Array<string> | undefined} types
191
+ * @returns {Array<any>}
192
+ * @description Filters the results based on the specified result types.
193
+ */
194
+ filterResults(res, types) {
195
+ const output = [];
196
+ for (const task of res.tasks || []) {
197
+ for (const result of task.result || []) {
198
+ for (const item of result.items || []) {
199
+ if (types === undefined ||
200
+ types.length === 0 ||
201
+ types.includes(item.type)) {
202
+ const newItem = this.cleanupUnnecessaryItems(item);
203
+ if (Object.keys(newItem).length !== 0) {
204
+ output.push(newItem);
205
+ }
206
+ }
207
+ if (this.topCount !== undefined && output.length >= this.topCount) {
208
+ break;
209
+ }
210
+ }
211
+ }
212
+ }
213
+ return output;
214
+ }
215
+ /* eslint-disable @typescript-eslint/no-explicit-any */
216
+ /* eslint-disable no-param-reassign */
217
+ /**
218
+ * @method cleanupUnnecessaryItems
219
+ * @param {any} d
220
+ * @description Removes unnecessary items from the response.
221
+ */
222
+ cleanupUnnecessaryItems(d) {
223
+ if (Array.isArray(d)) {
224
+ return d.map((item) => this.cleanupUnnecessaryItems(item));
225
+ }
226
+ const toRemove = ["xpath", "position", "rectangle"];
227
+ if (typeof d === "object" && d !== null) {
228
+ return Object.keys(d).reduce((newObj, key) => {
229
+ if ((this.jsonResultFields === undefined ||
230
+ this.jsonResultFields.includes(key)) &&
231
+ !toRemove.includes(key)) {
232
+ if (typeof d[key] === "object" && d[key] !== null) {
233
+ newObj[key] = this.cleanupUnnecessaryItems(d[key]);
234
+ }
235
+ else {
236
+ newObj[key] = d[key];
237
+ }
238
+ }
239
+ return newObj;
240
+ }, {});
241
+ }
242
+ return d;
243
+ }
244
+ /**
245
+ * @method processResponse
246
+ * @param {ApiResponse} res
247
+ * @returns {string}
248
+ * @description Processes the response to extract meaningful data.
249
+ */
250
+ processResponse(res) {
251
+ let returnValue = "No good search result found";
252
+ for (const task of res.tasks || []) {
253
+ for (const result of task.result || []) {
254
+ const { item_types } = result;
255
+ const items = result.items || [];
256
+ if (item_types.includes("answer_box")) {
257
+ returnValue = items.find((item) => item.type === "answer_box").text;
258
+ }
259
+ else if (item_types.includes("knowledge_graph")) {
260
+ returnValue = items.find((item) => item.type === "knowledge_graph").description;
261
+ }
262
+ else if (item_types.includes("featured_snippet")) {
263
+ returnValue = items.find((item) => item.type === "featured_snippet").description;
264
+ }
265
+ else if (item_types.includes("shopping")) {
266
+ returnValue = items.find((item) => item.type === "shopping").price;
267
+ }
268
+ else if (item_types.includes("organic")) {
269
+ returnValue = items.find((item) => item.type === "organic").description;
270
+ }
271
+ if (returnValue) {
272
+ break;
273
+ }
274
+ }
275
+ }
276
+ return returnValue;
277
+ }
278
+ }
279
+ exports.DataForSeoAPISearch = DataForSeoAPISearch;