{"version":3,"file":"google_trends.cjs","names":["Tool"],"sources":["../../src/tools/google_trends.ts"],"sourcesContent":["import { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { Tool } from \"@langchain/core/tools\";\n\n/**\n * Interfaces for the response from the SerpApi Google Trends API.\n */\ninterface TimelineValue {\n  query: string;\n  value: string;\n  extracted_value: number;\n}\n\ninterface TimelineData {\n  date: string;\n  timestamp: string;\n  values: TimelineValue[];\n}\n\n/**\n * Interface for parameters required by SERPGoogleTrendsTool class.\n */\nexport interface SERPGoogleTrendsToolParams {\n  apiKey?: string;\n}\n\n/**\n * Tool that queries the Google Trends API. Uses default interest over time.\n */\nexport class SERPGoogleTrendsTool extends Tool {\n  static lc_name() {\n    return \"SERPGoogleTrendsTool\";\n  }\n\n  get lc_secrets(): { [key: string]: string } | undefined {\n    return {\n      apiKey: \"SERPAPI_API_KEY\",\n    };\n  }\n\n  name = \"google_trends\";\n\n  protected apiKey: string;\n\n  description = `A wrapper around Google Trends API. Useful for analyzing and retrieving trending search data based on keywords, \n    categories, or regions. Input should be a search query or specific parameters for trends analysis.`;\n\n  constructor(fields?: SERPGoogleTrendsToolParams) {\n    super(...arguments);\n    const apiKey = fields?.apiKey ?? getEnvironmentVariable(\"SERPAPI_API_KEY\");\n    if (apiKey === undefined) {\n      throw new Error(\n        `Google Trends API key not set. You can set it as \"SERPAPI_API_KEY\" in your environment variables.`\n      );\n    }\n    this.apiKey = apiKey;\n  }\n\n  async _call(query: string): Promise<string> {\n    /**\n     * Related queries only accepts one at a time, and multiple\n     * queries at once on interest over time (default) is effectively the same as\n     * each query one by one.\n     *\n     * SerpApi caches queries, so the first time will be slower\n     * and subsequent identical queries will be very fast.\n     */\n    if (query.split(\",\").length > 1) {\n      throw new Error(\"Please do one query at a time\");\n    }\n    const serpapiApiKey = this.apiKey;\n    const params = new URLSearchParams({\n      engine: \"google_trends\",\n      api_key: serpapiApiKey,\n      q: query,\n    });\n\n    const res = await fetch(\n      `https://serpapi.com/search.json?${params.toString()}`,\n      {\n        method: \"GET\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n      }\n    );\n\n    if (!res.ok) {\n      throw new Error(`Error fetching data from SerpAPI: ${res.statusText}`);\n    }\n\n    const clientDict = await res.json();\n    const totalResults = clientDict.interest_over_time?.timeline_data ?? [];\n\n    if (totalResults.length === 0) {\n      return \"No good Trend Result was found\";\n    }\n\n    const startDate = totalResults[0].date.split(\" \");\n    const endDate = totalResults[totalResults.length - 1].date.split(\" \");\n    const values = totalResults.map(\n      (result: TimelineData) => result.values[0].extracted_value\n    );\n    const minValue = Math.min(...values);\n    const maxValue = Math.max(...values);\n    const avgValue =\n      values.reduce((a: number, b: number) => a + b, 0) / values.length;\n    const percentageChange =\n      ((values[values.length - 1] - values[0]) / (values[0] || 1)) * 100;\n\n    const relatedParams = new URLSearchParams({\n      engine: \"google_trends\",\n      api_key: serpapiApiKey,\n      data_type: \"RELATED_QUERIES\",\n      q: query,\n    });\n\n    const relatedRes = await fetch(\n      `https://serpapi.com/search.json?${relatedParams.toString()}`,\n      {\n        method: \"GET\",\n        headers: {\n          \"Content-Type\": \"application/json\",\n        },\n      }\n    );\n\n    let rising = [];\n    let top = [];\n    if (!relatedRes.ok) {\n      // Sometimes related queries from SerpAPI will fail, but interest over time will be fine\n      console.error(\n        `Error fetching related queries from SerpAPI: ${relatedRes.statusText}`\n      );\n    } else {\n      const relatedDict = await relatedRes.json();\n      rising =\n        relatedDict.related_queries?.rising?.map(\n          (result: { query: string }) => result.query\n        ) ?? [];\n      top =\n        relatedDict.related_queries?.top?.map(\n          (result: { query: string }) => result.query\n        ) ?? [];\n    }\n\n    const doc = [\n      `Query: ${query}`,\n      `Date From: ${startDate[0]} ${startDate[1]}, ${startDate[2]}`,\n      `Date To: ${endDate[0]} ${endDate[1]} ${endDate[2]}`,\n      `Min Value: ${minValue}`,\n      `Max Value: ${maxValue}`,\n      `Average Value: ${avgValue}`,\n      `Percent Change: ${percentageChange.toFixed(2)}%`,\n      `Trend values: ${values.join(\", \")}`,\n      `Rising Related Queries: ${rising.join(\", \")}`,\n      `Top Related Queries: ${top.join(\", \")}`,\n    ];\n\n    return doc.join(\"\\n\\n\");\n  }\n}\n"],"mappings":";;;;;;;;;AA4BA,IAAa,uBAAb,cAA0CA,sBAAAA,KAAK;CAC7C,OAAO,UAAU;AACf,SAAO;;CAGT,IAAI,aAAoD;AACtD,SAAO,EACL,QAAQ,mBACT;;CAGH,OAAO;CAEP;CAEA,cAAc;;CAGd,YAAY,QAAqC;AAC/C,QAAM,GAAG,UAAU;EACnB,MAAM,SAAS,QAAQ,WAAA,GAAA,0BAAA,wBAAiC,kBAAkB;AAC1E,MAAI,WAAW,KAAA,EACb,OAAM,IAAI,MACR,oGACD;AAEH,OAAK,SAAS;;CAGhB,MAAM,MAAM,OAAgC;;;;;;;;;AAS1C,MAAI,MAAM,MAAM,IAAI,CAAC,SAAS,EAC5B,OAAM,IAAI,MAAM,gCAAgC;EAElD,MAAM,gBAAgB,KAAK;EAC3B,MAAM,SAAS,IAAI,gBAAgB;GACjC,QAAQ;GACR,SAAS;GACT,GAAG;GACJ,CAAC;EAEF,MAAM,MAAM,MAAM,MAChB,mCAAmC,OAAO,UAAU,IACpD;GACE,QAAQ;GACR,SAAS,EACP,gBAAgB,oBACjB;GACF,CACF;AAED,MAAI,CAAC,IAAI,GACP,OAAM,IAAI,MAAM,qCAAqC,IAAI,aAAa;EAIxE,MAAM,gBADa,MAAM,IAAI,MAAM,EACH,oBAAoB,iBAAiB,EAAE;AAEvE,MAAI,aAAa,WAAW,EAC1B,QAAO;EAGT,MAAM,YAAY,aAAa,GAAG,KAAK,MAAM,IAAI;EACjD,MAAM,UAAU,aAAa,aAAa,SAAS,GAAG,KAAK,MAAM,IAAI;EACrE,MAAM,SAAS,aAAa,KACzB,WAAyB,OAAO,OAAO,GAAG,gBAC5C;EACD,MAAM,WAAW,KAAK,IAAI,GAAG,OAAO;EACpC,MAAM,WAAW,KAAK,IAAI,GAAG,OAAO;EACpC,MAAM,WACJ,OAAO,QAAQ,GAAW,MAAc,IAAI,GAAG,EAAE,GAAG,OAAO;EAC7D,MAAM,oBACF,OAAO,OAAO,SAAS,KAAK,OAAO,OAAO,OAAO,MAAM,KAAM;EAEjE,MAAM,gBAAgB,IAAI,gBAAgB;GACxC,QAAQ;GACR,SAAS;GACT,WAAW;GACX,GAAG;GACJ,CAAC;EAEF,MAAM,aAAa,MAAM,MACvB,mCAAmC,cAAc,UAAU,IAC3D;GACE,QAAQ;GACR,SAAS,EACP,gBAAgB,oBACjB;GACF,CACF;EAED,IAAI,SAAS,EAAE;EACf,IAAI,MAAM,EAAE;AACZ,MAAI,CAAC,WAAW,GAEd,SAAQ,MACN,gDAAgD,WAAW,aAC5D;OACI;GACL,MAAM,cAAc,MAAM,WAAW,MAAM;AAC3C,YACE,YAAY,iBAAiB,QAAQ,KAClC,WAA8B,OAAO,MACvC,IAAI,EAAE;AACT,SACE,YAAY,iBAAiB,KAAK,KAC/B,WAA8B,OAAO,MACvC,IAAI,EAAE;;AAgBX,SAbY;GACV,UAAU;GACV,cAAc,UAAU,GAAG,GAAG,UAAU,GAAG,IAAI,UAAU;GACzD,YAAY,QAAQ,GAAG,GAAG,QAAQ,GAAG,GAAG,QAAQ;GAChD,cAAc;GACd,cAAc;GACd,kBAAkB;GAClB,mBAAmB,iBAAiB,QAAQ,EAAE,CAAC;GAC/C,iBAAiB,OAAO,KAAK,KAAK;GAClC,2BAA2B,OAAO,KAAK,KAAK;GAC5C,wBAAwB,IAAI,KAAK,KAAK;GACvC,CAEU,KAAK,OAAO"}