{"version":3,"file":"snapshot.mjs","names":[],"sources":["../../../../../../../ai/src/planner/snapshot.ts"],"sourcesContent":["import { resolveDefaultSnapshotStore } from \"../config\";\nimport type { SnapshotStore } from \"../contracts/orchestrator/snapshot-store.contract\";\nimport type { PlannerResumeOptions } from \"../contracts/planner/planner-execute-options.type\";\nimport type { PlannerPlan } from \"../contracts/planner/planner-plan.type\";\nimport type { PlannerStepSnapshot } from \"../contracts/planner/planner-result.type\";\nimport type {\n  PlannerSnapshot,\n  PlannerSnapshotStatus,\n} from \"../contracts/planner/planner-snapshot.type\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport { PlannerDriftError, PlannerFailedError } from \"../errors\";\n\n/**\n * The planner's `durable` config, narrowed to the fields the snapshot\n * helpers read.\n */\nexport type PlannerDurableConfig = {\n  store?: SnapshotStore<PlannerSnapshot>;\n  deleteOnComplete?: boolean;\n};\n\n/**\n * Resolve the effective {@link SnapshotStore}: the planner's own\n * `durable.store` wins; absent that, fall back to the global default set\n * via `ai.config({ defaultSnapshotStore })`.\n *\n * The global default is typed for the supervisor snapshot shape, but\n * every store impl keys purely by `runId` and round-trips whatever\n * envelope it is handed — so it serves a `PlannerSnapshot` just as well.\n * The cast re-tags the shape at this single boundary (Option B); the\n * planner only ever hands it a `PlannerSnapshot`.\n */\nfunction resolveSnapshotStore(\n  durable: PlannerDurableConfig | undefined,\n): SnapshotStore<PlannerSnapshot> | undefined {\n  return (\n    durable?.store ??\n    (resolveDefaultSnapshotStore() as SnapshotStore<PlannerSnapshot> | undefined)\n  );\n}\n\nexport type PersistPlannerParams = {\n  durable: PlannerDurableConfig | undefined;\n  runId: string;\n  plannerName: string;\n  signature: string;\n  version?: string;\n  goal: string;\n  plan: PlannerPlan;\n  executedSteps: PlannerStepSnapshot[];\n  usage: Usage;\n  children: BaseReport[];\n  replanCount: number;\n  status: PlannerSnapshotStatus;\n  startedAt: string;\n};\n\nexport type PersistOutcome = { ok: true } | { ok: false; error: unknown };\n\n/**\n * Write the current run state to the resolved snapshot store. No-op\n * (returns `{ ok: true }`) when neither `durable.store` nor the global\n * `defaultSnapshotStore` is configured — the common non-durable path.\n * Failures are returned as `{ ok: false }` rather than thrown so the\n * engine can surface them via logs without aborting the run.\n */\nexport async function persistPlannerSnapshot(\n  params: PersistPlannerParams,\n): Promise<PersistOutcome> {\n  const store = resolveSnapshotStore(params.durable);\n\n  if (!store) {\n    return { ok: true };\n  }\n\n  const snapshot: PlannerSnapshot = {\n    runId: params.runId,\n    plannerName: params.plannerName,\n    signature: params.signature,\n    version: params.version,\n    goal: params.goal,\n    plan: params.plan,\n    executedSteps: params.executedSteps,\n    usage: params.usage,\n    children: params.children,\n    replanCount: params.replanCount,\n    status: params.status,\n    startedAt: params.startedAt,\n    savedAt: new Date().toISOString(),\n  };\n\n  try {\n    await store.save(snapshot);\n\n    return { ok: true };\n  } catch (error) {\n    return { ok: false, error };\n  }\n}\n\n/**\n * Delete a persisted snapshot — used after a successful run when\n * `durable.deleteOnComplete` is set. Never throws. No-op (ok) when no\n * store is configured.\n */\nexport async function deletePlannerSnapshot(params: {\n  durable: PlannerDurableConfig | undefined;\n  runId: string;\n}): Promise<PersistOutcome> {\n  const store = resolveSnapshotStore(params.durable);\n\n  if (!store) {\n    return { ok: true };\n  }\n\n  try {\n    await store.delete(params.runId);\n\n    return { ok: true };\n  } catch (error) {\n    return { ok: false, error };\n  }\n}\n\n/**\n * Load a persisted snapshot for `resume()` and run the drift check.\n * Throws `PlannerFailedError` when no store is configured or when the run\n * is missing; throws `PlannerDriftError` when the stored signature\n * doesn't match the current definition (unless `force` is set).\n */\nexport async function loadPlannerSnapshotForResume(params: {\n  durable: PlannerDurableConfig | undefined;\n  plannerName: string;\n  signature: string;\n  runId: string;\n  options?: PlannerResumeOptions<unknown>;\n}): Promise<PlannerSnapshot> {\n  const store = resolveSnapshotStore(params.durable);\n\n  if (!store) {\n    throw new PlannerFailedError(\n      `ai.planner(\"${params.plannerName}\"): no durable store configured — set \\`durable: { store }\\` on the config or call \\`ai.config({ defaultSnapshotStore })\\` at boot before calling resume()`,\n      { context: { runId: params.runId } },\n    );\n  }\n\n  const snapshot = (await store.load(params.runId)) ?? null;\n\n  if (!snapshot) {\n    throw new PlannerFailedError(\n      `ai.planner(\"${params.plannerName}\"): no snapshot for runId \"${params.runId}\"`,\n      { context: { runId: params.runId } },\n    );\n  }\n\n  if (!params.options?.force && snapshot.signature !== params.signature) {\n    throw new PlannerDriftError(\n      `ai.planner(\"${params.plannerName}\") signature drift on resume`,\n      {\n        savedSignature: snapshot.signature,\n        currentSignature: params.signature,\n        runId: params.runId,\n      },\n    );\n  }\n\n  return snapshot;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiCA,SAAS,qBACP,SAC4C;CAC5C,OACE,SAAS,SACR,4BAA4B;AAEjC;;;;;;;;AA2BA,eAAsB,uBACpB,QACyB;CACzB,MAAM,QAAQ,qBAAqB,OAAO,OAAO;CAEjD,IAAI,CAAC,OACH,OAAO,EAAE,IAAI,KAAK;CAGpB,MAAM,WAA4B;EAChC,OAAO,OAAO;EACd,aAAa,OAAO;EACpB,WAAW,OAAO;EAClB,SAAS,OAAO;EAChB,MAAM,OAAO;EACb,MAAM,OAAO;EACb,eAAe,OAAO;EACtB,OAAO,OAAO;EACd,UAAU,OAAO;EACjB,aAAa,OAAO;EACpB,QAAQ,OAAO;EACf,WAAW,OAAO;EAClB,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;CAClC;CAEA,IAAI;EACF,MAAM,MAAM,KAAK,QAAQ;EAEzB,OAAO,EAAE,IAAI,KAAK;CACpB,SAAS,OAAO;EACd,OAAO;GAAE,IAAI;GAAO;EAAM;CAC5B;AACF;;;;;;AAOA,eAAsB,sBAAsB,QAGhB;CAC1B,MAAM,QAAQ,qBAAqB,OAAO,OAAO;CAEjD,IAAI,CAAC,OACH,OAAO,EAAE,IAAI,KAAK;CAGpB,IAAI;EACF,MAAM,MAAM,OAAO,OAAO,KAAK;EAE/B,OAAO,EAAE,IAAI,KAAK;CACpB,SAAS,OAAO;EACd,OAAO;GAAE,IAAI;GAAO;EAAM;CAC5B;AACF;;;;;;;AAQA,eAAsB,6BAA6B,QAMtB;CAC3B,MAAM,QAAQ,qBAAqB,OAAO,OAAO;CAEjD,IAAI,CAAC,OACH,MAAM,IAAI,mBACR,eAAe,OAAO,YAAY,6JAClC,EAAE,SAAS,EAAE,OAAO,OAAO,MAAM,EAAE,CACrC;CAGF,MAAM,WAAY,MAAM,MAAM,KAAK,OAAO,KAAK,KAAM;CAErD,IAAI,CAAC,UACH,MAAM,IAAI,mBACR,eAAe,OAAO,YAAY,6BAA6B,OAAO,MAAM,IAC5E,EAAE,SAAS,EAAE,OAAO,OAAO,MAAM,EAAE,CACrC;CAGF,IAAI,CAAC,OAAO,SAAS,SAAS,SAAS,cAAc,OAAO,WAC1D,MAAM,IAAI,kBACR,eAAe,OAAO,YAAY,+BAClC;EACE,gBAAgB,SAAS;EACzB,kBAAkB,OAAO;EACzB,OAAO,OAAO;CAChB,CACF;CAGF,OAAO;AACT"}