langgraph-checkpoint-sqlite 2.0.5__tar.gz → 2.0.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,17 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: langgraph-checkpoint-sqlite
3
- Version: 2.0.5
3
+ Version: 2.0.7
4
4
  Summary: Library with a SQLite implementation of LangGraph checkpoint saver.
5
- Home-page: https://www.github.com/langchain-ai/langgraph
6
5
  License: MIT
7
- Requires-Python: >=3.9.0,<4.0.0
6
+ Requires-Python: >=3.9
8
7
  Classifier: License :: OSI Approved :: MIT License
9
8
  Classifier: Programming Language :: Python :: 3
10
9
  Classifier: Programming Language :: Python :: 3.9
11
10
  Classifier: Programming Language :: Python :: 3.10
12
11
  Classifier: Programming Language :: Python :: 3.11
13
12
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: aiosqlite (>=0.20,<0.22)
15
15
  Requires-Dist: langgraph-checkpoint (>=2.0.15,<3.0.0)
16
16
  Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
17
17
  Description-Content-Type: text/markdown
@@ -30,7 +30,7 @@ read_config = {"configurable": {"thread_id": "1"}}
30
30
 
31
31
  with SqliteSaver.from_conn_string(":memory:") as checkpointer:
32
32
  checkpoint = {
33
- "v": 1,
33
+ "v": 2,
34
34
  "ts": "2024-07-31T20:14:19.804150+00:00",
35
35
  "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
36
36
  "channel_values": {
@@ -72,7 +72,7 @@ from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
72
72
 
73
73
  async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
74
74
  checkpoint = {
75
- "v": 1,
75
+ "v": 2,
76
76
  "ts": "2024-07-31T20:14:19.804150+00:00",
77
77
  "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
78
78
  "channel_values": {
@@ -12,7 +12,7 @@ read_config = {"configurable": {"thread_id": "1"}}
12
12
 
13
13
  with SqliteSaver.from_conn_string(":memory:") as checkpointer:
14
14
  checkpoint = {
15
- "v": 1,
15
+ "v": 2,
16
16
  "ts": "2024-07-31T20:14:19.804150+00:00",
17
17
  "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
18
18
  "channel_values": {
@@ -54,7 +54,7 @@ from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
54
54
 
55
55
  async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
56
56
  checkpoint = {
57
- "v": 1,
57
+ "v": 2,
58
58
  "ts": "2024-07-31T20:14:19.804150+00:00",
59
59
  "id": "1ef4f797-8335-6428-8001-8a1503f9b875",
60
60
  "channel_values": {
@@ -56,7 +56,10 @@ class SqliteSaver(BaseCheckpointSaver[str]):
56
56
  >>> builder.add_node("add_one", lambda x: x + 1)
57
57
  >>> builder.set_entry_point("add_one")
58
58
  >>> builder.set_finish_point("add_one")
59
- >>> conn = sqlite3.connect("checkpoints.sqlite")
59
+ >>> # Create a new SqliteSaver instance
60
+ >>> # Note: check_same_thread=False is OK as the implementation uses a lock
61
+ >>> # to ensure thread safety.
62
+ >>> conn = sqlite3.connect("checkpoints.sqlite", check_same_thread=False)
60
63
  >>> memory = SqliteSaver(conn)
61
64
  >>> graph = builder.compile(checkpointer=memory)
62
65
  >>> config = {"configurable": {"thread_id": "1"}}
@@ -87,7 +90,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
87
90
  """Create a new SqliteSaver instance from a connection string.
88
91
 
89
92
  Args:
90
- conn_string (str): The SQLite connection string.
93
+ conn_string: The SQLite connection string.
91
94
 
92
95
  Yields:
93
96
  SqliteSaver: A new SqliteSaver instance.
@@ -184,7 +187,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
184
187
  for the given thread ID is retrieved.
185
188
 
186
189
  Args:
187
- config (RunnableConfig): The config to use for retrieving the checkpoint.
190
+ config: The config to use for retrieving the checkpoint.
188
191
 
189
192
  Returns:
190
193
  Optional[CheckpointTuple]: The retrieved checkpoint tuple, or None if no matching checkpoint was found.
@@ -290,10 +293,10 @@ class SqliteSaver(BaseCheckpointSaver[str]):
290
293
  on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
291
294
 
292
295
  Args:
293
- config (RunnableConfig): The config to use for listing the checkpoints.
294
- filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata. Defaults to None.
295
- before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
296
- limit (Optional[int]): The maximum number of checkpoints to return. Defaults to None.
296
+ config: The config to use for listing the checkpoints.
297
+ filter: Additional filtering criteria for metadata. Defaults to None.
298
+ before: If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
299
+ limit: The maximum number of checkpoints to return. Defaults to None.
297
300
 
298
301
  Yields:
299
302
  Iterator[CheckpointTuple]: An iterator of checkpoint tuples.
@@ -377,10 +380,10 @@ class SqliteSaver(BaseCheckpointSaver[str]):
377
380
  with the provided config and its parent config (if any).
378
381
 
379
382
  Args:
380
- config (RunnableConfig): The config to associate with the checkpoint.
381
- checkpoint (Checkpoint): The checkpoint to save.
382
- metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
383
- new_versions (ChannelVersions): New channel versions as of this write.
383
+ config: The config to associate with the checkpoint.
384
+ checkpoint: The checkpoint to save.
385
+ metadata: Additional metadata to save with the checkpoint.
386
+ new_versions: New channel versions as of this write.
384
387
 
385
388
  Returns:
386
389
  RunnableConfig: Updated configuration after storing the checkpoint.
@@ -434,10 +437,10 @@ class SqliteSaver(BaseCheckpointSaver[str]):
434
437
  This method saves intermediate writes associated with a checkpoint to the SQLite database.
435
438
 
436
439
  Args:
437
- config (RunnableConfig): Configuration of the related checkpoint.
438
- writes (Sequence[Tuple[str, Any]]): List of writes to store, each as (channel, value) pair.
439
- task_id (str): Identifier for the task creating the writes.
440
- task_path (str): Path of the task creating the writes.
440
+ config: Configuration of the related checkpoint.
441
+ writes: List of writes to store, each as (channel, value) pair.
442
+ task_id: Identifier for the task creating the writes.
443
+ task_path: Path of the task creating the writes.
441
444
  """
442
445
  query = (
443
446
  "INSERT OR REPLACE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
@@ -461,6 +464,25 @@ class SqliteSaver(BaseCheckpointSaver[str]):
461
464
  ],
462
465
  )
463
466
 
467
+ def delete_thread(self, thread_id: str) -> None:
468
+ """Delete all checkpoints and writes associated with a thread ID.
469
+
470
+ Args:
471
+ thread_id: The thread ID to delete.
472
+
473
+ Returns:
474
+ None
475
+ """
476
+ with self.cursor() as cur:
477
+ cur.execute(
478
+ "DELETE FROM checkpoints WHERE thread_id = ?",
479
+ (str(thread_id),),
480
+ )
481
+ cur.execute(
482
+ "DELETE FROM writes WHERE thread_id = ?",
483
+ (str(thread_id),),
484
+ )
485
+
464
486
  async def aget_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
465
487
  """Get a checkpoint tuple from the database asynchronously.
466
488
 
@@ -70,15 +70,18 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
70
70
  >>> from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
71
71
  >>> from langgraph.graph import StateGraph
72
72
  >>>
73
- >>> builder = StateGraph(int)
74
- >>> builder.add_node("add_one", lambda x: x + 1)
75
- >>> builder.set_entry_point("add_one")
76
- >>> builder.set_finish_point("add_one")
77
- >>> async with AsyncSqliteSaver.from_conn_string("checkpoints.db") as memory:
78
- >>> graph = builder.compile(checkpointer=memory)
79
- >>> coro = graph.ainvoke(1, {"configurable": {"thread_id": "thread-1"}})
80
- >>> print(asyncio.run(coro))
81
- Output: 2
73
+ >>> async def main():
74
+ >>> builder = StateGraph(int)
75
+ >>> builder.add_node("add_one", lambda x: x + 1)
76
+ >>> builder.set_entry_point("add_one")
77
+ >>> builder.set_finish_point("add_one")
78
+ >>> async with AsyncSqliteSaver.from_conn_string("checkpoints.db") as memory:
79
+ >>> graph = builder.compile(checkpointer=memory)
80
+ >>> coro = graph.ainvoke(1, {"configurable": {"thread_id": "thread-1"}})
81
+ >>> print(await asyncio.gather(coro))
82
+ >>>
83
+ >>> asyncio.run(main())
84
+ Output: [2]
82
85
  ```
83
86
  Raw usage:
84
87
 
@@ -90,12 +93,12 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
90
93
  >>> async def main():
91
94
  >>> async with aiosqlite.connect("checkpoints.db") as conn:
92
95
  ... saver = AsyncSqliteSaver(conn)
93
- ... config = {"configurable": {"thread_id": "1"}}
94
- ... checkpoint = {"ts": "2023-05-03T10:00:00Z", "data": {"key": "value"}}
96
+ ... config = {"configurable": {"thread_id": "1", "checkpoint_ns": ""}}
97
+ ... checkpoint = {"ts": "2023-05-03T10:00:00Z", "data": {"key": "value"}, "id": "0c62ca34-ac19-445d-bbb0-5b4984975b2a"}
95
98
  ... saved_config = await saver.aput(config, checkpoint, {}, {})
96
99
  ... print(saved_config)
97
100
  >>> asyncio.run(main())
98
- {"configurable": {"thread_id": "1", "checkpoint_id": "0c62ca34-ac19-445d-bbb0-5b4984975b2a"}}
101
+ {'configurable': {'thread_id': '1', 'checkpoint_ns': '', 'checkpoint_id': '0c62ca34-ac19-445d-bbb0-5b4984975b2a'}}
99
102
  ```
100
103
  """
101
104
 
@@ -123,7 +126,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
123
126
  """Create a new AsyncSqliteSaver instance from a connection string.
124
127
 
125
128
  Args:
126
- conn_string (str): The SQLite connection string.
129
+ conn_string: The SQLite connection string.
127
130
 
128
131
  Yields:
129
132
  AsyncSqliteSaver: A new AsyncSqliteSaver instance.
@@ -140,7 +143,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
140
143
  for the given thread ID is retrieved.
141
144
 
142
145
  Args:
143
- config (RunnableConfig): The config to use for retrieving the checkpoint.
146
+ config: The config to use for retrieving the checkpoint.
144
147
 
145
148
  Returns:
146
149
  Optional[CheckpointTuple]: The retrieved checkpoint tuple, or None if no matching checkpoint was found.
@@ -175,10 +178,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
175
178
  on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
176
179
 
177
180
  Args:
178
- config (Optional[RunnableConfig]): Base configuration for filtering checkpoints.
179
- filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata.
180
- before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
181
- limit (Optional[int]): Maximum number of checkpoints to return.
181
+ config: Base configuration for filtering checkpoints.
182
+ filter: Additional filtering criteria for metadata.
183
+ before: If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
184
+ limit: Maximum number of checkpoints to return.
182
185
 
183
186
  Yields:
184
187
  Iterator[CheckpointTuple]: An iterator of matching checkpoint tuples.
@@ -218,10 +221,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
218
221
  with the provided config and its parent config (if any).
219
222
 
220
223
  Args:
221
- config (RunnableConfig): The config to associate with the checkpoint.
222
- checkpoint (Checkpoint): The checkpoint to save.
223
- metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
224
- new_versions (ChannelVersions): New channel versions as of this write.
224
+ config: The config to associate with the checkpoint.
225
+ checkpoint: The checkpoint to save.
226
+ metadata: Additional metadata to save with the checkpoint.
227
+ new_versions: New channel versions as of this write.
225
228
 
226
229
  Returns:
227
230
  RunnableConfig: Updated configuration after storing the checkpoint.
@@ -241,6 +244,31 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
241
244
  self.aput_writes(config, writes, task_id, task_path), self.loop
242
245
  ).result()
243
246
 
247
+ def delete_thread(self, thread_id: str) -> None:
248
+ """Delete all checkpoints and writes associated with a thread ID.
249
+
250
+ Args:
251
+ thread_id: The thread ID to delete.
252
+
253
+ Returns:
254
+ None
255
+ """
256
+ try:
257
+ # check if we are in the main thread, only bg threads can block
258
+ # we don't check in other methods to avoid the overhead
259
+ if asyncio.get_running_loop() is self.loop:
260
+ raise asyncio.InvalidStateError(
261
+ "Synchronous calls to AsyncSqliteSaver are only allowed from a "
262
+ "different thread. From the main thread, use the async interface. "
263
+ "For example, use `checkpointer.alist(...)` or `await "
264
+ "graph.ainvoke(...)`."
265
+ )
266
+ except RuntimeError:
267
+ pass
268
+ return asyncio.run_coroutine_threadsafe(
269
+ self.adelete_thread(thread_id), self.loop
270
+ ).result()
271
+
244
272
  async def setup(self) -> None:
245
273
  """Set up the checkpoint database asynchronously.
246
274
 
@@ -292,7 +320,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
292
320
  for the given thread ID is retrieved.
293
321
 
294
322
  Args:
295
- config (RunnableConfig): The config to use for retrieving the checkpoint.
323
+ config: The config to use for retrieving the checkpoint.
296
324
 
297
325
  Returns:
298
326
  Optional[CheckpointTuple]: The retrieved checkpoint tuple, or None if no matching checkpoint was found.
@@ -378,10 +406,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
378
406
  on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
379
407
 
380
408
  Args:
381
- config (Optional[RunnableConfig]): Base configuration for filtering checkpoints.
382
- filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata.
383
- before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
384
- limit (Optional[int]): Maximum number of checkpoints to return.
409
+ config: Base configuration for filtering checkpoints.
410
+ filter: Additional filtering criteria for metadata.
411
+ before: If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
412
+ limit: Maximum number of checkpoints to return.
385
413
 
386
414
  Yields:
387
415
  AsyncIterator[CheckpointTuple]: An asynchronous iterator of matching checkpoint tuples.
@@ -452,10 +480,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
452
480
  with the provided config and its parent config (if any).
453
481
 
454
482
  Args:
455
- config (RunnableConfig): The config to associate with the checkpoint.
456
- checkpoint (Checkpoint): The checkpoint to save.
457
- metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
458
- new_versions (ChannelVersions): New channel versions as of this write.
483
+ config: The config to associate with the checkpoint.
484
+ checkpoint: The checkpoint to save.
485
+ metadata: Additional metadata to save with the checkpoint.
486
+ new_versions: New channel versions as of this write.
459
487
 
460
488
  Returns:
461
489
  RunnableConfig: Updated configuration after storing the checkpoint.
@@ -503,10 +531,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
503
531
  This method saves intermediate writes associated with a checkpoint to the database.
504
532
 
505
533
  Args:
506
- config (RunnableConfig): Configuration of the related checkpoint.
507
- writes (Sequence[Tuple[str, Any]]): List of writes to store, each as (channel, value) pair.
508
- task_id (str): Identifier for the task creating the writes.
509
- task_path (str): Path of the task creating the writes.
534
+ config: Configuration of the related checkpoint.
535
+ writes: List of writes to store, each as (channel, value) pair.
536
+ task_id: Identifier for the task creating the writes.
537
+ task_path: Path of the task creating the writes.
510
538
  """
511
539
  query = (
512
540
  "INSERT OR REPLACE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
@@ -530,6 +558,27 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
530
558
  for idx, (channel, value) in enumerate(writes)
531
559
  ],
532
560
  )
561
+ await self.conn.commit()
562
+
563
+ async def adelete_thread(self, thread_id: str) -> None:
564
+ """Delete all checkpoints and writes associated with a thread ID.
565
+
566
+ Args:
567
+ thread_id: The thread ID to delete.
568
+
569
+ Returns:
570
+ None
571
+ """
572
+ async with self.lock, self.conn.cursor() as cur:
573
+ await cur.execute(
574
+ "DELETE FROM checkpoints WHERE thread_id = ?",
575
+ (str(thread_id),),
576
+ )
577
+ await cur.execute(
578
+ "DELETE FROM writes WHERE thread_id = ?",
579
+ (str(thread_id),),
580
+ )
581
+ await self.conn.commit()
533
582
 
534
583
  def get_next_version(self, current: Optional[str], channel: ChannelProtocol) -> str:
535
584
  """Generate the next version ID for a channel.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "langgraph-checkpoint-sqlite"
3
- version = "2.0.5"
3
+ version = "2.0.7"
4
4
  description = "Library with a SQLite implementation of LangGraph checkpoint saver."
5
5
  authors = []
6
6
  license = "MIT"
@@ -9,9 +9,9 @@ repository = "https://www.github.com/langchain-ai/langgraph"
9
9
  packages = [{ include = "langgraph" }]
10
10
 
11
11
  [tool.poetry.dependencies]
12
- python = "^3.9.0"
12
+ python = ">=3.9"
13
13
  langgraph-checkpoint = "^2.0.15"
14
- aiosqlite = "^0.20.0"
14
+ aiosqlite = ">=0.20,<0.22"
15
15
 
16
16
  [tool.poetry.group.dev.dependencies]
17
17
  ruff = "^0.6.2"
@@ -19,7 +19,7 @@ codespell = "^2.2.0"
19
19
  pytest = "^7.2.1"
20
20
  pytest-asyncio = "^0.21.1"
21
21
  pytest-mock = "^3.11.1"
22
- pytest-watcher = "^0.4.1"
22
+ pytest-watcher = { version = ">=0.4.1", python = "<4.0" }
23
23
  mypy = "^1.10.0"
24
24
  langgraph-checkpoint = {path = "../checkpoint", develop = true}
25
25