{"version":3,"file":"memory.mjs","names":[],"sources":["../../../../../../../../ai/src/human/stores/memory.ts"],"sourcesContent":["import type {\n  InterruptStore,\n  PendingInterrupt,\n} from \"../contracts/interrupt-store.contract\";\n\n/**\n * In-memory {@link InterruptStore} — pending interrupts held in a\n * process-local `Map`, never persisted to disk.\n *\n * Owns: the `interruptId → {@link PendingInterrupt}` index and the\n * last-writer-wins `save` / `load` / `delete` / `list` semantics the\n * contract declares. Does NOT own: durability, cross-process sharing, or\n * TTL eviction — it is the zero-config default for dev, tests, and\n * single-process apps whose approval flow stays interactive (the run\n * `await`s the decision in-process and never needs to survive a restart).\n * Reach for `ai.human.interrupt.pg()` / `ai.human.interrupt.redis()` when\n * a reviewer rules out-of-process, hours later.\n *\n * Front it with the {@link memory} factory — callers never `new` it.\n */\nclass MemoryInterruptStore implements InterruptStore {\n  /** Pending interrupts keyed by their own `interruptId`. */\n  private readonly interrupts = new Map<string, PendingInterrupt>();\n\n  /**\n   * Persist a pending interrupt, keyed by its own `interruptId`.\n   * Overwrites any prior record for the same id — a call has exactly one\n   * live interrupt, so a re-save replaces rather than appends.\n   */\n  public async save(record: PendingInterrupt): Promise<void> {\n    this.interrupts.set(record.interruptId, record);\n  }\n\n  /**\n   * Return the interrupt for an `interruptId`, or `undefined` when none is\n   * recorded (never raised, or already resolved + deleted).\n   */\n  public async load(\n    interruptId: string,\n  ): Promise<PendingInterrupt | undefined> {\n    return this.interrupts.get(interruptId);\n  }\n\n  /**\n   * Drop the interrupt for an `interruptId`. Idempotent — deleting an\n   * absent id is a no-op.\n   */\n  public async delete(interruptId: string): Promise<void> {\n    this.interrupts.delete(interruptId);\n  }\n\n  /**\n   * List the interrupt ids the store knows, optionally filtered by a\n   * prefix. Returns a fresh array each call so a caller can mutate it\n   * freely without touching the backing index.\n   */\n  public async list(prefix?: string): Promise<string[]> {\n    const ids = [...this.interrupts.keys()];\n\n    if (prefix === undefined) {\n      return ids;\n    }\n\n    return ids.filter((id) => id.startsWith(prefix));\n  }\n\n  /**\n   * The memory store has no backing table — there is nothing to migrate.\n   * Returns an empty string so callers can treat `schema()` uniformly\n   * across drivers.\n   */\n  public schema(): string {\n    return \"\";\n  }\n}\n\n/**\n * Create an in-memory {@link InterruptStore}. Zero-config — no client, no\n * connection. Suitable for dev, tests, and single-process apps whose\n * approval flow stays interactive and doesn't need resume across\n * restarts.\n *\n * @example\n * import { ai } from \"@warlock.js/ai\";\n *\n * const store = ai.human.interrupt.memory();\n *\n * const agent = ai.agent({\n *   model,\n *   tools: [deleteAccount],\n *   middleware: [\n *     ai.human.approval({\n *       policy: { type: \"allowlist\", tools: [\"deleteAccount\"] },\n *       store,\n *       handler,\n *     }),\n *   ],\n * });\n */\nexport function memory(): InterruptStore {\n  return new MemoryInterruptStore();\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoBA,IAAM,uBAAN,MAAqD;;oCAErB,IAAI,IAA8B;;;;;;;CAOhE,MAAa,KAAK,QAAyC;EACzD,KAAK,WAAW,IAAI,OAAO,aAAa,MAAM;CAChD;;;;;CAMA,MAAa,KACX,aACuC;EACvC,OAAO,KAAK,WAAW,IAAI,WAAW;CACxC;;;;;CAMA,MAAa,OAAO,aAAoC;EACtD,KAAK,WAAW,OAAO,WAAW;CACpC;;;;;;CAOA,MAAa,KAAK,QAAoC;EACpD,MAAM,MAAM,CAAC,GAAG,KAAK,WAAW,KAAK,CAAC;EAEtC,IAAI,WAAW,QACb,OAAO;EAGT,OAAO,IAAI,QAAQ,OAAO,GAAG,WAAW,MAAM,CAAC;CACjD;;;;;;CAOA,AAAO,SAAiB;EACtB,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,SAAyB;CACvC,OAAO,IAAI,qBAAqB;AAClC"}