{"version":3,"file":"index.cjs","names":["TASKS","BaseCheckpointSaver","Database"],"sources":["../src/index.ts"],"sourcesContent":["import Database, { Database as DatabaseType, Statement } from \"better-sqlite3\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n  BaseCheckpointSaver,\n  type Checkpoint,\n  type CheckpointListOptions,\n  type CheckpointTuple,\n  type SerializerProtocol,\n  type PendingWrite,\n  type CheckpointMetadata,\n  TASKS,\n  copyCheckpoint,\n  maxChannelVersion,\n} from \"@langchain/langgraph-checkpoint\";\n\ninterface CheckpointRow {\n  checkpoint: string;\n  metadata: string;\n  parent_checkpoint_id?: string;\n  thread_id: string;\n  checkpoint_id: string;\n  checkpoint_ns?: string;\n  type?: string;\n  pending_writes: string;\n}\n\ninterface PendingWriteColumn {\n  task_id: string;\n  channel: string;\n  type: string;\n  value: string;\n}\n\ninterface PendingSendColumn {\n  type: string;\n  value: string;\n}\n\n// In the `SqliteSaver.list` method, we need to sanitize the `options.filter` argument to ensure it only contains keys\n// that are part of the `CheckpointMetadata` type. The lines below ensure that we get compile-time errors if the list\n// of keys that we use is out of sync with the `CheckpointMetadata` type.\nconst checkpointMetadataKeys = [\"source\", \"step\", \"parents\"] as const;\n\ntype CheckKeys<T, K extends readonly (keyof T)[]> = [K[number]] extends [\n  keyof T\n]\n  ? [keyof T] extends [K[number]]\n    ? K\n    : never\n  : never;\n\nfunction validateKeys<T, K extends readonly (keyof T)[]>(\n  keys: CheckKeys<T, K>\n): K {\n  return keys;\n}\n\n// If this line fails to compile, the list of keys that we use in the `SqliteSaver.list` method is out of sync with the\n// `CheckpointMetadata` type. In that case, just update `checkpointMetadataKeys` to contain all the keys in\n// `CheckpointMetadata`\nconst validCheckpointMetadataKeys = validateKeys<\n  CheckpointMetadata,\n  typeof checkpointMetadataKeys\n>(checkpointMetadataKeys);\n\nfunction prepareSql(db: DatabaseType, checkpointId: boolean) {\n  const sql = `\n  SELECT\n    thread_id,\n    checkpoint_ns,\n    checkpoint_id,\n    parent_checkpoint_id,\n    type,\n    checkpoint,\n    metadata,\n    (\n      SELECT\n        json_group_array(\n          json_object(\n            'task_id', pw.task_id,\n            'channel', pw.channel,\n            'type', pw.type,\n            'value', CAST(pw.value AS TEXT)\n          )\n        )\n      FROM writes as pw\n      WHERE pw.thread_id = checkpoints.thread_id\n        AND pw.checkpoint_ns = checkpoints.checkpoint_ns\n        AND pw.checkpoint_id = checkpoints.checkpoint_id\n    ) as pending_writes,\n    (\n      SELECT\n        json_group_array(\n          json_object(\n            'type', ps.type,\n            'value', CAST(ps.value AS TEXT)\n          )\n        )\n      FROM writes as ps\n      WHERE ps.thread_id = checkpoints.thread_id\n        AND ps.checkpoint_ns = checkpoints.checkpoint_ns\n        AND ps.checkpoint_id = checkpoints.parent_checkpoint_id\n        AND ps.channel = '${TASKS}'\n      ORDER BY ps.idx\n    ) as pending_sends\n  FROM checkpoints\n  WHERE thread_id = ? AND checkpoint_ns = ? ${\n    checkpointId\n      ? \"AND checkpoint_id = ?\"\n      : \"ORDER BY checkpoint_id DESC LIMIT 1\"\n  }`;\n\n  return db.prepare(sql);\n}\n\nexport class SqliteSaver extends BaseCheckpointSaver {\n  db: DatabaseType;\n\n  protected isSetup: boolean;\n\n  protected withoutCheckpoint: Statement;\n\n  protected withCheckpoint: Statement;\n\n  constructor(db: DatabaseType, serde?: SerializerProtocol) {\n    super(serde);\n    this.db = db;\n    this.isSetup = false;\n  }\n\n  static fromConnString(connStringOrLocalPath: string): SqliteSaver {\n    return new SqliteSaver(new Database(connStringOrLocalPath));\n  }\n\n  protected setup(): void {\n    if (this.isSetup) {\n      return;\n    }\n\n    this.db.pragma(\"journal_mode=WAL\");\n    this.db.exec(`\nCREATE TABLE IF NOT EXISTS checkpoints (\n  thread_id TEXT NOT NULL,\n  checkpoint_ns TEXT NOT NULL DEFAULT '',\n  checkpoint_id TEXT NOT NULL,\n  parent_checkpoint_id TEXT,\n  type TEXT,\n  checkpoint BLOB,\n  metadata BLOB,\n  PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id)\n);`);\n    this.db.exec(`\nCREATE TABLE IF NOT EXISTS writes (\n  thread_id TEXT NOT NULL,\n  checkpoint_ns TEXT NOT NULL DEFAULT '',\n  checkpoint_id TEXT NOT NULL,\n  task_id TEXT NOT NULL,\n  idx INTEGER NOT NULL,\n  channel TEXT NOT NULL,\n  type TEXT,\n  value BLOB,\n  PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx)\n);`);\n\n    this.withoutCheckpoint = prepareSql(this.db, false);\n    this.withCheckpoint = prepareSql(this.db, true);\n\n    this.isSetup = true;\n  }\n\n  async getTuple(config: RunnableConfig): Promise<CheckpointTuple | undefined> {\n    this.setup();\n    const {\n      thread_id,\n      checkpoint_ns = \"\",\n      checkpoint_id,\n    } = config.configurable ?? {};\n\n    const args = [thread_id, checkpoint_ns];\n    if (checkpoint_id) args.push(checkpoint_id);\n\n    const stm = checkpoint_id ? this.withCheckpoint : this.withoutCheckpoint;\n    const row = stm.get(...args) as CheckpointRow;\n    if (row === undefined) return undefined;\n\n    let finalConfig = config;\n\n    if (!checkpoint_id) {\n      finalConfig = {\n        configurable: {\n          thread_id: row.thread_id,\n          checkpoint_ns,\n          checkpoint_id: row.checkpoint_id,\n        },\n      };\n    }\n\n    if (\n      finalConfig.configurable?.thread_id === undefined ||\n      finalConfig.configurable?.checkpoint_id === undefined\n    ) {\n      throw new Error(\"Missing thread_id or checkpoint_id\");\n    }\n\n    const pendingWrites = await Promise.all(\n      (JSON.parse(row.pending_writes) as PendingWriteColumn[]).map(\n        async (write) => {\n          return [\n            write.task_id,\n            write.channel,\n            await this.serde.loadsTyped(\n              write.type ?? \"json\",\n              write.value ?? \"\"\n            ),\n          ] as [string, string, unknown];\n        }\n      )\n    );\n\n    const checkpoint = (await this.serde.loadsTyped(\n      row.type ?? \"json\",\n      row.checkpoint\n    )) as Checkpoint;\n\n    if (checkpoint.v < 4 && row.parent_checkpoint_id != null) {\n      await this.migratePendingSends(\n        checkpoint,\n        row.thread_id,\n        row.parent_checkpoint_id\n      );\n    }\n\n    return {\n      checkpoint,\n      config: finalConfig,\n      metadata: (await this.serde.loadsTyped(\n        row.type ?? \"json\",\n        row.metadata\n      )) as CheckpointMetadata,\n      parentConfig: row.parent_checkpoint_id\n        ? {\n            configurable: {\n              thread_id: row.thread_id,\n              checkpoint_ns,\n              checkpoint_id: row.parent_checkpoint_id,\n            },\n          }\n        : undefined,\n      pendingWrites,\n    };\n  }\n\n  async *list(\n    config: RunnableConfig,\n    options?: CheckpointListOptions\n  ): AsyncGenerator<CheckpointTuple> {\n    const { limit, before, filter } = options ?? {};\n    this.setup();\n    const thread_id = config.configurable?.thread_id;\n    const checkpoint_ns = config.configurable?.checkpoint_ns;\n    let sql = `\n      SELECT\n        thread_id,\n        checkpoint_ns,\n        checkpoint_id,\n        parent_checkpoint_id,\n        type,\n        checkpoint,\n        metadata,\n        (\n          SELECT\n            json_group_array(\n              json_object(\n                'task_id', pw.task_id,\n                'channel', pw.channel,\n                'type', pw.type,\n                'value', CAST(pw.value AS TEXT)\n              )\n            )\n          FROM writes as pw\n          WHERE pw.thread_id = checkpoints.thread_id\n            AND pw.checkpoint_ns = checkpoints.checkpoint_ns\n            AND pw.checkpoint_id = checkpoints.checkpoint_id\n        ) as pending_writes,\n        (\n          SELECT\n            json_group_array(\n              json_object(\n                'type', ps.type,\n                'value', CAST(ps.value AS TEXT)\n              )\n            )\n          FROM writes as ps\n          WHERE ps.thread_id = checkpoints.thread_id\n            AND ps.checkpoint_ns = checkpoints.checkpoint_ns\n            AND ps.checkpoint_id = checkpoints.parent_checkpoint_id\n            AND ps.channel = '${TASKS}'\n          ORDER BY ps.idx\n        ) as pending_sends\n      FROM checkpoints\\n`;\n\n    const whereClause: string[] = [];\n\n    if (thread_id) {\n      whereClause.push(\"thread_id = ?\");\n    }\n\n    if (checkpoint_ns !== undefined && checkpoint_ns !== null) {\n      whereClause.push(\"checkpoint_ns = ?\");\n    }\n\n    if (before?.configurable?.checkpoint_id !== undefined) {\n      whereClause.push(\"checkpoint_id < ?\");\n    }\n\n    const sanitizedFilter = Object.fromEntries(\n      Object.entries(filter ?? {}).filter(\n        ([key, value]) =>\n          value !== undefined &&\n          validCheckpointMetadataKeys.includes(key as keyof CheckpointMetadata)\n      )\n    );\n\n    whereClause.push(\n      ...Object.entries(sanitizedFilter).map(\n        ([key]) => `jsonb(CAST(metadata AS TEXT))->'$.${key}' = ?`\n      )\n    );\n\n    if (whereClause.length > 0) {\n      sql += `WHERE\\n  ${whereClause.join(\" AND\\n  \")}\\n`;\n    }\n\n    sql += \"\\nORDER BY checkpoint_id DESC\";\n\n    if (limit) {\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      sql += ` LIMIT ${parseInt(limit as any, 10)}`; // parseInt here (with cast to make TS happy) to sanitize input, as limit may be user-provided\n    }\n\n    const args = [\n      thread_id,\n      checkpoint_ns,\n      before?.configurable?.checkpoint_id,\n      ...Object.values(sanitizedFilter).map((value) => JSON.stringify(value)),\n    ].filter((value) => value !== undefined && value !== null);\n\n    const rows: CheckpointRow[] = this.db\n      .prepare(sql)\n      .all(...args) as CheckpointRow[];\n\n    if (rows) {\n      for (const row of rows) {\n        const pendingWrites = await Promise.all(\n          (JSON.parse(row.pending_writes) as PendingWriteColumn[]).map(\n            async (write) => {\n              return [\n                write.task_id,\n                write.channel,\n                await this.serde.loadsTyped(\n                  write.type ?? \"json\",\n                  write.value ?? \"\"\n                ),\n              ] as [string, string, unknown];\n            }\n          )\n        );\n\n        const checkpoint = (await this.serde.loadsTyped(\n          row.type ?? \"json\",\n          row.checkpoint\n        )) as Checkpoint;\n\n        if (checkpoint.v < 4 && row.parent_checkpoint_id != null) {\n          await this.migratePendingSends(\n            checkpoint,\n            row.thread_id,\n            row.parent_checkpoint_id\n          );\n        }\n\n        yield {\n          config: {\n            configurable: {\n              thread_id: row.thread_id,\n              checkpoint_ns: row.checkpoint_ns,\n              checkpoint_id: row.checkpoint_id,\n            },\n          },\n          checkpoint,\n          metadata: (await this.serde.loadsTyped(\n            row.type ?? \"json\",\n            row.metadata\n          )) as CheckpointMetadata,\n          parentConfig: row.parent_checkpoint_id\n            ? {\n                configurable: {\n                  thread_id: row.thread_id,\n                  checkpoint_ns: row.checkpoint_ns,\n                  checkpoint_id: row.parent_checkpoint_id,\n                },\n              }\n            : undefined,\n          pendingWrites,\n        };\n      }\n    }\n  }\n\n  async put(\n    config: RunnableConfig,\n    checkpoint: Checkpoint,\n    metadata: CheckpointMetadata\n  ): Promise<RunnableConfig> {\n    this.setup();\n\n    if (!config.configurable) {\n      throw new Error(\"Empty configuration supplied.\");\n    }\n\n    const thread_id = config.configurable?.thread_id;\n    const checkpoint_ns = config.configurable?.checkpoint_ns ?? \"\";\n    const parent_checkpoint_id = config.configurable?.checkpoint_id;\n\n    if (!thread_id) {\n      throw new Error(\n        `Missing \"thread_id\" field in passed \"config.configurable\".`\n      );\n    }\n\n    const preparedCheckpoint: Partial<Checkpoint> = copyCheckpoint(checkpoint);\n\n    const [[type1, serializedCheckpoint], [type2, serializedMetadata]] =\n      await Promise.all([\n        this.serde.dumpsTyped(preparedCheckpoint),\n        this.serde.dumpsTyped(metadata),\n      ]);\n\n    if (type1 !== type2) {\n      throw new Error(\n        \"Failed to serialized checkpoint and metadata to the same type.\"\n      );\n    }\n    const row = [\n      thread_id,\n      checkpoint_ns,\n      checkpoint.id,\n      parent_checkpoint_id,\n      type1,\n      serializedCheckpoint,\n      serializedMetadata,\n    ];\n\n    this.db\n      .prepare(\n        `INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)`\n      )\n      .run(...row);\n\n    return {\n      configurable: {\n        thread_id,\n        checkpoint_ns,\n        checkpoint_id: checkpoint.id,\n      },\n    };\n  }\n\n  async putWrites(\n    config: RunnableConfig,\n    writes: PendingWrite[],\n    taskId: string\n  ): Promise<void> {\n    this.setup();\n\n    if (!config.configurable) {\n      throw new Error(\"Empty configuration supplied.\");\n    }\n\n    if (!config.configurable?.thread_id) {\n      throw new Error(\"Missing thread_id field in config.configurable.\");\n    }\n\n    if (!config.configurable?.checkpoint_id) {\n      throw new Error(\"Missing checkpoint_id field in config.configurable.\");\n    }\n\n    const stmt = this.db.prepare(`\n      INSERT OR REPLACE INTO writes \n      (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) \n      VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n    `);\n\n    const transaction = this.db.transaction((rows) => {\n      for (const row of rows) {\n        stmt.run(...row);\n      }\n    });\n\n    const rows = await Promise.all(\n      writes.map(async (write, idx) => {\n        const [type, serializedWrite] = await this.serde.dumpsTyped(write[1]);\n        return [\n          config.configurable?.thread_id,\n          config.configurable?.checkpoint_ns,\n          config.configurable?.checkpoint_id,\n          taskId,\n          idx,\n          write[0],\n          type,\n          serializedWrite,\n        ];\n      })\n    );\n\n    transaction(rows);\n  }\n\n  async deleteThread(threadId: string) {\n    const transaction = this.db.transaction(() => {\n      this.db\n        .prepare(`DELETE FROM checkpoints WHERE thread_id = ?`)\n        .run(threadId);\n      this.db.prepare(`DELETE FROM writes WHERE thread_id = ?`).run(threadId);\n    });\n\n    transaction();\n  }\n\n  protected async migratePendingSends(\n    checkpoint: Checkpoint,\n    threadId: string,\n    parentCheckpointId: string\n  ) {\n    const { pending_sends } = this.db\n      .prepare(\n        `\n          SELECT\n            checkpoint_id,\n            json_group_array(\n              json_object(\n                'type', ps.type,\n                'value', CAST(ps.value AS TEXT)\n              )\n            ) as pending_sends\n          FROM writes as ps\n          WHERE ps.thread_id = ?\n            AND ps.checkpoint_id = ?\n            AND ps.channel = '${TASKS}'\n          ORDER BY ps.idx\n        `\n      )\n      .get(threadId, parentCheckpointId) as { pending_sends: string };\n\n    const mutableCheckpoint = checkpoint;\n\n    // add pending sends to checkpoint\n    mutableCheckpoint.channel_values ??= {};\n    mutableCheckpoint.channel_values[TASKS] = await Promise.all(\n      JSON.parse(pending_sends).map(({ type, value }: PendingSendColumn) =>\n        this.serde.loadsTyped(type, value)\n      )\n    );\n\n    // add to versions\n    mutableCheckpoint.channel_versions[TASKS] =\n      Object.keys(checkpoint.channel_versions).length > 0\n        ? maxChannelVersion(...Object.values(checkpoint.channel_versions))\n        : this.getNextVersion(undefined);\n  }\n}\n"],"mappings":"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"}