{"version":3,"sources":["../src/web-storage.ts"],"names":["deserializeMessages","validateMemoryRecord","serializeMessages","MemoryError","ErrorCodes"],"mappings":"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","file":"web-storage.cjs","sourcesContent":["import { deserializeMessages, ErrorCodes, MemoryError, serializeMessages } from '@agentskit/core'\nimport { validateMemoryRecord } from '@agentskit/core/memory-validation'\nimport type { ChatMemory, Message } from '@agentskit/core'\n\nexport interface WebStorageLike {\n  readonly getItem: (key: string) => string | null\n  readonly setItem: (key: string, value: string) => void\n  readonly removeItem: (key: string) => void\n}\n\nexport interface WebStorageMemoryMigration {\n  readonly keys: readonly string[]\n  readonly read: (value: unknown, key: string) => readonly Message[] | undefined\n}\n\nexport interface WebStorageMemoryOptions {\n  readonly key: string\n  readonly getStorage: () => WebStorageLike | undefined\n  readonly maxMessages?: number\n  readonly maxRecordBytes?: number\n  readonly migration?: WebStorageMemoryMigration\n}\n\nconst positiveInteger = (value: number, name: string): number => {\n  if (!Number.isSafeInteger(value) || value < 1) throw new TypeError(`${name} must be a positive safe integer.`)\n  return value\n}\n\nconst withinByteLimit = (value: string, limit: number): boolean =>\n  value.length <= limit && new TextEncoder().encode(value).byteLength <= limit\n\nconst parseCanonical = (raw: string, maxRecordBytes: number): Message[] | undefined => {\n  if (!withinByteLimit(raw, maxRecordBytes)) return undefined\n  try {\n    return deserializeMessages(validateMemoryRecord(JSON.parse(raw) as unknown))\n  } catch {\n    return undefined\n  }\n}\n\nconst validateMigrated = (messages: readonly Message[]): Message[] | undefined => {\n  try {\n    return deserializeMessages(validateMemoryRecord(serializeMessages([...messages])))\n  } catch {\n    return undefined\n  }\n}\n\nconst encodeRecord = (messages: readonly Message[], maxRecordBytes: number): string => {\n  let encoded: string\n  try {\n    encoded = JSON.stringify(validateMemoryRecord(serializeMessages([...messages])))\n  } catch (cause) {\n    throw new MemoryError({\n      code: ErrorCodes.AK_MEMORY_SAVE_FAILED,\n      message: 'Web Storage message record is invalid.',\n      hint: 'Save only canonical AgentsKit messages.',\n      cause,\n    })\n  }\n  if (!withinByteLimit(encoded, maxRecordBytes)) {\n    throw new MemoryError({\n      code: ErrorCodes.AK_MEMORY_SAVE_FAILED,\n      message: 'Web Storage message record exceeds the configured byte limit.',\n      hint: 'Reduce message history or increase maxRecordBytes before saving.',\n    })\n  }\n  return encoded\n}\n\n/**\n * Creates a validated, bounded ChatMemory over an injected browser Web Storage backend.\n * The storage getter is evaluated lazily so browser globals can remain SSR-safe.\n */\nexport function createWebStorageMemory({\n  key,\n  getStorage,\n  maxMessages = 20,\n  maxRecordBytes = 1_048_576,\n  migration,\n}: WebStorageMemoryOptions): ChatMemory {\n  if (key.length === 0) throw new TypeError('key must not be empty.')\n  const retained = positiveInteger(maxMessages, 'maxMessages')\n  const byteLimit = positiveInteger(maxRecordBytes, 'maxRecordBytes')\n\n  return {\n    async load(options) {\n      options?.signal?.throwIfAborted()\n      const storage = getStorage()\n      if (!storage) return []\n      for (const candidateKey of [key, ...(migration?.keys ?? [])]) {\n        options?.signal?.throwIfAborted()\n        const raw = storage.getItem(candidateKey)\n        if (raw === null) continue\n        const canonical = candidateKey === key ? parseCanonical(raw, byteLimit) : undefined\n        let messages = canonical\n        if (messages === undefined && candidateKey !== key && withinByteLimit(raw, byteLimit) && migration) {\n          try {\n            const migrated = migration.read(JSON.parse(raw) as unknown, candidateKey)\n            messages = migrated === undefined ? undefined : validateMigrated(migrated)\n          } catch {\n            messages = undefined\n          }\n        }\n        if (messages === undefined) {\n          try { storage.removeItem(candidateKey) } catch { /* best-effort invalid-record cleanup */ }\n          continue\n        }\n        const bounded = messages.slice(-retained)\n        if (candidateKey !== key) {\n          const encoded = encodeRecord(bounded, byteLimit)\n          try {\n            storage.setItem(key, encoded)\n            storage.removeItem(candidateKey)\n          } catch {\n            // Valid legacy data remains readable when storage is read-only or full.\n          }\n        }\n        return bounded\n      }\n      return []\n    },\n    async save(messages, options) {\n      options?.signal?.throwIfAborted()\n      const storage = getStorage()\n      if (!storage) return\n      const encoded = encodeRecord(messages.slice(-retained), byteLimit)\n      storage.setItem(key, encoded)\n    },\n    async clear(options) {\n      options?.signal?.throwIfAborted()\n      const storage = getStorage()\n      if (!storage) return\n      for (const candidateKey of [key, ...(migration?.keys ?? [])]) storage.removeItem(candidateKey)\n    },\n  }\n}\n"]}