Skip to content

blog: surviving the refresh - #1112

Open
AlemTuzlak wants to merge 2 commits into
mainfrom
blog/surviving-the-refresh
Open

blog: surviving the refresh#1112
AlemTuzlak wants to merge 2 commits into
mainfrom
blog/surviving-the-refresh

Conversation

@AlemTuzlak

@AlemTuzlak AlemTuzlak commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Launch post for the TanStack AI durability release.

What it covers

The problem framing is one user action: a reload mid-answer breaks the transcript, the stream, and the sandboxed agent doing the work. Three layers, three fixes.

  • How it works - one route with POST + GET and the useChat call, in a single snippet.
  • Layer 1 - chat persistence (withPersistence, client ownership choice, a defineMessageStore adapter).
  • Layer 2 - resumable streams (durability adapter, memoryStream to durableStream swap, SSE and NDJSON).
  • Layer 3 - generation persistence (withGenerationPersistence, useGenerateImage({ persistence: true })).
  • Layer 4 - durable sandboxed agent runs (journal, takeover, reapDetachedRuns).
  • Also in this release - server-side memory, the rebuilt interrupt lifecycle, multi-instance locks, the BytePlus adapter (Seedance video), and zod out of @tanstack/ai.

Notes

  • Every snippet is lifted from the new docs pages in TanStack/ai, so the API names, option shapes and model ids match what ships. Four snippets I first wrote from memory were corrected against the source.
  • Frontmatter matches the existing library: ai posts. Docs links use /ai/docs/....
  • No header image yet. 37 of 43 posts have one at /blog-assets/<slug>/header.png. Happy to add one before merge.
  • The release it announces is not published yet: it goes out with the batch in chore: bump unreleased docs dates, squash pending changesets ai#1051.

Summary by CodeRabbit

  • Documentation
    • Added the “Surviving the refresh” release article.
    • Documented server-side chat and generation persistence, resumable SSE/NDJSON streams, durable sandboxed agent runs, server-side memory, rebuilt interrupts, and multi-instance locks.
    • Included setup examples for routes, clients, storage adapters, stream resumption, media restoration, sandbox cleanup, memory, interrupts, and locking.
    • Documented removal of Zod from the core dependency graph.

Launch post for the TanStack AI durability release: chat persistence,
resumable streams, generation persistence and durable sandboxed agent runs,
plus server-side memory, the rebuilt interrupt lifecycle, multi-instance
locks and the BytePlus adapter.

Every snippet is taken from the new docs pages, so the API names match what
ships.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The new “Surviving the refresh” article documents TanStack AI persistence and durability features. It covers chat recovery, resumable streams, media generation, sandboxed agents, server-side memory, interrupts, locks, zod removal, and related documentation links.

Surviving the refresh article

