{"version":3,"file":"InMemoryLruCache.mjs","names":[],"sources":["../../../src/modules/cache/InMemoryLruCache.ts"],"sourcesContent":["import LRUMap from 'lru_map'\nimport type { AgentContext } from '../../agent/context'\nimport type { Cache, CacheOptions } from './Cache'\n\nexport interface InMemoryLruCacheOptions {\n  /** The maximum number of entries allowed in the cache */\n  limit: number\n}\n\n/**\n * In memory LRU cache.\n *\n * This cache can be used with multiple agent context instances. Keys are namespaced by the\n * `contextCorrelationId` of the agent context by default, and by `global:` for entries using the\n * `'global'` scope. Note that separate root agent instances sharing this cache also share the\n * `default` context namespace.\n *\n * The `limit` applies to the cache as a whole, spanning all contexts and the global scope, so a\n * busy context can evict entries of other contexts. `clear()` also clears all scopes and contexts.\n */\nexport class InMemoryLruCache implements Cache {\n  private readonly cache: LRUMap.LRUMap<string, CacheItem>\n\n  public constructor({ limit }: InMemoryLruCacheOptions) {\n    this.cache = new LRUMap.LRUMap<string, CacheItem>(limit)\n  }\n\n  private getNamespacedKey(agentContext: AgentContext, key: string, options?: CacheOptions) {\n    if (options?.scope === 'global') {\n      return `global:${key}`\n    }\n\n    return `${agentContext.contextCorrelationId}:${key}`\n  }\n\n  public async get<CacheValue>(agentContext: AgentContext, key: string, options?: CacheOptions) {\n    this.removeExpiredItems()\n    key = this.getNamespacedKey(agentContext, key, options)\n    const item = this.cache.get(key)\n\n    // Does not exist\n    if (!item) return null\n\n    return item.value as CacheValue\n  }\n\n  public async set<CacheValue>(\n    agentContext: AgentContext,\n    key: string,\n    value: CacheValue,\n    expiresInSeconds?: number,\n    options?: CacheOptions\n  ): Promise<void> {\n    this.removeExpiredItems()\n    let expiresDate: Date | undefined\n\n    if (expiresInSeconds) {\n      expiresDate = new Date()\n      expiresDate.setSeconds(expiresDate.getSeconds() + expiresInSeconds)\n    }\n\n    key = this.getNamespacedKey(agentContext, key, options)\n    this.cache.set(key, {\n      expiresAt: expiresDate?.getTime(),\n      value,\n    })\n  }\n\n  public clear() {\n    this.cache.clear()\n  }\n\n  public async remove(agentContext: AgentContext, key: string, options?: CacheOptions): Promise<void> {\n    this.removeExpiredItems()\n    key = this.getNamespacedKey(agentContext, key, options)\n    this.cache.delete(key)\n  }\n\n  private removeExpiredItems() {\n    this.cache.forEach((value, key) => {\n      if (value.expiresAt && Date.now() > value.expiresAt) {\n        this.cache.delete(key)\n      }\n    })\n  }\n}\n\ninterface CacheItem {\n  expiresAt?: number\n  value: unknown\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,IAAa,mBAAb,MAA+C;CAG7C,YAAmB,EAAE,SAAkC;EACrD,KAAK,QAAQ,IAAI,OAAO,OAA0B,KAAK;CACzD;CAEA,iBAAyB,cAA4B,KAAa,SAAwB;EACxF,IAAI,SAAS,UAAU,UACrB,OAAO,UAAU;EAGnB,OAAO,GAAG,aAAa,qBAAqB,GAAG;CACjD;CAEA,MAAa,IAAgB,cAA4B,KAAa,SAAwB;EAC5F,KAAK,mBAAmB;EACxB,MAAM,KAAK,iBAAiB,cAAc,KAAK,OAAO;EACtD,MAAM,OAAO,KAAK,MAAM,IAAI,GAAG;EAG/B,IAAI,CAAC,MAAM,OAAO;EAElB,OAAO,KAAK;CACd;CAEA,MAAa,IACX,cACA,KACA,OACA,kBACA,SACe;EACf,KAAK,mBAAmB;EACxB,IAAI;EAEJ,IAAI,kBAAkB;GACpB,8BAAc,IAAI,KAAK;GACvB,YAAY,WAAW,YAAY,WAAW,IAAI,gBAAgB;EACpE;EAEA,MAAM,KAAK,iBAAiB,cAAc,KAAK,OAAO;EACtD,KAAK,MAAM,IAAI,KAAK;GAClB,WAAW,aAAa,QAAQ;GAChC;EACF,CAAC;CACH;CAEA,QAAe;EACb,KAAK,MAAM,MAAM;CACnB;CAEA,MAAa,OAAO,cAA4B,KAAa,SAAuC;EAClG,KAAK,mBAAmB;EACxB,MAAM,KAAK,iBAAiB,cAAc,KAAK,OAAO;EACtD,KAAK,MAAM,OAAO,GAAG;CACvB;CAEA,qBAA6B;EAC3B,KAAK,MAAM,SAAS,OAAO,QAAQ;GACjC,IAAI,MAAM,aAAa,KAAK,IAAI,IAAI,MAAM,WACxC,KAAK,MAAM,OAAO,GAAG;EAEzB,CAAC;CACH;AACF"}