@mastra/elasticsearch 1.3.1 → 1.4.0
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.
- package/CHANGELOG.md +22 -0
- package/dist/docs/SKILL.md +4 -3
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/integrations-databases-elasticsearch.md +156 -0
- package/dist/docs/references/{docs-rag-vector-databases.md → reference-rag-vector-databases.md} +46 -5
- package/dist/index.cjs +1643 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +273 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +273 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1618 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["ElasticSearchClient","packageJson.version","operationIndex"],"sources":["../package.json","../src/vector/filter.ts","../src/vector/index.ts"],"sourcesContent":["","import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype ElasticSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype ElasticSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype ElasticSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type ElasticSearchVectorFilter = VectorFilter<\n keyof ElasticSearchOperatorValueMap,\n ElasticSearchOperatorValueMap,\n ElasticSearchLogicalOperatorValueMap,\n ElasticSearchBlacklisted\n>;\n\n/**\n * Translator for ElasticSearch filter queries.\n * Maintains ElasticSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class ElasticSearchFilterTranslator extends BaseFilterTranslator<ElasticSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not', '$nor'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: ElasticSearchVectorFilter): ElasticSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: ElasticSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n minimum_should_match: 1,\n },\n };\n case '$not':\n case '$nor':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Escapes wildcard metacharacters (* and ?) for use in wildcard queries.\n * Existing wildcard metacharacters in the pattern are escaped before\n * adding leading/trailing * to prevent semantic changes.\n * First escapes backslashes to avoid ambiguous encoding sequences.\n */\n private escapeWildcardMetacharacters(pattern: string): string {\n // First escape backslashes to avoid ambiguous encoding sequences\n // Then escape * and ? which are wildcard metacharacters\n return pattern.replace(/\\\\/g, '\\\\\\\\').replace(/\\*/g, '\\\\*').replace(/\\?/g, '\\\\?');\n }\n\n /**\n * Translates regex patterns to ElasticSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Escape existing wildcard metacharacters before adding leading/trailing *\n const escapedPattern = this.escapeWildcardMetacharacters(processedRegex);\n\n // Create wildcard pattern\n let wildcardPattern = escapedPattern;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: { value: wildcardPattern } } };\n }\n\n // Use regexp for other regex patterns\n // Pass the original regex pattern through unchanged to preserve regex semantics\n // ElasticSearch regexp queries accept valid regex patterns directly\n return { regexp: { [field]: { value: regexValue } } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to ElasticSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { Client as ElasticSearchClient } from '@elastic/elasticsearch';\nimport { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\n\nimport packageJson from '../../package.json';\nimport { ElasticSearchFilterTranslator } from './filter';\nimport type { ElasticSearchVectorFilter } from './filter';\n\nconst METRIC_MAPPING = {\n cosine: 'cosine',\n euclidean: 'l2_norm',\n dotproduct: 'dot_product',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosine: 'cosine',\n l2_norm: 'euclidean',\n dot_product: 'dotproduct',\n} as const;\n\ntype ElasticSearchVectorParams = QueryVectorParams<ElasticSearchVectorFilter>;\n\nexport type ElasticSearchAuth = { apiKey: string } | { username: string; password: string } | { bearer: string };\n\nexport type ElasticSearchVectorConfig =\n | { id: string; client: ElasticSearchClient; url?: never; auth?: never }\n | { id: string; url: string; auth?: ElasticSearchAuth; client?: never };\n\nexport class ElasticSearchVector extends MastraVector<ElasticSearchVectorFilter> {\n private client: ElasticSearchClient;\n\n /**\n * Creates a new ElasticSearchVector client.\n *\n * Accepts either a pre-configured ElasticSearch client or connection parameters:\n * - `{ id, client }` - Use an existing ElasticSearch client\n * - `{ id, url, auth? }` - Create a new client from connection parameters\n */\n constructor(config: ElasticSearchVectorConfig) {\n super({ id: config.id });\n if ('client' in config && config.client) {\n this.client = config.client;\n } else if ('url' in config && config.url) {\n this.client = new ElasticSearchClient({\n node: config.url,\n ...(config.auth && { auth: config.auth }),\n name: 'mastra-elasticsearch',\n headers: { 'user-agent': `mastra-es/${packageJson.version}` },\n });\n } else {\n throw new MastraError({\n id: 'ELASTIC_SEARCH_CONSTRUCTOR_ERROR',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.SYSTEM,\n text: 'Invalid config: provide either { client } or { url }.',\n });\n }\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n mappings: {\n properties: {\n metadata: { type: 'object' },\n embedding: {\n type: 'dense_vector',\n dims: dimension,\n index: true,\n similarity: METRIC_MAPPING[metric],\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined): index is string => index !== undefined && !index.startsWith('.'));\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Validates that an existing index matches the requested dimension and metric.\n * Throws an error if there's a mismatch, otherwise allows idempotent creation.\n */\n protected async validateExistingIndex(indexName: string, dimension: number, metric: string): Promise<void> {\n let info: IndexStats;\n try {\n info = await this.describeIndex({ indexName });\n } catch (infoError) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'VALIDATE_INDEX', 'FETCH_FAILED'),\n text: `Index \"${indexName}\" already exists, but failed to fetch index info for dimension check.`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.SYSTEM,\n details: { indexName },\n },\n infoError,\n );\n this.logger?.trackException(mastraError);\n this.logger?.error(mastraError.toString());\n throw mastraError;\n }\n\n const existingDim = info?.dimension;\n const existingMetric = info?.metric;\n\n if (existingDim === dimension) {\n this.logger?.info(\n `Index \"${indexName}\" already exists with ${existingDim} dimensions and metric ${existingMetric}, skipping creation.`,\n );\n if (existingMetric !== metric) {\n this.logger?.warn(\n `Attempted to create index with metric \"${metric}\", but index already exists with metric \"${existingMetric}\". To use a different metric, delete and recreate the index.`,\n );\n }\n } else if (info) {\n const mastraError = new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'VALIDATE_INDEX', 'DIMENSION_MISMATCH'),\n text: `Index \"${indexName}\" already exists with ${existingDim} dimensions, but ${dimension} dimensions were requested`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName, existingDim, requestedDim: dimension },\n });\n this.logger?.trackException(mastraError);\n this.logger?.error(mastraError.toString());\n throw mastraError;\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const indexInfo = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const similarity = embedding.similarity as keyof typeof REVERSE_METRIC_MAPPING;\n\n const countInfo = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dims),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[similarity],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName }, { ignore: [404] });\n } catch (error: any) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n throw mastraError;\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('ELASTICSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n const response = await this.client.bulk({ operations, refresh: true });\n\n // Check for item-level errors in bulk response\n if (response.errors) {\n const failedItems: Array<{ id: string; status: number; error: any }> = [];\n const successfulIds: string[] = [];\n\n // Iterate through items to collect failures\n for (let i = 0; i < response.items.length; i++) {\n const item = response.items[i];\n if (!item) continue;\n const operationType = Object.keys(item)[0] as 'index' | 'create' | 'update' | 'delete';\n const operationResult = item[operationType];\n if (!operationResult) continue;\n\n if (operationResult.error) {\n // Extract the ID from the original operations array\n // Operations alternate: operation, document, operation, document...\n const operationIndex = i * 2;\n const operationDoc = operations[operationIndex] as { index?: { _id?: string } };\n const failedId = operationDoc?.index?._id || vectorIds[i] || `unknown-${i}`;\n\n failedItems.push({\n id: failedId,\n status: operationResult.status || 0,\n error: operationResult.error,\n });\n } else if (operationResult?.status && operationResult.status < 300) {\n // Success - extract ID\n const operationIndex = i * 2;\n const operationDoc = operations[operationIndex] as { index?: { _id?: string } };\n const successId = operationDoc?.index?._id || vectorIds[i];\n if (successId) {\n successfulIds.push(successId);\n }\n }\n }\n\n // If there are failures, log and throw error\n if (failedItems.length > 0) {\n const failedItemDetails = failedItems\n .map(item => `${item.id}: ${item.error?.reason || item.error?.type || JSON.stringify(item.error)}`)\n .join('; ');\n\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPSERT', 'BULK_PARTIAL_FAILURE'),\n text: `Bulk upsert partially failed: ${failedItems.length} of ${response.items.length} operations failed. Failed items: ${failedItemDetails}`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n totalOperations: response.items.length,\n failedCount: failedItems.length,\n successfulCount: successfulIds.length,\n failedItemIds: failedItems.map(item => item.id).join(','),\n failedItemErrors: failedItemDetails,\n },\n },\n new Error(`Bulk operation had ${failedItems.length} failures`),\n );\n\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n\n // Throw error with details about failures\n throw mastraError;\n }\n }\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query.\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: ElasticSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for Elasticsearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('ELASTICSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n // Decide which fields to fetch from _source\n const sourceFields = includeVector ? ['metadata', 'embedding'] : ['metadata'];\n\n const response = await this.client.search({\n index: indexName,\n knn: {\n field: 'embedding',\n query_vector: queryVector,\n k: topK,\n num_candidates: topK * 2,\n ...(translatedFilter ? { filter: translatedFilter } : {}),\n },\n _source: sourceFields,\n });\n\n const results = response.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(hit._id),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the ElasticSearch DSL.\n *\n * @param {ElasticSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: ElasticSearchVectorFilter): any {\n const translator = new ElasticSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<ElasticSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const result = await this.client\n .get({\n index: indexName,\n id: id,\n _source: ['embedding', 'metadata'],\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!result || !result._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = result;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source as any;\n const updatedDoc: Record<string, any> = {};\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n document: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: ElasticSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new ElasticSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<ElasticSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n const response = await this.client.bulk({\n operations: bulkBody,\n refresh: true,\n });\n\n // Check for item-level errors in bulk response\n if (response.errors) {\n const failedItems: Array<{ id: string; status: number; error: any }> = [];\n const successfulIds: string[] = [];\n\n // Iterate through items to collect failures\n for (let i = 0; i < response.items.length; i++) {\n const item = response.items[i];\n if (!item) continue;\n const operationType = Object.keys(item)[0] as 'index' | 'create' | 'update' | 'delete';\n const operationResult = item[operationType];\n if (!operationResult) continue;\n\n if (operationResult.error) {\n // Extract the ID from the original operations array\n const operationIndex = i;\n const operationDoc = bulkBody[operationIndex] as { delete?: { _id?: string } };\n const failedId = operationDoc?.delete?._id || ids[i] || `unknown-${i}`;\n\n failedItems.push({\n id: failedId,\n status: operationResult.status || 0,\n error: operationResult.error,\n });\n } else if (operationResult?.status && operationResult.status < 300) {\n // Success - extract ID\n const operationIndex = i;\n const operationDoc = bulkBody[operationIndex] as { delete?: { _id?: string } };\n const successId = operationDoc?.delete?._id || ids[i];\n if (successId) {\n successfulIds.push(successId);\n }\n }\n }\n\n // If there are failures, log and throw error\n if (failedItems.length > 0) {\n const failedItemDetails = failedItems\n .map(item => `${item.id}: ${item.error?.reason || item.error?.type || JSON.stringify(item.error)}`)\n .join('; ');\n\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'BULK_PARTIAL_FAILURE'),\n text: `Bulk delete partially failed: ${failedItems.length} of ${response.items.length} operations failed. Failed items: ${failedItemDetails}`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n totalOperations: response.items.length,\n failedCount: failedItems.length,\n successfulCount: successfulIds.length,\n failedItemIds: failedItems.map(item => item.id).join(','),\n failedItemErrors: failedItemDetails,\n },\n },\n new Error(`Bulk delete operation had ${failedItems.length} failures`),\n );\n\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n\n // Throw error with details about failures\n throw mastraError;\n }\n }\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new ElasticSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n query: (translatedFilter as any) || { match_all: {} },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["ElasticSearchClient","packageJson.version","operationIndex","crypto","ElasticSearchClient","packageJson.version"],"sources":["../package.json","../src/vector/filter.ts","../src/vector/index.ts","../src/storage/domains/utils.ts","../src/storage/db.ts","../src/storage/domains/memory/index.ts","../src/storage/domains/scores/index.ts","../src/storage/domains/workflows/index.ts","../src/storage/store.ts"],"sourcesContent":["","import type {\n BlacklistedRootOperators,\n LogicalOperatorValueMap,\n OperatorSupport,\n OperatorValueMap,\n QueryOperator,\n VectorFilter,\n} from '@mastra/core/vector/filter';\nimport { BaseFilterTranslator } from '@mastra/core/vector/filter';\n\ntype ElasticSearchOperatorValueMap = Omit<OperatorValueMap, '$options' | '$nor' | '$elemMatch'>;\n\ntype ElasticSearchLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype ElasticSearchBlacklisted = BlacklistedRootOperators | '$nor';\n\nexport type ElasticSearchVectorFilter = VectorFilter<\n keyof ElasticSearchOperatorValueMap,\n ElasticSearchOperatorValueMap,\n ElasticSearchLogicalOperatorValueMap,\n ElasticSearchBlacklisted\n>;\n\n/**\n * Translator for ElasticSearch filter queries.\n * Maintains ElasticSearch-compatible syntax while ensuring proper validation\n * and normalization of values.\n */\nexport class ElasticSearchFilterTranslator extends BaseFilterTranslator<ElasticSearchVectorFilter> {\n protected override getSupportedOperators(): OperatorSupport {\n return {\n ...BaseFilterTranslator.DEFAULT_OPERATORS,\n logical: ['$and', '$or', '$not', '$nor'],\n array: ['$in', '$nin', '$all'],\n regex: ['$regex'],\n custom: [],\n };\n }\n\n translate(filter?: ElasticSearchVectorFilter): ElasticSearchVectorFilter {\n if (this.isEmpty(filter)) return undefined;\n this.validateFilter(filter);\n return this.translateNode(filter);\n }\n\n private translateNode(node: ElasticSearchVectorFilter): any {\n // Handle primitive values and arrays\n if (this.isPrimitive(node) || Array.isArray(node)) {\n return node;\n }\n\n const entries = Object.entries(node as Record<string, any>);\n\n // Extract logical operators and field conditions\n const logicalOperators: [string, any][] = [];\n const fieldConditions: [string, any][] = [];\n\n entries.forEach(([key, value]) => {\n if (this.isLogicalOperator(key)) {\n logicalOperators.push([key, value]);\n } else {\n fieldConditions.push([key, value]);\n }\n });\n\n // If we have a single logical operator\n if (logicalOperators.length === 1 && fieldConditions.length === 0) {\n const [operator, value] = logicalOperators[0] as [QueryOperator, any];\n if (!Array.isArray(value) && typeof value !== 'object') {\n throw new Error(`Invalid logical operator structure: ${operator} must have an array or object value`);\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // Process field conditions\n const fieldConditionQueries = fieldConditions.map(([key, value]) => {\n // Handle nested objects\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n // Check if the object contains operators\n const hasOperators = Object.keys(value).some(k => this.isOperator(k));\n\n // Use a more direct approach based on whether operators are present\n const nestedField = `metadata.${key}`;\n return hasOperators\n ? this.translateFieldConditions(nestedField, value)\n : this.translateNestedObject(nestedField, value);\n }\n\n // Handle arrays\n if (Array.isArray(value)) {\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { terms: { [fieldWithKeyword]: value } };\n }\n\n // Handle simple field equality\n const fieldWithKeyword = this.addKeywordIfNeeded(`metadata.${key}`, value);\n return { term: { [fieldWithKeyword]: value } };\n });\n\n // Handle case with both logical operators and field conditions or multiple logical operators\n if (logicalOperators.length > 0) {\n const logicalConditions = logicalOperators.map(([operator, value]) =>\n this.translateOperator(operator as QueryOperator, value),\n );\n\n return {\n bool: {\n must: [...logicalConditions, ...fieldConditionQueries],\n },\n };\n }\n\n // If we only have field conditions\n if (fieldConditionQueries.length > 1) {\n return {\n bool: {\n must: fieldConditionQueries,\n },\n };\n }\n\n // If we have only one field condition\n if (fieldConditionQueries.length === 1) {\n return fieldConditionQueries[0];\n }\n\n // If we have no conditions (e.g., only empty $and arrays)\n return { match_all: {} };\n }\n\n /**\n * Handles translation of nested objects with dot notation fields\n */\n private translateNestedObject(field: string, value: Record<string, any>): any {\n const conditions = Object.entries(value).map(([subField, subValue]) => {\n const fullField = `${field}.${subField}`;\n\n // Check if this is an operator in a nested field\n if (this.isOperator(subField)) {\n return this.translateOperator(subField as QueryOperator, subValue, field);\n }\n\n if (typeof subValue === 'object' && subValue !== null && !Array.isArray(subValue)) {\n // Check if the nested object contains operators\n const hasOperators = Object.keys(subValue).some(k => this.isOperator(k));\n if (hasOperators) {\n return this.translateFieldConditions(fullField, subValue);\n }\n return this.translateNestedObject(fullField, subValue);\n }\n const fieldWithKeyword = this.addKeywordIfNeeded(fullField, subValue);\n return { term: { [fieldWithKeyword]: subValue } };\n });\n\n return {\n bool: {\n must: conditions,\n },\n };\n }\n\n private translateLogicalOperator(operator: QueryOperator, value: any): any {\n const conditions = Array.isArray(value) ? value.map(item => this.translateNode(item)) : [this.translateNode(value)];\n switch (operator) {\n case '$and':\n // For empty $and, return a query that matches everything\n if (Array.isArray(value) && value.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must: conditions,\n },\n };\n case '$or':\n // For empty $or, return a query that matches nothing\n if (Array.isArray(value) && value.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n should: conditions,\n minimum_should_match: 1,\n },\n };\n case '$not':\n case '$nor':\n return {\n bool: {\n must_not: conditions,\n },\n };\n default:\n return value;\n }\n }\n\n private translateFieldOperator(field: string, operator: QueryOperator, value: any): any {\n // Handle basic comparison operators\n if (this.isBasicOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$eq':\n // Handle null equality: field does not exist or is null\n if (value === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n return { term: { [fieldWithKeyword]: normalizedValue } };\n case '$ne':\n // Handle null inequality: field exists (i.e., is not null)\n if (value === null) {\n return { exists: { field } };\n }\n return {\n bool: {\n must_not: [{ term: { [fieldWithKeyword]: normalizedValue } }],\n },\n };\n default:\n return { term: { [fieldWithKeyword]: normalizedValue } };\n }\n }\n\n // Handle numeric operators\n if (this.isNumericOperator(operator)) {\n const normalizedValue = this.normalizeComparisonValue(value);\n const rangeOp = operator.replace('$', '');\n return { range: { [field]: { [rangeOp]: normalizedValue } } };\n }\n\n // Handle array operators\n if (this.isArrayOperator(operator)) {\n if (!Array.isArray(value)) {\n throw new Error(`Invalid array operator value: ${operator} requires an array value`);\n }\n const normalizedValues = this.normalizeArrayValues(value);\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n switch (operator) {\n case '$in':\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n case '$nin':\n // For empty arrays, return a query that matches everything\n if (normalizedValues.length === 0) {\n return { match_all: {} };\n }\n return {\n bool: {\n must_not: [{ terms: { [fieldWithKeyword]: normalizedValues } }],\n },\n };\n case '$all':\n // For empty arrays, return a query that will match nothing\n if (normalizedValues.length === 0) {\n return {\n bool: {\n must_not: [{ match_all: {} }],\n },\n };\n }\n return {\n bool: {\n must: normalizedValues.map(v => ({ term: { [fieldWithKeyword]: v } })),\n },\n };\n default:\n return { terms: { [fieldWithKeyword]: normalizedValues } };\n }\n }\n\n // Handle element operators\n if (this.isElementOperator(operator)) {\n switch (operator) {\n case '$exists':\n return value ? { exists: { field } } : { bool: { must_not: [{ exists: { field } }] } };\n default:\n return { exists: { field } };\n }\n }\n\n // Handle regex operators\n if (this.isRegexOperator(operator)) {\n return this.translateRegexOperator(field, value);\n }\n\n const fieldWithKeyword = this.addKeywordIfNeeded(field, value);\n return { term: { [fieldWithKeyword]: value } };\n }\n\n /**\n * Escapes wildcard metacharacters (* and ?) for use in wildcard queries.\n * Existing wildcard metacharacters in the pattern are escaped before\n * adding leading/trailing * to prevent semantic changes.\n * First escapes backslashes to avoid ambiguous encoding sequences.\n */\n private escapeWildcardMetacharacters(pattern: string): string {\n // First escape backslashes to avoid ambiguous encoding sequences\n // Then escape * and ? which are wildcard metacharacters\n return pattern.replace(/\\\\/g, '\\\\\\\\').replace(/\\*/g, '\\\\*').replace(/\\?/g, '\\\\?');\n }\n\n /**\n * Translates regex patterns to ElasticSearch query syntax\n */\n private translateRegexOperator(field: string, value: any): any {\n // Convert value to string if it's not already\n const regexValue = typeof value === 'string' ? value : value.toString();\n\n // Process regex pattern to handle anchors properly\n let processedRegex = regexValue;\n const hasStartAnchor = regexValue.startsWith('^');\n const hasEndAnchor = regexValue.endsWith('$');\n\n // If we have anchors, use wildcard query for better handling\n if (hasStartAnchor || hasEndAnchor) {\n // Remove anchors\n if (hasStartAnchor) {\n processedRegex = processedRegex.substring(1);\n }\n if (hasEndAnchor) {\n processedRegex = processedRegex.substring(0, processedRegex.length - 1);\n }\n\n // Escape existing wildcard metacharacters before adding leading/trailing *\n const escapedPattern = this.escapeWildcardMetacharacters(processedRegex);\n\n // Create wildcard pattern\n let wildcardPattern = escapedPattern;\n if (!hasStartAnchor) {\n wildcardPattern = '*' + wildcardPattern;\n }\n if (!hasEndAnchor) {\n wildcardPattern = wildcardPattern + '*';\n }\n\n return { wildcard: { [field]: { value: wildcardPattern } } };\n }\n\n // Use regexp for other regex patterns\n // Pass the original regex pattern through unchanged to preserve regex semantics\n // ElasticSearch regexp queries accept valid regex patterns directly\n return { regexp: { [field]: { value: regexValue } } };\n }\n\n private addKeywordIfNeeded(field: string, value: any): string {\n // Add .keyword suffix for string fields\n if (typeof value === 'string') {\n return `${field}.keyword`;\n }\n // Add .keyword suffix for string array fields\n if (Array.isArray(value) && value.every(item => typeof item === 'string')) {\n return `${field}.keyword`;\n }\n return field;\n }\n\n /**\n * Helper method to handle special cases for the $not operator\n */\n private handleNotOperatorSpecialCases(value: any, field: string): any | null {\n // For \"not null\", we need to use exists query\n if (value === null) {\n return { exists: { field } };\n }\n\n if (typeof value === 'object' && value !== null) {\n // For \"not {$eq: null}\", we need to use exists query\n if ('$eq' in value && value.$eq === null) {\n return { exists: { field } };\n }\n\n // For \"not {$ne: null}\", we need to use must_not exists query\n if ('$ne' in value && value.$ne === null) {\n return {\n bool: {\n must_not: [{ exists: { field } }],\n },\n };\n }\n }\n\n return null; // No special case applies\n }\n\n private translateOperator(operator: QueryOperator, value: any, field?: string): any {\n // Check if this is a valid operator\n if (!this.isOperator(operator)) {\n throw new Error(`Unsupported operator: ${operator}`);\n }\n\n // Special case for $not with null or $eq: null\n if (operator === '$not' && field) {\n const specialCaseResult = this.handleNotOperatorSpecialCases(value, field);\n if (specialCaseResult) {\n return specialCaseResult;\n }\n }\n\n // Handle logical operators\n if (this.isLogicalOperator(operator)) {\n // For $not operator with field context and nested operators, handle specially\n if (operator === '$not' && field && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const entries = Object.entries(value);\n\n // Handle multiple operators in $not\n if (entries.length > 0) {\n // If all entries are operators, handle them as a single condition\n if (entries.every(([op]) => this.isOperator(op))) {\n const translatedCondition = this.translateFieldConditions(field, value);\n return {\n bool: {\n must_not: [translatedCondition],\n },\n };\n }\n\n // Handle single nested operator\n if (entries.length === 1 && entries[0] && this.isOperator(entries[0][0])) {\n const [nestedOp, nestedVal] = entries[0] as [QueryOperator, any];\n const translatedNested = this.translateFieldOperator(field, nestedOp, nestedVal);\n return {\n bool: {\n must_not: [translatedNested],\n },\n };\n }\n }\n }\n return this.translateLogicalOperator(operator, value);\n }\n\n // If a field is provided, use translateFieldOperator for more specific translation\n if (field) {\n return this.translateFieldOperator(field, operator, value);\n }\n\n // For non-logical operators without a field context, just return the value\n // The actual translation happens in translateFieldConditions where we have the field context\n return value;\n }\n\n /**\n * Translates field conditions to ElasticSearch query syntax\n * Handles special cases like range queries and multiple operators\n */\n private translateFieldConditions(field: string, conditions: Record<string, any>): any {\n // Special case: Optimize multiple numeric operators into a single range query\n if (this.canOptimizeToRangeQuery(conditions)) {\n return this.createRangeQuery(field, conditions);\n }\n\n // Handle all other operators consistently\n const queryConditions: any[] = [];\n Object.entries(conditions).forEach(([operator, value]) => {\n if (this.isOperator(operator)) {\n queryConditions.push(this.translateOperator(operator as QueryOperator, value, field));\n } else {\n // Handle non-operator keys (should not happen in normal usage)\n const fieldWithKeyword = this.addKeywordIfNeeded(`${field}.${operator}`, value);\n queryConditions.push({ term: { [fieldWithKeyword]: value } });\n }\n });\n\n // Return single condition without wrapping\n if (queryConditions.length === 1) {\n return queryConditions[0];\n }\n\n // Combine multiple conditions with AND logic\n return {\n bool: {\n must: queryConditions,\n },\n };\n }\n\n /**\n * Checks if conditions can be optimized to a range query\n */\n private canOptimizeToRangeQuery(conditions: Record<string, any>): boolean {\n return Object.keys(conditions).every(op => this.isNumericOperator(op)) && Object.keys(conditions).length > 0;\n }\n\n /**\n * Creates a range query from numeric operators\n */\n private createRangeQuery(field: string, conditions: Record<string, any>): any {\n const rangeParams = Object.fromEntries(\n Object.entries(conditions).map(([op, val]) => [op.replace('$', ''), this.normalizeComparisonValue(val)]),\n );\n\n return { range: { [field]: rangeParams } };\n }\n}\n","import { Client as ElasticSearchClient } from '@elastic/elasticsearch';\nimport { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport type {\n CreateIndexParams,\n DeleteIndexParams,\n DeleteVectorParams,\n DescribeIndexParams,\n IndexStats,\n QueryResult,\n QueryVectorParams,\n UpdateVectorParams,\n UpsertVectorParams,\n DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { MastraVector, validateUpsert, validateTopK } from '@mastra/core/vector';\n\nimport packageJson from '../../package.json';\nimport { ElasticSearchFilterTranslator } from './filter';\nimport type { ElasticSearchVectorFilter } from './filter';\n\nconst METRIC_MAPPING = {\n cosine: 'cosine',\n euclidean: 'l2_norm',\n dotproduct: 'dot_product',\n} as const;\n\nconst REVERSE_METRIC_MAPPING = {\n cosine: 'cosine',\n l2_norm: 'euclidean',\n dot_product: 'dotproduct',\n} as const;\n\ntype ElasticSearchVectorParams = QueryVectorParams<ElasticSearchVectorFilter>;\n\nexport type ElasticSearchAuth = { apiKey: string } | { username: string; password: string } | { bearer: string };\n\nexport type ElasticSearchVectorConfig =\n | { id: string; client: ElasticSearchClient; url?: never; auth?: never }\n | { id: string; url: string; auth?: ElasticSearchAuth; client?: never };\n\nexport class ElasticSearchVector extends MastraVector<ElasticSearchVectorFilter> {\n private client: ElasticSearchClient;\n\n /**\n * Creates a new ElasticSearchVector client.\n *\n * Accepts either a pre-configured ElasticSearch client or connection parameters:\n * - `{ id, client }` - Use an existing ElasticSearch client\n * - `{ id, url, auth? }` - Create a new client from connection parameters\n */\n constructor(config: ElasticSearchVectorConfig) {\n super({ id: config.id });\n if ('client' in config && config.client) {\n this.client = config.client;\n } else if ('url' in config && config.url) {\n this.client = new ElasticSearchClient({\n node: config.url,\n ...(config.auth && { auth: config.auth }),\n name: 'mastra-elasticsearch',\n headers: { 'user-agent': `mastra-es/${packageJson.version}` },\n });\n } else {\n throw new MastraError({\n id: 'ELASTIC_SEARCH_CONSTRUCTOR_ERROR',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.SYSTEM,\n text: 'Invalid config: provide either { client } or { url }.',\n });\n }\n }\n\n /**\n * Creates a new collection with the specified configuration.\n *\n * @param {string} indexName - The name of the collection to create.\n * @param {number} dimension - The dimension of the vectors to be stored in the collection.\n * @param {'cosine' | 'euclidean' | 'dotproduct'} [metric=cosine] - The metric to use to sort vectors in the collection.\n * @returns {Promise<void>} A promise that resolves when the collection is created.\n */\n async createIndex({ indexName, dimension, metric = 'cosine' }: CreateIndexParams): Promise<void> {\n if (!Number.isInteger(dimension) || dimension <= 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'CREATE_INDEX', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Dimension must be a positive integer',\n details: { indexName, dimension },\n });\n }\n\n try {\n await this.client.indices.create({\n index: indexName,\n mappings: {\n properties: {\n metadata: { type: 'object' },\n embedding: {\n type: 'dense_vector',\n dims: dimension,\n index: true,\n similarity: METRIC_MAPPING[metric],\n },\n },\n },\n });\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n // Fetch collection info and check dimension\n await this.validateExistingIndex(indexName, dimension, metric);\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'CREATE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, dimension, metric },\n },\n error,\n );\n }\n }\n\n /**\n * Lists all indexes.\n *\n * @returns {Promise<string[]>} A promise that resolves to an array of indexes.\n */\n async listIndexes(): Promise<string[]> {\n try {\n const response = await this.client.cat.indices({ format: 'json' });\n const indexes = response\n .map((record: { index?: string }) => record.index)\n .filter((index: string | undefined): index is string => index !== undefined && !index.startsWith('.'));\n\n return indexes;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'LIST_INDEXES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n },\n error,\n );\n }\n }\n\n /**\n * Validates that an existing index matches the requested dimension and metric.\n * Throws an error if there's a mismatch, otherwise allows idempotent creation.\n */\n protected async validateExistingIndex(indexName: string, dimension: number, metric: string): Promise<void> {\n let info: IndexStats;\n try {\n info = await this.describeIndex({ indexName });\n } catch (infoError) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'VALIDATE_INDEX', 'FETCH_FAILED'),\n text: `Index \"${indexName}\" already exists, but failed to fetch index info for dimension check.`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.SYSTEM,\n details: { indexName },\n },\n infoError,\n );\n this.logger?.trackException(mastraError);\n this.logger?.error(mastraError.toString());\n throw mastraError;\n }\n\n const existingDim = info?.dimension;\n const existingMetric = info?.metric;\n\n if (existingDim === dimension) {\n this.logger?.info(\n `Index \"${indexName}\" already exists with ${existingDim} dimensions and metric ${existingMetric}, skipping creation.`,\n );\n if (existingMetric !== metric) {\n this.logger?.warn(\n `Attempted to create index with metric \"${metric}\", but index already exists with metric \"${existingMetric}\". To use a different metric, delete and recreate the index.`,\n );\n }\n } else if (info) {\n const mastraError = new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'VALIDATE_INDEX', 'DIMENSION_MISMATCH'),\n text: `Index \"${indexName}\" already exists with ${existingDim} dimensions, but ${dimension} dimensions were requested`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName, existingDim, requestedDim: dimension },\n });\n this.logger?.trackException(mastraError);\n this.logger?.error(mastraError.toString());\n throw mastraError;\n }\n }\n\n /**\n * Retrieves statistics about a vector index.\n *\n * @param {string} indexName - The name of the index to describe\n * @returns A promise that resolves to the index statistics including dimension, count and metric\n */\n async describeIndex({ indexName }: DescribeIndexParams): Promise<IndexStats> {\n const indexInfo = await this.client.indices.get({ index: indexName });\n const mappings = indexInfo[indexName]?.mappings;\n const embedding: any = mappings?.properties?.embedding;\n const similarity = embedding.similarity as keyof typeof REVERSE_METRIC_MAPPING;\n\n const countInfo = await this.client.count({ index: indexName });\n\n return {\n dimension: Number(embedding.dims),\n count: Number(countInfo.count),\n metric: REVERSE_METRIC_MAPPING[similarity],\n };\n }\n\n /**\n * Deletes the specified index.\n *\n * @param {string} indexName - The name of the index to delete.\n * @returns {Promise<void>} A promise that resolves when the index is deleted.\n */\n async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n try {\n await this.client.indices.delete({ index: indexName }, { ignore: [404] });\n } catch (error: any) {\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName },\n },\n error,\n );\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n throw mastraError;\n }\n }\n\n /**\n * Inserts or updates vectors in the specified collection.\n *\n * @param {string} indexName - The name of the collection to upsert into.\n * @param {number[][]} vectors - An array of vectors to upsert.\n * @param {Record<string, any>[]} [metadata] - An optional array of metadata objects corresponding to each vector.\n * @param {string[]} [ids] - An optional array of IDs corresponding to each vector. If not provided, new IDs will be generated.\n * @returns {Promise<string[]>} A promise that resolves to an array of IDs of the upserted vectors.\n */\n async upsert({ indexName, vectors, metadata = [], ids }: UpsertVectorParams): Promise<string[]> {\n // Validate input parameters and vector values\n validateUpsert('ELASTICSEARCH', vectors, metadata, ids, true);\n\n const vectorIds = ids || vectors.map(() => crypto.randomUUID());\n const operations = [];\n\n try {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions(vectors, indexInfo.dimension);\n\n for (let i = 0; i < vectors.length; i++) {\n const operation = {\n index: {\n _index: indexName,\n _id: vectorIds[i],\n },\n };\n\n const document = {\n embedding: vectors[i],\n metadata: metadata[i] || {},\n };\n\n operations.push(operation);\n operations.push(document);\n }\n\n if (operations.length > 0) {\n const response = await this.client.bulk({ operations, refresh: true });\n\n // Check for item-level errors in bulk response\n if (response.errors) {\n const failedItems: Array<{ id: string; status: number; error: any }> = [];\n const successfulIds: string[] = [];\n\n // Iterate through items to collect failures\n for (let i = 0; i < response.items.length; i++) {\n const item = response.items[i];\n if (!item) continue;\n const operationType = Object.keys(item)[0] as 'index' | 'create' | 'update' | 'delete';\n const operationResult = item[operationType];\n if (!operationResult) continue;\n\n if (operationResult.error) {\n // Extract the ID from the original operations array\n // Operations alternate: operation, document, operation, document...\n const operationIndex = i * 2;\n const operationDoc = operations[operationIndex] as { index?: { _id?: string } };\n const failedId = operationDoc?.index?._id || vectorIds[i] || `unknown-${i}`;\n\n failedItems.push({\n id: failedId,\n status: operationResult.status || 0,\n error: operationResult.error,\n });\n } else if (operationResult?.status && operationResult.status < 300) {\n // Success - extract ID\n const operationIndex = i * 2;\n const operationDoc = operations[operationIndex] as { index?: { _id?: string } };\n const successId = operationDoc?.index?._id || vectorIds[i];\n if (successId) {\n successfulIds.push(successId);\n }\n }\n }\n\n // If there are failures, log and throw error\n if (failedItems.length > 0) {\n const failedItemDetails = failedItems\n .map(item => `${item.id}: ${item.error?.reason || item.error?.type || JSON.stringify(item.error)}`)\n .join('; ');\n\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPSERT', 'BULK_PARTIAL_FAILURE'),\n text: `Bulk upsert partially failed: ${failedItems.length} of ${response.items.length} operations failed. Failed items: ${failedItemDetails}`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n totalOperations: response.items.length,\n failedCount: failedItems.length,\n successfulCount: successfulIds.length,\n failedItemIds: failedItems.map(item => item.id).join(','),\n failedItemErrors: failedItemDetails,\n },\n },\n new Error(`Bulk operation had ${failedItems.length} failures`),\n );\n\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n\n // Throw error with details about failures\n throw mastraError;\n }\n }\n }\n\n return vectorIds;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, vectorCount: vectors?.length || 0 },\n },\n error,\n );\n }\n }\n\n /**\n * Queries the specified collection using a vector and optional filter.\n *\n * @param {string} indexName - The name of the collection to query.\n * @param {number[]} queryVector - The vector to query with.\n * @param {number} [topK] - The maximum number of results to return.\n * @param {Record<string, any>} [filter] - An optional filter to apply to the query.\n * @param {boolean} [includeVectors=false] - Whether to include the vectors in the response.\n * @returns {Promise<QueryResult[]>} A promise that resolves to an array of query results.\n */\n async query({\n indexName,\n queryVector,\n filter,\n topK = 10,\n includeVector = false,\n }: ElasticSearchVectorParams): Promise<QueryResult[]> {\n if (!queryVector) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'QUERY', 'MISSING_VECTOR'),\n text: 'queryVector is required for Elasticsearch queries. Metadata-only queries are not supported by this vector store.',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { indexName },\n });\n }\n\n // Validate topK parameter\n validateTopK('ELASTICSEARCH', topK);\n\n try {\n const translatedFilter = this.transformFilter(filter);\n\n // Decide which fields to fetch from _source\n const sourceFields = includeVector ? ['metadata', 'embedding'] : ['metadata'];\n\n const response = await this.client.search({\n index: indexName,\n knn: {\n field: 'embedding',\n query_vector: queryVector,\n k: topK,\n num_candidates: topK * 2,\n ...(translatedFilter ? { filter: translatedFilter } : {}),\n },\n _source: sourceFields,\n });\n\n const results = response.hits.hits.map((hit: any) => {\n const source = hit._source || {};\n return {\n id: String(hit._id),\n score: typeof hit._score === 'number' ? hit._score : 0,\n metadata: source.metadata || {},\n ...(includeVector && { vector: source.embedding as number[] }),\n };\n });\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'QUERY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { indexName, topK },\n },\n error,\n );\n }\n }\n\n /**\n * Validates the dimensions of the vectors.\n *\n * @param {number[][]} vectors - The vectors to validate.\n * @param {number} dimension - The dimension of the vectors.\n * @returns {void}\n */\n private validateVectorDimensions(vectors: number[][], dimension: number) {\n if (vectors.some(vector => vector.length !== dimension)) {\n throw new Error('Vector dimension does not match index dimension');\n }\n }\n\n /**\n * Transforms the filter to the ElasticSearch DSL.\n *\n * @param {ElasticSearchVectorFilter} filter - The filter to transform.\n * @returns {Record<string, any>} The transformed filter.\n */\n private transformFilter(filter?: ElasticSearchVectorFilter): any {\n const translator = new ElasticSearchFilterTranslator();\n return translator.translate(filter);\n }\n\n /**\n * Updates vectors by ID or filter with the provided vector and/or metadata.\n * @param params - Parameters containing either id or filter for targeting vectors to update\n * @param params.indexName - The name of the index containing the vector(s).\n * @param params.id - The ID of a single vector to update (mutually exclusive with filter).\n * @param params.filter - A filter to match multiple vectors to update (mutually exclusive with id).\n * @param params.update - An object containing the vector and/or metadata to update.\n * @returns A promise that resolves when the update is complete.\n * @throws Will throw an error if no updates are provided or if the update operation fails.\n */\n async updateVector(params: UpdateVectorParams<ElasticSearchVectorFilter>): Promise<void> {\n const { indexName, update } = params;\n\n // Validate mutually exclusive parameters\n if ('id' in params && 'filter' in params && params.id && params.filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'id and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!update.vector && !update.metadata) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'NO_UPDATES'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'No updates provided',\n details: { indexName },\n });\n }\n\n // Validate empty filter\n if ('filter' in params && params.filter && Object.keys(params.filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot update with empty filter',\n details: { indexName },\n });\n }\n\n // Type-narrowing: check if updating by id or by filter\n if ('id' in params && params.id) {\n // Update by ID\n await this.updateVectorById(indexName, params.id, update);\n } else if ('filter' in params && params.filter) {\n // Update by filter\n await this.updateVectorsByFilter(indexName, params.filter, update);\n } else {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either id or filter must be provided',\n details: { indexName },\n });\n }\n }\n\n /**\n * Updates a single vector by its ID.\n */\n private async updateVectorById(\n indexName: string,\n id: string,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n let existingDoc;\n try {\n // First get the current document to merge with updates\n const result = await this.client\n .get({\n index: indexName,\n id: id,\n _source: ['embedding', 'metadata'],\n })\n .catch(() => {\n throw new Error(`Document with ID ${id} not found in index ${indexName}`);\n });\n\n if (!result || !result._source) {\n throw new Error(`Document with ID ${id} has no source data in index ${indexName}`);\n }\n existingDoc = result;\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n\n const source = existingDoc._source as any;\n const updatedDoc: Record<string, any> = {};\n\n try {\n // Update vector if provided\n if (update.vector) {\n // Get index stats to check dimension\n const indexInfo = await this.describeIndex({ indexName });\n\n // Validate vector dimensions\n this.validateVectorDimensions([update.vector], indexInfo.dimension);\n\n updatedDoc.embedding = update.vector;\n } else if (source?.embedding) {\n updatedDoc.embedding = source.embedding;\n }\n\n // Update metadata if provided\n if (update.metadata) {\n updatedDoc.metadata = update.metadata;\n } else {\n updatedDoc.metadata = source?.metadata || {};\n }\n\n // Update the document\n await this.client.index({\n index: indexName,\n id: id,\n document: updatedDoc,\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n id,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Updates multiple vectors matching a filter.\n */\n private async updateVectorsByFilter(\n indexName: string,\n filter: ElasticSearchVectorFilter,\n update: { vector?: number[]; metadata?: Record<string, any> },\n ): Promise<void> {\n try {\n const translator = new ElasticSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n // Build the update script\n const scriptSource: string[] = [];\n const scriptParams: Record<string, any> = {};\n\n if (update.vector) {\n scriptSource.push('ctx._source.embedding = params.embedding');\n scriptParams.embedding = update.vector;\n }\n\n if (update.metadata) {\n scriptSource.push('ctx._source.metadata = params.metadata');\n scriptParams.metadata = update.metadata;\n }\n\n // Use update_by_query to update all matching documents\n await this.client.updateByQuery({\n index: indexName,\n query: (translatedFilter as any) || { match_all: {} },\n script: {\n source: scriptSource.join('; '),\n params: scriptParams,\n lang: 'painless',\n },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'UPDATE_VECTOR_BY_FILTER', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n filter: JSON.stringify(filter),\n },\n },\n error,\n );\n }\n }\n\n /**\n * Deletes a vector by its ID.\n * @param indexName - The name of the index containing the vector.\n * @param id - The ID of the vector to delete.\n * @returns A promise that resolves when the deletion is complete.\n * @throws Will throw an error if the deletion operation fails.\n */\n async deleteVector({ indexName, id }: DeleteVectorParams): Promise<void> {\n try {\n await this.client.delete({\n index: indexName,\n id: id,\n refresh: true,\n });\n } catch (error: unknown) {\n // Don't throw error if document doesn't exist (404)\n if (error && typeof error === 'object' && 'statusCode' in error && error.statusCode === 404) {\n return;\n }\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTOR', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<ElasticSearchVectorFilter>): Promise<void> {\n // Validate mutually exclusive parameters\n if (ids && filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'ids and filter are mutually exclusive',\n details: { indexName },\n });\n }\n\n if (!ids && !filter) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'NO_TARGET'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Either filter or ids must be provided',\n details: { indexName },\n });\n }\n\n // Validate non-empty arrays and objects\n if (ids && ids.length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'EMPTY_IDS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty ids array',\n details: { indexName },\n });\n }\n\n if (filter && Object.keys(filter).length === 0) {\n throw new MastraError({\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Cannot delete with empty filter',\n details: { indexName },\n });\n }\n\n try {\n if (ids) {\n // Delete by IDs using bulk API\n const bulkBody = ids.flatMap(id => [{ delete: { _index: indexName, _id: id } }]);\n\n const response = await this.client.bulk({\n operations: bulkBody,\n refresh: true,\n });\n\n // Check for item-level errors in bulk response\n if (response.errors) {\n const failedItems: Array<{ id: string; status: number; error: any }> = [];\n const successfulIds: string[] = [];\n\n // Iterate through items to collect failures\n for (let i = 0; i < response.items.length; i++) {\n const item = response.items[i];\n if (!item) continue;\n const operationType = Object.keys(item)[0] as 'index' | 'create' | 'update' | 'delete';\n const operationResult = item[operationType];\n if (!operationResult) continue;\n\n if (operationResult.error) {\n // Extract the ID from the original operations array\n const operationIndex = i;\n const operationDoc = bulkBody[operationIndex] as { delete?: { _id?: string } };\n const failedId = operationDoc?.delete?._id || ids[i] || `unknown-${i}`;\n\n failedItems.push({\n id: failedId,\n status: operationResult.status || 0,\n error: operationResult.error,\n });\n } else if (operationResult?.status && operationResult.status < 300) {\n // Success - extract ID\n const operationIndex = i;\n const operationDoc = bulkBody[operationIndex] as { delete?: { _id?: string } };\n const successId = operationDoc?.delete?._id || ids[i];\n if (successId) {\n successfulIds.push(successId);\n }\n }\n }\n\n // If there are failures, log and throw error\n if (failedItems.length > 0) {\n const failedItemDetails = failedItems\n .map(item => `${item.id}: ${item.error?.reason || item.error?.type || JSON.stringify(item.error)}`)\n .join('; ');\n\n const mastraError = new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'BULK_PARTIAL_FAILURE'),\n text: `Bulk delete partially failed: ${failedItems.length} of ${response.items.length} operations failed. Failed items: ${failedItemDetails}`,\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n totalOperations: response.items.length,\n failedCount: failedItems.length,\n successfulCount: successfulIds.length,\n failedItemIds: failedItems.map(item => item.id).join(','),\n failedItemErrors: failedItemDetails,\n },\n },\n new Error(`Bulk delete operation had ${failedItems.length} failures`),\n );\n\n this.logger?.error(mastraError.toString());\n this.logger?.trackException(mastraError);\n\n // Throw error with details about failures\n throw mastraError;\n }\n }\n } else if (filter) {\n // Delete by filter using delete_by_query\n const translator = new ElasticSearchFilterTranslator();\n const translatedFilter = translator.translate(filter);\n\n await this.client.deleteByQuery({\n index: indexName,\n query: (translatedFilter as any) || { match_all: {} },\n refresh: true,\n });\n }\n } catch (error) {\n if (error instanceof MastraError) throw error;\n throw new MastraError(\n {\n id: createVectorErrorId('ELASTICSEARCH', 'DELETE_VECTORS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n indexName,\n ...(filter && { filter: JSON.stringify(filter) }),\n ...(ids && { idsCount: ids.length }),\n },\n },\n error,\n );\n }\n }\n}\n","import { serializeDate, TABLE_MESSAGES, TABLE_WORKFLOW_SNAPSHOT } from '@mastra/core/storage';\nimport type { TABLE_NAMES } from '@mastra/core/storage';\n\n/**\n * Generate a document key from table name and key parts.\n *\n * @example\n * ```typescript\n * getKey('mastra_threads', { id: 'thread-123' });\n * // Returns: 'mastra_threads:id:thread-123'\n * ```\n */\nexport function getKey(tableName: TABLE_NAMES, keys: Record<string, unknown>): string {\n const keyParts = Object.entries(keys)\n .filter(([_, value]) => value !== undefined)\n .map(([key, value]) => {\n if (value && typeof value === 'object') {\n return `${key}:${JSON.stringify(value)}`;\n }\n\n return `${key}:${value}`;\n });\n\n return `${tableName}:${keyParts.join(':')}`;\n}\n\n/**\n * Process a record for storage, generating the appropriate document id and serializing dates.\n */\nexport function processRecord(tableName: TABLE_NAMES, record: Record<string, unknown>) {\n let key: string;\n\n if (tableName === TABLE_MESSAGES) {\n key = getKey(tableName, { threadId: record.threadId, id: record.id });\n } else if (tableName === TABLE_WORKFLOW_SNAPSHOT) {\n key = getKey(tableName, {\n namespace: record.namespace || 'workflows',\n workflow_name: record.workflow_name,\n run_id: record.run_id,\n ...(record.resourceId ? { resourceId: record.resourceId } : {}),\n });\n } else {\n key = getKey(tableName, { id: record.id });\n }\n\n const processedRecord = {\n ...record,\n createdAt: serializeDate(record.createdAt as Date | string | undefined),\n updatedAt: serializeDate(record.updatedAt as Date | string | undefined),\n };\n\n return { key, processedRecord };\n}\n","import type { Client as ElasticSearchClient } from '@elastic/elasticsearch';\nimport { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';\nimport { createStorageErrorId } from '@mastra/core/storage';\nimport type { TABLE_NAMES } from '@mastra/core/storage';\n\nimport { getKey, processRecord } from './domains/utils';\n\nconst SEARCH_PAGE_SIZE = 1000;\n\n/**\n * Thin document-store layer over ElasticSearch.\n *\n * Each Mastra table maps to one ElasticSearch index (same name, already lowercase).\n * Records are stored as opaque JSON strings in a non-indexed `doc` field, with a\n * `key` keyword field (copy of `_id`) used for stable `search_after` pagination.\n *\n * ElasticSearch is near-real-time: all writes use `refresh: true` so\n * subsequent searches observe them, and point reads use `_get` by id (which is\n * real-time regardless of refresh).\n */\nexport class ElasticSearchDB {\n private client: ElasticSearchClient;\n private ensuredIndexes = new Set<string>();\n\n constructor({ client }: { client: ElasticSearchClient }) {\n this.client = client;\n }\n\n getClient(): ElasticSearchClient {\n return this.client;\n }\n\n async ensureIndex(tableName: TABLE_NAMES): Promise<void> {\n if (this.ensuredIndexes.has(tableName)) {\n return;\n }\n try {\n const exists = await this.client.indices.exists({ index: tableName });\n if (!exists) {\n await this.client.indices.create({\n index: tableName,\n mappings: {\n dynamic: false,\n properties: {\n key: { type: 'keyword' },\n doc: { type: 'text', index: false },\n },\n },\n });\n }\n this.ensuredIndexes.add(tableName);\n } catch (error: any) {\n const message = error?.message || error?.toString();\n if (message && message.toLowerCase().includes('already exists')) {\n this.ensuredIndexes.add(tableName);\n return;\n }\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'ENSURE_INDEX', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async insert({ tableName, record }: { tableName: TABLE_NAMES; record: Record<string, unknown> }): Promise<void> {\n const { key, processedRecord } = processRecord(tableName, record);\n await this.set({ tableName, key, value: processedRecord });\n }\n\n async set({\n tableName,\n key,\n value,\n }: {\n tableName: TABLE_NAMES;\n key: string;\n value: Record<string, unknown>;\n }): Promise<void> {\n await this.ensureIndex(tableName);\n try {\n await this.client.index({\n index: tableName,\n id: key,\n document: { key, doc: JSON.stringify(value) },\n refresh: true,\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'INSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async bulkSet({\n tableName,\n entries,\n }: {\n tableName: TABLE_NAMES;\n entries: Array<{ key: string; value: Record<string, unknown> }>;\n }): Promise<void> {\n if (entries.length === 0) {\n return;\n }\n await this.ensureIndex(tableName);\n try {\n const operations = entries.flatMap(({ key, value }) => [\n { index: { _index: tableName, _id: key } },\n { key, doc: JSON.stringify(value) },\n ]);\n const response = await this.client.bulk({ operations, refresh: true });\n if (response.errors) {\n const firstError = response.items.find(item => item.index?.error)?.index?.error;\n throw new Error(`Bulk write failed: ${firstError?.reason ?? 'unknown error'}`);\n }\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'BATCH_INSERT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async get<R>({ tableName, keys }: { tableName: TABLE_NAMES; keys: Record<string, string> }): Promise<R | null> {\n const key = getKey(tableName, keys);\n return this.getByKey<R>({ tableName, key });\n }\n\n async getByKey<R>({ tableName, key }: { tableName: TABLE_NAMES; key: string }): Promise<R | null> {\n await this.ensureIndex(tableName);\n try {\n const response = await this.client.get<{ doc: string }>({ index: tableName, id: key }, { ignore: [404] });\n if (!response.found || !response._source?.doc) {\n return null;\n }\n return JSON.parse(response._source.doc) as R;\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LOAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n /**\n * Returns all documents in a table, parsed. Uses `search_after` on the `key`\n * field for stable deep pagination.\n */\n async listAll<R>({ tableName, keyPrefix }: { tableName: TABLE_NAMES; keyPrefix?: string }): Promise<R[]> {\n const entries = await this.listAllEntries<R>({ tableName, keyPrefix });\n return entries.map(entry => entry.value);\n }\n\n /**\n * Returns all `{ key, value }` entries in a table (optionally filtered by key\n * prefix), using `search_after` pagination.\n */\n async listAllEntries<R>({\n tableName,\n keyPrefix,\n }: {\n tableName: TABLE_NAMES;\n keyPrefix?: string;\n }): Promise<Array<{ key: string; value: R }>> {\n await this.ensureIndex(tableName);\n try {\n const results: Array<{ key: string; value: R }> = [];\n let searchAfter: Array<string | number> | undefined;\n\n while (true) {\n const response = await this.client.search<{ key: string; doc: string }>({\n index: tableName,\n size: SEARCH_PAGE_SIZE,\n query: keyPrefix ? { prefix: { key: keyPrefix } } : { match_all: {} },\n sort: [{ key: 'asc' }],\n ...(searchAfter ? { search_after: searchAfter } : {}),\n });\n\n const hits = response.hits.hits;\n for (const hit of hits) {\n if (hit._source?.doc) {\n results.push({ key: hit._source.key, value: JSON.parse(hit._source.doc) as R });\n }\n }\n\n if (hits.length < SEARCH_PAGE_SIZE) {\n break;\n }\n searchAfter = hits[hits.length - 1]!.sort as Array<string | number>;\n }\n\n return results;\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SCAN', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async delete({ tableName, key }: { tableName: TABLE_NAMES; key: string }): Promise<void> {\n await this.ensureIndex(tableName);\n try {\n await this.client.delete({ index: tableName, id: key, refresh: true }, { ignore: [404] });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'DELETE', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async deleteMany({ tableName, keys }: { tableName: TABLE_NAMES; keys: string[] }): Promise<void> {\n if (keys.length === 0) {\n return;\n }\n await this.ensureIndex(tableName);\n try {\n await this.client.deleteByQuery({\n index: tableName,\n query: { terms: { key: keys } },\n refresh: true,\n conflicts: 'proceed',\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'DELETE_MANY', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n\n async deleteData({ tableName, keyPrefix }: { tableName: TABLE_NAMES; keyPrefix?: string }): Promise<void> {\n await this.ensureIndex(tableName);\n try {\n await this.client.deleteByQuery({\n index: tableName,\n query: keyPrefix ? { prefix: { key: keyPrefix } } : { match_all: {} },\n refresh: true,\n conflicts: 'proceed',\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'CLEAR_TABLE', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { tableName },\n },\n error,\n );\n }\n }\n}\n\nexport interface ElasticSearchDomainConfig {\n client: ElasticSearchClient;\n}\n","import { MessageList } from '@mastra/core/agent';\nimport type { MastraMessageContentV2 } from '@mastra/core/agent';\nimport { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';\nimport type { MastraDBMessage, StorageThreadType } from '@mastra/core/memory';\nimport {\n MemoryStorage,\n TABLE_RESOURCES,\n TABLE_THREADS,\n TABLE_MESSAGES,\n normalizePerPage,\n calculatePagination,\n createStorageErrorId,\n ensureDate,\n filterByDateRange,\n jsonValueEquals,\n storageMessageMatchesMetadataFilter,\n validateStorageMetadataFilter,\n} from '@mastra/core/storage';\nimport type {\n StorageResourceType,\n StorageListMessagesInput,\n StorageListMessagesOutput,\n StorageListThreadsInput,\n StorageListThreadsOutput,\n ThreadOrderBy,\n ThreadSortDirection,\n StorageCloneThreadInput,\n StorageCloneThreadOutput,\n ThreadCloneMetadata,\n} from '@mastra/core/storage';\n\nimport { ElasticSearchDB } from '../../db';\nimport type { ElasticSearchDomainConfig } from '../../db';\nimport { getKey, processRecord } from '../utils';\n\ntype StoredMessage = MastraDBMessage & { _index?: number };\n\nexport class MemoryElasticSearch extends MemoryStorage {\n override readonly supportsPartialThreadUpdate = true;\n private db: ElasticSearchDB;\n\n constructor(config: ElasticSearchDomainConfig) {\n super();\n this.db = new ElasticSearchDB({ client: config.client });\n }\n\n public async dangerouslyClearAll(): Promise<void> {\n await this.db.deleteData({ tableName: TABLE_THREADS });\n await this.db.deleteData({ tableName: TABLE_MESSAGES });\n await this.db.deleteData({ tableName: TABLE_RESOURCES });\n }\n\n public async getThreadById({\n threadId,\n resourceId,\n }: {\n threadId: string;\n resourceId?: string;\n }): Promise<StorageThreadType | null> {\n try {\n const thread = await this.db.get<StorageThreadType>({\n tableName: TABLE_THREADS,\n keys: { id: threadId },\n });\n\n if (!thread || (resourceId !== undefined && thread.resourceId !== resourceId)) {\n return null;\n }\n\n return {\n ...thread,\n createdAt: ensureDate(thread.createdAt)!,\n updatedAt: ensureDate(thread.updatedAt)!,\n metadata: typeof thread.metadata === 'string' ? JSON.parse(thread.metadata) : thread.metadata,\n };\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'GET_THREAD_BY_ID', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId,\n },\n },\n error,\n );\n }\n }\n\n public async listThreadsByResourceId(args: StorageListThreadsInput): Promise<StorageListThreadsOutput> {\n return this.listThreads(args);\n }\n\n public async listThreads(args: StorageListThreadsInput): Promise<StorageListThreadsOutput> {\n const { page = 0, perPage: perPageInput, orderBy, filter } = args;\n const { field, direction } = this.parseOrderBy(orderBy);\n\n try {\n this.validatePaginationInput(page, perPageInput ?? 100);\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_THREADS', 'INVALID_PAGE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { page, ...(perPageInput !== undefined && { perPage: perPageInput }) },\n },\n error instanceof Error ? error : new Error('Invalid pagination parameters'),\n );\n }\n\n const perPage = normalizePerPage(perPageInput, 100);\n\n try {\n this.validateMetadataKeys(filter?.metadata);\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_THREADS', 'INVALID_METADATA_KEY'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(', ') : '' },\n },\n error instanceof Error ? error : new Error('Invalid metadata key'),\n );\n }\n\n const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);\n\n try {\n const allThreads: StorageThreadType[] = [];\n const results = await this.db.listAll<StorageThreadType>({ tableName: TABLE_THREADS });\n\n for (const thread of results) {\n if (filter?.resourceId && thread.resourceId !== filter.resourceId) {\n continue;\n }\n\n if (filter?.metadata && Object.keys(filter.metadata).length > 0) {\n const threadMetadata = typeof thread.metadata === 'string' ? JSON.parse(thread.metadata) : thread.metadata;\n const matches = Object.entries(filter.metadata).every(([key, value]) =>\n jsonValueEquals(threadMetadata?.[key], value),\n );\n if (!matches) {\n continue;\n }\n }\n\n allThreads.push({\n ...thread,\n createdAt: ensureDate(thread.createdAt)!,\n updatedAt: ensureDate(thread.updatedAt)!,\n metadata: typeof thread.metadata === 'string' ? JSON.parse(thread.metadata) : thread.metadata,\n });\n }\n\n const sortedThreads = this.sortThreads(allThreads, field, direction);\n const total = sortedThreads.length;\n const end = perPageInput === false ? total : offset + perPage;\n const paginatedThreads = sortedThreads.slice(offset, end);\n const hasMore = perPageInput === false ? false : end < total;\n\n return {\n threads: paginatedThreads,\n total,\n page,\n perPage: perPageForResponse,\n hasMore,\n };\n } catch (error) {\n // Re-throw USER errors (validation errors) directly so callers get proper 400 responses\n if (error instanceof MastraError && error.category === ErrorCategory.USER) {\n throw error;\n }\n const mastraError = new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_THREADS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n ...(filter?.resourceId && { resourceId: filter.resourceId }),\n hasMetadataFilter: !!filter?.metadata,\n page,\n perPage,\n },\n },\n error,\n );\n this.logger.trackException(mastraError);\n this.logger.error(mastraError.toString());\n throw mastraError;\n }\n }\n\n public async saveThread({ thread }: { thread: StorageThreadType }): Promise<StorageThreadType> {\n try {\n await this.db.insert({\n tableName: TABLE_THREADS,\n record: thread,\n });\n return thread;\n } catch (error) {\n const mastraError = new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SAVE_THREAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId: thread.id,\n },\n },\n error,\n );\n this.logger.trackException(mastraError);\n this.logger.error(mastraError.toString());\n throw mastraError;\n }\n }\n\n public async updateThread({\n id,\n title,\n metadata,\n }: {\n id: string;\n title?: string;\n metadata?: Record<string, unknown>;\n }): Promise<StorageThreadType> {\n const thread = await this.getThreadById({ threadId: id });\n if (!thread) {\n throw new MastraError({\n id: createStorageErrorId('ELASTICSEARCH', 'UPDATE_THREAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: `Thread ${id} not found`,\n details: {\n threadId: id,\n },\n });\n }\n\n const updatedThread = {\n ...thread,\n title: title ?? thread.title,\n metadata: {\n ...thread.metadata,\n ...metadata,\n },\n updatedAt: new Date(),\n };\n\n try {\n await this.saveThread({ thread: updatedThread });\n return updatedThread;\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'UPDATE_THREAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId: id,\n },\n },\n error,\n );\n }\n }\n\n public async deleteThread({ threadId }: { threadId: string }): Promise<void> {\n try {\n const entries = await this.db.listAllEntries<StoredMessage>({\n tableName: TABLE_MESSAGES,\n keyPrefix: threadMessagesPrefix(threadId),\n });\n\n const keysToDelete = [\n ...entries.map(entry => entry.key),\n ...entries.map(entry => getMessageIndexKey(entry.value.id)),\n ];\n await this.db.deleteMany({ tableName: TABLE_MESSAGES, keys: keysToDelete });\n await this.db.delete({ tableName: TABLE_THREADS, key: getKey(TABLE_THREADS, { id: threadId }) });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'DELETE_THREAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId,\n },\n },\n error,\n );\n }\n }\n\n public async saveMessages(args: { messages: MastraDBMessage[] }): Promise<{ messages: MastraDBMessage[] }> {\n const { messages } = args;\n if (messages.length === 0) {\n return { messages: [] };\n }\n\n const threadId = messages[0]?.threadId;\n let existingThread: StorageThreadType | null = null;\n try {\n if (!threadId) {\n throw new Error('Thread ID is required');\n }\n existingThread = await this.getThreadById({ threadId });\n if (!existingThread) {\n throw new Error(`Thread ${threadId} not found`);\n }\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SAVE_MESSAGES', 'INVALID_ARGS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n },\n error,\n );\n }\n\n const messagesWithIndex = messages.map((message, index) => {\n if (!message.threadId) {\n throw new Error(\n `Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred.`,\n );\n }\n if (!message.resourceId) {\n throw new Error(\n `Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred.`,\n );\n }\n return {\n ...message,\n _index: index,\n };\n });\n\n try {\n const keysToDelete: string[] = [];\n const entries: Array<{ key: string; value: Record<string, unknown> }> = [];\n\n for (const message of messagesWithIndex) {\n const existingIndex = await this.db.getByKey<{ threadId: string }>({\n tableName: TABLE_MESSAGES,\n key: getMessageIndexKey(message.id),\n });\n\n if (existingIndex?.threadId && existingIndex.threadId !== message.threadId) {\n keysToDelete.push(getMessageKey(existingIndex.threadId, message.id));\n }\n\n entries.push({ key: getMessageKey(message.threadId!, message.id), value: message });\n entries.push({ key: getMessageIndexKey(message.id), value: { threadId: message.threadId! } });\n }\n\n await this.db.deleteMany({ tableName: TABLE_MESSAGES, keys: keysToDelete });\n await this.db.bulkSet({ tableName: TABLE_MESSAGES, entries });\n\n const updatedThread = {\n ...existingThread,\n updatedAt: new Date(),\n };\n await this.db.insert({ tableName: TABLE_THREADS, record: updatedThread });\n\n const list = new MessageList().add(messages as Parameters<MessageList['add']>[0], 'memory');\n return { messages: list.get.all.db() };\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SAVE_MESSAGES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId,\n },\n },\n error,\n );\n }\n }\n\n /**\n * Returns all messages that belong to a thread, sorted in insertion order\n * (createdAt with `_index` tiebreaker).\n */\n private async listThreadMessages(threadId: string): Promise<StoredMessage[]> {\n const messages = await this.db.listAll<StoredMessage>({\n tableName: TABLE_MESSAGES,\n keyPrefix: threadMessagesPrefix(threadId),\n });\n return messages.sort((a, b) => getMessageScore(a) - getMessageScore(b));\n }\n\n /** Returns all message documents across all threads (excludes index docs). */\n private async listAllMessages(): Promise<StoredMessage[]> {\n return this.db.listAll<StoredMessage>({\n tableName: TABLE_MESSAGES,\n keyPrefix: `${TABLE_MESSAGES}:threadId:`,\n });\n }\n\n private async getThreadIdForMessage(messageId: string): Promise<string | null> {\n const indexed = await this.db.getByKey<{ threadId: string }>({\n tableName: TABLE_MESSAGES,\n key: getMessageIndexKey(messageId),\n });\n if (indexed?.threadId) {\n return indexed.threadId;\n }\n\n const allMessages = await this.listAllMessages();\n const message = allMessages.find(msg => msg.id === messageId);\n if (!message) {\n return null;\n }\n\n if (message.threadId) {\n await this.db.set({\n tableName: TABLE_MESSAGES,\n key: getMessageIndexKey(messageId),\n value: { threadId: message.threadId },\n });\n }\n\n return message.threadId || null;\n }\n\n /**\n * Fetches the messages named by `include` together with their surrounding context.\n *\n * @param include - Message ids to pin, each with an optional before/after window.\n * @param resourceId - When set, drops any pinned or context message owned by another\n * resource so an id from another resource returns nothing.\n */\n private async getIncludedMessages(\n include: StorageListMessagesInput['include'],\n resourceId?: string,\n ): Promise<MastraDBMessage[]> {\n if (!include?.length) {\n return [];\n }\n\n const messagesById = new Map<string, StoredMessage>();\n\n for (const item of include) {\n const itemThreadId = await this.getThreadIdForMessage(item.id);\n if (!itemThreadId) {\n continue;\n }\n\n let threadMessages = await this.listThreadMessages(itemThreadId);\n\n if (resourceId !== undefined) {\n threadMessages = threadMessages.filter(message => message.resourceId === resourceId);\n }\n\n const targetIndex = threadMessages.findIndex(message => message.id === item.id);\n if (targetIndex === -1) {\n continue;\n }\n\n const start = Math.max(0, targetIndex - (item.withPreviousMessages ?? 0));\n const end = Math.min(threadMessages.length, targetIndex + (item.withNextMessages ?? 0) + 1);\n for (const message of threadMessages.slice(start, end)) {\n messagesById.set(message.id, message);\n }\n }\n\n return Array.from(messagesById.values());\n }\n\n private parseStoredMessage(storedMessage: StoredMessage): MastraDBMessage {\n const defaultMessageContent = { format: 2, parts: [{ type: 'text', text: '' }] };\n const { _index, ...rest } = storedMessage;\n return {\n ...rest,\n createdAt: new Date(rest.createdAt),\n content: rest.content || defaultMessageContent,\n } satisfies MastraDBMessage;\n }\n\n public async listMessagesById({ messageIds }: { messageIds: string[] }): Promise<{ messages: MastraDBMessage[] }> {\n if (messageIds.length === 0) {\n return { messages: [] };\n }\n\n try {\n const rawMessages: StoredMessage[] = [];\n const unindexedIds: string[] = [];\n\n for (const id of messageIds) {\n const indexed = await this.db.getByKey<{ threadId: string }>({\n tableName: TABLE_MESSAGES,\n key: getMessageIndexKey(id),\n });\n if (!indexed?.threadId) {\n unindexedIds.push(id);\n continue;\n }\n const message = await this.db.getByKey<StoredMessage>({\n tableName: TABLE_MESSAGES,\n key: getMessageKey(indexed.threadId, id),\n });\n if (message) {\n rawMessages.push(message);\n } else {\n unindexedIds.push(id);\n }\n }\n\n if (unindexedIds.length > 0) {\n const allMessages = await this.listAllMessages();\n const unindexedSet = new Set(unindexedIds);\n const foundMessages = allMessages.filter(msg => unindexedSet.has(msg.id));\n rawMessages.push(...foundMessages);\n\n if (foundMessages.length > 0) {\n await this.db.bulkSet({\n tableName: TABLE_MESSAGES,\n entries: foundMessages\n .filter(msg => msg.threadId)\n .map(msg => ({ key: getMessageIndexKey(msg.id), value: { threadId: msg.threadId! } })),\n });\n }\n }\n\n const list = new MessageList().add(rawMessages.map(this.parseStoredMessage), 'memory');\n return { messages: list.get.all.db() };\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_MESSAGES_BY_ID', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n messageIds: JSON.stringify(messageIds),\n },\n },\n error,\n );\n }\n }\n\n public async listMessages(args: StorageListMessagesInput): Promise<StorageListMessagesOutput> {\n const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;\n\n const threadIds = Array.isArray(threadId) ? threadId : [threadId];\n const threadIdsSet = new Set(threadIds);\n\n if (threadIds.length === 0 || threadIds.some(id => !id.trim())) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_MESSAGES', 'INVALID_THREAD_ID'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { threadId: Array.isArray(threadId) ? threadId.join(',') : threadId },\n },\n new Error('threadId must be a non-empty string or array of non-empty strings'),\n );\n }\n\n const perPage = normalizePerPage(perPageInput, 40);\n const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);\n const metadataFilter = validateStorageMetadataFilter(filter?.metadata);\n\n try {\n if (page < 0) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_MESSAGES', 'INVALID_PAGE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { page },\n },\n new Error('page must be >= 0'),\n );\n }\n\n const { field, direction } = this.parseOrderBy(orderBy, 'ASC');\n\n const getFieldValue = (msg: MastraDBMessage): number => {\n if (field === 'createdAt') {\n return new Date(msg.createdAt).getTime();\n }\n\n const value = (msg as Record<string, unknown>)[field];\n if (typeof value === 'number') {\n return value;\n }\n if (value instanceof Date) {\n return value.getTime();\n }\n return 0;\n };\n\n if (perPage === 0 && (!include || include.length === 0)) {\n return {\n messages: [],\n total: 0,\n page,\n perPage: perPageForResponse,\n hasMore: false,\n };\n }\n\n let includedMessages: MastraDBMessage[] = [];\n if (include && include.length > 0) {\n const included = await this.getIncludedMessages(include, resourceId);\n includedMessages = included.map(this.parseStoredMessage);\n }\n\n if (perPage === 0 && include && include.length > 0) {\n const list = new MessageList().add(includedMessages, 'memory');\n const messages = list.get.all.db().sort((a, b) => {\n const aValue = getFieldValue(a);\n const bValue = getFieldValue(b);\n return direction === 'ASC' ? aValue - bValue : bValue - aValue;\n });\n\n return {\n messages,\n total: 0,\n page,\n perPage: perPageForResponse,\n hasMore: false,\n };\n }\n\n let messagesData: MastraDBMessage[] = [];\n for (const tid of threadIds) {\n const threadMessages = await this.listThreadMessages(tid);\n messagesData.push(...threadMessages.map(this.parseStoredMessage));\n }\n\n if (messagesData.length === 0) {\n return {\n messages: [],\n total: 0,\n page,\n perPage: perPageForResponse,\n hasMore: false,\n };\n }\n\n if (resourceId) {\n messagesData = messagesData.filter(msg => msg.resourceId === resourceId);\n }\n\n messagesData = filterByDateRange(\n messagesData,\n (msg: MastraDBMessage) => new Date(msg.createdAt),\n filter?.dateRange,\n );\n\n messagesData = messagesData.filter(message =>\n storageMessageMatchesMetadataFilter(message.content, metadataFilter),\n );\n\n messagesData.sort((a, b) => {\n const aValue = getFieldValue(a);\n const bValue = getFieldValue(b);\n return direction === 'ASC' ? aValue - bValue : bValue - aValue;\n });\n\n const total = messagesData.length;\n const start = offset;\n const end = perPageInput === false ? total : start + perPage;\n const paginatedMessages = messagesData.slice(start, end);\n\n const messageIdsSet = new Set<string>();\n const allMessages: MastraDBMessage[] = [];\n\n for (const msg of paginatedMessages) {\n if (messageIdsSet.has(msg.id)) {\n continue;\n }\n allMessages.push(msg);\n messageIdsSet.add(msg.id);\n }\n\n for (const msg of includedMessages) {\n if (messageIdsSet.has(msg.id)) {\n continue;\n }\n allMessages.push(msg);\n messageIdsSet.add(msg.id);\n }\n\n const list = new MessageList().add(allMessages, 'memory');\n let finalMessages = list.get.all.db();\n\n finalMessages = finalMessages.sort((a, b) => {\n const aValue = getFieldValue(a);\n const bValue = getFieldValue(b);\n return direction === 'ASC' ? aValue - bValue : bValue - aValue;\n });\n\n const returnedThreadMessageIds = new Set(\n finalMessages\n .filter(message => message.threadId && threadIdsSet.has(message.threadId))\n .map(message => message.id),\n );\n const hasMore =\n perPageInput !== false &&\n (metadataFilter || returnedThreadMessageIds.size < total) &&\n offset + paginatedMessages.length < total;\n\n return {\n messages: finalMessages,\n total,\n page,\n perPage: perPageForResponse,\n hasMore,\n };\n } catch (error) {\n // Re-throw USER errors (validation errors) directly so callers get proper 400 responses\n if (error instanceof MastraError && error.category === ErrorCategory.USER) {\n throw error;\n }\n const mastraError = new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_MESSAGES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n threadId: Array.isArray(threadId) ? threadId.join(',') : threadId,\n resourceId: resourceId ?? '',\n },\n },\n error,\n );\n this.logger.error(mastraError.toString());\n this.logger.trackException(mastraError);\n throw mastraError;\n }\n }\n\n public async getResourceById({ resourceId }: { resourceId: string }): Promise<StorageResourceType | null> {\n try {\n const resource = await this.db.getByKey<StorageResourceType>({\n tableName: TABLE_RESOURCES,\n key: `${TABLE_RESOURCES}:${resourceId}`,\n });\n if (!resource) {\n return null;\n }\n\n return {\n ...resource,\n createdAt: new Date(resource.createdAt),\n updatedAt: new Date(resource.updatedAt),\n workingMemory:\n typeof resource.workingMemory === 'object' ? JSON.stringify(resource.workingMemory) : resource.workingMemory,\n metadata: typeof resource.metadata === 'string' ? JSON.parse(resource.metadata) : resource.metadata,\n };\n } catch (error) {\n this.logger.error('Error getting resource by ID:', error);\n throw error;\n }\n }\n\n public async saveResource({ resource }: { resource: StorageResourceType }): Promise<StorageResourceType> {\n try {\n const serializedResource = {\n ...resource,\n metadata: JSON.stringify(resource.metadata),\n createdAt: resource.createdAt.toISOString(),\n updatedAt: resource.updatedAt.toISOString(),\n };\n\n await this.db.set({\n tableName: TABLE_RESOURCES,\n key: `${TABLE_RESOURCES}:${resource.id}`,\n value: serializedResource,\n });\n\n return resource;\n } catch (error) {\n this.logger.error('Error saving resource:', error);\n throw error;\n }\n }\n\n public async updateResource({\n resourceId,\n workingMemory,\n metadata,\n }: {\n resourceId: string;\n workingMemory?: string;\n metadata?: Record<string, unknown>;\n }): Promise<StorageResourceType> {\n try {\n const existingResource = await this.getResourceById({ resourceId });\n\n if (!existingResource) {\n const newResource: StorageResourceType = {\n id: resourceId,\n workingMemory,\n metadata: metadata || {},\n createdAt: new Date(),\n updatedAt: new Date(),\n };\n return this.saveResource({ resource: newResource });\n }\n\n const updatedResource = {\n ...existingResource,\n workingMemory: workingMemory !== undefined ? workingMemory : existingResource.workingMemory,\n metadata: {\n ...existingResource.metadata,\n ...metadata,\n },\n updatedAt: new Date(),\n };\n\n await this.saveResource({ resource: updatedResource });\n return updatedResource;\n } catch (error) {\n this.logger.error('Error updating resource:', error);\n throw error;\n }\n }\n\n public async updateMessages(args: {\n messages: (Partial<Omit<MastraDBMessage, 'createdAt'>> & {\n id: string;\n content?: { metadata?: MastraMessageContentV2['metadata']; content?: MastraMessageContentV2['content'] };\n })[];\n }): Promise<MastraDBMessage[]> {\n const { messages } = args;\n if (messages.length === 0) {\n return [];\n }\n\n try {\n const messageIds = messages.map(m => m.id);\n const allMessages = await this.listAllMessages();\n const existingMessages: StoredMessage[] = [];\n const messageIdToKey: Record<string, string> = {};\n\n for (const messageId of messageIds) {\n const message = allMessages.find(msg => msg.id === messageId);\n if (message?.threadId) {\n existingMessages.push(message);\n messageIdToKey[messageId] = getMessageKey(message.threadId, messageId);\n }\n }\n\n if (existingMessages.length === 0) {\n return [];\n }\n\n const threadIdsToUpdate = new Set<string>();\n const keysToDelete: string[] = [];\n const entries: Array<{ key: string; value: Record<string, unknown> }> = [];\n\n for (const existingMessage of existingMessages) {\n const updatePayload = messages.find(m => m.id === existingMessage.id);\n if (!updatePayload) {\n continue;\n }\n\n const { id, ...fieldsToUpdate } = updatePayload;\n if (Object.keys(fieldsToUpdate).length === 0) {\n continue;\n }\n\n threadIdsToUpdate.add(existingMessage.threadId!);\n if (updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {\n threadIdsToUpdate.add(updatePayload.threadId);\n }\n\n const updatedMessage = { ...existingMessage };\n\n if (fieldsToUpdate.content) {\n const existingContent = existingMessage.content as MastraMessageContentV2;\n const newContent = {\n ...existingContent,\n ...fieldsToUpdate.content,\n ...(existingContent?.metadata && fieldsToUpdate.content.metadata\n ? {\n metadata: {\n ...existingContent.metadata,\n ...fieldsToUpdate.content.metadata,\n },\n }\n : {}),\n };\n updatedMessage.content = newContent;\n }\n\n for (const key in fieldsToUpdate) {\n if (Object.prototype.hasOwnProperty.call(fieldsToUpdate, key) && key !== 'content') {\n (updatedMessage as Record<string, unknown>)[key] = fieldsToUpdate[key as keyof typeof fieldsToUpdate];\n }\n }\n\n const key = messageIdToKey[id];\n if (!key) {\n continue;\n }\n\n if (updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {\n keysToDelete.push(key);\n\n const newKey = getMessageKey(updatePayload.threadId, id);\n entries.push({ key: newKey, value: updatedMessage });\n entries.push({ key: getMessageIndexKey(id), value: { threadId: updatePayload.threadId } });\n\n messageIdToKey[id] = newKey;\n continue;\n }\n\n entries.push({ key, value: updatedMessage });\n }\n\n const now = new Date();\n const threadEntries: Array<{ key: string; value: Record<string, unknown> }> = [];\n for (const threadId of threadIdsToUpdate) {\n if (threadId) {\n const existingThread = await this.db.get<StorageThreadType>({\n tableName: TABLE_THREADS,\n keys: { id: threadId },\n });\n if (existingThread) {\n const updatedThread = {\n ...existingThread,\n updatedAt: now,\n };\n threadEntries.push({\n key: getKey(TABLE_THREADS, { id: threadId }),\n value: processRecord(TABLE_THREADS, updatedThread).processedRecord,\n });\n }\n }\n }\n\n await this.db.deleteMany({ tableName: TABLE_MESSAGES, keys: keysToDelete });\n await this.db.bulkSet({ tableName: TABLE_MESSAGES, entries });\n await this.db.bulkSet({ tableName: TABLE_THREADS, entries: threadEntries });\n\n const updatedMessages: MastraDBMessage[] = [];\n for (const messageId of messageIds) {\n const key = messageIdToKey[messageId];\n if (key) {\n const message = await this.db.getByKey<MastraDBMessage>({ tableName: TABLE_MESSAGES, key });\n if (message) {\n updatedMessages.push(message);\n }\n }\n }\n\n return updatedMessages;\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'UPDATE_MESSAGES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n messageIds: messages.map(m => m.id).join(','),\n },\n },\n error,\n );\n }\n }\n\n public async deleteMessages(messageIds: string[]): Promise<void> {\n if (!messageIds || messageIds.length === 0) {\n return;\n }\n\n try {\n const allMessages = await this.listAllMessages();\n const idsToDelete = new Set(messageIds);\n const threadIds = new Set<string>();\n const keysToDelete: string[] = [];\n\n for (const message of allMessages) {\n if (!idsToDelete.has(message.id) || !message.threadId) {\n continue;\n }\n keysToDelete.push(getMessageKey(message.threadId, message.id));\n keysToDelete.push(getMessageIndexKey(message.id));\n threadIds.add(message.threadId);\n }\n\n if (keysToDelete.length === 0) {\n return;\n }\n\n await this.db.deleteMany({ tableName: TABLE_MESSAGES, keys: keysToDelete });\n\n const threadEntries: Array<{ key: string; value: Record<string, unknown> }> = [];\n for (const threadId of threadIds) {\n const thread = await this.db.get<StorageThreadType>({ tableName: TABLE_THREADS, keys: { id: threadId } });\n if (!thread) {\n continue;\n }\n const updatedThread = { ...thread, updatedAt: new Date() };\n threadEntries.push({\n key: getKey(TABLE_THREADS, { id: threadId }),\n value: processRecord(TABLE_THREADS, updatedThread).processedRecord,\n });\n }\n await this.db.bulkSet({ tableName: TABLE_THREADS, entries: threadEntries });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'DELETE_MESSAGES', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { messageIds: messageIds.join(', ') },\n },\n error,\n );\n }\n }\n\n private sortThreads(\n threads: StorageThreadType[],\n field: ThreadOrderBy,\n direction: ThreadSortDirection,\n ): StorageThreadType[] {\n return threads.sort((a, b) => {\n const aValue = new Date(a[field]).getTime();\n const bValue = new Date(b[field]).getTime();\n return direction === 'ASC' ? aValue - bValue : bValue - aValue;\n });\n }\n\n public async cloneThread(args: StorageCloneThreadInput): Promise<StorageCloneThreadOutput> {\n const { sourceThreadId, newThreadId: providedThreadId, resourceId, title, metadata, options } = args;\n\n const sourceThread = await this.getThreadById({ threadId: sourceThreadId });\n if (!sourceThread) {\n throw new MastraError({\n id: createStorageErrorId('ELASTICSEARCH', 'CLONE_THREAD', 'SOURCE_NOT_FOUND'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: `Source thread with id ${sourceThreadId} not found`,\n details: { sourceThreadId },\n });\n }\n\n const newThreadId = providedThreadId || crypto.randomUUID();\n\n const existingThread = await this.getThreadById({ threadId: newThreadId });\n if (existingThread) {\n throw new MastraError({\n id: createStorageErrorId('ELASTICSEARCH', 'CLONE_THREAD', 'THREAD_EXISTS'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: `Thread with id ${newThreadId} already exists`,\n details: { newThreadId },\n });\n }\n\n try {\n let sourceMessages: StoredMessage[] = (await this.listThreadMessages(sourceThreadId)).map(msg => ({\n ...msg,\n createdAt: new Date(msg.createdAt),\n }));\n\n if (options?.messageFilter?.startDate || options?.messageFilter?.endDate) {\n sourceMessages = filterByDateRange(sourceMessages, (msg: MastraDBMessage) => new Date(msg.createdAt), {\n start: options.messageFilter?.startDate,\n end: options.messageFilter?.endDate,\n });\n }\n\n if (options?.messageFilter?.messageIds && options.messageFilter.messageIds.length > 0) {\n const messageIdSet = new Set(options.messageFilter.messageIds);\n sourceMessages = sourceMessages.filter(msg => messageIdSet.has(msg.id));\n }\n\n sourceMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());\n\n if (options?.messageLimit && options.messageLimit > 0 && sourceMessages.length > options.messageLimit) {\n sourceMessages = sourceMessages.slice(-options.messageLimit);\n }\n\n const now = new Date();\n const lastMessageId = sourceMessages.length > 0 ? sourceMessages[sourceMessages.length - 1]!.id : undefined;\n\n const cloneMetadata: ThreadCloneMetadata = {\n sourceThreadId,\n clonedAt: now,\n ...(lastMessageId && { lastMessageId }),\n };\n\n const newThread: StorageThreadType = {\n id: newThreadId,\n resourceId: resourceId || sourceThread.resourceId,\n title: title || (sourceThread.title ? `Clone of ${sourceThread.title}` : undefined),\n metadata: { ...metadata, clone: cloneMetadata },\n createdAt: now,\n updatedAt: now,\n };\n\n const clonedMessages: MastraDBMessage[] = [];\n const targetResourceId = resourceId || sourceThread.resourceId;\n const entries: Array<{ key: string; value: Record<string, unknown> }> = [];\n\n for (let i = 0; i < sourceMessages.length; i++) {\n const sourceMsg = sourceMessages[i]!;\n const newMessageId = crypto.randomUUID();\n const { _index, ...restMsg } = sourceMsg;\n\n const newMessage: MastraDBMessage = {\n ...restMsg,\n id: newMessageId,\n threadId: newThreadId,\n resourceId: targetResourceId,\n };\n\n entries.push({ key: getMessageKey(newThreadId, newMessageId), value: { ...newMessage, _index: i } });\n entries.push({ key: getMessageIndexKey(newMessageId), value: { threadId: newThreadId } });\n\n clonedMessages.push(newMessage);\n }\n\n await this.db.insert({ tableName: TABLE_THREADS, record: newThread });\n await this.db.bulkSet({ tableName: TABLE_MESSAGES, entries });\n\n return {\n thread: newThread,\n clonedMessages,\n };\n } catch (error) {\n if (error instanceof MastraError) {\n throw error;\n }\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'CLONE_THREAD', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { sourceThreadId, newThreadId },\n },\n error,\n );\n }\n }\n}\n\nfunction threadMessagesPrefix(threadId: string): string {\n return `${TABLE_MESSAGES}:threadId:${threadId}:id:`;\n}\n\nfunction getMessageKey(threadId: string, messageId: string): string {\n return getKey(TABLE_MESSAGES, { threadId, id: messageId });\n}\n\nfunction getMessageIndexKey(messageId: string): string {\n return `msg-idx:${messageId}`;\n}\n\nfunction getMessageScore(message: { createdAt: Date | string; _index?: number }): number {\n const createdAtScore = new Date(message.createdAt).getTime();\n const index = typeof message._index === 'number' ? message._index : 0;\n return createdAtScore * 1000 + index;\n}\n","import crypto from 'node:crypto';\nimport { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';\nimport type { SaveScorePayload, ScoreRowData, ScoringSource } from '@mastra/core/evals';\nimport { saveScorePayloadSchema } from '@mastra/core/evals';\nimport {\n calculatePagination,\n normalizePerPage,\n ScoresStorage,\n TABLE_SCORERS,\n transformScoreRow,\n createStorageErrorId,\n} from '@mastra/core/storage';\nimport type { PaginationInfo, StoragePagination, ScoreTenancyFilters } from '@mastra/core/storage';\n\nimport { ElasticSearchDB } from '../../db';\nimport type { ElasticSearchDomainConfig } from '../../db';\nimport { processRecord } from '../utils';\n\n/** Returns true when a row matches the multi-tenant scope filters (or none provided). */\nfunction matchesTenancy(row: Record<string, unknown>, filters?: ScoreTenancyFilters): boolean {\n if (filters?.organizationId !== undefined && row.organizationId !== filters.organizationId) return false;\n if (filters?.projectId !== undefined && row.projectId !== filters.projectId) return false;\n return true;\n}\n\nexport class ScoresElasticSearch extends ScoresStorage {\n private db: ElasticSearchDB;\n\n constructor(config: ElasticSearchDomainConfig) {\n super();\n this.db = new ElasticSearchDB({ client: config.client });\n }\n\n public async dangerouslyClearAll(): Promise<void> {\n await this.db.deleteData({ tableName: TABLE_SCORERS });\n }\n\n public async getScoreById({ id }: { id: string }): Promise<ScoreRowData | null> {\n try {\n const data = await this.db.get<ScoreRowData>({\n tableName: TABLE_SCORERS,\n keys: { id },\n });\n\n if (!data) {\n return null;\n }\n\n return transformScoreRow(data as Record<string, unknown>);\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'GET_SCORE_BY_ID', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n ...(id && { id }),\n },\n },\n error,\n );\n }\n }\n\n public async listScoresByScorerId({\n scorerId,\n entityId,\n entityType,\n source,\n pagination = { page: 0, perPage: 20 },\n filters,\n }: {\n scorerId: string;\n entityId?: string;\n entityType?: string;\n source?: ScoringSource;\n pagination?: StoragePagination;\n filters?: ScoreTenancyFilters;\n }): Promise<{\n scores: ScoreRowData[];\n pagination: PaginationInfo;\n }> {\n return this.fetchAndFilterScores(pagination, row => {\n if (row.scorerId !== scorerId) {\n return false;\n }\n if (entityId && row.entityId !== entityId) {\n return false;\n }\n if (entityType && row.entityType !== entityType) {\n return false;\n }\n if (source && row.source !== source) {\n return false;\n }\n if (!matchesTenancy(row, filters)) {\n return false;\n }\n return true;\n });\n }\n\n public async saveScore(score: SaveScorePayload): Promise<{ score: ScoreRowData }> {\n let validatedScore: SaveScorePayload;\n try {\n validatedScore = saveScorePayloadSchema.parse(score);\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SAVE_SCORE', 'VALIDATION_FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: {\n scorer: typeof score.scorer?.id === 'string' ? score.scorer.id : String(score.scorer?.id ?? 'unknown'),\n entityId: score.entityId ?? 'unknown',\n entityType: score.entityType ?? 'unknown',\n traceId: score.traceId ?? '',\n spanId: score.spanId ?? '',\n },\n },\n error,\n );\n }\n\n const now = new Date();\n const id = crypto.randomUUID();\n\n const scoreWithId = {\n ...validatedScore,\n id,\n createdAt: now,\n updatedAt: now,\n };\n\n const { key, processedRecord } = processRecord(TABLE_SCORERS, scoreWithId);\n try {\n await this.db.set({ tableName: TABLE_SCORERS, key, value: processedRecord });\n return { score: { ...validatedScore, id, createdAt: now, updatedAt: now } as ScoreRowData };\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'SAVE_SCORE', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { id },\n },\n error,\n );\n }\n }\n\n public async listScoresByRunId({\n runId,\n pagination = { page: 0, perPage: 20 },\n filters,\n }: {\n runId: string;\n pagination?: StoragePagination;\n filters?: ScoreTenancyFilters;\n }): Promise<{\n scores: ScoreRowData[];\n pagination: PaginationInfo;\n }> {\n return this.fetchAndFilterScores(pagination, row => row.runId === runId && matchesTenancy(row, filters));\n }\n\n public async listScoresByEntityId({\n entityId,\n entityType,\n pagination = { page: 0, perPage: 20 },\n filters,\n }: {\n entityId: string;\n entityType?: string;\n pagination?: StoragePagination;\n filters?: ScoreTenancyFilters;\n }): Promise<{\n scores: ScoreRowData[];\n pagination: PaginationInfo;\n }> {\n return this.fetchAndFilterScores(pagination, row => {\n if (row.entityId !== entityId) {\n return false;\n }\n if (entityType && row.entityType !== entityType) {\n return false;\n }\n if (!matchesTenancy(row, filters)) {\n return false;\n }\n return true;\n });\n }\n\n public async listScoresBySpan({\n traceId,\n spanId,\n pagination = { page: 0, perPage: 20 },\n filters,\n }: {\n traceId: string;\n spanId: string;\n pagination?: StoragePagination;\n filters?: ScoreTenancyFilters;\n }): Promise<{\n scores: ScoreRowData[];\n pagination: PaginationInfo;\n }> {\n return this.fetchAndFilterScores(\n pagination,\n row => row.traceId === traceId && row.spanId === spanId && matchesTenancy(row, filters),\n );\n }\n\n private async fetchAndFilterScores(\n pagination: StoragePagination,\n filterFn: (row: Record<string, unknown>) => boolean,\n ): Promise<{ scores: ScoreRowData[]; pagination: PaginationInfo }> {\n const { page, perPage: perPageInput } = pagination;\n const rows = await this.db.listAll<Record<string, unknown>>({ tableName: TABLE_SCORERS });\n\n const filtered = rows.filter(\n (row): row is Record<string, unknown> => !!row && typeof row === 'object' && filterFn(row),\n );\n\n const total = filtered.length;\n const perPage = normalizePerPage(perPageInput, 100);\n const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);\n const end = perPageInput === false ? total : start + perPage;\n const scores = filtered.slice(start, end).map(row => transformScoreRow(row));\n\n return {\n scores,\n pagination: {\n total,\n page,\n perPage: perPageForResponse,\n hasMore: end < total,\n },\n };\n }\n}\n","import { ErrorCategory, ErrorDomain, MastraError } from '@mastra/core/error';\nimport {\n createStorageErrorId,\n normalizePerPage,\n TABLE_WORKFLOW_SNAPSHOT,\n matchesExpectedWorkflowStatus,\n WorkflowsStorage,\n ensureDate,\n} from '@mastra/core/storage';\nimport type {\n StorageListWorkflowRunsInput,\n WorkflowRun,\n WorkflowRuns,\n UpdateWorkflowStateOptions,\n} from '@mastra/core/storage';\nimport type { StepResult, WorkflowRunState } from '@mastra/core/workflows';\n\nimport { ElasticSearchDB } from '../../db';\nimport type { ElasticSearchDomainConfig } from '../../db';\nimport { getKey } from '../utils';\n\ntype WorkflowSnapshotRecord = {\n namespace: string;\n workflow_name: string;\n run_id: string;\n resourceId?: string;\n snapshot: WorkflowRunState;\n createdAt: string | Date;\n updatedAt: string | Date;\n};\n\nfunction parseWorkflowRun(row: Record<string, unknown>): WorkflowRun {\n let parsedSnapshot: WorkflowRunState | string = row.snapshot as string;\n if (typeof parsedSnapshot === 'string') {\n try {\n parsedSnapshot = JSON.parse(row.snapshot as string) as WorkflowRunState;\n } catch (e) {\n console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);\n }\n }\n\n return {\n workflowName: row.workflow_name as string,\n runId: row.run_id as string,\n snapshot: parsedSnapshot,\n createdAt: ensureDate(row.createdAt as string | Date)!,\n updatedAt: ensureDate(row.updatedAt as string | Date)!,\n resourceId: row.resourceId as string | undefined,\n };\n}\n\nexport class WorkflowsElasticSearch extends WorkflowsStorage {\n private db: ElasticSearchDB;\n\n constructor(config: ElasticSearchDomainConfig) {\n super();\n this.db = new ElasticSearchDB({ client: config.client });\n }\n\n public supportsConcurrentUpdates(): boolean {\n return false;\n }\n\n public async dangerouslyClearAll(): Promise<void> {\n await this.db.deleteData({ tableName: TABLE_WORKFLOW_SNAPSHOT });\n }\n\n public async updateWorkflowResults({\n workflowName,\n runId,\n stepId,\n result,\n requestContext,\n }: {\n workflowName: string;\n runId: string;\n stepId: string;\n result: StepResult<unknown, unknown, unknown, unknown>;\n requestContext: Record<string, unknown>;\n }): Promise<Record<string, StepResult<unknown, unknown, unknown, unknown>>> {\n try {\n const existingRecord = await this.db.get<WorkflowSnapshotRecord>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keys: {\n namespace: 'workflows',\n workflow_name: workflowName,\n run_id: runId,\n },\n });\n\n const existingSnapshot = existingRecord?.snapshot;\n let snapshot = existingSnapshot;\n\n if (!snapshot) {\n snapshot = {\n context: {},\n activePaths: [],\n timestamp: Date.now(),\n suspendedPaths: {},\n activeStepsPath: {},\n resumeLabels: {},\n serializedStepGraph: [],\n status: 'pending',\n value: {},\n waitingPaths: {},\n runId,\n requestContext: {},\n } as WorkflowRunState;\n }\n\n snapshot.context[stepId] = result;\n snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };\n\n await this.persistWorkflowSnapshot({\n namespace: 'workflows',\n workflowName,\n runId,\n snapshot,\n createdAt: existingRecord?.createdAt ? ensureDate(existingRecord.createdAt) : undefined,\n });\n\n return snapshot.context;\n } catch (error) {\n if (error instanceof MastraError) {\n throw error;\n }\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'UPDATE_WORKFLOW_RESULTS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { workflowName, runId, stepId },\n },\n error,\n );\n }\n }\n\n public async updateWorkflowState({\n workflowName,\n runId,\n opts,\n }: {\n workflowName: string;\n runId: string;\n opts: UpdateWorkflowStateOptions;\n }): Promise<WorkflowRunState | undefined> {\n try {\n const existingRecord = await this.db.get<WorkflowSnapshotRecord>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keys: {\n namespace: 'workflows',\n workflow_name: workflowName,\n run_id: runId,\n },\n });\n\n const existingSnapshot = existingRecord?.snapshot;\n\n if (!existingSnapshot || !existingSnapshot.context) {\n return undefined;\n }\n\n // Best-effort only: this store reports `supportsConcurrentUpdates() === false`, so the\n // read and the write are not a single critical section.\n const { expectedStatus, ...state } = opts;\n if (!matchesExpectedWorkflowStatus(existingSnapshot.status, expectedStatus)) {\n return undefined;\n }\n\n const updatedSnapshot = { ...existingSnapshot, ...state };\n\n await this.persistWorkflowSnapshot({\n namespace: 'workflows',\n workflowName,\n runId,\n snapshot: updatedSnapshot,\n createdAt: existingRecord?.createdAt ? ensureDate(existingRecord.createdAt) : undefined,\n });\n\n return updatedSnapshot;\n } catch (error) {\n if (error instanceof MastraError) {\n throw error;\n }\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'UPDATE_WORKFLOW_STATE', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: { workflowName, runId },\n },\n error,\n );\n }\n }\n\n public async persistWorkflowSnapshot(params: {\n namespace?: string;\n workflowName: string;\n runId: string;\n resourceId?: string;\n snapshot: WorkflowRunState;\n createdAt?: Date;\n updatedAt?: Date;\n }): Promise<void> {\n const { namespace = 'workflows', workflowName, runId, resourceId, snapshot, createdAt, updatedAt } = params;\n try {\n let finalCreatedAt = createdAt;\n if (!finalCreatedAt) {\n const existing = await this.db.get<WorkflowSnapshotRecord>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keys: {\n namespace,\n workflow_name: workflowName,\n run_id: runId,\n },\n });\n finalCreatedAt = existing?.createdAt ? ensureDate(existing.createdAt) : new Date();\n }\n\n await this.db.insert({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n record: {\n namespace,\n workflow_name: workflowName,\n run_id: runId,\n resourceId,\n snapshot,\n createdAt: finalCreatedAt,\n updatedAt: updatedAt ?? new Date(),\n },\n });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'PERSIST_WORKFLOW_SNAPSHOT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n namespace,\n workflowName,\n runId,\n },\n },\n error,\n );\n }\n }\n\n public async loadWorkflowSnapshot(params: {\n namespace: string;\n workflowName: string;\n runId: string;\n }): Promise<WorkflowRunState | null> {\n const { namespace = 'workflows', workflowName, runId } = params;\n try {\n const record = await this.db.get<WorkflowSnapshotRecord>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keys: {\n namespace,\n workflow_name: workflowName,\n run_id: runId,\n },\n });\n return record?.snapshot ?? null;\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LOAD_WORKFLOW_SNAPSHOT', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n namespace,\n workflowName,\n runId,\n },\n },\n error,\n );\n }\n }\n\n public async getWorkflowRunById({\n runId,\n workflowName,\n }: {\n runId: string;\n workflowName?: string;\n }): Promise<WorkflowRun | null> {\n try {\n const records = await this.db.listAll<WorkflowSnapshotRecord>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keyPrefix: getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: 'workflows' }),\n });\n\n const data = records.find(workflow => {\n if (!workflow) {\n return false;\n }\n\n const runIdMatch = workflow.run_id === runId;\n\n if (workflowName) {\n return runIdMatch && workflow.workflow_name === workflowName;\n }\n\n return runIdMatch;\n });\n\n if (!data) {\n return null;\n }\n\n return parseWorkflowRun(data as Record<string, unknown>);\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'GET_WORKFLOW_RUN_BY_ID', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n namespace: 'workflows',\n runId,\n workflowName: workflowName || '',\n },\n },\n error,\n );\n }\n }\n\n public async deleteWorkflowRunById({ runId, workflowName }: { runId: string; workflowName: string }): Promise<void> {\n const key = getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: 'workflows', workflow_name: workflowName, run_id: runId });\n try {\n await this.db.delete({ tableName: TABLE_WORKFLOW_SNAPSHOT, key });\n } catch (error) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'DELETE_WORKFLOW_RUN_BY_ID', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n namespace: 'workflows',\n runId,\n workflowName,\n },\n },\n error,\n );\n }\n }\n\n public async listWorkflowRuns({\n workflowName,\n fromDate,\n toDate,\n perPage,\n page,\n resourceId,\n status,\n }: StorageListWorkflowRunsInput = {}): Promise<WorkflowRuns> {\n try {\n if (page !== undefined && page < 0) {\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_WORKFLOW_RUNS', 'INVALID_PAGE'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n details: { page },\n },\n new Error('page must be >= 0'),\n );\n }\n\n const normalizedFrom = fromDate ? ensureDate(fromDate) : undefined;\n const normalizedTo = toDate ? ensureDate(toDate) : undefined;\n\n let keyPrefix = getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: 'workflows' });\n if (workflowName) {\n keyPrefix = getKey(TABLE_WORKFLOW_SNAPSHOT, { namespace: 'workflows', workflow_name: workflowName }) + ':';\n }\n const records = await this.db.listAll<Record<string, unknown>>({\n tableName: TABLE_WORKFLOW_SNAPSHOT,\n keyPrefix,\n });\n\n let runs = records\n .filter(\n (record): record is Record<string, unknown> =>\n record !== null && record !== undefined && typeof record === 'object' && 'workflow_name' in record,\n )\n .filter(record => !workflowName || record.workflow_name === workflowName)\n .filter(record => !resourceId || record.resourceId === resourceId)\n .map(w => parseWorkflowRun(w))\n .filter(w => {\n if (normalizedFrom && w.createdAt < normalizedFrom) {\n return false;\n }\n if (normalizedTo && w.createdAt > normalizedTo) {\n return false;\n }\n if (status) {\n let snapshot = w.snapshot;\n if (typeof snapshot === 'string') {\n try {\n snapshot = JSON.parse(snapshot) as WorkflowRunState;\n } catch (e) {\n console.warn(`Failed to parse snapshot for workflow ${w.workflowName}: ${e}`);\n return false;\n }\n }\n return snapshot.status === status;\n }\n return true;\n })\n .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());\n\n const total = runs.length;\n\n if (typeof perPage === 'number' && typeof page === 'number') {\n const normalizedPerPage = normalizePerPage(perPage, Number.MAX_SAFE_INTEGER);\n const offset = page * normalizedPerPage;\n runs = runs.slice(offset, offset + normalizedPerPage);\n }\n\n return { runs, total };\n } catch (error) {\n if (error instanceof MastraError) {\n throw error;\n }\n throw new MastraError(\n {\n id: createStorageErrorId('ELASTICSEARCH', 'LIST_WORKFLOW_RUNS', 'FAILED'),\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.THIRD_PARTY,\n details: {\n namespace: 'workflows',\n workflowName: workflowName || '',\n resourceId: resourceId || '',\n },\n },\n error,\n );\n }\n }\n}\n","import { Client as ElasticSearchClient } from '@elastic/elasticsearch';\nimport { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { MastraStorage } from '@mastra/core/storage';\nimport type { StorageDomains } from '@mastra/core/storage';\n\nimport packageJson from '../../package.json';\nimport { MemoryElasticSearch } from './domains/memory';\nimport { ScoresElasticSearch } from './domains/scores';\nimport { WorkflowsElasticSearch } from './domains/workflows';\nimport type { ElasticSearchConfig } from './types';\n\n/**\n * ElasticSearch storage adapter for Mastra.\n *\n * Implements the memory, workflows, and scores storage domains on top of\n * ElasticSearch. Shares the same connection config surface as\n * `ElasticSearchVector`, so both can reuse one client or connection config.\n *\n * @example\n * ```typescript\n * // Using connection parameters\n * const storage = new ElasticSearchStore({\n * id: 'my-store',\n * url: 'http://localhost:9200',\n * auth: { apiKey: '...' },\n * });\n *\n * // Access memory domain\n * const memory = await storage.getStore('memory');\n * await memory?.saveThread({ thread });\n * ```\n *\n * @example\n * ```typescript\n * // Using a pre-configured client shared with ElasticSearchVector\n * import { Client } from '@elastic/elasticsearch';\n *\n * const client = new Client({ node: 'http://localhost:9200' });\n * const storage = new ElasticSearchStore({ id: 'my-store', client });\n * const vector = new ElasticSearchVector({ id: 'my-vector', client });\n * ```\n */\nexport class ElasticSearchStore extends MastraStorage {\n private client: ElasticSearchClient;\n private shouldManageConnection: boolean;\n public stores: StorageDomains;\n\n constructor(config: ElasticSearchConfig) {\n super({ id: config.id, name: 'ElasticSearch', disableInit: config.disableInit });\n\n if ('client' in config && config.client) {\n this.client = config.client;\n this.shouldManageConnection = false;\n } else if ('url' in config && config.url) {\n this.client = new ElasticSearchClient({\n node: config.url,\n ...(config.auth && { auth: config.auth }),\n name: 'mastra-elasticsearch',\n headers: { 'user-agent': `mastra-es/${packageJson.version}` },\n });\n this.shouldManageConnection = true;\n } else {\n throw new MastraError({\n id: 'ELASTIC_SEARCH_STORE_CONSTRUCTOR_ERROR',\n domain: ErrorDomain.STORAGE,\n category: ErrorCategory.USER,\n text: 'Invalid config: provide either { client } or { url }.',\n });\n }\n\n this.stores = {\n memory: new MemoryElasticSearch({ client: this.client }),\n workflows: new WorkflowsElasticSearch({ client: this.client }),\n scores: new ScoresElasticSearch({ client: this.client }),\n };\n }\n\n public getClient(): ElasticSearchClient {\n return this.client;\n }\n\n public async close(): Promise<void> {\n if (this.shouldManageConnection) {\n await this.client.close();\n }\n }\n}\n"],"mappings":"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"}
|