{"version":3,"file":"memory.cjs","names":["RecordManager"],"sources":["../../src/indexes/memory.ts"],"sourcesContent":["import {\n  ListKeyOptions,\n  RecordManager,\n  UpdateOptions,\n} from \"@langchain/core/indexing\";\n\ninterface MemoryRecord {\n  updatedAt: number;\n  groupId: string | null;\n}\n\nexport class InMemoryRecordManager extends RecordManager {\n  lc_namespace = [\"langchain\", \"recordmanagers\", \"memory\"];\n\n  records: Map<string, MemoryRecord>;\n\n  constructor() {\n    super();\n    this.records = new Map();\n  }\n\n  async createSchema(): Promise<void> {\n    // nothing to do here\n    // compatibility with other record managers\n    return Promise.resolve();\n  }\n\n  async getTime(): Promise<number> {\n    return Promise.resolve(Date.now());\n  }\n\n  async update(keys: string[], updateOptions?: UpdateOptions): Promise<void> {\n    const updatedAt = await this.getTime();\n    const { timeAtLeast, groupIds: _groupIds } = updateOptions ?? {};\n\n    if (timeAtLeast && updatedAt < timeAtLeast) {\n      throw new Error(\n        `Time sync issue with database ${updatedAt} < ${timeAtLeast}`\n      );\n    }\n\n    const groupIds = _groupIds ?? keys.map(() => null);\n\n    if (groupIds.length !== keys.length) {\n      throw new Error(\n        `Number of keys (${keys.length}) does not match number of group_ids ${groupIds.length})`\n      );\n    }\n\n    keys.forEach((key, i) => {\n      const old = this.records.get(key);\n      if (old) {\n        old.updatedAt = updatedAt;\n      } else {\n        this.records.set(key, { updatedAt, groupId: groupIds[i] });\n      }\n    });\n  }\n\n  async exists(keys: string[]): Promise<boolean[]> {\n    return Promise.resolve(keys.map((key) => this.records.has(key)));\n  }\n\n  async listKeys(options?: ListKeyOptions): Promise<string[]> {\n    const { before, after, limit, groupIds } = options ?? {};\n\n    const filteredRecords = Array.from(this.records).filter(([_key, doc]) => {\n      // Inclusive bounds for before and after (i.e. <= and >=).\n      // This is technically incorrect, but because there is no\n      // latency, it is not garanteed that after an update the\n      // timestamp on subsequent listKeys calls will be different.\n      const isBefore = !before || doc.updatedAt <= before;\n      const isAfter = !after || doc.updatedAt >= after;\n      const belongsToGroup = !groupIds || groupIds.includes(doc.groupId);\n      return isBefore && isAfter && belongsToGroup;\n    });\n\n    return Promise.resolve(\n      filteredRecords\n        .map(([key]) => key)\n        .slice(0, limit ?? filteredRecords.length)\n    );\n  }\n\n  async deleteKeys(keys: string[]): Promise<void> {\n    keys.forEach((key) => this.records.delete(key));\n    return Promise.resolve();\n  }\n}\n"],"mappings":";;;;;AAWA,IAAa,wBAAb,cAA2CA,yBAAAA,cAAc;CACvD,eAAe;EAAC;EAAa;EAAkB;EAAS;CAExD;CAEA,cAAc;AACZ,SAAO;AACP,OAAK,0BAAU,IAAI,KAAK;;CAG1B,MAAM,eAA8B;AAGlC,SAAO,QAAQ,SAAS;;CAG1B,MAAM,UAA2B;AAC/B,SAAO,QAAQ,QAAQ,KAAK,KAAK,CAAC;;CAGpC,MAAM,OAAO,MAAgB,eAA8C;EACzE,MAAM,YAAY,MAAM,KAAK,SAAS;EACtC,MAAM,EAAE,aAAa,UAAU,cAAc,iBAAiB,EAAE;AAEhE,MAAI,eAAe,YAAY,YAC7B,OAAM,IAAI,MACR,iCAAiC,UAAU,KAAK,cACjD;EAGH,MAAM,WAAW,aAAa,KAAK,UAAU,KAAK;AAElD,MAAI,SAAS,WAAW,KAAK,OAC3B,OAAM,IAAI,MACR,mBAAmB,KAAK,OAAO,uCAAuC,SAAS,OAAO,GACvF;AAGH,OAAK,SAAS,KAAK,MAAM;GACvB,MAAM,MAAM,KAAK,QAAQ,IAAI,IAAI;AACjC,OAAI,IACF,KAAI,YAAY;OAEhB,MAAK,QAAQ,IAAI,KAAK;IAAE;IAAW,SAAS,SAAS;IAAI,CAAC;IAE5D;;CAGJ,MAAM,OAAO,MAAoC;AAC/C,SAAO,QAAQ,QAAQ,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC;;CAGlE,MAAM,SAAS,SAA6C;EAC1D,MAAM,EAAE,QAAQ,OAAO,OAAO,aAAa,WAAW,EAAE;EAExD,MAAM,kBAAkB,MAAM,KAAK,KAAK,QAAQ,CAAC,QAAQ,CAAC,MAAM,SAAS;GAKvE,MAAM,WAAW,CAAC,UAAU,IAAI,aAAa;GAC7C,MAAM,UAAU,CAAC,SAAS,IAAI,aAAa;GAC3C,MAAM,iBAAiB,CAAC,YAAY,SAAS,SAAS,IAAI,QAAQ;AAClE,UAAO,YAAY,WAAW;IAC9B;AAEF,SAAO,QAAQ,QACb,gBACG,KAAK,CAAC,SAAS,IAAI,CACnB,MAAM,GAAG,SAAS,gBAAgB,OAAO,CAC7C;;CAGH,MAAM,WAAW,MAA+B;AAC9C,OAAK,SAAS,QAAQ,KAAK,QAAQ,OAAO,IAAI,CAAC;AAC/C,SAAO,QAAQ,SAAS"}