[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-tanstack-ai-persistenceserver":3,"mdc-qq0sk9-key":53,"related-repo-tanstack-ai-persistenceserver":2141,"related-org-tanstack-ai-persistenceserver":2241},{"slug":4,"name":5,"fn":6,"description":7,"org":8,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":48,"sourceUrl":51,"mdContent":52},"ai-persistenceserver","ai-persistence\u002Fserver","configure server-side chat state for TanStack AI","Server chat state with withPersistence from @tanstack\u002Fai-persistence. Authoritative transcript, run lifecycle, durable interrupts\u002Fapprovals, chatParamsFromRequest, reconstructChat, snapshotStreaming. Use when the server owns history, multi-device, or durable tool approvals. NOT client localStorage (see ai-core\u002Fclient-persistence in @tanstack\u002Fai) and NOT stream reconnect alone.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},"tanstack","TanStack","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Ftanstack.png",[13,17,20,23],{"name":14,"slug":15,"type":16},"Backend","backend","tag",{"name":18,"slug":19,"type":16},"AI","ai",{"name":21,"slug":22,"type":16},"Persistence","persistence",{"name":10,"slug":9,"type":16},2884,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Fai","2026-07-30T05:53:29.989036",null,269,[19,30,31,32,33,34,35,36,37,38,39,40,41,42,43,9,44,45,46,47],"ai-agents","ai-sdk","anthropic","chatbot","function-calling","gemini","generative-ai","llm","multimodal","openai","react","solidjs","streaming","svelte","tool-calling","typescript","typescript-sdk","vue",{"repoUrl":25,"stars":24,"forks":28,"topics":49,"description":50},[19,30,31,32,33,34,35,36,37,38,39,40,41,42,43,9,44,45,46,47],"🤖 Type-safe, provider-agnostic TypeScript AI SDK for streaming chat, tool calling, agents, and multimodal apps across OpenAI, Anthropic, Gemini, React, Vue, Svelte, and Solid.","https:\u002F\u002Fgithub.com\u002FTanStack\u002Fai\u002Ftree\u002FHEAD\u002Fpackages\u002Fai-persistence\u002Fskills\u002Fai-persistence\u002Fserver","---\nname: ai-persistence\u002Fserver\ndescription: >\n  Server chat state with withPersistence from @tanstack\u002Fai-persistence.\n  Authoritative transcript, run lifecycle, durable interrupts\u002Fapprovals,\n  chatParamsFromRequest, reconstructChat, snapshotStreaming. Use when the\n  server owns history, multi-device, or durable tool approvals. NOT client\n  localStorage (see ai-core\u002Fclient-persistence in @tanstack\u002Fai) and NOT\n  stream reconnect\n  alone.\ntype: sub-skill\nlibrary: tanstack-ai\nlibrary_version: '0.0.0'\nsources:\n  - 'TanStack\u002Fai:docs\u002Fpersistence\u002Fchat-persistence.md'\n  - 'TanStack\u002Fai:docs\u002Fpersistence\u002Foverview.md'\n  - 'TanStack\u002Fai:docs\u002Fpersistence\u002Fcontrols.md'\n---\n\n# Server Chat Persistence\n\n> Builds on **ai-persistence**. Package: `@tanstack\u002Fai-persistence`.\n\n`withPersistence(persistence)` is a `ChatMiddleware` that writes chat **state**\nto a backend: messages, runs, interrupts (optional metadata). It does not\nmutate the chunk stream and does not replace delivery durability.\n\n## Setup\n\n```ts\nimport {\n  chat,\n  chatParamsFromRequest,\n  toServerSentEventsResponse,\n} from '@tanstack\u002Fai'\nimport { openaiText } from '@tanstack\u002Fai-openai'\nimport { withPersistence } from '@tanstack\u002Fai-persistence'\n\u002F\u002F Your adapter — see ai-persistence\u002Fstores.\nimport { persistence } from '.\u002Fpersistence'\n\nexport async function POST(request: Request) {\n  const params = await chatParamsFromRequest(request)\n  const stream = chat({\n    adapter: openaiText('gpt-5.5'),\n    messages: params.messages,\n    threadId: params.threadId,\n    runId: params.runId,\n    ...(params.resume ? { resume: params.resume } : {}),\n    middleware: [withPersistence(persistence)],\n  })\n  return toServerSentEventsResponse(stream)\n}\n```\n\nAlways pass `threadId` and `runId` from the client (via\n`chatParamsFromRequest` \u002F body helpers). Forward `resume` when the client\nresolves pending interrupts.\n\nFor dev and tests, `memoryPersistence()` from `@tanstack\u002Fai-persistence` is a\ndrop-in backend that implements all four stores in process.\n\n## What each store does\n\n| Store        | Role                                    | Required?                                 |\n| ------------ | --------------------------------------- | ----------------------------------------- |\n| `messages`   | Full model-message transcript load\u002Fsave | **Yes** for `withPersistence`             |\n| `runs`       | Run status, timing, usage, errors       | Optional; needed for interrupt durability |\n| `interrupts` | Pending\u002Fresolved tool approvals & waits | Optional; **requires** `runs`             |\n| `metadata`   | App-owned namespaced key\u002Fvalue          | Optional                                  |\n\nNamed shapes: `ChatTranscriptPersistence` (floor), `ChatPersistence` (all four).\n**Annotate your factory with one of these**, not with bare `AIPersistence` —\nthe unparameterized type is the all-optional bag, and `withPersistence` rejects\nit because `stores.messages` is possibly `undefined`.\n\n## Authoritative-history contract\n\n- **Non-empty `messages`** → finish **overwrites** the stored thread with that\n  array. Post the **complete** transcript, never a delta.\n- **Empty `messages`** → middleware **loads** the stored thread and continues.\n\n## When state is written\n\n| Moment             | Writes                                                            | Best-effort?                     |\n| ------------------ | ----------------------------------------------------------------- | -------------------------------- |\n| `onStart`          | Pending turn snapshot (user + history)                            | Yes — failure does not abort     |\n| Interrupt boundary | New interrupts, run → `interrupted`, message snapshot             | No                               |\n| `onFinish`         | Full transcript **first**, then run → `completed`, commit resumes | No                               |\n| Stream (optional)  | Throttled partial assistant text                                  | Yes if `snapshotStreaming: true` |\n| `onError`          | Run → `failed`                                                    | Resumes stay pending             |\n| `onAbort`          | Run → `interrupted`                                               | Resumes stay pending             |\n\n```ts\nwithPersistence(persistence, {\n  snapshotStreaming: true,\n  snapshotIntervalMs: 1000, \u002F\u002F default\n})\n```\n\nStreaming snapshots default **off** (finish is authoritative). Enable only when\npartial-output durability is worth extra writes.\n\nResumes accepted in `onConfig` commit only at a success boundary (interrupt or\nfinish). A failed run leaves interrupts pending so the same resume batch can\nretry.\n\n## Interrupt \u002F resume flow\n\n1. Middleware records pending interrupts and **gates** new input: if pending\n   exist, the request must include a matching `resume` batch or `onConfig`\n   throws.\n2. On valid resume, middleware builds `resumeToolState` and clears\n   `config.resume` so the engine does not double-reconstruct from client\n   history (server owns transcript).\n3. On success boundary, interrupts are marked resolved\u002Fcancelled.\n\n## Hydrate a thread for the client (`reconstructChat`)\n\nServer-authoritative clients load history by `threadId` (often `GET`):\n\n```ts\nimport { reconstructChat } from '@tanstack\u002Fai-persistence'\n\nexport async function GET(request: Request) {\n  return reconstructChat(persistence, request, {\n    \u002F\u002F Multi-user: required in production\n    authorize: async (threadId, req) => {\n      const userId = await sessionUserId(req)\n      return userOwnsThread(userId, threadId)\n    },\n  })\n}\n```\n\nReturns `{ messages, activeRun, interrupts }`:\n\n- `messages` — UI messages for paint\n- `activeRun` — `{ runId }` if a run is still generating (`runs.findActiveRun`)\n- `interrupts` — pending human-in-the-loop state for re-prompt\n\n**Without `authorize`, anyone who guesses `?threadId=` gets the transcript.**\n\n## Generation activities\n\n`withGenerationPersistence(persistence)` tracks run records for non-chat\nactivities (image, audio, TTS, video, transcription). Do not fake\n`threadId = requestId` on chat run stores — use the generation helper.\n\n## Common mistakes\n\n### CRITICAL: Posting a message delta as `messages`\n\nWipes the stored thread down to that delta. Always send full history or `[]`.\n\n### HIGH: Omitting `threadId` \u002F `runId`\n\nPersistence keys and resume need stable ids. Use `chatParamsFromRequest`.\n\n### HIGH: Interrupts without `runs`\n\n`interrupts` requires `runs`; `withPersistence` throws otherwise.\n\n### HIGH: Typing a factory as bare `AIPersistence`\n\n`AIPersistence` defaults to the sparse all-optional bag, so `withPersistence`\nand `reconstructChat` reject the value. Return `ChatPersistence` (or\n`ChatTranscriptPersistence`) instead.\n\n### MEDIUM: Expecting `withPersistence` to reconnect a dropped stream\n\nThat is delivery durability (resumable streams), not state persistence.\n\n## Cross-references\n\n- **ai-persistence** — layers and recommended stack\n- **ai-persistence\u002Fstores** — implement the store interfaces\n- **ai-core\u002Fclient-persistence** (`@tanstack\u002Fai`) — browser half\n- **ai-core\u002Flocks** — multi-instance coordination\n",{"data":54,"body":62},{"name":5,"description":7,"type":55,"library":56,"library_version":57,"sources":58},"sub-skill","tanstack-ai","0.0.0",[59,60,61],"TanStack\u002Fai:docs\u002Fpersistence\u002Fchat-persistence.md","TanStack\u002Fai:docs\u002Fpersistence\u002Foverview.md","TanStack\u002Fai:docs\u002Fpersistence\u002Fcontrols.md",{"type":63,"children":64},"root",[65,74,101,127,134,801,835,855,861,1003,1061,1067,1123,1129,1317,1405,1417,1430,1436,1492,1505,1525,1810,1822,1871,1895,1901,1920,1926,1938,1950,1968,1979,1990,2014,2025,2063,2076,2081,2087,2135],{"type":66,"tag":67,"props":68,"children":70},"element","h1",{"id":69},"server-chat-persistence",[71],{"type":72,"value":73},"text","Server Chat Persistence",{"type":66,"tag":75,"props":76,"children":77},"blockquote",{},[78],{"type":66,"tag":79,"props":80,"children":81},"p",{},[82,84,90,92,99],{"type":72,"value":83},"Builds on ",{"type":66,"tag":85,"props":86,"children":87},"strong",{},[88],{"type":72,"value":89},"ai-persistence",{"type":72,"value":91},". Package: ",{"type":66,"tag":93,"props":94,"children":96},"code",{"className":95},[],[97],{"type":72,"value":98},"@tanstack\u002Fai-persistence",{"type":72,"value":100},".",{"type":66,"tag":79,"props":102,"children":103},{},[104,110,112,118,120,125],{"type":66,"tag":93,"props":105,"children":107},{"className":106},[],[108],{"type":72,"value":109},"withPersistence(persistence)",{"type":72,"value":111}," is a ",{"type":66,"tag":93,"props":113,"children":115},{"className":114},[],[116],{"type":72,"value":117},"ChatMiddleware",{"type":72,"value":119}," that writes chat ",{"type":66,"tag":85,"props":121,"children":122},{},[123],{"type":72,"value":124},"state",{"type":72,"value":126},"\nto a backend: messages, runs, interrupts (optional metadata). It does not\nmutate the chunk stream and does not replace delivery durability.",{"type":66,"tag":128,"props":129,"children":131},"h2",{"id":130},"setup",[132],{"type":72,"value":133},"Setup",{"type":66,"tag":135,"props":136,"children":141},"pre",{"className":137,"code":138,"language":139,"meta":140,"style":140},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import {\n  chat,\n  chatParamsFromRequest,\n  toServerSentEventsResponse,\n} from '@tanstack\u002Fai'\nimport { openaiText } from '@tanstack\u002Fai-openai'\nimport { withPersistence } from '@tanstack\u002Fai-persistence'\n\u002F\u002F Your adapter — see ai-persistence\u002Fstores.\nimport { persistence } from '.\u002Fpersistence'\n\nexport async function POST(request: Request) {\n  const params = await chatParamsFromRequest(request)\n  const stream = chat({\n    adapter: openaiText('gpt-5.5'),\n    messages: params.messages,\n    threadId: params.threadId,\n    runId: params.runId,\n    ...(params.resume ? { resume: params.resume } : {}),\n    middleware: [withPersistence(persistence)],\n  })\n  return toServerSentEventsResponse(stream)\n}\n","ts","",[142],{"type":66,"tag":93,"props":143,"children":144},{"__ignoreMap":140},[145,163,178,191,204,234,274,311,321,359,369,426,469,500,543,573,603,633,712,752,765,792],{"type":66,"tag":146,"props":147,"children":150},"span",{"class":148,"line":149},"line",1,[151,157],{"type":66,"tag":146,"props":152,"children":154},{"style":153},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[155],{"type":72,"value":156},"import",{"type":66,"tag":146,"props":158,"children":160},{"style":159},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[161],{"type":72,"value":162}," {\n",{"type":66,"tag":146,"props":164,"children":166},{"class":148,"line":165},2,[167,173],{"type":66,"tag":146,"props":168,"children":170},{"style":169},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[171],{"type":72,"value":172},"  chat",{"type":66,"tag":146,"props":174,"children":175},{"style":159},[176],{"type":72,"value":177},",\n",{"type":66,"tag":146,"props":179,"children":181},{"class":148,"line":180},3,[182,187],{"type":66,"tag":146,"props":183,"children":184},{"style":169},[185],{"type":72,"value":186},"  chatParamsFromRequest",{"type":66,"tag":146,"props":188,"children":189},{"style":159},[190],{"type":72,"value":177},{"type":66,"tag":146,"props":192,"children":194},{"class":148,"line":193},4,[195,200],{"type":66,"tag":146,"props":196,"children":197},{"style":169},[198],{"type":72,"value":199},"  toServerSentEventsResponse",{"type":66,"tag":146,"props":201,"children":202},{"style":159},[203],{"type":72,"value":177},{"type":66,"tag":146,"props":205,"children":207},{"class":148,"line":206},5,[208,213,218,223,229],{"type":66,"tag":146,"props":209,"children":210},{"style":159},[211],{"type":72,"value":212},"}",{"type":66,"tag":146,"props":214,"children":215},{"style":153},[216],{"type":72,"value":217}," from",{"type":66,"tag":146,"props":219,"children":220},{"style":159},[221],{"type":72,"value":222}," '",{"type":66,"tag":146,"props":224,"children":226},{"style":225},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[227],{"type":72,"value":228},"@tanstack\u002Fai",{"type":66,"tag":146,"props":230,"children":231},{"style":159},[232],{"type":72,"value":233},"'\n",{"type":66,"tag":146,"props":235,"children":237},{"class":148,"line":236},6,[238,242,247,252,257,261,265,270],{"type":66,"tag":146,"props":239,"children":240},{"style":153},[241],{"type":72,"value":156},{"type":66,"tag":146,"props":243,"children":244},{"style":159},[245],{"type":72,"value":246}," {",{"type":66,"tag":146,"props":248,"children":249},{"style":169},[250],{"type":72,"value":251}," openaiText",{"type":66,"tag":146,"props":253,"children":254},{"style":159},[255],{"type":72,"value":256}," }",{"type":66,"tag":146,"props":258,"children":259},{"style":153},[260],{"type":72,"value":217},{"type":66,"tag":146,"props":262,"children":263},{"style":159},[264],{"type":72,"value":222},{"type":66,"tag":146,"props":266,"children":267},{"style":225},[268],{"type":72,"value":269},"@tanstack\u002Fai-openai",{"type":66,"tag":146,"props":271,"children":272},{"style":159},[273],{"type":72,"value":233},{"type":66,"tag":146,"props":275,"children":277},{"class":148,"line":276},7,[278,282,286,291,295,299,303,307],{"type":66,"tag":146,"props":279,"children":280},{"style":153},[281],{"type":72,"value":156},{"type":66,"tag":146,"props":283,"children":284},{"style":159},[285],{"type":72,"value":246},{"type":66,"tag":146,"props":287,"children":288},{"style":169},[289],{"type":72,"value":290}," withPersistence",{"type":66,"tag":146,"props":292,"children":293},{"style":159},[294],{"type":72,"value":256},{"type":66,"tag":146,"props":296,"children":297},{"style":153},[298],{"type":72,"value":217},{"type":66,"tag":146,"props":300,"children":301},{"style":159},[302],{"type":72,"value":222},{"type":66,"tag":146,"props":304,"children":305},{"style":225},[306],{"type":72,"value":98},{"type":66,"tag":146,"props":308,"children":309},{"style":159},[310],{"type":72,"value":233},{"type":66,"tag":146,"props":312,"children":314},{"class":148,"line":313},8,[315],{"type":66,"tag":146,"props":316,"children":318},{"style":317},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[319],{"type":72,"value":320},"\u002F\u002F Your adapter — see ai-persistence\u002Fstores.\n",{"type":66,"tag":146,"props":322,"children":324},{"class":148,"line":323},9,[325,329,333,338,342,346,350,355],{"type":66,"tag":146,"props":326,"children":327},{"style":153},[328],{"type":72,"value":156},{"type":66,"tag":146,"props":330,"children":331},{"style":159},[332],{"type":72,"value":246},{"type":66,"tag":146,"props":334,"children":335},{"style":169},[336],{"type":72,"value":337}," persistence",{"type":66,"tag":146,"props":339,"children":340},{"style":159},[341],{"type":72,"value":256},{"type":66,"tag":146,"props":343,"children":344},{"style":153},[345],{"type":72,"value":217},{"type":66,"tag":146,"props":347,"children":348},{"style":159},[349],{"type":72,"value":222},{"type":66,"tag":146,"props":351,"children":352},{"style":225},[353],{"type":72,"value":354},".\u002Fpersistence",{"type":66,"tag":146,"props":356,"children":357},{"style":159},[358],{"type":72,"value":233},{"type":66,"tag":146,"props":360,"children":362},{"class":148,"line":361},10,[363],{"type":66,"tag":146,"props":364,"children":366},{"emptyLinePlaceholder":365},true,[367],{"type":72,"value":368},"\n",{"type":66,"tag":146,"props":370,"children":372},{"class":148,"line":371},11,[373,378,384,389,395,400,406,411,417,422],{"type":66,"tag":146,"props":374,"children":375},{"style":153},[376],{"type":72,"value":377},"export",{"type":66,"tag":146,"props":379,"children":381},{"style":380},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[382],{"type":72,"value":383}," async",{"type":66,"tag":146,"props":385,"children":386},{"style":380},[387],{"type":72,"value":388}," function",{"type":66,"tag":146,"props":390,"children":392},{"style":391},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[393],{"type":72,"value":394}," POST",{"type":66,"tag":146,"props":396,"children":397},{"style":159},[398],{"type":72,"value":399},"(",{"type":66,"tag":146,"props":401,"children":403},{"style":402},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[404],{"type":72,"value":405},"request",{"type":66,"tag":146,"props":407,"children":408},{"style":159},[409],{"type":72,"value":410},":",{"type":66,"tag":146,"props":412,"children":414},{"style":413},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[415],{"type":72,"value":416}," Request",{"type":66,"tag":146,"props":418,"children":419},{"style":159},[420],{"type":72,"value":421},")",{"type":66,"tag":146,"props":423,"children":424},{"style":159},[425],{"type":72,"value":162},{"type":66,"tag":146,"props":427,"children":429},{"class":148,"line":428},12,[430,435,440,445,450,455,460,464],{"type":66,"tag":146,"props":431,"children":432},{"style":380},[433],{"type":72,"value":434},"  const",{"type":66,"tag":146,"props":436,"children":437},{"style":169},[438],{"type":72,"value":439}," params",{"type":66,"tag":146,"props":441,"children":442},{"style":159},[443],{"type":72,"value":444}," =",{"type":66,"tag":146,"props":446,"children":447},{"style":153},[448],{"type":72,"value":449}," await",{"type":66,"tag":146,"props":451,"children":452},{"style":391},[453],{"type":72,"value":454}," chatParamsFromRequest",{"type":66,"tag":146,"props":456,"children":458},{"style":457},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[459],{"type":72,"value":399},{"type":66,"tag":146,"props":461,"children":462},{"style":169},[463],{"type":72,"value":405},{"type":66,"tag":146,"props":465,"children":466},{"style":457},[467],{"type":72,"value":468},")\n",{"type":66,"tag":146,"props":470,"children":472},{"class":148,"line":471},13,[473,477,482,486,491,495],{"type":66,"tag":146,"props":474,"children":475},{"style":380},[476],{"type":72,"value":434},{"type":66,"tag":146,"props":478,"children":479},{"style":169},[480],{"type":72,"value":481}," stream",{"type":66,"tag":146,"props":483,"children":484},{"style":159},[485],{"type":72,"value":444},{"type":66,"tag":146,"props":487,"children":488},{"style":391},[489],{"type":72,"value":490}," chat",{"type":66,"tag":146,"props":492,"children":493},{"style":457},[494],{"type":72,"value":399},{"type":66,"tag":146,"props":496,"children":497},{"style":159},[498],{"type":72,"value":499},"{\n",{"type":66,"tag":146,"props":501,"children":503},{"class":148,"line":502},14,[504,509,513,517,521,526,531,535,539],{"type":66,"tag":146,"props":505,"children":506},{"style":457},[507],{"type":72,"value":508},"    adapter",{"type":66,"tag":146,"props":510,"children":511},{"style":159},[512],{"type":72,"value":410},{"type":66,"tag":146,"props":514,"children":515},{"style":391},[516],{"type":72,"value":251},{"type":66,"tag":146,"props":518,"children":519},{"style":457},[520],{"type":72,"value":399},{"type":66,"tag":146,"props":522,"children":523},{"style":159},[524],{"type":72,"value":525},"'",{"type":66,"tag":146,"props":527,"children":528},{"style":225},[529],{"type":72,"value":530},"gpt-5.5",{"type":66,"tag":146,"props":532,"children":533},{"style":159},[534],{"type":72,"value":525},{"type":66,"tag":146,"props":536,"children":537},{"style":457},[538],{"type":72,"value":421},{"type":66,"tag":146,"props":540,"children":541},{"style":159},[542],{"type":72,"value":177},{"type":66,"tag":146,"props":544,"children":546},{"class":148,"line":545},15,[547,552,556,560,564,569],{"type":66,"tag":146,"props":548,"children":549},{"style":457},[550],{"type":72,"value":551},"    messages",{"type":66,"tag":146,"props":553,"children":554},{"style":159},[555],{"type":72,"value":410},{"type":66,"tag":146,"props":557,"children":558},{"style":169},[559],{"type":72,"value":439},{"type":66,"tag":146,"props":561,"children":562},{"style":159},[563],{"type":72,"value":100},{"type":66,"tag":146,"props":565,"children":566},{"style":169},[567],{"type":72,"value":568},"messages",{"type":66,"tag":146,"props":570,"children":571},{"style":159},[572],{"type":72,"value":177},{"type":66,"tag":146,"props":574,"children":576},{"class":148,"line":575},16,[577,582,586,590,594,599],{"type":66,"tag":146,"props":578,"children":579},{"style":457},[580],{"type":72,"value":581},"    threadId",{"type":66,"tag":146,"props":583,"children":584},{"style":159},[585],{"type":72,"value":410},{"type":66,"tag":146,"props":587,"children":588},{"style":169},[589],{"type":72,"value":439},{"type":66,"tag":146,"props":591,"children":592},{"style":159},[593],{"type":72,"value":100},{"type":66,"tag":146,"props":595,"children":596},{"style":169},[597],{"type":72,"value":598},"threadId",{"type":66,"tag":146,"props":600,"children":601},{"style":159},[602],{"type":72,"value":177},{"type":66,"tag":146,"props":604,"children":606},{"class":148,"line":605},17,[607,612,616,620,624,629],{"type":66,"tag":146,"props":608,"children":609},{"style":457},[610],{"type":72,"value":611},"    runId",{"type":66,"tag":146,"props":613,"children":614},{"style":159},[615],{"type":72,"value":410},{"type":66,"tag":146,"props":617,"children":618},{"style":169},[619],{"type":72,"value":439},{"type":66,"tag":146,"props":621,"children":622},{"style":159},[623],{"type":72,"value":100},{"type":66,"tag":146,"props":625,"children":626},{"style":169},[627],{"type":72,"value":628},"runId",{"type":66,"tag":146,"props":630,"children":631},{"style":159},[632],{"type":72,"value":177},{"type":66,"tag":146,"props":634,"children":636},{"class":148,"line":635},18,[637,642,646,651,655,660,665,669,674,678,682,686,690,694,699,704,708],{"type":66,"tag":146,"props":638,"children":639},{"style":159},[640],{"type":72,"value":641},"    ...",{"type":66,"tag":146,"props":643,"children":644},{"style":457},[645],{"type":72,"value":399},{"type":66,"tag":146,"props":647,"children":648},{"style":169},[649],{"type":72,"value":650},"params",{"type":66,"tag":146,"props":652,"children":653},{"style":159},[654],{"type":72,"value":100},{"type":66,"tag":146,"props":656,"children":657},{"style":169},[658],{"type":72,"value":659},"resume",{"type":66,"tag":146,"props":661,"children":662},{"style":159},[663],{"type":72,"value":664}," ?",{"type":66,"tag":146,"props":666,"children":667},{"style":159},[668],{"type":72,"value":246},{"type":66,"tag":146,"props":670,"children":671},{"style":457},[672],{"type":72,"value":673}," resume",{"type":66,"tag":146,"props":675,"children":676},{"style":159},[677],{"type":72,"value":410},{"type":66,"tag":146,"props":679,"children":680},{"style":169},[681],{"type":72,"value":439},{"type":66,"tag":146,"props":683,"children":684},{"style":159},[685],{"type":72,"value":100},{"type":66,"tag":146,"props":687,"children":688},{"style":169},[689],{"type":72,"value":659},{"type":66,"tag":146,"props":691,"children":692},{"style":159},[693],{"type":72,"value":256},{"type":66,"tag":146,"props":695,"children":696},{"style":159},[697],{"type":72,"value":698}," :",{"type":66,"tag":146,"props":700,"children":701},{"style":159},[702],{"type":72,"value":703}," {}",{"type":66,"tag":146,"props":705,"children":706},{"style":457},[707],{"type":72,"value":421},{"type":66,"tag":146,"props":709,"children":710},{"style":159},[711],{"type":72,"value":177},{"type":66,"tag":146,"props":713,"children":715},{"class":148,"line":714},19,[716,721,725,730,735,739,743,748],{"type":66,"tag":146,"props":717,"children":718},{"style":457},[719],{"type":72,"value":720},"    middleware",{"type":66,"tag":146,"props":722,"children":723},{"style":159},[724],{"type":72,"value":410},{"type":66,"tag":146,"props":726,"children":727},{"style":457},[728],{"type":72,"value":729}," [",{"type":66,"tag":146,"props":731,"children":732},{"style":391},[733],{"type":72,"value":734},"withPersistence",{"type":66,"tag":146,"props":736,"children":737},{"style":457},[738],{"type":72,"value":399},{"type":66,"tag":146,"props":740,"children":741},{"style":169},[742],{"type":72,"value":22},{"type":66,"tag":146,"props":744,"children":745},{"style":457},[746],{"type":72,"value":747},")]",{"type":66,"tag":146,"props":749,"children":750},{"style":159},[751],{"type":72,"value":177},{"type":66,"tag":146,"props":753,"children":755},{"class":148,"line":754},20,[756,761],{"type":66,"tag":146,"props":757,"children":758},{"style":159},[759],{"type":72,"value":760},"  }",{"type":66,"tag":146,"props":762,"children":763},{"style":457},[764],{"type":72,"value":468},{"type":66,"tag":146,"props":766,"children":768},{"class":148,"line":767},21,[769,774,779,783,788],{"type":66,"tag":146,"props":770,"children":771},{"style":153},[772],{"type":72,"value":773},"  return",{"type":66,"tag":146,"props":775,"children":776},{"style":391},[777],{"type":72,"value":778}," toServerSentEventsResponse",{"type":66,"tag":146,"props":780,"children":781},{"style":457},[782],{"type":72,"value":399},{"type":66,"tag":146,"props":784,"children":785},{"style":169},[786],{"type":72,"value":787},"stream",{"type":66,"tag":146,"props":789,"children":790},{"style":457},[791],{"type":72,"value":468},{"type":66,"tag":146,"props":793,"children":795},{"class":148,"line":794},22,[796],{"type":66,"tag":146,"props":797,"children":798},{"style":159},[799],{"type":72,"value":800},"}\n",{"type":66,"tag":79,"props":802,"children":803},{},[804,806,811,813,818,820,826,828,833],{"type":72,"value":805},"Always pass ",{"type":66,"tag":93,"props":807,"children":809},{"className":808},[],[810],{"type":72,"value":598},{"type":72,"value":812}," and ",{"type":66,"tag":93,"props":814,"children":816},{"className":815},[],[817],{"type":72,"value":628},{"type":72,"value":819}," from the client (via\n",{"type":66,"tag":93,"props":821,"children":823},{"className":822},[],[824],{"type":72,"value":825},"chatParamsFromRequest",{"type":72,"value":827}," \u002F body helpers). Forward ",{"type":66,"tag":93,"props":829,"children":831},{"className":830},[],[832],{"type":72,"value":659},{"type":72,"value":834}," when the client\nresolves pending interrupts.",{"type":66,"tag":79,"props":836,"children":837},{},[838,840,846,848,853],{"type":72,"value":839},"For dev and tests, ",{"type":66,"tag":93,"props":841,"children":843},{"className":842},[],[844],{"type":72,"value":845},"memoryPersistence()",{"type":72,"value":847}," from ",{"type":66,"tag":93,"props":849,"children":851},{"className":850},[],[852],{"type":72,"value":98},{"type":72,"value":854}," is a\ndrop-in backend that implements all four stores in process.",{"type":66,"tag":128,"props":856,"children":858},{"id":857},"what-each-store-does",[859],{"type":72,"value":860},"What each store does",{"type":66,"tag":862,"props":863,"children":864},"table",{},[865,889],{"type":66,"tag":866,"props":867,"children":868},"thead",{},[869],{"type":66,"tag":870,"props":871,"children":872},"tr",{},[873,879,884],{"type":66,"tag":874,"props":875,"children":876},"th",{},[877],{"type":72,"value":878},"Store",{"type":66,"tag":874,"props":880,"children":881},{},[882],{"type":72,"value":883},"Role",{"type":66,"tag":874,"props":885,"children":886},{},[887],{"type":72,"value":888},"Required?",{"type":66,"tag":890,"props":891,"children":892},"tbody",{},[893,925,947,981],{"type":66,"tag":870,"props":894,"children":895},{},[896,905,910],{"type":66,"tag":897,"props":898,"children":899},"td",{},[900],{"type":66,"tag":93,"props":901,"children":903},{"className":902},[],[904],{"type":72,"value":568},{"type":66,"tag":897,"props":906,"children":907},{},[908],{"type":72,"value":909},"Full model-message transcript load\u002Fsave",{"type":66,"tag":897,"props":911,"children":912},{},[913,918,920],{"type":66,"tag":85,"props":914,"children":915},{},[916],{"type":72,"value":917},"Yes",{"type":72,"value":919}," for ",{"type":66,"tag":93,"props":921,"children":923},{"className":922},[],[924],{"type":72,"value":734},{"type":66,"tag":870,"props":926,"children":927},{},[928,937,942],{"type":66,"tag":897,"props":929,"children":930},{},[931],{"type":66,"tag":93,"props":932,"children":934},{"className":933},[],[935],{"type":72,"value":936},"runs",{"type":66,"tag":897,"props":938,"children":939},{},[940],{"type":72,"value":941},"Run status, timing, usage, errors",{"type":66,"tag":897,"props":943,"children":944},{},[945],{"type":72,"value":946},"Optional; needed for interrupt durability",{"type":66,"tag":870,"props":948,"children":949},{},[950,959,964],{"type":66,"tag":897,"props":951,"children":952},{},[953],{"type":66,"tag":93,"props":954,"children":956},{"className":955},[],[957],{"type":72,"value":958},"interrupts",{"type":66,"tag":897,"props":960,"children":961},{},[962],{"type":72,"value":963},"Pending\u002Fresolved tool approvals & waits",{"type":66,"tag":897,"props":965,"children":966},{},[967,969,974,976],{"type":72,"value":968},"Optional; ",{"type":66,"tag":85,"props":970,"children":971},{},[972],{"type":72,"value":973},"requires",{"type":72,"value":975}," ",{"type":66,"tag":93,"props":977,"children":979},{"className":978},[],[980],{"type":72,"value":936},{"type":66,"tag":870,"props":982,"children":983},{},[984,993,998],{"type":66,"tag":897,"props":985,"children":986},{},[987],{"type":66,"tag":93,"props":988,"children":990},{"className":989},[],[991],{"type":72,"value":992},"metadata",{"type":66,"tag":897,"props":994,"children":995},{},[996],{"type":72,"value":997},"App-owned namespaced key\u002Fvalue",{"type":66,"tag":897,"props":999,"children":1000},{},[1001],{"type":72,"value":1002},"Optional",{"type":66,"tag":79,"props":1004,"children":1005},{},[1006,1008,1014,1016,1022,1024,1029,1031,1037,1039,1044,1046,1052,1054,1060],{"type":72,"value":1007},"Named shapes: ",{"type":66,"tag":93,"props":1009,"children":1011},{"className":1010},[],[1012],{"type":72,"value":1013},"ChatTranscriptPersistence",{"type":72,"value":1015}," (floor), ",{"type":66,"tag":93,"props":1017,"children":1019},{"className":1018},[],[1020],{"type":72,"value":1021},"ChatPersistence",{"type":72,"value":1023}," (all four).\n",{"type":66,"tag":85,"props":1025,"children":1026},{},[1027],{"type":72,"value":1028},"Annotate your factory with one of these",{"type":72,"value":1030},", not with bare ",{"type":66,"tag":93,"props":1032,"children":1034},{"className":1033},[],[1035],{"type":72,"value":1036},"AIPersistence",{"type":72,"value":1038}," —\nthe unparameterized type is the all-optional bag, and ",{"type":66,"tag":93,"props":1040,"children":1042},{"className":1041},[],[1043],{"type":72,"value":734},{"type":72,"value":1045}," rejects\nit because ",{"type":66,"tag":93,"props":1047,"children":1049},{"className":1048},[],[1050],{"type":72,"value":1051},"stores.messages",{"type":72,"value":1053}," is possibly ",{"type":66,"tag":93,"props":1055,"children":1057},{"className":1056},[],[1058],{"type":72,"value":1059},"undefined",{"type":72,"value":100},{"type":66,"tag":128,"props":1062,"children":1064},{"id":1063},"authoritative-history-contract",[1065],{"type":72,"value":1066},"Authoritative-history contract",{"type":66,"tag":1068,"props":1069,"children":1070},"ul",{},[1071,1101],{"type":66,"tag":1072,"props":1073,"children":1074},"li",{},[1075,1085,1087,1092,1094,1099],{"type":66,"tag":85,"props":1076,"children":1077},{},[1078,1080],{"type":72,"value":1079},"Non-empty ",{"type":66,"tag":93,"props":1081,"children":1083},{"className":1082},[],[1084],{"type":72,"value":568},{"type":72,"value":1086}," → finish ",{"type":66,"tag":85,"props":1088,"children":1089},{},[1090],{"type":72,"value":1091},"overwrites",{"type":72,"value":1093}," the stored thread with that\narray. Post the ",{"type":66,"tag":85,"props":1095,"children":1096},{},[1097],{"type":72,"value":1098},"complete",{"type":72,"value":1100}," transcript, never a delta.",{"type":66,"tag":1072,"props":1102,"children":1103},{},[1104,1114,1116,1121],{"type":66,"tag":85,"props":1105,"children":1106},{},[1107,1109],{"type":72,"value":1108},"Empty ",{"type":66,"tag":93,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":72,"value":568},{"type":72,"value":1115}," → middleware ",{"type":66,"tag":85,"props":1117,"children":1118},{},[1119],{"type":72,"value":1120},"loads",{"type":72,"value":1122}," the stored thread and continues.",{"type":66,"tag":128,"props":1124,"children":1126},{"id":1125},"when-state-is-written",[1127],{"type":72,"value":1128},"When state is written",{"type":66,"tag":862,"props":1130,"children":1131},{},[1132,1153],{"type":66,"tag":866,"props":1133,"children":1134},{},[1135],{"type":66,"tag":870,"props":1136,"children":1137},{},[1138,1143,1148],{"type":66,"tag":874,"props":1139,"children":1140},{},[1141],{"type":72,"value":1142},"Moment",{"type":66,"tag":874,"props":1144,"children":1145},{},[1146],{"type":72,"value":1147},"Writes",{"type":66,"tag":874,"props":1149,"children":1150},{},[1151],{"type":72,"value":1152},"Best-effort?",{"type":66,"tag":890,"props":1154,"children":1155},{},[1156,1178,1204,1240,1264,1292],{"type":66,"tag":870,"props":1157,"children":1158},{},[1159,1168,1173],{"type":66,"tag":897,"props":1160,"children":1161},{},[1162],{"type":66,"tag":93,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":72,"value":1167},"onStart",{"type":66,"tag":897,"props":1169,"children":1170},{},[1171],{"type":72,"value":1172},"Pending turn snapshot (user + history)",{"type":66,"tag":897,"props":1174,"children":1175},{},[1176],{"type":72,"value":1177},"Yes — failure does not abort",{"type":66,"tag":870,"props":1179,"children":1180},{},[1181,1186,1199],{"type":66,"tag":897,"props":1182,"children":1183},{},[1184],{"type":72,"value":1185},"Interrupt boundary",{"type":66,"tag":897,"props":1187,"children":1188},{},[1189,1191,1197],{"type":72,"value":1190},"New interrupts, run → ",{"type":66,"tag":93,"props":1192,"children":1194},{"className":1193},[],[1195],{"type":72,"value":1196},"interrupted",{"type":72,"value":1198},", message snapshot",{"type":66,"tag":897,"props":1200,"children":1201},{},[1202],{"type":72,"value":1203},"No",{"type":66,"tag":870,"props":1205,"children":1206},{},[1207,1216,1236],{"type":66,"tag":897,"props":1208,"children":1209},{},[1210],{"type":66,"tag":93,"props":1211,"children":1213},{"className":1212},[],[1214],{"type":72,"value":1215},"onFinish",{"type":66,"tag":897,"props":1217,"children":1218},{},[1219,1221,1226,1228,1234],{"type":72,"value":1220},"Full transcript ",{"type":66,"tag":85,"props":1222,"children":1223},{},[1224],{"type":72,"value":1225},"first",{"type":72,"value":1227},", then run → ",{"type":66,"tag":93,"props":1229,"children":1231},{"className":1230},[],[1232],{"type":72,"value":1233},"completed",{"type":72,"value":1235},", commit resumes",{"type":66,"tag":897,"props":1237,"children":1238},{},[1239],{"type":72,"value":1203},{"type":66,"tag":870,"props":1241,"children":1242},{},[1243,1248,1253],{"type":66,"tag":897,"props":1244,"children":1245},{},[1246],{"type":72,"value":1247},"Stream (optional)",{"type":66,"tag":897,"props":1249,"children":1250},{},[1251],{"type":72,"value":1252},"Throttled partial assistant text",{"type":66,"tag":897,"props":1254,"children":1255},{},[1256,1258],{"type":72,"value":1257},"Yes if ",{"type":66,"tag":93,"props":1259,"children":1261},{"className":1260},[],[1262],{"type":72,"value":1263},"snapshotStreaming: true",{"type":66,"tag":870,"props":1265,"children":1266},{},[1267,1276,1287],{"type":66,"tag":897,"props":1268,"children":1269},{},[1270],{"type":66,"tag":93,"props":1271,"children":1273},{"className":1272},[],[1274],{"type":72,"value":1275},"onError",{"type":66,"tag":897,"props":1277,"children":1278},{},[1279,1281],{"type":72,"value":1280},"Run → ",{"type":66,"tag":93,"props":1282,"children":1284},{"className":1283},[],[1285],{"type":72,"value":1286},"failed",{"type":66,"tag":897,"props":1288,"children":1289},{},[1290],{"type":72,"value":1291},"Resumes stay pending",{"type":66,"tag":870,"props":1293,"children":1294},{},[1295,1304,1313],{"type":66,"tag":897,"props":1296,"children":1297},{},[1298],{"type":66,"tag":93,"props":1299,"children":1301},{"className":1300},[],[1302],{"type":72,"value":1303},"onAbort",{"type":66,"tag":897,"props":1305,"children":1306},{},[1307,1308],{"type":72,"value":1280},{"type":66,"tag":93,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":72,"value":1196},{"type":66,"tag":897,"props":1314,"children":1315},{},[1316],{"type":72,"value":1291},{"type":66,"tag":135,"props":1318,"children":1320},{"className":137,"code":1319,"language":139,"meta":140,"style":140},"withPersistence(persistence, {\n  snapshotStreaming: true,\n  snapshotIntervalMs: 1000, \u002F\u002F default\n})\n",[1321],{"type":66,"tag":93,"props":1322,"children":1323},{"__ignoreMap":140},[1324,1345,1367,1394],{"type":66,"tag":146,"props":1325,"children":1326},{"class":148,"line":149},[1327,1331,1336,1341],{"type":66,"tag":146,"props":1328,"children":1329},{"style":391},[1330],{"type":72,"value":734},{"type":66,"tag":146,"props":1332,"children":1333},{"style":169},[1334],{"type":72,"value":1335},"(persistence",{"type":66,"tag":146,"props":1337,"children":1338},{"style":159},[1339],{"type":72,"value":1340},",",{"type":66,"tag":146,"props":1342,"children":1343},{"style":159},[1344],{"type":72,"value":162},{"type":66,"tag":146,"props":1346,"children":1347},{"class":148,"line":165},[1348,1353,1357,1363],{"type":66,"tag":146,"props":1349,"children":1350},{"style":457},[1351],{"type":72,"value":1352},"  snapshotStreaming",{"type":66,"tag":146,"props":1354,"children":1355},{"style":159},[1356],{"type":72,"value":410},{"type":66,"tag":146,"props":1358,"children":1360},{"style":1359},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[1361],{"type":72,"value":1362}," true",{"type":66,"tag":146,"props":1364,"children":1365},{"style":159},[1366],{"type":72,"value":177},{"type":66,"tag":146,"props":1368,"children":1369},{"class":148,"line":180},[1370,1375,1379,1385,1389],{"type":66,"tag":146,"props":1371,"children":1372},{"style":457},[1373],{"type":72,"value":1374},"  snapshotIntervalMs",{"type":66,"tag":146,"props":1376,"children":1377},{"style":159},[1378],{"type":72,"value":410},{"type":66,"tag":146,"props":1380,"children":1382},{"style":1381},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1383],{"type":72,"value":1384}," 1000",{"type":66,"tag":146,"props":1386,"children":1387},{"style":159},[1388],{"type":72,"value":1340},{"type":66,"tag":146,"props":1390,"children":1391},{"style":317},[1392],{"type":72,"value":1393}," \u002F\u002F default\n",{"type":66,"tag":146,"props":1395,"children":1396},{"class":148,"line":193},[1397,1401],{"type":66,"tag":146,"props":1398,"children":1399},{"style":159},[1400],{"type":72,"value":212},{"type":66,"tag":146,"props":1402,"children":1403},{"style":169},[1404],{"type":72,"value":468},{"type":66,"tag":79,"props":1406,"children":1407},{},[1408,1410,1415],{"type":72,"value":1409},"Streaming snapshots default ",{"type":66,"tag":85,"props":1411,"children":1412},{},[1413],{"type":72,"value":1414},"off",{"type":72,"value":1416}," (finish is authoritative). Enable only when\npartial-output durability is worth extra writes.",{"type":66,"tag":79,"props":1418,"children":1419},{},[1420,1422,1428],{"type":72,"value":1421},"Resumes accepted in ",{"type":66,"tag":93,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":72,"value":1427},"onConfig",{"type":72,"value":1429}," commit only at a success boundary (interrupt or\nfinish). A failed run leaves interrupts pending so the same resume batch can\nretry.",{"type":66,"tag":128,"props":1431,"children":1433},{"id":1432},"interrupt-resume-flow",[1434],{"type":72,"value":1435},"Interrupt \u002F resume flow",{"type":66,"tag":1437,"props":1438,"children":1439},"ol",{},[1440,1466,1487],{"type":66,"tag":1072,"props":1441,"children":1442},{},[1443,1445,1450,1452,1457,1459,1464],{"type":72,"value":1444},"Middleware records pending interrupts and ",{"type":66,"tag":85,"props":1446,"children":1447},{},[1448],{"type":72,"value":1449},"gates",{"type":72,"value":1451}," new input: if pending\nexist, the request must include a matching ",{"type":66,"tag":93,"props":1453,"children":1455},{"className":1454},[],[1456],{"type":72,"value":659},{"type":72,"value":1458}," batch or ",{"type":66,"tag":93,"props":1460,"children":1462},{"className":1461},[],[1463],{"type":72,"value":1427},{"type":72,"value":1465},"\nthrows.",{"type":66,"tag":1072,"props":1467,"children":1468},{},[1469,1471,1477,1479,1485],{"type":72,"value":1470},"On valid resume, middleware builds ",{"type":66,"tag":93,"props":1472,"children":1474},{"className":1473},[],[1475],{"type":72,"value":1476},"resumeToolState",{"type":72,"value":1478}," and clears\n",{"type":66,"tag":93,"props":1480,"children":1482},{"className":1481},[],[1483],{"type":72,"value":1484},"config.resume",{"type":72,"value":1486}," so the engine does not double-reconstruct from client\nhistory (server owns transcript).",{"type":66,"tag":1072,"props":1488,"children":1489},{},[1490],{"type":72,"value":1491},"On success boundary, interrupts are marked resolved\u002Fcancelled.",{"type":66,"tag":128,"props":1493,"children":1495},{"id":1494},"hydrate-a-thread-for-the-client-reconstructchat",[1496,1498,1504],{"type":72,"value":1497},"Hydrate a thread for the client (",{"type":66,"tag":93,"props":1499,"children":1501},{"className":1500},[],[1502],{"type":72,"value":1503},"reconstructChat",{"type":72,"value":421},{"type":66,"tag":79,"props":1506,"children":1507},{},[1508,1510,1515,1517,1523],{"type":72,"value":1509},"Server-authoritative clients load history by ",{"type":66,"tag":93,"props":1511,"children":1513},{"className":1512},[],[1514],{"type":72,"value":598},{"type":72,"value":1516}," (often ",{"type":66,"tag":93,"props":1518,"children":1520},{"className":1519},[],[1521],{"type":72,"value":1522},"GET",{"type":72,"value":1524},"):",{"type":66,"tag":135,"props":1526,"children":1528},{"className":137,"code":1527,"language":139,"meta":140,"style":140},"import { reconstructChat } from '@tanstack\u002Fai-persistence'\n\nexport async function GET(request: Request) {\n  return reconstructChat(persistence, request, {\n    \u002F\u002F Multi-user: required in production\n    authorize: async (threadId, req) => {\n      const userId = await sessionUserId(req)\n      return userOwnsThread(userId, threadId)\n    },\n  })\n}\n",[1529],{"type":66,"tag":93,"props":1530,"children":1531},{"__ignoreMap":140},[1532,1568,1575,1619,1655,1663,1710,1749,1784,1792,1803],{"type":66,"tag":146,"props":1533,"children":1534},{"class":148,"line":149},[1535,1539,1543,1548,1552,1556,1560,1564],{"type":66,"tag":146,"props":1536,"children":1537},{"style":153},[1538],{"type":72,"value":156},{"type":66,"tag":146,"props":1540,"children":1541},{"style":159},[1542],{"type":72,"value":246},{"type":66,"tag":146,"props":1544,"children":1545},{"style":169},[1546],{"type":72,"value":1547}," reconstructChat",{"type":66,"tag":146,"props":1549,"children":1550},{"style":159},[1551],{"type":72,"value":256},{"type":66,"tag":146,"props":1553,"children":1554},{"style":153},[1555],{"type":72,"value":217},{"type":66,"tag":146,"props":1557,"children":1558},{"style":159},[1559],{"type":72,"value":222},{"type":66,"tag":146,"props":1561,"children":1562},{"style":225},[1563],{"type":72,"value":98},{"type":66,"tag":146,"props":1565,"children":1566},{"style":159},[1567],{"type":72,"value":233},{"type":66,"tag":146,"props":1569,"children":1570},{"class":148,"line":165},[1571],{"type":66,"tag":146,"props":1572,"children":1573},{"emptyLinePlaceholder":365},[1574],{"type":72,"value":368},{"type":66,"tag":146,"props":1576,"children":1577},{"class":148,"line":180},[1578,1582,1586,1590,1595,1599,1603,1607,1611,1615],{"type":66,"tag":146,"props":1579,"children":1580},{"style":153},[1581],{"type":72,"value":377},{"type":66,"tag":146,"props":1583,"children":1584},{"style":380},[1585],{"type":72,"value":383},{"type":66,"tag":146,"props":1587,"children":1588},{"style":380},[1589],{"type":72,"value":388},{"type":66,"tag":146,"props":1591,"children":1592},{"style":391},[1593],{"type":72,"value":1594}," GET",{"type":66,"tag":146,"props":1596,"children":1597},{"style":159},[1598],{"type":72,"value":399},{"type":66,"tag":146,"props":1600,"children":1601},{"style":402},[1602],{"type":72,"value":405},{"type":66,"tag":146,"props":1604,"children":1605},{"style":159},[1606],{"type":72,"value":410},{"type":66,"tag":146,"props":1608,"children":1609},{"style":413},[1610],{"type":72,"value":416},{"type":66,"tag":146,"props":1612,"children":1613},{"style":159},[1614],{"type":72,"value":421},{"type":66,"tag":146,"props":1616,"children":1617},{"style":159},[1618],{"type":72,"value":162},{"type":66,"tag":146,"props":1620,"children":1621},{"class":148,"line":193},[1622,1626,1630,1634,1638,1642,1647,1651],{"type":66,"tag":146,"props":1623,"children":1624},{"style":153},[1625],{"type":72,"value":773},{"type":66,"tag":146,"props":1627,"children":1628},{"style":391},[1629],{"type":72,"value":1547},{"type":66,"tag":146,"props":1631,"children":1632},{"style":457},[1633],{"type":72,"value":399},{"type":66,"tag":146,"props":1635,"children":1636},{"style":169},[1637],{"type":72,"value":22},{"type":66,"tag":146,"props":1639,"children":1640},{"style":159},[1641],{"type":72,"value":1340},{"type":66,"tag":146,"props":1643,"children":1644},{"style":169},[1645],{"type":72,"value":1646}," request",{"type":66,"tag":146,"props":1648,"children":1649},{"style":159},[1650],{"type":72,"value":1340},{"type":66,"tag":146,"props":1652,"children":1653},{"style":159},[1654],{"type":72,"value":162},{"type":66,"tag":146,"props":1656,"children":1657},{"class":148,"line":206},[1658],{"type":66,"tag":146,"props":1659,"children":1660},{"style":317},[1661],{"type":72,"value":1662},"    \u002F\u002F Multi-user: required in production\n",{"type":66,"tag":146,"props":1664,"children":1665},{"class":148,"line":236},[1666,1671,1675,1679,1684,1688,1692,1697,1701,1706],{"type":66,"tag":146,"props":1667,"children":1668},{"style":391},[1669],{"type":72,"value":1670},"    authorize",{"type":66,"tag":146,"props":1672,"children":1673},{"style":159},[1674],{"type":72,"value":410},{"type":66,"tag":146,"props":1676,"children":1677},{"style":380},[1678],{"type":72,"value":383},{"type":66,"tag":146,"props":1680,"children":1681},{"style":159},[1682],{"type":72,"value":1683}," (",{"type":66,"tag":146,"props":1685,"children":1686},{"style":402},[1687],{"type":72,"value":598},{"type":66,"tag":146,"props":1689,"children":1690},{"style":159},[1691],{"type":72,"value":1340},{"type":66,"tag":146,"props":1693,"children":1694},{"style":402},[1695],{"type":72,"value":1696}," req",{"type":66,"tag":146,"props":1698,"children":1699},{"style":159},[1700],{"type":72,"value":421},{"type":66,"tag":146,"props":1702,"children":1703},{"style":380},[1704],{"type":72,"value":1705}," =>",{"type":66,"tag":146,"props":1707,"children":1708},{"style":159},[1709],{"type":72,"value":162},{"type":66,"tag":146,"props":1711,"children":1712},{"class":148,"line":276},[1713,1718,1723,1727,1731,1736,1740,1745],{"type":66,"tag":146,"props":1714,"children":1715},{"style":380},[1716],{"type":72,"value":1717},"      const",{"type":66,"tag":146,"props":1719,"children":1720},{"style":169},[1721],{"type":72,"value":1722}," userId",{"type":66,"tag":146,"props":1724,"children":1725},{"style":159},[1726],{"type":72,"value":444},{"type":66,"tag":146,"props":1728,"children":1729},{"style":153},[1730],{"type":72,"value":449},{"type":66,"tag":146,"props":1732,"children":1733},{"style":391},[1734],{"type":72,"value":1735}," sessionUserId",{"type":66,"tag":146,"props":1737,"children":1738},{"style":457},[1739],{"type":72,"value":399},{"type":66,"tag":146,"props":1741,"children":1742},{"style":169},[1743],{"type":72,"value":1744},"req",{"type":66,"tag":146,"props":1746,"children":1747},{"style":457},[1748],{"type":72,"value":468},{"type":66,"tag":146,"props":1750,"children":1751},{"class":148,"line":313},[1752,1757,1762,1766,1771,1775,1780],{"type":66,"tag":146,"props":1753,"children":1754},{"style":153},[1755],{"type":72,"value":1756},"      return",{"type":66,"tag":146,"props":1758,"children":1759},{"style":391},[1760],{"type":72,"value":1761}," userOwnsThread",{"type":66,"tag":146,"props":1763,"children":1764},{"style":457},[1765],{"type":72,"value":399},{"type":66,"tag":146,"props":1767,"children":1768},{"style":169},[1769],{"type":72,"value":1770},"userId",{"type":66,"tag":146,"props":1772,"children":1773},{"style":159},[1774],{"type":72,"value":1340},{"type":66,"tag":146,"props":1776,"children":1777},{"style":169},[1778],{"type":72,"value":1779}," threadId",{"type":66,"tag":146,"props":1781,"children":1782},{"style":457},[1783],{"type":72,"value":468},{"type":66,"tag":146,"props":1785,"children":1786},{"class":148,"line":323},[1787],{"type":66,"tag":146,"props":1788,"children":1789},{"style":159},[1790],{"type":72,"value":1791},"    },\n",{"type":66,"tag":146,"props":1793,"children":1794},{"class":148,"line":361},[1795,1799],{"type":66,"tag":146,"props":1796,"children":1797},{"style":159},[1798],{"type":72,"value":760},{"type":66,"tag":146,"props":1800,"children":1801},{"style":457},[1802],{"type":72,"value":468},{"type":66,"tag":146,"props":1804,"children":1805},{"class":148,"line":371},[1806],{"type":66,"tag":146,"props":1807,"children":1808},{"style":159},[1809],{"type":72,"value":800},{"type":66,"tag":79,"props":1811,"children":1812},{},[1813,1815,1821],{"type":72,"value":1814},"Returns ",{"type":66,"tag":93,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":72,"value":1820},"{ messages, activeRun, interrupts }",{"type":72,"value":410},{"type":66,"tag":1068,"props":1823,"children":1824},{},[1825,1835,1861],{"type":66,"tag":1072,"props":1826,"children":1827},{},[1828,1833],{"type":66,"tag":93,"props":1829,"children":1831},{"className":1830},[],[1832],{"type":72,"value":568},{"type":72,"value":1834}," — UI messages for paint",{"type":66,"tag":1072,"props":1836,"children":1837},{},[1838,1844,1846,1852,1854,1860],{"type":66,"tag":93,"props":1839,"children":1841},{"className":1840},[],[1842],{"type":72,"value":1843},"activeRun",{"type":72,"value":1845}," — ",{"type":66,"tag":93,"props":1847,"children":1849},{"className":1848},[],[1850],{"type":72,"value":1851},"{ runId }",{"type":72,"value":1853}," if a run is still generating (",{"type":66,"tag":93,"props":1855,"children":1857},{"className":1856},[],[1858],{"type":72,"value":1859},"runs.findActiveRun",{"type":72,"value":421},{"type":66,"tag":1072,"props":1862,"children":1863},{},[1864,1869],{"type":66,"tag":93,"props":1865,"children":1867},{"className":1866},[],[1868],{"type":72,"value":958},{"type":72,"value":1870}," — pending human-in-the-loop state for re-prompt",{"type":66,"tag":79,"props":1872,"children":1873},{},[1874],{"type":66,"tag":85,"props":1875,"children":1876},{},[1877,1879,1885,1887,1893],{"type":72,"value":1878},"Without ",{"type":66,"tag":93,"props":1880,"children":1882},{"className":1881},[],[1883],{"type":72,"value":1884},"authorize",{"type":72,"value":1886},", anyone who guesses ",{"type":66,"tag":93,"props":1888,"children":1890},{"className":1889},[],[1891],{"type":72,"value":1892},"?threadId=",{"type":72,"value":1894}," gets the transcript.",{"type":66,"tag":128,"props":1896,"children":1898},{"id":1897},"generation-activities",[1899],{"type":72,"value":1900},"Generation activities",{"type":66,"tag":79,"props":1902,"children":1903},{},[1904,1910,1912,1918],{"type":66,"tag":93,"props":1905,"children":1907},{"className":1906},[],[1908],{"type":72,"value":1909},"withGenerationPersistence(persistence)",{"type":72,"value":1911}," tracks run records for non-chat\nactivities (image, audio, TTS, video, transcription). Do not fake\n",{"type":66,"tag":93,"props":1913,"children":1915},{"className":1914},[],[1916],{"type":72,"value":1917},"threadId = requestId",{"type":72,"value":1919}," on chat run stores — use the generation helper.",{"type":66,"tag":128,"props":1921,"children":1923},{"id":1922},"common-mistakes",[1924],{"type":72,"value":1925},"Common mistakes",{"type":66,"tag":1927,"props":1928,"children":1930},"h3",{"id":1929},"critical-posting-a-message-delta-as-messages",[1931,1933],{"type":72,"value":1932},"CRITICAL: Posting a message delta as ",{"type":66,"tag":93,"props":1934,"children":1936},{"className":1935},[],[1937],{"type":72,"value":568},{"type":66,"tag":79,"props":1939,"children":1940},{},[1941,1943,1949],{"type":72,"value":1942},"Wipes the stored thread down to that delta. Always send full history or ",{"type":66,"tag":93,"props":1944,"children":1946},{"className":1945},[],[1947],{"type":72,"value":1948},"[]",{"type":72,"value":100},{"type":66,"tag":1927,"props":1951,"children":1953},{"id":1952},"high-omitting-threadid-runid",[1954,1956,1961,1963],{"type":72,"value":1955},"HIGH: Omitting ",{"type":66,"tag":93,"props":1957,"children":1959},{"className":1958},[],[1960],{"type":72,"value":598},{"type":72,"value":1962}," \u002F ",{"type":66,"tag":93,"props":1964,"children":1966},{"className":1965},[],[1967],{"type":72,"value":628},{"type":66,"tag":79,"props":1969,"children":1970},{},[1971,1973,1978],{"type":72,"value":1972},"Persistence keys and resume need stable ids. Use ",{"type":66,"tag":93,"props":1974,"children":1976},{"className":1975},[],[1977],{"type":72,"value":825},{"type":72,"value":100},{"type":66,"tag":1927,"props":1980,"children":1982},{"id":1981},"high-interrupts-without-runs",[1983,1985],{"type":72,"value":1984},"HIGH: Interrupts without ",{"type":66,"tag":93,"props":1986,"children":1988},{"className":1987},[],[1989],{"type":72,"value":936},{"type":66,"tag":79,"props":1991,"children":1992},{},[1993,1998,2000,2005,2007,2012],{"type":66,"tag":93,"props":1994,"children":1996},{"className":1995},[],[1997],{"type":72,"value":958},{"type":72,"value":1999}," requires ",{"type":66,"tag":93,"props":2001,"children":2003},{"className":2002},[],[2004],{"type":72,"value":936},{"type":72,"value":2006},"; ",{"type":66,"tag":93,"props":2008,"children":2010},{"className":2009},[],[2011],{"type":72,"value":734},{"type":72,"value":2013}," throws otherwise.",{"type":66,"tag":1927,"props":2015,"children":2017},{"id":2016},"high-typing-a-factory-as-bare-aipersistence",[2018,2020],{"type":72,"value":2019},"HIGH: Typing a factory as bare ",{"type":66,"tag":93,"props":2021,"children":2023},{"className":2022},[],[2024],{"type":72,"value":1036},{"type":66,"tag":79,"props":2026,"children":2027},{},[2028,2033,2035,2040,2042,2047,2049,2054,2056,2061],{"type":66,"tag":93,"props":2029,"children":2031},{"className":2030},[],[2032],{"type":72,"value":1036},{"type":72,"value":2034}," defaults to the sparse all-optional bag, so ",{"type":66,"tag":93,"props":2036,"children":2038},{"className":2037},[],[2039],{"type":72,"value":734},{"type":72,"value":2041},"\nand ",{"type":66,"tag":93,"props":2043,"children":2045},{"className":2044},[],[2046],{"type":72,"value":1503},{"type":72,"value":2048}," reject the value. Return ",{"type":66,"tag":93,"props":2050,"children":2052},{"className":2051},[],[2053],{"type":72,"value":1021},{"type":72,"value":2055}," (or\n",{"type":66,"tag":93,"props":2057,"children":2059},{"className":2058},[],[2060],{"type":72,"value":1013},{"type":72,"value":2062},") instead.",{"type":66,"tag":1927,"props":2064,"children":2066},{"id":2065},"medium-expecting-withpersistence-to-reconnect-a-dropped-stream",[2067,2069,2074],{"type":72,"value":2068},"MEDIUM: Expecting ",{"type":66,"tag":93,"props":2070,"children":2072},{"className":2071},[],[2073],{"type":72,"value":734},{"type":72,"value":2075}," to reconnect a dropped stream",{"type":66,"tag":79,"props":2077,"children":2078},{},[2079],{"type":72,"value":2080},"That is delivery durability (resumable streams), not state persistence.",{"type":66,"tag":128,"props":2082,"children":2084},{"id":2083},"cross-references",[2085],{"type":72,"value":2086},"Cross-references",{"type":66,"tag":1068,"props":2088,"children":2089},{},[2090,2099,2109,2125],{"type":66,"tag":1072,"props":2091,"children":2092},{},[2093,2097],{"type":66,"tag":85,"props":2094,"children":2095},{},[2096],{"type":72,"value":89},{"type":72,"value":2098}," — layers and recommended stack",{"type":66,"tag":1072,"props":2100,"children":2101},{},[2102,2107],{"type":66,"tag":85,"props":2103,"children":2104},{},[2105],{"type":72,"value":2106},"ai-persistence\u002Fstores",{"type":72,"value":2108}," — implement the store interfaces",{"type":66,"tag":1072,"props":2110,"children":2111},{},[2112,2117,2118,2123],{"type":66,"tag":85,"props":2113,"children":2114},{},[2115],{"type":72,"value":2116},"ai-core\u002Fclient-persistence",{"type":72,"value":1683},{"type":66,"tag":93,"props":2119,"children":2121},{"className":2120},[],[2122],{"type":72,"value":228},{"type":72,"value":2124},") — browser half",{"type":66,"tag":1072,"props":2126,"children":2127},{},[2128,2133],{"type":66,"tag":85,"props":2129,"children":2130},{},[2131],{"type":72,"value":2132},"ai-core\u002Flocks",{"type":72,"value":2134}," — multi-instance coordination",{"type":66,"tag":2136,"props":2137,"children":2138},"style",{},[2139],{"type":72,"value":2140},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2142,"total":2240},[2143,2161,2175,2190,2203,2217,2228],{"slug":2144,"name":2144,"fn":2145,"description":2146,"org":2147,"tags":2148,"stars":24,"repoUrl":25,"updatedAt":2160},"ai-code-mode","execute sandboxed TypeScript code with LLMs","LLM-generated TypeScript execution in sandboxed environments: createCodeModeTool() with isolate drivers (createNodeIsolateDriver, createQuickJSIsolateDriver, createCloudflareIsolateDriver), codeModeWithSkills() for persistent skill libraries, trust strategies, skill storage (FileSystem, LocalStorage, InMemory, Mongo), client-side execution progress via code_mode:* custom events in useChat.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2149,2151,2154,2157,2158],{"name":2150,"slug":31,"type":16},"AI SDK",{"name":2152,"slug":2153,"type":16},"Code Execution","code-execution",{"name":2155,"slug":2156,"type":16},"Sandboxing","sandboxing",{"name":10,"slug":9,"type":16},{"name":2159,"slug":45,"type":16},"TypeScript","2026-07-16T06:04:13.597905",{"slug":2162,"name":2162,"fn":2163,"description":2164,"org":2165,"tags":2166,"stars":24,"repoUrl":25,"updatedAt":2174},"ai-core","configure TanStack AI agent features","Entry point for TanStack AI skills. Routes to chat-experience, tool-calling, media-generation, structured-outputs, adapter-configuration, ag-ui-protocol, middleware, locks, custom-backend-integration, and debug-logging, plus the skills shipped by companion packages (@tanstack\u002Fai-persistence, @tanstack\u002Fai-code-mode). Use chat() not streamText(), openaiText() not createOpenAI(), toServerSentEventsResponse() not manual SSE, middleware hooks not onEnd callbacks.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2167,2170,2171],{"name":2168,"slug":2169,"type":16},"Agents","agents",{"name":18,"slug":19,"type":16},{"name":2172,"slug":2173,"type":16},"Middleware","middleware","2026-07-30T05:26:10.404565",{"slug":2176,"name":2177,"fn":2178,"description":2179,"org":2180,"tags":2181,"stars":24,"repoUrl":25,"updatedAt":2189},"ai-coreadapter-configuration","ai-core\u002Fadapter-configuration","configure AI provider adapters","Provider adapter selection and configuration: openaiText, anthropicText, geminiText, ollamaText, grokText, groqText, openRouterText, bedrockText, openaiCompatible. Per-model type safety with modelOptions, reasoning\u002Fthinking configuration, runtime adapter switching, extendAdapter() for custom models, createModel(). Generic OpenAI-compatible providers (DeepSeek, Together, Fireworks, etc.) via openaiCompatible({ baseURL, apiKey, models }) from @tanstack\u002Fai-openai\u002Fcompatible. API key env vars: OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY\u002FGEMINI_API_KEY, XAI_API_KEY, GROQ_API_KEY, OPENROUTER_API_KEY, OLLAMA_HOST, BEDROCK_API_KEY (or AWS_BEARER_TOKEN_BEDROCK).\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2182,2183,2186,2188],{"name":2150,"slug":31,"type":16},{"name":2184,"slug":2185,"type":16},"Configuration","configuration",{"name":2187,"slug":37,"type":16},"LLM",{"name":10,"slug":9,"type":16},"2026-07-16T06:04:17.82075",{"slug":2191,"name":2192,"fn":2193,"description":2194,"org":2195,"tags":2196,"stars":24,"repoUrl":25,"updatedAt":2202},"ai-coreag-ui-protocol","ai-core\u002Fag-ui-protocol","implement TanStack AI streaming protocol","Server-side AG-UI streaming protocol implementation: StreamChunk event types (RUN_STARTED, TEXT_MESSAGE_START\u002FCONTENT\u002FEND, TOOL_CALL_START\u002FARGS\u002FEND, RUN_FINISHED, RUN_ERROR, STEP_STARTED\u002FSTEP_FINISHED, STATE_SNAPSHOT\u002FDELTA, CUSTOM), toServerSentEventsStream() for SSE format, toHttpStream() for NDJSON format. For backends serving AG-UI events without client packages.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2197,2200,2201],{"name":2198,"slug":2199,"type":16},"API Development","api-development",{"name":2187,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-16T06:04:10.093367",{"slug":2204,"name":2205,"fn":2206,"description":2207,"org":2208,"tags":2209,"stars":24,"repoUrl":25,"updatedAt":2216},"ai-corechat-experience","ai-core\u002Fchat-experience","implement chat experiences with TanStack AI","End-to-end chat implementation: server endpoint with chat() and toServerSentEventsResponse(), client-side useChat hook with fetchServerSentEvents(), message rendering with UIMessage parts, multimodal content, thinking\u002Freasoning display. Covers streaming states, connection adapters, and message format conversions. NOT Vercel AI SDK — uses chat() not streamText().\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2210,2211,2214,2215],{"name":2198,"slug":2199,"type":16},{"name":2212,"slug":2213,"type":16},"Frontend","frontend",{"name":2187,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:11.505241",{"slug":2218,"name":2116,"fn":2219,"description":2220,"org":2221,"tags":2222,"stars":24,"repoUrl":25,"updatedAt":2227},"ai-coreclient-persistence","implement browser chat persistence for TanStack AI","Browser chat persistence on useChat \u002F ChatClient: localStoragePersistence, sessionStoragePersistence, indexedDBPersistence. Client-authoritative (adapter, full transcript) vs server-authoritative (persistence: true, no client cache). Reload restore, pending interrupts, mid-stream rejoin with delivery durability. Use for SPA reload durability — NOT server history alone. No extra package: the adapters ship in the framework packages.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2223,2224,2225,2226],{"name":18,"slug":19,"type":16},{"name":2212,"slug":2213,"type":16},{"name":21,"slug":22,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:53:35.503176",{"slug":2229,"name":2230,"fn":2231,"description":2232,"org":2233,"tags":2234,"stars":24,"repoUrl":25,"updatedAt":2239},"ai-corecustom-backend-integration","ai-core\u002Fcustom-backend-integration","integrate custom backends with TanStack AI","Connect useChat to a non-TanStack-AI backend through custom connection adapters. ConnectConnectionAdapter (single async iterable) vs SubscribeConnectionAdapter (separate subscribe\u002Fsend). Customize fetchServerSentEvents() and fetchHttpStream() with auth headers, custom URLs, and request options. Import from framework package, not @tanstack\u002Fai-client.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2235,2236,2237,2238],{"name":18,"slug":19,"type":16},{"name":2198,"slug":2199,"type":16},{"name":14,"slug":15,"type":16},{"name":10,"slug":9,"type":16},"2026-07-17T06:06:39.855351",27,{"items":2242,"total":2382},[2243,2257,2269,2281,2296,2308,2318,2328,2341,2351,2362,2372],{"slug":2244,"name":2244,"fn":2245,"description":2246,"org":2247,"tags":2248,"stars":2254,"repoUrl":2255,"updatedAt":2256},"aggregation","perform data aggregation in TanStack Table","Aggregate TanStack Table columns independently of grouping, including grand totals, caller-selected row totals, multiple keyed aggregations, custom context-based definitions, grouped merges, manual values, and worker constraints.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2249,2252,2253],{"name":2250,"slug":2251,"type":16},"Data Analysis","data-analysis",{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},28175,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Ftable","2026-07-30T05:25:59.429787",{"slug":2258,"name":2258,"fn":2259,"description":2260,"org":2261,"tags":2262,"stars":2254,"repoUrl":2255,"updatedAt":2268},"api-not-found","diagnose TanStack Table API errors","Diagnose missing TanStack Table v9 exports, options, state slices, and instance methods. Load before inventing an API when code sees a type error, undefined feature method, absent object key, adapter mismatch, or v8-shaped example.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2263,2266,2267],{"name":2264,"slug":2265,"type":16},"Debugging","debugging",{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:05.418735",{"slug":2270,"name":2270,"fn":2271,"description":2272,"org":2273,"tags":2274,"stars":2254,"repoUrl":2255,"updatedAt":2280},"cell-selection","select rectangular cell ranges in tables","Select rectangular cell ranges with cellSelectionFeature: two-corner range state keyed by row and column id, mousedown\u002Fmouseenter handlers, selection edges, render-order resolution under pinning, and autoResetCellSelection. Load when ranges widen unexpectedly after sorting or column reordering, when a drag re-renders the whole table, or when building copy-to-clipboard from a selection.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2275,2276,2277],{"name":2250,"slug":2251,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"UI Components","ui-components","2026-07-30T05:25:38.403427",{"slug":2282,"name":2282,"fn":2283,"description":2284,"org":2285,"tags":2286,"stars":2254,"repoUrl":2255,"updatedAt":2295},"client-vs-server","manage TanStack Table data pipelines","Choose client or server ownership for filtering, grouping, sorting, expanding, and pagination in TanStack Table v9. Load for manual* flags, mixed pipelines, server counts, or deciding which dataset each row-model stage receives.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2287,2290,2291,2294],{"name":2288,"slug":2289,"type":16},"Data Pipeline","data-pipeline",{"name":2212,"slug":2213,"type":16},{"name":2292,"slug":2293,"type":16},"Performance","performance",{"name":10,"slug":9,"type":16},"2026-07-30T05:25:45.400104",{"slug":2297,"name":2297,"fn":2298,"description":2299,"org":2300,"tags":2301,"stars":2254,"repoUrl":2255,"updatedAt":2307},"column-faceting","build faceted filter UIs","Build faceted filter UIs with columnFacetingFeature, facetedRowModel, facetedUniqueValues, and facetedMinMaxValues. Load for facet counts, numeric ranges, own-filter exclusion, or server-page facet completeness.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2302,2305,2306],{"name":2303,"slug":2304,"type":16},"Data Visualization","data-visualization",{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:41.397257",{"slug":2309,"name":2309,"fn":2310,"description":2311,"org":2312,"tags":2313,"stars":2254,"repoUrl":2255,"updatedAt":2317},"column-filtering","implement column filtering in TanStack Table","Filter columns with columnFilteringFeature, filteredRowModel, filterFns, filterMeta, nested-row direction, and manualFiltering. Load for accessor compatibility, controlled filter updaters, fuzzy metadata, or client\u002Fserver ownership.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2314,2315,2316],{"name":2250,"slug":2251,"type":16},{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:53.391632",{"slug":2319,"name":2319,"fn":2320,"description":2321,"org":2322,"tags":2323,"stars":2254,"repoUrl":2255,"updatedAt":2327},"column-ordering","manage TanStack Table column ordering","Control TanStack Table v9 leaf columnOrder with stable IDs while accounting for pinning regions, visibility, and groupedColumnMode precedence. Load for drag-and-drop columns or rendered order that differs from state.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2324,2325,2326],{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:26:03.37801",{"slug":2329,"name":2329,"fn":2330,"description":2331,"org":2332,"tags":2333,"stars":2254,"repoUrl":2255,"updatedAt":2340},"column-pinning","configure column pinning in TanStack Table","Pin columns into logical start, center, and end regions with columnPinningFeature and renderer-owned sticky CSS. Load for RTL offsets, z-index, backgrounds, overflow, widths, gaps, or overlaps.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2334,2337,2338,2339],{"name":2335,"slug":2336,"type":16},"CSS","css",{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:25:55.377366",{"slug":2342,"name":2342,"fn":2343,"description":2344,"org":2345,"tags":2346,"stars":2254,"repoUrl":2255,"updatedAt":2350},"column-resizing","implement column resizing in TanStack Table","Wire columnResizingFeature, header.getResizeHandler, resize mode and direction, pointer or touch events, and performant CSS-variable updates. Load when resize state changes but widths do not, or large tables resize slowly.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2347,2348,2349],{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:25:51.400011",{"slug":2352,"name":2352,"fn":2353,"description":2354,"org":2355,"tags":2356,"stars":2254,"repoUrl":2255,"updatedAt":2361},"column-sizing","configure column sizing in TanStack Table","Use columnSizingFeature numeric size, minSize, maxSize, getSize, getStart, getAfter, and total-size APIs in table, grid, or flex CSS. Load for auto or percentage misconceptions and sizing\u002Fpinning layout mismatch.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2357,2358,2359,2360],{"name":2335,"slug":2336,"type":16},{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:25:48.703799",{"slug":2363,"name":2363,"fn":2364,"description":2365,"org":2366,"tags":2367,"stars":2254,"repoUrl":2255,"updatedAt":2371},"column-visibility","manage column visibility in TanStack Table","Hide columns with columnVisibilityFeature while rendering visibility-aware header, column, and cell collections. Load when hidden columns remain in the DOM, false-versus-absent state is confused, or enableHiding is misunderstood.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2368,2369,2370],{"name":2212,"slug":2213,"type":16},{"name":10,"slug":9,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:25:47.367943",{"slug":2373,"name":2373,"fn":2374,"description":2375,"org":2376,"tags":2377,"stars":2254,"repoUrl":2255,"updatedAt":2381},"core","build data grids with TanStack Table","Use TanStack Table v9 as a headless data-grid state and row-processing engine. Load for first-table architecture, stable data and columns, row numbering with getDisplayIndex, semantic rendering, framework adapter choice, or deciding what Table owns versus the renderer.\n",{"slug":9,"name":10,"logoUrl":11,"githubOrg":10},[2378,2379,2380],{"name":2250,"slug":2251,"type":16},{"name":2212,"slug":2213,"type":16},{"name":2278,"slug":2279,"type":16},"2026-07-30T05:25:52.366295",125]