chore: non-interrupt residue archived from #970 slim#973
Conversation
…M-event catalog
- Add optional in-band `cursor` to StreamChunk + `cursor` input on chat().
- Add a *replayAndResume() seam: when a cursor is supplied and a ResumeSource
capability is provided, replay the persisted event tail; if the run is still
running and the adapter supports re-attach, continue live. No-op without a
resume source (a non-persisted run is unchanged).
- Move the generic LockStore + LocksCapability ('locks') into core so it is a
single shared token across the sandbox and persistence layers.
- Add ResumeSource capability/contract and a typed catalog of well-known CUSTOM
event names (file.changed, process.*, approval.*, artifact.*, sandbox.*).
…andbox bridge - @tanstack/ai-persistence: store contracts, withPersistence middleware, memoryPersistence, cursor utilities, approval controller, resume-source adapter, history projection. Fully optional; works with and without sandbox. - @tanstack/ai-persistence-sql: one SQL store impl behind a minimal SqlDriver (sqlite|postgres dialect) + versioned migrations + DDL. - Backends: -sqlite (node:sqlite/better-sqlite3), -postgres (pg), -cloudflare (D1, compile-verified), -drizzle and -prisma (BYO). - @tanstack/ai-sandbox-persistence: durable SQL-backed SandboxStore + withPersistenceBridge wiring durable store/locks into withSandbox (agent mode).
- Track the latest in-band cursor per active run; expose getResumeState(), resume(), and maybeAutoResume() with an `autoResume` opt-out (default on). - Pass `cursor` through the connection adapter's RunAgentInput payload so the server can replay a run. streamResponse reuses the original runId on resume.
…ip config - New docs/persistence/overview.md (+ nav entry, addedAt) with server + client + agent-mode usage. - New ai-core/persistence agent skill. - Changeset covering the feature; knip ignore for the optional pg peer dep.
# Conflicts: # docs/media/transcription.md
# Conflicts: # examples/ts-react-chat/src/routes/generations.image.tsx # examples/ts-react-chat/src/routes/generations.video.tsx # testing/e2e/src/routes/$provider/index.tsx
…ma-emit CLI
Let projects own the TanStack AI Drizzle schema instead of the bundled copy:
- drizzlePersistence(db, { schema }) — stores now operate over injected table
objects, so renamed tables/columns (incl. drizzle `casing` conventions) and
extra app-owned columns (e.g. a userId on messages) work through the same
code paths. TanstackAiSchema pins only column data shapes; construction
validates tables/columns and throws DrizzleSchemaError with per-item detail.
- tanstack-ai-drizzle-schema CLI (--out/--stdout/--force) emits the schema
module into the project so the user's own drizzle-kit journal owns the DDL
(verified: drizzle-kit generate on the emitted file reproduces the bundled
migration exactly).
- Conformance suite runs against a fully renamed variant schema with an
app-owned ownership column; sync test pins the emitted asset structurally
identical to the bundled schema; type-level tests cover assignability.
- Docs: drizzle.md "Own the schema", migrations.md cross-ref, persistence
SKILL.md; package contract tests updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A6Arc9bWdLq1aRRnDRCLMt
…ui-interrupts-implementation # Conflicts: # packages/ai-persistence-drizzle/src/index.ts # packages/ai-persistence-drizzle/src/stores.ts # packages/ai-persistence-drizzle/tests/api-types.test-d.ts
Let applications rename the TanStack AI models in their copy of the fragment
(e.g. to avoid collisions with an existing Message/Run model) and map each
store to the renamed client delegate:
prismaPersistence(prisma, { models: { messages: 'chatMessage' } })
- New model-contract.ts: minimal structural delegate interfaces the stores
operate over (field surface pinned, delegate names free), PrismaModelMap,
and construction-time validation throwing PrismaModelError with per-store
detail. Stores refactored to consume delegates instead of PrismaClient.
- Bytes inputs pinned to Uint8Array<ArrayBuffer> (what Prisma generates);
blob.upsert result typed unknown with a re-read, matching the Drizzle
sibling, so user-generated clients stay assignable.
- Conformance suite runs through a fully renamed client; type tests assert
the generated delegates satisfy the structural contract; validation and
partial-map tests added.
- Docs: prisma.md "Rename the models" section; persistence SKILL.md note.
Prisma counterpart of the Drizzle schema-injection change (659464a): DB
names were already free via @map/@@Map and generation already ships via the
models CLI — client-level model names were the remaining hardcoded surface.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A6Arc9bWdLq1aRRnDRCLMt
…ui-interrupts-implementation # Conflicts: # packages/ai-persistence-prisma/src/stores.ts
Interrupts is a large feature; move it out of "Chat & Streaming" into a dedicated top-level Interrupts section and rewrite the content to be succinct and example-first with real, rendered React components. - New docs/interrupts/ pages: overview, tool-approval, multiple, generic, client-tool-execution, persistence, migration - Remove the monolithic docs/chat/interrupts.md and docs/migration/interrupts.md - Add the Interrupts nav section and drop the old entries in docs/config.json - Repoint inbound cross-links (chat, tools, persistence, architecture, and the generated toolDefinition reference) to the new paths Examples now show handling a single interrupt, mapping/batching multiple interrupts, and validating a generic responseSchema in the UI directly, instead of abstract helper functions.
The Overview "three kinds" table read as if a tool is either tool-approval or client-tool-execution. Add a note plus a tool→interrupt matrix showing the axes are independent: a client tool with needsApproval produces a tool-approval interrupt first, then a client-tool-execution interrupt once approved.
Replace the `interrupts.find(...)` + whole-component `return null` pattern in the tool-approval, generic, and client-tool-execution examples with a `interrupts.map()` that narrows on `kind` and renders per-kind UI. This handles multiple pending items of a kind and matches the mixed-queue pattern on the Multiple Interrupts page. Generic items get a per-item child component for their editor state.
Client tools return results through their `.client()` implementation (which runs automatically) or `addToolResult` — not by resolving a client-tool-execution interrupt by hand. That manual path was redundant with the tool-result path and misrepresented how client tools work. - Delete docs/interrupts/client-tool-execution.md and its nav entry - Overview: list only tool-approval and generic as kinds you resolve; note client tools run automatically and approval is a separate axis - client-tools.md: drop the manual `execution.resolveInterrupt(...)` snippet; keep approval resolution + addToolResult as the manual escape hatch
…rupt API Client tools resolve through their `.client()` implementation (auto-executed) or `addToolResult` — never as a bound interrupt. The `client-tool-execution` kind was redundant public surface: `resolveInterrupt(output)` and `addToolResult` were two doors to the same resolution, and it invited users to hand-wire client-tool execution that already happens automatically. The internal architecture is unchanged — the server still emits the client-tool-execution interrupt as the browser handoff, the client processor still auto-executes `.client()` tools off it, persistence still stores its binding. Only the public exposure is removed. - Remove `ClientToolExecutionInterrupt` from the `ChatInterrupt` union + exports - Filter client-tool-execution items out of the published `interrupts` / `pendingInterrupts` snapshot while keeping them in the internal batch so `resolveClientToolOutput` (addToolResult) and auto-execution still work - Exclude client-tool items from the `resolveInterrupts(cb)` completeness check and the boolean-bulk path (they resolve out-of-band; `maybeSubmit` still gates real submission on them) - Update ai-client + framework type tests and the e2e to assert the client tool auto-executes and stays out of the public interrupts array
…om persistence stack Fuse the AG-UI interrupt foundation (#785 substrate) with the finalized interrupt implementation (#935) onto main, minus the server persistence story. Interrupts run ephemerally by resuming from full client message history in a fresh child run. Excludes (deferred to a follow-up persistence PR): the ai-persistence* store packages, durable/recovery examples and docs, and server recovery handlers. Client-side recovery hooks remain as dormant optional API.
…only) - Reconcile getChunkRunId precedence for interrupt continuation correlation - Add resume + loadInterruptState to client connection-adapter surface - Fix ai-react interrupt-state handler TDZ guard - Strip recovery/persistence from e2e fixture + example lab - Fix doc links + kiira snippets for removed persistence surface - Defer recovery-specific client tests (it.skip) to the persistence PR
- forward parentRunId from the e2e chat route to chat() so ephemeral interrupt resume correlates the child run (fixes tool-approval resume) - resolve the approval tool-call's owning message from history when the live active-message maps were reset by a MESSAGES_SNAPSHOT, so the deprecated part.state approval UI still updates - clear the deprecated approval part.state on approve/deny before the compat resolve path runs - remove interrupts-v2 (durable) e2e routes/fixtures/specs and the persistence-era recovery tests/type assertions; these return with the stacked persistence PR - restore the Provider cast on the $provider route dropped during extraction
…rupts
The AG-UI interrupt lifecycle was extracted from a larger persistence stack
and shipped ephemeral-only, but carried persistence-shaped code that is never
exercised without a durable layer (which is not part of this package). Remove it.
Server (@tanstack/ai):
- Drop the never-provided InterruptPersistenceGateway capability
(getInterruptPersistence/provideInterruptPersistence) and its input types
(OpenInterruptBatchInput, CommitInterruptResolutionsInput). The two call
sites now always take the ephemeral branch.
- Remove InterruptCommitResult, the InterruptResumeValidationError.recovery
field, the recovery type guard, and the tanstack:interruptRecovery emission.
Client (@tanstack/ai-client):
- Remove the recovery state machine: getRecoveryState, getPersistedDrafts,
reportRecoveryError, restorePersistedDrafts, recoverInterrupts,
{start,recover}PersistedInterrupts, joinContinuationRun, the persisted-state
branch of applyResumeSnapshot, and the conflict/replay branches of
submitInterruptBatch (now a plain ephemeral submit).
- Delete interrupt-recovery-parse.ts; drop PersistedInterruptDraft and the
ChatContinuationLoader option/type.
Kept as a dormant extension seam for a future persistence layer: the optional
ConnectionAdapter.loadInterruptState hook and its InterruptRecoveryStateV1 /
InterruptRecoveryQuery types.
Docs: trim the dangling withChatPersistence step and the persistence-only
migration checklist / recovery sections to match the ephemeral-only surface.
Runtime behavior is unchanged (persistence was never provided). Verified:
typecheck + lint clean across ai/ai-client/6 framework packages, full unit
suites green, docs links pass, and the interrupt lab round-trip re-verified
against the rebuilt dist.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
🚀 Changeset Version Preview9 package(s) bumped directly, 38 bumped as dependents. 🟥 Major bumps
🟨 Minor bumps
🟩 Patch bumps
|
|
View your CI Pipeline Execution ↗ for commit 912d006
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
Summary
Archive of the pre-slim tip of #970 (
feat/interrupts-overhaulbefore Option A cleanup).#970 was force-pushed to a slim surface (~132 files) that keeps the AG-UI interrupt lifecycle. This branch freezes the full pre-slim tree (267 files) so nothing was lost:
useGeneration*/ media generation wiring churnNot intended to merge as-is. Use it to cherry-pick or re-land non-interrupt work later (e.g. client generation resume, storage helpers that are not required for ephemeral interrupts).
Related: #970
Test plan
feat/interrupts-overhauland extract only the desired paths