{"version":3,"file":"memory.cjs","names":["BaseStore","tokenizePath","candidates: Item[]","compareValues","flatItems: Item[]","flatVectors: number[][]","scoreless: Item[]","kept: Array<[number | undefined, Item]>","toEmbed: { [text: string]: [string[], string, string][] }","getTextAtPath"],"sources":["../../src/store/memory.ts"],"sourcesContent":["import {\n  BaseStore,\n  type OperationResults,\n  type Item,\n  type Operation,\n  MatchCondition,\n  ListNamespacesOperation,\n  PutOperation,\n  SearchOperation,\n  GetOperation,\n  type IndexConfig,\n  type SearchItem,\n} from \"./base.js\";\nimport { tokenizePath, compareValues, getTextAtPath } from \"./utils.js\";\n\n/**\n * In-memory key-value store with optional vector search.\n *\n * A lightweight store implementation using JavaScript Maps. Supports basic\n * key-value operations and vector search when configured with embeddings.\n *\n * @example\n * ```typescript\n * // Basic key-value storage\n * const store = new InMemoryStore();\n * await store.put([\"users\", \"123\"], \"prefs\", { theme: \"dark\" });\n * const item = await store.get([\"users\", \"123\"], \"prefs\");\n *\n * // Vector search with embeddings\n * import { OpenAIEmbeddings } from \"@langchain/openai\";\n * const store = new InMemoryStore({\n *   index: {\n *     dims: 1536,\n *     embeddings: new OpenAIEmbeddings({ modelName: \"text-embedding-3-small\" }),\n *   }\n * });\n *\n * // Store documents\n * await store.put([\"docs\"], \"doc1\", { text: \"Python tutorial\" });\n * await store.put([\"docs\"], \"doc2\", { text: \"TypeScript guide\" });\n *\n * // Search by similarity\n * const results = await store.search([\"docs\"], { query: \"python programming\" });\n * ```\n *\n * **Warning**: This store keeps all data in memory. Data is lost when the process exits.\n * For persistence, use a database-backed store.\n */\nexport class InMemoryStore extends BaseStore {\n  private data: Map<string, Map<string, Item>> = new Map();\n\n  // Namespace -> Key -> Path/field -> Vector\n  private vectors: Map<string, Map<string, Map<string, number[]>>> = new Map();\n\n  private _indexConfig?: IndexConfig & {\n    __tokenizedFields: Array<[string, string[]]>;\n  };\n\n  constructor(options?: { index?: IndexConfig }) {\n    super();\n    if (options?.index) {\n      this._indexConfig = {\n        ...options.index,\n        __tokenizedFields: (options.index.fields ?? [\"$\"]).map((p) => [\n          p,\n          p === \"$\" ? [p] : tokenizePath(p),\n        ]),\n      };\n    }\n  }\n\n  async batch<Op extends readonly Operation[]>(\n    operations: Op\n  ): Promise<OperationResults<Op>> {\n    const results = [];\n    const putOps = new Map<string, PutOperation>();\n    const searchOps = new Map<number, [SearchOperation, Item[]]>();\n\n    // First pass - handle gets and prepare search/put operations\n    for (let i = 0; i < operations.length; i += 1) {\n      const op = operations[i];\n      if (\"key\" in op && \"namespace\" in op && !(\"value\" in op)) {\n        // GetOperation\n        results.push(this.getOperation(op));\n      } else if (\"namespacePrefix\" in op) {\n        // SearchOperation\n        const candidates = this.filterItems(op);\n        searchOps.set(i, [op, candidates]);\n        results.push(null);\n      } else if (\"value\" in op) {\n        // PutOperation\n        const key = `${op.namespace.join(\":\")}:${op.key}`;\n        putOps.set(key, op);\n        results.push(null);\n      } else if (\"matchConditions\" in op) {\n        // ListNamespacesOperation\n        results.push(this.listNamespacesOperation(op));\n      }\n    }\n\n    // Handle search operations with embeddings\n    if (searchOps.size > 0) {\n      if (this._indexConfig?.embeddings) {\n        const queries = new Set<string>();\n        for (const [op] of searchOps.values()) {\n          if (op.query) queries.add(op.query);\n        }\n\n        // Get embeddings for all queries\n        const queryEmbeddings =\n          queries.size > 0\n            ? await Promise.all(\n                Array.from(queries).map((q) =>\n                  this._indexConfig!.embeddings.embedQuery(q)\n                )\n              )\n            : [];\n        const queryVectors = Object.fromEntries(\n          Array.from(queries).map((q, i) => [q, queryEmbeddings[i]])\n        );\n\n        // Process each search operation\n        for (const [i, [op, candidates]] of searchOps.entries()) {\n          if (op.query && queryVectors[op.query]) {\n            const queryVector = queryVectors[op.query];\n            const scoredResults = this.scoreResults(\n              candidates,\n              queryVector,\n              op.offset ?? 0,\n              op.limit ?? 10\n            );\n            results[i] = scoredResults;\n          } else {\n            results[i] = this.paginateResults(\n              candidates.map((item) => ({ ...item, score: undefined })),\n              op.offset ?? 0,\n              op.limit ?? 10\n            );\n          }\n        }\n      } else {\n        // No embeddings - just paginate the filtered results\n        for (const [i, [op, candidates]] of searchOps.entries()) {\n          results[i] = this.paginateResults(\n            candidates.map((item) => ({ ...item, score: undefined })),\n            op.offset ?? 0,\n            op.limit ?? 10\n          );\n        }\n      }\n    }\n\n    // Handle put operations with embeddings\n    if (putOps.size > 0 && this._indexConfig?.embeddings) {\n      const toEmbed = this.extractTexts(Array.from(putOps.values()));\n      if (Object.keys(toEmbed).length > 0) {\n        const embeddings = await this._indexConfig.embeddings.embedDocuments(\n          Object.keys(toEmbed)\n        );\n        this.insertVectors(toEmbed, embeddings);\n      }\n    }\n\n    // Apply all put operations\n    for (const op of putOps.values()) {\n      this.putOperation(op);\n    }\n\n    return results as OperationResults<Op>;\n  }\n\n  private getOperation(op: GetOperation): Item | null {\n    const namespaceKey = op.namespace.join(\":\");\n    const item = this.data.get(namespaceKey)?.get(op.key);\n    return item ?? null;\n  }\n\n  private putOperation(op: PutOperation): void {\n    const namespaceKey = op.namespace.join(\":\");\n    if (!this.data.has(namespaceKey)) {\n      this.data.set(namespaceKey, new Map());\n    }\n    const namespaceMap = this.data.get(namespaceKey)!;\n\n    if (op.value === null) {\n      namespaceMap.delete(op.key);\n    } else {\n      const now = new Date();\n      if (namespaceMap.has(op.key)) {\n        const item = namespaceMap.get(op.key)!;\n        item.value = op.value;\n        item.updatedAt = now;\n      } else {\n        namespaceMap.set(op.key, {\n          value: op.value,\n          key: op.key,\n          namespace: op.namespace,\n          createdAt: now,\n          updatedAt: now,\n        });\n      }\n    }\n  }\n\n  private listNamespacesOperation(op: ListNamespacesOperation): string[][] {\n    const allNamespaces = Array.from(this.data.keys()).map((ns) =>\n      ns.split(\":\")\n    );\n    let namespaces = allNamespaces;\n\n    if (op.matchConditions && op.matchConditions.length > 0) {\n      namespaces = namespaces.filter((ns) =>\n        op.matchConditions!.every((condition) => this.doesMatch(condition, ns))\n      );\n    }\n\n    if (op.maxDepth !== undefined) {\n      namespaces = Array.from(\n        new Set(namespaces.map((ns) => ns.slice(0, op.maxDepth).join(\":\")))\n      ).map((ns) => ns.split(\":\"));\n    }\n\n    namespaces.sort((a, b) => a.join(\":\").localeCompare(b.join(\":\")));\n\n    return namespaces.slice(\n      op.offset ?? 0,\n      (op.offset ?? 0) + (op.limit ?? namespaces.length)\n    );\n  }\n\n  private doesMatch(matchCondition: MatchCondition, key: string[]): boolean {\n    const { matchType, path } = matchCondition;\n\n    if (matchType === \"prefix\") {\n      if (path.length > key.length) return false;\n      return path.every((pElem, index) => {\n        const kElem = key[index];\n        return pElem === \"*\" || kElem === pElem;\n      });\n    } else if (matchType === \"suffix\") {\n      if (path.length > key.length) return false;\n      return path.every((pElem, index) => {\n        const kElem = key[key.length - path.length + index];\n        return pElem === \"*\" || kElem === pElem;\n      });\n    }\n\n    throw new Error(`Unsupported match type: ${matchType}`);\n  }\n\n  private filterItems(op: SearchOperation): Item[] {\n    const candidates: Item[] = [];\n    for (const [namespace, items] of this.data.entries()) {\n      if (namespace.startsWith(op.namespacePrefix.join(\":\"))) {\n        candidates.push(...items.values());\n      }\n    }\n\n    let filteredCandidates = candidates;\n    if (op.filter) {\n      filteredCandidates = candidates.filter((item) =>\n        Object.entries(op.filter!).every(([key, value]) =>\n          compareValues(item.value[key], value)\n        )\n      );\n    }\n    return filteredCandidates;\n  }\n\n  private scoreResults(\n    candidates: Item[],\n    queryVector: number[],\n    offset: number = 0,\n    limit: number = 10\n  ): SearchItem[] {\n    const flatItems: Item[] = [];\n    const flatVectors: number[][] = [];\n    const scoreless: Item[] = [];\n\n    for (const item of candidates) {\n      const vectors = this.getVectors(item);\n      if (vectors.length) {\n        for (const vector of vectors) {\n          flatItems.push(item);\n          flatVectors.push(vector);\n        }\n      } else {\n        scoreless.push(item);\n      }\n    }\n\n    const scores = this.cosineSimilarity(queryVector, flatVectors);\n\n    const sortedResults = scores\n      .map((score, i) => [score, flatItems[i]] as [number, Item])\n      .sort((a, b) => b[0] - a[0]);\n\n    const seen = new Set<string>();\n    const kept: Array<[number | undefined, Item]> = [];\n\n    for (const [score, item] of sortedResults) {\n      const key = `${item.namespace.join(\":\")}:${item.key}`;\n      if (seen.has(key)) continue;\n\n      const ix = seen.size;\n      if (ix >= offset + limit) break;\n      if (ix < offset) {\n        seen.add(key);\n        continue;\n      }\n\n      seen.add(key);\n      kept.push([score, item]);\n    }\n\n    if (scoreless.length && kept.length < limit) {\n      for (const item of scoreless.slice(0, limit - kept.length)) {\n        const key = `${item.namespace.join(\":\")}:${item.key}`;\n        if (!seen.has(key)) {\n          seen.add(key);\n          kept.push([undefined, item]);\n        }\n      }\n    }\n    return kept.map(([score, item]) => ({\n      ...item,\n      score,\n    }));\n  }\n\n  private paginateResults(\n    results: SearchItem[],\n    offset: number,\n    limit: number\n  ): SearchItem[] {\n    return results.slice(offset, offset + limit);\n  }\n\n  private extractTexts(ops: PutOperation[]): {\n    [text: string]: [string[], string, string][];\n  } {\n    if (!ops.length || !this._indexConfig) {\n      return {};\n    }\n\n    const toEmbed: { [text: string]: [string[], string, string][] } = {};\n\n    for (const op of ops) {\n      if (op.value !== null && op.index !== false) {\n        const paths =\n          op.index === null || op.index === undefined\n            ? this._indexConfig.__tokenizedFields ?? []\n            : op.index.map(\n                (ix) => [ix, tokenizePath(ix)] as [string, string[]]\n              );\n        for (const [path, field] of paths) {\n          const texts = getTextAtPath(op.value, field);\n          if (texts.length) {\n            if (texts.length > 1) {\n              texts.forEach((text, i) => {\n                if (!toEmbed[text]) toEmbed[text] = [];\n                toEmbed[text].push([op.namespace, op.key, `${path}.${i}`]);\n              });\n            } else {\n              if (!toEmbed[texts[0]]) toEmbed[texts[0]] = [];\n              toEmbed[texts[0]].push([op.namespace, op.key, path]);\n            }\n          }\n        }\n      }\n    }\n\n    return toEmbed;\n  }\n\n  private insertVectors(\n    texts: { [text: string]: [string[], string, string][] },\n    embeddings: number[][]\n  ): void {\n    for (const [text, metadata] of Object.entries(texts)) {\n      const embedding = embeddings.shift();\n      if (!embedding) {\n        throw new Error(`No embedding found for text: ${text}`);\n      }\n\n      for (const [namespace, key, field] of metadata) {\n        const namespaceKey = namespace.join(\":\");\n        if (!this.vectors.has(namespaceKey)) {\n          this.vectors.set(namespaceKey, new Map());\n        }\n        const namespaceMap = this.vectors.get(namespaceKey)!;\n        if (!namespaceMap.has(key)) {\n          namespaceMap.set(key, new Map());\n        }\n        const itemMap = namespaceMap.get(key)!;\n        itemMap.set(field, embedding);\n      }\n    }\n  }\n\n  private getVectors(item: Item): number[][] {\n    const namespaceKey = item.namespace.join(\":\");\n    const itemKey = item.key;\n    if (!this.vectors.has(namespaceKey)) {\n      return [];\n    }\n    const namespaceMap = this.vectors.get(namespaceKey)!;\n    if (!namespaceMap.has(itemKey)) {\n      return [];\n    }\n    const itemMap = namespaceMap.get(itemKey)!;\n    const vectors = Array.from(itemMap.values());\n    if (!vectors.length) {\n      return [];\n    }\n    return vectors;\n  }\n\n  private cosineSimilarity(X: number[], Y: number[][]): number[] {\n    if (!Y.length) return [];\n\n    // Calculate dot products for all vectors at once\n    const dotProducts = Y.map((vector) =>\n      vector.reduce((acc, val, i) => acc + val * X[i], 0)\n    );\n\n    // Calculate magnitudes\n    const magnitude1 = Math.sqrt(X.reduce((acc, val) => acc + val * val, 0));\n    const magnitudes2 = Y.map((vector) =>\n      Math.sqrt(vector.reduce((acc, val) => acc + val * val, 0))\n    );\n\n    // Calculate similarities\n    return dotProducts.map((dot, i) => {\n      const magnitude2 = magnitudes2[i];\n      return magnitude1 && magnitude2 ? dot / (magnitude1 * magnitude2) : 0;\n    });\n  }\n\n  public get indexConfig(): IndexConfig | undefined {\n    return this._indexConfig;\n  }\n}\n\n/** @deprecated Alias for InMemoryStore */\nexport class MemoryStore extends InMemoryStore {}\n"],"mappings":"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"}