langgraph-checkpoint-sqlite 1.0.0__tar.gz → 1.0.2__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.
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/PKG-INFO +3 -4
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/README.md +1 -3
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/langgraph/checkpoint/sqlite/__init__.py +22 -12
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/langgraph/checkpoint/sqlite/aio.py +94 -51
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/langgraph/checkpoint/sqlite/utils.py +8 -3
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/pyproject.toml +3 -3
- {langgraph_checkpoint_sqlite-1.0.0 → langgraph_checkpoint_sqlite-1.0.2}/langgraph/checkpoint/py.typed +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: langgraph-checkpoint-sqlite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
4
4
|
Summary: Library with a SQLite implementation of LangGraph checkpoint saver.
|
|
5
5
|
Home-page: https://www.github.com/langchain-ai/langgraph
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
|
|
15
|
-
Requires-Dist: langgraph-checkpoint (>=1.0.
|
|
15
|
+
Requires-Dist: langgraph-checkpoint (>=1.0.8,<2.0.0)
|
|
16
16
|
Project-URL: Repository, https://www.github.com/langchain-ai/langgraph
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
|
|
@@ -53,7 +53,6 @@ with SqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"pending_sends": [],
|
|
56
|
-
"current_tasks": {}
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
# store checkpoint
|
|
@@ -96,7 +95,6 @@ async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
96
95
|
}
|
|
97
96
|
},
|
|
98
97
|
"pending_sends": [],
|
|
99
|
-
"current_tasks": {}
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
# store checkpoint
|
|
@@ -108,3 +106,4 @@ async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
108
106
|
# list checkpoints
|
|
109
107
|
[c async for c in checkpointer.alist(read_config)]
|
|
110
108
|
```
|
|
109
|
+
|
|
@@ -35,7 +35,6 @@ with SqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
35
35
|
}
|
|
36
36
|
},
|
|
37
37
|
"pending_sends": [],
|
|
38
|
-
"current_tasks": {}
|
|
39
38
|
}
|
|
40
39
|
|
|
41
40
|
# store checkpoint
|
|
@@ -78,7 +77,6 @@ async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
78
77
|
}
|
|
79
78
|
},
|
|
80
79
|
"pending_sends": [],
|
|
81
|
-
"current_tasks": {}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
# store checkpoint
|
|
@@ -89,4 +87,4 @@ async with AsyncSqliteSaver.from_conn_string(":memory:") as checkpointer:
|
|
|
89
87
|
|
|
90
88
|
# list checkpoints
|
|
91
89
|
[c async for c in checkpointer.alist(read_config)]
|
|
92
|
-
```
|
|
90
|
+
```
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import sqlite3
|
|
2
2
|
import threading
|
|
3
|
-
from contextlib import contextmanager
|
|
3
|
+
from contextlib import closing, contextmanager
|
|
4
4
|
from hashlib import md5
|
|
5
5
|
from typing import Any, AsyncIterator, Dict, Iterator, Optional, Sequence, Tuple
|
|
6
6
|
|
|
7
7
|
from langchain_core.runnables import RunnableConfig
|
|
8
8
|
|
|
9
9
|
from langgraph.checkpoint.base import (
|
|
10
|
+
WRITES_IDX_MAP,
|
|
10
11
|
BaseCheckpointSaver,
|
|
11
12
|
ChannelVersions,
|
|
12
13
|
Checkpoint,
|
|
@@ -176,7 +177,7 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
176
177
|
|
|
177
178
|
This method retrieves a checkpoint tuple from the SQLite database based on the
|
|
178
179
|
provided config. If the config contains a "checkpoint_id" key, the checkpoint with
|
|
179
|
-
the matching thread ID and
|
|
180
|
+
the matching thread ID and checkpoint ID is retrieved. Otherwise, the latest checkpoint
|
|
180
181
|
for the given thread ID is retrieved.
|
|
181
182
|
|
|
182
183
|
Args:
|
|
@@ -193,12 +194,12 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
193
194
|
>>> print(checkpoint_tuple)
|
|
194
195
|
CheckpointTuple(...)
|
|
195
196
|
|
|
196
|
-
With
|
|
197
|
+
With checkpoint ID:
|
|
197
198
|
|
|
198
199
|
>>> config = {
|
|
199
200
|
... "configurable": {
|
|
200
201
|
... "thread_id": "1",
|
|
201
|
-
|
|
202
|
+
... "checkpoint_ns": "",
|
|
202
203
|
... "checkpoint_id": "1ef4f797-8335-6428-8001-8a1503f9b875",
|
|
203
204
|
... }
|
|
204
205
|
... }
|
|
@@ -243,7 +244,7 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
243
244
|
}
|
|
244
245
|
# find any pending writes
|
|
245
246
|
cur.execute(
|
|
246
|
-
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ?",
|
|
247
|
+
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ? ORDER BY task_id, idx",
|
|
247
248
|
(
|
|
248
249
|
str(config["configurable"]["thread_id"]),
|
|
249
250
|
checkpoint_ns,
|
|
@@ -283,12 +284,12 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
283
284
|
"""List checkpoints from the database.
|
|
284
285
|
|
|
285
286
|
This method retrieves a list of checkpoint tuples from the SQLite database based
|
|
286
|
-
on the provided config. The checkpoints are ordered by
|
|
287
|
+
on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
|
|
287
288
|
|
|
288
289
|
Args:
|
|
289
290
|
config (RunnableConfig): The config to use for listing the checkpoints.
|
|
290
291
|
filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata. Defaults to None.
|
|
291
|
-
before (Optional[RunnableConfig]): If provided, only checkpoints before the specified
|
|
292
|
+
before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
|
|
292
293
|
limit (Optional[int]): The maximum number of checkpoints to return. Defaults to None.
|
|
293
294
|
|
|
294
295
|
Yields:
|
|
@@ -318,7 +319,7 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
318
319
|
ORDER BY checkpoint_id DESC"""
|
|
319
320
|
if limit:
|
|
320
321
|
query += f" LIMIT {limit}"
|
|
321
|
-
with self.cursor(transaction=False) as cur:
|
|
322
|
+
with self.cursor(transaction=False) as cur, closing(self.conn.cursor()) as wcur:
|
|
322
323
|
cur.execute(query, param_values)
|
|
323
324
|
for (
|
|
324
325
|
thread_id,
|
|
@@ -329,6 +330,10 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
329
330
|
checkpoint,
|
|
330
331
|
metadata,
|
|
331
332
|
) in cur:
|
|
333
|
+
wcur.execute(
|
|
334
|
+
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ? ORDER BY task_id, idx",
|
|
335
|
+
(thread_id, checkpoint_ns, checkpoint_id),
|
|
336
|
+
)
|
|
332
337
|
yield CheckpointTuple(
|
|
333
338
|
{
|
|
334
339
|
"configurable": {
|
|
@@ -350,6 +355,10 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
350
355
|
if parent_checkpoint_id
|
|
351
356
|
else None
|
|
352
357
|
),
|
|
358
|
+
[
|
|
359
|
+
(task_id, channel, self.serde.loads_typed((type, value)))
|
|
360
|
+
for task_id, channel, type, value in wcur
|
|
361
|
+
],
|
|
353
362
|
)
|
|
354
363
|
|
|
355
364
|
def put(
|
|
@@ -367,10 +376,11 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
367
376
|
Args:
|
|
368
377
|
config (RunnableConfig): The config to associate with the checkpoint.
|
|
369
378
|
checkpoint (Checkpoint): The checkpoint to save.
|
|
370
|
-
metadata (
|
|
379
|
+
metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
|
|
380
|
+
new_versions (ChannelVersions): New channel versions as of this write.
|
|
371
381
|
|
|
372
382
|
Returns:
|
|
373
|
-
RunnableConfig:
|
|
383
|
+
RunnableConfig: Updated configuration after storing the checkpoint.
|
|
374
384
|
|
|
375
385
|
Examples:
|
|
376
386
|
|
|
@@ -424,14 +434,14 @@ class SqliteSaver(BaseCheckpointSaver):
|
|
|
424
434
|
"""
|
|
425
435
|
with self.lock, self.cursor() as cur:
|
|
426
436
|
cur.executemany(
|
|
427
|
-
"INSERT OR
|
|
437
|
+
"INSERT OR IGNORE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
428
438
|
[
|
|
429
439
|
(
|
|
430
440
|
str(config["configurable"]["thread_id"]),
|
|
431
441
|
str(config["configurable"]["checkpoint_ns"]),
|
|
432
442
|
str(config["configurable"]["checkpoint_id"]),
|
|
433
443
|
task_id,
|
|
434
|
-
idx,
|
|
444
|
+
WRITES_IDX_MAP.get(channel, idx),
|
|
435
445
|
channel,
|
|
436
446
|
*self.serde.dumps_typed(value),
|
|
437
447
|
)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
-
import functools
|
|
3
2
|
from contextlib import asynccontextmanager
|
|
4
3
|
from typing import (
|
|
5
4
|
Any,
|
|
6
5
|
AsyncIterator,
|
|
7
6
|
Dict,
|
|
8
7
|
Iterator,
|
|
8
|
+
List,
|
|
9
9
|
Optional,
|
|
10
10
|
Sequence,
|
|
11
11
|
Tuple,
|
|
@@ -16,6 +16,7 @@ import aiosqlite
|
|
|
16
16
|
from langchain_core.runnables import RunnableConfig
|
|
17
17
|
|
|
18
18
|
from langgraph.checkpoint.base import (
|
|
19
|
+
WRITES_IDX_MAP,
|
|
19
20
|
BaseCheckpointSaver,
|
|
20
21
|
ChannelVersions,
|
|
21
22
|
Checkpoint,
|
|
@@ -30,20 +31,6 @@ from langgraph.checkpoint.sqlite.utils import search_where
|
|
|
30
31
|
T = TypeVar("T", bound=callable)
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
def not_implemented_sync_method(func: T) -> T:
|
|
34
|
-
@functools.wraps(func)
|
|
35
|
-
def wrapper(*args, **kwargs):
|
|
36
|
-
raise NotImplementedError(
|
|
37
|
-
"The AsyncSqliteSaver does not support synchronous methods. "
|
|
38
|
-
"Consider using the SqliteSaver instead.\n"
|
|
39
|
-
"from langgraph.checkpoint.sqlite import SqliteSaver\n"
|
|
40
|
-
"See https://langchain-ai.github.io/langgraph/reference/checkpoints/langgraph.checkpoint.sqlite.SqliteSaver "
|
|
41
|
-
"for more information."
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
return wrapper
|
|
45
|
-
|
|
46
|
-
|
|
47
34
|
class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
48
35
|
"""An asynchronous checkpoint saver that stores checkpoints in a SQLite database.
|
|
49
36
|
|
|
@@ -131,6 +118,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
131
118
|
self.jsonplus_serde = JsonPlusSerializer()
|
|
132
119
|
self.conn = conn
|
|
133
120
|
self.lock = asyncio.Lock()
|
|
121
|
+
self.loop = asyncio.get_running_loop()
|
|
134
122
|
self.is_setup = False
|
|
135
123
|
|
|
136
124
|
@classmethod
|
|
@@ -149,16 +137,24 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
149
137
|
async with aiosqlite.connect(conn_string) as conn:
|
|
150
138
|
yield AsyncSqliteSaver(conn)
|
|
151
139
|
|
|
152
|
-
@not_implemented_sync_method
|
|
153
140
|
def get_tuple(self, config: RunnableConfig) -> Optional[CheckpointTuple]:
|
|
154
141
|
"""Get a checkpoint tuple from the database.
|
|
155
142
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
143
|
+
This method retrieves a checkpoint tuple from the SQLite database based on the
|
|
144
|
+
provided config. If the config contains a "checkpoint_id" key, the checkpoint with
|
|
145
|
+
the matching thread ID and checkpoint ID is retrieved. Otherwise, the latest checkpoint
|
|
146
|
+
for the given thread ID is retrieved.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
config (RunnableConfig): The config to use for retrieving the checkpoint.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Optional[CheckpointTuple]: The retrieved checkpoint tuple, or None if no matching checkpoint was found.
|
|
159
153
|
"""
|
|
154
|
+
return asyncio.run_coroutine_threadsafe(
|
|
155
|
+
self.aget_tuple(config), self.loop
|
|
156
|
+
).result()
|
|
160
157
|
|
|
161
|
-
@not_implemented_sync_method
|
|
162
158
|
def list(
|
|
163
159
|
self,
|
|
164
160
|
config: Optional[RunnableConfig],
|
|
@@ -167,21 +163,60 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
167
163
|
before: Optional[RunnableConfig] = None,
|
|
168
164
|
limit: Optional[int] = None,
|
|
169
165
|
) -> Iterator[CheckpointTuple]:
|
|
170
|
-
"""List checkpoints from the database.
|
|
166
|
+
"""List checkpoints from the database asynchronously.
|
|
167
|
+
|
|
168
|
+
This method retrieves a list of checkpoint tuples from the SQLite database based
|
|
169
|
+
on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
|
|
170
|
+
|
|
171
|
+
Args:
|
|
172
|
+
config (Optional[RunnableConfig]): Base configuration for filtering checkpoints.
|
|
173
|
+
filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata.
|
|
174
|
+
before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
|
|
175
|
+
limit (Optional[int]): Maximum number of checkpoints to return.
|
|
171
176
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Or consider using the [SqliteSaver][sqlitesaver] checkpointer.
|
|
177
|
+
Yields:
|
|
178
|
+
Iterator[CheckpointTuple]: An iterator of matching checkpoint tuples.
|
|
175
179
|
"""
|
|
180
|
+
aiter_ = self.alist(config, filter=filter, before=before, limit=limit)
|
|
181
|
+
while True:
|
|
182
|
+
try:
|
|
183
|
+
yield asyncio.run_coroutine_threadsafe(
|
|
184
|
+
anext(aiter_), self.loop
|
|
185
|
+
).result()
|
|
186
|
+
except StopAsyncIteration:
|
|
187
|
+
break
|
|
176
188
|
|
|
177
|
-
@not_implemented_sync_method
|
|
178
189
|
def put(
|
|
179
190
|
self,
|
|
180
191
|
config: RunnableConfig,
|
|
181
192
|
checkpoint: Checkpoint,
|
|
182
193
|
metadata: CheckpointMetadata,
|
|
194
|
+
new_versions: ChannelVersions,
|
|
183
195
|
) -> RunnableConfig:
|
|
184
|
-
"""Save a checkpoint to the database.
|
|
196
|
+
"""Save a checkpoint to the database.
|
|
197
|
+
|
|
198
|
+
This method saves a checkpoint to the SQLite database. The checkpoint is associated
|
|
199
|
+
with the provided config and its parent config (if any).
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
config (RunnableConfig): The config to associate with the checkpoint.
|
|
203
|
+
checkpoint (Checkpoint): The checkpoint to save.
|
|
204
|
+
metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
|
|
205
|
+
new_versions (ChannelVersions): New channel versions as of this write.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
RunnableConfig: Updated configuration after storing the checkpoint.
|
|
209
|
+
"""
|
|
210
|
+
return asyncio.run_coroutine_threadsafe(
|
|
211
|
+
self.aput(config, checkpoint, metadata, new_versions), self.loop
|
|
212
|
+
).result()
|
|
213
|
+
|
|
214
|
+
def put_writes(
|
|
215
|
+
self, config: RunnableConfig, writes: List[Tuple[str, Any]], task_id: str
|
|
216
|
+
) -> None:
|
|
217
|
+
return asyncio.run_coroutine_threadsafe(
|
|
218
|
+
self.aput_writes(config, writes, task_id), self.loop
|
|
219
|
+
).result()
|
|
185
220
|
|
|
186
221
|
async def setup(self) -> None:
|
|
187
222
|
"""Set up the checkpoint database asynchronously.
|
|
@@ -230,7 +265,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
230
265
|
|
|
231
266
|
This method retrieves a checkpoint tuple from the SQLite database based on the
|
|
232
267
|
provided config. If the config contains a "checkpoint_id" key, the checkpoint with
|
|
233
|
-
the matching thread ID and
|
|
268
|
+
the matching thread ID and checkpoint ID is retrieved. Otherwise, the latest checkpoint
|
|
234
269
|
for the given thread ID is retrieved.
|
|
235
270
|
|
|
236
271
|
Args:
|
|
@@ -277,7 +312,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
277
312
|
}
|
|
278
313
|
# find any pending writes
|
|
279
314
|
await cur.execute(
|
|
280
|
-
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ?",
|
|
315
|
+
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ? ORDER BY task_id, idx",
|
|
281
316
|
(
|
|
282
317
|
str(config["configurable"]["thread_id"]),
|
|
283
318
|
checkpoint_ns,
|
|
@@ -317,26 +352,26 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
317
352
|
"""List checkpoints from the database asynchronously.
|
|
318
353
|
|
|
319
354
|
This method retrieves a list of checkpoint tuples from the SQLite database based
|
|
320
|
-
on the provided config. The checkpoints are ordered by
|
|
355
|
+
on the provided config. The checkpoints are ordered by checkpoint ID in descending order (newest first).
|
|
321
356
|
|
|
322
357
|
Args:
|
|
323
358
|
config (Optional[RunnableConfig]): Base configuration for filtering checkpoints.
|
|
324
359
|
filter (Optional[Dict[str, Any]]): Additional filtering criteria for metadata.
|
|
325
|
-
before (Optional[RunnableConfig]):
|
|
360
|
+
before (Optional[RunnableConfig]): If provided, only checkpoints before the specified checkpoint ID are returned. Defaults to None.
|
|
326
361
|
limit (Optional[int]): Maximum number of checkpoints to return.
|
|
327
362
|
|
|
328
363
|
Yields:
|
|
329
364
|
AsyncIterator[CheckpointTuple]: An asynchronous iterator of matching checkpoint tuples.
|
|
330
365
|
"""
|
|
331
366
|
await self.setup()
|
|
332
|
-
where,
|
|
367
|
+
where, params = search_where(config, filter, before)
|
|
333
368
|
query = f"""SELECT thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata
|
|
334
369
|
FROM checkpoints
|
|
335
370
|
{where}
|
|
336
371
|
ORDER BY checkpoint_id DESC"""
|
|
337
372
|
if limit:
|
|
338
373
|
query += f" LIMIT {limit}"
|
|
339
|
-
async with self.conn.execute(query,
|
|
374
|
+
async with self.conn.execute(query, params) as cur, self.conn.cursor() as wcur:
|
|
340
375
|
async for (
|
|
341
376
|
thread_id,
|
|
342
377
|
checkpoint_ns,
|
|
@@ -345,7 +380,11 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
345
380
|
type,
|
|
346
381
|
checkpoint,
|
|
347
382
|
metadata,
|
|
348
|
-
) in
|
|
383
|
+
) in cur:
|
|
384
|
+
await wcur.execute(
|
|
385
|
+
"SELECT task_id, channel, type, value FROM writes WHERE thread_id = ? AND checkpoint_ns = ? AND checkpoint_id = ? ORDER BY task_id, idx",
|
|
386
|
+
(thread_id, checkpoint_ns, checkpoint_id),
|
|
387
|
+
)
|
|
349
388
|
yield CheckpointTuple(
|
|
350
389
|
{
|
|
351
390
|
"configurable": {
|
|
@@ -367,6 +406,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
367
406
|
if parent_checkpoint_id
|
|
368
407
|
else None
|
|
369
408
|
),
|
|
409
|
+
[
|
|
410
|
+
(task_id, channel, self.serde.loads_typed((type, value)))
|
|
411
|
+
async for task_id, channel, type, value in wcur
|
|
412
|
+
],
|
|
370
413
|
)
|
|
371
414
|
|
|
372
415
|
async def aput(
|
|
@@ -385,10 +428,10 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
385
428
|
config (RunnableConfig): The config to associate with the checkpoint.
|
|
386
429
|
checkpoint (Checkpoint): The checkpoint to save.
|
|
387
430
|
metadata (CheckpointMetadata): Additional metadata to save with the checkpoint.
|
|
388
|
-
new_versions (
|
|
431
|
+
new_versions (ChannelVersions): New channel versions as of this write.
|
|
389
432
|
|
|
390
433
|
Returns:
|
|
391
|
-
RunnableConfig:
|
|
434
|
+
RunnableConfig: Updated configuration after storing the checkpoint.
|
|
392
435
|
"""
|
|
393
436
|
await self.setup()
|
|
394
437
|
thread_id = config["configurable"]["thread_id"]
|
|
@@ -432,19 +475,19 @@ class AsyncSqliteSaver(BaseCheckpointSaver):
|
|
|
432
475
|
task_id (str): Identifier for the task creating the writes.
|
|
433
476
|
"""
|
|
434
477
|
await self.setup()
|
|
435
|
-
async with self.conn.
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
478
|
+
async with self.conn.cursor() as cur:
|
|
479
|
+
await cur.executemany(
|
|
480
|
+
"INSERT OR IGNORE INTO writes (thread_id, checkpoint_ns, checkpoint_id, task_id, idx, channel, type, value) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
481
|
+
[
|
|
482
|
+
(
|
|
483
|
+
str(config["configurable"]["thread_id"]),
|
|
484
|
+
str(config["configurable"]["checkpoint_ns"]),
|
|
485
|
+
str(config["configurable"]["checkpoint_id"]),
|
|
486
|
+
task_id,
|
|
487
|
+
WRITES_IDX_MAP.get(channel, idx),
|
|
488
|
+
channel,
|
|
489
|
+
*self.serde.dumps_typed(value),
|
|
490
|
+
)
|
|
491
|
+
for idx, (channel, value) in enumerate(writes)
|
|
492
|
+
],
|
|
493
|
+
)
|
|
@@ -70,9 +70,14 @@ def search_where(
|
|
|
70
70
|
if config is not None:
|
|
71
71
|
wheres.append("thread_id = ?")
|
|
72
72
|
param_values.append(config["configurable"]["thread_id"])
|
|
73
|
-
checkpoint_ns = config["configurable"].get("checkpoint_ns"
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
checkpoint_ns = config["configurable"].get("checkpoint_ns")
|
|
74
|
+
if checkpoint_ns is not None:
|
|
75
|
+
wheres.append("checkpoint_ns = ?")
|
|
76
|
+
param_values.append(checkpoint_ns)
|
|
77
|
+
|
|
78
|
+
if checkpoint_id := get_checkpoint_id(config):
|
|
79
|
+
wheres.append("checkpoint_id = ?")
|
|
80
|
+
param_values.append(checkpoint_id)
|
|
76
81
|
|
|
77
82
|
# construct predicate for metadata filter
|
|
78
83
|
if filter:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "langgraph-checkpoint-sqlite"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.2"
|
|
4
4
|
description = "Library with a SQLite implementation of LangGraph checkpoint saver."
|
|
5
5
|
authors = []
|
|
6
6
|
license = "MIT"
|
|
@@ -10,11 +10,11 @@ packages = [{ include = "langgraph" }]
|
|
|
10
10
|
|
|
11
11
|
[tool.poetry.dependencies]
|
|
12
12
|
python = "^3.9.0"
|
|
13
|
-
langgraph-checkpoint = "^1.0.
|
|
13
|
+
langgraph-checkpoint = "^1.0.8"
|
|
14
14
|
aiosqlite = "^0.20.0"
|
|
15
15
|
|
|
16
16
|
[tool.poetry.group.dev.dependencies]
|
|
17
|
-
ruff = "^0.
|
|
17
|
+
ruff = "^0.6.2"
|
|
18
18
|
codespell = "^2.2.0"
|
|
19
19
|
pytest = "^7.2.1"
|
|
20
20
|
pytest-asyncio = "^0.21.1"
|
|
File without changes
|