{"version":3,"file":"stackexchange.cjs","names":["Tool","params: StackExchangeAPIParams","query: string","results: string[]","endpoint: string","params: StackExchangeOptions","endpointUrl: string"],"sources":["../../src/tools/stackexchange.ts"],"sourcesContent":["import { Tool } from \"@langchain/core/tools\";\n\nexport interface StackExchangeAnswer {\n  items: StackExchangeItem[];\n  has_more: boolean;\n  quota_max: number;\n  quota_remaining: number;\n}\n\nexport interface StackExchangeItem {\n  tags: string[];\n  question_score: number;\n  is_accepted: boolean;\n  has_accepted_answer?: boolean;\n  answer_count?: number;\n  is_answered: boolean;\n  question_id: number;\n  item_type: string;\n  score: number;\n  last_activity_date: number;\n  creation_date: number;\n  body: string;\n  excerpt: string;\n  title: string;\n  answer_id?: number;\n}\n\ntype StackExchangeOptions = Record<string, string | number | boolean>;\n\nexport interface StackExchangeAPIParams {\n  /**\n   * The maximum number of results to return from the search.\n   * Limiting to 10 to avoid context overload.\n   * @default 3\n   */\n  maxResult?: number;\n  /**\n   * Which part of StackOverflows items to match against. One of 'all', 'title',\n   * 'body'.\n   * @default \"all\"\n   */\n  queryType?: \"all\" | \"title\" | \"body\";\n  /**\n   * Additional params to pass to the StackExchange API\n   */\n  options?: StackExchangeOptions;\n  /**\n   * Separator between question,answer pairs.\n   * @default \"\\n\\n\"\n   */\n  resultSeparator?: string;\n}\n\n/**\n * Class for interacting with the StackExchange API\n * It extends the base Tool class to perform retrieval.\n */\nexport class StackExchangeAPI extends Tool {\n  name = \"stackexchange\";\n\n  description = \"Stack Exchange API Implementation\";\n\n  private pageSize: number;\n\n  private maxResult = 3;\n\n  private key: string | null;\n\n  private accessToken: string | null;\n\n  private site = \"stackoverflow\";\n\n  private version = \"2.3\";\n\n  private baseUrl = \"https://api.stackexchange.com\";\n\n  private queryType = \"all\";\n\n  private options?: StackExchangeOptions = {};\n\n  private resultSeparator?: string = \"\\n\\n\";\n\n  constructor(params: StackExchangeAPIParams = {}) {\n    const { maxResult, queryType = \"all\", options, resultSeparator } = params;\n    super();\n    this.maxResult = maxResult || this.maxResult;\n    this.pageSize = 100;\n    this.baseUrl = `${this.baseUrl}/${this.version}/`;\n    this.queryType = queryType === \"all\" ? \"q\" : queryType;\n    this.options = options || this.options;\n    this.resultSeparator = resultSeparator || this.resultSeparator;\n  }\n\n  async _call(query: string): Promise<string> {\n    const params = {\n      [this.queryType]: query,\n      site: this.site,\n      ...this.options,\n    };\n    const output = await this._fetch<StackExchangeAnswer>(\n      \"search/excerpts\",\n      params\n    );\n    if (output.items.length < 1) {\n      return `No relevant results found for '${query}' on Stack Overflow.`;\n    }\n    const questions = output.items\n      .filter((item) => item.item_type === \"question\")\n      .slice(0, this.maxResult);\n    const answers = output.items.filter((item) => item.item_type === \"answer\");\n\n    const results: string[] = [];\n\n    for (const question of questions) {\n      let res_text = `Question: ${question.title}\\n${question.excerpt}`;\n\n      const relevant_answers = answers.filter(\n        (answer) => answer.question_id === question.question_id\n      );\n      const accepted_answers = relevant_answers.filter(\n        (answer) => answer.is_accepted\n      );\n\n      if (relevant_answers.length > 0) {\n        const top_answer =\n          accepted_answers.length > 0\n            ? accepted_answers[0]\n            : relevant_answers[0];\n        const { excerpt } = top_answer;\n        res_text += `\\nAnswer: ${excerpt}`;\n      }\n\n      results.push(res_text);\n    }\n\n    return results.join(this.resultSeparator);\n  }\n\n  /**\n   * Call the StackExchange API\n   * @param endpoint Name of the endpoint from StackExchange API\n   * @param params Additional parameters passed to the endpoint\n   * @param page Number of the page to retrieve\n   * @param filter Filtering properties\n   */\n  private async _fetch<T>(\n    endpoint: string,\n    params: StackExchangeOptions = {},\n    page = 1,\n    filter = \"default\"\n  ): Promise<T> {\n    try {\n      if (!endpoint) {\n        throw new Error(\"No end point provided.\");\n      }\n      const queryParams = new URLSearchParams({\n        pagesize: this.pageSize.toString(),\n        page: page.toString(),\n        filter,\n        ...params,\n      });\n\n      if (this.key) {\n        queryParams.append(\"key\", this.key);\n      }\n      if (this.accessToken) {\n        queryParams.append(\"access_token\", this.accessToken);\n      }\n\n      const queryParamsString = queryParams.toString();\n\n      const endpointUrl = `${this.baseUrl}${endpoint}?${queryParamsString}`;\n      return await this._makeRequest(endpointUrl);\n    } catch {\n      throw new Error(\"Error while calling Stack Exchange API\");\n    }\n  }\n\n  /**\n   * Fetch the result of a specific endpoint\n   * @param endpointUrl Endpoint to call\n   */\n  private async _makeRequest<T>(endpointUrl: string): Promise<T> {\n    try {\n      const response = await fetch(endpointUrl);\n      if (response.status !== 200) {\n        throw new Error(`HTTP Error: ${response.statusText}`);\n      }\n      return await response.json();\n    } catch {\n      throw new Error(`Error while calling Stack Exchange API: ${endpointUrl}`);\n    }\n  }\n}\n"],"mappings":";;;;;;;;;;AAyDA,IAAa,mBAAb,cAAsCA,4BAAK;CACzC,OAAO;CAEP,cAAc;CAEd,AAAQ;CAER,AAAQ,YAAY;CAEpB,AAAQ;CAER,AAAQ;CAER,AAAQ,OAAO;CAEf,AAAQ,UAAU;CAElB,AAAQ,UAAU;CAElB,AAAQ,YAAY;CAEpB,AAAQ,UAAiC,CAAE;CAE3C,AAAQ,kBAA2B;CAEnC,YAAYC,SAAiC,CAAE,GAAE;EAC/C,MAAM,EAAE,WAAW,YAAY,OAAO,SAAS,iBAAiB,GAAG;EACnE,OAAO;EACP,KAAK,YAAY,aAAa,KAAK;EACnC,KAAK,WAAW;EAChB,KAAK,UAAU,GAAG,KAAK,QAAQ,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;EACjD,KAAK,YAAY,cAAc,QAAQ,MAAM;EAC7C,KAAK,UAAU,WAAW,KAAK;EAC/B,KAAK,kBAAkB,mBAAmB,KAAK;CAChD;CAED,MAAM,MAAMC,OAAgC;EAC1C,MAAM,SAAS;IACZ,KAAK,YAAY;GAClB,MAAM,KAAK;GACX,GAAG,KAAK;EACT;EACD,MAAM,SAAS,MAAM,KAAK,OACxB,mBACA,OACD;AACD,MAAI,OAAO,MAAM,SAAS,EACxB,QAAO,CAAC,+BAA+B,EAAE,MAAM,oBAAoB,CAAC;EAEtE,MAAM,YAAY,OAAO,MACtB,OAAO,CAAC,SAAS,KAAK,cAAc,WAAW,CAC/C,MAAM,GAAG,KAAK,UAAU;EAC3B,MAAM,UAAU,OAAO,MAAM,OAAO,CAAC,SAAS,KAAK,cAAc,SAAS;EAE1E,MAAMC,UAAoB,CAAE;AAE5B,OAAK,MAAM,YAAY,WAAW;GAChC,IAAI,WAAW,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,SAAS;GAEjE,MAAM,mBAAmB,QAAQ,OAC/B,CAAC,WAAW,OAAO,gBAAgB,SAAS,YAC7C;GACD,MAAM,mBAAmB,iBAAiB,OACxC,CAAC,WAAW,OAAO,YACpB;AAED,OAAI,iBAAiB,SAAS,GAAG;IAC/B,MAAM,aACJ,iBAAiB,SAAS,IACtB,iBAAiB,KACjB,iBAAiB;IACvB,MAAM,EAAE,SAAS,GAAG;IACpB,YAAY,CAAC,UAAU,EAAE,SAAS;GACnC;GAED,QAAQ,KAAK,SAAS;EACvB;AAED,SAAO,QAAQ,KAAK,KAAK,gBAAgB;CAC1C;;;;;;;;CASD,MAAc,OACZC,UACAC,SAA+B,CAAE,GACjC,OAAO,GACP,SAAS,WACG;AACZ,MAAI;AACF,OAAI,CAAC,SACH,OAAM,IAAI,MAAM;GAElB,MAAM,cAAc,IAAI,gBAAgB;IACtC,UAAU,KAAK,SAAS,UAAU;IAClC,MAAM,KAAK,UAAU;IACrB;IACA,GAAG;GACJ;AAED,OAAI,KAAK,KACP,YAAY,OAAO,OAAO,KAAK,IAAI;AAErC,OAAI,KAAK,aACP,YAAY,OAAO,gBAAgB,KAAK,YAAY;GAGtD,MAAM,oBAAoB,YAAY,UAAU;GAEhD,MAAM,cAAc,GAAG,KAAK,UAAU,SAAS,CAAC,EAAE,mBAAmB;AACrE,UAAO,MAAM,KAAK,aAAa,YAAY;EAC5C,QAAO;AACN,SAAM,IAAI,MAAM;EACjB;CACF;;;;;CAMD,MAAc,aAAgBC,aAAiC;AAC7D,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,YAAY;AACzC,OAAI,SAAS,WAAW,IACtB,OAAM,IAAI,MAAM,CAAC,YAAY,EAAE,SAAS,YAAY;AAEtD,UAAO,MAAM,SAAS,MAAM;EAC7B,QAAO;AACN,SAAM,IAAI,MAAM,CAAC,wCAAwC,EAAE,aAAa;EACzE;CACF;AACF"}