@btst/stack 3.0.0-rc.1 → 3.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1172) hide show
  1. package/README.md +122 -46
  2. package/dist/api/index.cjs +133 -29
  3. package/dist/api/index.d.cts +14 -32
  4. package/dist/api/index.d.mts +14 -32
  5. package/dist/api/index.d.ts +14 -32
  6. package/dist/api/index.mjs +133 -28
  7. package/dist/authorization/client.cjs +154 -0
  8. package/dist/authorization/client.d.cts +70 -0
  9. package/dist/authorization/client.d.mts +70 -0
  10. package/dist/authorization/client.d.ts +70 -0
  11. package/dist/authorization/client.mjs +152 -0
  12. package/dist/authorization/index.cjs +371 -0
  13. package/dist/authorization/index.d.cts +201 -0
  14. package/dist/authorization/index.d.mts +201 -0
  15. package/dist/authorization/index.d.ts +201 -0
  16. package/dist/authorization/index.mjs +365 -0
  17. package/dist/authorization/remote.cjs +117 -0
  18. package/dist/authorization/remote.d.cts +79 -0
  19. package/dist/authorization/remote.d.mts +79 -0
  20. package/dist/authorization/remote.d.ts +79 -0
  21. package/dist/authorization/remote.mjs +111 -0
  22. package/dist/authorization/server.cjs +77 -0
  23. package/dist/authorization/server.d.cts +51 -0
  24. package/dist/authorization/server.d.mts +51 -0
  25. package/dist/authorization/server.d.ts +51 -0
  26. package/dist/authorization/server.mjs +73 -0
  27. package/dist/client/components/index.cjs +1 -0
  28. package/dist/client/components/index.d.cts +23 -6
  29. package/dist/client/components/index.d.mts +23 -6
  30. package/dist/client/components/index.d.ts +23 -6
  31. package/dist/client/components/index.mjs +1 -1
  32. package/dist/client/hooks/index.cjs +8 -0
  33. package/dist/client/hooks/index.d.cts +25 -0
  34. package/dist/client/hooks/index.d.mts +25 -0
  35. package/dist/client/hooks/index.d.ts +25 -0
  36. package/dist/client/hooks/index.mjs +2 -0
  37. package/dist/client/index.cjs +38 -7
  38. package/dist/client/index.d.cts +30 -100
  39. package/dist/client/index.d.mts +30 -100
  40. package/dist/client/index.d.ts +30 -100
  41. package/dist/client/index.mjs +38 -7
  42. package/dist/client/server.cjs +96 -0
  43. package/dist/client/server.d.cts +57 -0
  44. package/dist/client/server.d.mts +57 -0
  45. package/dist/client/server.d.ts +57 -0
  46. package/dist/client/server.mjs +92 -0
  47. package/dist/components/auto-form/index.d.cts +2 -2
  48. package/dist/components/auto-form/index.d.mts +2 -2
  49. package/dist/components/auto-form/index.d.ts +2 -2
  50. package/dist/components/form-builder/index.d.cts +1 -1
  51. package/dist/components/form-builder/index.d.mts +1 -1
  52. package/dist/components/form-builder/index.d.ts +1 -1
  53. package/dist/components/stepped-auto-form/index.d.cts +1 -1
  54. package/dist/components/stepped-auto-form/index.d.mts +1 -1
  55. package/dist/components/stepped-auto-form/index.d.ts +1 -1
  56. package/dist/context/index.cjs +8 -2
  57. package/dist/context/index.d.cts +111 -89
  58. package/dist/context/index.d.mts +111 -89
  59. package/dist/context/index.d.ts +111 -89
  60. package/dist/context/index.mjs +3 -1
  61. package/dist/index.cjs +1 -2
  62. package/dist/index.d.cts +8 -3
  63. package/dist/index.d.mts +8 -3
  64. package/dist/index.d.ts +8 -3
  65. package/dist/index.mjs +1 -1
  66. package/dist/next/index.d.cts +30 -12
  67. package/dist/next/index.d.mts +30 -12
  68. package/dist/next/index.d.ts +30 -12
  69. package/dist/next/server.cjs +7 -0
  70. package/dist/next/server.d.cts +56 -0
  71. package/dist/next/server.d.mts +56 -0
  72. package/dist/next/server.d.ts +56 -0
  73. package/dist/next/server.mjs +1 -0
  74. package/dist/packages/stack/src/authorization/json.cjs +57 -0
  75. package/dist/packages/stack/src/authorization/json.mjs +55 -0
  76. package/dist/packages/stack/src/client/components/compose.cjs +91 -9
  77. package/dist/packages/stack/src/client/components/compose.mjs +92 -11
  78. package/dist/packages/stack/src/client/runtime.cjs +295 -0
  79. package/dist/packages/stack/src/client/runtime.mjs +293 -0
  80. package/dist/packages/stack/src/context/auth.cjs +141 -73
  81. package/dist/packages/stack/src/context/auth.mjs +139 -73
  82. package/dist/packages/stack/src/context/provider.cjs +11 -5
  83. package/dist/packages/stack/src/context/provider.mjs +11 -5
  84. package/dist/packages/stack/src/context/router.cjs +9 -0
  85. package/dist/packages/stack/src/context/router.mjs +7 -0
  86. package/dist/packages/stack/src/context/site-navigation.cjs +40 -0
  87. package/dist/packages/stack/src/context/site-navigation.mjs +38 -0
  88. package/dist/packages/stack/src/next/layout.cjs +27 -0
  89. package/dist/packages/stack/src/next/layout.mjs +25 -0
  90. package/dist/packages/stack/src/next/page.cjs +8 -6
  91. package/dist/packages/stack/src/next/page.mjs +8 -6
  92. package/dist/packages/stack/src/plugin-registration.cjs +59 -0
  93. package/dist/packages/stack/src/plugin-registration.mjs +57 -0
  94. package/dist/packages/stack/src/plugins/ai-chat/api/lifecycle-migrations.cjs +18 -0
  95. package/dist/packages/stack/src/plugins/ai-chat/api/lifecycle-migrations.mjs +16 -0
  96. package/dist/packages/stack/src/plugins/ai-chat/api/operations.cjs +1341 -0
  97. package/dist/packages/stack/src/plugins/ai-chat/api/operations.mjs +1333 -0
  98. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +82 -640
  99. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +78 -641
  100. package/dist/packages/stack/src/plugins/ai-chat/api/serializers.cjs +23 -0
  101. package/dist/packages/stack/src/plugins/ai-chat/api/serializers.mjs +20 -0
  102. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +183 -111
  103. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +187 -115
  104. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +562 -116
  105. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +567 -121
  106. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +6 -6
  107. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +6 -6
  108. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-message.cjs +1 -1
  109. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-message.mjs +1 -1
  110. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +45 -29
  111. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +46 -30
  112. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/404-page.cjs +1 -1
  113. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/404-page.mjs +1 -1
  114. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/chat-page.cjs +46 -7
  115. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.cjs +5 -3
  116. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.mjs +5 -3
  117. package/dist/packages/stack/src/plugins/ai-chat/client/components/pages/chat-page.mjs +48 -9
  118. package/dist/packages/stack/src/plugins/ai-chat/client/components/shared/default-error.cjs +1 -1
  119. package/dist/packages/stack/src/plugins/ai-chat/client/components/shared/default-error.mjs +1 -1
  120. package/dist/packages/stack/src/plugins/ai-chat/client/components/tool-call-display.cjs +1 -1
  121. package/dist/packages/stack/src/plugins/ai-chat/client/components/tool-call-display.mjs +1 -1
  122. package/dist/packages/stack/src/plugins/ai-chat/client/hooks/ai-chat-resource.cjs +1 -1
  123. package/dist/packages/stack/src/plugins/ai-chat/client/hooks/ai-chat-resource.mjs +1 -1
  124. package/dist/packages/stack/src/plugins/ai-chat/client/hooks/chat-hooks.cjs +179 -19
  125. package/dist/packages/stack/src/plugins/ai-chat/client/hooks/chat-hooks.mjs +180 -21
  126. package/dist/packages/stack/src/plugins/ai-chat/client/navigation.cjs +11 -0
  127. package/dist/packages/stack/src/plugins/ai-chat/client/navigation.mjs +9 -0
  128. package/dist/packages/stack/src/plugins/ai-chat/client/overrides.cjs +24 -0
  129. package/dist/packages/stack/src/plugins/ai-chat/client/overrides.mjs +21 -1
  130. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +152 -82
  131. package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +152 -82
  132. package/dist/packages/stack/src/plugins/api/create-endpoint.cjs +27 -9
  133. package/dist/packages/stack/src/plugins/api/create-endpoint.mjs +27 -10
  134. package/dist/packages/stack/src/plugins/api/endpoint-inventory.cjs +125 -0
  135. package/dist/packages/stack/src/plugins/api/endpoint-inventory.mjs +123 -0
  136. package/dist/packages/stack/src/plugins/api/operation.cjs +208 -0
  137. package/dist/packages/stack/src/plugins/api/operation.mjs +198 -0
  138. package/dist/packages/stack/src/plugins/blog/api/lifecycle-migrations.cjs +17 -0
  139. package/dist/packages/stack/src/plugins/blog/api/lifecycle-migrations.mjs +15 -0
  140. package/dist/packages/stack/src/plugins/blog/api/mutations.cjs +10 -2
  141. package/dist/packages/stack/src/plugins/blog/api/mutations.mjs +10 -2
  142. package/dist/packages/stack/src/plugins/blog/api/operations.cjs +455 -0
  143. package/dist/packages/stack/src/plugins/blog/api/operations.mjs +448 -0
  144. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +51 -298
  145. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +55 -304
  146. package/dist/packages/stack/src/plugins/blog/client/components/forms/image-field.cjs +2 -1
  147. package/dist/packages/stack/src/plugins/blog/client/components/forms/image-field.mjs +2 -1
  148. package/dist/packages/stack/src/plugins/blog/client/components/forms/markdown-editor-with-overrides.cjs +2 -1
  149. package/dist/packages/stack/src/plugins/blog/client/components/forms/markdown-editor-with-overrides.mjs +2 -1
  150. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +82 -67
  151. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +84 -69
  152. package/dist/packages/stack/src/plugins/blog/client/components/pages/404-page.cjs +2 -1
  153. package/dist/packages/stack/src/plugins/blog/client/components/pages/404-page.mjs +2 -1
  154. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.cjs +22 -4
  155. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +2 -1
  156. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +2 -1
  157. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.mjs +23 -5
  158. package/dist/packages/stack/src/plugins/blog/client/components/pages/home-page.cjs +6 -2
  159. package/dist/packages/stack/src/plugins/blog/client/components/pages/home-page.internal.cjs +2 -1
  160. package/dist/packages/stack/src/plugins/blog/client/components/pages/home-page.internal.mjs +2 -1
  161. package/dist/packages/stack/src/plugins/blog/client/components/pages/home-page.mjs +6 -2
  162. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.cjs +4 -2
  163. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +2 -1
  164. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +2 -1
  165. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.mjs +4 -2
  166. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.cjs +30 -3
  167. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +2 -1
  168. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +2 -1
  169. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.mjs +31 -4
  170. package/dist/packages/stack/src/plugins/blog/client/components/pages/tag-page.cjs +4 -1
  171. package/dist/packages/stack/src/plugins/blog/client/components/pages/tag-page.internal.cjs +2 -1
  172. package/dist/packages/stack/src/plugins/blog/client/components/pages/tag-page.internal.mjs +2 -1
  173. package/dist/packages/stack/src/plugins/blog/client/components/pages/tag-page.mjs +4 -1
  174. package/dist/packages/stack/src/plugins/blog/client/components/shared/collapsible-tag-list.cjs +2 -1
  175. package/dist/packages/stack/src/plugins/blog/client/components/shared/collapsible-tag-list.mjs +2 -1
  176. package/dist/packages/stack/src/plugins/blog/client/components/shared/default-error.cjs +2 -1
  177. package/dist/packages/stack/src/plugins/blog/client/components/shared/default-error.mjs +2 -1
  178. package/dist/packages/stack/src/plugins/blog/client/components/shared/on-this-page.cjs +3 -2
  179. package/dist/packages/stack/src/plugins/blog/client/components/shared/on-this-page.mjs +3 -2
  180. package/dist/packages/stack/src/plugins/blog/client/components/shared/page-wrapper.cjs +2 -1
  181. package/dist/packages/stack/src/plugins/blog/client/components/shared/page-wrapper.mjs +2 -1
  182. package/dist/packages/stack/src/plugins/blog/client/components/shared/post-card.cjs +2 -1
  183. package/dist/packages/stack/src/plugins/blog/client/components/shared/post-card.mjs +2 -1
  184. package/dist/packages/stack/src/plugins/blog/client/components/shared/posts-list.cjs +2 -1
  185. package/dist/packages/stack/src/plugins/blog/client/components/shared/posts-list.mjs +2 -1
  186. package/dist/packages/stack/src/plugins/blog/client/components/shared/recent-posts-carousel.cjs +2 -1
  187. package/dist/packages/stack/src/plugins/blog/client/components/shared/recent-posts-carousel.mjs +2 -1
  188. package/dist/packages/stack/src/plugins/blog/client/components/shared/search-input.cjs +2 -2
  189. package/dist/packages/stack/src/plugins/blog/client/components/shared/search-input.mjs +1 -1
  190. package/dist/packages/stack/src/plugins/blog/client/constants.cjs +5 -0
  191. package/dist/packages/stack/src/plugins/blog/client/constants.mjs +3 -0
  192. package/dist/packages/stack/src/plugins/blog/client/hooks/blog-resource.cjs +2 -1
  193. package/dist/packages/stack/src/plugins/blog/client/hooks/blog-resource.mjs +2 -1
  194. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +169 -163
  195. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +169 -163
  196. package/dist/packages/stack/src/plugins/client/resource/hooks.cjs +31 -16
  197. package/dist/packages/stack/src/plugins/client/resource/hooks.mjs +31 -16
  198. package/dist/packages/stack/src/plugins/client/resource/internal.cjs +66 -52
  199. package/dist/packages/stack/src/plugins/client/resource/internal.mjs +66 -52
  200. package/dist/packages/stack/src/plugins/client/resource/use-form.cjs +20 -17
  201. package/dist/packages/stack/src/plugins/client/resource/use-form.mjs +20 -17
  202. package/dist/packages/stack/src/plugins/client/resource/use-select.cjs +39 -33
  203. package/dist/packages/stack/src/plugins/client/resource/use-select.mjs +39 -33
  204. package/dist/packages/stack/src/plugins/cms/api/lifecycle-migrations.cjs +13 -0
  205. package/dist/packages/stack/src/plugins/cms/api/lifecycle-migrations.mjs +11 -0
  206. package/dist/packages/stack/src/plugins/cms/api/operations.cjs +1763 -0
  207. package/dist/packages/stack/src/plugins/cms/api/operations.mjs +1756 -0
  208. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +165 -752
  209. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +164 -755
  210. package/dist/packages/stack/src/plugins/cms/client/components/forms/content-form.cjs +2 -1
  211. package/dist/packages/stack/src/plugins/cms/client/components/forms/content-form.mjs +2 -1
  212. package/dist/packages/stack/src/plugins/cms/client/components/forms/file-upload.cjs +2 -1
  213. package/dist/packages/stack/src/plugins/cms/client/components/forms/file-upload.mjs +2 -1
  214. package/dist/packages/stack/src/plugins/cms/client/components/forms/relation-field.cjs +2 -1
  215. package/dist/packages/stack/src/plugins/cms/client/components/forms/relation-field.mjs +2 -1
  216. package/dist/packages/stack/src/plugins/cms/client/components/inverse-relations-panel.cjs +23 -13
  217. package/dist/packages/stack/src/plugins/cms/client/components/inverse-relations-panel.mjs +24 -14
  218. package/dist/packages/stack/src/plugins/cms/client/components/pages/404-page.cjs +5 -4
  219. package/dist/packages/stack/src/plugins/cms/client/components/pages/404-page.mjs +6 -5
  220. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.cjs +40 -7
  221. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.internal.cjs +15 -9
  222. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.internal.mjs +14 -8
  223. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-editor-page.mjs +41 -8
  224. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-list-page.cjs +7 -1
  225. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-list-page.internal.cjs +42 -29
  226. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-list-page.internal.mjs +40 -27
  227. package/dist/packages/stack/src/plugins/cms/client/components/pages/content-list-page.mjs +7 -1
  228. package/dist/packages/stack/src/plugins/cms/client/components/pages/dashboard-page.cjs +4 -1
  229. package/dist/packages/stack/src/plugins/cms/client/components/pages/dashboard-page.internal.cjs +13 -7
  230. package/dist/packages/stack/src/plugins/cms/client/components/pages/dashboard-page.internal.mjs +12 -6
  231. package/dist/packages/stack/src/plugins/cms/client/components/pages/dashboard-page.mjs +4 -1
  232. package/dist/packages/stack/src/plugins/cms/client/components/shared/page-wrapper.cjs +2 -1
  233. package/dist/packages/stack/src/plugins/cms/client/components/shared/page-wrapper.mjs +2 -1
  234. package/dist/packages/stack/src/plugins/cms/client/constants.cjs +5 -0
  235. package/dist/packages/stack/src/plugins/cms/client/constants.mjs +3 -0
  236. package/dist/packages/stack/src/plugins/cms/client/hooks/cms-resource.cjs +2 -1
  237. package/dist/packages/stack/src/plugins/cms/client/hooks/cms-resource.mjs +2 -1
  238. package/dist/packages/stack/src/plugins/cms/client/overrides.cjs +26 -0
  239. package/dist/packages/stack/src/plugins/cms/client/overrides.mjs +24 -0
  240. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +102 -81
  241. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +103 -82
  242. package/dist/packages/stack/src/plugins/comments/api/getters.cjs +6 -2
  243. package/dist/packages/stack/src/plugins/comments/api/getters.mjs +6 -3
  244. package/dist/packages/stack/src/plugins/comments/api/lifecycle-migrations.cjs +18 -0
  245. package/dist/packages/stack/src/plugins/comments/api/lifecycle-migrations.mjs +16 -0
  246. package/dist/packages/stack/src/plugins/comments/api/mutations.cjs +179 -68
  247. package/dist/packages/stack/src/plugins/comments/api/mutations.mjs +179 -68
  248. package/dist/packages/stack/src/plugins/comments/api/operations.cjs +453 -0
  249. package/dist/packages/stack/src/plugins/comments/api/operations.mjs +445 -0
  250. package/dist/packages/stack/src/plugins/comments/api/plugin.cjs +51 -276
  251. package/dist/packages/stack/src/plugins/comments/api/plugin.mjs +48 -277
  252. package/dist/packages/stack/src/plugins/comments/client/components/comment-count.cjs +32 -5
  253. package/dist/packages/stack/src/plugins/comments/client/components/comment-count.mjs +34 -7
  254. package/dist/packages/stack/src/plugins/comments/client/components/comment-thread.cjs +161 -105
  255. package/dist/packages/stack/src/plugins/comments/client/components/comment-thread.mjs +162 -106
  256. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.cjs +14 -2
  257. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.internal.cjs +141 -71
  258. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.internal.mjs +142 -72
  259. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-page.mjs +14 -2
  260. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-state.cjs +12 -0
  261. package/dist/packages/stack/src/plugins/comments/client/components/pages/moderation-state.mjs +9 -0
  262. package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.cjs +2 -1
  263. package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.internal.cjs +40 -26
  264. package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.internal.mjs +40 -26
  265. package/dist/packages/stack/src/plugins/comments/client/components/pages/my-comments-page.mjs +2 -1
  266. package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.cjs +9 -1
  267. package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.internal.cjs +25 -20
  268. package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.internal.mjs +26 -21
  269. package/dist/packages/stack/src/plugins/comments/client/components/pages/resource-comments-page.mjs +9 -1
  270. package/dist/packages/stack/src/plugins/comments/client/components/shared/page-wrapper.cjs +2 -1
  271. package/dist/packages/stack/src/plugins/comments/client/components/shared/page-wrapper.mjs +2 -1
  272. package/dist/packages/stack/src/plugins/comments/client/components/shared/pagination.cjs +2 -1
  273. package/dist/packages/stack/src/plugins/comments/client/components/shared/pagination.mjs +2 -1
  274. package/dist/packages/stack/src/plugins/comments/client/constants.cjs +5 -0
  275. package/dist/packages/stack/src/plugins/comments/client/constants.mjs +3 -0
  276. package/dist/packages/stack/src/plugins/comments/client/hooks/use-comments.cjs +323 -290
  277. package/dist/packages/stack/src/plugins/comments/client/hooks/use-comments.mjs +325 -292
  278. package/dist/packages/stack/src/plugins/comments/client/localization/comments-thread.cjs +1 -0
  279. package/dist/packages/stack/src/plugins/comments/client/localization/comments-thread.mjs +1 -0
  280. package/dist/packages/stack/src/plugins/comments/client/plugin.cjs +78 -46
  281. package/dist/packages/stack/src/plugins/comments/client/plugin.mjs +80 -48
  282. package/dist/packages/stack/src/plugins/form-builder/api/getters.cjs +9 -0
  283. package/dist/packages/stack/src/plugins/form-builder/api/getters.mjs +9 -1
  284. package/dist/packages/stack/src/plugins/form-builder/api/lifecycle-migrations.cjs +15 -0
  285. package/dist/packages/stack/src/plugins/form-builder/api/lifecycle-migrations.mjs +13 -0
  286. package/dist/packages/stack/src/plugins/form-builder/api/operations.cjs +1093 -0
  287. package/dist/packages/stack/src/plugins/form-builder/api/operations.mjs +1082 -0
  288. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +97 -466
  289. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +92 -468
  290. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.cjs +5 -0
  291. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.mjs +5 -0
  292. package/dist/packages/stack/src/plugins/form-builder/client/components/forms/form-renderer.cjs +41 -11
  293. package/dist/packages/stack/src/plugins/form-builder/client/components/forms/form-renderer.mjs +42 -12
  294. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/404-page.cjs +8 -5
  295. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/404-page.mjs +9 -6
  296. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-builder-page.cjs +36 -3
  297. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-builder-page.internal.cjs +32 -11
  298. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-builder-page.internal.mjs +35 -14
  299. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-builder-page.mjs +37 -4
  300. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-list-page.cjs +6 -1
  301. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-list-page.internal.cjs +34 -26
  302. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-list-page.internal.mjs +34 -26
  303. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/form-list-page.mjs +6 -1
  304. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.cjs +24 -7
  305. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.cjs +72 -40
  306. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.internal.mjs +76 -44
  307. package/dist/packages/stack/src/plugins/form-builder/client/components/pages/submissions-page.mjs +25 -8
  308. package/dist/packages/stack/src/plugins/form-builder/client/components/shared/page-wrapper.cjs +2 -1
  309. package/dist/packages/stack/src/plugins/form-builder/client/components/shared/page-wrapper.mjs +2 -1
  310. package/dist/packages/stack/src/plugins/form-builder/client/constants.cjs +5 -0
  311. package/dist/packages/stack/src/plugins/form-builder/client/constants.mjs +3 -0
  312. package/dist/packages/stack/src/plugins/form-builder/client/hooks/form-builder-hooks.cjs +29 -0
  313. package/dist/packages/stack/src/plugins/form-builder/client/hooks/form-builder-hooks.mjs +28 -1
  314. package/dist/packages/stack/src/plugins/form-builder/client/hooks/form-builder-resource.cjs +2 -1
  315. package/dist/packages/stack/src/plugins/form-builder/client/hooks/form-builder-resource.mjs +2 -1
  316. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +113 -86
  317. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +114 -87
  318. package/dist/packages/stack/src/plugins/form-builder/schemas.cjs +9 -3
  319. package/dist/packages/stack/src/plugins/form-builder/schemas.mjs +9 -3
  320. package/dist/packages/stack/src/plugins/kanban/api/getters.cjs +47 -36
  321. package/dist/packages/stack/src/plugins/kanban/api/getters.mjs +47 -37
  322. package/dist/packages/stack/src/plugins/kanban/api/lifecycle-migrations.cjs +23 -0
  323. package/dist/packages/stack/src/plugins/kanban/api/lifecycle-migrations.mjs +21 -0
  324. package/dist/packages/stack/src/plugins/kanban/api/operations.cjs +1552 -0
  325. package/dist/packages/stack/src/plugins/kanban/api/operations.mjs +1543 -0
  326. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +64 -631
  327. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +62 -634
  328. package/dist/packages/stack/src/plugins/kanban/api/serializers.cjs +21 -0
  329. package/dist/packages/stack/src/plugins/kanban/api/serializers.mjs +21 -1
  330. package/dist/packages/stack/src/plugins/kanban/client/components/forms/board-form.cjs +2 -1
  331. package/dist/packages/stack/src/plugins/kanban/client/components/forms/board-form.mjs +2 -1
  332. package/dist/packages/stack/src/plugins/kanban/client/components/forms/column-form.cjs +2 -1
  333. package/dist/packages/stack/src/plugins/kanban/client/components/forms/column-form.mjs +2 -1
  334. package/dist/packages/stack/src/plugins/kanban/client/components/forms/task-form.cjs +72 -54
  335. package/dist/packages/stack/src/plugins/kanban/client/components/forms/task-form.mjs +74 -56
  336. package/dist/packages/stack/src/plugins/kanban/client/components/pages/404-page.cjs +4 -6
  337. package/dist/packages/stack/src/plugins/kanban/client/components/pages/404-page.mjs +5 -7
  338. package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.cjs +22 -6
  339. package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.internal.cjs +82 -77
  340. package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.internal.mjs +83 -78
  341. package/dist/packages/stack/src/plugins/kanban/client/components/pages/board-page.mjs +23 -7
  342. package/dist/packages/stack/src/plugins/kanban/client/components/pages/boards-list-page.cjs +2 -1
  343. package/dist/packages/stack/src/plugins/kanban/client/components/pages/boards-list-page.internal.cjs +34 -24
  344. package/dist/packages/stack/src/plugins/kanban/client/components/pages/boards-list-page.internal.mjs +35 -25
  345. package/dist/packages/stack/src/plugins/kanban/client/components/pages/boards-list-page.mjs +2 -1
  346. package/dist/packages/stack/src/plugins/kanban/client/components/pages/new-board-page.cjs +2 -1
  347. package/dist/packages/stack/src/plugins/kanban/client/components/pages/new-board-page.internal.cjs +6 -9
  348. package/dist/packages/stack/src/plugins/kanban/client/components/pages/new-board-page.internal.mjs +7 -10
  349. package/dist/packages/stack/src/plugins/kanban/client/components/pages/new-board-page.mjs +2 -1
  350. package/dist/packages/stack/src/plugins/kanban/client/components/shared/column-content.cjs +72 -45
  351. package/dist/packages/stack/src/plugins/kanban/client/components/shared/column-content.mjs +73 -46
  352. package/dist/packages/stack/src/plugins/kanban/client/components/shared/default-error.cjs +2 -1
  353. package/dist/packages/stack/src/plugins/kanban/client/components/shared/default-error.mjs +2 -1
  354. package/dist/packages/stack/src/plugins/kanban/client/components/shared/kanban-board.cjs +4 -4
  355. package/dist/packages/stack/src/plugins/kanban/client/components/shared/kanban-board.mjs +4 -4
  356. package/dist/packages/stack/src/plugins/kanban/client/components/shared/permission-access-any.cjs +23 -0
  357. package/dist/packages/stack/src/plugins/kanban/client/components/shared/permission-access-any.mjs +21 -0
  358. package/dist/packages/stack/src/plugins/kanban/client/components/shared/task-card.cjs +54 -17
  359. package/dist/packages/stack/src/plugins/kanban/client/components/shared/task-card.mjs +55 -18
  360. package/dist/packages/stack/src/plugins/kanban/client/components/shared/user-avatar.cjs +2 -1
  361. package/dist/packages/stack/src/plugins/kanban/client/components/shared/user-avatar.mjs +2 -1
  362. package/dist/packages/stack/src/plugins/kanban/client/constants.cjs +5 -0
  363. package/dist/packages/stack/src/plugins/kanban/client/constants.mjs +3 -0
  364. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +38 -9
  365. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +39 -10
  366. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-resource.cjs +2 -1
  367. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-resource.mjs +2 -1
  368. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +177 -104
  369. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +178 -105
  370. package/dist/packages/stack/src/plugins/kanban/schemas.cjs +32 -23
  371. package/dist/packages/stack/src/plugins/kanban/schemas.mjs +33 -21
  372. package/dist/packages/stack/src/plugins/media/api/lifecycle-migrations.cjs +9 -0
  373. package/dist/packages/stack/src/plugins/media/api/lifecycle-migrations.mjs +7 -0
  374. package/dist/packages/stack/src/plugins/media/api/mutations.cjs +7 -2
  375. package/dist/packages/stack/src/plugins/media/api/mutations.mjs +7 -2
  376. package/dist/packages/stack/src/plugins/media/api/operations.cjs +1299 -0
  377. package/dist/packages/stack/src/plugins/media/api/operations.mjs +1290 -0
  378. package/dist/packages/stack/src/plugins/media/api/plugin.cjs +131 -508
  379. package/dist/packages/stack/src/plugins/media/api/plugin.mjs +127 -510
  380. package/dist/packages/stack/src/plugins/media/api/query-key-defs.cjs +26 -2
  381. package/dist/packages/stack/src/plugins/media/api/query-key-defs.mjs +25 -3
  382. package/dist/packages/stack/src/plugins/media/api/serializers.cjs +4 -2
  383. package/dist/packages/stack/src/plugins/media/api/serializers.mjs +4 -2
  384. package/dist/packages/stack/src/plugins/media/asset-url.cjs +13 -0
  385. package/dist/packages/stack/src/plugins/media/asset-url.mjs +11 -0
  386. package/dist/packages/stack/src/plugins/media/client/components/media-picker/asset-card.cjs +10 -10
  387. package/dist/packages/stack/src/plugins/media/client/components/media-picker/asset-card.mjs +12 -12
  388. package/dist/packages/stack/src/plugins/media/client/components/media-picker/folder-tree.cjs +47 -27
  389. package/dist/packages/stack/src/plugins/media/client/components/media-picker/folder-tree.mjs +49 -29
  390. package/dist/packages/stack/src/plugins/media/client/components/media-picker/index.cjs +225 -180
  391. package/dist/packages/stack/src/plugins/media/client/components/media-picker/index.mjs +228 -183
  392. package/dist/packages/stack/src/plugins/media/client/components/media-picker/upload-tab.cjs +1 -8
  393. package/dist/packages/stack/src/plugins/media/client/components/media-picker/upload-tab.mjs +2 -9
  394. package/dist/packages/stack/src/plugins/media/client/components/media-picker/url-tab.cjs +0 -6
  395. package/dist/packages/stack/src/plugins/media/client/components/media-picker/url-tab.mjs +1 -7
  396. package/dist/packages/stack/src/plugins/media/client/components/pages/library-page.cjs +4 -2
  397. package/dist/packages/stack/src/plugins/media/client/components/pages/library-page.internal.cjs +92 -75
  398. package/dist/packages/stack/src/plugins/media/client/components/pages/library-page.internal.mjs +93 -76
  399. package/dist/packages/stack/src/plugins/media/client/components/pages/library-page.mjs +4 -2
  400. package/dist/packages/stack/src/plugins/media/client/components/upload-permission-check.cjs +52 -0
  401. package/dist/packages/stack/src/plugins/media/client/components/upload-permission-check.mjs +49 -0
  402. package/dist/packages/stack/src/plugins/media/client/constants.cjs +5 -0
  403. package/dist/packages/stack/src/plugins/media/client/constants.mjs +3 -0
  404. package/dist/packages/stack/src/plugins/media/client/hooks/media-resource.cjs +2 -1
  405. package/dist/packages/stack/src/plugins/media/client/hooks/media-resource.mjs +2 -1
  406. package/dist/packages/stack/src/plugins/media/client/hooks/use-media.cjs +214 -43
  407. package/dist/packages/stack/src/plugins/media/client/hooks/use-media.mjs +217 -46
  408. package/dist/packages/stack/src/plugins/media/client/plugin.cjs +122 -62
  409. package/dist/packages/stack/src/plugins/media/client/plugin.mjs +123 -63
  410. package/dist/packages/stack/src/plugins/media/client/upload.cjs +121 -52
  411. package/dist/packages/stack/src/plugins/media/client/upload.mjs +121 -53
  412. package/dist/packages/stack/src/plugins/media/db.cjs +8 -0
  413. package/dist/packages/stack/src/plugins/media/db.mjs +8 -0
  414. package/dist/packages/stack/src/plugins/open-api/api/generator.cjs +36 -5
  415. package/dist/packages/stack/src/plugins/open-api/api/generator.mjs +36 -5
  416. package/dist/packages/stack/src/plugins/open-api/api/plugin.cjs +22 -11
  417. package/dist/packages/stack/src/plugins/open-api/api/plugin.mjs +22 -11
  418. package/dist/packages/stack/src/plugins/route-docs/client/components/pages/docs-page.cjs +65 -34
  419. package/dist/packages/stack/src/plugins/route-docs/client/components/pages/docs-page.mjs +56 -25
  420. package/dist/packages/stack/src/plugins/route-docs/client/constants.cjs +5 -0
  421. package/dist/packages/stack/src/plugins/route-docs/client/constants.mjs +3 -0
  422. package/dist/packages/stack/src/plugins/route-docs/client/hooks.cjs +9 -8
  423. package/dist/packages/stack/src/plugins/route-docs/client/hooks.mjs +10 -9
  424. package/dist/packages/stack/src/plugins/route-docs/client/plugin.cjs +143 -75
  425. package/dist/packages/stack/src/plugins/route-docs/client/plugin.mjs +144 -74
  426. package/dist/packages/stack/src/plugins/route-docs/client/schema.cjs +26 -0
  427. package/dist/packages/stack/src/plugins/route-docs/client/schema.mjs +23 -0
  428. package/dist/packages/stack/src/plugins/route-docs/generator.cjs +7 -4
  429. package/dist/packages/stack/src/plugins/route-docs/generator.mjs +7 -4
  430. package/dist/packages/stack/src/plugins/ui-builder/client/components/page-renderer.cjs +41 -12
  431. package/dist/packages/stack/src/plugins/ui-builder/client/components/page-renderer.mjs +42 -13
  432. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.cjs +37 -3
  433. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +32 -20
  434. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +34 -22
  435. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.mjs +38 -4
  436. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-list-page.cjs +8 -2
  437. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-list-page.internal.cjs +37 -19
  438. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-list-page.internal.mjs +38 -20
  439. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-list-page.mjs +8 -2
  440. package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/default-error.cjs +2 -1
  441. package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/default-error.mjs +2 -1
  442. package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/page-wrapper.cjs +2 -1
  443. package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/page-wrapper.mjs +2 -1
  444. package/dist/packages/stack/src/plugins/ui-builder/client/constants.cjs +5 -0
  445. package/dist/packages/stack/src/plugins/ui-builder/client/constants.mjs +3 -0
  446. package/dist/packages/stack/src/plugins/ui-builder/client/hooks/ui-builder-resource.cjs +2 -1
  447. package/dist/packages/stack/src/plugins/ui-builder/client/hooks/ui-builder-resource.mjs +2 -1
  448. package/dist/packages/stack/src/plugins/ui-builder/client/overrides.cjs +8 -0
  449. package/dist/packages/stack/src/plugins/ui-builder/client/overrides.mjs +6 -0
  450. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +93 -53
  451. package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +94 -54
  452. package/dist/packages/stack/src/plugins/utils.cjs +4 -12
  453. package/dist/packages/stack/src/plugins/utils.mjs +5 -12
  454. package/dist/packages/stack/src/react-router/layout.cjs +14 -0
  455. package/dist/packages/stack/src/react-router/layout.mjs +12 -0
  456. package/dist/packages/stack/src/react-router/page.cjs +27 -16
  457. package/dist/packages/stack/src/react-router/page.mjs +28 -17
  458. package/dist/packages/stack/src/shared/initial-identity.cjs +27 -0
  459. package/dist/packages/stack/src/shared/initial-identity.mjs +23 -0
  460. package/dist/packages/stack/src/tanstack/layout.cjs +10 -0
  461. package/dist/packages/stack/src/tanstack/layout.mjs +8 -0
  462. package/dist/packages/stack/src/tanstack/page.cjs +11 -5
  463. package/dist/packages/stack/src/tanstack/page.mjs +11 -5
  464. package/dist/plugins/ai-chat/api/index.cjs +10 -0
  465. package/dist/plugins/ai-chat/api/index.d.cts +31 -5
  466. package/dist/plugins/ai-chat/api/index.d.mts +31 -5
  467. package/dist/plugins/ai-chat/api/index.d.ts +31 -5
  468. package/dist/plugins/ai-chat/api/index.mjs +3 -1
  469. package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
  470. package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
  471. package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
  472. package/dist/plugins/ai-chat/client/hooks/index.cjs +1 -0
  473. package/dist/plugins/ai-chat/client/hooks/index.d.cts +14 -8
  474. package/dist/plugins/ai-chat/client/hooks/index.d.mts +14 -8
  475. package/dist/plugins/ai-chat/client/hooks/index.d.ts +14 -8
  476. package/dist/plugins/ai-chat/client/hooks/index.mjs +1 -1
  477. package/dist/plugins/ai-chat/client/index.d.cts +21 -25
  478. package/dist/plugins/ai-chat/client/index.d.mts +21 -25
  479. package/dist/plugins/ai-chat/client/index.d.ts +21 -25
  480. package/dist/plugins/ai-chat/permissions.cjs +90 -0
  481. package/dist/plugins/ai-chat/permissions.d.cts +84 -0
  482. package/dist/plugins/ai-chat/permissions.d.mts +84 -0
  483. package/dist/plugins/ai-chat/permissions.d.ts +84 -0
  484. package/dist/plugins/ai-chat/permissions.mjs +88 -0
  485. package/dist/plugins/ai-chat/query-keys.cjs +116 -18
  486. package/dist/plugins/ai-chat/query-keys.d.cts +6 -2
  487. package/dist/plugins/ai-chat/query-keys.d.mts +6 -2
  488. package/dist/plugins/ai-chat/query-keys.d.ts +6 -2
  489. package/dist/plugins/ai-chat/query-keys.mjs +116 -19
  490. package/dist/plugins/api/index.cjs +4 -0
  491. package/dist/plugins/api/index.d.cts +13 -18
  492. package/dist/plugins/api/index.d.mts +13 -18
  493. package/dist/plugins/api/index.d.ts +13 -18
  494. package/dist/plugins/api/index.mjs +1 -0
  495. package/dist/plugins/blog/api/index.cjs +9 -2
  496. package/dist/plugins/blog/api/index.d.cts +118 -4
  497. package/dist/plugins/blog/api/index.d.mts +118 -4
  498. package/dist/plugins/blog/api/index.d.ts +118 -4
  499. package/dist/plugins/blog/api/index.mjs +4 -1
  500. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  501. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  502. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  503. package/dist/plugins/blog/client/index.d.cts +210 -226
  504. package/dist/plugins/blog/client/index.d.mts +210 -226
  505. package/dist/plugins/blog/client/index.d.ts +210 -226
  506. package/dist/plugins/blog/permissions.cjs +47 -0
  507. package/dist/plugins/blog/permissions.d.cts +49 -0
  508. package/dist/plugins/blog/permissions.d.mts +49 -0
  509. package/dist/plugins/blog/permissions.d.ts +49 -0
  510. package/dist/plugins/blog/permissions.mjs +45 -0
  511. package/dist/plugins/blog/query-keys.d.cts +7 -3
  512. package/dist/plugins/blog/query-keys.d.mts +7 -3
  513. package/dist/plugins/blog/query-keys.d.ts +7 -3
  514. package/dist/plugins/client/hooks/index.d.cts +2 -2
  515. package/dist/plugins/client/hooks/index.d.mts +2 -2
  516. package/dist/plugins/client/hooks/index.d.ts +2 -2
  517. package/dist/plugins/client/index.cjs +3 -0
  518. package/dist/plugins/client/index.d.cts +30 -10
  519. package/dist/plugins/client/index.d.mts +30 -10
  520. package/dist/plugins/client/index.d.ts +30 -10
  521. package/dist/plugins/client/index.mjs +3 -0
  522. package/dist/plugins/cms/api/index.cjs +7 -0
  523. package/dist/plugins/cms/api/index.d.cts +173 -4
  524. package/dist/plugins/cms/api/index.d.mts +173 -4
  525. package/dist/plugins/cms/api/index.d.ts +173 -4
  526. package/dist/plugins/cms/api/index.mjs +2 -0
  527. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  528. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  529. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  530. package/dist/plugins/cms/client/index.d.cts +188 -184
  531. package/dist/plugins/cms/client/index.d.mts +188 -184
  532. package/dist/plugins/cms/client/index.d.ts +188 -184
  533. package/dist/plugins/cms/permissions.cjs +46 -0
  534. package/dist/plugins/cms/permissions.d.cts +42 -0
  535. package/dist/plugins/cms/permissions.d.mts +42 -0
  536. package/dist/plugins/cms/permissions.d.ts +42 -0
  537. package/dist/plugins/cms/permissions.mjs +44 -0
  538. package/dist/plugins/cms/query-keys.d.cts +4 -4
  539. package/dist/plugins/cms/query-keys.d.mts +4 -4
  540. package/dist/plugins/cms/query-keys.d.ts +4 -4
  541. package/dist/plugins/comments/api/index.cjs +10 -0
  542. package/dist/plugins/comments/api/index.d.cts +54 -18
  543. package/dist/plugins/comments/api/index.d.mts +54 -18
  544. package/dist/plugins/comments/api/index.d.ts +54 -18
  545. package/dist/plugins/comments/api/index.mjs +3 -0
  546. package/dist/plugins/comments/client/components/index.d.cts +7 -2
  547. package/dist/plugins/comments/client/components/index.d.mts +7 -2
  548. package/dist/plugins/comments/client/components/index.d.ts +7 -2
  549. package/dist/plugins/comments/client/hooks/index.d.cts +12 -18
  550. package/dist/plugins/comments/client/hooks/index.d.mts +12 -18
  551. package/dist/plugins/comments/client/hooks/index.d.ts +12 -18
  552. package/dist/plugins/comments/client/index.d.cts +96 -114
  553. package/dist/plugins/comments/client/index.d.mts +96 -114
  554. package/dist/plugins/comments/client/index.d.ts +96 -114
  555. package/dist/plugins/comments/permissions.cjs +70 -0
  556. package/dist/plugins/comments/permissions.d.cts +76 -0
  557. package/dist/plugins/comments/permissions.d.mts +76 -0
  558. package/dist/plugins/comments/permissions.d.ts +76 -0
  559. package/dist/plugins/comments/permissions.mjs +68 -0
  560. package/dist/plugins/comments/query-keys.cjs +1 -1
  561. package/dist/plugins/comments/query-keys.d.cts +16 -19
  562. package/dist/plugins/comments/query-keys.d.mts +16 -19
  563. package/dist/plugins/comments/query-keys.d.ts +16 -19
  564. package/dist/plugins/comments/query-keys.mjs +1 -1
  565. package/dist/plugins/form-builder/api/index.cjs +8 -0
  566. package/dist/plugins/form-builder/api/index.d.cts +115 -4
  567. package/dist/plugins/form-builder/api/index.d.mts +115 -4
  568. package/dist/plugins/form-builder/api/index.d.ts +115 -4
  569. package/dist/plugins/form-builder/api/index.mjs +4 -1
  570. package/dist/plugins/form-builder/client/components/index.d.cts +6 -2
  571. package/dist/plugins/form-builder/client/components/index.d.mts +6 -2
  572. package/dist/plugins/form-builder/client/components/index.d.ts +6 -2
  573. package/dist/plugins/form-builder/client/hooks/index.cjs +2 -0
  574. package/dist/plugins/form-builder/client/hooks/index.d.cts +34 -8
  575. package/dist/plugins/form-builder/client/hooks/index.d.mts +34 -8
  576. package/dist/plugins/form-builder/client/hooks/index.d.ts +34 -8
  577. package/dist/plugins/form-builder/client/hooks/index.mjs +1 -1
  578. package/dist/plugins/form-builder/client/index.d.cts +153 -174
  579. package/dist/plugins/form-builder/client/index.d.mts +153 -174
  580. package/dist/plugins/form-builder/client/index.d.ts +153 -174
  581. package/dist/plugins/form-builder/permissions.cjs +95 -0
  582. package/dist/plugins/form-builder/permissions.d.cts +94 -0
  583. package/dist/plugins/form-builder/permissions.d.mts +94 -0
  584. package/dist/plugins/form-builder/permissions.d.ts +94 -0
  585. package/dist/plugins/form-builder/permissions.mjs +93 -0
  586. package/dist/plugins/form-builder/query-keys.cjs +11 -4
  587. package/dist/plugins/form-builder/query-keys.d.cts +38 -12
  588. package/dist/plugins/form-builder/query-keys.d.mts +38 -12
  589. package/dist/plugins/form-builder/query-keys.d.ts +38 -12
  590. package/dist/plugins/form-builder/query-keys.mjs +11 -4
  591. package/dist/plugins/kanban/api/index.cjs +9 -0
  592. package/dist/plugins/kanban/api/index.d.cts +137 -5
  593. package/dist/plugins/kanban/api/index.d.mts +137 -5
  594. package/dist/plugins/kanban/api/index.d.ts +137 -5
  595. package/dist/plugins/kanban/api/index.mjs +5 -2
  596. package/dist/plugins/kanban/client/components/index.d.cts +18 -10
  597. package/dist/plugins/kanban/client/components/index.d.mts +18 -10
  598. package/dist/plugins/kanban/client/components/index.d.ts +18 -10
  599. package/dist/plugins/kanban/client/hooks/index.d.cts +15 -7
  600. package/dist/plugins/kanban/client/hooks/index.d.mts +15 -7
  601. package/dist/plugins/kanban/client/hooks/index.d.ts +15 -7
  602. package/dist/plugins/kanban/client/index.d.cts +32 -28
  603. package/dist/plugins/kanban/client/index.d.mts +32 -28
  604. package/dist/plugins/kanban/client/index.d.ts +32 -28
  605. package/dist/plugins/kanban/permissions.cjs +101 -0
  606. package/dist/plugins/kanban/permissions.d.cts +109 -0
  607. package/dist/plugins/kanban/permissions.d.mts +109 -0
  608. package/dist/plugins/kanban/permissions.d.ts +109 -0
  609. package/dist/plugins/kanban/permissions.mjs +99 -0
  610. package/dist/plugins/kanban/query-keys.cjs +14 -15
  611. package/dist/plugins/kanban/query-keys.d.cts +63 -42
  612. package/dist/plugins/kanban/query-keys.d.mts +63 -42
  613. package/dist/plugins/kanban/query-keys.d.ts +63 -42
  614. package/dist/plugins/kanban/query-keys.mjs +14 -15
  615. package/dist/plugins/media/api/adapters/local.d.cts +1 -1
  616. package/dist/plugins/media/api/adapters/local.d.mts +1 -1
  617. package/dist/plugins/media/api/adapters/local.d.ts +1 -1
  618. package/dist/plugins/media/api/adapters/s3.d.cts +1 -1
  619. package/dist/plugins/media/api/adapters/s3.d.mts +1 -1
  620. package/dist/plugins/media/api/adapters/s3.d.ts +1 -1
  621. package/dist/plugins/media/api/adapters/vercel-blob.cjs +46 -0
  622. package/dist/plugins/media/api/adapters/vercel-blob.d.cts +6 -9
  623. package/dist/plugins/media/api/adapters/vercel-blob.d.mts +6 -9
  624. package/dist/plugins/media/api/adapters/vercel-blob.d.ts +6 -9
  625. package/dist/plugins/media/api/adapters/vercel-blob.mjs +46 -0
  626. package/dist/plugins/media/api/index.cjs +10 -0
  627. package/dist/plugins/media/api/index.d.cts +93 -6
  628. package/dist/plugins/media/api/index.d.mts +93 -6
  629. package/dist/plugins/media/api/index.d.ts +93 -6
  630. package/dist/plugins/media/api/index.mjs +2 -0
  631. package/dist/plugins/media/client/components/index.d.cts +1 -1
  632. package/dist/plugins/media/client/components/index.d.mts +1 -1
  633. package/dist/plugins/media/client/components/index.d.ts +1 -1
  634. package/dist/plugins/media/client/hooks/index.d.cts +20 -10
  635. package/dist/plugins/media/client/hooks/index.d.mts +20 -10
  636. package/dist/plugins/media/client/hooks/index.d.ts +20 -10
  637. package/dist/plugins/media/client/index.cjs +1 -0
  638. package/dist/plugins/media/client/index.d.cts +112 -100
  639. package/dist/plugins/media/client/index.d.mts +112 -100
  640. package/dist/plugins/media/client/index.d.ts +112 -100
  641. package/dist/plugins/media/client/index.mjs +1 -1
  642. package/dist/plugins/media/permissions.cjs +63 -0
  643. package/dist/plugins/media/permissions.d.cts +64 -0
  644. package/dist/plugins/media/permissions.d.mts +64 -0
  645. package/dist/plugins/media/permissions.d.ts +64 -0
  646. package/dist/plugins/media/permissions.mjs +61 -0
  647. package/dist/plugins/media/query-keys.cjs +29 -17
  648. package/dist/plugins/media/query-keys.d.cts +24 -31
  649. package/dist/plugins/media/query-keys.d.mts +24 -31
  650. package/dist/plugins/media/query-keys.d.ts +24 -31
  651. package/dist/plugins/media/query-keys.mjs +30 -18
  652. package/dist/plugins/open-api/api/index.d.cts +9 -4
  653. package/dist/plugins/open-api/api/index.d.mts +9 -4
  654. package/dist/plugins/open-api/api/index.d.ts +9 -4
  655. package/dist/plugins/route-docs/client/index.cjs +2 -2
  656. package/dist/plugins/route-docs/client/index.d.cts +54 -53
  657. package/dist/plugins/route-docs/client/index.d.mts +54 -53
  658. package/dist/plugins/route-docs/client/index.d.ts +54 -53
  659. package/dist/plugins/route-docs/client/index.mjs +2 -1
  660. package/dist/plugins/ui-builder/client/components/index.d.cts +8 -5
  661. package/dist/plugins/ui-builder/client/components/index.d.mts +8 -5
  662. package/dist/plugins/ui-builder/client/components/index.d.ts +8 -5
  663. package/dist/plugins/ui-builder/client/hooks/index.d.cts +5 -5
  664. package/dist/plugins/ui-builder/client/hooks/index.d.mts +5 -5
  665. package/dist/plugins/ui-builder/client/hooks/index.d.ts +5 -5
  666. package/dist/plugins/ui-builder/client/index.d.cts +151 -199
  667. package/dist/plugins/ui-builder/client/index.d.mts +151 -199
  668. package/dist/plugins/ui-builder/client/index.d.ts +151 -199
  669. package/dist/plugins/ui-builder/index.d.cts +11 -8
  670. package/dist/plugins/ui-builder/index.d.mts +11 -8
  671. package/dist/plugins/ui-builder/index.d.ts +11 -8
  672. package/dist/plugins/ui-builder/query-keys.d.cts +6 -6
  673. package/dist/plugins/ui-builder/query-keys.d.mts +6 -6
  674. package/dist/plugins/ui-builder/query-keys.d.ts +6 -6
  675. package/dist/react-router/index.cjs +2 -0
  676. package/dist/react-router/index.d.cts +41 -7
  677. package/dist/react-router/index.d.mts +41 -7
  678. package/dist/react-router/index.d.ts +41 -7
  679. package/dist/react-router/index.mjs +1 -0
  680. package/dist/shared/stack.0O62uXqP.d.ts +613 -0
  681. package/dist/shared/stack.0y6iTP03.d.ts +533 -0
  682. package/dist/shared/{stack.CbZenbej.d.cts → stack.1ukVJym7.d.cts} +3 -4
  683. package/dist/shared/{stack.CbZenbej.d.mts → stack.1ukVJym7.d.mts} +3 -4
  684. package/dist/shared/{stack.CbZenbej.d.ts → stack.1ukVJym7.d.ts} +3 -4
  685. package/dist/shared/stack.3Sr6qRtT.d.ts +507 -0
  686. package/dist/shared/{stack.9BAOaSqE.d.mts → stack.5_zzCejP.d.cts} +16 -14
  687. package/dist/shared/{stack.9BAOaSqE.d.ts → stack.5_zzCejP.d.mts} +16 -14
  688. package/dist/shared/{stack.9BAOaSqE.d.cts → stack.5_zzCejP.d.ts} +16 -14
  689. package/dist/shared/stack.B1UrNoVl.d.mts +533 -0
  690. package/dist/shared/{stack.B2xi4jj7.d.cts → stack.B1srlBud.d.mts} +2 -2
  691. package/dist/shared/stack.B3_aDcYL.d.cts +281 -0
  692. package/dist/shared/stack.B3_aDcYL.d.mts +281 -0
  693. package/dist/shared/stack.B3_aDcYL.d.ts +281 -0
  694. package/dist/shared/stack.B5yPgHsp.d.mts +507 -0
  695. package/dist/shared/stack.B8PG21zX.d.mts +764 -0
  696. package/dist/shared/stack.BFP_9pRX.d.cts +707 -0
  697. package/dist/shared/{stack.INBa9-TO.d.cts → stack.BGzgFx3R.d.cts} +5 -5
  698. package/dist/shared/stack.BJx1ZXrN.d.cts +118 -0
  699. package/dist/shared/{stack.7b3vsM8_.d.ts → stack.BK9Z2dcL.d.ts} +2 -2
  700. package/dist/shared/stack.BMHoxAn7.d.mts +707 -0
  701. package/dist/shared/stack.BMmvEBH_.d.ts +118 -0
  702. package/dist/shared/stack.BOZRaVpu.d.cts +1184 -0
  703. package/dist/shared/stack.BPLykw4s.d.ts +436 -0
  704. package/dist/shared/{stack.aqVZ6PEW.d.mts → stack.BRvqQWGt.d.cts} +40 -1
  705. package/dist/shared/{stack.aqVZ6PEW.d.cts → stack.BRvqQWGt.d.mts} +40 -1
  706. package/dist/shared/{stack.aqVZ6PEW.d.ts → stack.BRvqQWGt.d.ts} +40 -1
  707. package/dist/shared/stack.BSACE667.d.cts +23 -0
  708. package/dist/shared/stack.BYMentwB.d.cts +47 -0
  709. package/dist/shared/stack.BYMentwB.d.mts +47 -0
  710. package/dist/shared/stack.BYMentwB.d.ts +47 -0
  711. package/dist/shared/stack.Bt8hfw9o.d.ts +707 -0
  712. package/dist/shared/{stack.D7bewlgt.d.mts → stack.Bu2IPOLi.d.cts} +1 -0
  713. package/dist/shared/{stack.D7bewlgt.d.ts → stack.Bu2IPOLi.d.mts} +1 -0
  714. package/dist/shared/{stack.D7bewlgt.d.cts → stack.Bu2IPOLi.d.ts} +1 -0
  715. package/dist/shared/stack.BuxUQqL8.d.ts +408 -0
  716. package/dist/shared/stack.BzWGB5MG.d.cts +436 -0
  717. package/dist/shared/stack.C3bU9w6L.d.ts +351 -0
  718. package/dist/shared/stack.C4oVW2qK.d.cts +507 -0
  719. package/dist/shared/stack.CKXzdGiJ.d.cts +3 -0
  720. package/dist/shared/stack.CKXzdGiJ.d.mts +3 -0
  721. package/dist/shared/stack.CKXzdGiJ.d.ts +3 -0
  722. package/dist/shared/{stack.C3GBG8in.d.ts → stack.COrJrztD.d.cts} +1 -1
  723. package/dist/shared/{stack.C3GBG8in.d.cts → stack.COrJrztD.d.mts} +1 -1
  724. package/dist/shared/{stack.C3GBG8in.d.mts → stack.COrJrztD.d.ts} +1 -1
  725. package/dist/shared/stack.CX83YNuS.d.cts +408 -0
  726. package/dist/shared/stack.Cbd7sD5M.d.mts +118 -0
  727. package/dist/shared/{stack.B9NtGpAR.d.ts → stack.CcjENrr4.d.cts} +1 -5
  728. package/dist/shared/stack.CfK5NKlK.d.mts +613 -0
  729. package/dist/shared/{stack.3di7vQs6.d.mts → stack.CjCSDfWy.d.mts} +5 -5
  730. package/dist/shared/stack.Cmg7lzzy.d.cts +44 -0
  731. package/dist/shared/stack.Cmg7lzzy.d.mts +44 -0
  732. package/dist/shared/stack.Cmg7lzzy.d.ts +44 -0
  733. package/dist/shared/stack.CpE1mS3p.d.ts +331 -0
  734. package/dist/shared/stack.CskhFw3z.d.mts +23 -0
  735. package/dist/shared/stack.CvlC5kqe.d.cts +331 -0
  736. package/dist/shared/stack.CxKc9evq.d.ts +23 -0
  737. package/dist/shared/stack.CyalJ0j6.d.ts +764 -0
  738. package/dist/shared/stack.D6Pg-ufX.d.cts +764 -0
  739. package/dist/shared/{stack.lkebw2nj.d.mts → stack.DVEjWKCT.d.cts} +19 -5
  740. package/dist/shared/{stack.lkebw2nj.d.ts → stack.DVEjWKCT.d.mts} +19 -5
  741. package/dist/shared/{stack.lkebw2nj.d.cts → stack.DVEjWKCT.d.ts} +19 -5
  742. package/dist/shared/{stack.Cp_6mO5s.d.mts → stack.DbbvHbhn.d.mts} +1 -5
  743. package/dist/shared/stack.DiuRuzIs.d.cts +613 -0
  744. package/dist/shared/{stack.BMlLOMED.d.mts → stack.DjGixVx3.d.cts} +6 -2
  745. package/dist/shared/{stack.BMlLOMED.d.ts → stack.DjGixVx3.d.mts} +6 -2
  746. package/dist/shared/{stack.BMlLOMED.d.cts → stack.DjGixVx3.d.ts} +6 -2
  747. package/dist/shared/stack.DlBoNqYu.d.ts +1184 -0
  748. package/dist/shared/stack.DlCycSM-.d.mts +331 -0
  749. package/dist/shared/{stack.DycBcTeg.d.mts → stack.DmpPDPxA.d.cts} +2 -2
  750. package/dist/shared/{stack.CRelKJfH.d.ts → stack.Dpg_JjIo.d.ts} +5 -5
  751. package/dist/shared/stack.Dvy7FmaA.d.mts +1184 -0
  752. package/dist/shared/stack.DxHPKr2R.d.mts +436 -0
  753. package/dist/shared/stack.Egr3RWhA.d.mts +408 -0
  754. package/dist/shared/stack.Mak7pzIV.d.cts +533 -0
  755. package/dist/shared/stack.OYT8WU4n.d.mts +351 -0
  756. package/dist/shared/{stack.CPsYC2-Z.d.cts → stack.fdi94T4S.d.cts} +7 -7
  757. package/dist/shared/{stack.CPsYC2-Z.d.mts → stack.fdi94T4S.d.mts} +7 -7
  758. package/dist/shared/{stack.CPsYC2-Z.d.ts → stack.fdi94T4S.d.ts} +7 -7
  759. package/dist/shared/{stack.Dlgtumru.d.cts → stack.kaCV7vEL.d.ts} +1 -5
  760. package/dist/shared/stack.v2O65JqF.d.cts +351 -0
  761. package/dist/tanstack/index.cjs +2 -0
  762. package/dist/tanstack/index.d.cts +44 -14
  763. package/dist/tanstack/index.d.mts +44 -14
  764. package/dist/tanstack/index.d.ts +44 -14
  765. package/dist/tanstack/index.mjs +1 -0
  766. package/dist/tanstack/server.cjs +9 -0
  767. package/dist/tanstack/server.d.cts +15 -0
  768. package/dist/tanstack/server.d.mts +15 -0
  769. package/dist/tanstack/server.d.ts +15 -0
  770. package/dist/tanstack/server.mjs +7 -0
  771. package/package.json +203 -8
  772. package/src/__tests__/ai-chat-client-runtime.test.ts +481 -0
  773. package/src/__tests__/ai-chat-client-runtime.typecheck.tsx +130 -0
  774. package/src/__tests__/ai-chat-lifecycle-migrations.typecheck.ts +61 -0
  775. package/src/__tests__/ai-chat-query-keys.test.ts +125 -22
  776. package/src/__tests__/auth-provider.test.tsx +41 -314
  777. package/src/__tests__/auth-test-utils.ts +24 -0
  778. package/src/__tests__/authorization-client.test.tsx +767 -0
  779. package/src/__tests__/authorization-contraction.test.ts +182 -0
  780. package/src/__tests__/authorization-remote.test.ts +222 -0
  781. package/src/__tests__/authorization-server.test.ts +90 -0
  782. package/src/__tests__/authorization.test.ts +652 -0
  783. package/src/__tests__/authorization.typecheck.ts +671 -0
  784. package/src/__tests__/backend-plugin-factories.test.ts +54 -0
  785. package/src/__tests__/backend-plugin-factories.typecheck.ts +133 -0
  786. package/src/__tests__/client-plugin-ssr-loaders.test.ts +304 -138
  787. package/src/__tests__/client-runtime.test.ts +1021 -0
  788. package/src/__tests__/client-runtime.typecheck.ts +107 -0
  789. package/src/__tests__/client-stack-test-utils.ts +36 -0
  790. package/src/__tests__/content-lifecycle-migrations.typecheck.ts +122 -0
  791. package/src/__tests__/endpoint-inventory.test.ts +768 -0
  792. package/src/__tests__/entry-factories.test.tsx +104 -4
  793. package/src/__tests__/form-builder-query-keys.test.ts +32 -0
  794. package/src/__tests__/i18n-provider.test.tsx +4 -3
  795. package/src/__tests__/initial-identity-hydration.test.tsx +156 -0
  796. package/src/__tests__/initial-identity-layouts.test.tsx +204 -0
  797. package/src/__tests__/kanban-query-keys.test.ts +189 -2
  798. package/src/__tests__/managed-origin-hydration.browser.test.tsx +163 -0
  799. package/src/__tests__/media-query-keys.test.ts +91 -17
  800. package/src/__tests__/notify-provider.test.tsx +3 -2
  801. package/src/__tests__/package-metadata.test.ts +315 -0
  802. package/src/__tests__/page-component-overrides.test.tsx +3 -4
  803. package/src/__tests__/plugin-registration.test.tsx +183 -0
  804. package/src/__tests__/plugin-registration.typecheck.tsx +139 -0
  805. package/src/__tests__/plugins.test.tsx +72 -42
  806. package/src/__tests__/resource-factory.test.tsx +79 -2
  807. package/src/__tests__/resource-use-form.test.tsx +2 -2
  808. package/src/__tests__/resource-use-select.test.tsx +2 -4
  809. package/src/__tests__/router-overrides.test.tsx +20 -8
  810. package/src/__tests__/sitemap.test.ts +38 -22
  811. package/src/__tests__/stack-api.test.ts +39 -34
  812. package/src/__tests__/stack-auth.test.ts +44 -140
  813. package/src/__tests__/stack-constructors.test.ts +96 -0
  814. package/src/__tests__/stack-constructors.typecheck.ts +115 -0
  815. package/src/__tests__/use-list-state.test.tsx +7 -6
  816. package/src/__tests__/workflow-lifecycle-migrations.typecheck.ts +150 -0
  817. package/src/api/index.ts +204 -99
  818. package/src/authorization/client.tsx +310 -0
  819. package/src/authorization/index.ts +873 -0
  820. package/src/authorization/json.ts +70 -0
  821. package/src/authorization/remote.ts +234 -0
  822. package/src/authorization/server.ts +171 -0
  823. package/src/client/__tests__/server-origin.test.ts +119 -0
  824. package/src/client/components/compose.tsx +126 -18
  825. package/src/client/hooks/index.ts +12 -0
  826. package/src/client/hooks/use-list-state.ts +7 -13
  827. package/src/client/index.ts +105 -50
  828. package/src/client/runtime.ts +414 -0
  829. package/src/client/server.ts +174 -0
  830. package/src/context/auth.tsx +205 -154
  831. package/src/context/index.ts +10 -4
  832. package/src/context/provider.tsx +96 -57
  833. package/src/context/router.tsx +7 -0
  834. package/src/context/site-navigation.ts +52 -0
  835. package/src/next/index.tsx +2 -0
  836. package/src/next/layout.tsx +81 -0
  837. package/src/next/page.tsx +33 -12
  838. package/src/next/router.tsx +1 -1
  839. package/src/next/server.ts +5 -0
  840. package/src/plugin-registration.ts +70 -0
  841. package/src/plugins/ai-chat/__tests__/authorization.test.ts +2051 -0
  842. package/src/plugins/ai-chat/__tests__/chat-hooks.test.tsx +147 -0
  843. package/src/plugins/ai-chat/__tests__/chat-input-authorization.test.tsx +188 -0
  844. package/src/plugins/ai-chat/__tests__/client-sweep.test.tsx +1506 -34
  845. package/src/plugins/ai-chat/__tests__/hooks.test.tsx +131 -23
  846. package/src/plugins/ai-chat/api/getters.ts +2 -2
  847. package/src/plugins/ai-chat/api/index.ts +6 -1
  848. package/src/plugins/ai-chat/api/lifecycle-migrations.ts +20 -0
  849. package/src/plugins/ai-chat/api/operations.ts +1865 -0
  850. package/src/plugins/ai-chat/api/plugin.ts +78 -1168
  851. package/src/plugins/ai-chat/api/serializers.ts +30 -0
  852. package/src/plugins/ai-chat/client/components/chat-input.tsx +228 -129
  853. package/src/plugins/ai-chat/client/components/chat-interface.tsx +776 -183
  854. package/src/plugins/ai-chat/client/components/chat-layout.tsx +6 -7
  855. package/src/plugins/ai-chat/client/components/chat-message.tsx +1 -1
  856. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +57 -37
  857. package/src/plugins/ai-chat/client/components/pages/404-page.tsx +1 -1
  858. package/src/plugins/ai-chat/client/components/pages/chat-page.internal.tsx +5 -3
  859. package/src/plugins/ai-chat/client/components/pages/chat-page.tsx +56 -15
  860. package/src/plugins/ai-chat/client/components/shared/default-error.tsx +1 -1
  861. package/src/plugins/ai-chat/client/components/tool-call-display.tsx +1 -1
  862. package/src/plugins/ai-chat/client/hooks/ai-chat-resource.ts +1 -1
  863. package/src/plugins/ai-chat/client/hooks/chat-hooks.tsx +253 -20
  864. package/src/plugins/ai-chat/client/index.ts +1 -0
  865. package/src/plugins/ai-chat/client/navigation.ts +11 -0
  866. package/src/plugins/ai-chat/client/overrides.ts +47 -11
  867. package/src/plugins/ai-chat/client/plugin.tsx +208 -111
  868. package/src/plugins/ai-chat/permissions.ts +89 -0
  869. package/src/plugins/ai-chat/query-keys.ts +183 -25
  870. package/src/plugins/ai-chat/types.ts +7 -5
  871. package/src/plugins/api/create-endpoint.ts +40 -22
  872. package/src/plugins/api/endpoint-inventory.ts +206 -0
  873. package/src/plugins/api/index.ts +38 -4
  874. package/src/plugins/api/operation.ts +600 -0
  875. package/src/plugins/blog/__tests__/authorization.test.ts +1366 -0
  876. package/src/plugins/blog/__tests__/client-runtime.browser.test.tsx +257 -0
  877. package/src/plugins/blog/__tests__/client-runtime.test.ts +283 -0
  878. package/src/plugins/blog/__tests__/client-runtime.typecheck.tsx +98 -0
  879. package/src/plugins/blog/__tests__/client-sweep.test.tsx +212 -37
  880. package/src/plugins/blog/api/getters.ts +3 -3
  881. package/src/plugins/blog/api/index.ts +2 -0
  882. package/src/plugins/blog/api/lifecycle-migrations.ts +19 -0
  883. package/src/plugins/blog/api/mutations.ts +26 -5
  884. package/src/plugins/blog/api/operations.ts +727 -0
  885. package/src/plugins/blog/api/plugin.ts +99 -504
  886. package/src/plugins/blog/client/components/forms/image-field.tsx +2 -1
  887. package/src/plugins/blog/client/components/forms/markdown-editor-with-overrides.tsx +2 -1
  888. package/src/plugins/blog/client/components/forms/post-forms.tsx +61 -33
  889. package/src/plugins/blog/client/components/pages/404-page.tsx +3 -1
  890. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +2 -1
  891. package/src/plugins/blog/client/components/pages/edit-post-page.tsx +28 -5
  892. package/src/plugins/blog/client/components/pages/home-page.internal.tsx +2 -1
  893. package/src/plugins/blog/client/components/pages/home-page.tsx +7 -4
  894. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +2 -1
  895. package/src/plugins/blog/client/components/pages/new-post-page.tsx +5 -2
  896. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +2 -1
  897. package/src/plugins/blog/client/components/pages/post-page.tsx +38 -4
  898. package/src/plugins/blog/client/components/pages/tag-page.internal.tsx +2 -1
  899. package/src/plugins/blog/client/components/pages/tag-page.tsx +5 -1
  900. package/src/plugins/blog/client/components/shared/collapsible-tag-list.tsx +2 -1
  901. package/src/plugins/blog/client/components/shared/default-error.tsx +3 -1
  902. package/src/plugins/blog/client/components/shared/on-this-page.tsx +5 -2
  903. package/src/plugins/blog/client/components/shared/page-wrapper.tsx +2 -1
  904. package/src/plugins/blog/client/components/shared/post-card.tsx +2 -1
  905. package/src/plugins/blog/client/components/shared/posts-list.tsx +2 -1
  906. package/src/plugins/blog/client/components/shared/recent-posts-carousel.tsx +2 -1
  907. package/src/plugins/blog/client/components/shared/search-input.tsx +1 -1
  908. package/src/plugins/blog/client/constants.ts +2 -0
  909. package/src/plugins/blog/client/hooks/blog-resource.ts +2 -1
  910. package/src/plugins/blog/client/overrides.ts +1 -6
  911. package/src/plugins/blog/client/plugin.tsx +145 -129
  912. package/src/plugins/blog/permissions.ts +44 -0
  913. package/src/plugins/client/index.ts +108 -7
  914. package/src/plugins/client/resource/hooks.tsx +41 -18
  915. package/src/plugins/client/resource/internal.ts +77 -61
  916. package/src/plugins/client/resource/queries.ts +3 -4
  917. package/src/plugins/client/resource/use-form.ts +23 -20
  918. package/src/plugins/client/resource/use-select.ts +40 -34
  919. package/src/plugins/cms/__tests__/authorization.test.ts +2188 -0
  920. package/src/plugins/cms/__tests__/client-runtime.browser.test.tsx +245 -0
  921. package/src/plugins/cms/__tests__/client-runtime.test.ts +320 -0
  922. package/src/plugins/cms/__tests__/client-runtime.typecheck.tsx +208 -0
  923. package/src/plugins/cms/__tests__/client-sweep.test.tsx +202 -50
  924. package/src/plugins/cms/api/getters.ts +4 -4
  925. package/src/plugins/cms/api/index.ts +20 -0
  926. package/src/plugins/cms/api/lifecycle-migrations.ts +15 -0
  927. package/src/plugins/cms/api/mutations.ts +2 -2
  928. package/src/plugins/cms/api/operations.ts +2218 -0
  929. package/src/plugins/cms/api/plugin.ts +169 -1047
  930. package/src/plugins/cms/api/relations.ts +3 -1
  931. package/src/plugins/cms/client/components/forms/content-form.tsx +2 -1
  932. package/src/plugins/cms/client/components/forms/file-upload.tsx +3 -1
  933. package/src/plugins/cms/client/components/forms/relation-field.tsx +3 -1
  934. package/src/plugins/cms/client/components/inverse-relations-panel.tsx +29 -17
  935. package/src/plugins/cms/client/components/pages/404-page.tsx +7 -5
  936. package/src/plugins/cms/client/components/pages/content-editor-page.internal.tsx +19 -10
  937. package/src/plugins/cms/client/components/pages/content-editor-page.tsx +50 -12
  938. package/src/plugins/cms/client/components/pages/content-list-page.internal.tsx +48 -34
  939. package/src/plugins/cms/client/components/pages/content-list-page.tsx +8 -1
  940. package/src/plugins/cms/client/components/pages/dashboard-page.internal.tsx +15 -8
  941. package/src/plugins/cms/client/components/pages/dashboard-page.tsx +5 -1
  942. package/src/plugins/cms/client/components/shared/page-wrapper.tsx +2 -1
  943. package/src/plugins/cms/client/constants.ts +2 -0
  944. package/src/plugins/cms/client/hooks/cms-resource.ts +2 -1
  945. package/src/plugins/cms/client/index.ts +6 -1
  946. package/src/plugins/cms/client/overrides.ts +46 -6
  947. package/src/plugins/cms/client/plugin.tsx +135 -80
  948. package/src/plugins/cms/permissions.ts +43 -0
  949. package/src/plugins/cms/types.ts +174 -46
  950. package/src/plugins/comments/__tests__/authorization.test.ts +1570 -0
  951. package/src/plugins/comments/__tests__/client-runtime.browser.test.tsx +207 -0
  952. package/src/plugins/comments/__tests__/client-runtime.test.ts +224 -0
  953. package/src/plugins/comments/__tests__/client-runtime.typecheck.tsx +85 -0
  954. package/src/plugins/comments/__tests__/client-sweep.test.tsx +465 -79
  955. package/src/plugins/comments/api/getters.ts +19 -3
  956. package/src/plugins/comments/api/index.ts +2 -6
  957. package/src/plugins/comments/api/lifecycle-migrations.ts +20 -0
  958. package/src/plugins/comments/api/mutations.ts +261 -88
  959. package/src/plugins/comments/api/operations.ts +742 -0
  960. package/src/plugins/comments/api/plugin.ts +76 -548
  961. package/src/plugins/comments/client/components/comment-count.tsx +38 -5
  962. package/src/plugins/comments/client/components/comment-thread.tsx +154 -112
  963. package/src/plugins/comments/client/components/pages/moderation-page.internal.tsx +144 -78
  964. package/src/plugins/comments/client/components/pages/moderation-page.tsx +18 -2
  965. package/src/plugins/comments/client/components/pages/moderation-state.ts +13 -0
  966. package/src/plugins/comments/client/components/pages/my-comments-page.internal.tsx +38 -30
  967. package/src/plugins/comments/client/components/pages/my-comments-page.tsx +3 -1
  968. package/src/plugins/comments/client/components/pages/resource-comments-page.internal.tsx +29 -30
  969. package/src/plugins/comments/client/components/pages/resource-comments-page.tsx +10 -1
  970. package/src/plugins/comments/client/components/shared/page-wrapper.tsx +2 -1
  971. package/src/plugins/comments/client/components/shared/pagination.tsx +2 -1
  972. package/src/plugins/comments/client/constants.ts +2 -0
  973. package/src/plugins/comments/client/hooks/use-comments.tsx +430 -421
  974. package/src/plugins/comments/client/localization/comments-thread.ts +1 -0
  975. package/src/plugins/comments/client/plugin.tsx +113 -72
  976. package/src/plugins/comments/permissions.ts +68 -0
  977. package/src/plugins/comments/query-keys.ts +9 -10
  978. package/src/plugins/comments/schemas.ts +7 -8
  979. package/src/plugins/form-builder/__tests__/authorization.test.ts +1600 -0
  980. package/src/plugins/form-builder/__tests__/client-runtime.browser.test.tsx +255 -0
  981. package/src/plugins/form-builder/__tests__/client-runtime.test.ts +132 -0
  982. package/src/plugins/form-builder/__tests__/client-runtime.typecheck.tsx +77 -0
  983. package/src/plugins/form-builder/__tests__/client-sweep.test.tsx +350 -54
  984. package/src/plugins/form-builder/__tests__/form-renderer-authorization.test.tsx +162 -0
  985. package/src/plugins/form-builder/api/getters.ts +21 -5
  986. package/src/plugins/form-builder/api/index.ts +31 -0
  987. package/src/plugins/form-builder/api/lifecycle-migrations.ts +17 -0
  988. package/src/plugins/form-builder/api/operations.ts +1493 -0
  989. package/src/plugins/form-builder/api/plugin.ts +125 -632
  990. package/src/plugins/form-builder/api/query-key-defs.ts +7 -0
  991. package/src/plugins/form-builder/api/serializers.ts +1 -0
  992. package/src/plugins/form-builder/client/components/forms/form-renderer.tsx +49 -19
  993. package/src/plugins/form-builder/client/components/pages/404-page.tsx +9 -9
  994. package/src/plugins/form-builder/client/components/pages/form-builder-page.internal.tsx +54 -30
  995. package/src/plugins/form-builder/client/components/pages/form-builder-page.tsx +42 -9
  996. package/src/plugins/form-builder/client/components/pages/form-list-page.internal.tsx +46 -34
  997. package/src/plugins/form-builder/client/components/pages/form-list-page.tsx +6 -2
  998. package/src/plugins/form-builder/client/components/pages/submissions-page.internal.tsx +98 -64
  999. package/src/plugins/form-builder/client/components/pages/submissions-page.tsx +29 -9
  1000. package/src/plugins/form-builder/client/components/shared/page-wrapper.tsx +2 -1
  1001. package/src/plugins/form-builder/client/constants.ts +2 -0
  1002. package/src/plugins/form-builder/client/hooks/form-builder-hooks.tsx +68 -4
  1003. package/src/plugins/form-builder/client/hooks/form-builder-resource.ts +2 -1
  1004. package/src/plugins/form-builder/client/hooks/index.tsx +1 -0
  1005. package/src/plugins/form-builder/client/overrides.ts +1 -6
  1006. package/src/plugins/form-builder/client/plugin.tsx +128 -96
  1007. package/src/plugins/form-builder/permissions.ts +94 -0
  1008. package/src/plugins/form-builder/query-keys.ts +28 -3
  1009. package/src/plugins/form-builder/schemas.ts +9 -1
  1010. package/src/plugins/form-builder/types.ts +173 -41
  1011. package/src/plugins/kanban/__tests__/authorization.test.ts +1382 -0
  1012. package/src/plugins/kanban/__tests__/client-runtime.browser.test.tsx +302 -0
  1013. package/src/plugins/kanban/__tests__/client-runtime.test.ts +130 -0
  1014. package/src/plugins/kanban/__tests__/client-runtime.typecheck.tsx +81 -0
  1015. package/src/plugins/kanban/__tests__/client-sweep.test.tsx +418 -33
  1016. package/src/plugins/kanban/__tests__/identity-partition.test.tsx +306 -0
  1017. package/src/plugins/kanban/api/getters.ts +65 -50
  1018. package/src/plugins/kanban/api/index.ts +55 -4
  1019. package/src/plugins/kanban/api/lifecycle-migrations.ts +25 -0
  1020. package/src/plugins/kanban/api/mutations.ts +3 -3
  1021. package/src/plugins/kanban/api/operations.ts +2065 -0
  1022. package/src/plugins/kanban/api/plugin.ts +83 -1013
  1023. package/src/plugins/kanban/api/serializers.ts +26 -0
  1024. package/src/plugins/kanban/client/components/forms/board-form.tsx +3 -1
  1025. package/src/plugins/kanban/client/components/forms/column-form.tsx +3 -1
  1026. package/src/plugins/kanban/client/components/forms/task-form.tsx +92 -74
  1027. package/src/plugins/kanban/client/components/pages/404-page.tsx +6 -9
  1028. package/src/plugins/kanban/client/components/pages/board-page.internal.tsx +57 -74
  1029. package/src/plugins/kanban/client/components/pages/board-page.tsx +31 -7
  1030. package/src/plugins/kanban/client/components/pages/boards-list-page.internal.tsx +54 -45
  1031. package/src/plugins/kanban/client/components/pages/boards-list-page.tsx +2 -1
  1032. package/src/plugins/kanban/client/components/pages/new-board-page.internal.tsx +8 -12
  1033. package/src/plugins/kanban/client/components/pages/new-board-page.tsx +2 -1
  1034. package/src/plugins/kanban/client/components/shared/column-content.tsx +61 -48
  1035. package/src/plugins/kanban/client/components/shared/default-error.tsx +3 -1
  1036. package/src/plugins/kanban/client/components/shared/kanban-board.tsx +6 -6
  1037. package/src/plugins/kanban/client/components/shared/permission-access-any.tsx +32 -0
  1038. package/src/plugins/kanban/client/components/shared/task-card.tsx +64 -20
  1039. package/src/plugins/kanban/client/components/shared/user-avatar.tsx +3 -1
  1040. package/src/plugins/kanban/client/constants.ts +2 -0
  1041. package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +55 -10
  1042. package/src/plugins/kanban/client/hooks/kanban-resource.ts +2 -1
  1043. package/src/plugins/kanban/client/overrides.ts +0 -5
  1044. package/src/plugins/kanban/client/plugin.tsx +201 -113
  1045. package/src/plugins/kanban/permissions.ts +100 -0
  1046. package/src/plugins/kanban/query-keys.ts +61 -21
  1047. package/src/plugins/kanban/schemas.ts +44 -18
  1048. package/src/plugins/kanban/types.ts +381 -1
  1049. package/src/plugins/media/__tests__/authorization.test.ts +1769 -0
  1050. package/src/plugins/media/__tests__/client-runtime.browser.test.tsx +975 -0
  1051. package/src/plugins/media/__tests__/client-runtime.test.ts +539 -0
  1052. package/src/plugins/media/__tests__/client-runtime.typecheck.tsx +135 -0
  1053. package/src/plugins/media/__tests__/client-sweep.test.tsx +292 -24
  1054. package/src/plugins/media/__tests__/identity-partition.test.tsx +741 -0
  1055. package/src/plugins/media/__tests__/plugin.test.ts +68 -28
  1056. package/src/plugins/media/__tests__/query-key-defs.test.ts +32 -2
  1057. package/src/plugins/media/api/adapters/vercel-blob.ts +84 -8
  1058. package/src/plugins/media/api/getters.ts +6 -6
  1059. package/src/plugins/media/api/index.ts +3 -0
  1060. package/src/plugins/media/api/lifecycle-migrations.ts +11 -0
  1061. package/src/plugins/media/api/mutations.ts +19 -13
  1062. package/src/plugins/media/api/operations.ts +1873 -0
  1063. package/src/plugins/media/api/plugin.ts +211 -899
  1064. package/src/plugins/media/api/query-key-defs.ts +66 -4
  1065. package/src/plugins/media/api/serializers.ts +4 -2
  1066. package/src/plugins/media/api/storage-adapter.ts +22 -4
  1067. package/src/plugins/media/asset-url.ts +14 -0
  1068. package/src/plugins/media/client/components/media-picker/asset-card.tsx +105 -98
  1069. package/src/plugins/media/client/components/media-picker/folder-tree.tsx +82 -60
  1070. package/src/plugins/media/client/components/media-picker/index.tsx +235 -171
  1071. package/src/plugins/media/client/components/media-picker/upload-tab.tsx +2 -10
  1072. package/src/plugins/media/client/components/media-picker/url-tab.tsx +1 -8
  1073. package/src/plugins/media/client/components/pages/library-page.internal.tsx +103 -82
  1074. package/src/plugins/media/client/components/pages/library-page.tsx +4 -2
  1075. package/src/plugins/media/client/components/upload-permission-check.tsx +75 -0
  1076. package/src/plugins/media/client/constants.ts +2 -0
  1077. package/src/plugins/media/client/hooks/media-resource.ts +2 -1
  1078. package/src/plugins/media/client/hooks/use-media.tsx +292 -49
  1079. package/src/plugins/media/client/index.ts +16 -3
  1080. package/src/plugins/media/client/overrides.ts +6 -17
  1081. package/src/plugins/media/client/plugin.tsx +188 -123
  1082. package/src/plugins/media/client/upload.ts +170 -53
  1083. package/src/plugins/media/db.ts +8 -0
  1084. package/src/plugins/media/permissions.ts +61 -0
  1085. package/src/plugins/media/query-keys.ts +63 -19
  1086. package/src/plugins/media/types.ts +8 -2
  1087. package/src/plugins/open-api/__tests__/route-introspection.test.ts +277 -0
  1088. package/src/plugins/open-api/api/generator.ts +49 -8
  1089. package/src/plugins/open-api/api/plugin.ts +36 -14
  1090. package/src/plugins/route-docs/client/components/pages/docs-page.tsx +63 -23
  1091. package/src/plugins/route-docs/client/constants.ts +2 -0
  1092. package/src/plugins/route-docs/client/hooks.ts +23 -13
  1093. package/src/plugins/route-docs/client/index.ts +7 -1
  1094. package/src/plugins/route-docs/client/plugin.tsx +222 -145
  1095. package/src/plugins/route-docs/client/schema.ts +31 -0
  1096. package/src/plugins/route-docs/generator.ts +9 -5
  1097. package/src/plugins/ui-builder/__tests__/client-sweep.test.tsx +427 -48
  1098. package/src/plugins/ui-builder/client/components/page-renderer.tsx +58 -16
  1099. package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +47 -26
  1100. package/src/plugins/ui-builder/client/components/pages/page-builder-page.tsx +43 -8
  1101. package/src/plugins/ui-builder/client/components/pages/page-list-page.internal.tsx +38 -19
  1102. package/src/plugins/ui-builder/client/components/pages/page-list-page.tsx +8 -2
  1103. package/src/plugins/ui-builder/client/components/shared/default-error.tsx +2 -1
  1104. package/src/plugins/ui-builder/client/components/shared/page-wrapper.tsx +2 -1
  1105. package/src/plugins/ui-builder/client/constants.ts +2 -0
  1106. package/src/plugins/ui-builder/client/hooks/ui-builder-resource.ts +2 -1
  1107. package/src/plugins/ui-builder/client/index.ts +4 -1
  1108. package/src/plugins/ui-builder/client/overrides.ts +16 -21
  1109. package/src/plugins/ui-builder/client/plugin.tsx +119 -66
  1110. package/src/plugins/ui-builder/client/registry.ts +3 -5
  1111. package/src/plugins/ui-builder/types.ts +7 -4
  1112. package/src/plugins/utils.ts +5 -1
  1113. package/src/react-router/index.tsx +6 -0
  1114. package/src/react-router/layout.ts +43 -0
  1115. package/src/react-router/page.tsx +46 -17
  1116. package/src/react-router/router.tsx +1 -1
  1117. package/src/shared/auth-types.ts +19 -70
  1118. package/src/shared/entry-factories.ts +12 -3
  1119. package/src/shared/initial-identity.ts +73 -0
  1120. package/src/shared/list-state.ts +12 -0
  1121. package/src/shared/types.ts +1 -0
  1122. package/src/tanstack/index.tsx +7 -0
  1123. package/src/tanstack/layout.ts +36 -0
  1124. package/src/tanstack/page.tsx +35 -13
  1125. package/src/tanstack/router.tsx +1 -1
  1126. package/src/tanstack/server.ts +18 -0
  1127. package/src/types.ts +557 -65
  1128. package/dist/shared/stack.80-y2TTR.d.mts +0 -840
  1129. package/dist/shared/stack.B-hEIoUw.d.ts +0 -406
  1130. package/dist/shared/stack.B8vdOMnQ.d.cts +0 -329
  1131. package/dist/shared/stack.BISAZ5LX.d.mts +0 -492
  1132. package/dist/shared/stack.BL5PvShn.d.mts +0 -193
  1133. package/dist/shared/stack.Be1QIHEn.d.cts +0 -23
  1134. package/dist/shared/stack.Be1QIHEn.d.mts +0 -23
  1135. package/dist/shared/stack.Be1QIHEn.d.ts +0 -23
  1136. package/dist/shared/stack.BjvOk_Bs.d.cts +0 -492
  1137. package/dist/shared/stack.Bk5UB_BT.d.ts +0 -840
  1138. package/dist/shared/stack.BozPgbrZ.d.cts +0 -201
  1139. package/dist/shared/stack.BozPgbrZ.d.mts +0 -201
  1140. package/dist/shared/stack.BozPgbrZ.d.ts +0 -201
  1141. package/dist/shared/stack.BqTR6qi2.d.ts +0 -193
  1142. package/dist/shared/stack.BvxHSZYT.d.cts +0 -406
  1143. package/dist/shared/stack.C1ATQ3pd.d.ts +0 -416
  1144. package/dist/shared/stack.C4_gEENS.d.cts +0 -97
  1145. package/dist/shared/stack.C4_gEENS.d.mts +0 -97
  1146. package/dist/shared/stack.C4_gEENS.d.ts +0 -97
  1147. package/dist/shared/stack.C5Y5lViI.d.cts +0 -461
  1148. package/dist/shared/stack.C8SwdUz8.d.ts +0 -461
  1149. package/dist/shared/stack.CBsp9rDM.d.cts +0 -193
  1150. package/dist/shared/stack.CMbX8Q5C.d.ts +0 -560
  1151. package/dist/shared/stack.Cf-DbL1A.d.ts +0 -329
  1152. package/dist/shared/stack.DHTvwoNG.d.mts +0 -329
  1153. package/dist/shared/stack.DJaKVY7v.d.cts +0 -76
  1154. package/dist/shared/stack.DJaKVY7v.d.mts +0 -76
  1155. package/dist/shared/stack.DJaKVY7v.d.ts +0 -76
  1156. package/dist/shared/stack.DKZMaVr6.d.cts +0 -416
  1157. package/dist/shared/stack.DQq8DEIv.d.mts +0 -461
  1158. package/dist/shared/stack.Dd-8shBE.d.ts +0 -492
  1159. package/dist/shared/stack.Dj04W2c3.d.mts +0 -560
  1160. package/dist/shared/stack.DrUBX-QE.d.cts +0 -34
  1161. package/dist/shared/stack.DrUBX-QE.d.mts +0 -34
  1162. package/dist/shared/stack.DrUBX-QE.d.ts +0 -34
  1163. package/dist/shared/stack.H5B8miAV.d.cts +0 -840
  1164. package/dist/shared/stack.aXdBOJAR.d.cts +0 -173
  1165. package/dist/shared/stack.aXdBOJAR.d.mts +0 -173
  1166. package/dist/shared/stack.aXdBOJAR.d.ts +0 -173
  1167. package/dist/shared/stack.eq5eg1yt.d.cts +0 -560
  1168. package/dist/shared/stack.f8Vke-eH.d.mts +0 -406
  1169. package/dist/shared/stack.oBokjN_J.d.mts +0 -416
  1170. package/dist/shared/{stack.B0muOwUF.d.cts → stack.Csi-4Mgz.d.cts} +8 -8
  1171. package/dist/shared/{stack.B0muOwUF.d.mts → stack.Csi-4Mgz.d.mts} +8 -8
  1172. package/dist/shared/{stack.B0muOwUF.d.ts → stack.Csi-4Mgz.d.ts} +8 -8