Layer / File(s) Summary
Chat and stream durability
src/blog/surviving-the-refresh.md
Documents durable chat routes, transcript storage, delivery logs, custom persistence contracts, conformance tests, and resumable SSE and NDJSON streams.
Generation and agent recovery
src/blog/surviving-the-refresh.md
Documents persistent media generation, artifact restoration, durable sandboxed-agent runs, takeover and replay, sweeping, reclamation, and cross-process resumption.
Server-side state and controls
src/blog/surviving-the-refresh.md
Documents server-side memory, interrupt resolution, structured errors, client approval controls, and multi-instance sandbox locks.
Release references
src/blog/surviving-the-refresh.md
Records zod removal from the core dependency graph and adds installation and persistence documentation links.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the added blog post about the TanStack AI durability release.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch blog/surviving-the-refresh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/blog/surviving-the-refresh.md`:
- Around line 107-120: Update the storage section text around defineMessageStore
to replace “typers” with “type helpers” or the correct exported type name, and
change “testkit” to “test kit” unless it is an official product name.
- Around line 164-170: Update the imports for the POST generation example to
include the exported generationParamsFromRequest helper from `@tanstack/ai`,
alongside generateImage and toServerSentEventsResponse, so the existing call
resolves correctly.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: db479a20-881a-4bf7-a646-f677fb53c982

📥 Commits

Reviewing files that changed from the base of the PR and between b91f028 and c67ec2a.

📒 Files selected for processing (1)
  • src/blog/surviving-the-refresh.md

Comment thread src/blog/surviving-the-refresh.md Outdated
Comment thread src/blog/surviving-the-refresh.md Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 4, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
tanstack-com ae6ebc7 Commit Preview URL

Branch Preview URL
Aug 05 2026, 05:15 AM

Humanize the prose, drop BytePlus from this post, note Start server
functions and persistence skills, and fix the generation example import.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/blog/surviving-the-refresh.md (2)

167-210: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Show the generation recovery route end-to-end.

The prose promises reconstructGeneration, but the example only shows POST with withGenerationPersistence and a client without the reconstruction path. Add the release-version HTTP/TanStack Start wiring, or explicitly limit this section to run metadata persistence rather than restored media bytes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/blog/surviving-the-refresh.md` around lines 167 - 210, Update the
image-generation example to show the complete release-version recovery flow:
retain the POST persistence setup, add the HTTP/TanStack Start GET route that
invokes reconstructGeneration for the same threadId, and wire the client’s
persistence option to that recovery endpoint. Ensure the example’s code matches
the documented restored-media behavior, or revise the prose to describe
metadata-only persistence if media reconstruction is not included.

Source: MCP tools


147-159: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not use memoryStream in production durability examples.

memoryStream keeps the durability log in this process, so host or replica restarts lose resumable state. Use durableStream in both the POST writer and the GET replay handler, and label memoryStream as development-only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/blog/surviving-the-refresh.md` around lines 147 - 159, Replace
memoryStream with durableStream in both the POST writer and GET replay handler
examples in src/blog/surviving-the-refresh.md: lines 147-159 and 212-216.
Configure durableStream with the request and DURABLE_STREAMS_URL in each
handler, and label memoryStream as development-only wherever it remains.

Source: MCP tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/blog/surviving-the-refresh.md`:
- Line 282: Update the component example around the interrupts.map(...)
expression so the mapped interrupt controls are included in the component’s
returned JSX. Wrap the expression in the existing return or add a return
statement, ensuring the controls render instead of remaining a standalone unused
expression.

---

Outside diff comments:
In `@src/blog/surviving-the-refresh.md`:
- Around line 167-210: Update the image-generation example to show the complete
release-version recovery flow: retain the POST persistence setup, add the
HTTP/TanStack Start GET route that invokes reconstructGeneration for the same
threadId, and wire the client’s persistence option to that recovery endpoint.
Ensure the example’s code matches the documented restored-media behavior, or
revise the prose to describe metadata-only persistence if media reconstruction
is not included.
- Around line 147-159: Replace memoryStream with durableStream in both the POST
writer and GET replay handler examples in src/blog/surviving-the-refresh.md:
lines 147-159 and 212-216. Configure durableStream with the request and
DURABLE_STREAMS_URL in each handler, and label memoryStream as development-only
wherever it remains.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 94104871-d386-46d5-b8dd-fc10718072aa

📥 Commits

Reviewing files that changed from the base of the PR and between c67ec2a and ae6ebc7.

📒 Files selected for processing (1)
  • src/blog/surviving-the-refresh.md

})
```

**Interrupts, rebuilt.** Tool approvals, generic interrupts, and client tools now follow the AG-UI interrupt lifecycle: typed bound resolvers, atomic batches, and structured errors. No database required — the continuation carries the message history.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Return the interrupt controls from the component.

The example shows the interrupts.map(...) expression as a standalone block after useChat. In a component body, it does not render. Wrap it in return (...) or place it inside the component’s existing JSX return.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/blog/surviving-the-refresh.md` at line 282, Update the component example
around the interrupts.map(...) expression so the mapped interrupt controls are
included in the component’s returned JSX. Wrap the expression in the existing
return or add a return statement, ensuring the controls render instead of
remaining a standalone unused expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants