{"version":3,"sources":["../../../src/tools/database/elasticsearch.ts"],"names":["ElasticSearchAction","ListIndices","GetIndexDetails","Search","ElasticSearchTool","Tool","name","description","inputSchema","z","object","action","nativeEnum","describe","indexName","string","optional","query","start","coerce","number","int","min","default","size","max","emitter","Emitter","root","child","namespace","creator","validateInput","schema","input","ToolInputValidationError","register","options","connection","cloud","node","nodes","ValidationError","message","propertyName","client","Client","info","error","ToolError","isRetryable","isFatal","_run","_options","run","indices","listIndices","signal","JSONToolOutput","indexDetails","getIndexDetails","response","search","aggregations","hits","map","hit","_source","cat","expand_wildcards","h","format","filter","record","index","startsWith","getMapping","parsedQuery","parseBrokenJson","searchBody","from","body"],"mappings":"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","file":"elasticsearch.cjs","sourcesContent":["/**\n * Copyright 2025 © BeeAI a Series of LF Projects, LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport {\n  Tool,\n  ToolInput,\n  ToolError,\n  BaseToolOptions,\n  BaseToolRunOptions,\n  JSONToolOutput,\n  ToolInputValidationError,\n  ToolEmitter,\n} from \"@/tools/base.js\";\nimport { Cache } from \"@/cache/decoratorCache.js\";\nimport { RunContext } from \"@/context.js\";\nimport { z } from \"zod\";\nimport { ValidationError } from \"ajv\";\nimport { AnyToolSchemaLike } from \"@/internals/helpers/schema.js\";\nimport { parseBrokenJson } from \"@/internals/helpers/schema.js\";\nimport { Client, ClientOptions, estypes as ESTypes } from \"@elastic/elasticsearch\";\nimport { Emitter } from \"@/emitter/emitter.js\";\n\nexport interface ElasticSearchToolOptions extends BaseToolOptions {\n  connection: ClientOptions;\n}\n\nexport type ElasticSearchToolResult =\n  | ESTypes.CatIndicesResponse\n  | ESTypes.IndicesGetMappingResponse\n  | ESTypes.SearchResponse;\n\nexport const ElasticSearchAction = {\n  ListIndices: \"LIST_INDICES\",\n  GetIndexDetails: \"GET_INDEX_DETAILS\",\n  Search: \"SEARCH\",\n} as const;\n\nexport class ElasticSearchTool extends Tool<\n  JSONToolOutput<ElasticSearchToolResult>,\n  ElasticSearchToolOptions\n> {\n  name = \"ElasticSearchTool\";\n\n  description = `Can query data from an ElasticSearch database. IMPORTANT: strictly follow this order of actions:\n   1. ${ElasticSearchAction.ListIndices} - retrieve a list of available indices\n   2. ${ElasticSearchAction.GetIndexDetails} - get details of index fields\n   3. ${ElasticSearchAction.Search} - perform search or aggregation query on a specific index or pass the original user query without modifications if it's a valid JSON ElasticSearch query after identifying the index`;\n\n  inputSchema() {\n    return z.object({\n      action: z\n        .nativeEnum(ElasticSearchAction)\n        .describe(\n          `The action to perform. ${ElasticSearchAction.ListIndices} lists all indices, ${ElasticSearchAction.GetIndexDetails} fetches details for a specified index, and ${ElasticSearchAction.Search} executes a search or aggregation query`,\n        ),\n      indexName: z\n        .string()\n        .optional()\n        .describe(\n          `The name of the index to query, required for ${ElasticSearchAction.GetIndexDetails} and ${ElasticSearchAction.Search}`,\n        ),\n      query: z\n        .string()\n        .optional()\n        .describe(\n          `Valid ElasticSearch JSON search or aggregation query for ${ElasticSearchAction.Search} action`,\n        ),\n      start: z.coerce\n        .number()\n        .int()\n        .min(0)\n        .default(0)\n        .optional()\n        .describe(\n          \"The record index from which the query will start. Increase by the size of the query to get the next page of results\",\n        ),\n      size: z.coerce\n        .number()\n        .int()\n        .min(0)\n        .max(10)\n        .default(10)\n        .optional()\n        .describe(\"How many records will be retrieved from the ElasticSearch query. Maximum is 10\"),\n    });\n  }\n\n  public readonly emitter: ToolEmitter<ToolInput<this>, JSONToolOutput<ElasticSearchToolResult>> =\n    Emitter.root.child({\n      namespace: [\"tool\", \"database\", \"elasticsearch\"],\n      creator: this,\n    });\n\n  protected validateInput(\n    schema: AnyToolSchemaLike,\n    input: unknown,\n  ): asserts input is ToolInput<this> {\n    super.validateInput(schema, input);\n    if (input.action === ElasticSearchAction.GetIndexDetails && !input.indexName) {\n      throw new ToolInputValidationError(\n        `Index name is required for ${ElasticSearchAction.GetIndexDetails} action.`,\n      );\n    }\n    if (input.action === ElasticSearchAction.Search && (!input.indexName || !input.query)) {\n      throw new ToolInputValidationError(\n        `Both index name and query are required for ${ElasticSearchAction.Search} action.`,\n      );\n    }\n  }\n\n  static {\n    this.register();\n  }\n\n  public constructor(options: ElasticSearchToolOptions) {\n    super(options);\n    if (!options.connection.cloud && !options.connection.node && !options.connection.nodes) {\n      throw new ValidationError([\n        {\n          message: \"At least one of the properties must be provided\",\n          propertyName: \"connection.cloud, connection.node, connection.nodes\",\n        },\n      ]);\n    }\n  }\n\n  @Cache()\n  protected async client(): Promise<Client> {\n    try {\n      const client = new Client(this.options.connection);\n      await client.info();\n      return client;\n    } catch (error) {\n      throw new ToolError(`Unable to connect to ElasticSearch.`, [error], {\n        isRetryable: false,\n        isFatal: true,\n      });\n    }\n  }\n\n  protected async _run(\n    input: ToolInput<this>,\n    _options: Partial<BaseToolRunOptions>,\n    run: RunContext<this>,\n  ): Promise<JSONToolOutput<any>> {\n    if (input.action === ElasticSearchAction.ListIndices) {\n      const indices = await this.listIndices(run.signal);\n      return new JSONToolOutput(indices);\n    } else if (input.action === ElasticSearchAction.GetIndexDetails) {\n      const indexDetails = await this.getIndexDetails(input, run.signal);\n      return new JSONToolOutput(indexDetails);\n    } else if (input.action === ElasticSearchAction.Search) {\n      const response = await this.search(input, run.signal);\n      if (response.aggregations) {\n        return new JSONToolOutput(response.aggregations);\n      } else {\n        return new JSONToolOutput(response.hits.hits.map((hit: ESTypes.SearchHit) => hit._source));\n      }\n    } else {\n      throw new ToolError(`Invalid action specified: ${input.action}`);\n    }\n  }\n\n  protected async listIndices(signal?: AbortSignal): Promise<ESTypes.CatIndicesResponse> {\n    const client = await this.client();\n    const response = await client.cat.indices(\n      {\n        expand_wildcards: \"open\",\n        h: \"index\",\n        format: \"json\",\n      },\n      { signal: signal },\n    );\n    return response\n      .filter((record) => record.index && !record.index.startsWith(\".\")) // Exclude system indices\n      .map((record) => ({ index: record.index }));\n  }\n\n  protected async getIndexDetails(\n    input: ToolInput<this>,\n    signal: AbortSignal,\n  ): Promise<ESTypes.IndicesGetMappingResponse> {\n    const client = await this.client();\n    return await client.indices.getMapping(\n      {\n        index: input.indexName,\n      },\n      { signal: signal },\n    );\n  }\n\n  protected async search(\n    input: ToolInput<this>,\n    signal: AbortSignal,\n  ): Promise<ESTypes.SearchResponse> {\n    const parsedQuery = parseBrokenJson(input.query);\n    const searchBody: ESTypes.SearchRequest = {\n      ...parsedQuery,\n      from: parsedQuery.from || input.start,\n      size: parsedQuery.size || input.size,\n    };\n    const client = await this.client();\n    return await client.search(\n      {\n        index: input.indexName,\n        body: searchBody,\n      },\n      { signal: signal },\n    );\n  }\n}\n"]}