@gaunt-sloth/core 2.0.0-beta.5 → 2.0.0-beta.6
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.
- package/dist/config/schema.d.ts +4 -0
- package/dist/config/schema.js +64 -2
- package/dist/config/schema.js.map +1 -1
- package/dist/config/tokenBudget.d.ts +88 -0
- package/dist/config/tokenBudget.js +155 -0
- package/dist/config/tokenBudget.js.map +1 -0
- package/dist/config/types.d.ts +33 -4
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +24 -0
- package/dist/core/GthAbstractAgent.js +37 -1
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +216 -1
- package/dist/core/GthAgentRunner.js +424 -3
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +196 -0
- package/dist/core/GthLangChainAgent.js +392 -2
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/conversationGrants.d.ts +60 -0
- package/dist/core/approvals/conversationGrants.js +77 -0
- package/dist/core/approvals/conversationGrants.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +16 -0
- package/dist/core/approvals/grants.js +20 -5
- package/dist/core/approvals/grants.js.map +1 -1
- package/dist/core/compaction.d.ts +181 -0
- package/dist/core/compaction.js +293 -0
- package/dist/core/compaction.js.map +1 -0
- package/dist/core/compactionThreshold.d.ts +158 -0
- package/dist/core/compactionThreshold.js +183 -0
- package/dist/core/compactionThreshold.js.map +1 -0
- package/dist/core/contextWindow.d.ts +146 -0
- package/dist/core/contextWindow.js +256 -0
- package/dist/core/contextWindow.js.map +1 -0
- package/dist/core/exitOutputChannel.d.ts +51 -0
- package/dist/core/exitOutputChannel.js +65 -0
- package/dist/core/exitOutputChannel.js.map +1 -0
- package/dist/core/refusal.d.ts +17 -2
- package/dist/core/refusal.js +80 -14
- package/dist/core/refusal.js.map +1 -1
- package/dist/core/runStats.d.ts +1 -1
- package/dist/core/terminationNotice.d.ts +8 -0
- package/dist/core/terminationNotice.js +10 -4
- package/dist/core/terminationNotice.js.map +1 -1
- package/dist/core/terminationReason.d.ts +28 -0
- package/dist/core/terminationReason.js +27 -0
- package/dist/core/terminationReason.js.map +1 -1
- package/dist/core/types.d.ts +35 -1
- package/dist/core/types.js.map +1 -1
- package/dist/history/checkpointRetention.d.ts +279 -0
- package/dist/history/checkpointRetention.js +567 -0
- package/dist/history/checkpointRetention.js.map +1 -0
- package/dist/history/checkpointSaver.d.ts +93 -0
- package/dist/history/checkpointSaver.js +464 -0
- package/dist/history/checkpointSaver.js.map +1 -0
- package/dist/history/historyEnabled.d.ts +27 -0
- package/dist/history/historyEnabled.js +23 -0
- package/dist/history/historyEnabled.js.map +1 -0
- package/dist/history/historyFormat.d.ts +27 -0
- package/dist/history/historyFormat.js +125 -2
- package/dist/history/historyFormat.js.map +1 -1
- package/dist/history/historyStore.d.ts +61 -0
- package/dist/history/historyStore.js +180 -7
- package/dist/history/historyStore.js.map +1 -1
- package/dist/history/recordSession.d.ts +84 -22
- package/dist/history/recordSession.js +187 -12
- package/dist/history/recordSession.js.map +1 -1
- package/dist/history/sessionCheckpointer.d.ts +48 -0
- package/dist/history/sessionCheckpointer.js +200 -0
- package/dist/history/sessionCheckpointer.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/modelCatalog.d.ts +14 -0
- package/dist/providers/modelCatalog.js +4 -0
- package/dist/providers/modelCatalog.js.map +1 -1
- package/dist/providers/modelDiscovery.d.ts +3 -1
- package/dist/providers/modelDiscovery.js +22 -8
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.js +3 -19
- package/dist/providers/ollama.js.map +1 -1
- package/dist/runtime/conversation.js +7 -1
- package/dist/runtime/conversation.js.map +1 -1
- package/dist/runtime/singleShot.js +6 -1
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +77 -0
- package/dist/utils/consoleUtils.js +81 -0
- package/dist/utils/consoleUtils.js.map +1 -1
- package/package.json +2 -2
- package/schema/gsloth-config.schema.json +33 -14
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @packageDocumentation
|
|
3
|
+
* GS2-107 — **the retention policy for the checkpoint tables, and the readout that makes their
|
|
4
|
+
* size visible.**
|
|
5
|
+
*
|
|
6
|
+
* A checkpoint is not a history row. A `sessions` row is a prompt and a response; a checkpoint is
|
|
7
|
+
* the state the agent was working with — tool results verbatim, file contents that were read,
|
|
8
|
+
* command output, whatever an MCP server returned. `history.enabled` is on by default, so every
|
|
9
|
+
* interactive session writes full graph state per super-step, and until this module nothing ever
|
|
10
|
+
* reclaimed a byte.
|
|
11
|
+
*
|
|
12
|
+
* ## The policy, and why it is split in two
|
|
13
|
+
*
|
|
14
|
+
* **Automatic reclamation removes only what can never be resumed. Anything that would cost a user a
|
|
15
|
+
* resume is available only as an explicit command they type.** That follows the ruling GS2-20 was
|
|
16
|
+
* built to: resume sheds nothing, and shedding is the user's own act. An age-based sweep that
|
|
17
|
+
* silently made an old conversation unresumable would remove, without being asked, the one
|
|
18
|
+
* capability the durable checkpointer exists to provide.
|
|
19
|
+
*
|
|
20
|
+
* So:
|
|
21
|
+
*
|
|
22
|
+
* - {@link reclaimUnresumableThreads} is automatic and cannot cost a resume, because it only
|
|
23
|
+
* deletes threads **no conversation row names** — see the predicate below.
|
|
24
|
+
* - {@link selectPrunableConversations} + {@link deleteThreads} is `gth history prune`: it removes
|
|
25
|
+
* state a user *could* still have resumed, so it is never automatic, never has a silent default
|
|
26
|
+
* bound, and says what it will remove before it removes it.
|
|
27
|
+
*
|
|
28
|
+
* ## The predicate: one class, not two
|
|
29
|
+
*
|
|
30
|
+
* A resume travels exactly one link — `gth history list` prints a conversation id,
|
|
31
|
+
* `conversations.thread_id` turns that id into a thread, and the thread is what
|
|
32
|
+
* `resolveResumeTarget` looks up. So a thread that **no conversation row names** cannot be reached
|
|
33
|
+
* by any id a person could type: it is unaddressable, and deleting it removes no capability anyone
|
|
34
|
+
* had.
|
|
35
|
+
*
|
|
36
|
+
* That single predicate covers both classes retention has to reclaim, because the second collapses
|
|
37
|
+
* into the first at the row level:
|
|
38
|
+
*
|
|
39
|
+
* - a thread with **no conversation row at all** — a `/clear` mints a fresh thread that nothing ever
|
|
40
|
+
* names ([[EXT-109]]), and an abandoned boot or a test can leave one too;
|
|
41
|
+
* - a conversation whose **`thread_id` is NULL** — written by `clearConversationThread` when a
|
|
42
|
+
* checkpoint write fails. NULLing the column *destroys the link*, so the thread it used to name is
|
|
43
|
+
* thereafter an orphan by exactly the definition above. There is no second query to write.
|
|
44
|
+
*
|
|
45
|
+
* ## Whole threads, never a prefix
|
|
46
|
+
*
|
|
47
|
+
* Pruning the middle of a thread is forbidden here even though it was **measured not to break this
|
|
48
|
+
* graph**: `channelsFromCheckpoint` walks ancestors only for a `DeltaChannel` absent from
|
|
49
|
+
* `channel_values`, and this state schema has none (`messages` is a `BinaryOperatorAggregate` and
|
|
50
|
+
* every checkpoint carries the whole array), so `getDeltaChannelHistory` is never called on a
|
|
51
|
+
* resume. A prefix policy is nevertheless a wider decision than retention makes, and it would become
|
|
52
|
+
* wrong the moment a channel moves behind a reducer. Whole threads only.
|
|
53
|
+
*
|
|
54
|
+
* ## Two guards, and which one covers which case
|
|
55
|
+
*
|
|
56
|
+
* `/clear` rotates a **live** session onto a thread no conversation row names, and it stays there
|
|
57
|
+
* for the rest of the session. So "unaddressable" does not imply "finished": a thread being written
|
|
58
|
+
* right now can satisfy the predicate, and deleting it is silent amnesia rather than a lost resume,
|
|
59
|
+
* because both interactive surfaces send only the new message and let checkpoint state carry the
|
|
60
|
+
* conversation.
|
|
61
|
+
*
|
|
62
|
+
* - **In this process, the write set.** `GthSqliteSaver` remembers every `thread_id` it has written
|
|
63
|
+
* and excludes that set from every pass it runs. It is the only place that knows: the runner
|
|
64
|
+
* rotates threads without notifying the checkpointer, so an exclusion assembled by a caller from
|
|
65
|
+
* the id a session started with names the wrong thread after the first `/clear` or `/resume`.
|
|
66
|
+
* - **Across processes, {@link RECLAIM_GRACE_MS}.** Another process cannot be asked whether it is
|
|
67
|
+
* still there, so nothing is reclaimed until its newest checkpoint is older than the window. A
|
|
68
|
+
* thread whose age cannot be established is left alone.
|
|
69
|
+
*
|
|
70
|
+
* The residual is a session in another process that has been idle longer than the window — the
|
|
71
|
+
* write set does not reach it and the age gate no longer holds it. Closing that needs shared
|
|
72
|
+
* cross-process session state, which retention does not add.
|
|
73
|
+
*/
|
|
74
|
+
import { DatabaseSync } from 'node:sqlite';
|
|
75
|
+
/**
|
|
76
|
+
* How stale a thread's newest checkpoint must be before automatic reclamation will touch it.
|
|
77
|
+
*
|
|
78
|
+
* Not a tidy-up margin: after a `/clear` a live session writes every remaining checkpoint under a
|
|
79
|
+
* thread no conversation row names, and another process cannot be asked whether it is still there.
|
|
80
|
+
* A day is far longer than the gap between two super-steps of a session anyone is still using,
|
|
81
|
+
* while still reclaiming the rows within a day of the session ending.
|
|
82
|
+
*/
|
|
83
|
+
export declare const RECLAIM_GRACE_MS: number;
|
|
84
|
+
/** How many threads the readout names individually. */
|
|
85
|
+
export declare const DEFAULT_TOP_THREADS = 5;
|
|
86
|
+
/** One thread's footprint in the checkpoint tables. */
|
|
87
|
+
export interface ThreadUsage {
|
|
88
|
+
threadId: string;
|
|
89
|
+
/** The conversation that names this thread, when one does — absent means unaddressable. */
|
|
90
|
+
conversationId?: number;
|
|
91
|
+
command?: string;
|
|
92
|
+
checkpointCount: number;
|
|
93
|
+
/** Bytes of checkpoint / metadata / pending-write blobs stored under the thread. */
|
|
94
|
+
bytes: number;
|
|
95
|
+
/** The `ts` of the newest checkpoint, when it could be read. */
|
|
96
|
+
newestTs?: string;
|
|
97
|
+
}
|
|
98
|
+
/** What the checkpoint tables hold, for the readout. */
|
|
99
|
+
export interface CheckpointStoreStats {
|
|
100
|
+
dbPath: string;
|
|
101
|
+
/**
|
|
102
|
+
* Size of the database file, which also holds `sessions` / `conversations` / the FTS index — so it
|
|
103
|
+
* is reported beside {@link checkpointBytes} rather than instead of it. Zero when the file is
|
|
104
|
+
* absent.
|
|
105
|
+
*/
|
|
106
|
+
fileBytes: number;
|
|
107
|
+
/** Bytes of checkpoint, metadata and pending-write blobs — the checkpoint tables' own share. */
|
|
108
|
+
checkpointBytes: number;
|
|
109
|
+
checkpointCount: number;
|
|
110
|
+
writeCount: number;
|
|
111
|
+
threadCount: number;
|
|
112
|
+
/** The biggest threads by stored bytes, largest first. */
|
|
113
|
+
largestThreads: ThreadUsage[];
|
|
114
|
+
/** Threads no conversation row names, and what they cost — what reclamation will take. */
|
|
115
|
+
unresumableThreadCount: number;
|
|
116
|
+
unresumableBytes: number;
|
|
117
|
+
}
|
|
118
|
+
/** What one {@link reclaimUnresumableThreads} / {@link deleteThreads} pass removed. */
|
|
119
|
+
export interface ReclaimSummary {
|
|
120
|
+
threadCount: number;
|
|
121
|
+
checkpointCount: number;
|
|
122
|
+
writeCount: number;
|
|
123
|
+
bytes: number;
|
|
124
|
+
}
|
|
125
|
+
/** A conversation `gth history prune` would remove the stored state of. */
|
|
126
|
+
export interface PrunableConversation {
|
|
127
|
+
conversationId: number;
|
|
128
|
+
threadId: string;
|
|
129
|
+
command?: string;
|
|
130
|
+
/** Last recorded activity: the newest turn's timestamp, or the conversation's start. */
|
|
131
|
+
lastActivityTs: string;
|
|
132
|
+
turnCount: number;
|
|
133
|
+
checkpointCount: number;
|
|
134
|
+
bytes: number;
|
|
135
|
+
/**
|
|
136
|
+
* True when the last recorded turn is newer than {@link RECLAIM_GRACE_MS} — so this conversation
|
|
137
|
+
* may be **open in another window right now**, and pruning it would take a live session's memory
|
|
138
|
+
* rather than an old one's.
|
|
139
|
+
*
|
|
140
|
+
* A flag and not an exclusion, deliberately. `gth history prune` is given an explicit bound by the
|
|
141
|
+
* person typing it, and silently keeping back rows inside that bound would make the bound a lie;
|
|
142
|
+
* liveness across processes is also not knowable from here, so a refusal would be a guess wearing
|
|
143
|
+
* a guarantee. The automatic pass can be conservative because nobody asked for it. This one says
|
|
144
|
+
* what it is about to do and lets the person answer.
|
|
145
|
+
*/
|
|
146
|
+
recentlyActive: boolean;
|
|
147
|
+
}
|
|
148
|
+
/** Bounds for {@link selectPrunableConversations}. At least one is required by the command. */
|
|
149
|
+
export interface PruneBounds {
|
|
150
|
+
/** Prune conversations whose last activity is older than this many days. */
|
|
151
|
+
olderThanDays?: number;
|
|
152
|
+
/**
|
|
153
|
+
* Keep the N most recently active resumable conversations **whole** and prune the rest.
|
|
154
|
+
*
|
|
155
|
+
* Deliberately NOT "keep the last N super-steps of each thread": that is the prefix policy this
|
|
156
|
+
* module forbids, and a flag whose name suggested it would be a documentation hazard.
|
|
157
|
+
*/
|
|
158
|
+
keepLast?: number;
|
|
159
|
+
/** Injectable clock for the age bound. */
|
|
160
|
+
now?: number;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* True when both halves of the link this module reasons over are present. Without `conversations`
|
|
164
|
+
* every thread would look unaddressable and a reclamation pass would delete the whole store — so a
|
|
165
|
+
* database missing that table is left entirely alone rather than swept.
|
|
166
|
+
*/
|
|
167
|
+
export declare function retentionTablesReady(db: DatabaseSync): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* The predicate itself, as one constant.
|
|
170
|
+
*
|
|
171
|
+
* It asks `conversations` a question once per distinct thread in the store, so it is only cheap
|
|
172
|
+
* while `conversations.thread_id` is indexed — `conversations.id` is a rowid alias and indexes
|
|
173
|
+
* nothing else, which left this scanning the whole table per thread (measured: 3.18s at 6,000
|
|
174
|
+
* threads, 13ms with `idx_conversations_thread_id`, created in `historyStore.migrate`). Named here
|
|
175
|
+
* rather than inlined so the spec that asks SQLite for the query plan is looking at the same text
|
|
176
|
+
* this runs, and cannot go on passing after the query is edited.
|
|
177
|
+
*/
|
|
178
|
+
export declare const UNADDRESSABLE_THREADS_SQL = "SELECT DISTINCT c.thread_id AS thread_id\n FROM checkpoints c\n WHERE NOT EXISTS (\n SELECT 1 FROM conversations v WHERE v.thread_id = c.thread_id\n )";
|
|
179
|
+
/**
|
|
180
|
+
* Every thread in the checkpoint tables that **no conversation row names** — see the module note for
|
|
181
|
+
* why that one predicate covers both unresumable classes.
|
|
182
|
+
*
|
|
183
|
+
* `includeWithinGrace: true` answers "what is unaddressable", which is what the readout reports;
|
|
184
|
+
* the default answers "what may be deleted now", which additionally requires the thread's newest
|
|
185
|
+
* checkpoint to be older than {@link RECLAIM_GRACE_MS}. Never throws.
|
|
186
|
+
*/
|
|
187
|
+
export declare function findUnaddressableThreads(db: DatabaseSync, options?: {
|
|
188
|
+
now?: number;
|
|
189
|
+
graceMs?: number;
|
|
190
|
+
includeWithinGrace?: boolean;
|
|
191
|
+
excludeThreadIds?: readonly string[];
|
|
192
|
+
}): string[];
|
|
193
|
+
/**
|
|
194
|
+
* Delete every checkpoint and pending write of the named threads, and report what went.
|
|
195
|
+
*
|
|
196
|
+
* The single-thread spelling on the saver (`GthSqliteSaver.deleteThread`) routes through here, so
|
|
197
|
+
* there is one implementation of the delete rather than two that can drift.
|
|
198
|
+
*
|
|
199
|
+
* **Both tables go in one transaction.** A thread's rows live in `checkpoints` and in
|
|
200
|
+
* `checkpoint_writes`, and only the first of those is what anything looks for: every candidate query
|
|
201
|
+
* in this module reads `FROM checkpoints`. So a failure between the two statements would leave
|
|
202
|
+
* `checkpoint_writes` rows belonging to a thread that no longer appears in `checkpoints` — bytes the
|
|
203
|
+
* readout still counts as stored, that no later pass can find, and that no reader can reach. Not a
|
|
204
|
+
* self-healing leak; a permanent one. Either both deletes land or neither does.
|
|
205
|
+
*
|
|
206
|
+
* The caller must not already be inside a transaction: the rollback here would discard theirs. No
|
|
207
|
+
* caller is — the two entry points are the close hook and `gth history prune`.
|
|
208
|
+
*/
|
|
209
|
+
export declare function deleteThreads(db: DatabaseSync, threadIds: readonly string[]): ReclaimSummary;
|
|
210
|
+
/**
|
|
211
|
+
* The automatic half of the policy: delete every thread no conversation row names and whose newest
|
|
212
|
+
* checkpoint is past the grace window. Never throws, and never touches a thread a resume could
|
|
213
|
+
* reach.
|
|
214
|
+
*/
|
|
215
|
+
export declare function reclaimUnresumableThreads(db: DatabaseSync, options?: {
|
|
216
|
+
now?: number;
|
|
217
|
+
graceMs?: number;
|
|
218
|
+
excludeThreadIds?: readonly string[];
|
|
219
|
+
}): ReclaimSummary;
|
|
220
|
+
/**
|
|
221
|
+
* The conversations `gth history prune` would remove the stored state of, newest activity first.
|
|
222
|
+
*
|
|
223
|
+
* A conversation qualifies when it still names a thread that has checkpoints (there is something to
|
|
224
|
+
* remove) and it satisfies **every** bound given. `olderThanDays` and `keepLast` therefore compose
|
|
225
|
+
* as a conjunction: with both, a conversation is pruned only when it is older than the age AND
|
|
226
|
+
* outside the newest N. Passing neither selects nothing — the command requires an explicit bound,
|
|
227
|
+
* so that there is no silent default for an operation that can cost a resume.
|
|
228
|
+
*
|
|
229
|
+
* **Neither of the automatic pass's two guards applies here, and that is the design.** The bounds
|
|
230
|
+
* the person typed are the whole selection: a grace window layered on top would quietly shrink the
|
|
231
|
+
* set they asked for, and the in-process write set is empty in a `gth history prune` process, which
|
|
232
|
+
* shares no state with the session in the window next door. What this does instead is *say so* —
|
|
233
|
+
* {@link PrunableConversation.recentlyActive} marks every candidate whose last turn is inside
|
|
234
|
+
* {@link RECLAIM_GRACE_MS}, the plan prints that marker, and the command asks before removing
|
|
235
|
+
* anything.
|
|
236
|
+
*/
|
|
237
|
+
export declare function selectPrunableConversations(db: DatabaseSync, bounds: PruneBounds): PrunableConversation[];
|
|
238
|
+
/**
|
|
239
|
+
* `VACUUM` — the part that actually gives the disk space back. Deleting rows in SQLite moves pages
|
|
240
|
+
* onto the free list and leaves the file exactly as large as it was, so a prune that skipped this
|
|
241
|
+
* would report bytes removed while the file a user can see never moved.
|
|
242
|
+
*
|
|
243
|
+
* Returns whether it ran. It cannot run inside a transaction, and it needs the file to itself; a
|
|
244
|
+
* failure is reported rather than thrown, because the rows are already gone and the run should say
|
|
245
|
+
* so.
|
|
246
|
+
*/
|
|
247
|
+
export declare function vacuumStore(db: DatabaseSync): boolean;
|
|
248
|
+
/**
|
|
249
|
+
* The readout: what the checkpoint tables hold, and what of it is unaddressable.
|
|
250
|
+
*
|
|
251
|
+
* `fileBytes` and `checkpointBytes` are reported separately on purpose — the same file also holds
|
|
252
|
+
* the session transcripts and the FTS index, so one number labelled "checkpoints" that is really the
|
|
253
|
+
* whole file would be a false statement on the very screen this exists to make honest.
|
|
254
|
+
*/
|
|
255
|
+
export declare function collectCheckpointStoreStats(db: DatabaseSync, dbPath: string, topN?: number): CheckpointStoreStats;
|
|
256
|
+
/**
|
|
257
|
+
* A read/write connection to the history file for the maintenance commands, or `null` when there is
|
|
258
|
+
* nothing there. Fail-soft in the same shape as `openHistoryStore` / `openCheckpointSaver`, and it
|
|
259
|
+
* never CREATES the file: `gth history prune` on a machine with no history should say there is none,
|
|
260
|
+
* not leave an empty database behind.
|
|
261
|
+
*/
|
|
262
|
+
export declare class CheckpointMaintenance {
|
|
263
|
+
private readonly db;
|
|
264
|
+
private constructor();
|
|
265
|
+
static open(dbPath: string): CheckpointMaintenance | null;
|
|
266
|
+
stats(dbPath: string, topN?: number): CheckpointStoreStats;
|
|
267
|
+
prunable(bounds: PruneBounds): PrunableConversation[];
|
|
268
|
+
unaddressable(options?: {
|
|
269
|
+
now?: number;
|
|
270
|
+
graceMs?: number;
|
|
271
|
+
}): string[];
|
|
272
|
+
remove(threadIds: readonly string[]): ReclaimSummary;
|
|
273
|
+
/** Bytes stored under exactly these threads — what removing them would reclaim. */
|
|
274
|
+
bytesOf(threadIds: readonly string[]): number;
|
|
275
|
+
vacuum(): boolean;
|
|
276
|
+
close(): void;
|
|
277
|
+
}
|
|
278
|
+
/** Fail-soft opener for {@link CheckpointMaintenance}; `null` when there is no store to maintain. */
|
|
279
|
+
export declare function openCheckpointMaintenance(dbPath: string): CheckpointMaintenance | null;
|