@@ -0,0 +1,1865 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import type { DBAdapter as Adapter } from "@btst/db";
3
+ import type { PermissionFactsFor } from "@btst/stack/authorization";
4
+ import {
5
+ defineOperation,
6
+ definePassthroughOperation,
7
+ type DeepReadonly,
8
+ type Operation,
9
+ OperationHttpError,
10
+ type OperationContext,
11
+ } from "@btst/stack/plugins/api";
12
+ import {
13
+ convertToModelMessages,
14
+ stepCountIs,
15
+ streamText,
16
+ type LanguageModel,
17
+ type Tool,
18
+ type UIMessage,
19
+ } from "ai";
20
+ import { z } from "zod";
21
+ import { aiChatPermissions } from "../permissions";
22
+ import {
23
+ chatRequestSchema,
24
+ createConversationSchema,
25
+ updateConversationSchema,
26
+ } from "../schemas";
27
+ import type {
28
+ Conversation,
29
+ Message,
30
+ SerializedConversation,
31
+ SerializedMessage,
32
+ } from "../types";
33
+ import { getAllConversations, getConversationById } from "./getters";
34
+ import {
35
+ BUILT_IN_PAGE_TOOL_ROUTE_ALLOWLIST,
36
+ BUILT_IN_PAGE_TOOL_SCHEMAS,
37
+ } from "./page-tools";
38
+ import { serializeConversation, serializeMessage } from "./serializers";
39
+
40
+ type TransactionAdapter = Parameters<Parameters<Adapter["transaction"]>[0]>[0];
41
+ type ActiveAdapter = Omit<Adapter, "transaction"> &
42
+ Partial<Pick<Adapter, "transaction">>;
43
+ type MemoryHistoryLockContext = {
44
+ owner: object;
45
+ adapter: ActiveAdapter;
46
+ inTransaction?: boolean;
47
+ rollbackError?: unknown;
48
+ rollbackOnly?: boolean;
49
+ };
50
+
51
+ export type AiChatAccess = "authorized" | "public";
52
+
53
+ /** Runtime input for one conversation operation. */
54
+ export const ConversationOperationInputSchema = z.object({ id: z.string() });
55
+ /** Runtime input for one conversation rename operation. */
56
+ export const UpdateConversationOperationInputSchema = z.object({
57
+ id: z.string(),
58
+ data: updateConversationSchema,
59
+ });
60
+ /** Runtime input accepted only from trusted stream callers. */
61
+ export const ChatOperationInputSchema = chatRequestSchema.extend({
62
+ trustedUserId: z.string().optional(),
63
+ }) as unknown as z.ZodType<ChatOperationInput>;
64
+ /** JSON-safe AI SDK message shape accepted at the operation boundary. */
65
+ export type ChatOperationInput = {
66
+ readonly messages: readonly (
67
+ | {
68
+ readonly role: "system" | "user" | "assistant" | "data";
69
+ readonly content: string;
70
+ readonly id?: string;
71
+ }
72
+ | {
73
+ readonly role: "system" | "user" | "assistant" | "data";
74
+ readonly parts: readonly ({
75
+ readonly type: string;
76
+ readonly text?: string;
77
+ } & Record<string, any>)[];
78
+ readonly id?: string;
79
+ readonly metadata?: any;
80
+ }
81
+ )[];
82
+ readonly conversationId?: string;
83
+ readonly model?: string;
84
+ readonly pageContext?: string;
85
+ readonly availableTools?: readonly string[];
86
+ readonly routeName?: string;
87
+ readonly trustedUserId?: string;
88
+ };
89
+ const EmptyInputSchema = z.object({});
90
+
91
+ type ConversationReadFacts = PermissionFactsFor<
92
+ typeof aiChatPermissions.conversation.read
93
+ >;
94
+ type ConversationRecordFacts = PermissionFactsFor<
95
+ typeof aiChatPermissions.conversation.update
96
+ >;
97
+ type StreamStartFacts = PermissionFactsFor<
98
+ typeof aiChatPermissions.stream.start
99
+ >;
100
+
101
+ /** One conversation and its serialized message history. */
102
+ export type AiChatConversationResult = SerializedConversation & {
103
+ readonly messages: readonly SerializedMessage[];
104
+ };
105
+
106
+ /** Complete AI Chat operation inventory shared by every server transport. */
107
+ export type AiChatOperations = {
108
+ readonly startStream: Operation<
109
+ typeof ChatOperationInputSchema,
110
+ typeof aiChatPermissions.stream.start,
111
+ Response,
112
+ true
113
+ >;
114
+ readonly listConversations: Operation<
115
+ typeof EmptyInputSchema,
116
+ typeof aiChatPermissions.conversation.read,
117
+ readonly SerializedConversation[]
118
+ >;
119
+ readonly getConversation: Operation<
120
+ typeof ConversationOperationInputSchema,
121
+ typeof aiChatPermissions.conversation.read,
122
+ AiChatConversationResult
123
+ >;
124
+ readonly createConversation: Operation<
125
+ typeof createConversationSchema,
126
+ typeof aiChatPermissions.conversation.create,
127
+ SerializedConversation
128
+ >;
129
+ readonly updateConversation: Operation<
130
+ typeof UpdateConversationOperationInputSchema,
131
+ typeof aiChatPermissions.conversation.update,
132
+ SerializedConversation
133
+ >;
134
+ readonly deleteConversation: Operation<
135
+ typeof ConversationOperationInputSchema,
136
+ typeof aiChatPermissions.conversation.delete,
137
+ { readonly success: true }
138
+ >;
139
+ };
140
+
141
+ /** Executable inventory used by tests, docs, and future transport audits. */
142
+ export const AI_CHAT_OPERATION_INVENTORY = Object.freeze({
143
+ startStream: Object.freeze({
144
+ http: "POST /chat",
145
+ request: "forRequest(request).operations.aiChat.startStream",
146
+ trusted: "trusted.aiChat.startStream",
147
+ ui: Object.freeze([
148
+ "composer",
149
+ "edit",
150
+ "retry",
151
+ "attachment",
152
+ "tool-result",
153
+ ]),
154
+ semantics: Object.freeze([
155
+ "stream.start",
156
+ "conversation.create",
157
+ "message.send",
158
+ "message.edit",
159
+ "message.retry",
160
+ "attachment.send",
161
+ "tool.activate",
162
+ ]),
163
+ publicSemantics: Object.freeze([
164
+ "stream.start",
165
+ "message.send",
166
+ "message.edit",
167
+ "message.retry",
168
+ "attachment.send",
169
+ "tool.activate",
170
+ ]),
171
+ publicWhenConfigured: true,
172
+ }),
173
+ listConversations: Object.freeze({
174
+ http: "GET /chat/conversations",
175
+ request: "forRequest(request).operations.aiChat.listConversations",
176
+ trusted: "trusted.aiChat.listConversations",
177
+ ui: Object.freeze(["conversation sidebar"]),
178
+ semantics: Object.freeze(["conversation.read"]),
179
+ publicWhenConfigured: false,
180
+ }),
181
+ getConversation: Object.freeze({
182
+ http: "GET /chat/conversations/:id",
183
+ request: "forRequest(request).operations.aiChat.getConversation",
184
+ trusted: "trusted.aiChat.getConversation",
185
+ ui: Object.freeze(["conversation route"]),
186
+ semantics: Object.freeze(["conversation.read"]),
187
+ publicWhenConfigured: false,
188
+ }),
189
+ createConversation: Object.freeze({
190
+ http: "POST /chat/conversations",
191
+ request: "forRequest(request).operations.aiChat.createConversation",
192
+ trusted: "trusted.aiChat.createConversation",
193
+ ui: Object.freeze(["new chat"]),
194
+ semantics: Object.freeze(["conversation.create"]),
195
+ publicWhenConfigured: false,
196
+ }),
197
+ updateConversation: Object.freeze({
198
+ http: "PUT /chat/conversations/:id",
199
+ request: "forRequest(request).operations.aiChat.updateConversation",
200
+ trusted: "trusted.aiChat.updateConversation",
201
+ ui: Object.freeze(["rename conversation"]),
202
+ semantics: Object.freeze(["conversation.update"]),
203
+ publicWhenConfigured: false,
204
+ }),
205
+ deleteConversation: Object.freeze({
206
+ http: "DELETE /chat/conversations/:id",
207
+ request: "forRequest(request).operations.aiChat.deleteConversation",
208
+ trusted: "trusted.aiChat.deleteConversation",
209
+ ui: Object.freeze(["delete conversation"]),
210
+ semantics: Object.freeze(["conversation.delete"]),
211
+ publicWhenConfigured: false,
212
+ }),
213
+ });
214
+
215
+ /** Standalone raw getters that bypass authorization and operation lifecycle hooks. */
216
+ export const AI_CHAT_RAW_ESCAPE_HATCH_INVENTORY = Object.freeze([
217
+ "@btst/stack/plugins/ai-chat/api#getAllConversations",
218
+ "@btst/stack/plugins/ai-chat/api#getConversationById",
219
+ ]);
220
+
221
+ /** A domain/HTTP failure raised after AI Chat authorization succeeds. */
222
+ export class AiChatOperationError extends OperationHttpError {
223
+ constructor(statusCode: number, message: string, code: string) {
224
+ super(statusCode, message, code);
225
+ this.name = "AiChatOperationError";
226
+ }
227
+ }
228
+
229
+ async function runBeforeHook<T>(
230
+ hook: () => T | Promise<T>,
231
+ defaultMessage: string,
232
+ ): Promise<Awaited<T>> {
233
+ try {
234
+ return await hook();
235
+ } catch (cause) {
236
+ if (cause instanceof AiChatOperationError) throw cause;
237
+ throw new AiChatOperationError(
238
+ 403,
239
+ cause instanceof Error ? cause.message : defaultMessage,
240
+ "HOOK_DENIED",
241
+ );
242
+ }
243
+ }
244
+
245
+ /** Typed operation context supplied to AI Chat lifecycle hooks. */
246
+ export interface ChatApiContext<TInput = unknown, TFacts = unknown>
247
+ extends OperationContext<TInput, TFacts> {
248
+ readonly headers?: Headers;
249
+ readonly body?: DeepReadonly<TInput>;
250
+ readonly params?: Readonly<Record<string, string>>;
251
+ readonly query?: DeepReadonly<TInput>;
252
+ }
253
+
254
+ /** Post-authorization AI Chat domain lifecycle hooks. */
255
+ export interface AiChatBackendHooks {
256
+ onBeforeChat?: (
257
+ messages: readonly { readonly role: string; readonly content: string }[],
258
+ context: ChatApiContext<
259
+ z.output<typeof ChatOperationInputSchema>,
260
+ StreamStartFacts
261
+ >,
262
+ ) => Promise<void> | void;
263
+ onBeforeListConversations?: (
264
+ context: ChatApiContext<
265
+ z.output<typeof EmptyInputSchema>,
266
+ ConversationReadFacts
267
+ >,
268
+ ) => Promise<void> | void;
269
+ onBeforeGetConversation?: (
270
+ conversationId: string,
271
+ context: ChatApiContext<
272
+ z.output<typeof ConversationOperationInputSchema>,
273
+ ConversationReadFacts
274
+ >,
275
+ ) => Promise<void> | void;
276
+ onBeforeCreateConversation?: (
277
+ data: DeepReadonly<z.output<typeof createConversationSchema>>,
278
+ context: ChatApiContext<
279
+ z.output<typeof createConversationSchema>,
280
+ undefined
281
+ >,
282
+ ) => Promise<void> | void;
283
+ onBeforeUpdateConversation?: (
284
+ conversationId: string,
285
+ data: DeepReadonly<z.output<typeof updateConversationSchema>>,
286
+ context: ChatApiContext<
287
+ z.output<typeof UpdateConversationOperationInputSchema>,
288
+ ConversationRecordFacts
289
+ >,
290
+ ) => Promise<void> | void;
291
+ onBeforeDeleteConversation?: (
292
+ conversationId: string,
293
+ context: ChatApiContext<
294
+ z.output<typeof ConversationOperationInputSchema>,
295
+ ConversationRecordFacts
296
+ >,
297
+ ) => Promise<void> | void;
298
+ /**
299
+ * Post-authorization tool safety/filter hook. Structural route validation and
300
+ * exact `tool.activate` authorization have already succeeded.
301
+ */
302
+ onBeforeActivateTools?: (
303
+ toolNames: readonly string[],
304
+ routeName: string | undefined,
305
+ context: ChatApiContext<
306
+ z.output<typeof ChatOperationInputSchema>,
307
+ StreamStartFacts
308
+ >,
309
+ ) => Promise<readonly string[]> | readonly string[];
310
+ onAfterChat?: (
311
+ conversationId: string,
312
+ messages: readonly SerializedMessage[],
313
+ context: ChatApiContext<
314
+ z.output<typeof ChatOperationInputSchema>,
315
+ StreamStartFacts
316
+ >,
317
+ ) => Promise<void> | void;
318
+ onAfterListConversations?: (
319
+ conversations: readonly SerializedConversation[],
320
+ context: ChatApiContext<
321
+ z.output<typeof EmptyInputSchema>,
322
+ ConversationReadFacts
323
+ >,
324
+ ) => Promise<void> | void;
325
+ onAfterGetConversation?: (
326
+ conversation: DeepReadonly<AiChatConversationResult>,
327
+ context: ChatApiContext<
328
+ z.output<typeof ConversationOperationInputSchema>,
329
+ ConversationReadFacts
330
+ >,
331
+ ) => Promise<void> | void;
332
+ onAfterCreateConversation?: (
333
+ conversation: DeepReadonly<SerializedConversation>,
334
+ context: ChatApiContext<
335
+ z.output<typeof createConversationSchema>,
336
+ undefined
337
+ >,
338
+ ) => Promise<void> | void;
339
+ onAfterUpdateConversation?: (
340
+ conversation: DeepReadonly<SerializedConversation>,
341
+ context: ChatApiContext<
342
+ z.output<typeof UpdateConversationOperationInputSchema>,
343
+ ConversationRecordFacts
344
+ >,
345
+ ) => Promise<void> | void;
346
+ onAfterDeleteConversation?: (
347
+ conversationId: string,
348
+ context: ChatApiContext<
349
+ z.output<typeof ConversationOperationInputSchema>,
350
+ ConversationRecordFacts
351
+ >,
352
+ ) => Promise<void> | void;
353
+ onErrorChat?: (
354
+ error: Error,
355
+ context: ChatApiContext<
356
+ z.output<typeof ChatOperationInputSchema>,
357
+ StreamStartFacts
358
+ >,
359
+ ) => Promise<void> | void;
360
+ onErrorListConversations?: (
361
+ error: Error,
362
+ context: ChatApiContext<
363
+ z.output<typeof EmptyInputSchema>,
364
+ ConversationReadFacts
365
+ >,
366
+ ) => Promise<void> | void;
367
+ onErrorGetConversation?: (
368
+ error: Error,
369
+ context: ChatApiContext<
370
+ z.output<typeof ConversationOperationInputSchema>,
371
+ ConversationReadFacts
372
+ >,
373
+ ) => Promise<void> | void;
374
+ onErrorCreateConversation?: (
375
+ error: Error,
376
+ context: ChatApiContext<
377
+ z.output<typeof createConversationSchema>,
378
+ undefined
379
+ >,
380
+ ) => Promise<void> | void;
381
+ onErrorUpdateConversation?: (
382
+ error: Error,
383
+ context: ChatApiContext<
384
+ z.output<typeof UpdateConversationOperationInputSchema>,
385
+ ConversationRecordFacts
386
+ >,
387
+ ) => Promise<void> | void;
388
+ onErrorDeleteConversation?: (
389
+ error: Error,
390
+ context: ChatApiContext<
391
+ z.output<typeof ConversationOperationInputSchema>,
392
+ ConversationRecordFacts
393
+ >,
394
+ ) => Promise<void> | void;
395
+ }
396
+
397
+ export interface AiChatOperationsConfig {
398
+ access: AiChatAccess;
399
+ model: LanguageModel;
400
+ systemPrompt?: string;
401
+ tools?: Record<string, Tool>;
402
+ enablePageTools?: boolean;
403
+ clientToolSchemas?: Record<string, Tool>;
404
+ hooks?: AiChatBackendHooks;
405
+ }
406
+
407
+ interface ConversationSnapshot {
408
+ readonly id: string;
409
+ readonly userId?: string;
410
+ readonly title: string;
411
+ readonly createdAt: number;
412
+ readonly updatedAt: number;
413
+ readonly messages: readonly MessageSnapshot[];
414
+ }
415
+
416
+ interface MessageSnapshot {
417
+ readonly id: string;
418
+ readonly conversationId: string;
419
+ readonly role: Message["role"];
420
+ readonly content: string;
421
+ readonly createdAt: number;
422
+ }
423
+
424
+ interface StreamPreparation {
425
+ readonly snapshot: ConversationSnapshot | null;
426
+ readonly intent: StreamStartFacts["intent"];
427
+ readonly messageId?: string;
428
+ readonly mediaTypes: readonly string[];
429
+ readonly authorizationToolNames: readonly string[];
430
+ readonly toolNames: readonly string[];
431
+ }
432
+
433
+ function normalizeError(error: unknown, fallback: string): Error {
434
+ if (error instanceof Error) return error;
435
+ return new Error(typeof error === "string" ? error : fallback, {
436
+ cause: error,
437
+ });
438
+ }
439
+
440
+ function requestFields(request: Request | undefined) {
441
+ return request ? { request, headers: request.headers } : {};
442
+ }
443
+
444
+ function hookContext<TInput, TFacts>(
445
+ context: OperationContext<TInput, TFacts>,
446
+ fields: {
447
+ body?: DeepReadonly<TInput>;
448
+ params?: Readonly<Record<string, string>>;
449
+ query?: DeepReadonly<TInput>;
450
+ } = {},
451
+ ): ChatApiContext<TInput, TFacts> {
452
+ return Object.freeze({
453
+ ...context,
454
+ ...requestFields(context.request),
455
+ ...fields,
456
+ });
457
+ }
458
+
459
+ async function notifyError<TInput, TFacts>(
460
+ hook:
461
+ | ((
462
+ error: Error,
463
+ context: ChatApiContext<TInput, TFacts>,
464
+ ) => Promise<void> | void)
465
+ | undefined,
466
+ error: unknown,
467
+ context: OperationContext<TInput, TFacts>,
468
+ fields?: {
469
+ body?: DeepReadonly<TInput>;
470
+ params?: Readonly<Record<string, string>>;
471
+ query?: DeepReadonly<TInput>;
472
+ },
473
+ ) {
474
+ await hook?.(
475
+ normalizeError(error, "AI Chat operation failed"),
476
+ hookContext(context, fields),
477
+ );
478
+ }
479
+
480
+ function publicConversation(
481
+ conversation: Conversation,
482
+ ): SerializedConversation {
483
+ // `userId` is the minimum rendered owner hint needed by browser permission
484
+ // gates. The server always reloads the authoritative owner before enforcement.
485
+ return serializeConversation(conversation);
486
+ }
487
+
488
+ function conversationResult(
489
+ conversation: Conversation & { messages: Message[] },
490
+ ): AiChatConversationResult {
491
+ return {
492
+ ...publicConversation(conversation),
493
+ messages: conversation.messages.map(serializeMessage),
494
+ };
495
+ }
496
+
497
+ function snapshotConversation(
498
+ conversation: Conversation & { messages?: Message[] },
499
+ ): ConversationSnapshot {
500
+ return {
501
+ id: conversation.id,
502
+ ...(conversation.userId ? { userId: conversation.userId } : {}),
503
+ title: conversation.title,
504
+ createdAt: conversation.createdAt.getTime(),
505
+ updatedAt: conversation.updatedAt.getTime(),
506
+ messages: (conversation.messages ?? []).map((message) => ({
507
+ id: message.id,
508
+ conversationId: message.conversationId,
509
+ role: message.role,
510
+ content: message.content,
511
+ createdAt: message.createdAt.getTime(),
512
+ })),
513
+ };
514
+ }
515
+
516
+ function sameSnapshot(
517
+ conversation: (Conversation & { messages: Message[] }) | null,
518
+ expected: ConversationSnapshot | null,
519
+ ) {
520
+ if (!conversation || !expected)
521
+ return conversation === null && expected === null;
522
+ return (
523
+ JSON.stringify(snapshotConversation(conversation)) ===
524
+ JSON.stringify(expected)
525
+ );
526
+ }
527
+
528
+ function recordFacts(
529
+ id: string,
530
+ snapshot: ConversationSnapshot | null,
531
+ ): ConversationRecordFacts {
532
+ return {
533
+ conversationId: id,
534
+ exists: snapshot !== null,
535
+ ...(snapshot?.userId ? { ownerId: snapshot.userId } : {}),
536
+ };
537
+ }
538
+
539
+ function textContent(message: UIMessage): string {
540
+ return (message.parts ?? [])
541
+ .filter(
542
+ (part): part is Extract<UIMessage["parts"][number], { type: "text" }> =>
543
+ part.type === "text",
544
+ )
545
+ .map((part) => part.text)
546
+ .join("");
547
+ }
548
+
549
+ function serializedParts(message: UIMessage): string {
550
+ return JSON.stringify(
551
+ (message.parts ?? []).filter(
552
+ (part) => part.type === "text" || part.type === "file",
553
+ ),
554
+ );
555
+ }
556
+
557
+ function matchesPersistedUserMessage(
558
+ message: UIMessage,
559
+ persisted: MessageSnapshot,
560
+ ) {
561
+ if (persisted.content === serializedParts(message)) return true;
562
+ const parts = message.parts ?? [];
563
+ return (
564
+ parts.length === 1 &&
565
+ parts[0]?.type === "text" &&
566
+ persisted.content === parts[0].text
567
+ );
568
+ }
569
+
570
+ function fileParts(messages: readonly UIMessage[]) {
571
+ return messages.flatMap((message) =>
572
+ (message.parts ?? []).filter(
573
+ (part): part is Extract<UIMessage["parts"][number], { type: "file" }> =>
574
+ part.type === "file",
575
+ ),
576
+ );
577
+ }
578
+
579
+ function completedToolNames(message: UIMessage | undefined) {
580
+ if (!message) return [];
581
+ return [
582
+ ...new Set(
583
+ (message.parts ?? []).flatMap((part) => {
584
+ if (
585
+ !("state" in part) ||
586
+ (part.state !== "output-available" && part.state !== "output-error")
587
+ ) {
588
+ return [];
589
+ }
590
+ if (part.type === "dynamic-tool" && "toolName" in part) {
591
+ return typeof part.toolName === "string" ? [part.toolName] : [];
592
+ }
593
+ return part.type.startsWith("tool-") ? [part.type.slice(5)] : [];
594
+ }),
595
+ ),
596
+ ];
597
+ }
598
+
599
+ function validateAttachments(messages: readonly UIMessage[]) {
600
+ const files = fileParts(messages);
601
+ if (files.length > 10) {
602
+ throw new AiChatOperationError(
603
+ 400,
604
+ "A chat request may include at most 10 attachments.",
605
+ "TOO_MANY_ATTACHMENTS",
606
+ );
607
+ }
608
+ for (const file of files) {
609
+ if (
610
+ typeof file.url !== "string" ||
611
+ (!file.url.startsWith("https://") &&
612
+ !file.url.startsWith("http://") &&
613
+ !file.url.startsWith("data:"))
614
+ ) {
615
+ throw new AiChatOperationError(
616
+ 400,
617
+ "Attachment URLs must use http, https, or data URLs.",
618
+ "INVALID_ATTACHMENT_URL",
619
+ );
620
+ }
621
+ if (file.url.startsWith("data:") && file.url.length > 14_000_000) {
622
+ throw new AiChatOperationError(
623
+ 413,
624
+ "Inline attachments must not exceed 10 MB.",
625
+ "ATTACHMENT_TOO_LARGE",
626
+ );
627
+ }
628
+ }
629
+ }
630
+
631
+ function structuralToolNames(
632
+ input: DeepReadonly<z.output<typeof ChatOperationInputSchema>>,
633
+ config: AiChatOperationsConfig,
634
+ ) {
635
+ if (!config.enablePageTools || !input.availableTools?.length) return [];
636
+ const consumerSchemas = config.clientToolSchemas ?? {};
637
+ return [...new Set(input.availableTools)].filter((name) => {
638
+ if (name in BUILT_IN_PAGE_TOOL_SCHEMAS) {
639
+ const allowlist = BUILT_IN_PAGE_TOOL_ROUTE_ALLOWLIST[name];
640
+ return Boolean(
641
+ allowlist && input.routeName && allowlist.includes(input.routeName),
642
+ );
643
+ }
644
+ return name in consumerSchemas;
645
+ });
646
+ }
647
+
648
+ function buildTools(names: readonly string[], config: AiChatOperationsConfig) {
649
+ const pageTools = Object.fromEntries(
650
+ names.map((name) => [
651
+ name,
652
+ BUILT_IN_PAGE_TOOL_SCHEMAS[name] ?? config.clientToolSchemas?.[name],
653
+ ]),
654
+ ) as Record<string, Tool>;
655
+ return Object.keys(pageTools).length > 0
656
+ ? { ...pageTools, ...config.tools }
657
+ : config.tools;
658
+ }
659
+
660
+ function determineIntent(
661
+ messages: readonly UIMessage[],
662
+ snapshot: ConversationSnapshot | null,
663
+ ): { intent: StreamStartFacts["intent"]; messageId?: string } {
664
+ const last = messages[messages.length - 1];
665
+ if (!last) return { intent: "send" };
666
+ if (last.role !== "user" && last.role !== "assistant") {
667
+ throw new AiChatOperationError(
668
+ 400,
669
+ "A chat request must end with a user or assistant message.",
670
+ "INVALID_MESSAGE_SEQUENCE",
671
+ );
672
+ }
673
+ if (!snapshot) return { intent: "send" };
674
+ const incomingUsers = messages.filter((message) => message.role === "user");
675
+ const persistedUsers = snapshot.messages.filter(
676
+ (message) => message.role === "user",
677
+ );
678
+ const sharedUserCount = Math.min(incomingUsers.length, persistedUsers.length);
679
+ for (let index = 0; index < sharedUserCount; index++) {
680
+ const incoming = incomingUsers[index];
681
+ const persisted = persistedUsers[index];
682
+ if (!incoming || !persisted) continue;
683
+ const matches = matchesPersistedUserMessage(incoming, persisted);
684
+ if (matches) continue;
685
+ if (
686
+ last.role === "user" &&
687
+ incoming === last &&
688
+ index === incomingUsers.length - 1
689
+ ) {
690
+ return { intent: "edit", messageId: persisted.id };
691
+ }
692
+ throw new AiChatOperationError(
693
+ 409,
694
+ "The conversation transcript changed before authorization.",
695
+ "STALE_MESSAGE",
696
+ );
697
+ }
698
+ if (incomingUsers.length > persistedUsers.length) {
699
+ if (
700
+ incomingUsers.length === persistedUsers.length + 1 &&
701
+ incomingUsers[incomingUsers.length - 1] === last
702
+ ) {
703
+ return { intent: "send" };
704
+ }
705
+ throw new AiChatOperationError(
706
+ 409,
707
+ "The conversation transcript changed before authorization.",
708
+ "STALE_MESSAGE",
709
+ );
710
+ }
711
+ const isToolResult =
712
+ last.role === "assistant" && completedToolNames(last).length > 0;
713
+ if (isToolResult && incomingUsers.length !== persistedUsers.length) {
714
+ throw new AiChatOperationError(
715
+ 409,
716
+ "The tool continuation no longer follows the latest user message.",
717
+ "STALE_MESSAGE",
718
+ );
719
+ }
720
+ const target = persistedUsers[incomingUsers.length - 1];
721
+ if (!target) {
722
+ throw new AiChatOperationError(
723
+ 400,
724
+ "Retry requires a persisted message.",
725
+ "MESSAGE_NOT_FOUND",
726
+ );
727
+ }
728
+ return {
729
+ intent: isToolResult ? "tool-result" : "retry",
730
+ messageId: target.id,
731
+ };
732
+ }
733
+
734
+ function nextVersion(date: Date) {
735
+ return new Date(Math.max(Date.now(), date.getTime() + 1));
736
+ }
737
+
738
+ const AFFECTED_ROW_KEYS = [
739
+ "rowCount",
740
+ "affectedRows",
741
+ "rowsAffected",
742
+ "changes",
743
+ "numUpdatedRows",
744
+ ] as const;
745
+
746
+ function hasPositiveCount(value: unknown): boolean {
747
+ if (typeof value === "number") return Number.isFinite(value) && value > 0;
748
+ if (typeof value === "bigint") return value > 0n;
749
+ return false;
750
+ }
751
+
752
+ /** Normalize conditional-update results across the supported adapters. */
753
+ function didAffectRow(result: unknown, expectedId: string): boolean {
754
+ if (typeof result === "number" || typeof result === "bigint") {
755
+ return hasPositiveCount(result);
756
+ }
757
+ if (!result || typeof result !== "object") return false;
758
+ const record = result as Record<string, unknown>;
759
+ if ("count" in record) return hasPositiveCount(record.count);
760
+ if (Array.isArray(result)) {
761
+ return result.length > 0 && didAffectRow(result[0], expectedId);
762
+ }
763
+ for (const key of AFFECTED_ROW_KEYS) {
764
+ if (key in record) return hasPositiveCount(record[key]);
765
+ }
766
+ if ("meta" in record) {
767
+ const meta = record.meta;
768
+ return Boolean(
769
+ meta &&
770
+ typeof meta === "object" &&
771
+ "changes" in meta &&
772
+ hasPositiveCount((meta as Record<string, unknown>).changes),
773
+ );
774
+ }
775
+ return record.id === expectedId;
776
+ }
777
+
778
+ const memoryRollbackMarkers = new WeakMap<Adapter, (error: unknown) => void>();
779
+
780
+ function markMemoryRollback(adapter: Adapter, error: unknown) {
781
+ memoryRollbackMarkers.get(adapter)?.(error);
782
+ }
783
+
784
+ /**
785
+ * The published memory adapter rolls transactions back from a whole-database
786
+ * clone. Serialize every access to the shared adapter so a rejected AI Chat
787
+ * transaction cannot erase a concurrent operation from this or another plugin.
788
+ */
789
+ function serializeMemoryOperations(adapter: Adapter): Adapter {
790
+ if (adapter.id !== "memory" || memoryRollbackMarkers.has(adapter)) {
791
+ return adapter;
792
+ }
793
+ const source: Adapter = { ...adapter };
794
+ const lockContext = new AsyncLocalStorage<MemoryHistoryLockContext>();
795
+ let tail = Promise.resolve();
796
+ let activeOwner: object | undefined;
797
+ const withLock = async <T>(
798
+ run: (activeAdapter: ActiveAdapter) => Promise<T>,
799
+ ): Promise<T> => {
800
+ const inherited = lockContext.getStore();
801
+ if (inherited && inherited.owner === activeOwner) {
802
+ return run(inherited.adapter);
803
+ }
804
+ let release = () => {};
805
+ const previous = tail;
806
+ tail = new Promise<void>((resolve) => {
807
+ release = resolve;
808
+ });
809
+ await previous;
810
+ const owner = {};
811
+ activeOwner = owner;
812
+ try {
813
+ return await lockContext.run({ owner, adapter: source }, () =>
814
+ run(source),
815
+ );
816
+ } finally {
817
+ if (activeOwner === owner) activeOwner = undefined;
818
+ release();
819
+ }
820
+ };
821
+ const serialized: Adapter = {
822
+ ...source,
823
+ create: ((input) =>
824
+ withLock((active) => active.create(input))) as Adapter["create"],
825
+ findOne: ((input) =>
826
+ withLock((active) => active.findOne(input))) as Adapter["findOne"],
827
+ findMany: ((input) =>
828
+ withLock((active) => active.findMany(input))) as Adapter["findMany"],
829
+ count: (input) => withLock((active) => active.count(input)),
830
+ update: ((input) =>
831
+ withLock((active) => active.update(input))) as Adapter["update"],
832
+ updateMany: (input) => withLock((active) => active.updateMany(input)),
833
+ delete: ((input) =>
834
+ withLock((active) => active.delete(input))) as Adapter["delete"],
835
+ deleteMany: (input) => withLock((active) => active.deleteMany(input)),
836
+ consumeOne: ((input) =>
837
+ withLock((active) => active.consumeOne(input))) as Adapter["consumeOne"],
838
+ transaction: ((callback) =>
839
+ withLock((active) => {
840
+ const context = lockContext.getStore();
841
+ if (!context)
842
+ throw new TypeError("Missing AI Chat memory lock context.");
843
+ if (context.inTransaction) {
844
+ return callback(active as TransactionAdapter).catch((error) => {
845
+ context.rollbackOnly = true;
846
+ context.rollbackError = error;
847
+ throw error;
848
+ });
849
+ }
850
+ if (!active.transaction) {
851
+ throw new TypeError("Missing AI Chat memory transaction adapter.");
852
+ }
853
+ return active.transaction((transaction) =>
854
+ lockContext.run(
855
+ {
856
+ owner: context.owner,
857
+ adapter: transaction,
858
+ inTransaction: true,
859
+ },
860
+ async () => {
861
+ const transactionContext = lockContext.getStore();
862
+ const result = await callback(transaction);
863
+ if (transactionContext?.rollbackOnly) {
864
+ throw transactionContext.rollbackError;
865
+ }
866
+ return result;
867
+ },
868
+ ),
869
+ );
870
+ })) as Adapter["transaction"],
871
+ };
872
+ Object.assign(adapter, serialized);
873
+ memoryRollbackMarkers.set(adapter, (error) => {
874
+ const context = lockContext.getStore();
875
+ if (!context || context.owner !== activeOwner || !context.inTransaction) {
876
+ return;
877
+ }
878
+ context.rollbackOnly = true;
879
+ context.rollbackError = error;
880
+ });
881
+ return adapter;
882
+ }
883
+
884
+ function requireAtomicConversationTransactions(adapter: Adapter) {
885
+ if (
886
+ adapter.id !== "memory" &&
887
+ typeof adapter.options?.adapterConfig.transaction !== "function"
888
+ ) {
889
+ throw new AiChatOperationError(
890
+ 500,
891
+ "AI Chat conversation writes require an adapter with isolated transaction support.",
892
+ "ATOMIC_TRANSACTION_REQUIRED",
893
+ );
894
+ }
895
+ }
896
+
897
+ async function scopedUserId(
898
+ context: OperationContext<any, any>,
899
+ input: object,
900
+ ) {
901
+ if (context.identity) return context.identity.id;
902
+ const trustedUserId = (input as { trustedUserId?: string }).trustedUserId;
903
+ if (!context.request && trustedUserId) return trustedUserId;
904
+ return undefined;
905
+ }
906
+
907
+ function assertConversationScope(
908
+ snapshot: ConversationSnapshot | null,
909
+ userId: string | undefined,
910
+ message: string,
911
+ ) {
912
+ if (userId && snapshot?.userId && snapshot.userId !== userId) {
913
+ throw new AiChatOperationError(403, message, "FORBIDDEN");
914
+ }
915
+ }
916
+
917
+ /** Build all AI Chat operations once for HTTP, request, and trusted execution. */
918
+ export function createAiChatOperations(
919
+ sourceAdapter: Adapter,
920
+ config: AiChatOperationsConfig,
921
+ ): AiChatOperations {
922
+ const adapter = serializeMemoryOperations(sourceAdapter);
923
+ const hooks = config.hooks;
924
+ const conversationSnapshots = new WeakMap<
925
+ object,
926
+ ConversationSnapshot | null
927
+ >();
928
+ const streamPreparations = new WeakMap<object, StreamPreparation>();
929
+ const scopedUserIds = new WeakMap<object, string | undefined>();
930
+ const pendingRequestedConversationClaims = new Set<string>();
931
+ const pendingConversationMutationClaims = new Set<string>();
932
+ const claimConversationMutation = (conversationId: string) => {
933
+ requireAtomicConversationTransactions(adapter);
934
+ if (pendingConversationMutationClaims.has(conversationId)) {
935
+ throw new AiChatOperationError(
936
+ 409,
937
+ "Conversation changed during authorization.",
938
+ "STALE_CONVERSATION",
939
+ );
940
+ }
941
+ pendingConversationMutationClaims.add(conversationId);
942
+ return () => pendingConversationMutationClaims.delete(conversationId);
943
+ };
944
+ const assertHistoryAvailable = () => {
945
+ if (config.access === "public") {
946
+ throw new AiChatOperationError(
947
+ 404,
948
+ "Conversations are not available in public mode.",
949
+ "HISTORY_UNAVAILABLE",
950
+ );
951
+ }
952
+ };
953
+
954
+ const listConversations = defineOperation({
955
+ input: EmptyInputSchema,
956
+ permission: aiChatPermissions.conversation.read,
957
+ facts: () => {
958
+ assertHistoryAvailable();
959
+ return { scope: "collection" as const };
960
+ },
961
+ before: async (context) => {
962
+ const userId = await scopedUserId(context, context.input);
963
+ scopedUserIds.set(context.input as object, userId);
964
+ await runBeforeHook(
965
+ () =>
966
+ hooks?.onBeforeListConversations?.(
967
+ hookContext(context, { query: context.input }),
968
+ ),
969
+ "Unauthorized: Cannot list conversations",
970
+ );
971
+ },
972
+ execute: async (context) => {
973
+ const userId = scopedUserIds.get(context.input as object);
974
+ const allConversations = await getAllConversations(adapter, userId);
975
+ const conversations = (
976
+ context.request && !userId
977
+ ? allConversations.filter((conversation) => !conversation.userId)
978
+ : allConversations
979
+ ).map(publicConversation);
980
+ await hooks?.onAfterListConversations?.(
981
+ conversations,
982
+ hookContext(context, { query: context.input }),
983
+ );
984
+ return conversations;
985
+ },
986
+ onError: ({ error, ...context }) =>
987
+ notifyError(hooks?.onErrorListConversations, error, context, {
988
+ query: context.input,
989
+ }),
990
+ });
991
+
992
+ const getConversation = defineOperation({
993
+ input: ConversationOperationInputSchema,
994
+ permission: aiChatPermissions.conversation.read,
995
+ facts: async ({ input }) => {
996
+ assertHistoryAvailable();
997
+ const conversation = await getConversationById(adapter, input.id);
998
+ const snapshot = conversation ? snapshotConversation(conversation) : null;
999
+ conversationSnapshots.set(input as object, snapshot);
1000
+ return {
1001
+ scope: "record" as const,
1002
+ ...recordFacts(input.id, snapshot),
1003
+ };
1004
+ },
1005
+ before: async (context) => {
1006
+ const userId = await scopedUserId(context, context.input);
1007
+ assertConversationScope(
1008
+ conversationSnapshots.get(context.input as object) ?? null,
1009
+ context.identity ? undefined : userId,
1010
+ "Unauthorized: Cannot access this conversation",
1011
+ );
1012
+ const current = await getConversationById(adapter, context.input.id);
1013
+ if (
1014
+ !sameSnapshot(
1015
+ current,
1016
+ conversationSnapshots.get(context.input as object) ?? null,
1017
+ )
1018
+ ) {
1019
+ throw new AiChatOperationError(
1020
+ 409,
1021
+ "Conversation changed during authorization.",
1022
+ "STALE_CONVERSATION",
1023
+ );
1024
+ }
1025
+ await runBeforeHook(
1026
+ () =>
1027
+ hooks?.onBeforeGetConversation?.(
1028
+ context.input.id,
1029
+ hookContext(context, { params: { id: context.input.id } }),
1030
+ ),
1031
+ "Unauthorized: Cannot get conversation",
1032
+ );
1033
+ },
1034
+ execute: async (context) => {
1035
+ const conversation = await getConversationById(adapter, context.input.id);
1036
+ if (!conversation) {
1037
+ throw new AiChatOperationError(
1038
+ 404,
1039
+ "Conversation not found.",
1040
+ "CONVERSATION_NOT_FOUND",
1041
+ );
1042
+ }
1043
+ if (
1044
+ !sameSnapshot(
1045
+ conversation,
1046
+ conversationSnapshots.get(context.input as object) ?? null,
1047
+ )
1048
+ ) {
1049
+ throw new AiChatOperationError(
1050
+ 409,
1051
+ "Conversation changed during authorization.",
1052
+ "STALE_CONVERSATION",
1053
+ );
1054
+ }
1055
+ const result = conversationResult(conversation);
1056
+ await hooks?.onAfterGetConversation?.(
1057
+ result,
1058
+ hookContext(context, { params: { id: context.input.id } }),
1059
+ );
1060
+ return result;
1061
+ },
1062
+ onError: ({ error, ...context }) =>
1063
+ notifyError(hooks?.onErrorGetConversation, error, context, {
1064
+ params: { id: context.input.id },
1065
+ }),
1066
+ });
1067
+
1068
+ const createConversation = defineOperation({
1069
+ input: createConversationSchema,
1070
+ permission: aiChatPermissions.conversation.create,
1071
+ facts: () => {
1072
+ assertHistoryAvailable();
1073
+ return undefined;
1074
+ },
1075
+ before: async (context) => {
1076
+ const userId = await scopedUserId(context, context.input);
1077
+ scopedUserIds.set(context.input as object, userId);
1078
+ await runBeforeHook(
1079
+ () =>
1080
+ hooks?.onBeforeCreateConversation?.(
1081
+ context.input,
1082
+ hookContext(context, { body: context.input }),
1083
+ ),
1084
+ "Unauthorized: Cannot create conversation",
1085
+ );
1086
+ },
1087
+ execute: async (context) => {
1088
+ const userId = scopedUserIds.get(context.input as object);
1089
+ const now = new Date();
1090
+ const conversation = await adapter.create<Conversation>({
1091
+ model: "conversation",
1092
+ forceAllowId: Boolean(context.input.id),
1093
+ data: {
1094
+ ...(context.input.id ? { id: context.input.id } : {}),
1095
+ ...(userId ? { userId } : {}),
1096
+ title: context.input.title || "New Conversation",
1097
+ createdAt: now,
1098
+ updatedAt: now,
1099
+ } as Conversation,
1100
+ });
1101
+ const result = publicConversation(conversation);
1102
+ await hooks?.onAfterCreateConversation?.(
1103
+ result,
1104
+ hookContext(context, { body: context.input }),
1105
+ );
1106
+ return result;
1107
+ },
1108
+ onError: ({ error, ...context }) => {
1109
+ markMemoryRollback(adapter, error);
1110
+ return notifyError(hooks?.onErrorCreateConversation, error, context, {
1111
+ body: context.input,
1112
+ });
1113
+ },
1114
+ });
1115
+
1116
+ const updateConversation = defineOperation({
1117
+ input: UpdateConversationOperationInputSchema,
1118
+ permission: aiChatPermissions.conversation.update,
1119
+ facts: async ({ input }) => {
1120
+ assertHistoryAvailable();
1121
+ const conversation = await getConversationById(adapter, input.id);
1122
+ const snapshot = conversation ? snapshotConversation(conversation) : null;
1123
+ conversationSnapshots.set(input as object, snapshot);
1124
+ return recordFacts(input.id, snapshot);
1125
+ },
1126
+ execute: async (context) => {
1127
+ const expected =
1128
+ conversationSnapshots.get(context.input as object) ?? null;
1129
+ if (!expected) {
1130
+ throw new AiChatOperationError(
1131
+ 404,
1132
+ "Conversation not found.",
1133
+ "CONVERSATION_NOT_FOUND",
1134
+ );
1135
+ }
1136
+ const userId = await scopedUserId(context, context.input);
1137
+ assertConversationScope(
1138
+ expected,
1139
+ context.identity ? undefined : userId,
1140
+ "Unauthorized: Cannot update this conversation",
1141
+ );
1142
+ const releaseMutation = claimConversationMutation(expected.id);
1143
+ try {
1144
+ return await adapter.transaction(async (tx) => {
1145
+ const current = await getConversationById(tx, context.input.id);
1146
+ if (!sameSnapshot(current, expected)) {
1147
+ throw new AiChatOperationError(
1148
+ 409,
1149
+ "Conversation changed during authorization.",
1150
+ "STALE_CONVERSATION",
1151
+ );
1152
+ }
1153
+ await runBeforeHook(
1154
+ () =>
1155
+ hooks?.onBeforeUpdateConversation?.(
1156
+ context.input.id,
1157
+ context.input.data,
1158
+ hookContext(context, {
1159
+ body: context.input,
1160
+ params: { id: context.input.id },
1161
+ }),
1162
+ ),
1163
+ "Unauthorized: Cannot update conversation",
1164
+ );
1165
+ const updatedAt = nextVersion(new Date(expected.updatedAt));
1166
+ const matched = await tx.updateMany({
1167
+ model: "conversation",
1168
+ where: [
1169
+ {
1170
+ field: "id",
1171
+ value: expected.id,
1172
+ operator: "eq" as const,
1173
+ },
1174
+ {
1175
+ field: "updatedAt",
1176
+ value: new Date(expected.updatedAt),
1177
+ operator: "gte" as const,
1178
+ },
1179
+ {
1180
+ field: "updatedAt",
1181
+ value: new Date(expected.updatedAt),
1182
+ operator: "lte" as const,
1183
+ },
1184
+ ],
1185
+ update: { title: context.input.data.title, updatedAt },
1186
+ });
1187
+ if (!didAffectRow(matched, expected.id)) {
1188
+ throw new AiChatOperationError(
1189
+ 409,
1190
+ "Conversation changed during authorization.",
1191
+ "STALE_CONVERSATION",
1192
+ );
1193
+ }
1194
+ const updated = await tx.findOne<Conversation>({
1195
+ model: "conversation",
1196
+ where: [{ field: "id", value: expected.id }],
1197
+ });
1198
+ if (!updated) {
1199
+ throw new AiChatOperationError(
1200
+ 404,
1201
+ "Conversation not found.",
1202
+ "CONVERSATION_NOT_FOUND",
1203
+ );
1204
+ }
1205
+ return publicConversation(updated);
1206
+ });
1207
+ } finally {
1208
+ releaseMutation();
1209
+ }
1210
+ },
1211
+ after: (context) =>
1212
+ hooks?.onAfterUpdateConversation?.(
1213
+ context.result,
1214
+ hookContext(context, {
1215
+ body: context.input,
1216
+ params: { id: context.input.id },
1217
+ }),
1218
+ ),
1219
+ onError: ({ error, ...context }) => {
1220
+ markMemoryRollback(adapter, error);
1221
+ return notifyError(hooks?.onErrorUpdateConversation, error, context, {
1222
+ body: context.input,
1223
+ params: { id: context.input.id },
1224
+ });
1225
+ },
1226
+ });
1227
+
1228
+ const deleteConversation = defineOperation({
1229
+ input: ConversationOperationInputSchema,
1230
+ permission: aiChatPermissions.conversation.delete,
1231
+ facts: async ({ input }) => {
1232
+ assertHistoryAvailable();
1233
+ const conversation = await getConversationById(adapter, input.id);
1234
+ const snapshot = conversation ? snapshotConversation(conversation) : null;
1235
+ conversationSnapshots.set(input as object, snapshot);
1236
+ return recordFacts(input.id, snapshot);
1237
+ },
1238
+ execute: async (context) => {
1239
+ const expected =
1240
+ conversationSnapshots.get(context.input as object) ?? null;
1241
+ if (!expected) {
1242
+ throw new AiChatOperationError(
1243
+ 404,
1244
+ "Conversation not found.",
1245
+ "CONVERSATION_NOT_FOUND",
1246
+ );
1247
+ }
1248
+ const userId = await scopedUserId(context, context.input);
1249
+ assertConversationScope(
1250
+ expected,
1251
+ context.identity ? undefined : userId,
1252
+ "Unauthorized: Cannot delete this conversation",
1253
+ );
1254
+ const releaseMutation = claimConversationMutation(expected.id);
1255
+ try {
1256
+ return await adapter.transaction(async (tx) => {
1257
+ const current = await getConversationById(tx, context.input.id);
1258
+ if (!sameSnapshot(current, expected)) {
1259
+ throw new AiChatOperationError(
1260
+ 409,
1261
+ "Conversation changed during authorization.",
1262
+ "STALE_CONVERSATION",
1263
+ );
1264
+ }
1265
+ await runBeforeHook(
1266
+ () =>
1267
+ hooks?.onBeforeDeleteConversation?.(
1268
+ context.input.id,
1269
+ hookContext(context, {
1270
+ params: { id: context.input.id },
1271
+ }),
1272
+ ),
1273
+ "Unauthorized: Cannot delete conversation",
1274
+ );
1275
+ const deleted = await tx.deleteMany({
1276
+ model: "conversation",
1277
+ where: [
1278
+ {
1279
+ field: "id",
1280
+ value: expected.id,
1281
+ operator: "eq" as const,
1282
+ },
1283
+ {
1284
+ field: "updatedAt",
1285
+ value: new Date(expected.updatedAt),
1286
+ operator: "gte" as const,
1287
+ },
1288
+ {
1289
+ field: "updatedAt",
1290
+ value: new Date(expected.updatedAt),
1291
+ operator: "lte" as const,
1292
+ },
1293
+ ],
1294
+ });
1295
+ if (!didAffectRow(deleted, expected.id)) {
1296
+ throw new AiChatOperationError(
1297
+ 409,
1298
+ "Conversation changed during authorization.",
1299
+ "STALE_CONVERSATION",
1300
+ );
1301
+ }
1302
+ return { success: true as const };
1303
+ });
1304
+ } finally {
1305
+ releaseMutation();
1306
+ }
1307
+ },
1308
+ after: (context) =>
1309
+ hooks?.onAfterDeleteConversation?.(
1310
+ context.input.id,
1311
+ hookContext(context, { params: { id: context.input.id } }),
1312
+ ),
1313
+ onError: ({ error, ...context }) => {
1314
+ markMemoryRollback(adapter, error);
1315
+ return notifyError(hooks?.onErrorDeleteConversation, error, context, {
1316
+ params: { id: context.input.id },
1317
+ });
1318
+ },
1319
+ });
1320
+
1321
+ const startStream = definePassthroughOperation({
1322
+ input: ChatOperationInputSchema,
1323
+ permission: aiChatPermissions.stream.start,
1324
+ access: config.access,
1325
+ facts: async ({ input }) => {
1326
+ const uiMessages = input.messages as UIMessage[];
1327
+ if (!uiMessages[0]) {
1328
+ throw new AiChatOperationError(
1329
+ 400,
1330
+ "At least one message is required.",
1331
+ "EMPTY_CHAT",
1332
+ );
1333
+ }
1334
+ validateAttachments(uiMessages);
1335
+ const conversation =
1336
+ config.access === "authorized" && input.conversationId
1337
+ ? await getConversationById(adapter, input.conversationId)
1338
+ : null;
1339
+ const snapshot = conversation ? snapshotConversation(conversation) : null;
1340
+ const intent = determineIntent(uiMessages, snapshot);
1341
+ const mediaTypes = fileParts(uiMessages).map((file) => file.mediaType);
1342
+ const toolNames = structuralToolNames(input, config);
1343
+ const toolResultNames = completedToolNames(
1344
+ uiMessages[uiMessages.length - 1],
1345
+ );
1346
+ const availableToolNames = new Set([
1347
+ ...toolNames,
1348
+ ...Object.keys(config.tools ?? {}),
1349
+ ]);
1350
+ if (toolResultNames.some((name) => !availableToolNames.has(name))) {
1351
+ throw new AiChatOperationError(
1352
+ 400,
1353
+ "Tool results must match a server-enabled tool.",
1354
+ "INVALID_TOOL_RESULT",
1355
+ );
1356
+ }
1357
+ streamPreparations.set(input as object, {
1358
+ snapshot,
1359
+ ...intent,
1360
+ mediaTypes,
1361
+ authorizationToolNames: [...availableToolNames],
1362
+ toolNames,
1363
+ });
1364
+ return {
1365
+ ...(input.conversationId
1366
+ ? { conversationId: input.conversationId }
1367
+ : {}),
1368
+ ...(snapshot?.userId ? { ownerId: snapshot.userId } : {}),
1369
+ createsConversation: snapshot === null,
1370
+ intent: intent.intent,
1371
+ };
1372
+ },
1373
+ additionalPermissions: ({ input, facts }) => {
1374
+ const prepared = streamPreparations.get(input as object);
1375
+ if (!prepared) {
1376
+ throw new AiChatOperationError(
1377
+ 500,
1378
+ "Stream authorization context is unavailable.",
1379
+ "AUTHORIZATION_SNAPSHOT_MISSING",
1380
+ );
1381
+ }
1382
+ const requests = [];
1383
+ if (config.access === "authorized" && !prepared.snapshot) {
1384
+ requests.push(aiChatPermissions.conversation.create());
1385
+ }
1386
+ const base = {
1387
+ ...(facts.conversationId
1388
+ ? { conversationId: facts.conversationId }
1389
+ : {}),
1390
+ ...(facts.ownerId ? { ownerId: facts.ownerId } : {}),
1391
+ };
1392
+ if (prepared.intent === "send") {
1393
+ requests.push(
1394
+ aiChatPermissions.message.send({
1395
+ ...base,
1396
+ createsConversation: !prepared.snapshot,
1397
+ }),
1398
+ );
1399
+ } else if (prepared.intent === "edit" && facts.conversationId) {
1400
+ if (!prepared.messageId) {
1401
+ throw new AiChatOperationError(
1402
+ 500,
1403
+ "Edit authorization message is unavailable.",
1404
+ "AUTHORIZATION_SNAPSHOT_MISSING",
1405
+ );
1406
+ }
1407
+ requests.push(
1408
+ aiChatPermissions.message.edit({
1409
+ conversationId: facts.conversationId,
1410
+ messageId: prepared.messageId,
1411
+ ...(facts.ownerId ? { ownerId: facts.ownerId } : {}),
1412
+ }),
1413
+ );
1414
+ } else if (prepared.intent === "retry" && facts.conversationId) {
1415
+ if (!prepared.messageId) {
1416
+ throw new AiChatOperationError(
1417
+ 500,
1418
+ "Retry authorization message is unavailable.",
1419
+ "AUTHORIZATION_SNAPSHOT_MISSING",
1420
+ );
1421
+ }
1422
+ requests.push(
1423
+ aiChatPermissions.message.retry({
1424
+ conversationId: facts.conversationId,
1425
+ messageId: prepared.messageId,
1426
+ ...(facts.ownerId ? { ownerId: facts.ownerId } : {}),
1427
+ }),
1428
+ );
1429
+ } else if (prepared.intent === "tool-result") {
1430
+ requests.push(
1431
+ aiChatPermissions.message.send({
1432
+ ...base,
1433
+ createsConversation: false,
1434
+ }),
1435
+ );
1436
+ if (!facts.conversationId || !prepared.messageId) {
1437
+ throw new AiChatOperationError(
1438
+ 500,
1439
+ "Tool continuation authorization message is unavailable.",
1440
+ "AUTHORIZATION_SNAPSHOT_MISSING",
1441
+ );
1442
+ }
1443
+ // A completed tool result starts another generation for the same
1444
+ // persisted user message. Requiring retry as well as send prevents an
1445
+ // assistant-ended browser transcript from bypassing a denied retry rule.
1446
+ requests.push(
1447
+ aiChatPermissions.message.retry({
1448
+ conversationId: facts.conversationId,
1449
+ messageId: prepared.messageId,
1450
+ ...(facts.ownerId ? { ownerId: facts.ownerId } : {}),
1451
+ }),
1452
+ );
1453
+ }
1454
+ if (prepared.mediaTypes.length > 0) {
1455
+ requests.push(
1456
+ aiChatPermissions.attachment.send({
1457
+ ...base,
1458
+ mediaTypes: [...prepared.mediaTypes],
1459
+ }),
1460
+ );
1461
+ }
1462
+ if (prepared.authorizationToolNames.length > 0) {
1463
+ requests.push(
1464
+ aiChatPermissions.tool.activate({
1465
+ ...base,
1466
+ ...(input.routeName ? { routeName: input.routeName } : {}),
1467
+ toolNames: [...prepared.authorizationToolNames],
1468
+ }),
1469
+ );
1470
+ }
1471
+ return requests;
1472
+ },
1473
+ execute: async (context) => {
1474
+ const prepared = streamPreparations.get(context.input as object);
1475
+ if (!prepared) {
1476
+ throw new AiChatOperationError(
1477
+ 500,
1478
+ "Stream authorization context is unavailable.",
1479
+ "AUTHORIZATION_SNAPSHOT_MISSING",
1480
+ );
1481
+ }
1482
+ const uiMessages = context.input.messages as UIMessage[];
1483
+ const firstMessage = uiMessages[0] as UIMessage;
1484
+ const userId =
1485
+ config.access === "authorized"
1486
+ ? await scopedUserId(context, context.input)
1487
+ : undefined;
1488
+ if (config.access === "authorized") {
1489
+ assertConversationScope(
1490
+ prepared.snapshot,
1491
+ context.identity ? undefined : userId,
1492
+ "Unauthorized: Cannot access this conversation",
1493
+ );
1494
+ }
1495
+
1496
+ if (config.access === "authorized" && context.input.conversationId) {
1497
+ const current = await getConversationById(
1498
+ adapter,
1499
+ context.input.conversationId,
1500
+ );
1501
+ if (!sameSnapshot(current, prepared.snapshot)) {
1502
+ throw new AiChatOperationError(
1503
+ 409,
1504
+ "Conversation changed during authorization.",
1505
+ "STALE_CONVERSATION",
1506
+ );
1507
+ }
1508
+ }
1509
+
1510
+ const modelMessages = await convertToModelMessages(uiMessages);
1511
+ const pageContext = context.input.pageContext?.trim();
1512
+ const pageSuffix = pageContext
1513
+ ? `\n\nCurrent page context:\n${pageContext}`
1514
+ : "";
1515
+ const systemContent = config.systemPrompt
1516
+ ? `${config.systemPrompt}${pageSuffix}`
1517
+ : pageSuffix || undefined;
1518
+ const messages = systemContent
1519
+ ? [
1520
+ { role: "system" as const, content: systemContent },
1521
+ ...modelMessages,
1522
+ ]
1523
+ : modelMessages;
1524
+ const contextForHooks = hookContext(context, { body: context.input });
1525
+ const enterChatLifecycle = async () => {
1526
+ await runBeforeHook(
1527
+ () =>
1528
+ hooks?.onBeforeChat?.(
1529
+ uiMessages.map((message) => ({
1530
+ role: message.role,
1531
+ content: textContent(message),
1532
+ })),
1533
+ contextForHooks,
1534
+ ),
1535
+ "Unauthorized: Cannot start chat",
1536
+ );
1537
+
1538
+ let allowedToolNames = [...prepared.toolNames];
1539
+ if (allowedToolNames.length > 0 && hooks?.onBeforeActivateTools) {
1540
+ const onBeforeActivateTools = hooks.onBeforeActivateTools;
1541
+ const filtered = await runBeforeHook(
1542
+ () =>
1543
+ onBeforeActivateTools(
1544
+ allowedToolNames,
1545
+ context.input.routeName,
1546
+ contextForHooks,
1547
+ ),
1548
+ "Unauthorized: Tool activation denied",
1549
+ );
1550
+ const structurallyAllowed = new Set(allowedToolNames);
1551
+ allowedToolNames = [
1552
+ ...new Set(
1553
+ filtered.filter((name) => structurallyAllowed.has(name)),
1554
+ ),
1555
+ ];
1556
+ }
1557
+ return buildTools(allowedToolNames, config);
1558
+ };
1559
+
1560
+ const reportStreamError = async (error: unknown) => {
1561
+ try {
1562
+ await hooks?.onErrorChat?.(
1563
+ normalizeError(error, "Chat provider stream failed"),
1564
+ contextForHooks,
1565
+ );
1566
+ } catch (hookError) {
1567
+ console.error("[ai-chat] Error in onErrorChat hook:", hookError);
1568
+ }
1569
+ };
1570
+
1571
+ const startModelStream = (
1572
+ mergedTools: Record<string, Tool> | undefined,
1573
+ onFinish?: (completion: { text: string }) => Promise<void>,
1574
+ ) => {
1575
+ const result = streamText({
1576
+ model: config.model,
1577
+ messages,
1578
+ tools: mergedTools,
1579
+ ...(mergedTools ? { stopWhen: stepCountIs(5) } : {}),
1580
+ ...(onFinish ? { onFinish } : {}),
1581
+ onError: ({ error }) => reportStreamError(error),
1582
+ });
1583
+ return result.toUIMessageStreamResponse({
1584
+ originalMessages: uiMessages,
1585
+ });
1586
+ };
1587
+
1588
+ if (config.access === "public") {
1589
+ const mergedTools = await enterChatLifecycle();
1590
+ return startModelStream(mergedTools);
1591
+ }
1592
+ requireAtomicConversationTransactions(adapter);
1593
+ const releaseExistingConversationClaim = prepared.snapshot
1594
+ ? claimConversationMutation(prepared.snapshot.id)
1595
+ : undefined;
1596
+
1597
+ const requestedMissingConversationId =
1598
+ !prepared.snapshot && context.input.conversationId
1599
+ ? context.input.conversationId
1600
+ : undefined;
1601
+ if (
1602
+ requestedMissingConversationId &&
1603
+ pendingRequestedConversationClaims.has(requestedMissingConversationId)
1604
+ ) {
1605
+ throw new AiChatOperationError(
1606
+ 409,
1607
+ "Conversation changed during authorization.",
1608
+ "STALE_CONVERSATION",
1609
+ );
1610
+ }
1611
+ if (requestedMissingConversationId) {
1612
+ pendingRequestedConversationClaims.add(requestedMissingConversationId);
1613
+ }
1614
+ try {
1615
+ return await adapter.transaction(async (tx) => {
1616
+ let conversationId = context.input.conversationId;
1617
+ let streamClaimVersion: Date | undefined;
1618
+ const createConversation = () => {
1619
+ const now = new Date();
1620
+ return tx.create<Conversation>({
1621
+ model: "conversation",
1622
+ forceAllowId: Boolean(conversationId),
1623
+ data: {
1624
+ ...(conversationId ? { id: conversationId } : {}),
1625
+ ...(userId ? { userId } : {}),
1626
+ title:
1627
+ textContent(firstMessage).slice(0, 50) || "New Conversation",
1628
+ createdAt: now,
1629
+ updatedAt: now,
1630
+ } as Conversation,
1631
+ });
1632
+ };
1633
+ if (prepared.snapshot) {
1634
+ const claimedAt = nextVersion(
1635
+ new Date(prepared.snapshot.updatedAt),
1636
+ );
1637
+ const claimed = await tx.updateMany({
1638
+ model: "conversation",
1639
+ where: [
1640
+ {
1641
+ field: "id",
1642
+ value: prepared.snapshot.id,
1643
+ operator: "eq" as const,
1644
+ },
1645
+ {
1646
+ field: "updatedAt",
1647
+ value: new Date(prepared.snapshot.updatedAt),
1648
+ operator: "gte" as const,
1649
+ },
1650
+ {
1651
+ field: "updatedAt",
1652
+ value: new Date(prepared.snapshot.updatedAt),
1653
+ operator: "lte" as const,
1654
+ },
1655
+ ],
1656
+ update: { updatedAt: claimedAt },
1657
+ });
1658
+ if (!didAffectRow(claimed, prepared.snapshot.id)) {
1659
+ throw new AiChatOperationError(
1660
+ 409,
1661
+ "Conversation changed during authorization.",
1662
+ "STALE_CONVERSATION",
1663
+ );
1664
+ }
1665
+ conversationId = prepared.snapshot.id;
1666
+ streamClaimVersion = claimedAt;
1667
+ } else if (conversationId) {
1668
+ // A caller-selected id is also the atomic absence claim. Creating it
1669
+ // inside the transaction ensures a concurrent loser fails before any
1670
+ // ordinary lifecycle hook runs; hook failures roll the claim back.
1671
+ const current = await getConversationById(tx, conversationId);
1672
+ if (current) {
1673
+ throw new AiChatOperationError(
1674
+ 409,
1675
+ "Conversation changed during authorization.",
1676
+ "STALE_CONVERSATION",
1677
+ );
1678
+ }
1679
+ const created = await createConversation();
1680
+ conversationId = created.id;
1681
+ streamClaimVersion = created.updatedAt;
1682
+ }
1683
+ const mergedTools = await enterChatLifecycle();
1684
+ if (!prepared.snapshot && !conversationId) {
1685
+ const created = await createConversation();
1686
+ conversationId = created.id;
1687
+ streamClaimVersion = created.updatedAt;
1688
+ }
1689
+ if (!conversationId || !streamClaimVersion) {
1690
+ throw new AiChatOperationError(
1691
+ 500,
1692
+ "Conversation id was not created.",
1693
+ "CONVERSATION_CREATE_FAILED",
1694
+ );
1695
+ }
1696
+ const existingMessages = await tx.findMany<Message>({
1697
+ model: "message",
1698
+ where: [
1699
+ {
1700
+ field: "conversationId",
1701
+ value: conversationId,
1702
+ operator: "eq",
1703
+ },
1704
+ ],
1705
+ sortBy: { field: "createdAt", direction: "asc" },
1706
+ });
1707
+ const lastIncoming = uiMessages[uiMessages.length - 1];
1708
+ const targetIndex = prepared.messageId
1709
+ ? existingMessages.findIndex(
1710
+ (message) => message.id === prepared.messageId,
1711
+ )
1712
+ : -1;
1713
+ if (
1714
+ (prepared.intent === "retry" || prepared.intent === "edit") &&
1715
+ targetIndex === -1
1716
+ ) {
1717
+ throw new AiChatOperationError(
1718
+ 409,
1719
+ "The authorized message changed before persistence.",
1720
+ "STALE_MESSAGE",
1721
+ );
1722
+ }
1723
+ const deleteFrom =
1724
+ prepared.intent === "edit"
1725
+ ? targetIndex
1726
+ : prepared.intent === "retry"
1727
+ ? targetIndex + 1
1728
+ : existingMessages.length;
1729
+ for (const message of existingMessages.slice(deleteFrom)) {
1730
+ await tx.delete({
1731
+ model: "message",
1732
+ where: [{ field: "id", value: message.id }],
1733
+ });
1734
+ }
1735
+ if (
1736
+ (prepared.intent === "send" || prepared.intent === "edit") &&
1737
+ lastIncoming?.role === "user"
1738
+ ) {
1739
+ await tx.create<Message>({
1740
+ model: "message",
1741
+ data: {
1742
+ conversationId,
1743
+ role: "user",
1744
+ content: serializedParts(lastIncoming),
1745
+ createdAt: new Date(),
1746
+ },
1747
+ });
1748
+ }
1749
+
1750
+ const completionConversationId = conversationId;
1751
+ const completionClaimVersion = streamClaimVersion;
1752
+ const response = startModelStream(mergedTools, async ({ text }) => {
1753
+ try {
1754
+ requireAtomicConversationTransactions(adapter);
1755
+ const persisted = await adapter.transaction(
1756
+ async (completionTx) => {
1757
+ const completedAt = nextVersion(completionClaimVersion);
1758
+ const claimed = await completionTx.updateMany({
1759
+ model: "conversation",
1760
+ where: [
1761
+ {
1762
+ field: "id",
1763
+ value: completionConversationId,
1764
+ operator: "eq" as const,
1765
+ },
1766
+ {
1767
+ field: "updatedAt",
1768
+ value: completionClaimVersion,
1769
+ operator: "gte" as const,
1770
+ },
1771
+ {
1772
+ field: "updatedAt",
1773
+ value: completionClaimVersion,
1774
+ operator: "lte" as const,
1775
+ },
1776
+ ],
1777
+ update: { updatedAt: completedAt },
1778
+ });
1779
+ if (!didAffectRow(claimed, completionConversationId)) {
1780
+ throw new AiChatOperationError(
1781
+ 409,
1782
+ "A newer stream owns this conversation.",
1783
+ "STALE_STREAM",
1784
+ );
1785
+ }
1786
+ await completionTx.create<Message>({
1787
+ model: "message",
1788
+ data: {
1789
+ conversationId: completionConversationId,
1790
+ role: "assistant",
1791
+ content: JSON.stringify(
1792
+ text ? [{ type: "text", text }] : [],
1793
+ ),
1794
+ createdAt: new Date(),
1795
+ },
1796
+ });
1797
+ return completionTx.findMany<Message>({
1798
+ model: "message",
1799
+ where: [
1800
+ {
1801
+ field: "conversationId",
1802
+ value: completionConversationId,
1803
+ operator: "eq",
1804
+ },
1805
+ ],
1806
+ sortBy: { field: "createdAt", direction: "asc" },
1807
+ });
1808
+ },
1809
+ );
1810
+ if (hooks?.onAfterChat) {
1811
+ await hooks.onAfterChat(
1812
+ completionConversationId,
1813
+ persisted.map(serializeMessage),
1814
+ contextForHooks,
1815
+ );
1816
+ }
1817
+ } catch (error) {
1818
+ console.error("[ai-chat] Error in stream completion:", error);
1819
+ try {
1820
+ await hooks?.onErrorChat?.(
1821
+ normalizeError(error, "Chat completion persistence failed"),
1822
+ contextForHooks,
1823
+ );
1824
+ } catch (hookError) {
1825
+ console.error(
1826
+ "[ai-chat] Error in onErrorChat hook:",
1827
+ hookError,
1828
+ );
1829
+ }
1830
+ }
1831
+ });
1832
+ const headers = new Headers(response.headers);
1833
+ headers.set("X-Conversation-Id", completionConversationId);
1834
+ return new Response(response.body, {
1835
+ status: response.status,
1836
+ statusText: response.statusText,
1837
+ headers,
1838
+ });
1839
+ });
1840
+ } finally {
1841
+ releaseExistingConversationClaim?.();
1842
+ if (requestedMissingConversationId) {
1843
+ pendingRequestedConversationClaims.delete(
1844
+ requestedMissingConversationId,
1845
+ );
1846
+ }
1847
+ }
1848
+ },
1849
+ onError: ({ error, ...context }) => {
1850
+ markMemoryRollback(adapter, error);
1851
+ return notifyError(hooks?.onErrorChat, error, context, {
1852
+ body: context.input,
1853
+ });
1854
+ },
1855
+ });
1856
+
1857
+ return {
1858
+ startStream,
1859
+ listConversations,
1860
+ getConversation,
1861
+ createConversation,
1862
+ updateConversation,
1863
+ deleteConversation,
1864
+ };
1865
+ }