Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
b91d1d4
feat(ai): cursor + chat() resume seam, shared locks capability, CUSTO…
AlemTuzlak Jun 18, 2026
aacddbf
feat(persistence): @tanstack/ai-persistence + SQL core + backends + s…
AlemTuzlak Jun 18, 2026
d2462d6
feat(ai-client): in-session auto-resume
AlemTuzlak Jun 18, 2026
fb45b01
docs(persistence): overview page, ai-persistence skill, changeset, kn…
AlemTuzlak Jun 18, 2026
b141e4b
ci: apply automated fixes
autofix-ci[bot] Jun 18, 2026
d0d8672
feat: finalize ai persistence
AlemTuzlak Jul 2, 2026
fc45b4c
feat: add mysql persistence chat example
AlemTuzlak Jul 3, 2026
3a75f11
fix: quote mysql usage column
AlemTuzlak Jul 3, 2026
0d661c8
feat: add cloudflare r2 artifact persistence
AlemTuzlak Jul 3, 2026
253a2eb
feat: add cloudflare blob persistence primitives
AlemTuzlak Jul 3, 2026
a46c9bc
docs: split persistence guide by scenario
AlemTuzlak Jul 3, 2026
c864d51
feat(persistence): client resume + framework use-chat persistence upd…
AlemTuzlak Jul 3, 2026
17e9b93
feat(sandbox): consume persistence without bridge
AlemTuzlak Jul 6, 2026
8d61c54
feat(persistence): add orm migration CLIs
AlemTuzlak Jul 6, 2026
a4470f5
Merge remote-tracking branch 'origin/main' into feat/persistence
AlemTuzlak Jul 6, 2026
39ce14a
feat(sandbox): persist managed workspace files
AlemTuzlak Jul 6, 2026
6ce5403
fix(ai): tolerate seed messages without parts
AlemTuzlak Jul 6, 2026
276faea
docs(persistence): type-check persistence examples
AlemTuzlak Jul 6, 2026
173fcc5
fix(client): preserve pending interrupts on mount
AlemTuzlak Jul 6, 2026
c94d5b8
ci: apply automated fixes
autofix-ci[bot] Jul 6, 2026
356188b
feat: add generation persistence and resumability
AlemTuzlak Jul 7, 2026
50b2314
ci: apply automated fixes
autofix-ci[bot] Jul 7, 2026
e3d928d
Merge remote-tracking branch 'origin/main' into feat/persistence
AlemTuzlak Jul 8, 2026
e46b990
Merge remote-tracking branch 'origin/feat/persistence' into feat/pers…
AlemTuzlak Jul 8, 2026
174eeb3
fix: address persistence ci failures
AlemTuzlak Jul 8, 2026
52e2b2e
ci: apply automated fixes
autofix-ci[bot] Jul 8, 2026
0271f9a
fix(persistence): default migrations to opt-in
AlemTuzlak Jul 8, 2026
c6cccfa
feat(persistence): add SQL migration CLI docs
AlemTuzlak Jul 8, 2026
9981da4
docs(persistence): reorganize persistence guides
AlemTuzlak Jul 8, 2026
d580018
fix(persistence): document internals and r2 prefixes
AlemTuzlak Jul 8, 2026
bbf2d2a
Use shared base64 utils
tombeckenham Jul 9, 2026
d681407
feat(persistence): split chat and generation middleware
tombeckenham Jul 9, 2026
39ea98f
ci: apply automated fixes
autofix-ci[bot] Jul 9, 2026
d5e8af7
feat: split persistence into state (middleware) + delivery (transport…
AlemTuzlak Jul 9, 2026
f9db0af
refactor(ai)!: group batch under durability option ({ adapter, batch })
AlemTuzlak Jul 9, 2026
d4361b1
Merge origin/main into feat/persistence
AlemTuzlak Jul 10, 2026
61026d5
feat: add persistence and delivery durability
AlemTuzlak Jul 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .changeset/persistence-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
'@tanstack/ai': minor
'@tanstack/ai-client': minor
'@tanstack/ai-durable-stream': patch
'@tanstack/ai-persistence': patch
'@tanstack/ai-persistence-cloudflare': patch
'@tanstack/ai-persistence-drizzle': patch
'@tanstack/ai-persistence-prisma': patch
'@tanstack/ai-sandbox': minor
'@tanstack/ai-event-client': patch
'@tanstack/ai-angular': minor
'@tanstack/ai-preact': minor
'@tanstack/ai-react': minor
'@tanstack/ai-solid': minor
'@tanstack/ai-svelte': minor
'@tanstack/ai-vue': minor
---

Persistence v2: split state (middleware) vs delivery (transport) durability.

State durability stays on the middleware layer as `withChatPersistence` /
`withGenerationPersistence`, backed by a store contract (messages, runs,
interrupts, metadata, locks, artifacts, blobs). The `@tanstack/ai-persistence`
package now ships a state-only middleware, an in-core memory backend, and a
shared conformance suite; `@tanstack/ai-persistence-drizzle` and
`@tanstack/ai-persistence-prisma` provide ORM state backends, while
`@tanstack/ai-persistence-cloudflare` provides first-class D1, Durable Object,
and R2-backed stores.

Delivery durability (replay a disconnected/reloaded stream) moves to the
transport layer via a pluggable `StreamDurability` sink — the SDK owns zero
delivery-event storage. The new `@tanstack/ai-durable-stream` package provides a
durable-streams-protocol `StreamDurability` adapter, and the client
(`@tanstack/ai-client`) plus every framework binding (`@tanstack/ai-react`,
`-solid`, `-vue`, `-svelte`, `-angular`, `-preact`) switch to resumable SSE with
interrupt-only resume.

The home-grown delivery/event-log subsystem is removed: the in-band `cursor` on
`StreamChunk`, the `cursor` param on `chat()`, the public/internal event stores,
the `ResumeSource` seam, cursor-replay client machinery, and the deprecated
approval-store shim are all deleted (this feature is unreleased — no back-compat
shims). Interrupt resume (approvals / client-tool results via
`RunAgentInput.resume[]`) is preserved as state durability.

The delivery-store / SQL-driver packages that only existed to back the removed
event log — `@tanstack/ai-persistence-sql`,
`@tanstack/ai-persistence-sqlite`, and `@tanstack/ai-persistence-postgres` — are
removed. They were never published (part of this same unreleased persistence
work), so no npm tombstone release is needed.

Generation events no longer expose transport cursors. Stream offsets remain
owned by delivery-durability adapters; generation events retain their thread
and run identifiers for correlation.
7 changes: 5 additions & 2 deletions docs/api/ai-angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,12 @@ export class CustomGenerationComponent {
}
```

**Options:** `connection?`, `fetcher?`, `id?`, `body?` (reactive), `devtools?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`
**Options:** `connection?`, `fetcher?`, `id?`, `body?` (reactive), `persistence?`, `autoResume?`, `initialResumeSnapshot?`, `resumeState?` (reactive), `devtools?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`

**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset` — all reactive state is a read-only `Signal<T>`.
**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset`, `resume`, `resumeSnapshot`, `resumeState`, `pendingArtifacts`, `resultArtifacts` — all reactive state is a read-only `Signal<T>`.

For the end-to-end persistence setup, see
[Generation Persistence](../persistence/generation-persistence).

### `injectGenerateImage(options)`

Expand Down
20 changes: 19 additions & 1 deletion docs/api/ai-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ Extends `ChatClientOptions` from `@tanstack/ai-client`:
- `initialMessages?` - Initial messages array
- `id?` - Unique identifier for this chat instance
- `threadId?` - Thread ID for AG-UI run correlation. Persists across sends; auto-generated if omitted
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-4o' }`)
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-5.5' }`)
- `body?` - **Deprecated.** Use `forwardedProps` instead. Still works for backward compatibility; values are merged into `forwardedProps` on the wire
- `context?` - Typed client-local runtime context passed to client tool implementations. This value is not serialized to the server
- `onResponse?` - Callback when response is received
Expand Down Expand Up @@ -158,6 +158,24 @@ function that resolves per request.
For error narrowing, import `UnsupportedResponseStreamError` and
`StreamTruncatedError` from `@tanstack/ai-client`.

