diff --git a/.changeset/ag-ui-interrupts.md b/.changeset/ag-ui-interrupts.md deleted file mode 100644 index a3a23ff85..000000000 --- a/.changeset/ag-ui-interrupts.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-client': minor -'@tanstack/ai-react': minor -'@tanstack/ai-preact': minor -'@tanstack/ai-solid': minor -'@tanstack/ai-vue': minor -'@tanstack/ai-svelte': minor -'@tanstack/ai-angular': minor ---- - -Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and -client-tool execution, with typed bound resolvers, atomic batches, and -structured errors. Interrupts run ephemerally by resuming from the full client -message history in a fresh child run — no persistence required. - -This changes native approval and client-tool streams from legacy custom events -to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated -`pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and -legacy event readers remain as limited compatibility surfaces for migration; -`addToolResult` remains supported. diff --git a/.changeset/client-browser-refresh-durability.md b/.changeset/client-browser-refresh-durability.md deleted file mode 100644 index 32b6b665c..000000000 --- a/.changeset/client-browser-refresh-durability.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -'@tanstack/ai-client': minor -'@tanstack/ai-react': minor -'@tanstack/ai-solid': minor -'@tanstack/ai-vue': minor -'@tanstack/ai-svelte': minor -'@tanstack/ai-angular': minor -'@tanstack/ai-preact': minor ---- - -Add browser-refresh durability to the `persistence` option. - -The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. - -**If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. - -The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. - -New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. diff --git a/.changeset/define-lock.md b/.changeset/define-lock.md deleted file mode 100644 index 547df8e15..000000000 --- a/.changeset/define-lock.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -'@tanstack/ai': minor ---- - -Add `defineLock` to `@tanstack/ai/locks`: an identity typer for a `LockStore` -implementation, matching the `define*Store` helpers in `@tanstack/ai-persistence`. -Pass a `withLock` object and get autocomplete and contract checking inline, with -no `: LockStore` annotation, then hand it to `withLocks`. - -```ts -import { defineLock, withLocks } from '@tanstack/ai/locks' - -const locks = defineLock({ - async withLock(key, fn) { - const { release, signal } = await acquire(key) - try { - return await fn(signal) - } finally { - release() - } - }, -}) - -const middleware = [withLocks(locks)] -``` diff --git a/.changeset/define-store-helpers.md b/.changeset/define-store-helpers.md deleted file mode 100644 index 5c41da435..000000000 --- a/.changeset/define-store-helpers.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -'@tanstack/ai-persistence': minor ---- - -Add per-store typer helpers: `defineMessageStore`, `defineRunStore`, -`defineInterruptStore`, `defineMetadataStore`. - -Each takes a store implementation and returns it typed against the contract, so -you get autocomplete and checking on the object literal inline — no separate -`: MessageStore` return annotation. They compose into `defineAIPersistence`, -which already infers **exact presence**: a store you define is a defined, -non-optional, autocompleted key on `persistence.stores`, and accessing a store -you did not define is a compile error. - -```ts -import { - defineAIPersistence, - defineMessageStore, - defineRunStore, -} from '@tanstack/ai-persistence' - -const persistence = defineAIPersistence({ - stores: { - messages: defineMessageStore({ loadThread, saveThread }), - runs: defineRunStore({ createOrResume, update, get }), - }, -}) - -persistence.stores.runs // RunStore (defined) -persistence.stores.interrupts // compile error — not provided -``` diff --git a/.changeset/devtools-memory-inspector.md b/.changeset/devtools-memory-inspector.md deleted file mode 100644 index 5fd1e33aa..000000000 --- a/.changeset/devtools-memory-inspector.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -'@tanstack/ai-memory': minor -'@tanstack/ai-event-client': minor -'@tanstack/ai-client': minor -'@tanstack/ai-devtools-core': minor ---- - -**Surface server-side memory state in the TanStack AI DevTools.** - -The DevTools panel now has a **Memory** tab for any chat wired with -`memoryMiddleware`. It shows, per scope (session), an operations timeline (each -turn's recall — query, fragment count, injected system-prompt size, whether -memory tools were exposed, duration) and the current stored records/facts when -the adapter implements the optional `inspect`/`listFacts` methods. - -Because memory runs on the server (whose event bus never reaches the browser), -the middleware transports its state to the panel over the chat stream as a -`memory:state` `CUSTOM` event, which `@tanstack/ai-client`'s devtools bridge -re-emits as browser `memory:*` events — the same pattern generation results use. -The snapshot reflects memory as of the start of each turn; opening the panel -mid-conversation replays the latest state so the tab isn't empty. - -- `@tanstack/ai-memory` — `memoryMiddleware` injects a `memory:state` `CUSTOM` - chunk carrying recall metrics + an `inspect`/`listFacts` snapshot; exports - `MEMORY_STATE_EVENT` and `MemoryStateEventValue`. -- `@tanstack/ai-event-client` — adds the `memory:snapshot` devtools event. -- `@tanstack/ai-client` — the chat devtools bridge re-emits `memory:*` from the - transported chunk and replays the last snapshot on `devtools:request-state`. -- `@tanstack/ai-devtools-core` — new Memory tab + per-scope memory store slice. diff --git a/.changeset/fast-fail-rejoin.md b/.changeset/fast-fail-rejoin.md deleted file mode 100644 index a01f42a8f..000000000 --- a/.changeset/fast-fail-rejoin.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-client': patch ---- - -Make a reload rejoin fast, robust, and repeatable. - -- **`memoryStream` first-chunk deadline now defaults to 100ms** (was 30s). The - common from-start join is a reload rejoining a run whose producer ran in a - prior request: an in-flight run's log already holds chunks (it streams - immediately, the deadline never applies), and an empty log means the run is - gone — so failing fast lets the client re-enable input near-instantly instead - of holding a dead connection open. Raise `firstChunkDeadlineMs` for a backend - whose producer can legitimately start well after a joiner attaches. -- **`ChatClient` reload rejoin hardened:** it bounds the wait for the first - chunk and clears a dead resume pointer (so a stale pointer can't pin the UI in - a loading state and can't be retried on the next load); it drops the hydrated - in-flight partial only when real content arrives (never on `RUN_STARTED` - alone), so a rejoin that connects but delivers nothing can't leave an empty - assistant bubble; and it no longer lets a replayed `RUN_STARTED` (which - carries the provider run id) overwrite the persisted resume pointer with an id - the durability log isn't keyed by — so a SECOND consecutive reload still - re-attaches and continues. diff --git a/.changeset/fresh-client-tail.md b/.changeset/fresh-client-tail.md deleted file mode 100644 index d7e1c032b..000000000 --- a/.changeset/fresh-client-tail.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -'@tanstack/ai-persistence': minor -'@tanstack/ai-client': minor ---- - -Server-authoritative reconnect is now automatic and keyed on the thread, not the run. - -A chat's durable identity is its **thread**; run ids are ephemeral (a single turn -can span several runs via interrupts or tool continuations), so basing reconnect -on a client-cached run id goes stale the moment a turn rolls to a new run. This -moves the whole reconnect story onto the stable thread id, resolved by the server. - -- **`RunStore.findActiveRun(threadId)`** — new optional, feature-detected store - method returning the most recent `'running'` run for a thread. Implemented by - the in-memory reference backend and covered by the conformance testkit, so any - adapter that provides it is held to the same invariants (most-recent-running - wins, thread-scoped, null when idle). -- **`reconstructChat` now returns `{ messages, activeRun, interrupts }`** (was a - bare message array): the stored transcript as UI messages, a cursor to an - in-flight run if one exists, and any pending human-in-the-loop interrupts (tool - approvals / waits) plus the run they paused. It reads the active run before the - transcript so observing "no active run" guarantees the transcript is final - (closing a finish-window race). -- **`@tanstack/ai-client` hydrates itself on mount.** In server-authoritative - mode (`persistence: true`) the client caches no transcript and no run - pointer: on mount `useChat`/`ChatClient` calls the connection's new - `hydrate(threadId)` (a JSON GET against the same endpoint), paints the returned - transcript, and — if a run is in flight — tails it via the existing `joinRun` - durability replay. A reload and the same thread opened on another device are the - identical, server-resolved path. No loader, no `initialMessages`, no - `initialResumeSnapshot`, no app-side fetching required. -- **Interrupts reconstruct from the server too.** A paused approval (a tool with - `needsApproval`) is restored from `reconstructChat`'s `interrupts` exactly as a - persisted resume snapshot would be, so a reload — or another device — re-prompts - the same approve/reject decision and resumes the run it paused. Previously the - pending interrupt was only recoverable from client storage, so a fresh client - showed the paused tool call with no way to resolve it. - -Apps keep the single GET endpoint they already have (durability replay when a -resume cursor is present, else `reconstructChat`); everything else is handled by -the hook. diff --git a/.changeset/interrupt-binding-ownership.md b/.changeset/interrupt-binding-ownership.md deleted file mode 100644 index b681fe9dd..000000000 --- a/.changeset/interrupt-binding-ownership.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -'@tanstack/ai-client': minor -'@tanstack/ai': minor ---- - -Make interrupt ownership explicit rather than assumed. - -An AG-UI `Interrupt` is a shared envelope — a workflow engine's durable -approval or another agent framework's pause can arrive on the same stream. What -makes a pause resumable through `chat()` is the binding this package attaches -under `tanstack:interruptBinding`. - -- Interrupts that carry no binding this client understands now surface as - `kind: 'unbound'` with `canResolve: false`, instead of being given a - synthesized binding and rendered as resolvable generic interrupts. Resolving - those produced an answer submitted against a run with nothing pending, which - failed as `unknown-interrupt` only after the user had filled in the form. - Unbound items never block submission of the interrupts that are yours. -- The binding carries a wire version (`INTERRUPT_BINDING_VERSION`). Readers - reject a version they don't recognise rather than duck-typing its fields. A - binding written before the field existed is still read. -- `INTERRUPT_BINDING_METADATA_KEY`, `withInterruptBinding()` and - `readInterruptBinding()` are exported, so anything producing an interrupt this - package must later resume attaches the binding through a supported API - instead of copying the metadata key. -- Interrupt classification is driven by the binding alone. `Interrupt.reason` is - free-form AG-UI text another producer can also use, so it is now a display - hint only and never decides ownership. -- The interrupt protocol surface is enumerated instead of `export *`. The - unimplemented durable-recovery contract (`InterruptRecoveryStateV1`, - `InterruptRecoveryQuery`, the never-called `loadInterruptState` adapter hook, - and the `persistence-required` / `atomic-commit-unsupported` / - `recovery-unavailable` error codes) is removed rather than published. diff --git a/.changeset/interrupts-validation-ownership.md b/.changeset/interrupts-validation-ownership.md deleted file mode 100644 index 122b0687b..000000000 --- a/.changeset/interrupts-validation-ownership.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-client': minor ---- - -Interrupts: the application owns wire-schema validation, and the hashing -dependency is gone. - -The library no longer transforms a generic interrupt's wire JSON Schema into a -validator or validates the resolved value against it, on either the client or -the server. Whatever you pass to `resolveInterrupt` (client) or send in the -`resume` batch (server) flows through as-is. Validate it yourself if you need to -trust it, e.g. with `z.fromJSONSchema(interrupt.responseSchema).safeParse(value)` -on the client and your own check on the server. Validation of a tool's -code-authored Standard Schema (`approvalSchema` / `inputSchema`) is unchanged. - -This drops the `ajv` and `ajv-formats` dependencies. Interrupt binding hashes and -resolution fingerprints now use a small bundled SHA-256 instead of -`@noble/hashes`, so that dependency is gone too. The wire hash shape -(`sha256:`) is unchanged. diff --git a/.changeset/locks-to-core.md b/.changeset/locks-to-core.md deleted file mode 100644 index b1b32b497..000000000 --- a/.changeset/locks-to-core.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-persistence': minor -'@tanstack/ai-sandbox': minor ---- - -Move multi-instance **locks** to `@tanstack/ai` under a dedicated `@tanstack/ai/locks` subpath, and nest persistence agent skills like `ai-core`. - -- **`LockStore` / `InMemoryLockStore` / `LocksCapability` / `getLocks` / `provideLocks` / `withLocks`** live in `@tanstack/ai/locks` (not the main `@tanstack/ai` barrel, and not `@tanstack/ai-persistence`). -- `@tanstack/ai-sandbox` consumes the core `LocksCapability` token (no local lock re-export). -- The locks agent skill moves with the code: `ai-core/locks` in `@tanstack/ai`, not `ai-persistence/locks`. -- Agent skills under `@tanstack/ai-persistence` nest as `skills/ai-persistence/{stores,server,build-*-adapter}/`. -- Docs: locks guide under advanced middleware. diff --git a/.changeset/memory-middleware.md b/.changeset/memory-middleware.md deleted file mode 100644 index 6e9cd9f31..000000000 --- a/.changeset/memory-middleware.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-event-client': minor -'@tanstack/ai-memory': minor ---- - -**Add server-side memory via a `recall`/`save` adapter contract in `@tanstack/ai-memory`.** - -Memory is now a single, provider-agnostic contract with two verbs — `recall` and -`save` — which is the shape every memory backend (in-process, Redis, and hosted -vendors) naturally exposes. `memoryMiddleware` recalls relevant memory into the -system prompt (and optionally injects vendor tools) before the model runs, then -defers `save` of the finished turn via `ctx.defer` so streaming is never blocked. -Extraction, ranking, and rendering live inside each adapter — the middleware is thin. - -`@tanstack/ai-memory` (new package) — everything ships here: - -- Root: `memoryMiddleware`, the `MemoryAdapter` contract - (`recall` / `save` / optional `inspect` / `listFacts`), and the `MemoryScope` / - `MemoryTurn` / `RecallResult` / `SaveReceipt` types. -- `@tanstack/ai-memory/in-memory` → `inMemory()` — zero-dependency adapter for dev, - tests, and single-process demos. Pass an `embedder` for semantic scoring and/or an - `extract` function to persist derived facts. -- `@tanstack/ai-memory/redis` → `redis({ redis, prefix? })` — production adapter for - plain Redis. `ioredis` wires in directly; `redis` (node-redis v4+) via the - `fromNodeRedis(client)` wrapper. Both are optional peer dependencies. -- `@tanstack/ai-memory/hindsight` → `hindsight()`, `@tanstack/ai-memory/mem0` → - `mem0()`, `@tanstack/ai-memory/honcho` → `honcho()` — hosted-vendor adapters. Their - SDKs (`@vectorize-io/hindsight-client`, `@honcho-ai/sdk`) are optional peers loaded - lazily; mem0 talks to its server over plain HTTP (no SDK). Vendors can expose LLM - tools through `recall` (e.g. hindsight's retain/recall/reflect). -- A shared `recall`/`save` contract-test suite (`@tanstack/ai-memory/tests/contract`) - that any adapter — including third-party ones — can run. - -`@tanstack/ai`: - -- **Removes the (unreleased) `@tanstack/ai/memory` subpath.** The middleware, - contract, and helpers all moved to `@tanstack/ai-memory`. - -`@tanstack/ai-event-client`: - -- The five `memory:*` devtools events (`memory:retrieve:started` / `:completed`, - `memory:persist:started` / `:completed`, `memory:error`) now carry recall/save - payloads (adapter id, fragment/receipt counts, `phase: 'recall' | 'save'`). diff --git a/.changeset/memory-scope-threadid.md b/.changeset/memory-scope-threadid.md deleted file mode 100644 index ba5c66bfe..000000000 --- a/.changeset/memory-scope-threadid.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -'@tanstack/ai-memory': minor -'@tanstack/ai-event-client': minor -'@tanstack/ai-client': minor -'@tanstack/ai-devtools-core': minor ---- - -**Align `MemoryScope` to the shared `Scope` type (`threadId`).** - -`MemoryScope` is now an alias of `Scope` from `@tanstack/ai` so memory and -persistence share one isolation vocabulary. The conversation key is -`threadId` (required); optional dims are `userId`, `tenantId`, and reserved -`namespace`. There is no public `sessionId` on memory scope — hard cut while -`@tanstack/ai-memory` is still `0.x` / unreleased. - -- `@tanstack/ai-memory` — `export type MemoryScope = Scope`. Built-in adapters - (`inMemory`, `redis`) and middleware use `threadId`; `sameScope` also matches - `tenantId` when present on the query. Redis index keys are now - `{prefix}:index:{tenantId|_}:{userId|_}:{threadId}` (escaped). Hindsight banks - use `{user}__{threadId}`. Anyone who wrote Redis rows under the pre-rename - layout needs to reindex or wipe — keys are not dual-read. -- `@tanstack/ai-event-client` — `MemoryScopeLite` is - `{ threadId?, userId?, tenantId? }` (devtools telemetry; not an isolation - authority). -- `@tanstack/ai-client` / `@tanstack/ai-devtools-core` — memory event payloads - and the Memory panel registry follow the same `threadId` field names. diff --git a/.changeset/memorystream-agent-loop-delivery.md b/.changeset/memorystream-agent-loop-delivery.md deleted file mode 100644 index a7760ca82..000000000 --- a/.changeset/memorystream-agent-loop-delivery.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -'@tanstack/ai': patch ---- - -Fix `memoryStream` truncating a tool-calling (agent-loop) run at its first tool -call. - -An agent-loop run emits one `RUN_STARTED`/`RUN_FINISHED` pair per iteration -(`finishReason: "tool_calls"` for a turn that calls a tool, then `"stop"` for the -final answer). `memoryStream` treated the _first_ terminal chunk as the end of -the log — both marking the log complete on append and ending the reader on read — -so a run that called a tool was delivered only up to that first `RUN_FINISHED`: -the tool result and everything after (the model's actual answer) never reached -the client, leaving the tool call stuck "running" and the reply missing, on the -initial stream and on any reconnect/reload. - -Completion is now driven solely by the producer calling `close()` (which it does -on every exit — the documented `StreamDurability.close` contract, honored by -`toServerSentEventsResponse`/`resumeServerSentEventsResponse` and detached -producers). The reader tails across per-iteration terminals and ends when the -producer closes, so a tool-calling run is delivered in full — live, on rejoin, -and on a server-authoritative reload. diff --git a/.changeset/persistence-packages.md b/.changeset/persistence-packages.md deleted file mode 100644 index f6d3b9858..000000000 --- a/.changeset/persistence-packages.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@tanstack/ai-persistence': minor ---- - -Add server-side persistence for `chat()`: durable thread messages, run records, and interrupts. - -`withPersistence(persistence)` is a chat middleware that stores the conversation transcript, tracks each run's status, and records interrupt state so a paused run (tool approval, client-tool execution, generic interrupt) survives a server restart. - -`@tanstack/ai-persistence` ships the **contract**, not a backend for your database: - -- The four store interfaces — `MessageStore`, `RunStore`, `InterruptStore`, `MetadataStore` — with the invariants the middleware depends on (full-replace `saveThread`, idempotent `createOrResume`, insert-if-absent interrupt `create`, `requestedAt`-ascending listings). -- The `withPersistence` / `withGenerationPersistence` middleware, plus `composePersistence` to assemble stores that live in different systems. -- `memoryPersistence()`, an in-process reference backend for dev and tests. -- `LockStore` / `withLocks` / `InMemoryLockStore` for cross-worker coordination — deliberately **not** a state store, and not composable through `composePersistence`. -- A shared conformance testkit at `@tanstack/ai-persistence/testkit`. `runPersistenceConformance` exercises every method of every store you provide and fails loudly on a store that is missing without being declared in `skip`. - -Implement the stores against whatever database you already run and hand the result to `withPersistence` — the core never inspects your tables, so the schema stays yours. The [Build Your Own Adapter](https://tanstack.com/ai/latest/docs/persistence/build-your-own-adapter) guide walks through a complete `node:sqlite` backend end to end, and the package ships Agent Skills with worked Drizzle, Prisma, and Cloudflare D1 recipes (`npx @tanstack/intent@latest install`). `examples/ts-react-chat` runs on a self-contained `node:sqlite` adapter built this way and verified by the conformance testkit. - -Resume reconstruction is delegated to the chat engine: persistence records interrupts and gates new input on a thread with pending interrupts, while the engine rebuilds the resume tool state from the resume batch and the interrupt bindings carried in the (server-loaded) message history. - -`reconstructChat(persistence, request)` is a server helper that returns a thread's stored messages as a JSON `Response`, so a server-authoritative client can hydrate its transcript on load from a one-line `GET` handler. diff --git a/.changeset/rejoin-not-aborted-on-mount.md b/.changeset/rejoin-not-aborted-on-mount.md deleted file mode 100644 index 69da6fc16..000000000 --- a/.changeset/rejoin-not-aborted-on-mount.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@tanstack/ai-react': patch ---- - -Fix `useChat` aborting an in-flight delivery resume on mount. When `live` was -not enabled, the mount effect called `client.unsubscribe()` unconditionally, -which cancelled the shared in-flight stream — including the `joinRun` rejoin the -client had just started for a reloaded run. The result was a mid-stream reload -that caught up to the buffered point and then froze instead of continuing. -`useChat` now only tears down a subscription it actually started, so a reload -rejoins and streams the run through to completion. diff --git a/.changeset/resumable-streams.md b/.changeset/resumable-streams.md deleted file mode 100644 index 35b6ebfd7..000000000 --- a/.changeset/resumable-streams.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-client': minor -'@tanstack/ai-durable-stream': minor ---- - -Resumable streams: reconnect to an in-flight SSE **or NDJSON** response without -re-running the provider. - -`toServerSentEventsResponse` and `toHttpResponse` both accept a -`durability: { adapter, batch }` option. The adapter (`StreamDurability`) -records every chunk to an ordered log before delivery and tags each event with -an opaque, adapter-owned offset — an SSE `id:` line, or the `id` of an NDJSON -`{ id, chunk }` envelope (NDJSON has no native event-id). A reconnect -(`Last-Event-ID`) or an explicit `?offset` read replays strictly after that -offset from the log — the lazy provider stream is never iterated on resume. -Producers terminalize the log on cancellation and failure (`RUN_ERROR` append - -- `close()`) and on completion when the source stream emits its own terminal - event (`chat()` always does), so readers are never parked on a dead run. - -Two adapters ship: `memoryStream(request)` in `@tanstack/ai` (process-local, -for development and tests) and the new `@tanstack/ai-durable-stream` package, -a Durable Streams protocol adapter for production backends. - -For the `GET` handler that a reload or a second tab reconnects to, -`resumeServerSentEventsResponse({ adapter })` and `resumeHttpResponse({ adapter })` -replay a run straight from the durability log. They need no producer stream and -return a 400 when the request carries no resume offset. - -On the client, all four HTTP adapters are now resumable — `fetchServerSentEvents`, -`fetchHttpStream`, `xhrServerSentEvents`, and `xhrHttpStream`. Each tracks the -per-event offset, auto-reconnects with `Last-Event-ID`, de-duplicates the -replayed prefix, and exposes `joinRun(runId)` to attach to an in-flight or -finished run from the start (read-only GET with `offset=-1`). Untagged streams -behave exactly as before. A durable run that ends with no terminal event and no -forward progress now throws `DurableStreamIncompleteError` instead of hanging. - -Reconnection and durability are bounded so failures surface rather than hang or -loop: - -- `memoryStream` evicts completed logs after a grace window (unbounded growth - is gone); resuming an expired/unknown run throws, and a from-start join to a - run that never produces fails after `MemoryStreamOptions.firstChunkDeadlineMs`. -- all four HTTP adapters accept `reconnect: { maxAttempts, delayMs }` — a - throttle plus a ceiling on CONSECUTIVE no-progress reconnects (default 5; - forward progress resets it) that fails with the new `StreamReconnectLimitError` - instead of reconnecting endlessly, without penalizing a healthy long-lived run. -- `durableStream` accepts `reconnect: { maxReadFailures, delayMs }` to bound its - read-retry loop, and `server` is now optional when `fetch` is provided (e.g. a - Cloudflare service binding). -- `toServerSentEventsResponse` accepts `debug` to record durability terminal / - close failures server-side, where a replaying joiner cannot observe them. diff --git a/.changeset/seamless-reload-resume.md b/.changeset/seamless-reload-resume.md deleted file mode 100644 index 1573d5572..000000000 --- a/.changeset/seamless-reload-resume.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -'@tanstack/ai': minor -'@tanstack/ai-client': minor -'@tanstack/ai-persistence': minor ---- - -Make a mid-stream reload resume the same conversation cleanly. - -- `withPersistence` now persists the pending turn at the start of a run (so a - reload during generation still shows the user's message), stamps each - assistant turn with its stream `messageId`, and accepts - `withPersistence(persistence, { snapshotStreaming: true })` to also persist the - in-progress reply on a throttled interval (`snapshotIntervalMs`, default - `1000`) for partial-output durability. -- `ModelMessage` gains an optional `id`; `modelMessagesToUIMessages` preserves - it, so a hydrated message keeps the same identity as its live stream. -- On reload, the chat client rebuilds an in-flight assistant turn from the - delivery log (replaying from the start and applying the buffered backlog in one - batch) instead of reconciling against the persisted partial, so the reload - shows one clean bubble that catches up and continues rather than a frozen or - duplicated partial. diff --git a/.changeset/shared-scope.md b/.changeset/shared-scope.md deleted file mode 100644 index 7dee65362..000000000 --- a/.changeset/shared-scope.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -'@tanstack/ai': minor ---- - -**Add a shared `Scope` identity type to `@tanstack/ai`.** - -`Scope` is the single identity/isolation vocabulary for the subsystems that -persist or recall per-conversation data — `@tanstack/ai-persistence` and -`@tanstack/ai-memory`. Rather than each subsystem inventing its own notion of -"whose data is this?", both import one type: - -```ts -interface Scope { - threadId: string // required — the single conversation key (same as ctx.threadId) - userId?: string // durable end-user identity; required in practice for multi-user apps - tenantId?: string // multi-tenant boundary - namespace?: string // reserved logical partition; no subsystem keys on it yet -} -``` - -`threadId` is the one conversation key across the codebase (matching -`ChatMiddlewareContext.threadId`, with `conversationId` already deprecated in -favor of it) — subsystems must not introduce a second name (`sessionId`, …) for -the same concept. Every field is an isolation boundary and must be derived -server-side from trusted session state, never from client input. - -Introduced ahead of the persistence and memory packages so both share one settled -identity contract. `@tanstack/ai-memory` now aliases `MemoryScope` to `Scope` -(see the memory-scope-threadid changeset). diff --git a/.changeset/skill-discoverability.md b/.changeset/skill-discoverability.md deleted file mode 100644 index d0d884dba..000000000 --- a/.changeset/skill-discoverability.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -'@tanstack/ai': patch -'@tanstack/ai-mcp': patch -'@tanstack/ai-sandbox': patch -'@tanstack/ai-memory': patch ---- - -**Make every bundled Agent Skill discoverable by TanStack Intent.** - -Intent finds skills by scanning `node_modules` for packages that carry the -`tanstack-intent` keyword, and can only load what npm actually publishes. Three -packages shipped skills that failed one half of that contract: - -- `@tanstack/ai-mcp` wrote its skill into a `skills/` directory that was missing - from `files`, so it was never published at all. -- `@tanstack/ai-memory` and `@tanstack/ai-sandbox` published their skills but - lacked the keyword, so Intent never looked at them. - -All three now publish `skills` and carry the keyword, matching `@tanstack/ai`, -`@tanstack/ai-code-mode`, and `@tanstack/ai-persistence`. - -The client persistence skill also moves from `@tanstack/ai-persistence` to -`@tanstack/ai` as `ai-core/client-persistence`. It teaches -`localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` -and the `persistence` option on `useChat` — all of which live in the framework -packages, not in `@tanstack/ai-persistence`. An app doing browser-only -persistence never installs that package, so the guidance was unreachable for -exactly the people who needed it, and `ai-core` routed to a path that did not -exist on disk. Skills now follow the code that owns them. diff --git a/.changeset/sync-models.md b/.changeset/sync-models.md deleted file mode 100644 index 63eef764c..000000000 --- a/.changeset/sync-models.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@tanstack/ai-openrouter': patch ---- - -Update model metadata from OpenRouter API diff --git a/.changeset/usechat-threadid-identity.md b/.changeset/usechat-threadid-identity.md deleted file mode 100644 index 90f65cbda..000000000 --- a/.changeset/usechat-threadid-identity.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -'@tanstack/ai-react': minor -'@tanstack/ai-preact': minor -'@tanstack/ai-solid': minor -'@tanstack/ai-vue': minor -'@tanstack/ai-svelte': minor -'@tanstack/ai-client': minor ---- - -The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. - -`useChat` / `createChat` previously accepted a separate `id` that keyed client -persistence and named the devtools instance, defaulting to a framework -`useId()` when omitted. That meant persistence keyed on an ephemeral render-tree -id even when you passed a stable `threadId`, so a reload found nothing under the -thread's key. - -Now the `threadId` is the single identity: - -- The hooks drop the `id` option. Pass `threadId` to persist a conversation and - restore it on reload; omit it for an ephemeral chat. -- Persistence keys on `threadId` (unchanged in `ChatClient`, which already - resolved `id ?? threadId` — the hooks simply stop overriding it). -- `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` - instead of a generated id, so a thread shows up in devtools under its own id. -- Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates - the client so the new thread takes effect; previously the change was ignored. - -`ChatClient` still accepts `id` directly as a lower-level escape hatch for -keying storage separately from the wire thread; only the framework hooks drop it. - -Migration: replace `useChat({ id })` with `useChat({ threadId })`. diff --git a/examples/ag-ui/CHANGELOG.md b/examples/ag-ui/CHANGELOG.md index 41d1e2e02..be789f249 100644 --- a/examples/ag-ui/CHANGELOG.md +++ b/examples/ag-ui/CHANGELOG.md @@ -1,5 +1,14 @@ # ag-ui +## 0.0.3 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-client@0.23.0 + - @tanstack/ai-react@0.19.0 + - @tanstack/ai-react-ui@0.8.16 + ## 0.0.2 ### Patch Changes diff --git a/examples/ag-ui/package.json b/examples/ag-ui/package.json index 3475ab6f6..2eb3f2b18 100644 --- a/examples/ag-ui/package.json +++ b/examples/ag-ui/package.json @@ -2,7 +2,7 @@ "name": "ag-ui", "private": true, "type": "module", - "version": "0.0.2", + "version": "0.0.3", "scripts": { "detect-servers": "node scripts/detect-servers.mjs", "predev": "node scripts/detect-servers.mjs", diff --git a/packages/ai-acp/CHANGELOG.md b/packages/ai-acp/CHANGELOG.md index 663b6797f..e5a793a01 100644 --- a/packages/ai-acp/CHANGELOG.md +++ b/packages/ai-acp/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-acp +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-acp/package.json b/packages/ai-acp/package.json index 7f766d480..dcb042296 100644 --- a/packages/ai-acp/package.json +++ b/packages/ai-acp/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-acp", - "version": "0.2.3", + "version": "0.2.4", "description": "Shared Agent Client Protocol (ACP) transport, session, and AG-UI translation for TanStack AI harness adapters.", "author": "", "license": "MIT", diff --git a/packages/ai-angular/CHANGELOG.md b/packages/ai-angular/CHANGELOG.md index 32645461d..a78d9e114 100644 --- a/packages/ai-angular/CHANGELOG.md +++ b/packages/ai-angular/CHANGELOG.md @@ -1,5 +1,36 @@ # @tanstack/ai-angular +## 0.4.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.3.1 ### Patch Changes diff --git a/packages/ai-angular/package.json b/packages/ai-angular/package.json index 0cc622277..fb1d48aa9 100644 --- a/packages/ai-angular/package.json +++ b/packages/ai-angular/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-angular", - "version": "0.3.1", + "version": "0.4.0", "description": "Angular signals integration for TanStack AI streaming chat, structured outputs, and media generation.", "author": "", "license": "MIT", diff --git a/packages/ai-anthropic/CHANGELOG.md b/packages/ai-anthropic/CHANGELOG.md index f9f654410..e9ba643e7 100644 --- a/packages/ai-anthropic/CHANGELOG.md +++ b/packages/ai-anthropic/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-anthropic +## 0.16.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.16.3 ### Patch Changes diff --git a/packages/ai-anthropic/package.json b/packages/ai-anthropic/package.json index 4f6702cbb..ba67655c8 100644 --- a/packages/ai-anthropic/package.json +++ b/packages/ai-anthropic/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-anthropic", - "version": "0.16.3", + "version": "0.16.4", "description": "Anthropic Claude adapter for TanStack AI chat, tool calling, thinking, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-bedrock/CHANGELOG.md b/packages/ai-bedrock/CHANGELOG.md index d737219ad..7d1649c7c 100644 --- a/packages/ai-bedrock/CHANGELOG.md +++ b/packages/ai-bedrock/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-bedrock +## 0.1.5 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/openai-base@0.9.10 + ## 0.1.4 ### Patch Changes diff --git a/packages/ai-bedrock/package.json b/packages/ai-bedrock/package.json index 1981b2b4c..5ac0ae8fa 100644 --- a/packages/ai-bedrock/package.json +++ b/packages/ai-bedrock/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-bedrock", - "version": "0.1.4", + "version": "0.1.5", "type": "module", "description": "Amazon Bedrock adapter for TanStack AI — OpenAI-compatible chat, responses, tools, and reasoning.", "author": "", diff --git a/packages/ai-claude-code/CHANGELOG.md b/packages/ai-claude-code/CHANGELOG.md index 048c0b7d7..d6430f2b9 100644 --- a/packages/ai-claude-code/CHANGELOG.md +++ b/packages/ai-claude-code/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-claude-code +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-claude-code/package.json b/packages/ai-claude-code/package.json index 9d960189c..fa976a33f 100644 --- a/packages/ai-claude-code/package.json +++ b/packages/ai-claude-code/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-claude-code", - "version": "0.2.3", + "version": "0.2.4", "description": "Claude Code harness adapter for TanStack AI — run Claude Code as a chat backend with local tool execution and stateful sessions.", "author": "", "license": "MIT", diff --git a/packages/ai-client/CHANGELOG.md b/packages/ai-client/CHANGELOG.md index e0b56d32f..4b24dc73a 100644 --- a/packages/ai-client/CHANGELOG.md +++ b/packages/ai-client/CHANGELOG.md @@ -1,5 +1,259 @@ # @tanstack/ai-client +## 0.23.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Surface server-side memory state in the TanStack AI DevTools.** + + The DevTools panel now has a **Memory** tab for any chat wired with + `memoryMiddleware`. It shows, per scope (session), an operations timeline (each + turn's recall — query, fragment count, injected system-prompt size, whether + memory tools were exposed, duration) and the current stored records/facts when + the adapter implements the optional `inspect`/`listFacts` methods. + + Because memory runs on the server (whose event bus never reaches the browser), + the middleware transports its state to the panel over the chat stream as a + `memory:state` `CUSTOM` event, which `@tanstack/ai-client`'s devtools bridge + re-emits as browser `memory:*` events — the same pattern generation results use. + The snapshot reflects memory as of the start of each turn; opening the panel + mid-conversation replays the latest state so the tab isn't empty. + - `@tanstack/ai-memory` — `memoryMiddleware` injects a `memory:state` `CUSTOM` + chunk carrying recall metrics + an `inspect`/`listFacts` snapshot; exports + `MEMORY_STATE_EVENT` and `MemoryStateEventValue`. + - `@tanstack/ai-event-client` — adds the `memory:snapshot` devtools event. + - `@tanstack/ai-client` — the chat devtools bridge re-emits `memory:*` from the + transported chunk and replays the last snapshot on `devtools:request-state`. + - `@tanstack/ai-devtools-core` — new Memory tab + per-scope memory store slice. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Server-authoritative reconnect is now automatic and keyed on the thread, not the run. + + A chat's durable identity is its **thread**; run ids are ephemeral (a single turn + can span several runs via interrupts or tool continuations), so basing reconnect + on a client-cached run id goes stale the moment a turn rolls to a new run. This + moves the whole reconnect story onto the stable thread id, resolved by the server. + - **`RunStore.findActiveRun(threadId)`** — new optional, feature-detected store + method returning the most recent `'running'` run for a thread. Implemented by + the in-memory reference backend and covered by the conformance testkit, so any + adapter that provides it is held to the same invariants (most-recent-running + wins, thread-scoped, null when idle). + - **`reconstructChat` now returns `{ messages, activeRun, interrupts }`** (was a + bare message array): the stored transcript as UI messages, a cursor to an + in-flight run if one exists, and any pending human-in-the-loop interrupts (tool + approvals / waits) plus the run they paused. It reads the active run before the + transcript so observing "no active run" guarantees the transcript is final + (closing a finish-window race). + - **`@tanstack/ai-client` hydrates itself on mount.** In server-authoritative + mode (`persistence: true`) the client caches no transcript and no run + pointer: on mount `useChat`/`ChatClient` calls the connection's new + `hydrate(threadId)` (a JSON GET against the same endpoint), paints the returned + transcript, and — if a run is in flight — tails it via the existing `joinRun` + durability replay. A reload and the same thread opened on another device are the + identical, server-resolved path. No loader, no `initialMessages`, no + `initialResumeSnapshot`, no app-side fetching required. + - **Interrupts reconstruct from the server too.** A paused approval (a tool with + `needsApproval`) is restored from `reconstructChat`'s `interrupts` exactly as a + persisted resume snapshot would be, so a reload — or another device — re-prompts + the same approve/reject decision and resumes the run it paused. Previously the + pending interrupt was only recoverable from client storage, so a fresh client + showed the paused tool call with no way to resolve it. + + Apps keep the single GET endpoint they already have (durability replay when a + resume cursor is present, else `reconstructChat`); everything else is handled by + the hook. + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Make interrupt ownership explicit rather than assumed. + + An AG-UI `Interrupt` is a shared envelope — a workflow engine's durable + approval or another agent framework's pause can arrive on the same stream. What + makes a pause resumable through `chat()` is the binding this package attaches + under `tanstack:interruptBinding`. + - Interrupts that carry no binding this client understands now surface as + `kind: 'unbound'` with `canResolve: false`, instead of being given a + synthesized binding and rendered as resolvable generic interrupts. Resolving + those produced an answer submitted against a run with nothing pending, which + failed as `unknown-interrupt` only after the user had filled in the form. + Unbound items never block submission of the interrupts that are yours. + - The binding carries a wire version (`INTERRUPT_BINDING_VERSION`). Readers + reject a version they don't recognise rather than duck-typing its fields. A + binding written before the field existed is still read. + - `INTERRUPT_BINDING_METADATA_KEY`, `withInterruptBinding()` and + `readInterruptBinding()` are exported, so anything producing an interrupt this + package must later resume attaches the binding through a supported API + instead of copying the metadata key. + - Interrupt classification is driven by the binding alone. `Interrupt.reason` is + free-form AG-UI text another producer can also use, so it is now a display + hint only and never decides ownership. + - The interrupt protocol surface is enumerated instead of `export *`. The + unimplemented durable-recovery contract (`InterruptRecoveryStateV1`, + `InterruptRecoveryQuery`, the never-called `loadInterruptState` adapter hook, + and the `persistence-required` / `atomic-commit-unsupported` / + `recovery-unavailable` error codes) is removed rather than published. + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Interrupts: the application owns wire-schema validation, and the hashing + dependency is gone. + + The library no longer transforms a generic interrupt's wire JSON Schema into a + validator or validates the resolved value against it, on either the client or + the server. Whatever you pass to `resolveInterrupt` (client) or send in the + `resume` batch (server) flows through as-is. Validate it yourself if you need to + trust it, e.g. with `z.fromJSONSchema(interrupt.responseSchema).safeParse(value)` + on the client and your own check on the server. Validation of a tool's + code-authored Standard Schema (`approvalSchema` / `inputSchema`) is unchanged. + + This drops the `ajv` and `ajv-formats` dependencies. Interrupt binding hashes and + resolution fingerprints now use a small bundled SHA-256 instead of + `@noble/hashes`, so that dependency is gone too. The wire hash shape + (`sha256:`) is unchanged. + +- [#991](https://github.com/TanStack/ai/pull/991) [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371) - **Align `MemoryScope` to the shared `Scope` type (`threadId`).** + + `MemoryScope` is now an alias of `Scope` from `@tanstack/ai` so memory and + persistence share one isolation vocabulary. The conversation key is + `threadId` (required); optional dims are `userId`, `tenantId`, and reserved + `namespace`. There is no public `sessionId` on memory scope — hard cut while + `@tanstack/ai-memory` is still `0.x` / unreleased. + - `@tanstack/ai-memory` — `export type MemoryScope = Scope`. Built-in adapters + (`inMemory`, `redis`) and middleware use `threadId`; `sameScope` also matches + `tenantId` when present on the query. Redis index keys are now + `{prefix}:index:{tenantId|_}:{userId|_}:{threadId}` (escaped). Hindsight banks + use `{user}__{threadId}`. Anyone who wrote Redis rows under the pre-rename + layout needs to reindex or wipe — keys are not dual-read. + - `@tanstack/ai-event-client` — `MemoryScopeLite` is + `{ threadId?, userId?, tenantId? }` (devtools telemetry; not an isolation + authority). + - `@tanstack/ai-client` / `@tanstack/ai-devtools-core` — memory event payloads + and the Memory panel registry follow the same `threadId` field names. + +- [#955](https://github.com/TanStack/ai/pull/955) [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288) - Resumable streams: reconnect to an in-flight SSE **or NDJSON** response without + re-running the provider. + + `toServerSentEventsResponse` and `toHttpResponse` both accept a + `durability: { adapter, batch }` option. The adapter (`StreamDurability`) + records every chunk to an ordered log before delivery and tags each event with + an opaque, adapter-owned offset — an SSE `id:` line, or the `id` of an NDJSON + `{ id, chunk }` envelope (NDJSON has no native event-id). A reconnect + (`Last-Event-ID`) or an explicit `?offset` read replays strictly after that + offset from the log — the lazy provider stream is never iterated on resume. + Producers terminalize the log on cancellation and failure (`RUN_ERROR` append + - `close()`) and on completion when the source stream emits its own terminal + event (`chat()` always does), so readers are never parked on a dead run. + + Two adapters ship: `memoryStream(request)` in `@tanstack/ai` (process-local, + for development and tests) and the new `@tanstack/ai-durable-stream` package, + a Durable Streams protocol adapter for production backends. + + For the `GET` handler that a reload or a second tab reconnects to, + `resumeServerSentEventsResponse({ adapter })` and `resumeHttpResponse({ adapter })` + replay a run straight from the durability log. They need no producer stream and + return a 400 when the request carries no resume offset. + + On the client, all four HTTP adapters are now resumable — `fetchServerSentEvents`, + `fetchHttpStream`, `xhrServerSentEvents`, and `xhrHttpStream`. Each tracks the + per-event offset, auto-reconnects with `Last-Event-ID`, de-duplicates the + replayed prefix, and exposes `joinRun(runId)` to attach to an in-flight or + finished run from the start (read-only GET with `offset=-1`). Untagged streams + behave exactly as before. A durable run that ends with no terminal event and no + forward progress now throws `DurableStreamIncompleteError` instead of hanging. + + Reconnection and durability are bounded so failures surface rather than hang or + loop: + - `memoryStream` evicts completed logs after a grace window (unbounded growth + is gone); resuming an expired/unknown run throws, and a from-start join to a + run that never produces fails after `MemoryStreamOptions.firstChunkDeadlineMs`. + - all four HTTP adapters accept `reconnect: { maxAttempts, delayMs }` — a + throttle plus a ceiling on CONSECUTIVE no-progress reconnects (default 5; + forward progress resets it) that fails with the new `StreamReconnectLimitError` + instead of reconnecting endlessly, without penalizing a healthy long-lived run. + - `durableStream` accepts `reconnect: { maxReadFailures, delayMs }` to bound its + read-retry loop, and `server` is now optional when `fetch` is provided (e.g. a + Cloudflare service binding). + - `toServerSentEventsResponse` accepts `debug` to record durability terminal / + close failures server-side, where a replaying joiner cannot observe them. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Make a mid-stream reload resume the same conversation cleanly. + - `withPersistence` now persists the pending turn at the start of a run (so a + reload during generation still shows the user's message), stamps each + assistant turn with its stream `messageId`, and accepts + `withPersistence(persistence, { snapshotStreaming: true })` to also persist the + in-progress reply on a throttled interval (`snapshotIntervalMs`, default + `1000`) for partial-output durability. + - `ModelMessage` gains an optional `id`; `modelMessagesToUIMessages` preserves + it, so a hydrated message keeps the same identity as its live stream. + - On reload, the chat client rebuilds an in-flight assistant turn from the + delivery log (replaying from the start and applying the buffered backlog in one + batch) instead of reconciling against the persisted partial, so the reload + shows one clean bubble that catches up and continues rather than a frozen or + duplicated partial. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Make a reload rejoin fast, robust, and repeatable. + - **`memoryStream` first-chunk deadline now defaults to 100ms** (was 30s). The + common from-start join is a reload rejoining a run whose producer ran in a + prior request: an in-flight run's log already holds chunks (it streams + immediately, the deadline never applies), and an empty log means the run is + gone — so failing fast lets the client re-enable input near-instantly instead + of holding a dead connection open. Raise `firstChunkDeadlineMs` for a backend + whose producer can legitimately start well after a joiner attaches. + - **`ChatClient` reload rejoin hardened:** it bounds the wait for the first + chunk and clears a dead resume pointer (so a stale pointer can't pin the UI in + a loading state and can't be retried on the next load); it drops the hydrated + in-flight partial only when real content arrives (never on `RUN_STARTED` + alone), so a rejoin that connects but delivers nothing can't leave an empty + assistant bubble; and it no longer lets a replayed `RUN_STARTED` (which + carries the provider run id) overwrite the persisted resume pointer with an id + the durability log isn't keyed by — so a SECOND consecutive reload still + re-attaches and continues. + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-event-client@0.7.0 + ## 0.22.1 ### Patch Changes diff --git a/packages/ai-client/package.json b/packages/ai-client/package.json index 2423f6948..1d11e6141 100644 --- a/packages/ai-client/package.json +++ b/packages/ai-client/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-client", - "version": "0.22.1", + "version": "0.23.0", "description": "Framework-agnostic headless client for TanStack AI chat, realtime sessions, streaming transports, and media generations.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-code-mode-skills/CHANGELOG.md b/packages/ai-code-mode-skills/CHANGELOG.md index 94c22b6a9..bea8d0c67 100644 --- a/packages/ai-code-mode-skills/CHANGELOG.md +++ b/packages/ai-code-mode-skills/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-code-mode-skills +## 0.3.12 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-code-mode@0.3.9 + ## 0.3.11 ### Patch Changes diff --git a/packages/ai-code-mode-skills/package.json b/packages/ai-code-mode-skills/package.json index 48ffd8d90..64782b2f7 100644 --- a/packages/ai-code-mode-skills/package.json +++ b/packages/ai-code-mode-skills/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-code-mode-skills", - "version": "0.3.11", + "version": "0.3.12", "description": "Persistent runtime skill library for TanStack AI Code Mode agents and sandboxed tool orchestration.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-code-mode/CHANGELOG.md b/packages/ai-code-mode/CHANGELOG.md index 3ca87fd9d..57b48e40e 100644 --- a/packages/ai-code-mode/CHANGELOG.md +++ b/packages/ai-code-mode/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-code-mode +## 0.3.9 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.3.8 ### Patch Changes diff --git a/packages/ai-code-mode/package.json b/packages/ai-code-mode/package.json index 85a837d0b..90fb51501 100644 --- a/packages/ai-code-mode/package.json +++ b/packages/ai-code-mode/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-code-mode", - "version": "0.3.8", + "version": "0.3.9", "description": "Secure TypeScript Code Mode for TanStack AI agents to execute sandboxed tool orchestration programs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-codex/CHANGELOG.md b/packages/ai-codex/CHANGELOG.md index 6710f31d7..88605a10b 100644 --- a/packages/ai-codex/CHANGELOG.md +++ b/packages/ai-codex/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-codex +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-codex/package.json b/packages/ai-codex/package.json index 4bdfad50c..2ba51c787 100644 --- a/packages/ai-codex/package.json +++ b/packages/ai-codex/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-codex", - "version": "0.2.3", + "version": "0.2.4", "description": "Codex harness adapter for TanStack AI — run OpenAI Codex as a chat backend with local tool execution and stateful sessions.", "author": "", "license": "MIT", diff --git a/packages/ai-devtools/CHANGELOG.md b/packages/ai-devtools/CHANGELOG.md index 9a00d78c5..4e0ba48b3 100644 --- a/packages/ai-devtools/CHANGELOG.md +++ b/packages/ai-devtools/CHANGELOG.md @@ -1,5 +1,56 @@ # @tanstack/ai-devtools-core +## 0.5.0 + +### Minor Changes + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Surface server-side memory state in the TanStack AI DevTools.** + + The DevTools panel now has a **Memory** tab for any chat wired with + `memoryMiddleware`. It shows, per scope (session), an operations timeline (each + turn's recall — query, fragment count, injected system-prompt size, whether + memory tools were exposed, duration) and the current stored records/facts when + the adapter implements the optional `inspect`/`listFacts` methods. + + Because memory runs on the server (whose event bus never reaches the browser), + the middleware transports its state to the panel over the chat stream as a + `memory:state` `CUSTOM` event, which `@tanstack/ai-client`'s devtools bridge + re-emits as browser `memory:*` events — the same pattern generation results use. + The snapshot reflects memory as of the start of each turn; opening the panel + mid-conversation replays the latest state so the tab isn't empty. + - `@tanstack/ai-memory` — `memoryMiddleware` injects a `memory:state` `CUSTOM` + chunk carrying recall metrics + an `inspect`/`listFacts` snapshot; exports + `MEMORY_STATE_EVENT` and `MemoryStateEventValue`. + - `@tanstack/ai-event-client` — adds the `memory:snapshot` devtools event. + - `@tanstack/ai-client` — the chat devtools bridge re-emits `memory:*` from the + transported chunk and replays the last snapshot on `devtools:request-state`. + - `@tanstack/ai-devtools-core` — new Memory tab + per-scope memory store slice. + +- [#991](https://github.com/TanStack/ai/pull/991) [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371) - **Align `MemoryScope` to the shared `Scope` type (`threadId`).** + + `MemoryScope` is now an alias of `Scope` from `@tanstack/ai` so memory and + persistence share one isolation vocabulary. The conversation key is + `threadId` (required); optional dims are `userId`, `tenantId`, and reserved + `namespace`. There is no public `sessionId` on memory scope — hard cut while + `@tanstack/ai-memory` is still `0.x` / unreleased. + - `@tanstack/ai-memory` — `export type MemoryScope = Scope`. Built-in adapters + (`inMemory`, `redis`) and middleware use `threadId`; `sameScope` also matches + `tenantId` when present on the query. Redis index keys are now + `{prefix}:index:{tenantId|_}:{userId|_}:{threadId}` (escaped). Hindsight banks + use `{user}__{threadId}`. Anyone who wrote Redis rows under the pre-rename + layout needs to reindex or wipe — keys are not dual-read. + - `@tanstack/ai-event-client` — `MemoryScopeLite` is + `{ threadId?, userId?, tenantId? }` (devtools telemetry; not an isolation + authority). + - `@tanstack/ai-client` / `@tanstack/ai-devtools-core` — memory event payloads + and the Memory panel registry follow the same `threadId` field names. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-event-client@0.7.0 + ## 0.4.24 ### Patch Changes diff --git a/packages/ai-devtools/package.json b/packages/ai-devtools/package.json index e0a766d97..84b3a0452 100644 --- a/packages/ai-devtools/package.json +++ b/packages/ai-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-devtools-core", - "version": "0.4.24", + "version": "0.5.0", "description": "Core TanStack AI Devtools plugin for inspecting chat messages, tool calls, streams, and errors.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-durable-stream/CHANGELOG.md b/packages/ai-durable-stream/CHANGELOG.md new file mode 100644 index 000000000..3eae896e1 --- /dev/null +++ b/packages/ai-durable-stream/CHANGELOG.md @@ -0,0 +1,56 @@ +# @tanstack/ai-durable-stream + +## 0.1.0 + +### Minor Changes + +- [#955](https://github.com/TanStack/ai/pull/955) [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288) - Resumable streams: reconnect to an in-flight SSE **or NDJSON** response without + re-running the provider. + + `toServerSentEventsResponse` and `toHttpResponse` both accept a + `durability: { adapter, batch }` option. The adapter (`StreamDurability`) + records every chunk to an ordered log before delivery and tags each event with + an opaque, adapter-owned offset — an SSE `id:` line, or the `id` of an NDJSON + `{ id, chunk }` envelope (NDJSON has no native event-id). A reconnect + (`Last-Event-ID`) or an explicit `?offset` read replays strictly after that + offset from the log — the lazy provider stream is never iterated on resume. + Producers terminalize the log on cancellation and failure (`RUN_ERROR` append + - `close()`) and on completion when the source stream emits its own terminal + event (`chat()` always does), so readers are never parked on a dead run. + + Two adapters ship: `memoryStream(request)` in `@tanstack/ai` (process-local, + for development and tests) and the new `@tanstack/ai-durable-stream` package, + a Durable Streams protocol adapter for production backends. + + For the `GET` handler that a reload or a second tab reconnects to, + `resumeServerSentEventsResponse({ adapter })` and `resumeHttpResponse({ adapter })` + replay a run straight from the durability log. They need no producer stream and + return a 400 when the request carries no resume offset. + + On the client, all four HTTP adapters are now resumable — `fetchServerSentEvents`, + `fetchHttpStream`, `xhrServerSentEvents`, and `xhrHttpStream`. Each tracks the + per-event offset, auto-reconnects with `Last-Event-ID`, de-duplicates the + replayed prefix, and exposes `joinRun(runId)` to attach to an in-flight or + finished run from the start (read-only GET with `offset=-1`). Untagged streams + behave exactly as before. A durable run that ends with no terminal event and no + forward progress now throws `DurableStreamIncompleteError` instead of hanging. + + Reconnection and durability are bounded so failures surface rather than hang or + loop: + - `memoryStream` evicts completed logs after a grace window (unbounded growth + is gone); resuming an expired/unknown run throws, and a from-start join to a + run that never produces fails after `MemoryStreamOptions.firstChunkDeadlineMs`. + - all four HTTP adapters accept `reconnect: { maxAttempts, delayMs }` — a + throttle plus a ceiling on CONSECUTIVE no-progress reconnects (default 5; + forward progress resets it) that fails with the new `StreamReconnectLimitError` + instead of reconnecting endlessly, without penalizing a healthy long-lived run. + - `durableStream` accepts `reconnect: { maxReadFailures, delayMs }` to bound its + read-retry loop, and `server` is now optional when `fetch` is provided (e.g. a + Cloudflare service binding). + - `toServerSentEventsResponse` accepts `debug` to record durability terminal / + close failures server-side, where a replaying joiner cannot observe them. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 diff --git a/packages/ai-durable-stream/package.json b/packages/ai-durable-stream/package.json index 2ce39ffb8..dd3b365fb 100644 --- a/packages/ai-durable-stream/package.json +++ b/packages/ai-durable-stream/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-durable-stream", - "version": "0.0.0", + "version": "0.1.0", "description": "Delivery durability for TanStack AI over the durable-streams HTTP protocol — a resumable StreamDurability transport sink (append/read/resume) that stores zero delivery events itself.", "author": "", "license": "MIT", diff --git a/packages/ai-elevenlabs/CHANGELOG.md b/packages/ai-elevenlabs/CHANGELOG.md index e441d6d16..8dec28731 100644 --- a/packages/ai-elevenlabs/CHANGELOG.md +++ b/packages/ai-elevenlabs/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-elevenlabs +## 0.2.35 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.2.34 ### Patch Changes diff --git a/packages/ai-elevenlabs/package.json b/packages/ai-elevenlabs/package.json index ee1c39d20..d4d7e6648 100644 --- a/packages/ai-elevenlabs/package.json +++ b/packages/ai-elevenlabs/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-elevenlabs", - "version": "0.2.34", + "version": "0.2.35", "description": "ElevenLabs adapter for TanStack AI realtime voice, text-to-speech, transcription, music, and sound effects.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-event-client/CHANGELOG.md b/packages/ai-event-client/CHANGELOG.md index 636549768..b70153785 100644 --- a/packages/ai-event-client/CHANGELOG.md +++ b/packages/ai-event-client/CHANGELOG.md @@ -1,5 +1,86 @@ # @tanstack/ai-event-client +## 0.7.0 + +### Minor Changes + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Surface server-side memory state in the TanStack AI DevTools.** + + The DevTools panel now has a **Memory** tab for any chat wired with + `memoryMiddleware`. It shows, per scope (session), an operations timeline (each + turn's recall — query, fragment count, injected system-prompt size, whether + memory tools were exposed, duration) and the current stored records/facts when + the adapter implements the optional `inspect`/`listFacts` methods. + + Because memory runs on the server (whose event bus never reaches the browser), + the middleware transports its state to the panel over the chat stream as a + `memory:state` `CUSTOM` event, which `@tanstack/ai-client`'s devtools bridge + re-emits as browser `memory:*` events — the same pattern generation results use. + The snapshot reflects memory as of the start of each turn; opening the panel + mid-conversation replays the latest state so the tab isn't empty. + - `@tanstack/ai-memory` — `memoryMiddleware` injects a `memory:state` `CUSTOM` + chunk carrying recall metrics + an `inspect`/`listFacts` snapshot; exports + `MEMORY_STATE_EVENT` and `MemoryStateEventValue`. + - `@tanstack/ai-event-client` — adds the `memory:snapshot` devtools event. + - `@tanstack/ai-client` — the chat devtools bridge re-emits `memory:*` from the + transported chunk and replays the last snapshot on `devtools:request-state`. + - `@tanstack/ai-devtools-core` — new Memory tab + per-scope memory store slice. + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Add server-side memory via a `recall`/`save` adapter contract in `@tanstack/ai-memory`.** + + Memory is now a single, provider-agnostic contract with two verbs — `recall` and + `save` — which is the shape every memory backend (in-process, Redis, and hosted + vendors) naturally exposes. `memoryMiddleware` recalls relevant memory into the + system prompt (and optionally injects vendor tools) before the model runs, then + defers `save` of the finished turn via `ctx.defer` so streaming is never blocked. + Extraction, ranking, and rendering live inside each adapter — the middleware is thin. + + `@tanstack/ai-memory` (new package) — everything ships here: + - Root: `memoryMiddleware`, the `MemoryAdapter` contract + (`recall` / `save` / optional `inspect` / `listFacts`), and the `MemoryScope` / + `MemoryTurn` / `RecallResult` / `SaveReceipt` types. + - `@tanstack/ai-memory/in-memory` → `inMemory()` — zero-dependency adapter for dev, + tests, and single-process demos. Pass an `embedder` for semantic scoring and/or an + `extract` function to persist derived facts. + - `@tanstack/ai-memory/redis` → `redis({ redis, prefix? })` — production adapter for + plain Redis. `ioredis` wires in directly; `redis` (node-redis v4+) via the + `fromNodeRedis(client)` wrapper. Both are optional peer dependencies. + - `@tanstack/ai-memory/hindsight` → `hindsight()`, `@tanstack/ai-memory/mem0` → + `mem0()`, `@tanstack/ai-memory/honcho` → `honcho()` — hosted-vendor adapters. Their + SDKs (`@vectorize-io/hindsight-client`, `@honcho-ai/sdk`) are optional peers loaded + lazily; mem0 talks to its server over plain HTTP (no SDK). Vendors can expose LLM + tools through `recall` (e.g. hindsight's retain/recall/reflect). + - A shared `recall`/`save` contract-test suite (`@tanstack/ai-memory/tests/contract`) + that any adapter — including third-party ones — can run. + + `@tanstack/ai`: + - **Removes the (unreleased) `@tanstack/ai/memory` subpath.** The middleware, + contract, and helpers all moved to `@tanstack/ai-memory`. + + `@tanstack/ai-event-client`: + - The five `memory:*` devtools events (`memory:retrieve:started` / `:completed`, + `memory:persist:started` / `:completed`, `memory:error`) now carry recall/save + payloads (adapter id, fragment/receipt counts, `phase: 'recall' | 'save'`). + +- [#991](https://github.com/TanStack/ai/pull/991) [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371) - **Align `MemoryScope` to the shared `Scope` type (`threadId`).** + + `MemoryScope` is now an alias of `Scope` from `@tanstack/ai` so memory and + persistence share one isolation vocabulary. The conversation key is + `threadId` (required); optional dims are `userId`, `tenantId`, and reserved + `namespace`. There is no public `sessionId` on memory scope — hard cut while + `@tanstack/ai-memory` is still `0.x` / unreleased. + - `@tanstack/ai-memory` — `export type MemoryScope = Scope`. Built-in adapters + (`inMemory`, `redis`) and middleware use `threadId`; `sameScope` also matches + `tenantId` when present on the query. Redis index keys are now + `{prefix}:index:{tenantId|_}:{userId|_}:{threadId}` (escaped). Hindsight banks + use `{user}__{threadId}`. Anyone who wrote Redis rows under the pre-rename + layout needs to reindex or wipe — keys are not dual-read. + - `@tanstack/ai-event-client` — `MemoryScopeLite` is + `{ threadId?, userId?, tenantId? }` (devtools telemetry; not an isolation + authority). + - `@tanstack/ai-client` / `@tanstack/ai-devtools-core` — memory event payloads + and the Memory panel registry follow the same `threadId` field names. + ## 0.6.8 ### Patch Changes diff --git a/packages/ai-event-client/package.json b/packages/ai-event-client/package.json index 8e7ed2a49..0a4abacc2 100644 --- a/packages/ai-event-client/package.json +++ b/packages/ai-event-client/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-event-client", - "version": "0.6.8", + "version": "0.7.0", "description": "Typed event client for TanStack AI devtools, observability, and streamed runtime events.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-fal/CHANGELOG.md b/packages/ai-fal/CHANGELOG.md index e7239bcc4..31d15bf6f 100644 --- a/packages/ai-fal/CHANGELOG.md +++ b/packages/ai-fal/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-fal +## 0.9.13 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.9.12 ### Patch Changes diff --git a/packages/ai-fal/package.json b/packages/ai-fal/package.json index 8290805ba..bb7e6b134 100644 --- a/packages/ai-fal/package.json +++ b/packages/ai-fal/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-fal", - "version": "0.9.12", + "version": "0.9.13", "description": "fal.ai adapter for TanStack AI image, video, audio, speech, and transcription generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-gemini/CHANGELOG.md b/packages/ai-gemini/CHANGELOG.md index 7c2f00957..73f786d00 100644 --- a/packages/ai-gemini/CHANGELOG.md +++ b/packages/ai-gemini/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-gemini +## 0.20.2 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.20.1 ### Patch Changes @@ -22,7 +29,9 @@ ```ts createOpenaiImage('gpt-image-1', apiKey, { allowUrlFetch: true }) createOpenaiVideo('sora-2', apiKey, { allowUrlFetch: true }) - createGeminiVideo('veo-3.1-generate-preview', apiKey, { allowUrlFetch: true }) + createGeminiVideo('veo-3.1-generate-preview', apiKey, { + allowUrlFetch: true, + }) ``` Migration: if you passed HTTP(S) URL image inputs to these adapters, either fetch the bytes yourself and pass a `data:` URI, pass a `gs://` reference (Veo), or set `allowUrlFetch: true`. diff --git a/packages/ai-gemini/package.json b/packages/ai-gemini/package.json index 412fa0a58..e7cb5e9a5 100644 --- a/packages/ai-gemini/package.json +++ b/packages/ai-gemini/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-gemini", - "version": "0.20.1", + "version": "0.20.2", "description": "Google Gemini adapter for TanStack AI chat, images, speech, audio generation, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-grok-build/CHANGELOG.md b/packages/ai-grok-build/CHANGELOG.md index bb7a7132f..ca6c5ad9a 100644 --- a/packages/ai-grok-build/CHANGELOG.md +++ b/packages/ai-grok-build/CHANGELOG.md @@ -1,5 +1,14 @@ # @tanstack/ai-grok-build +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + - @tanstack/ai-acp@0.2.4 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-grok-build/package.json b/packages/ai-grok-build/package.json index 7aeb00977..274841c7c 100644 --- a/packages/ai-grok-build/package.json +++ b/packages/ai-grok-build/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-grok-build", - "version": "0.2.3", + "version": "0.2.4", "description": "Grok Build harness adapter for TanStack AI — run Grok Build as a chat backend with local tool execution and stateful sessions.", "author": "", "license": "MIT", diff --git a/packages/ai-grok/CHANGELOG.md b/packages/ai-grok/CHANGELOG.md index 80eb945ea..eb1ff0038 100644 --- a/packages/ai-grok/CHANGELOG.md +++ b/packages/ai-grok/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-grok +## 0.14.10 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/openai-base@0.9.10 + ## 0.14.9 ### Patch Changes diff --git a/packages/ai-grok/package.json b/packages/ai-grok/package.json index caae1ee0c..3b32629da 100644 --- a/packages/ai-grok/package.json +++ b/packages/ai-grok/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-grok", - "version": "0.14.9", + "version": "0.14.10", "description": "xAI Grok adapter for TanStack AI chat, image generation, realtime, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-groq/CHANGELOG.md b/packages/ai-groq/CHANGELOG.md index b3a32a8cc..96db7f2c2 100644 --- a/packages/ai-groq/CHANGELOG.md +++ b/packages/ai-groq/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-groq +## 0.5.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/openai-base@0.9.10 + ## 0.5.3 ### Patch Changes diff --git a/packages/ai-groq/package.json b/packages/ai-groq/package.json index 2f1aaef65..2bd567d15 100644 --- a/packages/ai-groq/package.json +++ b/packages/ai-groq/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-groq", - "version": "0.5.3", + "version": "0.5.4", "description": "Groq adapter for TanStack AI low-latency chat, tool calling, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-isolate-cloudflare/CHANGELOG.md b/packages/ai-isolate-cloudflare/CHANGELOG.md index eacf35de7..f8ea64db3 100644 --- a/packages/ai-isolate-cloudflare/CHANGELOG.md +++ b/packages/ai-isolate-cloudflare/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-isolate-cloudflare +## 0.2.39 + +### Patch Changes + +- Updated dependencies []: + - @tanstack/ai-code-mode@0.3.9 + ## 0.2.38 ### Patch Changes diff --git a/packages/ai-isolate-cloudflare/package.json b/packages/ai-isolate-cloudflare/package.json index 726e3b45c..5ee9a3fca 100644 --- a/packages/ai-isolate-cloudflare/package.json +++ b/packages/ai-isolate-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-isolate-cloudflare", - "version": "0.2.38", + "version": "0.2.39", "description": "Cloudflare Workers sandbox driver for TanStack AI Code Mode TypeScript execution at the edge.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-isolate-node/CHANGELOG.md b/packages/ai-isolate-node/CHANGELOG.md index 355dae5c8..97bdb1d36 100644 --- a/packages/ai-isolate-node/CHANGELOG.md +++ b/packages/ai-isolate-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-isolate-node +## 0.1.48 + +### Patch Changes + +- Updated dependencies []: + - @tanstack/ai-code-mode@0.3.9 + ## 0.1.47 ### Patch Changes diff --git a/packages/ai-isolate-node/package.json b/packages/ai-isolate-node/package.json index 18b95cf4c..1c484f827 100644 --- a/packages/ai-isolate-node/package.json +++ b/packages/ai-isolate-node/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-isolate-node", - "version": "0.1.47", + "version": "0.1.48", "description": "Node.js isolated-vm sandbox driver for TanStack AI Code Mode TypeScript execution.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-isolate-quickjs/CHANGELOG.md b/packages/ai-isolate-quickjs/CHANGELOG.md index 21b609c72..77cf64afc 100644 --- a/packages/ai-isolate-quickjs/CHANGELOG.md +++ b/packages/ai-isolate-quickjs/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-isolate-quickjs +## 0.1.48 + +### Patch Changes + +- Updated dependencies []: + - @tanstack/ai-code-mode@0.3.9 + ## 0.1.47 ### Patch Changes diff --git a/packages/ai-isolate-quickjs/package.json b/packages/ai-isolate-quickjs/package.json index 27a7640f6..84a1e3c16 100644 --- a/packages/ai-isolate-quickjs/package.json +++ b/packages/ai-isolate-quickjs/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-isolate-quickjs", - "version": "0.1.47", + "version": "0.1.48", "description": "QuickJS WASM sandbox driver for TanStack AI Code Mode TypeScript execution across runtimes.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-mcp/CHANGELOG.md b/packages/ai-mcp/CHANGELOG.md index 68604fba8..ae7de682f 100644 --- a/packages/ai-mcp/CHANGELOG.md +++ b/packages/ai-mcp/CHANGELOG.md @@ -1,5 +1,34 @@ # @tanstack/ai-mcp +## 0.2.6 + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - **Make every bundled Agent Skill discoverable by TanStack Intent.** + + Intent finds skills by scanning `node_modules` for packages that carry the + `tanstack-intent` keyword, and can only load what npm actually publishes. Three + packages shipped skills that failed one half of that contract: + - `@tanstack/ai-mcp` wrote its skill into a `skills/` directory that was missing + from `files`, so it was never published at all. + - `@tanstack/ai-memory` and `@tanstack/ai-sandbox` published their skills but + lacked the keyword, so Intent never looked at them. + + All three now publish `skills` and carry the keyword, matching `@tanstack/ai`, + `@tanstack/ai-code-mode`, and `@tanstack/ai-persistence`. + + The client persistence skill also moves from `@tanstack/ai-persistence` to + `@tanstack/ai` as `ai-core/client-persistence`. It teaches + `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` + and the `persistence` option on `useChat` — all of which live in the framework + packages, not in `@tanstack/ai-persistence`. An app doing browser-only + persistence never installs that package, so the guidance was unreachable for + exactly the people who needed it, and `ai-core` routed to a path that did not + exist on disk. Skills now follow the code that owns them. + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.2.5 ### Patch Changes diff --git a/packages/ai-mcp/package.json b/packages/ai-mcp/package.json index 95af96517..c84512af4 100644 --- a/packages/ai-mcp/package.json +++ b/packages/ai-mcp/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-mcp", - "version": "0.2.5", + "version": "0.2.6", "description": "Host-side Model Context Protocol client for TanStack AI: discover and run MCP server tools, resources, and prompts in any adapter's chat() loop, with generated end-to-end types.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-memory/CHANGELOG.md b/packages/ai-memory/CHANGELOG.md new file mode 100644 index 000000000..ec18e396b --- /dev/null +++ b/packages/ai-memory/CHANGELOG.md @@ -0,0 +1,110 @@ +# @tanstack/ai-memory + +## 0.1.0 + +### Minor Changes + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Surface server-side memory state in the TanStack AI DevTools.** + + The DevTools panel now has a **Memory** tab for any chat wired with + `memoryMiddleware`. It shows, per scope (session), an operations timeline (each + turn's recall — query, fragment count, injected system-prompt size, whether + memory tools were exposed, duration) and the current stored records/facts when + the adapter implements the optional `inspect`/`listFacts` methods. + + Because memory runs on the server (whose event bus never reaches the browser), + the middleware transports its state to the panel over the chat stream as a + `memory:state` `CUSTOM` event, which `@tanstack/ai-client`'s devtools bridge + re-emits as browser `memory:*` events — the same pattern generation results use. + The snapshot reflects memory as of the start of each turn; opening the panel + mid-conversation replays the latest state so the tab isn't empty. + - `@tanstack/ai-memory` — `memoryMiddleware` injects a `memory:state` `CUSTOM` + chunk carrying recall metrics + an `inspect`/`listFacts` snapshot; exports + `MEMORY_STATE_EVENT` and `MemoryStateEventValue`. + - `@tanstack/ai-event-client` — adds the `memory:snapshot` devtools event. + - `@tanstack/ai-client` — the chat devtools bridge re-emits `memory:*` from the + transported chunk and replays the last snapshot on `devtools:request-state`. + - `@tanstack/ai-devtools-core` — new Memory tab + per-scope memory store slice. + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Add server-side memory via a `recall`/`save` adapter contract in `@tanstack/ai-memory`.** + + Memory is now a single, provider-agnostic contract with two verbs — `recall` and + `save` — which is the shape every memory backend (in-process, Redis, and hosted + vendors) naturally exposes. `memoryMiddleware` recalls relevant memory into the + system prompt (and optionally injects vendor tools) before the model runs, then + defers `save` of the finished turn via `ctx.defer` so streaming is never blocked. + Extraction, ranking, and rendering live inside each adapter — the middleware is thin. + + `@tanstack/ai-memory` (new package) — everything ships here: + - Root: `memoryMiddleware`, the `MemoryAdapter` contract + (`recall` / `save` / optional `inspect` / `listFacts`), and the `MemoryScope` / + `MemoryTurn` / `RecallResult` / `SaveReceipt` types. + - `@tanstack/ai-memory/in-memory` → `inMemory()` — zero-dependency adapter for dev, + tests, and single-process demos. Pass an `embedder` for semantic scoring and/or an + `extract` function to persist derived facts. + - `@tanstack/ai-memory/redis` → `redis({ redis, prefix? })` — production adapter for + plain Redis. `ioredis` wires in directly; `redis` (node-redis v4+) via the + `fromNodeRedis(client)` wrapper. Both are optional peer dependencies. + - `@tanstack/ai-memory/hindsight` → `hindsight()`, `@tanstack/ai-memory/mem0` → + `mem0()`, `@tanstack/ai-memory/honcho` → `honcho()` — hosted-vendor adapters. Their + SDKs (`@vectorize-io/hindsight-client`, `@honcho-ai/sdk`) are optional peers loaded + lazily; mem0 talks to its server over plain HTTP (no SDK). Vendors can expose LLM + tools through `recall` (e.g. hindsight's retain/recall/reflect). + - A shared `recall`/`save` contract-test suite (`@tanstack/ai-memory/tests/contract`) + that any adapter — including third-party ones — can run. + + `@tanstack/ai`: + - **Removes the (unreleased) `@tanstack/ai/memory` subpath.** The middleware, + contract, and helpers all moved to `@tanstack/ai-memory`. + + `@tanstack/ai-event-client`: + - The five `memory:*` devtools events (`memory:retrieve:started` / `:completed`, + `memory:persist:started` / `:completed`, `memory:error`) now carry recall/save + payloads (adapter id, fragment/receipt counts, `phase: 'recall' | 'save'`). + +- [#991](https://github.com/TanStack/ai/pull/991) [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371) - **Align `MemoryScope` to the shared `Scope` type (`threadId`).** + + `MemoryScope` is now an alias of `Scope` from `@tanstack/ai` so memory and + persistence share one isolation vocabulary. The conversation key is + `threadId` (required); optional dims are `userId`, `tenantId`, and reserved + `namespace`. There is no public `sessionId` on memory scope — hard cut while + `@tanstack/ai-memory` is still `0.x` / unreleased. + - `@tanstack/ai-memory` — `export type MemoryScope = Scope`. Built-in adapters + (`inMemory`, `redis`) and middleware use `threadId`; `sameScope` also matches + `tenantId` when present on the query. Redis index keys are now + `{prefix}:index:{tenantId|_}:{userId|_}:{threadId}` (escaped). Hindsight banks + use `{user}__{threadId}`. Anyone who wrote Redis rows under the pre-rename + layout needs to reindex or wipe — keys are not dual-read. + - `@tanstack/ai-event-client` — `MemoryScopeLite` is + `{ threadId?, userId?, tenantId? }` (devtools telemetry; not an isolation + authority). + - `@tanstack/ai-client` / `@tanstack/ai-devtools-core` — memory event payloads + and the Memory panel registry follow the same `threadId` field names. + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - **Make every bundled Agent Skill discoverable by TanStack Intent.** + + Intent finds skills by scanning `node_modules` for packages that carry the + `tanstack-intent` keyword, and can only load what npm actually publishes. Three + packages shipped skills that failed one half of that contract: + - `@tanstack/ai-mcp` wrote its skill into a `skills/` directory that was missing + from `files`, so it was never published at all. + - `@tanstack/ai-memory` and `@tanstack/ai-sandbox` published their skills but + lacked the keyword, so Intent never looked at them. + + All three now publish `skills` and carry the keyword, matching `@tanstack/ai`, + `@tanstack/ai-code-mode`, and `@tanstack/ai-persistence`. + + The client persistence skill also moves from `@tanstack/ai-persistence` to + `@tanstack/ai` as `ai-core/client-persistence`. It teaches + `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` + and the `persistence` option on `useChat` — all of which live in the framework + packages, not in `@tanstack/ai-persistence`. An app doing browser-only + persistence never installs that package, so the guidance was unreachable for + exactly the people who needed it, and `ai-core` routed to a path that did not + exist on disk. Skills now follow the code that owns them. + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-event-client@0.7.0 diff --git a/packages/ai-memory/package.json b/packages/ai-memory/package.json index 15fcba1e3..d5ffd2160 100644 --- a/packages/ai-memory/package.json +++ b/packages/ai-memory/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-memory", - "version": "0.0.0", + "version": "0.1.0", "description": "Pluggable memory adapters for TanStack AI memoryMiddleware", "author": "", "license": "MIT", diff --git a/packages/ai-mistral/CHANGELOG.md b/packages/ai-mistral/CHANGELOG.md index 5bd877325..eefbfa8de 100644 --- a/packages/ai-mistral/CHANGELOG.md +++ b/packages/ai-mistral/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-mistral +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-mistral/package.json b/packages/ai-mistral/package.json index 177210044..1d5c84639 100644 --- a/packages/ai-mistral/package.json +++ b/packages/ai-mistral/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-mistral", - "version": "0.2.3", + "version": "0.2.4", "type": "module", "description": "Mistral adapter for TanStack AI", "author": "", diff --git a/packages/ai-ollama/CHANGELOG.md b/packages/ai-ollama/CHANGELOG.md index 80f9fa2ef..60ac3ed2f 100644 --- a/packages/ai-ollama/CHANGELOG.md +++ b/packages/ai-ollama/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-ollama +## 0.8.17 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.8.16 ### Patch Changes diff --git a/packages/ai-ollama/package.json b/packages/ai-ollama/package.json index 8b414b3a4..f57636beb 100644 --- a/packages/ai-ollama/package.json +++ b/packages/ai-ollama/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-ollama", - "version": "0.8.16", + "version": "0.8.17", "description": "Ollama adapter for TanStack AI local LLM chat, tool calling, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-openai/CHANGELOG.md b/packages/ai-openai/CHANGELOG.md index 90c8fa673..904a4d7a2 100644 --- a/packages/ai-openai/CHANGELOG.md +++ b/packages/ai-openai/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-openai +## 0.17.2 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/openai-base@0.9.10 + ## 0.17.1 ### Patch Changes @@ -21,7 +29,9 @@ ```ts createOpenaiImage('gpt-image-1', apiKey, { allowUrlFetch: true }) createOpenaiVideo('sora-2', apiKey, { allowUrlFetch: true }) - createGeminiVideo('veo-3.1-generate-preview', apiKey, { allowUrlFetch: true }) + createGeminiVideo('veo-3.1-generate-preview', apiKey, { + allowUrlFetch: true, + }) ``` Migration: if you passed HTTP(S) URL image inputs to these adapters, either fetch the bytes yourself and pass a `data:` URI, pass a `gs://` reference (Veo), or set `allowUrlFetch: true`. diff --git a/packages/ai-openai/package.json b/packages/ai-openai/package.json index c10867be9..7ec0cc798 100644 --- a/packages/ai-openai/package.json +++ b/packages/ai-openai/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-openai", - "version": "0.17.1", + "version": "0.17.2", "description": "OpenAI adapter for TanStack AI chat, tools, images, video, speech, transcription, realtime, and structured outputs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-opencode/CHANGELOG.md b/packages/ai-opencode/CHANGELOG.md index 809af39b4..1564b8ffa 100644 --- a/packages/ai-opencode/CHANGELOG.md +++ b/packages/ai-opencode/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-opencode +## 0.2.4 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.3 ### Patch Changes diff --git a/packages/ai-opencode/package.json b/packages/ai-opencode/package.json index 091203639..ff8583692 100644 --- a/packages/ai-opencode/package.json +++ b/packages/ai-opencode/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-opencode", - "version": "0.2.3", + "version": "0.2.4", "description": "OpenCode harness adapter for TanStack AI — run OpenCode as a chat backend with local tool execution and stateful sessions.", "author": "", "license": "MIT", diff --git a/packages/ai-openrouter/CHANGELOG.md b/packages/ai-openrouter/CHANGELOG.md index 49d91c73f..dfc308abb 100644 --- a/packages/ai-openrouter/CHANGELOG.md +++ b/packages/ai-openrouter/CHANGELOG.md @@ -1,5 +1,14 @@ # @tanstack/ai-openrouter +## 0.15.11 + +### Patch Changes + +- [#888](https://github.com/TanStack/ai/pull/888) [`50d7a7d`](https://github.com/TanStack/ai/commit/50d7a7da319bd39c578548390a723302f90068c7) - Update model metadata from OpenRouter API + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.15.10 ### Patch Changes diff --git a/packages/ai-openrouter/package.json b/packages/ai-openrouter/package.json index 5aa817ade..d3d4d8506 100644 --- a/packages/ai-openrouter/package.json +++ b/packages/ai-openrouter/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-openrouter", - "version": "0.15.10", + "version": "0.15.11", "description": "TanStack AI adapter for OpenRouter chat, provider tools, structured outputs, and access to hundreds of LLMs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-persistence/CHANGELOG.md b/packages/ai-persistence/CHANGELOG.md new file mode 100644 index 000000000..5c06e942c --- /dev/null +++ b/packages/ai-persistence/CHANGELOG.md @@ -0,0 +1,113 @@ +# @tanstack/ai-persistence + +## 0.1.0 + +### Minor Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add per-store typer helpers: `defineMessageStore`, `defineRunStore`, + `defineInterruptStore`, `defineMetadataStore`. + + Each takes a store implementation and returns it typed against the contract, so + you get autocomplete and checking on the object literal inline — no separate + `: MessageStore` return annotation. They compose into `defineAIPersistence`, + which already infers **exact presence**: a store you define is a defined, + non-optional, autocompleted key on `persistence.stores`, and accessing a store + you did not define is a compile error. + + ```ts + import { + defineAIPersistence, + defineMessageStore, + defineRunStore, + } from '@tanstack/ai-persistence' + + const persistence = defineAIPersistence({ + stores: { + messages: defineMessageStore({ loadThread, saveThread }), + runs: defineRunStore({ createOrResume, update, get }), + }, + }) + + persistence.stores.runs // RunStore (defined) + persistence.stores.interrupts // compile error — not provided + ``` + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Server-authoritative reconnect is now automatic and keyed on the thread, not the run. + + A chat's durable identity is its **thread**; run ids are ephemeral (a single turn + can span several runs via interrupts or tool continuations), so basing reconnect + on a client-cached run id goes stale the moment a turn rolls to a new run. This + moves the whole reconnect story onto the stable thread id, resolved by the server. + - **`RunStore.findActiveRun(threadId)`** — new optional, feature-detected store + method returning the most recent `'running'` run for a thread. Implemented by + the in-memory reference backend and covered by the conformance testkit, so any + adapter that provides it is held to the same invariants (most-recent-running + wins, thread-scoped, null when idle). + - **`reconstructChat` now returns `{ messages, activeRun, interrupts }`** (was a + bare message array): the stored transcript as UI messages, a cursor to an + in-flight run if one exists, and any pending human-in-the-loop interrupts (tool + approvals / waits) plus the run they paused. It reads the active run before the + transcript so observing "no active run" guarantees the transcript is final + (closing a finish-window race). + - **`@tanstack/ai-client` hydrates itself on mount.** In server-authoritative + mode (`persistence: true`) the client caches no transcript and no run + pointer: on mount `useChat`/`ChatClient` calls the connection's new + `hydrate(threadId)` (a JSON GET against the same endpoint), paints the returned + transcript, and — if a run is in flight — tails it via the existing `joinRun` + durability replay. A reload and the same thread opened on another device are the + identical, server-resolved path. No loader, no `initialMessages`, no + `initialResumeSnapshot`, no app-side fetching required. + - **Interrupts reconstruct from the server too.** A paused approval (a tool with + `needsApproval`) is restored from `reconstructChat`'s `interrupts` exactly as a + persisted resume snapshot would be, so a reload — or another device — re-prompts + the same approve/reject decision and resumes the run it paused. Previously the + pending interrupt was only recoverable from client storage, so a fresh client + showed the paused tool call with no way to resolve it. + + Apps keep the single GET endpoint they already have (durability replay when a + resume cursor is present, else `reconstructChat`); everything else is handled by + the hook. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Move multi-instance **locks** to `@tanstack/ai` under a dedicated `@tanstack/ai/locks` subpath, and nest persistence agent skills like `ai-core`. + - **`LockStore` / `InMemoryLockStore` / `LocksCapability` / `getLocks` / `provideLocks` / `withLocks`** live in `@tanstack/ai/locks` (not the main `@tanstack/ai` barrel, and not `@tanstack/ai-persistence`). + - `@tanstack/ai-sandbox` consumes the core `LocksCapability` token (no local lock re-export). + - The locks agent skill moves with the code: `ai-core/locks` in `@tanstack/ai`, not `ai-persistence/locks`. + - Agent skills under `@tanstack/ai-persistence` nest as `skills/ai-persistence/{stores,server,build-*-adapter}/`. + - Docs: locks guide under advanced middleware. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add server-side persistence for `chat()`: durable thread messages, run records, and interrupts. + + `withPersistence(persistence)` is a chat middleware that stores the conversation transcript, tracks each run's status, and records interrupt state so a paused run (tool approval, client-tool execution, generic interrupt) survives a server restart. + + `@tanstack/ai-persistence` ships the **contract**, not a backend for your database: + - The four store interfaces — `MessageStore`, `RunStore`, `InterruptStore`, `MetadataStore` — with the invariants the middleware depends on (full-replace `saveThread`, idempotent `createOrResume`, insert-if-absent interrupt `create`, `requestedAt`-ascending listings). + - The `withPersistence` / `withGenerationPersistence` middleware, plus `composePersistence` to assemble stores that live in different systems. + - `memoryPersistence()`, an in-process reference backend for dev and tests. + - `LockStore` / `withLocks` / `InMemoryLockStore` for cross-worker coordination — deliberately **not** a state store, and not composable through `composePersistence`. + - A shared conformance testkit at `@tanstack/ai-persistence/testkit`. `runPersistenceConformance` exercises every method of every store you provide and fails loudly on a store that is missing without being declared in `skip`. + + Implement the stores against whatever database you already run and hand the result to `withPersistence` — the core never inspects your tables, so the schema stays yours. The [Build Your Own Adapter](https://tanstack.com/ai/latest/docs/persistence/build-your-own-adapter) guide walks through a complete `node:sqlite` backend end to end, and the package ships Agent Skills with worked Drizzle, Prisma, and Cloudflare D1 recipes (`npx @tanstack/intent@latest install`). `examples/ts-react-chat` runs on a self-contained `node:sqlite` adapter built this way and verified by the conformance testkit. + + Resume reconstruction is delegated to the chat engine: persistence records interrupts and gates new input on a thread with pending interrupts, while the engine rebuilds the resume tool state from the resume batch and the interrupt bindings carried in the (server-loaded) message history. + + `reconstructChat(persistence, request)` is a server helper that returns a thread's stored messages as a JSON `Response`, so a server-authoritative client can hydrate its transcript on load from a one-line `GET` handler. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Make a mid-stream reload resume the same conversation cleanly. + - `withPersistence` now persists the pending turn at the start of a run (so a + reload during generation still shows the user's message), stamps each + assistant turn with its stream `messageId`, and accepts + `withPersistence(persistence, { snapshotStreaming: true })` to also persist the + in-progress reply on a throttled interval (`snapshotIntervalMs`, default + `1000`) for partial-output durability. + - `ModelMessage` gains an optional `id`; `modelMessagesToUIMessages` preserves + it, so a hydrated message keeps the same identity as its live stream. + - On reload, the chat client rebuilds an in-flight assistant turn from the + delivery log (replaying from the start and applying the buffered backlog in one + batch) instead of reconciling against the persisted partial, so the reload + shows one clean bubble that catches up and continues rather than a frozen or + duplicated partial. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 diff --git a/packages/ai-persistence/package.json b/packages/ai-persistence/package.json index f86e0563d..84a6581f5 100644 --- a/packages/ai-persistence/package.json +++ b/packages/ai-persistence/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-persistence", - "version": "0.0.0", + "version": "0.1.0", "description": "Composable state persistence for TanStack AI messages, runs, interrupts, metadata, and locks.", "author": "", "license": "MIT", diff --git a/packages/ai-preact/CHANGELOG.md b/packages/ai-preact/CHANGELOG.md index 1f66e75ad..85d6a092b 100644 --- a/packages/ai-preact/CHANGELOG.md +++ b/packages/ai-preact/CHANGELOG.md @@ -1,5 +1,59 @@ # @tanstack/ai-preact +## 0.12.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.11.1 ### Patch Changes diff --git a/packages/ai-preact/package.json b/packages/ai-preact/package.json index 3fae2bba4..4bc2b91e5 100644 --- a/packages/ai-preact/package.json +++ b/packages/ai-preact/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-preact", - "version": "0.11.1", + "version": "0.12.0", "description": "Preact hooks for TanStack AI streaming chat and typed messages.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-react-ui/CHANGELOG.md b/packages/ai-react-ui/CHANGELOG.md index 1de3edb2c..ff0ebbb1b 100644 --- a/packages/ai-react-ui/CHANGELOG.md +++ b/packages/ai-react-ui/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-react-ui +## 0.8.16 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-client@0.23.0 + - @tanstack/ai-react@0.19.0 + ## 0.8.15 ### Patch Changes diff --git a/packages/ai-react-ui/package.json b/packages/ai-react-ui/package.json index 05058a215..2747a47e7 100644 --- a/packages/ai-react-ui/package.json +++ b/packages/ai-react-ui/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-react-ui", - "version": "0.8.15", + "version": "0.8.16", "description": "Headless React components for building TanStack AI chat interfaces with streamed message parts.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-react/CHANGELOG.md b/packages/ai-react/CHANGELOG.md index 25bdce91d..1d849ad8f 100644 --- a/packages/ai-react/CHANGELOG.md +++ b/packages/ai-react/CHANGELOG.md @@ -1,5 +1,66 @@ # @tanstack/ai-react +## 0.19.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Fix `useChat` aborting an in-flight delivery resume on mount. When `live` was + not enabled, the mount effect called `client.unsubscribe()` unconditionally, + which cancelled the shared in-flight stream — including the `joinRun` rejoin the + client had just started for a reloaded run. The result was a mid-stream reload + that caught up to the buffered point and then froze instead of continuing. + `useChat` now only tears down a subscription it actually started, so a reload + rejoins and streams the run through to completion. +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.18.1 ### Patch Changes diff --git a/packages/ai-react/package.json b/packages/ai-react/package.json index 8cf8747e4..1940f79ff 100644 --- a/packages/ai-react/package.json +++ b/packages/ai-react/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-react", - "version": "0.18.1", + "version": "0.19.0", "description": "React hooks for TanStack AI streaming chat, realtime voice, structured outputs, and media generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-sandbox-cloudflare/CHANGELOG.md b/packages/ai-sandbox-cloudflare/CHANGELOG.md index 214f16495..d07649aa5 100644 --- a/packages/ai-sandbox-cloudflare/CHANGELOG.md +++ b/packages/ai-sandbox-cloudflare/CHANGELOG.md @@ -1,5 +1,14 @@ # @tanstack/ai-sandbox-cloudflare +## 0.2.5 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-sandbox@0.3.0 + - @tanstack/ai-sandbox-local-process@0.2.1 + ## 0.2.4 ### Patch Changes diff --git a/packages/ai-sandbox-cloudflare/package.json b/packages/ai-sandbox-cloudflare/package.json index e8c644836..f47f6f1ac 100644 --- a/packages/ai-sandbox-cloudflare/package.json +++ b/packages/ai-sandbox-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-cloudflare", - "version": "0.2.4", + "version": "0.2.5", "description": "Cloudflare sandbox provider for TanStack AI — run harness adapters inside Cloudflare Containers (edge) through the uniform SandboxHandle.", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox-daytona/CHANGELOG.md b/packages/ai-sandbox-daytona/CHANGELOG.md index e6a434ee1..550c7d4f0 100644 --- a/packages/ai-sandbox-daytona/CHANGELOG.md +++ b/packages/ai-sandbox-daytona/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-sandbox-daytona +## 0.2.1 + +### Patch Changes + +- Updated dependencies [[`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.0 ### Minor Changes diff --git a/packages/ai-sandbox-daytona/package.json b/packages/ai-sandbox-daytona/package.json index 671d5615d..6d926325b 100644 --- a/packages/ai-sandbox-daytona/package.json +++ b/packages/ai-sandbox-daytona/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-daytona", - "version": "0.2.0", + "version": "0.2.1", "description": "Daytona sandbox provider for TanStack AI — run harness adapters inside isolated Daytona cloud sandboxes through the uniform SandboxHandle.", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox-docker/CHANGELOG.md b/packages/ai-sandbox-docker/CHANGELOG.md index ef558b9a2..ab6f667db 100644 --- a/packages/ai-sandbox-docker/CHANGELOG.md +++ b/packages/ai-sandbox-docker/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-sandbox-docker +## 0.2.1 + +### Patch Changes + +- Updated dependencies [[`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.0 ### Minor Changes diff --git a/packages/ai-sandbox-docker/package.json b/packages/ai-sandbox-docker/package.json index 410826af0..7ff28de45 100644 --- a/packages/ai-sandbox-docker/package.json +++ b/packages/ai-sandbox-docker/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-docker", - "version": "0.2.0", + "version": "0.2.1", "description": "Docker sandbox provider for TanStack AI — run harness adapters inside isolated Docker containers through the uniform SandboxHandle.", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox-local-process/CHANGELOG.md b/packages/ai-sandbox-local-process/CHANGELOG.md index 10197a8f0..ad4552b61 100644 --- a/packages/ai-sandbox-local-process/CHANGELOG.md +++ b/packages/ai-sandbox-local-process/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-sandbox-local-process +## 0.2.1 + +### Patch Changes + +- Updated dependencies [[`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.0 ### Minor Changes diff --git a/packages/ai-sandbox-local-process/package.json b/packages/ai-sandbox-local-process/package.json index ece8b6feb..deb668f9a 100644 --- a/packages/ai-sandbox-local-process/package.json +++ b/packages/ai-sandbox-local-process/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-local-process", - "version": "0.2.0", + "version": "0.2.1", "description": "Local-process sandbox provider for TanStack AI — runs the agent directly on the host through the uniform SandboxHandle (no isolation; trusted/dev use).", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox-sprites/CHANGELOG.md b/packages/ai-sandbox-sprites/CHANGELOG.md index 2ceeaad52..6da06251c 100644 --- a/packages/ai-sandbox-sprites/CHANGELOG.md +++ b/packages/ai-sandbox-sprites/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-sandbox-sprites +## 0.2.2 + +### Patch Changes + +- Updated dependencies [[`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.1 ### Patch Changes diff --git a/packages/ai-sandbox-sprites/package.json b/packages/ai-sandbox-sprites/package.json index 490659c65..5cee2b366 100644 --- a/packages/ai-sandbox-sprites/package.json +++ b/packages/ai-sandbox-sprites/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-sprites", - "version": "0.2.1", + "version": "0.2.2", "description": "Sprites sandbox provider for TanStack AI — run harness adapters inside isolated Fly.io Sprite stateful sandboxes through the uniform SandboxHandle.", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox-vercel/CHANGELOG.md b/packages/ai-sandbox-vercel/CHANGELOG.md index 0ca6cfc5a..488532d8d 100644 --- a/packages/ai-sandbox-vercel/CHANGELOG.md +++ b/packages/ai-sandbox-vercel/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-sandbox-vercel +## 0.2.1 + +### Patch Changes + +- Updated dependencies [[`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-sandbox@0.3.0 + ## 0.2.0 ### Minor Changes diff --git a/packages/ai-sandbox-vercel/package.json b/packages/ai-sandbox-vercel/package.json index 00c3cc1a4..baa8a79b8 100644 --- a/packages/ai-sandbox-vercel/package.json +++ b/packages/ai-sandbox-vercel/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox-vercel", - "version": "0.2.0", + "version": "0.2.1", "description": "Vercel Sandbox provider for TanStack AI — run harness adapters inside isolated Vercel microVM sandboxes through the uniform SandboxHandle.", "author": "", "license": "MIT", diff --git a/packages/ai-sandbox/CHANGELOG.md b/packages/ai-sandbox/CHANGELOG.md index 6f3ee0dc9..491dde28c 100644 --- a/packages/ai-sandbox/CHANGELOG.md +++ b/packages/ai-sandbox/CHANGELOG.md @@ -1,5 +1,43 @@ # @tanstack/ai-sandbox +## 0.3.0 + +### Minor Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Move multi-instance **locks** to `@tanstack/ai` under a dedicated `@tanstack/ai/locks` subpath, and nest persistence agent skills like `ai-core`. + - **`LockStore` / `InMemoryLockStore` / `LocksCapability` / `getLocks` / `provideLocks` / `withLocks`** live in `@tanstack/ai/locks` (not the main `@tanstack/ai` barrel, and not `@tanstack/ai-persistence`). + - `@tanstack/ai-sandbox` consumes the core `LocksCapability` token (no local lock re-export). + - The locks agent skill moves with the code: `ai-core/locks` in `@tanstack/ai`, not `ai-persistence/locks`. + - Agent skills under `@tanstack/ai-persistence` nest as `skills/ai-persistence/{stores,server,build-*-adapter}/`. + - Docs: locks guide under advanced middleware. + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - **Make every bundled Agent Skill discoverable by TanStack Intent.** + + Intent finds skills by scanning `node_modules` for packages that carry the + `tanstack-intent` keyword, and can only load what npm actually publishes. Three + packages shipped skills that failed one half of that contract: + - `@tanstack/ai-mcp` wrote its skill into a `skills/` directory that was missing + from `files`, so it was never published at all. + - `@tanstack/ai-memory` and `@tanstack/ai-sandbox` published their skills but + lacked the keyword, so Intent never looked at them. + + All three now publish `skills` and carry the keyword, matching `@tanstack/ai`, + `@tanstack/ai-code-mode`, and `@tanstack/ai-persistence`. + + The client persistence skill also moves from `@tanstack/ai-persistence` to + `@tanstack/ai` as `ai-core/client-persistence`. It teaches + `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` + and the `persistence` option on `useChat` — all of which live in the framework + packages, not in `@tanstack/ai-persistence`. An app doing browser-only + persistence never installs that package, so the guidance was unreachable for + exactly the people who needed it, and `ai-core` routed to a path that did not + exist on disk. Skills now follow the code that owns them. + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.2.4 ### Patch Changes diff --git a/packages/ai-sandbox/package.json b/packages/ai-sandbox/package.json index 09796516a..13633126e 100644 --- a/packages/ai-sandbox/package.json +++ b/packages/ai-sandbox/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-sandbox", - "version": "0.2.4", + "version": "0.3.0", "description": "Provider-agnostic sandbox layer for TanStack AI — run harness adapters inside isolated sandboxes (defineSandbox, defineWorkspace, withSandbox) with a uniform SandboxHandle, workspace bootstrap, policy, and resumable lifecycle.", "author": "", "license": "MIT", diff --git a/packages/ai-solid-ui/CHANGELOG.md b/packages/ai-solid-ui/CHANGELOG.md index 29c42b34b..c730f7393 100644 --- a/packages/ai-solid-ui/CHANGELOG.md +++ b/packages/ai-solid-ui/CHANGELOG.md @@ -1,5 +1,13 @@ # @tanstack/ai-solid-ui +## 0.7.15 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-client@0.23.0 + - @tanstack/ai-solid@0.16.0 + ## 0.7.14 ### Patch Changes diff --git a/packages/ai-solid-ui/package.json b/packages/ai-solid-ui/package.json index 17cdecd3b..5670e789d 100644 --- a/packages/ai-solid-ui/package.json +++ b/packages/ai-solid-ui/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-solid-ui", - "version": "0.7.14", + "version": "0.7.15", "description": "Headless Solid components for building TanStack AI chat interfaces with streamed message parts.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-solid/CHANGELOG.md b/packages/ai-solid/CHANGELOG.md index 1e502f29a..23801869e 100644 --- a/packages/ai-solid/CHANGELOG.md +++ b/packages/ai-solid/CHANGELOG.md @@ -1,5 +1,59 @@ # @tanstack/ai-solid +## 0.16.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.15.1 ### Patch Changes diff --git a/packages/ai-solid/package.json b/packages/ai-solid/package.json index 2518689b1..f03de7491 100644 --- a/packages/ai-solid/package.json +++ b/packages/ai-solid/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-solid", - "version": "0.15.1", + "version": "0.16.0", "description": "Solid hooks for TanStack AI streaming chat, structured outputs, and media generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-svelte/CHANGELOG.md b/packages/ai-svelte/CHANGELOG.md index 514279b95..44988f3cd 100644 --- a/packages/ai-svelte/CHANGELOG.md +++ b/packages/ai-svelte/CHANGELOG.md @@ -1,5 +1,59 @@ # @tanstack/ai-svelte +## 0.16.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.15.1 ### Patch Changes diff --git a/packages/ai-svelte/package.json b/packages/ai-svelte/package.json index ddb1e59b5..2c2606d6d 100644 --- a/packages/ai-svelte/package.json +++ b/packages/ai-svelte/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-svelte", - "version": "0.15.1", + "version": "0.16.0", "description": "Svelte 5 bindings for TanStack AI streaming chat, structured outputs, and media generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-vue-ui/CHANGELOG.md b/packages/ai-vue-ui/CHANGELOG.md index c8db6f736..f99f93eab 100644 --- a/packages/ai-vue-ui/CHANGELOG.md +++ b/packages/ai-vue-ui/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/ai-vue-ui +## 0.2.35 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai-vue@0.16.0 + ## 0.2.34 ### Patch Changes diff --git a/packages/ai-vue-ui/package.json b/packages/ai-vue-ui/package.json index 9036d8330..86801bccb 100644 --- a/packages/ai-vue-ui/package.json +++ b/packages/ai-vue-ui/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-vue-ui", - "version": "0.2.34", + "version": "0.2.35", "description": "Headless Vue components for building TanStack AI chat interfaces with streamed message parts.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai-vue/CHANGELOG.md b/packages/ai-vue/CHANGELOG.md index e7ed5fa20..bc83c9399 100644 --- a/packages/ai-vue/CHANGELOG.md +++ b/packages/ai-vue/CHANGELOG.md @@ -1,5 +1,59 @@ # @tanstack/ai-vue +## 0.16.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add browser-refresh durability to the `persistence` option. + + The client `persistence` adapter now stores one combined record per chat id, the message transcript plus a resume snapshot, so a full page reload restores the conversation, rehydrates any pending interrupt, and rejoins a run that was still streaming (via `joinRun`, when the connection is durability-backed). A bare `UIMessage[]` from an older store is still read for backward compatibility. + + **If you hand-rolled a `persistence` adapter, update its write path.** `setItem` now receives the combined `{ messages, resume? }` record where it used to receive a bare `UIMessage[]`, so an adapter that assumed an array will write the new shape and then fail to parse it back — and because adapter reads are best-effort, the failure is silent: the conversation simply does not restore. Read `{ messages, resume? }` in `getItem` (a bare array is still accepted), or switch to the `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` adapters below, which handle it for you. + + The `persistence` option also accepts `true` for a server-authoritative chat: the client caches nothing, and on mount it hydrates the thread from the server by its `threadId` (painting the stored transcript and tailing any run still generating). Use it to keep large transcripts off the client while the server stays authoritative for history; it needs a connection with a `hydrate` handler and a server GET endpoint (`reconstructChat`). Passing an adapter is client-authoritative; omitting `persistence` (or `false`) is ephemeral, in-memory only. + + New web storage adapters are exported for this: `localStoragePersistence`, `sessionStoragePersistence`, and `indexedDBPersistence` (plus `StorageUnavailableError` and the `ChatPersistedState` / `ChatStorageAdapter` / `ChatPersistenceOption` types). Because durability rides the existing `persistence` option, every framework integration (`react`, `solid`, `vue`, `svelte`, `angular`, `preact`) gets it with no framework-specific code. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - The chat hooks no longer take an `id` option — a hook's identity is its `threadId`. + + `useChat` / `createChat` previously accepted a separate `id` that keyed client + persistence and named the devtools instance, defaulting to a framework + `useId()` when omitted. That meant persistence keyed on an ephemeral render-tree + id even when you passed a stable `threadId`, so a reload found nothing under the + thread's key. + + Now the `threadId` is the single identity: + - The hooks drop the `id` option. Pass `threadId` to persist a conversation and + restore it on reload; omit it for an ephemeral chat. + - Persistence keys on `threadId` (unchanged in `ChatClient`, which already + resolved `id ?? threadId` — the hooks simply stop overriding it). + - `ChatClient.uniqueId` (the devtools instance id) now falls back to `threadId` + instead of a generated id, so a thread shows up in devtools under its own id. + - Changing `threadId` on a mounted `useChat` (react/preact/solid) now recreates + the client so the new thread takes effect; previously the change was ignored. + + `ChatClient` still accepts `id` directly as a lower-level escape hatch for + keying storage separately from the wire thread; only the framework hooks drop it. + + Migration: replace `useChat({ id })` with `useChat({ threadId })`. + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + - @tanstack/ai-client@0.23.0 + ## 0.15.1 ### Patch Changes diff --git a/packages/ai-vue/package.json b/packages/ai-vue/package.json index fc57375f0..abcce741b 100644 --- a/packages/ai-vue/package.json +++ b/packages/ai-vue/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai-vue", - "version": "0.15.1", + "version": "0.16.0", "description": "Vue composables for TanStack AI streaming chat, structured outputs, and media generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index a95900586..f5ab0e5c5 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,5 +1,280 @@ # @tanstack/ai +## 0.43.0 + +### Minor Changes + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Adopt the AG-UI interrupt lifecycle for tool approvals, generic responses, and + client-tool execution, with typed bound resolvers, atomic batches, and + structured errors. Interrupts run ephemerally by resuming from the full client + message history in a fresh child run — no persistence required. + + This changes native approval and client-tool streams from legacy custom events + to snapshot-plus-`RUN_FINISHED` interrupt outcomes. Deprecated + `pendingInterrupts`, `addToolApprovalResponse`, raw `resumeInterrupts`, and + legacy event readers remain as limited compatibility surfaces for migration; + `addToolResult` remains supported. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Add `defineLock` to `@tanstack/ai/locks`: an identity typer for a `LockStore` + implementation, matching the `define*Store` helpers in `@tanstack/ai-persistence`. + Pass a `withLock` object and get autocomplete and contract checking inline, with + no `: LockStore` annotation, then hand it to `withLocks`. + + ```ts + import { defineLock, withLocks } from '@tanstack/ai/locks' + + const locks = defineLock({ + async withLock(key, fn) { + const { release, signal } = await acquire(key) + try { + return await fn(signal) + } finally { + release() + } + }, + }) + + const middleware = [withLocks(locks)] + ``` + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Make a reload rejoin fast, robust, and repeatable. + - **`memoryStream` first-chunk deadline now defaults to 100ms** (was 30s). The + common from-start join is a reload rejoining a run whose producer ran in a + prior request: an in-flight run's log already holds chunks (it streams + immediately, the deadline never applies), and an empty log means the run is + gone — so failing fast lets the client re-enable input near-instantly instead + of holding a dead connection open. Raise `firstChunkDeadlineMs` for a backend + whose producer can legitimately start well after a joiner attaches. + - **`ChatClient` reload rejoin hardened:** it bounds the wait for the first + chunk and clears a dead resume pointer (so a stale pointer can't pin the UI in + a loading state and can't be retried on the next load); it drops the hydrated + in-flight partial only when real content arrives (never on `RUN_STARTED` + alone), so a rejoin that connects but delivers nothing can't leave an empty + assistant bubble; and it no longer lets a replayed `RUN_STARTED` (which + carries the provider run id) overwrite the persisted resume pointer with an id + the durability log isn't keyed by — so a SECOND consecutive reload still + re-attaches and continues. + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Make interrupt ownership explicit rather than assumed. + + An AG-UI `Interrupt` is a shared envelope — a workflow engine's durable + approval or another agent framework's pause can arrive on the same stream. What + makes a pause resumable through `chat()` is the binding this package attaches + under `tanstack:interruptBinding`. + - Interrupts that carry no binding this client understands now surface as + `kind: 'unbound'` with `canResolve: false`, instead of being given a + synthesized binding and rendered as resolvable generic interrupts. Resolving + those produced an answer submitted against a run with nothing pending, which + failed as `unknown-interrupt` only after the user had filled in the form. + Unbound items never block submission of the interrupts that are yours. + - The binding carries a wire version (`INTERRUPT_BINDING_VERSION`). Readers + reject a version they don't recognise rather than duck-typing its fields. A + binding written before the field existed is still read. + - `INTERRUPT_BINDING_METADATA_KEY`, `withInterruptBinding()` and + `readInterruptBinding()` are exported, so anything producing an interrupt this + package must later resume attaches the binding through a supported API + instead of copying the metadata key. + - Interrupt classification is driven by the binding alone. `Interrupt.reason` is + free-form AG-UI text another producer can also use, so it is now a display + hint only and never decides ownership. + - The interrupt protocol surface is enumerated instead of `export *`. The + unimplemented durable-recovery contract (`InterruptRecoveryStateV1`, + `InterruptRecoveryQuery`, the never-called `loadInterruptState` adapter hook, + and the `persistence-required` / `atomic-commit-unsupported` / + `recovery-unavailable` error codes) is removed rather than published. + +- [#970](https://github.com/TanStack/ai/pull/970) [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a) - Interrupts: the application owns wire-schema validation, and the hashing + dependency is gone. + + The library no longer transforms a generic interrupt's wire JSON Schema into a + validator or validates the resolved value against it, on either the client or + the server. Whatever you pass to `resolveInterrupt` (client) or send in the + `resume` batch (server) flows through as-is. Validate it yourself if you need to + trust it, e.g. with `z.fromJSONSchema(interrupt.responseSchema).safeParse(value)` + on the client and your own check on the server. Validation of a tool's + code-authored Standard Schema (`approvalSchema` / `inputSchema`) is unchanged. + + This drops the `ajv` and `ajv-formats` dependencies. Interrupt binding hashes and + resolution fingerprints now use a small bundled SHA-256 instead of + `@noble/hashes`, so that dependency is gone too. The wire hash shape + (`sha256:`) is unchanged. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Move multi-instance **locks** to `@tanstack/ai` under a dedicated `@tanstack/ai/locks` subpath, and nest persistence agent skills like `ai-core`. + - **`LockStore` / `InMemoryLockStore` / `LocksCapability` / `getLocks` / `provideLocks` / `withLocks`** live in `@tanstack/ai/locks` (not the main `@tanstack/ai` barrel, and not `@tanstack/ai-persistence`). + - `@tanstack/ai-sandbox` consumes the core `LocksCapability` token (no local lock re-export). + - The locks agent skill moves with the code: `ai-core/locks` in `@tanstack/ai`, not `ai-persistence/locks`. + - Agent skills under `@tanstack/ai-persistence` nest as `skills/ai-persistence/{stores,server,build-*-adapter}/`. + - Docs: locks guide under advanced middleware. + +- [#541](https://github.com/TanStack/ai/pull/541) [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4) - **Add server-side memory via a `recall`/`save` adapter contract in `@tanstack/ai-memory`.** + + Memory is now a single, provider-agnostic contract with two verbs — `recall` and + `save` — which is the shape every memory backend (in-process, Redis, and hosted + vendors) naturally exposes. `memoryMiddleware` recalls relevant memory into the + system prompt (and optionally injects vendor tools) before the model runs, then + defers `save` of the finished turn via `ctx.defer` so streaming is never blocked. + Extraction, ranking, and rendering live inside each adapter — the middleware is thin. + + `@tanstack/ai-memory` (new package) — everything ships here: + - Root: `memoryMiddleware`, the `MemoryAdapter` contract + (`recall` / `save` / optional `inspect` / `listFacts`), and the `MemoryScope` / + `MemoryTurn` / `RecallResult` / `SaveReceipt` types. + - `@tanstack/ai-memory/in-memory` → `inMemory()` — zero-dependency adapter for dev, + tests, and single-process demos. Pass an `embedder` for semantic scoring and/or an + `extract` function to persist derived facts. + - `@tanstack/ai-memory/redis` → `redis({ redis, prefix? })` — production adapter for + plain Redis. `ioredis` wires in directly; `redis` (node-redis v4+) via the + `fromNodeRedis(client)` wrapper. Both are optional peer dependencies. + - `@tanstack/ai-memory/hindsight` → `hindsight()`, `@tanstack/ai-memory/mem0` → + `mem0()`, `@tanstack/ai-memory/honcho` → `honcho()` — hosted-vendor adapters. Their + SDKs (`@vectorize-io/hindsight-client`, `@honcho-ai/sdk`) are optional peers loaded + lazily; mem0 talks to its server over plain HTTP (no SDK). Vendors can expose LLM + tools through `recall` (e.g. hindsight's retain/recall/reflect). + - A shared `recall`/`save` contract-test suite (`@tanstack/ai-memory/tests/contract`) + that any adapter — including third-party ones — can run. + + `@tanstack/ai`: + - **Removes the (unreleased) `@tanstack/ai/memory` subpath.** The middleware, + contract, and helpers all moved to `@tanstack/ai-memory`. + + `@tanstack/ai-event-client`: + - The five `memory:*` devtools events (`memory:retrieve:started` / `:completed`, + `memory:persist:started` / `:completed`, `memory:error`) now carry recall/save + payloads (adapter id, fragment/receipt counts, `phase: 'recall' | 'save'`). + +- [#955](https://github.com/TanStack/ai/pull/955) [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288) - Resumable streams: reconnect to an in-flight SSE **or NDJSON** response without + re-running the provider. + + `toServerSentEventsResponse` and `toHttpResponse` both accept a + `durability: { adapter, batch }` option. The adapter (`StreamDurability`) + records every chunk to an ordered log before delivery and tags each event with + an opaque, adapter-owned offset — an SSE `id:` line, or the `id` of an NDJSON + `{ id, chunk }` envelope (NDJSON has no native event-id). A reconnect + (`Last-Event-ID`) or an explicit `?offset` read replays strictly after that + offset from the log — the lazy provider stream is never iterated on resume. + Producers terminalize the log on cancellation and failure (`RUN_ERROR` append + - `close()`) and on completion when the source stream emits its own terminal + event (`chat()` always does), so readers are never parked on a dead run. + + Two adapters ship: `memoryStream(request)` in `@tanstack/ai` (process-local, + for development and tests) and the new `@tanstack/ai-durable-stream` package, + a Durable Streams protocol adapter for production backends. + + For the `GET` handler that a reload or a second tab reconnects to, + `resumeServerSentEventsResponse({ adapter })` and `resumeHttpResponse({ adapter })` + replay a run straight from the durability log. They need no producer stream and + return a 400 when the request carries no resume offset. + + On the client, all four HTTP adapters are now resumable — `fetchServerSentEvents`, + `fetchHttpStream`, `xhrServerSentEvents`, and `xhrHttpStream`. Each tracks the + per-event offset, auto-reconnects with `Last-Event-ID`, de-duplicates the + replayed prefix, and exposes `joinRun(runId)` to attach to an in-flight or + finished run from the start (read-only GET with `offset=-1`). Untagged streams + behave exactly as before. A durable run that ends with no terminal event and no + forward progress now throws `DurableStreamIncompleteError` instead of hanging. + + Reconnection and durability are bounded so failures surface rather than hang or + loop: + - `memoryStream` evicts completed logs after a grace window (unbounded growth + is gone); resuming an expired/unknown run throws, and a from-start join to a + run that never produces fails after `MemoryStreamOptions.firstChunkDeadlineMs`. + - all four HTTP adapters accept `reconnect: { maxAttempts, delayMs }` — a + throttle plus a ceiling on CONSECUTIVE no-progress reconnects (default 5; + forward progress resets it) that fails with the new `StreamReconnectLimitError` + instead of reconnecting endlessly, without penalizing a healthy long-lived run. + - `durableStream` accepts `reconnect: { maxReadFailures, delayMs }` to bound its + read-retry loop, and `server` is now optional when `fetch` is provided (e.g. a + Cloudflare service binding). + - `toServerSentEventsResponse` accepts `debug` to record durability terminal / + close failures server-side, where a replaying joiner cannot observe them. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Make a mid-stream reload resume the same conversation cleanly. + - `withPersistence` now persists the pending turn at the start of a run (so a + reload during generation still shows the user's message), stamps each + assistant turn with its stream `messageId`, and accepts + `withPersistence(persistence, { snapshotStreaming: true })` to also persist the + in-progress reply on a throttled interval (`snapshotIntervalMs`, default + `1000`) for partial-output durability. + - `ModelMessage` gains an optional `id`; `modelMessagesToUIMessages` preserves + it, so a hydrated message keeps the same identity as its live stream. + - On reload, the chat client rebuilds an in-flight assistant turn from the + delivery log (replaying from the start and applying the buffered backlog in one + batch) instead of reconciling against the persisted partial, so the reload + shows one clean bubble that catches up and continues rather than a frozen or + duplicated partial. + +- [#980](https://github.com/TanStack/ai/pull/980) [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa) - **Add a shared `Scope` identity type to `@tanstack/ai`.** + + `Scope` is the single identity/isolation vocabulary for the subsystems that + persist or recall per-conversation data — `@tanstack/ai-persistence` and + `@tanstack/ai-memory`. Rather than each subsystem inventing its own notion of + "whose data is this?", both import one type: + + ```ts + interface Scope { + threadId: string // required — the single conversation key (same as ctx.threadId) + userId?: string // durable end-user identity; required in practice for multi-user apps + tenantId?: string // multi-tenant boundary + namespace?: string // reserved logical partition; no subsystem keys on it yet + } + ``` + + `threadId` is the one conversation key across the codebase (matching + `ChatMiddlewareContext.threadId`, with `conversationId` already deprecated in + favor of it) — subsystems must not introduce a second name (`sessionId`, …) for + the same concept. Every field is an isolation boundary and must be derived + server-side from trusted session state, never from client input. + + Introduced ahead of the persistence and memory packages so both share one settled + identity contract. `@tanstack/ai-memory` now aliases `MemoryScope` to `Scope` + (see the memory-scope-threadid changeset). + +### Patch Changes + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - Fix `memoryStream` truncating a tool-calling (agent-loop) run at its first tool + call. + + An agent-loop run emits one `RUN_STARTED`/`RUN_FINISHED` pair per iteration + (`finishReason: "tool_calls"` for a turn that calls a tool, then `"stop"` for the + final answer). `memoryStream` treated the _first_ terminal chunk as the end of + the log — both marking the log complete on append and ending the reader on read — + so a run that called a tool was delivered only up to that first `RUN_FINISHED`: + the tool result and everything after (the model's actual answer) never reached + the client, leaving the tool call stuck "running" and the reply missing, on the + initial stream and on any reconnect/reload. + + Completion is now driven solely by the producer calling `close()` (which it does + on every exit — the documented `StreamDurability.close` contract, honored by + `toServerSentEventsResponse`/`resumeServerSentEventsResponse` and detached + producers). The reader tails across per-iteration terminals and ends when the + producer closes, so a tool-calling run is delivered in full — live, on rejoin, + and on a server-authoritative reload. + +- [#984](https://github.com/TanStack/ai/pull/984) [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a) - **Make every bundled Agent Skill discoverable by TanStack Intent.** + + Intent finds skills by scanning `node_modules` for packages that carry the + `tanstack-intent` keyword, and can only load what npm actually publishes. Three + packages shipped skills that failed one half of that contract: + - `@tanstack/ai-mcp` wrote its skill into a `skills/` directory that was missing + from `files`, so it was never published at all. + - `@tanstack/ai-memory` and `@tanstack/ai-sandbox` published their skills but + lacked the keyword, so Intent never looked at them. + + All three now publish `skills` and carry the keyword, matching `@tanstack/ai`, + `@tanstack/ai-code-mode`, and `@tanstack/ai-persistence`. + + The client persistence skill also moves from `@tanstack/ai-persistence` to + `@tanstack/ai` as `ai-core/client-persistence`. It teaches + `localStoragePersistence` / `sessionStoragePersistence` / `indexedDBPersistence` + and the `persistence` option on `useChat` — all of which live in the framework + packages, not in `@tanstack/ai-persistence`. An app doing browser-only + persistence never installs that package, so the guidance was unreachable for + exactly the people who needed it, and `ai-core` routed to a path that did not + exist on disk. Skills now follow the code that owns them. + +- Updated dependencies [[`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371)]: + - @tanstack/ai-event-client@0.7.0 + ## 0.42.0 ### Minor Changes diff --git a/packages/ai/package.json b/packages/ai/package.json index 23284ece9..2fd80af3a 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/ai", - "version": "0.42.0", + "version": "0.43.0", "description": "Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/openai-base/CHANGELOG.md b/packages/openai-base/CHANGELOG.md index 16a2b786a..20051dbe4 100644 --- a/packages/openai-base/CHANGELOG.md +++ b/packages/openai-base/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/openai-base +## 0.9.10 + +### Patch Changes + +- Updated dependencies [[`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`3301398`](https://github.com/TanStack/ai/commit/330139878958fc5c5c167a69347c884fa35b792a), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`7c7aa09`](https://github.com/TanStack/ai/commit/7c7aa09a7402b45e6285ebc78a606131aec3e288), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a), [`4ce7600`](https://github.com/TanStack/ai/commit/4ce7600d5b543d4b7e3bd6d63cdf5ecf91cdeeaa), [`4ab149f`](https://github.com/TanStack/ai/commit/4ab149fd46a1cf55691266cdd118fdc9999c0b2a)]: + - @tanstack/ai@0.43.0 + ## 0.9.9 ### Patch Changes diff --git a/packages/openai-base/package.json b/packages/openai-base/package.json index 63532ef4e..eb9241884 100644 --- a/packages/openai-base/package.json +++ b/packages/openai-base/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/openai-base", - "version": "0.9.9", + "version": "0.9.10", "description": "Shared OpenAI SDK base adapters for TanStack AI providers using Chat Completions and Responses APIs.", "author": "Tanner Linsley", "license": "MIT", diff --git a/packages/preact-ai-devtools/CHANGELOG.md b/packages/preact-ai-devtools/CHANGELOG.md index adf1ffa56..fa87087e4 100644 --- a/packages/preact-ai-devtools/CHANGELOG.md +++ b/packages/preact-ai-devtools/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/preact-ai-devtools +## 0.1.68 + +### Patch Changes + +- Updated dependencies [[`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371)]: + - @tanstack/ai-devtools-core@0.5.0 + ## 0.1.67 ### Patch Changes diff --git a/packages/preact-ai-devtools/package.json b/packages/preact-ai-devtools/package.json index c33f8246f..dbe39533d 100644 --- a/packages/preact-ai-devtools/package.json +++ b/packages/preact-ai-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/preact-ai-devtools", - "version": "0.1.67", + "version": "0.1.68", "description": "Preact Devtools plugin for inspecting TanStack AI chat messages, tool calls, streams, and errors.", "author": "tannerlinsley", "license": "MIT", diff --git a/packages/react-ai-devtools/CHANGELOG.md b/packages/react-ai-devtools/CHANGELOG.md index 7f137cae6..a150d0bb9 100644 --- a/packages/react-ai-devtools/CHANGELOG.md +++ b/packages/react-ai-devtools/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/react-ai-devtools +## 0.2.68 + +### Patch Changes + +- Updated dependencies [[`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371)]: + - @tanstack/ai-devtools-core@0.5.0 + ## 0.2.67 ### Patch Changes diff --git a/packages/react-ai-devtools/package.json b/packages/react-ai-devtools/package.json index 18dc96f51..fabdc3642 100644 --- a/packages/react-ai-devtools/package.json +++ b/packages/react-ai-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-ai-devtools", - "version": "0.2.67", + "version": "0.2.68", "description": "React Devtools plugin for inspecting TanStack AI chat messages, tool calls, streams, and errors.", "author": "tannerlinsley", "license": "MIT", diff --git a/packages/solid-ai-devtools/CHANGELOG.md b/packages/solid-ai-devtools/CHANGELOG.md index b0b43c73c..6f34f18f6 100644 --- a/packages/solid-ai-devtools/CHANGELOG.md +++ b/packages/solid-ai-devtools/CHANGELOG.md @@ -1,5 +1,12 @@ # @tanstack/solid-ai-devtools +## 0.2.68 + +### Patch Changes + +- Updated dependencies [[`347b61b`](https://github.com/TanStack/ai/commit/347b61bc788bb816bbd12287c1a426ca7def00f4), [`cc88874`](https://github.com/TanStack/ai/commit/cc88874ecb0639daa1f8a8c32be5dcc9b2749371)]: + - @tanstack/ai-devtools-core@0.5.0 + ## 0.2.67 ### Patch Changes diff --git a/packages/solid-ai-devtools/package.json b/packages/solid-ai-devtools/package.json index 492ed6a9a..85cf57124 100644 --- a/packages/solid-ai-devtools/package.json +++ b/packages/solid-ai-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/solid-ai-devtools", - "version": "0.2.67", + "version": "0.2.68", "description": "Solid Devtools plugin for inspecting TanStack AI chat messages, tool calls, streams, and errors.", "author": "Tanner Linsley", "license": "MIT",