[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-tanstack-ai-corelocks":3,"mdc--w26vp2-key":53,"related-org-tanstack-ai-corelocks":1471,"related-repo-tanstack-ai-corelocks":1615},{"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-corelocks","ai-core\u002Flocks","manage multi-instance locks in TanStack AI","LockStore, InMemoryLockStore, LocksCapability and withLocks for multi-instance coordination in TanStack AI. Ships in @tanstack\u002Fai — NOT in @tanstack\u002Fai-persistence. Separate from AIPersistence state stores — not a stores key, not composable. InMemoryLockStore vs a distributed (e.g. Cloudflare Durable Object) lock, lease recovery, AbortSignal in critical sections. Use when sandbox or other middleware needs cross-worker mutual exclusion — NOT for storing messages\u002Fruns (use withPersistence).\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},"AI","ai","tag",{"name":18,"slug":19,"type":16},"Concurrency","concurrency",{"name":21,"slug":22,"type":16},"Engineering","engineering",{"name":10,"slug":9,"type":16},2884,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Fai","2026-07-30T05:53:37.544096",null,269,[15,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},[15,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\u002Fskills\u002Fai-core\u002Flocks","---\nname: ai-core\u002Flocks\ndescription: >\n  LockStore, InMemoryLockStore, LocksCapability and withLocks for\n  multi-instance coordination in TanStack AI. Ships in @tanstack\u002Fai — NOT in\n  @tanstack\u002Fai-persistence. Separate from AIPersistence state stores — not a\n  stores key, not composable. InMemoryLockStore vs a distributed (e.g.\n  Cloudflare Durable Object) lock, lease recovery, AbortSignal in critical\n  sections. Use when sandbox or other middleware needs cross-worker mutual\n  exclusion — NOT for storing messages\u002Fruns (use withPersistence).\ntype: sub-skill\nlibrary: tanstack-ai\nlibrary_version: '0.10.0'\nsources:\n  - 'TanStack\u002Fai:docs\u002Fadvanced\u002Flocks.md'\n  - 'TanStack\u002Fai:packages\u002Fai\u002Fsrc\u002Factivities\u002Fchat\u002Fmiddleware\u002Flocks.ts'\n---\n\n# Locks (coordination — not persistence)\n\n> **Dependency note:** This skill builds on ai-core and ai-core\u002Fmiddleware.\n> `withLocks` is a ChatMiddleware that provides a capability. Locks are **not**\n> part of `AIPersistence.stores` and are **not** composed with\n> `composePersistence` — they ship in `@tanstack\u002Fai`, independent of\n> `@tanstack\u002Fai-persistence`.\n\n## Why separate?\n\nState stores answer \"what is durable chat data?\"  \nLocks answer \"who may run this critical section right now?\"\n\n`withPersistence` does **not** automatically lock a whole turn. Take a\nper-thread (or other) lock yourself when multi-writer races matter.\n\n## Wire locks\n\n```ts\nimport { withLocks, InMemoryLockStore } from '@tanstack\u002Fai\u002Flocks'\n\nmiddleware: [\n  withLocks(new InMemoryLockStore()), \u002F\u002F single process\n]\n```\n\nAlongside persistence — optional, locks do not require it:\n\n```ts\nimport { withLocks, InMemoryLockStore } from '@tanstack\u002Fai\u002Flocks'\nimport { withPersistence } from '@tanstack\u002Fai-persistence'\n\nmiddleware: [withPersistence(persistence), withLocks(new InMemoryLockStore())]\n```\n\n`withLocks` provides `LocksCapability` for downstream middleware (e.g.\nsandbox). Order: usually state first, locks alongside or after depending on\nwho consumes the capability.\n\n## The contract\n\n```ts\ninterface LockStore {\n  withLock\u003CT>(key: string, fn: (signal: AbortSignal) => Promise\u003CT>): Promise\u003CT>\n}\n```\n\n`InMemoryLockStore` ships in **`@tanstack\u002Fai\u002Flocks`**: a per-key promise chain,\ncorrect **within a single process only**. Multi-instance deployments need a\ndistributed implementation — you write it. The Cloudflare Durable Object recipe\nis in **ai-persistence\u002Fbuild-cloudflare-adapter** (`@tanstack\u002Fai-persistence`).\n\nType your own store with `defineLock` (autocomplete, no `: LockStore`\nannotation), then hand it to `withLocks`. Acquire the key, run `fn`, release when\n`fn` settles:\n\n```ts\nimport { defineLock, withLocks } from '@tanstack\u002Fai\u002Flocks'\nimport { acquire } from '.\u002Fmy-lock-backend'\n\nconst locks = defineLock({\n  async withLock(key, fn) {\n    const { release, signal } = await acquire(key)\n    try {\n      return await fn(signal)\n    } finally {\n      release()\n    }\n  },\n})\n\nmiddleware: [withLocks(locks)]\n```\n\n## Lease semantics\n\nA good `LockStore`:\n\n- Serializes owners per key,\n- Uses **leases** (or equivalent) so a crashed owner cannot block forever,\n- Passes an `AbortSignal` into the critical section via `withLock`; when the\n  lease is lost, abort so work stops starting external mutations.\n\nCallbacks must honor the signal and pass it to cancellable dependencies.\n`InMemoryLockStore` never aborts its signal — within one process, ownership\ncannot be lost.\n\n## Capability identity\n\nThe `'locks'` capability token lives in `@tanstack\u002Fai\u002Flocks`. Capability identity\nis by **object reference**, so one shared token means a `withLocks` in the chain\nreaches `withSandbox` automatically.\n\n## Common mistakes\n\n### HIGH: Importing locks from `@tanstack\u002Fai-persistence`\n\nThey are not exported there. Use `@tanstack\u002Fai`.\n\n### HIGH: Putting `locks` on `AIPersistence.stores`\n\nNot supported. `stores` accepts only `messages`, `runs`, `interrupts`,\n`metadata` — never `locks`. Use `withLocks`.\n\n### HIGH: Passing `locks` to `composePersistence` overrides\n\nSame rejection, at the override layer. Locks are not state.\n\n### HIGH: Passing `'locks'` to the conformance testkit's `skip`\n\n`skip` accepts only chat state store keys. The suite does not cover locks\nat all — test lease expiry and abort separately.\n\n### HIGH: `InMemoryLockStore` across multiple processes\n\nNo mutual exclusion between machines — use a distributed lock store.\n\n### MEDIUM: Ignoring lease abort\n\nContinuing work after losing the lease races other owners.\n\n## Cross-references\n\n- See also: **ai-core\u002Fmiddleware\u002FSKILL.md** -- the middleware chain and capability plumbing\n- See also: **`@tanstack\u002Fai-persistence` skills** (`skills\u002Fai-persistence\u002FSKILL.md` in that package) -- `ai-persistence\u002Fserver` (state middleware) and `ai-persistence\u002Fbuild-cloudflare-adapter` (Durable Object lock recipe)\n",{"data":54,"body":61},{"name":5,"description":7,"type":55,"library":56,"library_version":57,"sources":58},"sub-skill","tanstack-ai","0.10.0",[59,60],"TanStack\u002Fai:docs\u002Fadvanced\u002Flocks.md","TanStack\u002Fai:packages\u002Fai\u002Fsrc\u002Factivities\u002Fchat\u002Fmiddleware\u002Flocks.ts",{"type":62,"children":63},"root",[64,73,143,150,161,178,184,333,338,481,499,505,655,696,739,1098,1104,1116,1159,1171,1177,1219,1225,1237,1248,1267,1324,1344,1349,1367,1377,1390,1395,1401,1406,1412,1465],{"type":65,"tag":66,"props":67,"children":69},"element","h1",{"id":68},"locks-coordination-not-persistence",[70],{"type":71,"value":72},"text","Locks (coordination — not persistence)",{"type":65,"tag":74,"props":75,"children":76},"blockquote",{},[77],{"type":65,"tag":78,"props":79,"children":80},"p",{},[81,87,89,96,98,103,105,111,113,117,119,125,127,133,135,141],{"type":65,"tag":82,"props":83,"children":84},"strong",{},[85],{"type":71,"value":86},"Dependency note:",{"type":71,"value":88}," This skill builds on ai-core and ai-core\u002Fmiddleware.\n",{"type":65,"tag":90,"props":91,"children":93},"code",{"className":92},[],[94],{"type":71,"value":95},"withLocks",{"type":71,"value":97}," is a ChatMiddleware that provides a capability. Locks are ",{"type":65,"tag":82,"props":99,"children":100},{},[101],{"type":71,"value":102},"not",{"type":71,"value":104},"\npart of ",{"type":65,"tag":90,"props":106,"children":108},{"className":107},[],[109],{"type":71,"value":110},"AIPersistence.stores",{"type":71,"value":112}," and are ",{"type":65,"tag":82,"props":114,"children":115},{},[116],{"type":71,"value":102},{"type":71,"value":118}," composed with\n",{"type":65,"tag":90,"props":120,"children":122},{"className":121},[],[123],{"type":71,"value":124},"composePersistence",{"type":71,"value":126}," — they ship in ",{"type":65,"tag":90,"props":128,"children":130},{"className":129},[],[131],{"type":71,"value":132},"@tanstack\u002Fai",{"type":71,"value":134},", independent of\n",{"type":65,"tag":90,"props":136,"children":138},{"className":137},[],[139],{"type":71,"value":140},"@tanstack\u002Fai-persistence",{"type":71,"value":142},".",{"type":65,"tag":144,"props":145,"children":147},"h2",{"id":146},"why-separate",[148],{"type":71,"value":149},"Why separate?",{"type":65,"tag":78,"props":151,"children":152},{},[153,155,159],{"type":71,"value":154},"State stores answer \"what is durable chat data?\"",{"type":65,"tag":156,"props":157,"children":158},"br",{},[],{"type":71,"value":160},"\nLocks answer \"who may run this critical section right now?\"",{"type":65,"tag":78,"props":162,"children":163},{},[164,170,172,176],{"type":65,"tag":90,"props":165,"children":167},{"className":166},[],[168],{"type":71,"value":169},"withPersistence",{"type":71,"value":171}," does ",{"type":65,"tag":82,"props":173,"children":174},{},[175],{"type":71,"value":102},{"type":71,"value":177}," automatically lock a whole turn. Take a\nper-thread (or other) lock yourself when multi-writer races matter.",{"type":65,"tag":144,"props":179,"children":181},{"id":180},"wire-locks",[182],{"type":71,"value":183},"Wire locks",{"type":65,"tag":185,"props":186,"children":191},"pre",{"className":187,"code":188,"language":189,"meta":190,"style":190},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { withLocks, InMemoryLockStore } from '@tanstack\u002Fai\u002Flocks'\n\nmiddleware: [\n  withLocks(new InMemoryLockStore()), \u002F\u002F single process\n]\n","ts","",[192],{"type":65,"tag":90,"props":193,"children":194},{"__ignoreMap":190},[195,255,265,285,324],{"type":65,"tag":196,"props":197,"children":200},"span",{"class":198,"line":199},"line",1,[201,207,213,219,224,229,234,239,244,250],{"type":65,"tag":196,"props":202,"children":204},{"style":203},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[205],{"type":71,"value":206},"import",{"type":65,"tag":196,"props":208,"children":210},{"style":209},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[211],{"type":71,"value":212}," {",{"type":65,"tag":196,"props":214,"children":216},{"style":215},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[217],{"type":71,"value":218}," withLocks",{"type":65,"tag":196,"props":220,"children":221},{"style":209},[222],{"type":71,"value":223},",",{"type":65,"tag":196,"props":225,"children":226},{"style":215},[227],{"type":71,"value":228}," InMemoryLockStore",{"type":65,"tag":196,"props":230,"children":231},{"style":209},[232],{"type":71,"value":233}," }",{"type":65,"tag":196,"props":235,"children":236},{"style":203},[237],{"type":71,"value":238}," from",{"type":65,"tag":196,"props":240,"children":241},{"style":209},[242],{"type":71,"value":243}," '",{"type":65,"tag":196,"props":245,"children":247},{"style":246},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[248],{"type":71,"value":249},"@tanstack\u002Fai\u002Flocks",{"type":65,"tag":196,"props":251,"children":252},{"style":209},[253],{"type":71,"value":254},"'\n",{"type":65,"tag":196,"props":256,"children":258},{"class":198,"line":257},2,[259],{"type":65,"tag":196,"props":260,"children":262},{"emptyLinePlaceholder":261},true,[263],{"type":71,"value":264},"\n",{"type":65,"tag":196,"props":266,"children":268},{"class":198,"line":267},3,[269,275,280],{"type":65,"tag":196,"props":270,"children":272},{"style":271},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[273],{"type":71,"value":274},"middleware",{"type":65,"tag":196,"props":276,"children":277},{"style":209},[278],{"type":71,"value":279},":",{"type":65,"tag":196,"props":281,"children":282},{"style":215},[283],{"type":71,"value":284}," [\n",{"type":65,"tag":196,"props":286,"children":288},{"class":198,"line":287},4,[289,295,300,305,309,314,318],{"type":65,"tag":196,"props":290,"children":292},{"style":291},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[293],{"type":71,"value":294},"  withLocks",{"type":65,"tag":196,"props":296,"children":297},{"style":215},[298],{"type":71,"value":299},"(",{"type":65,"tag":196,"props":301,"children":302},{"style":209},[303],{"type":71,"value":304},"new",{"type":65,"tag":196,"props":306,"children":307},{"style":291},[308],{"type":71,"value":228},{"type":65,"tag":196,"props":310,"children":311},{"style":215},[312],{"type":71,"value":313},"())",{"type":65,"tag":196,"props":315,"children":316},{"style":209},[317],{"type":71,"value":223},{"type":65,"tag":196,"props":319,"children":321},{"style":320},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[322],{"type":71,"value":323}," \u002F\u002F single process\n",{"type":65,"tag":196,"props":325,"children":327},{"class":198,"line":326},5,[328],{"type":65,"tag":196,"props":329,"children":330},{"style":215},[331],{"type":71,"value":332},"]\n",{"type":65,"tag":78,"props":334,"children":335},{},[336],{"type":71,"value":337},"Alongside persistence — optional, locks do not require it:",{"type":65,"tag":185,"props":339,"children":341},{"className":187,"code":340,"language":189,"meta":190,"style":190},"import { withLocks, InMemoryLockStore } from '@tanstack\u002Fai\u002Flocks'\nimport { withPersistence } from '@tanstack\u002Fai-persistence'\n\nmiddleware: [withPersistence(persistence), withLocks(new InMemoryLockStore())]\n",[342],{"type":65,"tag":90,"props":343,"children":344},{"__ignoreMap":190},[345,388,424,431],{"type":65,"tag":196,"props":346,"children":347},{"class":198,"line":199},[348,352,356,360,364,368,372,376,380,384],{"type":65,"tag":196,"props":349,"children":350},{"style":203},[351],{"type":71,"value":206},{"type":65,"tag":196,"props":353,"children":354},{"style":209},[355],{"type":71,"value":212},{"type":65,"tag":196,"props":357,"children":358},{"style":215},[359],{"type":71,"value":218},{"type":65,"tag":196,"props":361,"children":362},{"style":209},[363],{"type":71,"value":223},{"type":65,"tag":196,"props":365,"children":366},{"style":215},[367],{"type":71,"value":228},{"type":65,"tag":196,"props":369,"children":370},{"style":209},[371],{"type":71,"value":233},{"type":65,"tag":196,"props":373,"children":374},{"style":203},[375],{"type":71,"value":238},{"type":65,"tag":196,"props":377,"children":378},{"style":209},[379],{"type":71,"value":243},{"type":65,"tag":196,"props":381,"children":382},{"style":246},[383],{"type":71,"value":249},{"type":65,"tag":196,"props":385,"children":386},{"style":209},[387],{"type":71,"value":254},{"type":65,"tag":196,"props":389,"children":390},{"class":198,"line":257},[391,395,399,404,408,412,416,420],{"type":65,"tag":196,"props":392,"children":393},{"style":203},[394],{"type":71,"value":206},{"type":65,"tag":196,"props":396,"children":397},{"style":209},[398],{"type":71,"value":212},{"type":65,"tag":196,"props":400,"children":401},{"style":215},[402],{"type":71,"value":403}," withPersistence",{"type":65,"tag":196,"props":405,"children":406},{"style":209},[407],{"type":71,"value":233},{"type":65,"tag":196,"props":409,"children":410},{"style":203},[411],{"type":71,"value":238},{"type":65,"tag":196,"props":413,"children":414},{"style":209},[415],{"type":71,"value":243},{"type":65,"tag":196,"props":417,"children":418},{"style":246},[419],{"type":71,"value":140},{"type":65,"tag":196,"props":421,"children":422},{"style":209},[423],{"type":71,"value":254},{"type":65,"tag":196,"props":425,"children":426},{"class":198,"line":267},[427],{"type":65,"tag":196,"props":428,"children":429},{"emptyLinePlaceholder":261},[430],{"type":71,"value":264},{"type":65,"tag":196,"props":432,"children":433},{"class":198,"line":287},[434,438,442,447,451,456,460,464,468,472,476],{"type":65,"tag":196,"props":435,"children":436},{"style":271},[437],{"type":71,"value":274},{"type":65,"tag":196,"props":439,"children":440},{"style":209},[441],{"type":71,"value":279},{"type":65,"tag":196,"props":443,"children":444},{"style":215},[445],{"type":71,"value":446}," [",{"type":65,"tag":196,"props":448,"children":449},{"style":291},[450],{"type":71,"value":169},{"type":65,"tag":196,"props":452,"children":453},{"style":215},[454],{"type":71,"value":455},"(persistence)",{"type":65,"tag":196,"props":457,"children":458},{"style":209},[459],{"type":71,"value":223},{"type":65,"tag":196,"props":461,"children":462},{"style":291},[463],{"type":71,"value":218},{"type":65,"tag":196,"props":465,"children":466},{"style":215},[467],{"type":71,"value":299},{"type":65,"tag":196,"props":469,"children":470},{"style":209},[471],{"type":71,"value":304},{"type":65,"tag":196,"props":473,"children":474},{"style":291},[475],{"type":71,"value":228},{"type":65,"tag":196,"props":477,"children":478},{"style":215},[479],{"type":71,"value":480},"())]\n",{"type":65,"tag":78,"props":482,"children":483},{},[484,489,491,497],{"type":65,"tag":90,"props":485,"children":487},{"className":486},[],[488],{"type":71,"value":95},{"type":71,"value":490}," provides ",{"type":65,"tag":90,"props":492,"children":494},{"className":493},[],[495],{"type":71,"value":496},"LocksCapability",{"type":71,"value":498}," for downstream middleware (e.g.\nsandbox). Order: usually state first, locks alongside or after depending on\nwho consumes the capability.",{"type":65,"tag":144,"props":500,"children":502},{"id":501},"the-contract",[503],{"type":71,"value":504},"The contract",{"type":65,"tag":185,"props":506,"children":508},{"className":187,"code":507,"language":189,"meta":190,"style":190},"interface LockStore {\n  withLock\u003CT>(key: string, fn: (signal: AbortSignal) => Promise\u003CT>): Promise\u003CT>\n}\n",[509],{"type":65,"tag":90,"props":510,"children":511},{"__ignoreMap":190},[512,531,647],{"type":65,"tag":196,"props":513,"children":514},{"class":198,"line":199},[515,521,526],{"type":65,"tag":196,"props":516,"children":518},{"style":517},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[519],{"type":71,"value":520},"interface",{"type":65,"tag":196,"props":522,"children":523},{"style":271},[524],{"type":71,"value":525}," LockStore",{"type":65,"tag":196,"props":527,"children":528},{"style":209},[529],{"type":71,"value":530}," {\n",{"type":65,"tag":196,"props":532,"children":533},{"class":198,"line":257},[534,540,545,550,555,561,565,570,574,579,583,588,593,597,602,607,612,617,621,625,630,634,638,642],{"type":65,"tag":196,"props":535,"children":537},{"style":536},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[538],{"type":71,"value":539},"  withLock",{"type":65,"tag":196,"props":541,"children":542},{"style":209},[543],{"type":71,"value":544},"\u003C",{"type":65,"tag":196,"props":546,"children":547},{"style":271},[548],{"type":71,"value":549},"T",{"type":65,"tag":196,"props":551,"children":552},{"style":209},[553],{"type":71,"value":554},">(",{"type":65,"tag":196,"props":556,"children":558},{"style":557},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[559],{"type":71,"value":560},"key",{"type":65,"tag":196,"props":562,"children":563},{"style":209},[564],{"type":71,"value":279},{"type":65,"tag":196,"props":566,"children":567},{"style":271},[568],{"type":71,"value":569}," string",{"type":65,"tag":196,"props":571,"children":572},{"style":209},[573],{"type":71,"value":223},{"type":65,"tag":196,"props":575,"children":576},{"style":291},[577],{"type":71,"value":578}," fn",{"type":65,"tag":196,"props":580,"children":581},{"style":209},[582],{"type":71,"value":279},{"type":65,"tag":196,"props":584,"children":585},{"style":209},[586],{"type":71,"value":587}," (",{"type":65,"tag":196,"props":589,"children":590},{"style":557},[591],{"type":71,"value":592},"signal",{"type":65,"tag":196,"props":594,"children":595},{"style":209},[596],{"type":71,"value":279},{"type":65,"tag":196,"props":598,"children":599},{"style":271},[600],{"type":71,"value":601}," AbortSignal",{"type":65,"tag":196,"props":603,"children":604},{"style":209},[605],{"type":71,"value":606},")",{"type":65,"tag":196,"props":608,"children":609},{"style":517},[610],{"type":71,"value":611}," =>",{"type":65,"tag":196,"props":613,"children":614},{"style":271},[615],{"type":71,"value":616}," Promise",{"type":65,"tag":196,"props":618,"children":619},{"style":209},[620],{"type":71,"value":544},{"type":65,"tag":196,"props":622,"children":623},{"style":271},[624],{"type":71,"value":549},{"type":65,"tag":196,"props":626,"children":627},{"style":209},[628],{"type":71,"value":629},">):",{"type":65,"tag":196,"props":631,"children":632},{"style":271},[633],{"type":71,"value":616},{"type":65,"tag":196,"props":635,"children":636},{"style":209},[637],{"type":71,"value":544},{"type":65,"tag":196,"props":639,"children":640},{"style":271},[641],{"type":71,"value":549},{"type":65,"tag":196,"props":643,"children":644},{"style":209},[645],{"type":71,"value":646},">\n",{"type":65,"tag":196,"props":648,"children":649},{"class":198,"line":267},[650],{"type":65,"tag":196,"props":651,"children":652},{"style":209},[653],{"type":71,"value":654},"}\n",{"type":65,"tag":78,"props":656,"children":657},{},[658,664,666,674,676,681,683,688,689,694],{"type":65,"tag":90,"props":659,"children":661},{"className":660},[],[662],{"type":71,"value":663},"InMemoryLockStore",{"type":71,"value":665}," ships in ",{"type":65,"tag":82,"props":667,"children":668},{},[669],{"type":65,"tag":90,"props":670,"children":672},{"className":671},[],[673],{"type":71,"value":249},{"type":71,"value":675},": a per-key promise chain,\ncorrect ",{"type":65,"tag":82,"props":677,"children":678},{},[679],{"type":71,"value":680},"within a single process only",{"type":71,"value":682},". Multi-instance deployments need a\ndistributed implementation — you write it. The Cloudflare Durable Object recipe\nis in ",{"type":65,"tag":82,"props":684,"children":685},{},[686],{"type":71,"value":687},"ai-persistence\u002Fbuild-cloudflare-adapter",{"type":71,"value":587},{"type":65,"tag":90,"props":690,"children":692},{"className":691},[],[693],{"type":71,"value":140},{"type":71,"value":695},").",{"type":65,"tag":78,"props":697,"children":698},{},[699,701,707,709,715,717,722,724,730,732,737],{"type":71,"value":700},"Type your own store with ",{"type":65,"tag":90,"props":702,"children":704},{"className":703},[],[705],{"type":71,"value":706},"defineLock",{"type":71,"value":708}," (autocomplete, no ",{"type":65,"tag":90,"props":710,"children":712},{"className":711},[],[713],{"type":71,"value":714},": LockStore",{"type":71,"value":716},"\nannotation), then hand it to ",{"type":65,"tag":90,"props":718,"children":720},{"className":719},[],[721],{"type":71,"value":95},{"type":71,"value":723},". Acquire the key, run ",{"type":65,"tag":90,"props":725,"children":727},{"className":726},[],[728],{"type":71,"value":729},"fn",{"type":71,"value":731},", release when\n",{"type":65,"tag":90,"props":733,"children":735},{"className":734},[],[736],{"type":71,"value":729},{"type":71,"value":738}," settles:",{"type":65,"tag":185,"props":740,"children":742},{"className":187,"code":741,"language":189,"meta":190,"style":190},"import { defineLock, withLocks } from '@tanstack\u002Fai\u002Flocks'\nimport { acquire } from '.\u002Fmy-lock-backend'\n\nconst locks = defineLock({\n  async withLock(key, fn) {\n    const { release, signal } = await acquire(key)\n    try {\n      return await fn(signal)\n    } finally {\n      release()\n    }\n  },\n})\n\nmiddleware: [withLocks(locks)]\n",[743],{"type":65,"tag":90,"props":744,"children":745},{"__ignoreMap":190},[746,790,827,834,865,902,960,973,1002,1020,1034,1043,1052,1065,1073],{"type":65,"tag":196,"props":747,"children":748},{"class":198,"line":199},[749,753,757,762,766,770,774,778,782,786],{"type":65,"tag":196,"props":750,"children":751},{"style":203},[752],{"type":71,"value":206},{"type":65,"tag":196,"props":754,"children":755},{"style":209},[756],{"type":71,"value":212},{"type":65,"tag":196,"props":758,"children":759},{"style":215},[760],{"type":71,"value":761}," defineLock",{"type":65,"tag":196,"props":763,"children":764},{"style":209},[765],{"type":71,"value":223},{"type":65,"tag":196,"props":767,"children":768},{"style":215},[769],{"type":71,"value":218},{"type":65,"tag":196,"props":771,"children":772},{"style":209},[773],{"type":71,"value":233},{"type":65,"tag":196,"props":775,"children":776},{"style":203},[777],{"type":71,"value":238},{"type":65,"tag":196,"props":779,"children":780},{"style":209},[781],{"type":71,"value":243},{"type":65,"tag":196,"props":783,"children":784},{"style":246},[785],{"type":71,"value":249},{"type":65,"tag":196,"props":787,"children":788},{"style":209},[789],{"type":71,"value":254},{"type":65,"tag":196,"props":791,"children":792},{"class":198,"line":257},[793,797,801,806,810,814,818,823],{"type":65,"tag":196,"props":794,"children":795},{"style":203},[796],{"type":71,"value":206},{"type":65,"tag":196,"props":798,"children":799},{"style":209},[800],{"type":71,"value":212},{"type":65,"tag":196,"props":802,"children":803},{"style":215},[804],{"type":71,"value":805}," acquire",{"type":65,"tag":196,"props":807,"children":808},{"style":209},[809],{"type":71,"value":233},{"type":65,"tag":196,"props":811,"children":812},{"style":203},[813],{"type":71,"value":238},{"type":65,"tag":196,"props":815,"children":816},{"style":209},[817],{"type":71,"value":243},{"type":65,"tag":196,"props":819,"children":820},{"style":246},[821],{"type":71,"value":822},".\u002Fmy-lock-backend",{"type":65,"tag":196,"props":824,"children":825},{"style":209},[826],{"type":71,"value":254},{"type":65,"tag":196,"props":828,"children":829},{"class":198,"line":267},[830],{"type":65,"tag":196,"props":831,"children":832},{"emptyLinePlaceholder":261},[833],{"type":71,"value":264},{"type":65,"tag":196,"props":835,"children":836},{"class":198,"line":287},[837,842,847,852,856,860],{"type":65,"tag":196,"props":838,"children":839},{"style":517},[840],{"type":71,"value":841},"const",{"type":65,"tag":196,"props":843,"children":844},{"style":215},[845],{"type":71,"value":846}," locks ",{"type":65,"tag":196,"props":848,"children":849},{"style":209},[850],{"type":71,"value":851},"=",{"type":65,"tag":196,"props":853,"children":854},{"style":291},[855],{"type":71,"value":761},{"type":65,"tag":196,"props":857,"children":858},{"style":215},[859],{"type":71,"value":299},{"type":65,"tag":196,"props":861,"children":862},{"style":209},[863],{"type":71,"value":864},"{\n",{"type":65,"tag":196,"props":866,"children":867},{"class":198,"line":326},[868,873,878,882,886,890,894,898],{"type":65,"tag":196,"props":869,"children":870},{"style":517},[871],{"type":71,"value":872},"  async",{"type":65,"tag":196,"props":874,"children":875},{"style":536},[876],{"type":71,"value":877}," withLock",{"type":65,"tag":196,"props":879,"children":880},{"style":209},[881],{"type":71,"value":299},{"type":65,"tag":196,"props":883,"children":884},{"style":557},[885],{"type":71,"value":560},{"type":65,"tag":196,"props":887,"children":888},{"style":209},[889],{"type":71,"value":223},{"type":65,"tag":196,"props":891,"children":892},{"style":557},[893],{"type":71,"value":578},{"type":65,"tag":196,"props":895,"children":896},{"style":209},[897],{"type":71,"value":606},{"type":65,"tag":196,"props":899,"children":900},{"style":209},[901],{"type":71,"value":530},{"type":65,"tag":196,"props":903,"children":905},{"class":198,"line":904},6,[906,911,915,920,924,929,933,938,943,947,951,955],{"type":65,"tag":196,"props":907,"children":908},{"style":517},[909],{"type":71,"value":910},"    const",{"type":65,"tag":196,"props":912,"children":913},{"style":209},[914],{"type":71,"value":212},{"type":65,"tag":196,"props":916,"children":917},{"style":215},[918],{"type":71,"value":919}," release",{"type":65,"tag":196,"props":921,"children":922},{"style":209},[923],{"type":71,"value":223},{"type":65,"tag":196,"props":925,"children":926},{"style":215},[927],{"type":71,"value":928}," signal",{"type":65,"tag":196,"props":930,"children":931},{"style":209},[932],{"type":71,"value":233},{"type":65,"tag":196,"props":934,"children":935},{"style":209},[936],{"type":71,"value":937}," =",{"type":65,"tag":196,"props":939,"children":940},{"style":203},[941],{"type":71,"value":942}," await",{"type":65,"tag":196,"props":944,"children":945},{"style":291},[946],{"type":71,"value":805},{"type":65,"tag":196,"props":948,"children":949},{"style":536},[950],{"type":71,"value":299},{"type":65,"tag":196,"props":952,"children":953},{"style":215},[954],{"type":71,"value":560},{"type":65,"tag":196,"props":956,"children":957},{"style":536},[958],{"type":71,"value":959},")\n",{"type":65,"tag":196,"props":961,"children":963},{"class":198,"line":962},7,[964,969],{"type":65,"tag":196,"props":965,"children":966},{"style":203},[967],{"type":71,"value":968},"    try",{"type":65,"tag":196,"props":970,"children":971},{"style":209},[972],{"type":71,"value":530},{"type":65,"tag":196,"props":974,"children":976},{"class":198,"line":975},8,[977,982,986,990,994,998],{"type":65,"tag":196,"props":978,"children":979},{"style":203},[980],{"type":71,"value":981},"      return",{"type":65,"tag":196,"props":983,"children":984},{"style":203},[985],{"type":71,"value":942},{"type":65,"tag":196,"props":987,"children":988},{"style":291},[989],{"type":71,"value":578},{"type":65,"tag":196,"props":991,"children":992},{"style":536},[993],{"type":71,"value":299},{"type":65,"tag":196,"props":995,"children":996},{"style":215},[997],{"type":71,"value":592},{"type":65,"tag":196,"props":999,"children":1000},{"style":536},[1001],{"type":71,"value":959},{"type":65,"tag":196,"props":1003,"children":1005},{"class":198,"line":1004},9,[1006,1011,1016],{"type":65,"tag":196,"props":1007,"children":1008},{"style":209},[1009],{"type":71,"value":1010},"    }",{"type":65,"tag":196,"props":1012,"children":1013},{"style":203},[1014],{"type":71,"value":1015}," finally",{"type":65,"tag":196,"props":1017,"children":1018},{"style":209},[1019],{"type":71,"value":530},{"type":65,"tag":196,"props":1021,"children":1023},{"class":198,"line":1022},10,[1024,1029],{"type":65,"tag":196,"props":1025,"children":1026},{"style":291},[1027],{"type":71,"value":1028},"      release",{"type":65,"tag":196,"props":1030,"children":1031},{"style":536},[1032],{"type":71,"value":1033},"()\n",{"type":65,"tag":196,"props":1035,"children":1037},{"class":198,"line":1036},11,[1038],{"type":65,"tag":196,"props":1039,"children":1040},{"style":209},[1041],{"type":71,"value":1042},"    }\n",{"type":65,"tag":196,"props":1044,"children":1046},{"class":198,"line":1045},12,[1047],{"type":65,"tag":196,"props":1048,"children":1049},{"style":209},[1050],{"type":71,"value":1051},"  },\n",{"type":65,"tag":196,"props":1053,"children":1055},{"class":198,"line":1054},13,[1056,1061],{"type":65,"tag":196,"props":1057,"children":1058},{"style":209},[1059],{"type":71,"value":1060},"}",{"type":65,"tag":196,"props":1062,"children":1063},{"style":215},[1064],{"type":71,"value":959},{"type":65,"tag":196,"props":1066,"children":1068},{"class":198,"line":1067},14,[1069],{"type":65,"tag":196,"props":1070,"children":1071},{"emptyLinePlaceholder":261},[1072],{"type":71,"value":264},{"type":65,"tag":196,"props":1074,"children":1076},{"class":198,"line":1075},15,[1077,1081,1085,1089,1093],{"type":65,"tag":196,"props":1078,"children":1079},{"style":271},[1080],{"type":71,"value":274},{"type":65,"tag":196,"props":1082,"children":1083},{"style":209},[1084],{"type":71,"value":279},{"type":65,"tag":196,"props":1086,"children":1087},{"style":215},[1088],{"type":71,"value":446},{"type":65,"tag":196,"props":1090,"children":1091},{"style":291},[1092],{"type":71,"value":95},{"type":65,"tag":196,"props":1094,"children":1095},{"style":215},[1096],{"type":71,"value":1097},"(locks)]\n",{"type":65,"tag":144,"props":1099,"children":1101},{"id":1100},"lease-semantics",[1102],{"type":71,"value":1103},"Lease semantics",{"type":65,"tag":78,"props":1105,"children":1106},{},[1107,1109,1115],{"type":71,"value":1108},"A good ",{"type":65,"tag":90,"props":1110,"children":1112},{"className":1111},[],[1113],{"type":71,"value":1114},"LockStore",{"type":71,"value":279},{"type":65,"tag":1117,"props":1118,"children":1119},"ul",{},[1120,1126,1138],{"type":65,"tag":1121,"props":1122,"children":1123},"li",{},[1124],{"type":71,"value":1125},"Serializes owners per key,",{"type":65,"tag":1121,"props":1127,"children":1128},{},[1129,1131,1136],{"type":71,"value":1130},"Uses ",{"type":65,"tag":82,"props":1132,"children":1133},{},[1134],{"type":71,"value":1135},"leases",{"type":71,"value":1137}," (or equivalent) so a crashed owner cannot block forever,",{"type":65,"tag":1121,"props":1139,"children":1140},{},[1141,1143,1149,1151,1157],{"type":71,"value":1142},"Passes an ",{"type":65,"tag":90,"props":1144,"children":1146},{"className":1145},[],[1147],{"type":71,"value":1148},"AbortSignal",{"type":71,"value":1150}," into the critical section via ",{"type":65,"tag":90,"props":1152,"children":1154},{"className":1153},[],[1155],{"type":71,"value":1156},"withLock",{"type":71,"value":1158},"; when the\nlease is lost, abort so work stops starting external mutations.",{"type":65,"tag":78,"props":1160,"children":1161},{},[1162,1164,1169],{"type":71,"value":1163},"Callbacks must honor the signal and pass it to cancellable dependencies.\n",{"type":65,"tag":90,"props":1165,"children":1167},{"className":1166},[],[1168],{"type":71,"value":663},{"type":71,"value":1170}," never aborts its signal — within one process, ownership\ncannot be lost.",{"type":65,"tag":144,"props":1172,"children":1174},{"id":1173},"capability-identity",[1175],{"type":71,"value":1176},"Capability identity",{"type":65,"tag":78,"props":1178,"children":1179},{},[1180,1182,1188,1190,1195,1197,1202,1204,1209,1211,1217],{"type":71,"value":1181},"The ",{"type":65,"tag":90,"props":1183,"children":1185},{"className":1184},[],[1186],{"type":71,"value":1187},"'locks'",{"type":71,"value":1189}," capability token lives in ",{"type":65,"tag":90,"props":1191,"children":1193},{"className":1192},[],[1194],{"type":71,"value":249},{"type":71,"value":1196},". Capability identity\nis by ",{"type":65,"tag":82,"props":1198,"children":1199},{},[1200],{"type":71,"value":1201},"object reference",{"type":71,"value":1203},", so one shared token means a ",{"type":65,"tag":90,"props":1205,"children":1207},{"className":1206},[],[1208],{"type":71,"value":95},{"type":71,"value":1210}," in the chain\nreaches ",{"type":65,"tag":90,"props":1212,"children":1214},{"className":1213},[],[1215],{"type":71,"value":1216},"withSandbox",{"type":71,"value":1218}," automatically.",{"type":65,"tag":144,"props":1220,"children":1222},{"id":1221},"common-mistakes",[1223],{"type":71,"value":1224},"Common mistakes",{"type":65,"tag":1226,"props":1227,"children":1229},"h3",{"id":1228},"high-importing-locks-from-tanstackai-persistence",[1230,1232],{"type":71,"value":1231},"HIGH: Importing locks from ",{"type":65,"tag":90,"props":1233,"children":1235},{"className":1234},[],[1236],{"type":71,"value":140},{"type":65,"tag":78,"props":1238,"children":1239},{},[1240,1242,1247],{"type":71,"value":1241},"They are not exported there. Use ",{"type":65,"tag":90,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":71,"value":132},{"type":71,"value":142},{"type":65,"tag":1226,"props":1249,"children":1251},{"id":1250},"high-putting-locks-on-aipersistencestores",[1252,1254,1260,1262],{"type":71,"value":1253},"HIGH: Putting ",{"type":65,"tag":90,"props":1255,"children":1257},{"className":1256},[],[1258],{"type":71,"value":1259},"locks",{"type":71,"value":1261}," on ",{"type":65,"tag":90,"props":1263,"children":1265},{"className":1264},[],[1266],{"type":71,"value":110},{"type":65,"tag":78,"props":1268,"children":1269},{},[1270,1272,1278,1280,1286,1288,1294,1295,1301,1303,1309,1311,1316,1318,1323],{"type":71,"value":1271},"Not supported. ",{"type":65,"tag":90,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":71,"value":1277},"stores",{"type":71,"value":1279}," accepts only ",{"type":65,"tag":90,"props":1281,"children":1283},{"className":1282},[],[1284],{"type":71,"value":1285},"messages",{"type":71,"value":1287},", ",{"type":65,"tag":90,"props":1289,"children":1291},{"className":1290},[],[1292],{"type":71,"value":1293},"runs",{"type":71,"value":1287},{"type":65,"tag":90,"props":1296,"children":1298},{"className":1297},[],[1299],{"type":71,"value":1300},"interrupts",{"type":71,"value":1302},",\n",{"type":65,"tag":90,"props":1304,"children":1306},{"className":1305},[],[1307],{"type":71,"value":1308},"metadata",{"type":71,"value":1310}," — never ",{"type":65,"tag":90,"props":1312,"children":1314},{"className":1313},[],[1315],{"type":71,"value":1259},{"type":71,"value":1317},". Use ",{"type":65,"tag":90,"props":1319,"children":1321},{"className":1320},[],[1322],{"type":71,"value":95},{"type":71,"value":142},{"type":65,"tag":1226,"props":1325,"children":1327},{"id":1326},"high-passing-locks-to-composepersistence-overrides",[1328,1330,1335,1337,1342],{"type":71,"value":1329},"HIGH: Passing ",{"type":65,"tag":90,"props":1331,"children":1333},{"className":1332},[],[1334],{"type":71,"value":1259},{"type":71,"value":1336}," to ",{"type":65,"tag":90,"props":1338,"children":1340},{"className":1339},[],[1341],{"type":71,"value":124},{"type":71,"value":1343}," overrides",{"type":65,"tag":78,"props":1345,"children":1346},{},[1347],{"type":71,"value":1348},"Same rejection, at the override layer. Locks are not state.",{"type":65,"tag":1226,"props":1350,"children":1352},{"id":1351},"high-passing-locks-to-the-conformance-testkits-skip",[1353,1354,1359,1361],{"type":71,"value":1329},{"type":65,"tag":90,"props":1355,"children":1357},{"className":1356},[],[1358],{"type":71,"value":1187},{"type":71,"value":1360}," to the conformance testkit's ",{"type":65,"tag":90,"props":1362,"children":1364},{"className":1363},[],[1365],{"type":71,"value":1366},"skip",{"type":65,"tag":78,"props":1368,"children":1369},{},[1370,1375],{"type":65,"tag":90,"props":1371,"children":1373},{"className":1372},[],[1374],{"type":71,"value":1366},{"type":71,"value":1376}," accepts only chat state store keys. The suite does not cover locks\nat all — test lease expiry and abort separately.",{"type":65,"tag":1226,"props":1378,"children":1380},{"id":1379},"high-inmemorylockstore-across-multiple-processes",[1381,1383,1388],{"type":71,"value":1382},"HIGH: ",{"type":65,"tag":90,"props":1384,"children":1386},{"className":1385},[],[1387],{"type":71,"value":663},{"type":71,"value":1389}," across multiple processes",{"type":65,"tag":78,"props":1391,"children":1392},{},[1393],{"type":71,"value":1394},"No mutual exclusion between machines — use a distributed lock store.",{"type":65,"tag":1226,"props":1396,"children":1398},{"id":1397},"medium-ignoring-lease-abort",[1399],{"type":71,"value":1400},"MEDIUM: Ignoring lease abort",{"type":65,"tag":78,"props":1402,"children":1403},{},[1404],{"type":71,"value":1405},"Continuing work after losing the lease races other owners.",{"type":65,"tag":144,"props":1407,"children":1409},{"id":1408},"cross-references",[1410],{"type":71,"value":1411},"Cross-references",{"type":65,"tag":1117,"props":1413,"children":1414},{},[1415,1427],{"type":65,"tag":1121,"props":1416,"children":1417},{},[1418,1420,1425],{"type":71,"value":1419},"See also: ",{"type":65,"tag":82,"props":1421,"children":1422},{},[1423],{"type":71,"value":1424},"ai-core\u002Fmiddleware\u002FSKILL.md",{"type":71,"value":1426}," -- the middleware chain and capability plumbing",{"type":65,"tag":1121,"props":1428,"children":1429},{},[1430,1431,1441,1442,1448,1450,1456,1458,1463],{"type":71,"value":1419},{"type":65,"tag":82,"props":1432,"children":1433},{},[1434,1439],{"type":65,"tag":90,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":71,"value":140},{"type":71,"value":1440}," skills",{"type":71,"value":587},{"type":65,"tag":90,"props":1443,"children":1445},{"className":1444},[],[1446],{"type":71,"value":1447},"skills\u002Fai-persistence\u002FSKILL.md",{"type":71,"value":1449}," in that package) -- ",{"type":65,"tag":90,"props":1451,"children":1453},{"className":1452},[],[1454],{"type":71,"value":1455},"ai-persistence\u002Fserver",{"type":71,"value":1457}," (state middleware) and ",{"type":65,"tag":90,"props":1459,"children":1461},{"className":1460},[],[1462],{"type":71,"value":687},{"type":71,"value":1464}," (Durable Object lock recipe)",{"type":65,"tag":1466,"props":1467,"children":1468},"style",{},[1469],{"type":71,"value":1470},"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":1472,"total":1614},[1473,1489,1501,1513,1528,1540,1550,1560,1573,1583,1594,1604],{"slug":1474,"name":1474,"fn":1475,"description":1476,"org":1477,"tags":1478,"stars":1486,"repoUrl":1487,"updatedAt":1488},"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},[1479,1482,1485],{"name":1480,"slug":1481,"type":16},"Data Analysis","data-analysis",{"name":1483,"slug":1484,"type":16},"Frontend","frontend",{"name":10,"slug":9,"type":16},28175,"https:\u002F\u002Fgithub.com\u002FTanStack\u002Ftable","2026-07-30T05:25:59.429787",{"slug":1490,"name":1490,"fn":1491,"description":1492,"org":1493,"tags":1494,"stars":1486,"repoUrl":1487,"updatedAt":1500},"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},[1495,1498,1499],{"name":1496,"slug":1497,"type":16},"Debugging","debugging",{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:05.418735",{"slug":1502,"name":1502,"fn":1503,"description":1504,"org":1505,"tags":1506,"stars":1486,"repoUrl":1487,"updatedAt":1512},"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},[1507,1508,1509],{"name":1480,"slug":1481,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"UI Components","ui-components","2026-07-30T05:25:38.403427",{"slug":1514,"name":1514,"fn":1515,"description":1516,"org":1517,"tags":1518,"stars":1486,"repoUrl":1487,"updatedAt":1527},"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},[1519,1522,1523,1526],{"name":1520,"slug":1521,"type":16},"Data Pipeline","data-pipeline",{"name":1483,"slug":1484,"type":16},{"name":1524,"slug":1525,"type":16},"Performance","performance",{"name":10,"slug":9,"type":16},"2026-07-30T05:25:45.400104",{"slug":1529,"name":1529,"fn":1530,"description":1531,"org":1532,"tags":1533,"stars":1486,"repoUrl":1487,"updatedAt":1539},"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},[1534,1537,1538],{"name":1535,"slug":1536,"type":16},"Data Visualization","data-visualization",{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:41.397257",{"slug":1541,"name":1541,"fn":1542,"description":1543,"org":1544,"tags":1545,"stars":1486,"repoUrl":1487,"updatedAt":1549},"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},[1546,1547,1548],{"name":1480,"slug":1481,"type":16},{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:25:53.391632",{"slug":1551,"name":1551,"fn":1552,"description":1553,"org":1554,"tags":1555,"stars":1486,"repoUrl":1487,"updatedAt":1559},"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},[1556,1557,1558],{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:26:03.37801",{"slug":1561,"name":1561,"fn":1562,"description":1563,"org":1564,"tags":1565,"stars":1486,"repoUrl":1487,"updatedAt":1572},"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},[1566,1569,1570,1571],{"name":1567,"slug":1568,"type":16},"CSS","css",{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:25:55.377366",{"slug":1574,"name":1574,"fn":1575,"description":1576,"org":1577,"tags":1578,"stars":1486,"repoUrl":1487,"updatedAt":1582},"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},[1579,1580,1581],{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:25:51.400011",{"slug":1584,"name":1584,"fn":1585,"description":1586,"org":1587,"tags":1588,"stars":1486,"repoUrl":1487,"updatedAt":1593},"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},[1589,1590,1591,1592],{"name":1567,"slug":1568,"type":16},{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:25:48.703799",{"slug":1595,"name":1595,"fn":1596,"description":1597,"org":1598,"tags":1599,"stars":1486,"repoUrl":1487,"updatedAt":1603},"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},[1600,1601,1602],{"name":1483,"slug":1484,"type":16},{"name":10,"slug":9,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:25:47.367943",{"slug":1605,"name":1605,"fn":1606,"description":1607,"org":1608,"tags":1609,"stars":1486,"repoUrl":1487,"updatedAt":1613},"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},[1610,1611,1612],{"name":1480,"slug":1481,"type":16},{"name":1483,"slug":1484,"type":16},{"name":1510,"slug":1511,"type":16},"2026-07-30T05:25:52.366295",125,{"items":1616,"total":1716},[1617,1635,1648,1663,1676,1688,1702],{"slug":1618,"name":1618,"fn":1619,"description":1620,"org":1621,"tags":1622,"stars":24,"repoUrl":25,"updatedAt":1634},"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},[1623,1625,1628,1631,1632],{"name":1624,"slug":31,"type":16},"AI SDK",{"name":1626,"slug":1627,"type":16},"Code Execution","code-execution",{"name":1629,"slug":1630,"type":16},"Sandboxing","sandboxing",{"name":10,"slug":9,"type":16},{"name":1633,"slug":45,"type":16},"TypeScript","2026-07-16T06:04:13.597905",{"slug":1636,"name":1636,"fn":1637,"description":1638,"org":1639,"tags":1640,"stars":24,"repoUrl":25,"updatedAt":1647},"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},[1641,1644,1645],{"name":1642,"slug":1643,"type":16},"Agents","agents",{"name":14,"slug":15,"type":16},{"name":1646,"slug":274,"type":16},"Middleware","2026-07-30T05:26:10.404565",{"slug":1649,"name":1650,"fn":1651,"description":1652,"org":1653,"tags":1654,"stars":24,"repoUrl":25,"updatedAt":1662},"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},[1655,1656,1659,1661],{"name":1624,"slug":31,"type":16},{"name":1657,"slug":1658,"type":16},"Configuration","configuration",{"name":1660,"slug":37,"type":16},"LLM",{"name":10,"slug":9,"type":16},"2026-07-16T06:04:17.82075",{"slug":1664,"name":1665,"fn":1666,"description":1667,"org":1668,"tags":1669,"stars":24,"repoUrl":25,"updatedAt":1675},"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},[1670,1673,1674],{"name":1671,"slug":1672,"type":16},"API Development","api-development",{"name":1660,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-16T06:04:10.093367",{"slug":1677,"name":1678,"fn":1679,"description":1680,"org":1681,"tags":1682,"stars":24,"repoUrl":25,"updatedAt":1687},"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},[1683,1684,1685,1686],{"name":1671,"slug":1672,"type":16},{"name":1483,"slug":1484,"type":16},{"name":1660,"slug":37,"type":16},{"name":10,"slug":9,"type":16},"2026-07-30T05:26:11.505241",{"slug":1689,"name":1690,"fn":1691,"description":1692,"org":1693,"tags":1694,"stars":24,"repoUrl":25,"updatedAt":1701},"ai-coreclient-persistence","ai-core\u002Fclient-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},[1695,1696,1697,1700],{"name":14,"slug":15,"type":16},{"name":1483,"slug":1484,"type":16},{"name":1698,"slug":1699,"type":16},"Persistence","persistence",{"name":10,"slug":9,"type":16},"2026-07-30T05:53:35.503176",{"slug":1703,"name":1704,"fn":1705,"description":1706,"org":1707,"tags":1708,"stars":24,"repoUrl":25,"updatedAt":1715},"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},[1709,1710,1711,1714],{"name":14,"slug":15,"type":16},{"name":1671,"slug":1672,"type":16},{"name":1712,"slug":1713,"type":16},"Backend","backend",{"name":10,"slug":9,"type":16},"2026-07-17T06:06:39.855351",27]