@tanstack/ai-persistence 0.5.5 → 0.5.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-persistence",
3
- "version": "0.5.5",
3
+ "version": "0.5.7",
4
4
  "description": "Composable state persistence for TanStack AI messages, runs, interrupts, metadata, and locks.",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "vitest": "^4.1.10",
46
- "@tanstack/ai": "^0.52.1"
46
+ "@tanstack/ai": "^0.54.0"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "vitest": {
@@ -53,7 +53,7 @@
53
53
  "devDependencies": {
54
54
  "@vitest/coverage-v8": "4.1.10",
55
55
  "vitest": "^4.1.10",
56
- "@tanstack/ai": "0.52.1"
56
+ "@tanstack/ai": "0.54.0"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "vite build",
@@ -28,6 +28,17 @@ type an object literal inline (autocomplete + contract checking, no separate
28
28
  annotation).
29
29
 
30
30
  ```ts
31
+ import type {
32
+ ArtifactRecord,
33
+ BlobBody,
34
+ BlobGetOptions,
35
+ BlobListOptions,
36
+ BlobListPage,
37
+ BlobObject,
38
+ BlobPutOptions,
39
+ BlobRecord,
40
+ } from '@tanstack/ai-persistence'
41
+
31
42
  // BlobStore — the byte layer. R2 backs it.
32
43
  interface BlobStore {
33
44
  put: (
@@ -259,7 +259,7 @@ inspects your storage.
259
259
  You rarely need all four stores at once. Implement what you own and fill the
260
260
  rest from another base:
261
261
 
262
- ```ts ignore
262
+ ```ts
263
263
  import { composePersistence, memoryPersistence } from '@tanstack/ai-persistence'
264
264
  import { messages, runs } from './my-stores'
265
265
 
@@ -307,7 +307,7 @@ This matters more here than anywhere else: there is no reference driver to
307
307
  compare against, so the testkit is the only thing standing between a subtle
308
308
  idempotency bug and stuck approvals in production.
309
309
 
310
- ```ts ignore
310
+ ```ts
311
311
  import { runPersistenceConformance } from '@tanstack/ai-persistence/testkit'
312
312
  import { chatPersistence } from '../src/lib/chat-persistence'
313
313
 
@@ -516,7 +516,7 @@ route** — derive the user from the session, never trust a client-supplied id.
516
516
 
517
517
  ## 5. Verify
518
518
 
519
- ```ts ignore
519
+ ```ts
520
520
  import { runPersistenceConformance } from '@tanstack/ai-persistence/testkit'
521
521
  import { chatPersistence } from '../src/lib/chat-persistence'
522
522
 
@@ -474,7 +474,7 @@ route** — derive the user from the session, never trust a client-supplied id.
474
474
 
475
475
  ## 5. Verify
476
476
 
477
- ```ts ignore
477
+ ```ts
478
478
  import { runPersistenceConformance } from '@tanstack/ai-persistence/testkit'
479
479
  import { chatPersistence } from '../src/lib/chat-persistence'
480
480
 
@@ -98,6 +98,9 @@ preserve plain-text and structured-output assistant messages separately when
98
98
  those messages use different ids.
99
99
 
100
100
  ```ts
101
+ import { withPersistence } from '@tanstack/ai-persistence'
102
+ import { persistence } from './persistence'
103
+
101
104
  withPersistence(persistence, {
102
105
  snapshotStreaming: true,
103
106
  snapshotIntervalMs: 1000, // default
@@ -159,6 +162,8 @@ Server-authoritative clients load history by `threadId` (often `GET`):
159
162
 
160
163
  ```ts
161
164
  import { reconstructChat } from '@tanstack/ai-persistence'
165
+ import { persistence } from './persistence'
166
+ import { sessionUserId, userOwnsThread } from './auth'
162
167
 
163
168
  export async function GET(request: Request) {
164
169
  return reconstructChat(persistence, request, {
@@ -37,6 +37,7 @@ a complete `node:sqlite` implementation lives in
37
37
  ```ts
38
38
  import { defineAIPersistence } from '@tanstack/ai-persistence'
39
39
  import type { ChatWithInterruptsPersistence } from '@tanstack/ai-persistence'
40
+ import { messages, runs, interrupts } from './stores'
40
41
 
41
42
  // Sparse is fine — only implement what you need.
42
43
  export const persistence: ChatWithInterruptsPersistence = defineAIPersistence({
@@ -73,9 +74,11 @@ mistake when writing an adapter.
73
74
  ### `MessageStore`
74
75
 
75
76
  ```ts
77
+ import type { ModelMessage } from '@tanstack/ai'
78
+
76
79
  interface MessageStore {
77
- loadThread(threadId: string): Promise<Array<ModelMessage>>
78
- saveThread(threadId: string, messages: Array<ModelMessage>): Promise<void>
80
+ loadThread: (threadId: string) => Promise<Array<ModelMessage>>
81
+ saveThread: (threadId: string, messages: Array<ModelMessage>) => Promise<void>
79
82
  }
80
83
  ```
81
84
 
@@ -120,6 +123,9 @@ always a choice you made on purpose rather than a check that quietly did not
120
123
  run. Declare yours and the suite reports them as skipped with a reason:
121
124
 
122
125
  ```ts
126
+ import { runPersistenceConformance } from '@tanstack/ai-persistence/testkit'
127
+ import { persistence } from './persistence'
128
+
123
129
  // The shipped sqlite example implements findActiveRun and listReclaimable and
124
130
  // declares only the one it omits.
125
131
  runPersistenceConformance('sqlite', () => persistence, {
@@ -128,14 +134,16 @@ runPersistenceConformance('sqlite', () => persistence, {
128
134
  ```
129
135
 
130
136
  ```ts
137
+ import type { RunRecord, RunStatus } from '@tanstack/ai-persistence'
138
+
131
139
  interface RunStore {
132
140
  // Required
133
- createOrResume(
141
+ createOrResume: (
134
142
  input: Pick<RunRecord, 'runId' | 'threadId' | 'startedAt'> & {
135
143
  status?: RunStatus
136
144
  },
137
- ): Promise<RunRecord>
138
- update(
145
+ ) => Promise<RunRecord>
146
+ update: (
139
147
  runId: string,
140
148
  patch: Partial<
141
149
  Pick<
@@ -150,16 +158,16 @@ interface RunStore {
150
158
  | 'driverEpoch'
151
159
  >
152
160
  >,
153
- ): Promise<void>
154
- get(runId: string): Promise<RunRecord | null>
155
- findActiveRun(threadId: string): Promise<RunRecord | null>
161
+ ) => Promise<void>
162
+ get: (runId: string) => Promise<RunRecord | null>
163
+ findActiveRun: (threadId: string) => Promise<RunRecord | null>
156
164
 
157
165
  // Optional
158
- listByThread?(threadId: string): Promise<Array<RunRecord>>
159
- listReclaimable?(opts: {
166
+ listByThread?: (threadId: string) => Promise<Array<RunRecord>>
167
+ listReclaimable?: (opts: {
160
168
  now: number
161
169
  ttlMs: number
162
- }): Promise<Array<RunRecord>>
170
+ }) => Promise<Array<RunRecord>>
163
171
  }
164
172
  ```
165
173
 
@@ -293,15 +301,25 @@ and each must be declared via `skipMethods` when absent.
293
301
  ### `InterruptStore`
294
302
 
295
303
  ```ts
304
+ import type {
305
+ InterruptCommitEntry,
306
+ InterruptRecord,
307
+ } from '@tanstack/ai-persistence'
308
+
296
309
  interface InterruptStore {
297
- create(record: Omit<InterruptRecord, 'status' | 'resolvedAt'>): Promise<void>
298
- resolve(interruptId: string, response?: unknown): Promise<void>
299
- cancel(interruptId: string): Promise<void>
300
- get(interruptId: string): Promise<InterruptRecord | null>
301
- list(threadId: string): Promise<Array<InterruptRecord>>
302
- listPending(threadId: string): Promise<Array<InterruptRecord>>
303
- listByRun(runId: string): Promise<Array<InterruptRecord>>
304
- listPendingByRun(runId: string): Promise<Array<InterruptRecord>>
310
+ create: (
311
+ record: Omit<InterruptRecord, 'status' | 'resolvedAt'>,
312
+ ) => Promise<void>
313
+ resolve: (interruptId: string, response?: unknown) => Promise<void>
314
+ cancel: (interruptId: string) => Promise<void>
315
+ // Optional: apply a validated resume batch all-or-nothing instead of
316
+ // per-entry resolve/cancel.
317
+ commitBatch?: (entries: ReadonlyArray<InterruptCommitEntry>) => Promise<void>
318
+ get: (interruptId: string) => Promise<InterruptRecord | null>
319
+ list: (threadId: string) => Promise<Array<InterruptRecord>>
320
+ listPending: (threadId: string) => Promise<Array<InterruptRecord>>
321
+ listByRun: (runId: string) => Promise<Array<InterruptRecord>>
322
+ listPendingByRun: (runId: string) => Promise<Array<InterruptRecord>>
305
323
  }
306
324
  ```
307
325
 
@@ -314,9 +332,9 @@ interface InterruptStore {
314
332
 
315
333
  ```ts
316
334
  interface MetadataStore {
317
- get(namespace: string, key: string): Promise<unknown | null>
318
- set(namespace: string, key: string, value: unknown): Promise<void>
319
- delete(namespace: string, key: string): Promise<void>
335
+ get: (namespace: string, key: string) => Promise<unknown | null>
336
+ set: (namespace: string, key: string, value: unknown) => Promise<void>
337
+ delete: (namespace: string, key: string) => Promise<void>
320
338
  }
321
339
  ```
322
340