{"version":3,"file":"index.cjs","names":["BaseFilterTranslator","MastraVector","QdrantClient","MastraError","createVectorErrorId","ErrorDomain","ErrorCategory"],"sources":["../src/vector/filter.ts","../src/vector/index.ts","../src/vector/prompt.ts"],"sourcesContent":["import { BaseFilterTranslator } from '@mastra/core/vector/filter';\nimport type {\n  VectorFilter,\n  LogicalOperator,\n  OperatorSupport,\n  OperatorValueMap,\n  LogicalOperatorValueMap,\n  BlacklistedRootOperators,\n} from '@mastra/core/vector/filter';\n\ntype QdrantOperatorValueMap = Omit<OperatorValueMap, '$options' | '$elemMatch'> & {\n  /**\n   * $count: Filter by array length or value count.\n   * Example: { tags: { $count: { gt: 2 } } }\n   */\n  $count: {\n    $gt?: number;\n    $gte?: number;\n    $lt?: number;\n    $lte?: number;\n    $eq?: number;\n  };\n\n  /**\n   * $geo: Geospatial filter.\n   * Example: { location: { $geo: { type: 'geo_radius', center: [lon, lat], radius: 1000 } } }\n   */\n  $geo: {\n    type: string;\n    [key: string]: any;\n  };\n\n  /**\n   * $hasId: Filter by point IDs.\n   * Allowed at root level.\n   * Example: { $hasId: '123' } or { $hasId: ['123', '456'] }\n   */\n  $hasId: string | string[];\n\n  /**\n   * $nested: Nested object filter.\n   * Example: { metadata: { $nested: { key: 'foo', filter: { $eq: 'bar' } } } }\n   */\n  $nested: {\n    // Additional properties depend on the nested object structure\n    [key: string]: any;\n  };\n\n  /**\n   * $hasVector: Filter by vector existence or field.\n   * Allowed at root level.\n   * Example: { $hasVector: true } or { $hasVector: 'vector_field' }\n   */\n  $hasVector: boolean | string;\n\n  /**\n   * $datetime: RFC 3339 datetime range.\n   * Example: { createdAt: { $datetime: { gte: '2024-01-01T00:00:00Z' } } }\n   */\n  $datetime: {\n    key?: string;\n    range?: {\n      gt?: Date | string;\n      gte?: Date | string;\n      lt?: Date | string;\n      lte?: Date | string;\n      eq?: Date | string;\n    };\n  };\n\n  /**\n   * $null: Check if a field is null.\n   * Example: { metadata: { $null: true } }\n   */\n  $null: boolean;\n\n  /**\n   * $empty: Check if an array or object field is empty.\n   * Example: { tags: { $empty: true } }\n   */\n  $empty: boolean;\n};\n\ntype QdrantLogicalOperatorValueMap = Omit<LogicalOperatorValueMap, '$nor'>;\n\ntype QdrantBlacklistedRootOperators =\n  | BlacklistedRootOperators\n  | '$count'\n  | '$geo'\n  | '$nested'\n  | '$datetime'\n  | '$null'\n  | '$empty';\n\nexport type QdrantVectorFilter = VectorFilter<\n  keyof QdrantOperatorValueMap,\n  QdrantOperatorValueMap,\n  QdrantLogicalOperatorValueMap,\n  QdrantBlacklistedRootOperators\n>;\n\n/**\n * Translates MongoDB-style filters to Qdrant compatible filters.\n *\n * Key transformations:\n * - $and -> must\n * - $or -> should\n * - $not -> must_not\n * - { field: { $op: value } } -> { key: field, match/range: { value/gt/lt: value } }\n *\n * Custom operators (Qdrant-specific):\n * - $count -> values_count (array length/value count)\n * - $geo -> geo filters (box, radius, polygon)\n * - $hasId -> has_id filter\n * - $nested -> nested object filters\n * - $hasVector -> vector existence check\n * - $datetime -> RFC 3339 datetime range\n * - $null -> is_null check\n * - $empty -> is_empty check\n */\nexport class QdrantFilterTranslator extends BaseFilterTranslator<QdrantVectorFilter> {\n  protected override isLogicalOperator(key: string): key is LogicalOperator {\n    return super.isLogicalOperator(key) || key === '$hasId' || key === '$hasVector';\n  }\n\n  protected override getSupportedOperators(): OperatorSupport {\n    return {\n      ...BaseFilterTranslator.DEFAULT_OPERATORS,\n      logical: ['$and', '$or', '$not'],\n      array: ['$in', '$nin', '$all'],\n      regex: ['$regex'],\n      element: ['$exists'],\n      custom: ['$count', '$geo', '$nested', '$datetime', '$null', '$empty', '$hasId', '$hasVector'],\n    };\n  }\n\n  protected override isOperator(key: string): key is any {\n    // $not can be both a logical operator and a field-level operator\n    // When used at field level like { field: { $not: { $gt: 5 } } }, treat it as an operator\n    return super.isOperator(key) || key === '$not';\n  }\n\n  translate(filter?: QdrantVectorFilter): QdrantVectorFilter {\n    if (this.isEmpty(filter)) return filter;\n    this.validateFilter(filter);\n    return this.translateNode(filter);\n  }\n\n  private createCondition(type: string, value: any, fieldKey?: string) {\n    const condition = { [type]: value };\n    return fieldKey ? { key: fieldKey, ...condition } : condition;\n  }\n\n  private translateNode(node: QdrantVectorFilter, isNested: boolean = false, fieldKey?: string): any {\n    if (!this.isEmpty(node) && !!node && typeof node === 'object' && 'must' in node) {\n      return node;\n    }\n\n    if (this.isPrimitive(node)) {\n      if (node === null) {\n        return { is_null: { key: fieldKey } };\n      }\n      return this.createCondition('match', { value: this.normalizeComparisonValue(node) }, fieldKey);\n    }\n\n    if (this.isRegex(node)) {\n      throw new Error('Direct regex pattern format is not supported in Qdrant');\n    }\n\n    if (Array.isArray(node)) {\n      return node.length === 0\n        ? { is_empty: { key: fieldKey } }\n        : this.createCondition('match', { any: this.normalizeArrayValues(node) }, fieldKey);\n    }\n\n    const entries = Object.entries(node as Record<string, any>);\n\n    // Handle logical operators first (but not $not when we have a fieldKey - that's handled as a field operator)\n    const logicalResult = this.handleLogicalOperators(entries, isNested, fieldKey);\n    if (logicalResult) {\n      return logicalResult;\n    }\n\n    // Handle field conditions\n    const { conditions, range, matchCondition } = this.handleFieldConditions(entries, fieldKey);\n\n    if (Object.keys(range).length > 0) {\n      conditions.push({ key: fieldKey, range });\n    }\n\n    if (matchCondition) {\n      conditions.push({ key: fieldKey, match: matchCondition });\n    }\n\n    return this.buildFinalConditions(conditions, isNested);\n  }\n\n  private buildFinalConditions(conditions: any[], isNested: boolean): any {\n    if (conditions.length === 0) {\n      return {};\n    } else if (conditions.length === 1 && isNested) {\n      return conditions[0];\n    } else {\n      return { must: conditions };\n    }\n  }\n\n  private handleLogicalOperators(entries: [string, any][], isNested: boolean, fieldKey?: string): any | null {\n    const firstKey = entries[0]?.[0];\n\n    // When we have a fieldKey and see $not, it's a field-level $not operator, not a logical operator\n    // Let handleFieldConditions handle it via the _specialNot path\n    if (firstKey === '$not' && fieldKey) {\n      return null;\n    }\n\n    if (firstKey && this.isLogicalOperator(firstKey) && !this.isCustomOperator(firstKey)) {\n      const [key, value] = entries[0]!;\n      const qdrantOp = this.getQdrantLogicalOp(key);\n      return {\n        [qdrantOp]: Array.isArray(value)\n          ? value.map(v => this.translateNode(v, true))\n          : [this.translateNode(value, true)],\n      };\n    }\n\n    if (\n      entries.length > 1 &&\n      !isNested &&\n      entries.every(([key]) => !this.isOperator(key) && !this.isCustomOperator(key))\n    ) {\n      return {\n        must: entries.map(([key, value]) => this.translateNode(value, true, key)),\n      };\n    }\n\n    return null;\n  }\n\n  private handleFieldConditions(\n    entries: [string, any][],\n    fieldKey?: string,\n  ): { conditions: any[]; range: Record<string, any>; matchCondition: Record<string, any> | null } {\n    const conditions = [];\n    let range: Record<string, any> = {};\n    let matchCondition: Record<string, any> | null = null;\n\n    for (const [key, value] of entries) {\n      if (this.isCustomOperator(key)) {\n        const customOp = this.translateCustomOperator(key, value, fieldKey);\n        conditions.push(customOp);\n      } else if (this.isOperator(key)) {\n        const opResult = this.translateOperatorValue(key, value);\n\n        // Handle special markers for operators that need custom handling\n        if (opResult._specialNull) {\n          // $eq: null -> use is_null\n          conditions.push({ is_null: { key: fieldKey } });\n        } else if (opResult._specialNotNull) {\n          // $ne: null -> use must_not with is_null\n          conditions.push({ must_not: [{ is_null: { key: fieldKey } }] });\n        } else if (opResult._specialNe) {\n          // $ne: value -> use must_not with match\n          conditions.push({\n            must_not: [{ key: fieldKey, match: { value: opResult._specialNe } }],\n          });\n        } else if (opResult._specialNin) {\n          // $nin: [values] -> use must_not with match any\n          conditions.push({\n            must_not: [{ key: fieldKey, match: { any: opResult._specialNin } }],\n          });\n        } else if (opResult._specialAll) {\n          // $all: [values] -> create multiple match conditions joined with must\n          for (const val of opResult._specialAll) {\n            conditions.push({ key: fieldKey, match: { value: val } });\n          }\n        } else if (opResult._specialExists) {\n          // $exists: true -> field must not be null or empty\n          conditions.push({\n            must_not: [{ is_null: { key: fieldKey } }, { is_empty: { key: fieldKey } }],\n          });\n        } else if (opResult._specialNotExists) {\n          // $exists: false -> field must be null or empty\n          conditions.push({\n            should: [{ is_null: { key: fieldKey } }, { is_empty: { key: fieldKey } }],\n          });\n        } else if (opResult._specialNot) {\n          // $not: { operator: value } -> translate inner condition and wrap in must_not\n          const innerResult = this.translateNode(opResult._specialNot, true, fieldKey);\n          conditions.push({ must_not: [innerResult] });\n        } else if (opResult.range) {\n          Object.assign(range, opResult.range);\n        } else {\n          matchCondition = opResult;\n        }\n      } else {\n        const nestedKey = fieldKey ? `${fieldKey}.${key}` : key;\n        const nestedCondition = this.translateNode(value, true, nestedKey);\n\n        if (nestedCondition.must) {\n          conditions.push(...nestedCondition.must);\n        } else if (!this.isEmpty(nestedCondition)) {\n          conditions.push(nestedCondition);\n        }\n      }\n    }\n\n    return { conditions, range, matchCondition };\n  }\n\n  private translateCustomOperator(op: string, value: any, fieldKey?: string): any {\n    switch (op) {\n      case '$count':\n        const countConditions = Object.entries(value).reduce(\n          (acc, [k, v]) => ({\n            ...acc,\n            [k.replace('$', '')]: v,\n          }),\n          {},\n        );\n        return { key: fieldKey, values_count: countConditions };\n      case '$geo':\n        const geoOp = this.translateGeoFilter(value.type, value);\n        return { key: fieldKey, ...geoOp };\n      case '$hasId':\n        return { has_id: Array.isArray(value) ? value : [value] };\n      case '$nested':\n        return {\n          nested: {\n            key: fieldKey,\n            filter: this.translateNode(value),\n          },\n        };\n      case '$hasVector':\n        return { has_vector: value };\n      case '$datetime':\n        return {\n          key: fieldKey,\n          range: this.normalizeDatetimeRange(value.range),\n        };\n      case '$null':\n        return { is_null: { key: fieldKey } };\n      case '$empty':\n        return { is_empty: { key: fieldKey } };\n      default:\n        throw new Error(`Unsupported custom operator: ${op}`);\n    }\n  }\n\n  private getQdrantLogicalOp(op: string): string {\n    switch (op) {\n      case '$and':\n        return 'must';\n      case '$or':\n        return 'should';\n      case '$not':\n        return 'must_not';\n      default:\n        throw new Error(`Unsupported logical operator: ${op}`);\n    }\n  }\n\n  private translateOperatorValue(operator: string, value: any): any {\n    const normalizedValue = this.normalizeComparisonValue(value);\n\n    switch (operator) {\n      case '$eq':\n        // Handle null comparison: use is_null instead of match\n        if (value === null) {\n          return { _specialNull: true };\n        }\n        return { value: normalizedValue };\n      case '$ne':\n        // Handle null comparison: for \"not null\", we need is_null wrapped in must_not\n        if (value === null) {\n          return { _specialNotNull: true };\n        }\n        // For $ne with non-null values, we need to use must_not with match\n        return { _specialNe: normalizedValue };\n      case '$gt':\n        return { range: { gt: normalizedValue } };\n      case '$gte':\n        return { range: { gte: normalizedValue } };\n      case '$lt':\n        return { range: { lt: normalizedValue } };\n      case '$lte':\n        return { range: { lte: normalizedValue } };\n      case '$in':\n        return { any: this.normalizeArrayValues(value) };\n      case '$nin':\n        // Similar to $ne, $nin should use must_not\n        return { _specialNin: this.normalizeArrayValues(value) };\n      case '$regex':\n        return { text: value };\n      case '$all':\n        // For $all operator, all values must be present in the array\n        // Qdrant doesn't have native $all, but we can use must with multiple match conditions\n        return { _specialAll: this.normalizeArrayValues(value) };\n      case '$exists':\n        // $exists: true means field must not be null/empty\n        // $exists: false means field must be null or empty\n        return value ? { _specialExists: true } : { _specialNotExists: true };\n      case '$not':\n        // $not wraps another operator\n        return { _specialNot: value };\n      default:\n        throw new Error(`Unsupported operator: ${operator}`);\n    }\n  }\n\n  private translateGeoFilter(type: string, value: any): any {\n    switch (type) {\n      case 'box':\n        return {\n          geo_bounding_box: {\n            top_left: value.top_left,\n            bottom_right: value.bottom_right,\n          },\n        };\n      case 'radius':\n        return {\n          geo_radius: {\n            center: value.center,\n            radius: value.radius,\n          },\n        };\n      case 'polygon':\n        return {\n          geo_polygon: {\n            exterior: value.exterior,\n            interiors: value.interiors,\n          },\n        };\n      default:\n        throw new Error(`Unsupported geo filter type: ${type}`);\n    }\n  }\n\n  private normalizeDatetimeRange(value: any): any {\n    const range: Record<string, string> = {};\n    for (const [op, val] of Object.entries(value)) {\n      if (val instanceof Date) {\n        range[op] = val.toISOString();\n      } else if (typeof val === 'string') {\n        // Assume string is already in proper format\n        range[op] = val;\n      }\n    }\n    return range;\n  }\n}\n","import { MastraError, ErrorDomain, ErrorCategory } from '@mastra/core/error';\nimport { createVectorErrorId } from '@mastra/core/storage';\nimport { MastraVector, validateUpsertInput } from '@mastra/core/vector';\nimport type {\n  QueryResult,\n  IndexStats,\n  CreateIndexParams,\n  UpsertVectorParams,\n  QueryVectorParams,\n  DescribeIndexParams,\n  DeleteIndexParams,\n  DeleteVectorParams,\n  UpdateVectorParams,\n  DeleteVectorsParams,\n} from '@mastra/core/vector';\nimport { QdrantClient } from '@qdrant/js-client-rest';\nimport type { QdrantClientParams, Schemas } from '@qdrant/js-client-rest';\n\nimport { QdrantFilterTranslator } from './filter';\nimport type { QdrantVectorFilter } from './filter';\n\nconst BATCH_SIZE = 256;\nconst DISTANCE_MAPPING: Record<string, Schemas['Distance']> = {\n  cosine: 'Cosine',\n  euclidean: 'Euclid',\n  dotproduct: 'Dot',\n};\n\n/**\n * Configuration for a named vector space in Qdrant.\n * @see https://qdrant.tech/documentation/concepts/vectors/#named-vectors\n */\nexport interface NamedVectorConfig {\n  /** The dimension (size) of vectors in this space. */\n  size: number;\n  /** The distance metric for similarity search. */\n  distance: 'cosine' | 'euclidean' | 'dotproduct';\n}\n\n/**\n * Query parameters for Qdrant vector store.\n * Extends the base QueryVectorParams with Qdrant-specific options.\n */\nexport interface QdrantQueryVectorParams extends QueryVectorParams<QdrantVectorFilter> {\n  /**\n   * Name of the vector field to query against when using named vectors.\n   * Use this when your collection has multiple named vector fields.\n   * @see https://qdrant.tech/documentation/concepts/vectors/#named-vectors\n   */\n  using?: string;\n}\n\n/**\n * Parameters for creating a Qdrant index/collection.\n * Extends the base CreateIndexParams with support for named vectors.\n */\nexport interface QdrantCreateIndexParams extends CreateIndexParams {\n  /**\n   * Configuration for named vector spaces.\n   * When provided, creates a collection with multiple named vector fields.\n   * Each key is the vector name, and the value defines its configuration.\n   * @see https://qdrant.tech/documentation/concepts/vectors/#named-vectors\n   *\n   * @example\n   * ```ts\n   * namedVectors: {\n   *   text: { size: 768, distance: 'cosine' },\n   *   image: { size: 512, distance: 'euclidean' },\n   * }\n   * ```\n   */\n  namedVectors?: Record<string, NamedVectorConfig>;\n}\n\n/**\n * Parameters for upserting vectors into Qdrant.\n * Extends the base UpsertVectorParams with support for named vectors.\n */\nexport interface QdrantUpsertVectorParams extends UpsertVectorParams {\n  /**\n   * Name of the vector space to upsert into when using named vectors.\n   * Required when the collection was created with namedVectors.\n   * @see https://qdrant.tech/documentation/concepts/vectors/#named-vectors\n   */\n  vectorName?: string;\n}\n\n/**\n * Supported payload schema types for Qdrant payload indexes.\n * These correspond to Qdrant's native payload indexing types.\n * @see https://qdrant.tech/documentation/concepts/indexing/#payload-index\n */\nexport type PayloadSchemaType = 'keyword' | 'integer' | 'float' | 'geo' | 'text' | 'bool' | 'datetime' | 'uuid';\n\n/**\n * Parameters for creating a payload index on a Qdrant collection.\n */\nexport interface CreatePayloadIndexParams {\n  /** The name of the collection (index) to create the payload index on. */\n  indexName: string;\n  /** The name of the payload field to index. */\n  fieldName: string;\n  /** The schema type for the payload field. */\n  fieldSchema: PayloadSchemaType;\n  /** Whether to wait for the operation to complete. Defaults to true. */\n  wait?: boolean;\n}\n\n/**\n * Parameters for deleting a payload index from a Qdrant collection.\n */\nexport interface DeletePayloadIndexParams {\n  /** The name of the collection (index) to delete the payload index from. */\n  indexName: string;\n  /** The name of the payload field index to delete. */\n  fieldName: string;\n  /** Whether to wait for the operation to complete. Defaults to true. */\n  wait?: boolean;\n}\n\n// Qdrant accepts simple, hyphenated, braced, and `urn:uuid:` UUID forms.\nconst QDRANT_UUID_REGEX =\n  /^(?:urn:uuid:)?(?:[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}|\\{[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}\\})$/i;\nconst QDRANT_MAX_POINT_ID = 18446744073709551615n;\n\nfunction isValidQdrantPointId(id: string): boolean {\n  if (/^\\d+$/.test(id)) return BigInt(id) <= QDRANT_MAX_POINT_ID;\n  return QDRANT_UUID_REGEX.test(id);\n}\n\nexport class QdrantVector extends MastraVector {\n  protected client: QdrantClient;\n\n  /**\n   * Creates a new QdrantVector client.\n   * @param id - The unique identifier for this vector store instance.\n   * @param url - The URL of the Qdrant server.\n   * @param apiKey - The API key for Qdrant.\n   * @param https - Whether to use HTTPS.\n   */\n  constructor({ id, ...qdrantParams }: QdrantClientParams & { id: string }) {\n    super({ id });\n    this.client = new QdrantClient(qdrantParams);\n  }\n\n  /**\n   * Validates that a named vector exists in the collection.\n   * @param indexName - The name of the collection to check.\n   * @param vectorName - The name of the vector space to validate.\n   * @throws Error if the vector name doesn't exist in the collection.\n   */\n  private async validateVectorName(indexName: string, vectorName: string): Promise<void> {\n    const { config } = await this.client.getCollection(indexName);\n    const vectorsConfig = config.params.vectors;\n    const isNamedVectors = vectorsConfig && typeof vectorsConfig === 'object' && !('size' in vectorsConfig);\n\n    if (!isNamedVectors || !(vectorName in vectorsConfig)) {\n      throw new Error(`Vector name \"${vectorName}\" does not exist in collection \"${indexName}\"`);\n    }\n  }\n\n  /**\n   * Upserts vectors into the index.\n   * @param indexName - The name of the index to upsert into.\n   * @param vectors - Array of embedding vectors.\n   * @param metadata - Optional metadata for each vector.\n   * @param ids - Optional vector IDs (auto-generated if not provided).\n   * @param vectorName - Optional name of the vector space when using named vectors.\n   */\n  async upsert({ indexName, vectors, metadata, ids, vectorName }: QdrantUpsertVectorParams): Promise<string[]> {\n    // Validate input parameters\n    validateUpsertInput('QDRANT', vectors, metadata, ids);\n    const pointIds = ids ? ids.map(id => this.parsePointId(id)) : vectors.map(() => crypto.randomUUID());\n\n    // Validate vector name if provided\n    if (vectorName) {\n      try {\n        await this.validateVectorName(indexName, vectorName);\n      } catch (validationError) {\n        throw new MastraError(\n          {\n            id: createVectorErrorId('QDRANT', 'UPSERT', 'INVALID_VECTOR_NAME'),\n            domain: ErrorDomain.STORAGE,\n            category: ErrorCategory.USER,\n            details: { indexName, vectorName },\n          },\n          validationError,\n        );\n      }\n    }\n\n    const records = vectors.map((vector, i) => ({\n      id: pointIds[i]!,\n      vector: vectorName ? { [vectorName]: vector } : vector,\n      payload: metadata?.[i] || {},\n    }));\n\n    try {\n      for (let i = 0; i < records.length; i += BATCH_SIZE) {\n        const batch = records.slice(i, i + BATCH_SIZE);\n        await this.client.upsert(indexName, {\n          points: batch,\n          wait: true,\n        });\n      }\n\n      return pointIds.map(String);\n    } catch (error) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'UPSERT', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName, vectorCount: vectors.length, ...(vectorName && { vectorName }) },\n        },\n        error,\n      );\n    }\n  }\n\n  /**\n   * Creates a new index (collection) in Qdrant.\n   * Supports both single vector and named vector configurations.\n   *\n   * @param indexName - The name of the collection to create.\n   * @param dimension - Vector dimension (required for single vector mode).\n   * @param metric - Distance metric (default: 'cosine').\n   * @param namedVectors - Optional named vector configurations for multi-vector collections.\n   *\n   * @example\n   * ```ts\n   * // Single vector collection\n   * await qdrant.createIndex({ indexName: 'docs', dimension: 768, metric: 'cosine' });\n   *\n   * // Named vectors collection\n   * await qdrant.createIndex({\n   *   indexName: 'multi-modal',\n   *   dimension: 768, // Used as fallback, can be omitted with namedVectors\n   *   namedVectors: {\n   *     text: { size: 768, distance: 'cosine' },\n   *     image: { size: 512, distance: 'euclidean' },\n   *   },\n   * });\n   * ```\n   */\n  async createIndex({ indexName, dimension, metric = 'cosine', namedVectors }: QdrantCreateIndexParams): Promise<void> {\n    try {\n      if (namedVectors) {\n        // Validate named vectors configuration\n        if (Object.keys(namedVectors).length === 0) {\n          throw new Error('namedVectors must contain at least one named vector configuration');\n        }\n        for (const [name, config] of Object.entries(namedVectors)) {\n          if (!Number.isInteger(config.size) || config.size <= 0) {\n            throw new Error(`Named vector \"${name}\": size must be a positive integer`);\n          }\n          if (!DISTANCE_MAPPING[config.distance]) {\n            throw new Error(\n              `Named vector \"${name}\": invalid distance \"${config.distance}\". Must be one of: cosine, euclidean, dotproduct`,\n            );\n          }\n        }\n      } else {\n        // Validate single vector configuration\n        if (!Number.isInteger(dimension) || dimension <= 0) {\n          throw new Error('Dimension must be a positive integer');\n        }\n        if (!DISTANCE_MAPPING[metric]) {\n          throw new Error(`Invalid metric: \"${metric}\". Must be one of: cosine, euclidean, dotproduct`);\n        }\n      }\n    } catch (validationError) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'CREATE_INDEX', 'INVALID_ARGS'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.USER,\n          details: {\n            indexName,\n            dimension,\n            metric,\n            ...(namedVectors && { namedVectorNames: Object.keys(namedVectors).join(', ') }),\n          },\n        },\n        validationError,\n      );\n    }\n\n    try {\n      // Build vectors configuration\n      if (namedVectors) {\n        const namedVectorsConfig = Object.entries(namedVectors).reduce(\n          (acc, [name, config]) => {\n            acc[name] = {\n              size: config.size,\n              distance: DISTANCE_MAPPING[config.distance]!,\n            };\n            return acc;\n          },\n          {} as Record<string, { size: number; distance: Schemas['Distance'] }>,\n        );\n\n        await this.client.createCollection(indexName, {\n          vectors: namedVectorsConfig,\n        });\n      } else {\n        await this.client.createCollection(indexName, {\n          vectors: {\n            size: dimension,\n            distance: DISTANCE_MAPPING[metric]!,\n          },\n        });\n      }\n    } catch (error: any) {\n      const message = error?.message || error?.toString();\n      // Qdrant typically returns 409 for existing collection\n      if (error?.status === 409 || (typeof message === 'string' && message.toLowerCase().includes('exists'))) {\n        if (!namedVectors) {\n          // Fetch collection info and check dimension for single vector mode\n          await this.validateExistingIndex(indexName, dimension, metric);\n        } else {\n          // For named vectors, just log and continue (validation is complex)\n          this.logger.info(\n            `Collection \"${indexName}\" already exists. Skipping validation for named vectors configuration.`,\n          );\n        }\n        return;\n      }\n\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', '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  transformFilter(filter?: QdrantVectorFilter) {\n    const translator = new QdrantFilterTranslator();\n    return translator.translate(filter);\n  }\n\n  /**\n   * Queries the index for similar vectors.\n   *\n   * @param indexName - The name of the index to query.\n   * @param queryVector - The query vector to find similar vectors for.\n   * @param topK - Number of results to return (default: 10).\n   * @param filter - Optional metadata filter.\n   * @param includeVector - Whether to include vectors in results (default: false).\n   * @param using - Name of the vector space to query when using named vectors.\n   */\n  async query({\n    indexName,\n    queryVector,\n    topK = 10,\n    filter,\n    includeVector = false,\n    using,\n  }: QdrantQueryVectorParams): Promise<QueryResult[]> {\n    if (!queryVector) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'QUERY', 'MISSING_VECTOR'),\n        text: 'queryVector is required for Qdrant 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    const translatedFilter = this.transformFilter(filter) ?? {};\n\n    try {\n      const results = (\n        await this.client.query(indexName, {\n          query: queryVector,\n          limit: topK,\n          filter: translatedFilter,\n          with_payload: true,\n          with_vector: includeVector,\n          ...(using ? { using } : {}),\n        })\n      ).points;\n\n      return results.map(match => {\n        let vector: number[] = [];\n        if (includeVector && match.vector != null) {\n          if (Array.isArray(match.vector)) {\n            // Single vector mode - already an array of numbers\n            vector = match.vector as number[];\n          } else if (typeof match.vector === 'object' && match.vector !== null) {\n            // Named vectors mode - extract from the correct vector space\n            const namedVectors = match.vector as Record<string, unknown>;\n\n            // If `using` is specified, try to get that specific vector\n            // Otherwise, find the first array in the object\n            const sourceArray: unknown[] | undefined =\n              using && Array.isArray(namedVectors[using])\n                ? (namedVectors[using] as unknown[])\n                : (Object.values(namedVectors).find(v => Array.isArray(v)) as unknown[] | undefined);\n\n            if (sourceArray) {\n              vector = sourceArray.filter((v): v is number => typeof v === 'number');\n            }\n          }\n        }\n\n        return {\n          id: match.id as string,\n          score: match.score || 0,\n          metadata: match.payload as Record<string, any>,\n          ...(includeVector && { vector }),\n        };\n      });\n    } catch (error) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'QUERY', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName, topK, ...(using && { using }) },\n        },\n        error,\n      );\n    }\n  }\n\n  async listIndexes(): Promise<string[]> {\n    try {\n      const response = await this.client.getCollections();\n      return response.collections.map(collection => collection.name) || [];\n    } catch (error) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'LIST_INDEXES', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n        },\n        error,\n      );\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    try {\n      const { config, points_count } = await this.client.getCollection(indexName);\n\n      const distance = config.params.vectors?.distance as Schemas['Distance'];\n      return {\n        dimension: config.params.vectors?.size as number,\n        count: points_count || 0,\n        metric: (Object.keys(DISTANCE_MAPPING) as (keyof typeof DISTANCE_MAPPING)[]).find(\n          key => DISTANCE_MAPPING[key] === distance,\n        ) as IndexStats['metric'],\n      };\n    } catch (error) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'DESCRIBE_INDEX', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName },\n        },\n        error,\n      );\n    }\n  }\n\n  async deleteIndex({ indexName }: DeleteIndexParams): Promise<void> {\n    try {\n      await this.client.deleteCollection(indexName);\n    } catch (error: any) {\n      // If the collection doesn't exist, treat it as a no-op (already deleted)\n      const errorMessage = error?.message || error?.toString() || '';\n      if (\n        error?.status === 404 ||\n        errorMessage.toLowerCase().includes('not found') ||\n        errorMessage.toLowerCase().includes('not exist')\n      ) {\n        this.logger.info(`Collection ${indexName} does not exist, treating as already deleted`);\n        return;\n      }\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'DELETE_INDEX', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName },\n        },\n        error,\n      );\n    }\n  }\n\n  /**\n   * Updates a vector by its ID or multiple vectors matching a filter.\n   * @param indexName - The name of the index containing the vector(s).\n   * @param id - The ID of the vector to update (mutually exclusive with filter).\n   * @param filter - Filter to match multiple vectors to update (mutually exclusive with id).\n   * @param update - An object containing the vector and/or metadata to update.\n   * @param update.vector - An optional array of numbers representing the new vector.\n   * @param update.metadata - An optional record containing the new metadata.\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({ indexName, id, filter, update }: UpdateVectorParams<QdrantVectorFilter>): Promise<void> {\n    // Validate mutually exclusive parameters\n    if (id && filter) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'UPDATE_VECTOR', 'MUTUALLY_EXCLUSIVE'),\n        text: 'Cannot specify both id and filter - they are mutually exclusive',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    if (!id && !filter) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'UPDATE_VECTOR', 'NO_TARGET'),\n        text: 'Either id or filter must be provided',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    if (!update.vector && !update.metadata) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'UPDATE_VECTOR', 'NO_PAYLOAD'),\n        text: 'No updates provided',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: {\n          indexName,\n          ...(id && { id }),\n        },\n      });\n    }\n\n    // Validate filter is not empty\n    if (filter && Object.keys(filter).length === 0) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'UPDATE_VECTOR', 'EMPTY_FILTER'),\n        text: 'Filter cannot be an empty filter object',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    try {\n      if (id) {\n        // Update single vector by ID\n        const pointId = this.parsePointId(id);\n\n        // Handle metadata-only update\n        if (update.metadata && !update.vector) {\n          await this.client.setPayload(indexName, { payload: update.metadata, points: [pointId] });\n          return;\n        }\n\n        // Handle vector-only update\n        if (update.vector && !update.metadata) {\n          await this.client.updateVectors(indexName, {\n            points: [\n              {\n                id: pointId,\n                vector: update.vector,\n              },\n            ],\n          });\n          return;\n        }\n\n        // Handle both vector and metadata update\n        if (update.vector && update.metadata) {\n          const point = {\n            id: pointId,\n            vector: update.vector,\n            payload: update.metadata,\n          };\n\n          await this.client.upsert(indexName, {\n            points: [point],\n          });\n          return;\n        }\n      } else if (filter) {\n        // Update multiple vectors matching filter\n        const translatedFilter = this.transformFilter(filter);\n\n        // First, scroll through all matching points to get their IDs\n        const matchingPoints: Array<{ id: string | number; vector?: number[] }> = [];\n        let offset: string | number | undefined = undefined;\n\n        do {\n          const scrollResult = await this.client.scroll(indexName, {\n            filter: translatedFilter,\n            limit: 100,\n            offset,\n            with_payload: false,\n            with_vector: !update.vector, // Only fetch vectors if not updating them\n          });\n\n          matchingPoints.push(\n            ...scrollResult.points.map(point => ({\n              id: point.id,\n              vector: Array.isArray(point.vector) ? (point.vector as number[]) : undefined,\n            })),\n          );\n\n          const nextOffset = scrollResult.next_page_offset;\n          offset = typeof nextOffset === 'string' || typeof nextOffset === 'number' ? nextOffset : undefined;\n        } while (offset !== undefined);\n\n        if (matchingPoints.length === 0) {\n          // No vectors to update - this is not an error\n          return;\n        }\n\n        const pointIds = matchingPoints.map(p => p.id);\n\n        // Handle metadata-only update\n        if (update.metadata && !update.vector) {\n          await this.client.setPayload(indexName, { payload: update.metadata, points: pointIds });\n          return;\n        }\n\n        // Handle vector-only or both updates\n        if (update.vector) {\n          // For vector updates with filter, we need to upsert each point\n          const points = matchingPoints.map(p => ({\n            id: p.id,\n            vector: update.vector!,\n            payload: update.metadata || {},\n          }));\n\n          // Batch upsert\n          for (let i = 0; i < points.length; i += BATCH_SIZE) {\n            const batch = points.slice(i, i + BATCH_SIZE);\n            await this.client.upsert(indexName, {\n              points: batch,\n              wait: true,\n            });\n          }\n          return;\n        }\n      }\n    } catch (error) {\n      if (error instanceof MastraError) throw error;\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'UPDATE_VECTOR', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: {\n            indexName,\n            ...(id && { id }),\n            ...(filter && { 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      // Parse the ID - Qdrant supports both string and numeric IDs\n      const pointId = this.parsePointId(id);\n\n      // Use the Qdrant client to delete the point from the collection\n      await this.client.delete(indexName, {\n        points: [pointId],\n      });\n    } catch (error) {\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', '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  /**\n   * Parses and converts a string ID to the appropriate type (string or number) for Qdrant point operations.\n   *\n   * Qdrant supports both numeric and string IDs. This helper method ensures IDs are in the correct format\n   * before sending them to the Qdrant client API.\n   *\n   * @param id - The ID string to parse\n   * @returns The parsed ID as either a number (if string contains only digits) or the original string\n   *\n   * @example\n   * // Numeric ID strings are converted to numbers\n   * parsePointId(\"123\") => 123\n   * parsePointId(\"42\") => 42\n   * parsePointId(\"0\") => 0\n   *\n   * // String IDs containing any non-digit characters remain as strings\n   * parsePointId(\"doc-123\") => \"doc-123\"\n   * parsePointId(\"user_42\") => \"user_42\"\n   * parsePointId(\"abc123\") => \"abc123\"\n   * parsePointId(\"123abc\") => \"123abc\"\n   * parsePointId(\"\") => \"\"\n   * parsePointId(\"uuid-5678-xyz\") => \"uuid-5678-xyz\"\n   *\n   * @remarks\n   * - This conversion is important because Qdrant treats numeric and string IDs differently\n   * - Only positive integers are converted to numbers (negative numbers with minus signs remain strings)\n   * - The method uses base-10 parsing, so leading zeros will be dropped in numeric conversions\n   * - reference: https://qdrant.tech/documentation/concepts/points/?q=qdrant+point+id#point-ids\n   */\n  private parsePointId(id: string): string | number {\n    // Try to parse as number if it looks like one\n    if (/^\\d+$/.test(id)) {\n      return parseInt(id, 10);\n    }\n    return id;\n  }\n\n  /**\n   * Deletes multiple vectors by IDs or filter.\n   * @param indexName - The name of the index containing the vectors.\n   * @param ids - Array of vector IDs to delete (mutually exclusive with filter).\n   * @param filter - Filter to match vectors to delete (mutually exclusive with ids).\n   * @returns A promise that resolves when the deletion is complete.\n   * @throws Will throw an error if both ids and filter are provided, or if neither is provided.\n   */\n  async deleteVectors({ indexName, filter, ids }: DeleteVectorsParams<QdrantVectorFilter>): Promise<void> {\n    // Validate mutually exclusive parameters\n    if (ids && filter) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_VECTORS', 'MUTUALLY_EXCLUSIVE'),\n        text: 'Cannot specify both ids and filter - they are mutually exclusive',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    if (!ids && !filter) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_VECTORS', 'NO_TARGET'),\n        text: 'Either filter or ids must be provided',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    // Validate ids array is not empty\n    if (ids && ids.length === 0) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_VECTORS', 'EMPTY_IDS'),\n        text: 'Cannot delete with empty ids array',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    // Validate filter is not empty\n    if (filter && Object.keys(filter).length === 0) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_VECTORS', 'EMPTY_FILTER'),\n        text: 'Cannot delete with empty filter object',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName },\n      });\n    }\n\n    try {\n      if (ids) {\n        // Qdrant rejects the whole batch with a 400 if any ID is not a uint64 or UUID,\n        // so surface malformed IDs as a user error instead of letting nothing be deleted.\n        const invalidIds = ids.filter(id => !isValidQdrantPointId(id));\n        if (invalidIds.length > 0) {\n          throw new MastraError({\n            id: createVectorErrorId('QDRANT', 'DELETE_VECTORS', 'INVALID_IDS'),\n            text: `Invalid Qdrant point IDs (must be unsigned integers or UUIDs): ${invalidIds.join(', ')}`,\n            domain: ErrorDomain.STORAGE,\n            category: ErrorCategory.USER,\n            details: { indexName, invalidIds: invalidIds.join(', ') },\n          });\n        }\n        await this.client.delete(indexName, {\n          points: ids.map(id => this.parsePointId(id)),\n          wait: true,\n        });\n      } else if (filter) {\n        // Delete by filter\n        const translatedFilter = this.transformFilter(filter) ?? {};\n        await this.client.delete(indexName, {\n          filter: translatedFilter as any,\n          wait: true,\n        });\n      }\n    } catch (error) {\n      if (error instanceof MastraError) throw error;\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', '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  /**\n   * Creates a payload index on a Qdrant collection to enable efficient filtering on metadata fields.\n   *\n   * This is required for Qdrant Cloud and any Qdrant instance with `strict_mode_config = true`,\n   * where metadata (payload) fields must be explicitly indexed before they can be used for filtering.\n   *\n   * @param params - The parameters for creating the payload index.\n   * @param params.indexName - The name of the collection (index) to create the payload index on.\n   * @param params.fieldName - The name of the payload field to index.\n   * @param params.fieldSchema - The schema type for the field (e.g., 'keyword', 'integer', 'text').\n   * @param params.wait - Whether to wait for the operation to complete. Defaults to true.\n   * @returns A promise that resolves when the index is created (idempotent if index already exists).\n   * @throws Will throw a MastraError if arguments are invalid or if the operation fails.\n   *\n   * @example\n   * ```ts\n   * // Create a keyword index for filtering by source\n   * await qdrant.createPayloadIndex({\n   *   indexName: 'my-collection',\n   *   fieldName: 'source',\n   *   fieldSchema: 'keyword',\n   * });\n   *\n   * // Create an integer index for numeric filtering\n   * await qdrant.createPayloadIndex({\n   *   indexName: 'my-collection',\n   *   fieldName: 'price',\n   *   fieldSchema: 'integer',\n   * });\n   * ```\n   *\n   * @see https://qdrant.tech/documentation/concepts/indexing/#payload-index\n   */\n  async createPayloadIndex({\n    indexName,\n    fieldName,\n    fieldSchema,\n    wait = true,\n  }: CreatePayloadIndexParams): Promise<void> {\n    // Validate inputs\n    const validSchemas: PayloadSchemaType[] = [\n      'keyword',\n      'integer',\n      'float',\n      'geo',\n      'text',\n      'bool',\n      'datetime',\n      'uuid',\n    ];\n\n    if (!indexName || typeof indexName !== 'string' || indexName.trim() === '') {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'CREATE_PAYLOAD_INDEX', 'INVALID_ARGS'),\n        text: 'indexName must be a non-empty string',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName, fieldName, fieldSchema },\n      });\n    }\n\n    if (!fieldName || typeof fieldName !== 'string' || fieldName.trim() === '') {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'CREATE_PAYLOAD_INDEX', 'INVALID_ARGS'),\n        text: 'fieldName must be a non-empty string',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName, fieldName, fieldSchema },\n      });\n    }\n\n    if (!validSchemas.includes(fieldSchema)) {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'CREATE_PAYLOAD_INDEX', 'INVALID_ARGS'),\n        text: `fieldSchema must be one of: ${validSchemas.join(', ')}`,\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName, fieldName, fieldSchema },\n      });\n    }\n\n    try {\n      await this.client.createPayloadIndex(indexName, {\n        field_name: fieldName,\n        field_schema: fieldSchema,\n        wait,\n      });\n    } catch (error: any) {\n      const message = error?.message || error?.toString() || '';\n      // Qdrant returns 409 or \"exists\" message if index already exists - treat as idempotent success\n      if (error?.status === 409 || message.toLowerCase().includes('exists')) {\n        this.logger.info(`Payload index for field \"${fieldName}\" already exists on collection \"${indexName}\"`);\n        return;\n      }\n\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'CREATE_PAYLOAD_INDEX', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName, fieldName, fieldSchema },\n        },\n        error,\n      );\n    }\n  }\n\n  /**\n   * Deletes a payload index from a Qdrant collection.\n   *\n   * @param params - The parameters for deleting the payload index.\n   * @param params.indexName - The name of the collection (index) to delete the payload index from.\n   * @param params.fieldName - The name of the payload field index to delete.\n   * @param params.wait - Whether to wait for the operation to complete. Defaults to true.\n   * @returns A promise that resolves when the index is deleted (idempotent if index doesn't exist).\n   * @throws Will throw a MastraError if the operation fails.\n   *\n   * @example\n   * ```ts\n   * await qdrant.deletePayloadIndex({\n   *   indexName: 'my-collection',\n   *   fieldName: 'source',\n   * });\n   * ```\n   */\n  async deletePayloadIndex({ indexName, fieldName, wait = true }: DeletePayloadIndexParams): Promise<void> {\n    // Validate inputs\n    if (!indexName || typeof indexName !== 'string' || indexName.trim() === '') {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_PAYLOAD_INDEX', 'INVALID_ARGS'),\n        text: 'indexName must be a non-empty string',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName, fieldName },\n      });\n    }\n\n    if (!fieldName || typeof fieldName !== 'string' || fieldName.trim() === '') {\n      throw new MastraError({\n        id: createVectorErrorId('QDRANT', 'DELETE_PAYLOAD_INDEX', 'INVALID_ARGS'),\n        text: 'fieldName must be a non-empty string',\n        domain: ErrorDomain.STORAGE,\n        category: ErrorCategory.USER,\n        details: { indexName, fieldName },\n      });\n    }\n\n    try {\n      await this.client.deletePayloadIndex(indexName, fieldName, { wait });\n    } catch (error: any) {\n      const message = error?.message || error?.toString() || '';\n      // If index doesn't exist, treat as idempotent success (already deleted)\n      if (\n        error?.status === 404 ||\n        message.toLowerCase().includes('not found') ||\n        message.toLowerCase().includes('not exist')\n      ) {\n        this.logger.info(`Payload index for field \"${fieldName}\" does not exist on collection \"${indexName}\"`);\n        return;\n      }\n\n      throw new MastraError(\n        {\n          id: createVectorErrorId('QDRANT', 'DELETE_PAYLOAD_INDEX', 'FAILED'),\n          domain: ErrorDomain.STORAGE,\n          category: ErrorCategory.THIRD_PARTY,\n          details: { indexName, fieldName },\n        },\n        error,\n      );\n    }\n  }\n}\n","/**\n * Vector store specific prompt that details supported operators and examples.\n * This prompt helps users construct valid filters for Qdrant Vector.\n */\nexport const QDRANT_PROMPT = `When querying Qdrant, you can ONLY use the operators listed below. Any other operators will be rejected.\nImportant: Don't explain how to construct the filter - use the specified operators and fields to search the content and return relevant results.\nIf a user tries to give an explicit operator that is not supported, reject the filter entirely and let them know that the operator is not supported.\n\nBasic Comparison Operators:\n- $eq: Exact match (default when using field: value)\n  Example: { \"category\": \"electronics\" }\n- $ne: Not equal\n  Example: { \"category\": { \"$ne\": \"electronics\" } }\n- $gt: Greater than\n  Example: { \"price\": { \"$gt\": 100 } }\n- $gte: Greater than or equal\n  Example: { \"price\": { \"$gte\": 100 } }\n- $lt: Less than\n  Example: { \"price\": { \"$lt\": 100 } }\n- $lte: Less than or equal\n  Example: { \"price\": { \"$lte\": 100 } }\n\nArray Operators:\n- $in: Match any value in array\n  Example: { \"category\": { \"$in\": [\"electronics\", \"books\"] } }\n- $nin: Does not match any value in array\n  Example: { \"category\": { \"$nin\": [\"electronics\", \"books\"] } }\n\nLogical Operators:\n- $and: Logical AND (can be implicit or explicit)\n  Implicit Example: { \"price\": { \"$gt\": 100 }, \"category\": \"electronics\" }\n  Explicit Example: { \"$and\": [{ \"price\": { \"$gt\": 100 } }, { \"category\": \"electronics\" }] }\n- $or: Logical OR\n  Example: { \"$or\": [{ \"price\": { \"$lt\": 50 } }, { \"category\": \"books\" }] }\n- $not: Logical NOT\n  Example: { \"$not\": { \"category\": \"electronics\" } }\n\nElement Operators:\n- $exists: Check if field exists\n  Example: { \"rating\": { \"$exists\": true } }\n- $match: Match text using full-text search\n  Example: { \"description\": { \"$match\": \"gaming laptop\" } }\n- $null: Check if field is null\n  Example: { \"rating\": { \"$null\": true } }\n\nRestrictions:\n- Regex patterns are not supported\n- Only $and, $or, and $not logical operators are supported at the top level\n- Empty arrays in $in/$nin will return no results\n- Nested fields are supported using dot notation\n- Multiple conditions on the same field are supported with both implicit and explicit $and\n- At least one key-value pair is required in filter object\n- Empty objects and undefined values are treated as no filter\n- Invalid types in comparison operators will throw errors\n- All non-logical operators must be used within a field condition\n  Valid: { \"field\": { \"$gt\": 100 } }\n  Valid: { \"$and\": [...] }\n  Invalid: { \"$gt\": 100 }\n- Logical operators must contain field conditions, not direct operators\n  Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n  Invalid: { \"$and\": [{ \"$gt\": 100 }] }\n- Logical operators ($and, $or, $not):\n  - Can only be used at top level or nested within other logical operators\n  - Can not be used on a field level, or be nested inside a field\n  - Can not be used inside an operator\n  - Valid: { \"$and\": [{ \"field\": { \"$gt\": 100 } }] }\n  - Valid: { \"$or\": [{ \"$and\": [{ \"field\": { \"$gt\": 100 } }] }] }\n  - Invalid: { \"field\": { \"$and\": [{ \"$gt\": 100 }] } }\n  - Invalid: { \"field\": { \"$or\": [{ \"$gt\": 100 }] } }\n  - Invalid: { \"field\": { \"$gt\": { \"$and\": [{...}] } } }\n\nExample Complex Query:\n{\n  \"$and\": [\n    { \"category\": { \"$in\": [\"electronics\", \"computers\"] } },\n    { \"price\": { \"$gte\": 100, \"$lte\": 1000 } },\n    { \"description\": { \"$match\": \"gaming laptop\" } },\n    { \"rating\": { \"$exists\": true, \"$gt\": 4 } },\n    { \"$or\": [\n      { \"stock\": { \"$gt\": 0 } },\n      { \"preorder\": { \"$null\": false } }\n    ]},\n    { \"$not\": { \"status\": \"discontinued\" } }\n  ]\n}`;\n"],"mappings":"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"}