{"version":3,"file":"s3vectors.mjs","names":["#opts","#settle","#client","#cmd","#index","#dims","#metrics"],"sources":["../../../src/batteries/vector/s3vectors/index.ts"],"sourcesContent":["/**\n * @module @nhtio/adk/batteries/vector/s3vectors\n *\n * AWS S3 Vectors vector-store adapter. A vector BUCKET is provisioned out-of-band (the adapter\n * does NOT create the bucket); a logical collection = an **index** inside that bucket. The SDK is\n * command-based: create/delete/list indexes, PutVectors/QueryVectors/GetVectors/DeleteVectors.\n *\n * Scoring rule: QueryVectors returns `distance`. For cosine, distance = 1 - cosineSim; identical\n * vectors → 0. For euclidean, distance = L2 distance. Scores are derived from the returned\n * distance and normalized to [0,1].\n *\n * Metadata is NATIVE JSON (object). Store the document text under the reserved metadata key\n * `__document`; keep user metadata flat alongside. On read, pull `__document` out into\n * `match.document` and return the rest as `match.metadata`.\n *\n * Filtering: S3 Vectors supports a native filter (Mongo-ish), but for guaranteed cross-adapter\n * parity, **over-fetch and JS-filter** with `evaluateFilter`. When `plan.filter` is set, request\n * a larger `topK` (e.g. 500) without a native filter, then JS-filter, then slice.\n *\n * Eventual consistency: settle-poll after writes/deletes so the conformance suite — which writes\n * then immediately reads — passes deterministically.\n */\n\nimport { evaluateFilter } from '../filters'\nimport { BaseVectorStore } from '../contract'\nimport { validateRecords } from '../validation'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { normalizeScore, sanitizeMetadata } from '../helpers'\nimport {\n  E_VECTOR_STORE_DRIVER_UNAVAILABLE,\n  E_VECTOR_STORE_CONNECTION_FAILED,\n  E_VECTOR_STORE_COLLECTION_FAILED,\n  E_VECTOR_STORE_UPSERT_FAILED,\n  E_VECTOR_STORE_SEARCH_FAILED,\n  E_VECTOR_STORE_DELETE_FAILED,\n  E_VECTOR_STORE_DIMENSION_MISMATCH,\n  E_VECTOR_STORE_UNSUPPORTED_OPERATION,\n} from '../exceptions'\nimport type { SearchPlan, UpsertPlan, DeletePlan, CollectionSpec } from '../plan'\nimport type {\n  VectorMatch,\n  VectorStoreCapabilities,\n  BaseVectorStoreOptions,\n  VectorMetadata,\n  DistanceMetric,\n} from '../types'\n\nconst getS3Vectors = async (): Promise<{\n  S3VectorsClient: any\n  CreateIndexCommand: any\n  DeleteIndexCommand: any\n  ListIndexesCommand: any\n  PutVectorsCommand: any\n  QueryVectorsCommand: any\n  GetVectorsCommand: any\n  DeleteVectorsCommand: any\n}> => {\n  try {\n    const mod = await import('@aws-sdk/client-s3vectors')\n    return {\n      S3VectorsClient: mod.S3VectorsClient,\n      CreateIndexCommand: mod.CreateIndexCommand,\n      DeleteIndexCommand: mod.DeleteIndexCommand,\n      ListIndexesCommand: mod.ListIndexesCommand,\n      PutVectorsCommand: mod.PutVectorsCommand,\n      QueryVectorsCommand: mod.QueryVectorsCommand,\n      GetVectorsCommand: mod.GetVectorsCommand,\n      DeleteVectorsCommand: mod.DeleteVectorsCommand,\n    }\n  } catch {\n    throw new E_VECTOR_STORE_DRIVER_UNAVAILABLE(['@aws-sdk/client-s3vectors'])\n  }\n}\n\nexport interface S3VectorsVectorStoreOptions extends BaseVectorStoreOptions {\n  /** Connection and authentication parameters for the backend. */\n  connection: {\n    bucket: string\n    region?: string\n    credentials?: { accessKeyId: string; secretAccessKey: string; sessionToken?: string }\n    indexPrefix?: string\n  }\n}\n\nconst mapMetricToS3 = (metric: DistanceMetric): string => {\n  if (metric === 'cosine') return 'cosine'\n  if (metric === 'euclidean') return 'euclidean'\n  // dot is not supported by S3 Vectors\n  throw new E_VECTOR_STORE_COLLECTION_FAILED([\n    'createCollection',\n    'Metric \"dot\" is not supported by AWS S3 Vectors; use \"cosine\" or \"euclidean\"',\n  ])\n}\n\n// QueryVectors returns a `distance`; convert it to the battery's normalized [0,1] similarity\n// score. For cosine, S3 Vectors distance = 1 - cosineSim, so sim = 1 - distance.\nconst scoreFromDistance = (distance: number, metric: DistanceMetric): number => {\n  if (metric === 'cosine') {\n    // cosine distance = 1 - sim, so sim = 1 - distance\n    return normalizeScore(1 - distance, 'cosine', 'similarity')\n  } else if (metric === 'euclidean') {\n    return normalizeScore(distance, 'euclidean', 'distance')\n  } else {\n    // Fallback\n    return normalizeScore(1 - distance, 'cosine', 'similarity')\n  }\n}\n\nexport class S3VectorsVectorStore extends BaseVectorStore {\n  readonly capabilities: VectorStoreCapabilities = {\n    transactions: false,\n    namedVectors: false,\n    rename: false,\n    rawSql: false,\n    builtInEncoding: false,\n    consistency: { configurable: false, default: 'strong', modes: ['strong'] },\n  }\n\n  #client: any | null = null\n  #dims: Map<string, number> = new Map()\n  #metrics: Map<string, DistanceMetric> = new Map()\n\n  get #opts(): S3VectorsVectorStoreOptions {\n    return this.options as S3VectorsVectorStoreOptions\n  }\n\n  // Map a logical collection name to its physical S3 Vectors index name (with optional prefix).\n  #index(collection: string): string {\n    const prefix = this.#opts.connection.indexPrefix ?? ''\n    return `${prefix}${collection}`\n  }\n\n  // Settle-poll: wait until the given keys are visible in QueryVectors (for upsert) or absent\n  // (for delete), bounded ~10s with 300ms polls.\n  async #settle(\n    physicalIndex: string,\n    opts: { present?: string[]; absent?: string[] }\n  ): Promise<void> {\n    const present = opts.present ?? []\n    const absent = opts.absent ?? []\n    if (present.length === 0 && absent.length === 0) return\n\n    const deadline = Date.now() + 10_000\n    const probeVec = new Array(this.#opts.dimensions ?? 3).fill(0).map((_, i) => (i === 0 ? 1 : 0))\n    const bucket = this.#opts.connection.bucket\n\n    while (true) {\n      let presentOk = true\n      let absentOk = true\n\n      if (present.length > 0) {\n        try {\n          const qr = await this.#client!.send(\n            new this.#cmd!.QueryVectorsCommand({\n              vectorBucketName: bucket,\n              indexName: physicalIndex,\n              queryVector: { float32: probeVec },\n              topK: Math.max(present.length + 5, 10),\n              returnMetadata: false,\n              returnDistance: false,\n            })\n          )\n          const seen = new Set((qr.vectors ?? []).map((v: any) => v.key))\n          presentOk = present.every((k) => seen.has(k))\n        } catch {\n          presentOk = false\n        }\n      }\n\n      if (absent.length > 0) {\n        try {\n          const qr = await this.#client!.send(\n            new this.#cmd!.QueryVectorsCommand({\n              vectorBucketName: bucket,\n              indexName: physicalIndex,\n              queryVector: { float32: probeVec },\n              topK: 100,\n              returnMetadata: false,\n              returnDistance: false,\n            })\n          )\n          const seen = new Set((qr.vectors ?? []).map((v: any) => v.key))\n          absentOk = absent.every((k) => !seen.has(k))\n        } catch {\n          absentOk = false\n        }\n      }\n\n      if (presentOk && absentOk) return\n      if (Date.now() >= deadline) return\n      await new Promise((r) => setTimeout(r, 300))\n    }\n  }\n\n  /** Static availability probe: whether this adapter's runtime driver can load in the current environment. */\n  static isAvailable(): boolean {\n    return typeof process !== 'undefined'\n  }\n\n  isAvailable(): boolean {\n    return typeof process !== 'undefined'\n  }\n\n  #cmd?: {\n    CreateIndexCommand: any\n    DeleteIndexCommand: any\n    ListIndexesCommand: any\n    PutVectorsCommand: any\n    QueryVectorsCommand: any\n    GetVectorsCommand: any\n    DeleteVectorsCommand: any\n  }\n\n  async connect(): Promise<void> {\n    if (this.#client) return\n    const { S3VectorsClient, ...cmd } = await getS3Vectors()\n    this.#cmd = cmd\n    const { region, credentials } = this.#opts.connection\n    try {\n      this.#client = new S3VectorsClient({ region, credentials })\n    } catch (err) {\n      throw new E_VECTOR_STORE_CONNECTION_FAILED([String(err)])\n    }\n  }\n\n  async close(): Promise<void> {\n    if (this.#client) {\n      await this.#client.destroy?.()\n      this.#client = null\n      this.#cmd = undefined\n    }\n  }\n\n  async createCollection(spec: CollectionSpec, ifNotExists: boolean): Promise<void> {\n    const collection = spec.collection\n    const physicalIndex = this.#index(collection)\n    const dims = spec.vector.dimensions\n    const metric = spec.vector.metric\n\n    // Map metric (throws on dot)\n    const s3Metric = mapMetricToS3(metric)\n\n    this.#dims.set(collection, dims)\n    this.#metrics.set(collection, metric)\n\n    if (ifNotExists) {\n      if (await this.hasCollection(collection)) return\n    }\n\n    try {\n      await this.connect()\n      await this.#client!.send(\n        new this.#cmd!.CreateIndexCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n          indexName: physicalIndex,\n          dataType: 'float32',\n          dimension: dims,\n          distanceMetric: s3Metric,\n        })\n      )\n\n      // Brief settle to ensure index is queryable (create has propagation delay)\n      const probeVec = new Array(dims).fill(0).map((_, i) => (i === 0 ? 1 : 0))\n      const deadline = Date.now() + 5_000\n      while (Date.now() < deadline) {\n        try {\n          await this.#client!.send(\n            new this.#cmd!.QueryVectorsCommand({\n              vectorBucketName: this.#opts.connection.bucket,\n              indexName: physicalIndex,\n              queryVector: { float32: probeVec },\n              topK: 1,\n              returnMetadata: false,\n              returnDistance: false,\n            })\n          )\n          break\n        } catch {\n          await new Promise((r) => setTimeout(r, 100))\n        }\n      }\n    } catch (err: any) {\n      throw new E_VECTOR_STORE_COLLECTION_FAILED(['createCollection', String(err)])\n    }\n  }\n\n  async dropCollection(collection: string, ifExists: boolean): Promise<void> {\n    const physicalIndex = this.#index(collection)\n\n    if (ifExists) {\n      if (!(await this.hasCollection(collection))) return\n    } else if (!(await this.hasCollection(collection))) {\n      return\n    }\n\n    try {\n      await this.connect()\n      await this.#client!.send(\n        new this.#cmd!.DeleteIndexCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n          indexName: physicalIndex,\n        })\n      )\n\n      // Clear local state\n      this.#dims.delete(collection)\n      this.#metrics.delete(collection)\n    } catch (err: any) {\n      const msg = String(err)\n      if (ifExists && (msg.includes('not found') || msg.includes('ResourceNotFoundException'))) {\n        return\n      }\n      throw new E_VECTOR_STORE_COLLECTION_FAILED(['dropCollection', msg])\n    }\n  }\n\n  async hasCollection(collection: string): Promise<boolean> {\n    await this.connect()\n    try {\n      const { indexes } = await this.#client!.send(\n        new this.#cmd!.ListIndexesCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n        })\n      )\n      const physicalIndex = this.#index(collection)\n      return !!indexes?.find((idx: any) => idx.indexName === physicalIndex)\n    } catch {\n      return false\n    }\n  }\n\n  async renameCollection(_from: string, _to: string): Promise<void> {\n    throw new E_VECTOR_STORE_UNSUPPORTED_OPERATION(['renameCollection', 's3vectors'])\n  }\n\n  async executeUpsert(plan: UpsertPlan): Promise<void> {\n    if (plan.records.length === 0) return\n    validateRecords(plan.records)\n\n    const collection = plan.collection\n    const physicalIndex = this.#index(collection)\n    const dims = this.#dims.get(collection) ?? this.#opts.dimensions\n\n    try {\n      await this.connect()\n\n      const vectors: any[] = []\n      for (const r of plan.records) {\n        let vector = r.vector\n        if (!vector && r.document) {\n          const [v] = await this.encode([r.document], 'document')\n          vector = v\n        }\n        if (!vector) {\n          throw new E_VECTOR_STORE_UPSERT_FAILED(['Record missing vector and document'])\n        }\n        if (dims !== undefined && vector.length !== dims) {\n          throw new E_VECTOR_STORE_DIMENSION_MISMATCH([dims, vector.length])\n        }\n        vectors.push({\n          key: r.id,\n          data: { float32: vector },\n          metadata: { ...sanitizeMetadata(r.metadata ?? {}), __document: r.document ?? '' },\n        })\n      }\n\n      await this.#client!.send(\n        new this.#cmd!.PutVectorsCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n          indexName: physicalIndex,\n          vectors,\n        })\n      )\n\n      // Settle until keys are visible\n      await this.#settle(physicalIndex, { present: plan.records.map((r) => r.id) })\n    } catch (err) {\n      if (\n        isInstanceOf(err, 'E_VECTOR_STORE_DIMENSION_MISMATCH', E_VECTOR_STORE_DIMENSION_MISMATCH) ||\n        isInstanceOf(err, 'E_VECTOR_STORE_UPSERT_FAILED', E_VECTOR_STORE_UPSERT_FAILED)\n      ) {\n        throw err\n      }\n      throw new E_VECTOR_STORE_UPSERT_FAILED([String(err)])\n    }\n  }\n\n  async executeSearch(plan: SearchPlan): Promise<VectorMatch[]> {\n    await this.connect()\n    const collection = plan.collection\n    const physicalIndex = this.#index(collection)\n    const metric = this.#metrics.get(collection) ?? this.#opts.metric ?? 'cosine'\n    const offset = plan.offset ?? 0\n\n    let queryVector: number[] | undefined\n    if (plan.near) {\n      if ('vector' in plan.near) {\n        queryVector = plan.near.vector\n      } else if ('serverText' in plan.near) {\n        const [v] = await this.encode([plan.near.serverText], 'query')\n        queryVector = v\n      } else if ('id' in plan.near) {\n        try {\n          const res = await this.#client!.send(\n            new this.#cmd!.GetVectorsCommand({\n              vectorBucketName: this.#opts.connection.bucket,\n              indexName: physicalIndex,\n              keys: [plan.near.id],\n              returnData: true,\n              returnMetadata: true,\n            })\n          )\n          const vec = res.vectors?.[0]\n          if (!vec || !vec.data?.float32) {\n            throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n          }\n          queryVector = vec.data.float32\n        } catch (err: any) {\n          if (\n            err?.message?.includes('not found') ||\n            err?.message?.includes('ResourceNotFoundException')\n          ) {\n            throw new E_VECTOR_STORE_SEARCH_FAILED(['Referenced id not found: ' + plan.near.id])\n          }\n          throw new E_VECTOR_STORE_SEARCH_FAILED([String(err)])\n        }\n      }\n    }\n\n    const topK = plan.topK\n    if (queryVector) {\n      // Similarity search: QueryVectors with oversampling + JS-filter.\n      // S3 Vectors caps topK at 100, so over-fetch up to that ceiling.\n      const k = plan.filter ? 100 : Math.min(100, Math.max(topK + offset, 10))\n      const res = await this.#client!.send(\n        new this.#cmd!.QueryVectorsCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n          indexName: physicalIndex,\n          queryVector: { float32: queryVector },\n          topK: k,\n          returnMetadata: true,\n          returnDistance: true,\n        })\n      )\n\n      let rawMatches = res.vectors ?? []\n      // Filter by JS-evaluateFilter if plan.filter present\n      if (plan.filter) {\n        rawMatches = rawMatches.filter((v: any) => {\n          const meta: VectorMetadata = {}\n          for (const key in v.metadata) {\n            if (key !== '__document') meta[key] = v.metadata[key]\n          }\n          return evaluateFilter(plan.filter!, meta)\n        })\n      }\n      // Slice offset+topK\n      rawMatches = rawMatches.slice(offset, offset + topK)\n\n      // Project matches, recompute scores, and fetch vectors if needed\n      const projected: VectorMatch[] = []\n      const keysToFetch = new Set<string>()\n      if (plan.projection.vector) {\n        for (const v of rawMatches) keysToFetch.add(v.key)\n      }\n\n      // Fetch vectors only when projected\n      const vecStore: Record<string, number[]> = {}\n      if (keysToFetch.size > 0) {\n        const batch = Array.from(keysToFetch)\n        const vecRes = await this.#client!.send(\n          new this.#cmd!.GetVectorsCommand({\n            vectorBucketName: this.#opts.connection.bucket,\n            indexName: physicalIndex,\n            keys: batch,\n            returnData: true,\n            returnMetadata: false,\n          })\n        )\n        for (const v of vecRes.vectors ?? []) {\n          if (v.data?.float32) vecStore[v.key] = v.data.float32\n        }\n      }\n\n      for (const v of rawMatches) {\n        const proj: VectorMatch = {}\n        if (plan.projection.id) proj.id = v.key\n        if (plan.projection.document) {\n          proj.document = typeof v.metadata?.__document === 'string' ? v.metadata.__document : ''\n        }\n        if (plan.projection.metadata) {\n          const meta: VectorMetadata = {}\n          for (const key in v.metadata) {\n            if (key !== '__document') meta[key] = v.metadata[key]\n          }\n          proj.metadata = meta\n        }\n        if (plan.projection.vector) {\n          proj.vector = vecStore[v.key]\n        }\n        if (plan.near && v.distance !== undefined) {\n          proj.score = scoreFromDistance(v.distance, metric)\n        }\n        projected.push(proj)\n      }\n\n      return projected\n    } else {\n      // Filter-scan: over-fetch via QueryVectors with arbitrary vector, JS-filter, project without score\n      const res = await this.#client!.send(\n        new this.#cmd!.QueryVectorsCommand({\n          vectorBucketName: this.#opts.connection.bucket,\n          indexName: physicalIndex,\n          queryVector: {\n            float32: new Array(this.#opts.dimensions ?? 3).fill(0).map((_, i) => (i === 0 ? 1 : 0)),\n          },\n          topK: 100, // S3 Vectors max topK\n          returnMetadata: true,\n          returnDistance: false,\n        })\n      )\n\n      let rawMatches = res.vectors ?? []\n      // JS-filter for parity, then slice\n      if (plan.filter) {\n        rawMatches = rawMatches.filter((v: any) => {\n          const meta: VectorMetadata = {}\n          for (const key in v.metadata) {\n            if (key !== '__document') meta[key] = v.metadata[key]\n          }\n          return evaluateFilter(plan.filter!, meta)\n        })\n      }\n      rawMatches = rawMatches.slice(offset, offset + topK)\n\n      // Fetch vectors only when projected\n      const vecStore: Record<string, number[]> = {}\n      if (plan.projection.vector && rawMatches.length > 0) {\n        const vecRes = await this.#client!.send(\n          new this.#cmd!.GetVectorsCommand({\n            vectorBucketName: this.#opts.connection.bucket,\n            indexName: physicalIndex,\n            keys: rawMatches.map((v: any) => v.key),\n            returnData: true,\n            returnMetadata: false,\n          })\n        )\n        for (const v of vecRes.vectors ?? []) {\n          if (v.data?.float32) vecStore[v.key] = v.data.float32\n        }\n      }\n\n      const projected: VectorMatch[] = []\n      for (const v of rawMatches) {\n        const proj: VectorMatch = {}\n        if (plan.projection.id) proj.id = v.key\n        if (plan.projection.document) {\n          proj.document = typeof v.metadata?.__document === 'string' ? v.metadata.__document : ''\n        }\n        if (plan.projection.metadata) {\n          const meta: VectorMetadata = {}\n          for (const key in v.metadata) {\n            if (key !== '__document') meta[key] = v.metadata[key]\n          }\n          proj.metadata = meta\n        }\n        if (plan.projection.vector) proj.vector = vecStore[v.key]\n        // filter-scan: no score\n        projected.push(proj)\n      }\n\n      return projected\n    }\n  }\n\n  async executeDelete(plan: DeletePlan): Promise<void> {\n    const collection = plan.collection\n    const physicalIndex = this.#index(collection)\n\n    try {\n      await this.connect()\n      const bucket = this.#opts.connection.bucket\n\n      if (plan.ids && plan.ids.length > 0) {\n        await this.#client!.send(\n          new this.#cmd!.DeleteVectorsCommand({\n            vectorBucketName: bucket,\n            indexName: physicalIndex,\n            keys: plan.ids,\n          })\n        )\n        // Settle until absent\n        await this.#settle(physicalIndex, { absent: plan.ids })\n      } else if (plan.filter) {\n        // Enumerate all, JS-filter, delete matched\n        const res = await this.#client!.send(\n          new this.#cmd!.QueryVectorsCommand({\n            vectorBucketName: bucket,\n            indexName: physicalIndex,\n            queryVector: {\n              float32: new Array(this.#opts.dimensions ?? 3)\n                .fill(0)\n                .map((_, i) => (i === 0 ? 1 : 0)),\n            },\n            topK: 100, // S3 Vectors max topK\n            returnMetadata: true,\n            returnDistance: false,\n          })\n        )\n\n        const targets: string[] = []\n        for (const v of res.vectors ?? []) {\n          const evalMeta: VectorMetadata = {}\n          for (const key in v.metadata) {\n            if (key !== '__document') evalMeta[key] = v.metadata[key]\n          }\n          if (evaluateFilter(plan.filter, evalMeta)) {\n            targets.push(v.key)\n          }\n        }\n\n        if (targets.length > 0) {\n          await this.#client!.send(\n            new this.#cmd!.DeleteVectorsCommand({\n              vectorBucketName: bucket,\n              indexName: physicalIndex,\n              keys: targets,\n            })\n          )\n          // Settle until absent\n          await this.#settle(physicalIndex, { absent: targets })\n        }\n      } else {\n        // Delete all: enumerate all keys + delete\n        const res = await this.#client!.send(\n          new this.#cmd!.QueryVectorsCommand({\n            vectorBucketName: bucket,\n            indexName: physicalIndex,\n            queryVector: {\n              float32: new Array(this.#opts.dimensions ?? 3)\n                .fill(0)\n                .map((_, i) => (i === 0 ? 1 : 0)),\n            },\n            topK: 100, // S3 Vectors max topK\n            returnMetadata: false,\n            returnDistance: false,\n          })\n        )\n        const allKeys = (res.vectors ?? []).map((v: any) => v.key)\n\n        // If index has many vectors, may need pagination; but S3 Vectors QueryVectors is limited to 1000\n        // For truly large collections, users should use filter-scan pattern explicitly.\n        // Here, we do a best-effort single-page delete.\n        if (allKeys.length > 0) {\n          await this.#client!.send(\n            new this.#cmd!.DeleteVectorsCommand({\n              vectorBucketName: bucket,\n              indexName: physicalIndex,\n              keys: allKeys,\n            })\n          )\n          // Settle until absent\n          await this.#settle(physicalIndex, { absent: allKeys })\n        }\n      }\n    } catch (err: any) {\n      throw new E_VECTOR_STORE_DELETE_FAILED([String(err)])\n    }\n  }\n}\n"],"mappings":"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"}