## Generation Hooks

React also exports `useGeneration`, `useGenerateImage`, `useGenerateAudio`,
`useGenerateSpeech`, `useTranscription`, `useSummarize`, and
`useGenerateVideo`.

Generation hook options include `connection` or `fetcher`, `id`, `body`,
`persistence`, `autoResume`, `initialResumeSnapshot`, `resumeState`,
`devtools`, `onResult`, `onError`, `onProgress`, and `onChunk`.

Generation hook returns include `generate`, `result`, `isLoading`, `error`,
`status`, `stop`, `reset`, `resume`, `resumeSnapshot`, `resumeState`,
`pendingArtifacts`, and `resultArtifacts`. Video generation also returns
`jobId` and `videoStatus`.

For the end-to-end persistence setup, see
[Generation Persistence](../persistence/generation-persistence).

## Example: Basic Chat

```tsx
Expand Down
21 changes: 20 additions & 1 deletion docs/api/ai-solid.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Extends `ChatClientOptions` from `@tanstack/ai-client`:
- `initialMessages?` - Initial messages array
- `id?` - Unique identifier for this chat instance
- `threadId?` - Thread ID for AG-UI run correlation. Persists across sends; auto-generated if omitted
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-4o' }`)
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-5.5' }`)
- `body?` - **Deprecated.** Use `forwardedProps` instead. Still works for backward compatibility; values are merged into `forwardedProps` on the wire
- `context?` - Typed client-local runtime context passed to client tool implementations. This value is not serialized to the server
- `onResponse?` - Callback when response is received
Expand Down Expand Up @@ -120,6 +120,25 @@ interface UseChatReturn {

**Note:** Unlike React, `messages`, `isLoading`, and `error` are SolidJS `Accessor` functions, so you need to call them to get their values (e.g., `messages()` instead of just `messages`).

## Generation Hooks

Solid also exports `useGeneration`, `useGenerateImage`, `useGenerateAudio`,
`useGenerateSpeech`, `useTranscription`, `useSummarize`, and
`useGenerateVideo`.

Generation hook options include `connection` or `fetcher`, `id`, `body`,
`persistence`, `autoResume`, `initialResumeSnapshot`, `resumeState`,
`devtools`, `onResult`, `onError`, `onProgress`, and `onChunk`.

Generation hook returns include `generate`, `result`, `isLoading`, `error`,
`status`, `stop`, `reset`, `resume`, `resumeSnapshot`, `resumeState`,
`pendingArtifacts`, and `resultArtifacts`. Reactive values are Solid accessors,
so read `resumeState()` and `pendingArtifacts()`. Video generation also returns
`jobId` and `videoStatus`.

For the end-to-end persistence setup, see
[Generation Persistence](../persistence/generation-persistence).

## Connection Adapters

Re-exported from `@tanstack/ai-client` for convenience:
Expand Down
9 changes: 6 additions & 3 deletions docs/api/ai-svelte.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Extends `ChatClientOptions` from `@tanstack/ai-client` (minus internal state cal
- `initialMessages?` - Initial messages array
- `id?` - Unique identifier for this chat instance
- `threadId?` - Thread ID for AG-UI run correlation. Persists across sends; auto-generated if omitted
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-4o' }`)
- `forwardedProps?` - Arbitrary client-controlled JSON forwarded to the server in the AG-UI `RunAgentInput.forwardedProps` field (e.g., `{ provider: 'openai', model: 'gpt-5.5' }`)
- `body?` - **Deprecated.** Use `forwardedProps` instead. Still works for backward compatibility; values are merged into `forwardedProps` on the wire
- `context?` - Typed client-local runtime context passed to client tool implementations. This value is not serialized to the server
- `live?` - Enable live subscription mode (subscribes on creation)
Expand Down Expand Up @@ -297,9 +297,12 @@ const gen = createGeneration({
// gen.result, gen.isLoading, gen.error, gen.status
```

**Options:** `connection?`, `fetcher?`, `id?`, `body?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`
**Options:** `connection?`, `fetcher?`, `id?`, `body?`, `persistence?`, `autoResume?`, `initialResumeSnapshot?`, `resumeState?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`

**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset`, `updateBody` -- all state properties are reactive getters.
**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset`, `updateBody`, `dispose`, `resume`, `resumeSnapshot`, `resumeState`, `pendingArtifacts`, `resultArtifacts` -- all state properties are reactive getters.

For the end-to-end persistence setup, see
[Generation Persistence](../persistence/generation-persistence).

### `createGenerateImage(options)`

Expand Down
7 changes: 5 additions & 2 deletions docs/api/ai-vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,12 @@ const { generate, result, isLoading, error, status, stop, reset } =
});
```

**Options:** `connection?`, `fetcher?`, `id?`, `body?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`
**Options:** `connection?`, `fetcher?`, `id?`, `body?`, `persistence?`, `autoResume?`, `initialResumeSnapshot?`, `resumeState?`, `onResult?`, `onError?`, `onProgress?`, `onChunk?`

**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset` -- all reactive state is `DeepReadonly<ShallowRef<T>>`.
**Returns:** `generate`, `result`, `isLoading`, `error`, `status`, `stop`, `reset`, `resume`, `resumeSnapshot`, `resumeState`, `pendingArtifacts`, `resultArtifacts` -- all reactive state is `DeepReadonly<ShallowRef<T>>`. Read refs with `.value` in `<script setup>`.

For the end-to-end persistence setup, see
[Generation Persistence](../persistence/generation-persistence).

### `useGenerateImage(options)`

Expand Down
Loading
Loading