@btst/stack 2.2.0 → 2.4.0

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 (237) hide show
  1. package/dist/packages/stack/src/client/components/compose.cjs +1 -2
  2. package/dist/packages/stack/src/client/components/compose.mjs +1 -2
  3. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.cjs +71 -0
  4. package/dist/packages/stack/src/plugins/ai-chat/api/page-tools.mjs +68 -0
  5. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.cjs +54 -7
  6. package/dist/packages/stack/src/plugins/ai-chat/api/plugin.mjs +54 -7
  7. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.cjs +2 -2
  8. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-input.mjs +2 -2
  9. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.cjs +89 -22
  10. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-interface.mjs +90 -23
  11. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.cjs +110 -33
  12. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-layout.mjs +112 -35
  13. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +1 -1
  14. package/dist/packages/stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +1 -1
  15. package/dist/packages/stack/src/plugins/ai-chat/schemas.cjs +17 -1
  16. package/dist/packages/stack/src/plugins/ai-chat/schemas.mjs +17 -1
  17. package/dist/packages/stack/src/plugins/blog/api/plugin.cjs +52 -1
  18. package/dist/packages/stack/src/plugins/blog/api/plugin.mjs +52 -1
  19. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.cjs +18 -0
  20. package/dist/packages/stack/src/plugins/blog/api/query-key-defs.mjs +15 -0
  21. package/dist/packages/stack/src/plugins/blog/api/serializers.cjs +21 -0
  22. package/dist/packages/stack/src/plugins/blog/api/serializers.mjs +18 -0
  23. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.cjs +15 -2
  24. package/dist/packages/stack/src/plugins/blog/client/components/forms/post-forms.mjs +16 -3
  25. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.cjs +24 -1
  26. package/dist/packages/stack/src/plugins/blog/client/components/pages/edit-post-page.internal.mjs +24 -1
  27. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.cjs +26 -0
  28. package/dist/packages/stack/src/plugins/blog/client/components/pages/fill-blog-form-handler.mjs +24 -0
  29. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.cjs +30 -1
  30. package/dist/packages/stack/src/plugins/blog/client/components/pages/new-post-page.internal.mjs +30 -1
  31. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +18 -0
  32. package/dist/packages/stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +18 -0
  33. package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +15 -0
  34. package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +16 -1
  35. package/dist/packages/stack/src/plugins/cms/api/getters.cjs +10 -0
  36. package/dist/packages/stack/src/plugins/cms/api/getters.mjs +10 -1
  37. package/dist/packages/stack/src/plugins/cms/api/mutations.cjs +48 -0
  38. package/dist/packages/stack/src/plugins/cms/api/mutations.mjs +46 -0
  39. package/dist/packages/stack/src/plugins/cms/api/plugin.cjs +75 -0
  40. package/dist/packages/stack/src/plugins/cms/api/plugin.mjs +76 -1
  41. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.cjs +29 -0
  42. package/dist/packages/stack/src/plugins/cms/api/query-key-defs.mjs +26 -0
  43. package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +15 -0
  44. package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +16 -1
  45. package/dist/packages/stack/src/plugins/form-builder/api/getters.cjs +9 -0
  46. package/dist/packages/stack/src/plugins/form-builder/api/getters.mjs +9 -1
  47. package/dist/packages/stack/src/plugins/form-builder/api/plugin.cjs +62 -1
  48. package/dist/packages/stack/src/plugins/form-builder/api/plugin.mjs +63 -2
  49. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.cjs +37 -0
  50. package/dist/packages/stack/src/plugins/form-builder/api/query-key-defs.mjs +33 -0
  51. package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +15 -0
  52. package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +16 -1
  53. package/dist/packages/stack/src/plugins/kanban/api/mutations.cjs +91 -0
  54. package/dist/packages/stack/src/plugins/kanban/api/mutations.mjs +87 -0
  55. package/dist/packages/stack/src/plugins/kanban/api/plugin.cjs +34 -1
  56. package/dist/packages/stack/src/plugins/kanban/api/plugin.mjs +34 -1
  57. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.cjs +26 -0
  58. package/dist/packages/stack/src/plugins/kanban/api/query-key-defs.mjs +23 -0
  59. package/dist/packages/stack/src/plugins/kanban/api/serializers.cjs +30 -0
  60. package/dist/packages/stack/src/plugins/kanban/api/serializers.mjs +26 -0
  61. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +7 -3
  62. package/dist/packages/stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +7 -3
  63. package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +10 -0
  64. package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +11 -1
  65. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.cjs +89 -0
  66. package/dist/packages/stack/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.mjs +89 -0
  67. package/dist/packages/stack/src/plugins/utils.cjs +6 -0
  68. package/dist/packages/stack/src/plugins/utils.mjs +6 -1
  69. package/dist/plugins/ai-chat/api/index.d.cts +1 -1
  70. package/dist/plugins/ai-chat/api/index.d.mts +1 -1
  71. package/dist/plugins/ai-chat/api/index.d.ts +1 -1
  72. package/dist/plugins/ai-chat/client/components/index.d.cts +1 -1
  73. package/dist/plugins/ai-chat/client/components/index.d.mts +1 -1
  74. package/dist/plugins/ai-chat/client/components/index.d.ts +1 -1
  75. package/dist/plugins/ai-chat/client/context/page-ai-context.cjs +92 -0
  76. package/dist/plugins/ai-chat/client/context/page-ai-context.d.cts +84 -0
  77. package/dist/plugins/ai-chat/client/context/page-ai-context.d.mts +84 -0
  78. package/dist/plugins/ai-chat/client/context/page-ai-context.d.ts +84 -0
  79. package/dist/plugins/ai-chat/client/context/page-ai-context.mjs +88 -0
  80. package/dist/plugins/ai-chat/client/hooks/index.d.cts +1 -1
  81. package/dist/plugins/ai-chat/client/hooks/index.d.mts +1 -1
  82. package/dist/plugins/ai-chat/client/hooks/index.d.ts +1 -1
  83. package/dist/plugins/ai-chat/client/index.d.cts +2 -2
  84. package/dist/plugins/ai-chat/client/index.d.mts +2 -2
  85. package/dist/plugins/ai-chat/client/index.d.ts +2 -2
  86. package/dist/plugins/ai-chat/query-keys.d.cts +1 -1
  87. package/dist/plugins/ai-chat/query-keys.d.mts +1 -1
  88. package/dist/plugins/ai-chat/query-keys.d.ts +1 -1
  89. package/dist/plugins/blog/api/index.cjs +5 -0
  90. package/dist/plugins/blog/api/index.d.cts +19 -4
  91. package/dist/plugins/blog/api/index.d.mts +19 -4
  92. package/dist/plugins/blog/api/index.d.ts +19 -4
  93. package/dist/plugins/blog/api/index.mjs +2 -0
  94. package/dist/plugins/blog/client/hooks/index.d.cts +3 -3
  95. package/dist/plugins/blog/client/hooks/index.d.mts +3 -3
  96. package/dist/plugins/blog/client/hooks/index.d.ts +3 -3
  97. package/dist/plugins/blog/client/index.d.cts +1 -1
  98. package/dist/plugins/blog/client/index.d.mts +1 -1
  99. package/dist/plugins/blog/client/index.d.ts +1 -1
  100. package/dist/plugins/blog/query-keys.cjs +6 -5
  101. package/dist/plugins/blog/query-keys.d.cts +8 -387
  102. package/dist/plugins/blog/query-keys.d.mts +8 -387
  103. package/dist/plugins/blog/query-keys.d.ts +8 -387
  104. package/dist/plugins/blog/query-keys.mjs +6 -5
  105. package/dist/plugins/client/index.cjs +1 -0
  106. package/dist/plugins/client/index.d.cts +8 -1
  107. package/dist/plugins/client/index.d.mts +8 -1
  108. package/dist/plugins/client/index.d.ts +8 -1
  109. package/dist/plugins/client/index.mjs +1 -1
  110. package/dist/plugins/cms/api/index.cjs +8 -0
  111. package/dist/plugins/cms/api/index.d.cts +7 -219
  112. package/dist/plugins/cms/api/index.d.mts +7 -219
  113. package/dist/plugins/cms/api/index.d.ts +7 -219
  114. package/dist/plugins/cms/api/index.mjs +3 -1
  115. package/dist/plugins/cms/client/hooks/index.d.cts +1 -1
  116. package/dist/plugins/cms/client/hooks/index.d.mts +1 -1
  117. package/dist/plugins/cms/client/hooks/index.d.ts +1 -1
  118. package/dist/plugins/cms/query-keys.cjs +2 -1
  119. package/dist/plugins/cms/query-keys.d.cts +5 -9
  120. package/dist/plugins/cms/query-keys.d.mts +5 -9
  121. package/dist/plugins/cms/query-keys.d.ts +5 -9
  122. package/dist/plugins/cms/query-keys.mjs +2 -1
  123. package/dist/plugins/form-builder/api/index.cjs +6 -0
  124. package/dist/plugins/form-builder/api/index.d.cts +7 -211
  125. package/dist/plugins/form-builder/api/index.d.mts +7 -211
  126. package/dist/plugins/form-builder/api/index.d.ts +7 -211
  127. package/dist/plugins/form-builder/api/index.mjs +2 -1
  128. package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
  129. package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
  130. package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
  131. package/dist/plugins/form-builder/client/hooks/index.d.cts +1 -1
  132. package/dist/plugins/form-builder/client/hooks/index.d.mts +1 -1
  133. package/dist/plugins/form-builder/client/hooks/index.d.ts +1 -1
  134. package/dist/plugins/form-builder/query-keys.cjs +3 -2
  135. package/dist/plugins/form-builder/query-keys.d.cts +6 -6
  136. package/dist/plugins/form-builder/query-keys.d.mts +6 -6
  137. package/dist/plugins/form-builder/query-keys.d.ts +6 -6
  138. package/dist/plugins/form-builder/query-keys.mjs +3 -2
  139. package/dist/plugins/kanban/api/index.cjs +10 -0
  140. package/dist/plugins/kanban/api/index.d.cts +17 -392
  141. package/dist/plugins/kanban/api/index.d.mts +17 -392
  142. package/dist/plugins/kanban/api/index.d.ts +17 -392
  143. package/dist/plugins/kanban/api/index.mjs +3 -0
  144. package/dist/plugins/kanban/client/components/index.d.cts +1 -1
  145. package/dist/plugins/kanban/client/components/index.d.mts +1 -1
  146. package/dist/plugins/kanban/client/components/index.d.ts +1 -1
  147. package/dist/plugins/kanban/client/hooks/index.d.cts +1 -1
  148. package/dist/plugins/kanban/client/hooks/index.d.mts +1 -1
  149. package/dist/plugins/kanban/client/hooks/index.d.ts +1 -1
  150. package/dist/plugins/kanban/client/index.d.cts +1 -1
  151. package/dist/plugins/kanban/client/index.d.mts +1 -1
  152. package/dist/plugins/kanban/client/index.d.ts +1 -1
  153. package/dist/plugins/kanban/query-keys.cjs +2 -9
  154. package/dist/plugins/kanban/query-keys.d.cts +4 -16
  155. package/dist/plugins/kanban/query-keys.d.mts +4 -16
  156. package/dist/plugins/kanban/query-keys.d.ts +4 -16
  157. package/dist/plugins/kanban/query-keys.mjs +2 -9
  158. package/dist/plugins/ui-builder/index.d.cts +1 -1
  159. package/dist/plugins/ui-builder/index.d.mts +1 -1
  160. package/dist/plugins/ui-builder/index.d.ts +1 -1
  161. package/dist/shared/stack.B7ONvlD_.d.mts +293 -0
  162. package/dist/shared/{stack.BeSm90va.d.ts → stack.BEn34wW6.d.ts} +60 -2
  163. package/dist/shared/stack.BUkC2EsZ.d.cts +327 -0
  164. package/dist/shared/{stack.DaOcgmrM.d.ts → stack.BV9hnvu4.d.cts} +31 -7
  165. package/dist/shared/{stack.DaOcgmrM.d.cts → stack.BV9hnvu4.d.mts} +31 -7
  166. package/dist/shared/{stack.DaOcgmrM.d.mts → stack.BV9hnvu4.d.ts} +31 -7
  167. package/dist/shared/stack.BepFXT3w.d.mts +500 -0
  168. package/dist/shared/stack.CL8ts1Mu.d.ts +419 -0
  169. package/dist/shared/{stack.CXjzTMsb.d.cts → stack.CVDTkMoO.d.cts} +7 -1
  170. package/dist/shared/{stack.CXjzTMsb.d.mts → stack.CVDTkMoO.d.mts} +7 -1
  171. package/dist/shared/{stack.CXjzTMsb.d.ts → stack.CVDTkMoO.d.ts} +7 -1
  172. package/dist/shared/stack.CczspVn2.d.mts +327 -0
  173. package/dist/shared/stack.CgWzG5jH.d.ts +500 -0
  174. package/dist/shared/stack.D3GB6wKv.d.cts +500 -0
  175. package/dist/shared/stack.DASmUVjX.d.ts +327 -0
  176. package/dist/shared/{stack.QD1y_7NY.d.cts → stack.DJaKVY7v.d.cts} +1 -1
  177. package/dist/shared/{stack.QD1y_7NY.d.mts → stack.DJaKVY7v.d.mts} +1 -1
  178. package/dist/shared/{stack.QD1y_7NY.d.ts → stack.DJaKVY7v.d.ts} +1 -1
  179. package/dist/shared/{stack.Dg09R0oB.d.mts → stack.DTDxgFj8.d.mts} +60 -2
  180. package/dist/shared/{stack.CMh_EdxW.d.cts → stack.DWoCZff7.d.cts} +60 -2
  181. package/dist/shared/{stack.CIrIsc-A.d.cts → stack.DdI5W6MB.d.cts} +7 -1
  182. package/dist/shared/{stack.CIrIsc-A.d.mts → stack.DdI5W6MB.d.mts} +7 -1
  183. package/dist/shared/{stack.CIrIsc-A.d.ts → stack.DdI5W6MB.d.ts} +7 -1
  184. package/dist/shared/stack.Dk5r4W1F.d.mts +419 -0
  185. package/dist/shared/stack.Kq2-QzOC.d.ts +293 -0
  186. package/dist/shared/stack.heOA9gzA.d.cts +419 -0
  187. package/dist/shared/stack.kcdnD4gA.d.cts +293 -0
  188. package/package.json +16 -3
  189. package/src/client/components/compose.tsx +7 -4
  190. package/src/plugins/ai-chat/api/page-tools.ts +111 -0
  191. package/src/plugins/ai-chat/api/plugin.ts +180 -9
  192. package/src/plugins/ai-chat/client/components/chat-input.tsx +2 -2
  193. package/src/plugins/ai-chat/client/components/chat-interface.tsx +154 -58
  194. package/src/plugins/ai-chat/client/components/chat-layout.tsx +166 -32
  195. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +1 -1
  196. package/src/plugins/ai-chat/client/context/page-ai-context.tsx +240 -0
  197. package/src/plugins/ai-chat/schemas.ts +16 -0
  198. package/src/plugins/blog/api/index.ts +2 -0
  199. package/src/plugins/blog/api/plugin.ts +85 -0
  200. package/src/plugins/blog/api/query-key-defs.ts +46 -0
  201. package/src/plugins/blog/api/serializers.ts +27 -0
  202. package/src/plugins/blog/client/components/forms/post-forms.tsx +29 -2
  203. package/src/plugins/blog/client/components/pages/edit-post-page.internal.tsx +28 -0
  204. package/src/plugins/blog/client/components/pages/fill-blog-form-handler.ts +38 -0
  205. package/src/plugins/blog/client/components/pages/new-post-page.internal.tsx +33 -1
  206. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +20 -0
  207. package/src/plugins/blog/client/plugin.tsx +19 -0
  208. package/src/plugins/blog/query-keys.ts +5 -7
  209. package/src/plugins/client/index.ts +1 -1
  210. package/src/plugins/cms/api/getters.ts +24 -0
  211. package/src/plugins/cms/api/index.ts +14 -1
  212. package/src/plugins/cms/api/mutations.ts +84 -0
  213. package/src/plugins/cms/api/plugin.ts +114 -0
  214. package/src/plugins/cms/api/query-key-defs.ts +53 -0
  215. package/src/plugins/cms/api/serializers.ts +12 -0
  216. package/src/plugins/cms/client/plugin.tsx +19 -0
  217. package/src/plugins/cms/query-keys.ts +2 -1
  218. package/src/plugins/form-builder/api/getters.ts +23 -0
  219. package/src/plugins/form-builder/api/index.ts +15 -2
  220. package/src/plugins/form-builder/api/plugin.ts +91 -0
  221. package/src/plugins/form-builder/api/query-key-defs.ts +79 -0
  222. package/src/plugins/form-builder/api/serializers.ts +12 -0
  223. package/src/plugins/form-builder/client/plugin.tsx +19 -0
  224. package/src/plugins/form-builder/query-keys.ts +6 -2
  225. package/src/plugins/kanban/api/index.ts +9 -0
  226. package/src/plugins/kanban/api/mutations.ts +169 -0
  227. package/src/plugins/kanban/api/plugin.ts +61 -0
  228. package/src/plugins/kanban/api/query-key-defs.ts +54 -0
  229. package/src/plugins/kanban/api/serializers.ts +49 -0
  230. package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +4 -0
  231. package/src/plugins/kanban/client/plugin.tsx +13 -0
  232. package/src/plugins/kanban/query-keys.ts +2 -9
  233. package/src/plugins/ui-builder/client/components/pages/page-builder-page.internal.tsx +132 -0
  234. package/src/plugins/utils.ts +19 -0
  235. package/dist/shared/{stack.BkYlUT_8.d.cts → stack.BQmuNl5p.d.cts} +6 -6
  236. package/dist/shared/{stack.BkYlUT_8.d.mts → stack.BQmuNl5p.d.mts} +6 -6
  237. package/dist/shared/{stack.BkYlUT_8.d.ts → stack.BQmuNl5p.d.ts} +6 -6
@@ -33,7 +33,8 @@ function useBoards(params) {
33
33
  const queries = createKanbanQueryKeys(client, headers);
34
34
  return useQuery({
35
35
  ...queries.boards.list(params),
36
- staleTime: 3e4
36
+ staleTime: 3e4,
37
+ refetchOnWindowFocus: true
37
38
  });
38
39
  }
39
40
  function useSuspenseBoards(params) {
@@ -41,7 +42,8 @@ function useSuspenseBoards(params) {
41
42
  const queries = createKanbanQueryKeys(client, headers);
42
43
  const result = useSuspenseQuery({
43
44
  ...queries.boards.list(params),
44
- staleTime: 3e4
45
+ staleTime: 3e4,
46
+ refetchOnWindowFocus: true
45
47
  });
46
48
  if (result.error && !result.isFetching) {
47
49
  throw result.error;
@@ -54,6 +56,7 @@ function useBoard(boardId) {
54
56
  return useQuery({
55
57
  ...queries.boards.detail(boardId),
56
58
  staleTime: 3e4,
59
+ refetchOnWindowFocus: true,
57
60
  enabled: !!boardId
58
61
  });
59
62
  }
@@ -62,7 +65,8 @@ function useSuspenseBoard(boardId) {
62
65
  const queries = createKanbanQueryKeys(client, headers);
63
66
  const result = useSuspenseQuery({
64
67
  ...queries.boards.detail(boardId),
65
- staleTime: 3e4
68
+ staleTime: 3e4,
69
+ refetchOnWindowFocus: true
66
70
  });
67
71
  if (result.error && !result.isFetching) {
68
72
  throw result.error;
@@ -51,6 +51,11 @@ function createBoardsLoader(config) {
51
51
  await hooks.onLoadError(error, context);
52
52
  }
53
53
  } catch (error) {
54
+ if (client.isConnectionError(error)) {
55
+ console.warn(
56
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
57
+ );
58
+ }
54
59
  if (hooks?.onLoadError) {
55
60
  await hooks.onLoadError(error, context);
56
61
  }
@@ -103,6 +108,11 @@ function createBoardLoader(boardId, config) {
103
108
  await hooks.onLoadError(error, context);
104
109
  }
105
110
  } catch (error) {
111
+ if (client.isConnectionError(error)) {
112
+ console.warn(
113
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
114
+ );
115
+ }
106
116
  if (hooks?.onLoadError) {
107
117
  await hooks.onLoadError(error, context);
108
118
  }
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { defineClientPlugin, createApiClient } from '@btst/stack/plugins/client';
2
+ import { defineClientPlugin, createApiClient, isConnectionError } from '@btst/stack/plugins/client';
3
3
  import { createRoute } from '@btst/yar';
4
4
  import { createKanbanQueryKeys } from '../../../../../../plugins/kanban/query-keys.mjs';
5
5
  import { BoardsListPageComponent } from './components/pages/boards-list-page.mjs';
@@ -49,6 +49,11 @@ function createBoardsLoader(config) {
49
49
  await hooks.onLoadError(error, context);
50
50
  }
51
51
  } catch (error) {
52
+ if (isConnectionError(error)) {
53
+ console.warn(
54
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
55
+ );
56
+ }
52
57
  if (hooks?.onLoadError) {
53
58
  await hooks.onLoadError(error, context);
54
59
  }
@@ -101,6 +106,11 @@ function createBoardLoader(boardId, config) {
101
106
  await hooks.onLoadError(error, context);
102
107
  }
103
108
  } catch (error) {
109
+ if (isConnectionError(error)) {
110
+ console.warn(
111
+ "[btst/kanban] route.loader() failed \u2014 no server running at build time. Use myStack.api.kanban.prefetchForRoute() for SSG data prefetching."
112
+ );
113
+ }
104
114
  if (hooks?.onLoadError) {
105
115
  await hooks.onLoadError(error, context);
106
116
  }
@@ -12,10 +12,73 @@ const label = require('../../../../../../../ui/src/components/label.cjs');
12
12
  const LucideIcons = require('lucide-react');
13
13
  const sonner = require('sonner');
14
14
  const index$1 = require('../../../../../../../ui/src/components/ui-builder/index.cjs');
15
+ const layerStore = require('../../../../../../../ui/src/lib/ui-builder/store/layer-store.cjs');
16
+ const context$1 = require('@btst/stack/plugins/ai-chat/client/context');
15
17
  const uiBuilderHooks = require('../../hooks/ui-builder-hooks.cjs');
16
18
  const index = require('../../localization/index.cjs');
17
19
  const registry = require('../../registry.cjs');
18
20
 
21
+ function buildRegistryDescription(registry) {
22
+ const lines = [];
23
+ for (const [name, entry] of Object.entries(registry)) {
24
+ let propsLine = "";
25
+ try {
26
+ const shape = entry.schema?.shape;
27
+ if (shape) {
28
+ const fields = Object.keys(shape).join(", ");
29
+ propsLine = ` \u2014 props: ${fields}`;
30
+ }
31
+ } catch {
32
+ }
33
+ lines.push(`- ${name}${propsLine}`);
34
+ }
35
+ return lines.join("\n");
36
+ }
37
+ function buildPageDescription(id, slug, layers, registry) {
38
+ const header = id ? `UI Builder \u2014 editing page (slug: "${slug}")` : "UI Builder \u2014 creating new page";
39
+ const layersJson = JSON.stringify(layers, null, 2);
40
+ const registryDesc = buildRegistryDescription(registry);
41
+ const layerFormat = `Each layer: { id: string, type: string, name: string, props: Record<string,any>, children?: ComponentLayer[] | string }`;
42
+ const full = [
43
+ header,
44
+ "",
45
+ `## Current Layers (${layers.length})`,
46
+ layersJson,
47
+ "",
48
+ `## Available Component Types`,
49
+ registryDesc,
50
+ "",
51
+ `## ComponentLayer format`,
52
+ layerFormat
53
+ ].join("\n");
54
+ if (full.length <= 16e3) return full;
55
+ const overhead = [
56
+ header,
57
+ "",
58
+ `## Current Layers (${layers.length})`,
59
+ "",
60
+ "",
61
+ `## Available Component Types`,
62
+ registryDesc,
63
+ "",
64
+ `## ComponentLayer format`,
65
+ layerFormat
66
+ ].join("\n").length + 30;
67
+ const budget = Math.max(0, 16e3 - overhead);
68
+ const truncatedLayers = layersJson.length > budget ? layersJson.slice(0, budget) + "\n...(truncated)" : layersJson;
69
+ return [
70
+ header,
71
+ "",
72
+ `## Current Layers (${layers.length})`,
73
+ truncatedLayers,
74
+ "",
75
+ `## Available Component Types`,
76
+ registryDesc,
77
+ "",
78
+ `## ComponentLayer format`,
79
+ layerFormat
80
+ ].join("\n");
81
+ }
19
82
  function slugify(str) {
20
83
  return str.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
21
84
  }
@@ -72,6 +135,32 @@ function PageBuilderPageContent({
72
135
  const [layers, setLayers] = React.useState(existingLayers);
73
136
  const [variables, setVariables] = React.useState(existingVariables);
74
137
  const [autoSlug, setAutoSlug] = React.useState(!id);
138
+ context$1.useRegisterPageAIContext({
139
+ routeName: id ? "ui-builder-edit-page" : "ui-builder-new-page",
140
+ pageDescription: buildPageDescription(id, slug, layers, componentRegistry),
141
+ suggestions: [
142
+ "Add a hero section",
143
+ "Add a 3-column feature grid",
144
+ "Make the layout full-width",
145
+ "Add a card with a title, description, and button",
146
+ "Replace the layout with a centered single-column design"
147
+ ],
148
+ clientTools: {
149
+ updatePageLayers: async ({ layers: newLayers }) => {
150
+ const store = layerStore.useLayerStore.getState();
151
+ store.initialize(
152
+ newLayers,
153
+ store.selectedPageId || newLayers[0]?.id,
154
+ void 0,
155
+ store.variables
156
+ );
157
+ return {
158
+ success: true,
159
+ message: `Applied ${newLayers.length} layer(s) to the page`
160
+ };
161
+ }
162
+ }
163
+ });
75
164
  const handleLayersChange = React.useCallback(
76
165
  (newLayers) => {
77
166
  setLayers(newLayers);
@@ -10,10 +10,73 @@ import { Label } from '../../../../../../../ui/src/components/label.mjs';
10
10
  import { ArrowLeft, Settings2, Save } from 'lucide-react';
11
11
  import { toast } from 'sonner';
12
12
  import UIBuilder from '../../../../../../../ui/src/components/ui-builder/index.mjs';
13
+ import { useLayerStore } from '../../../../../../../ui/src/lib/ui-builder/store/layer-store.mjs';
14
+ import { useRegisterPageAIContext } from '@btst/stack/plugins/ai-chat/client/context';
13
15
  import { useSuspenseUIBuilderPage, useCreateUIBuilderPage, useUpdateUIBuilderPage } from '../../hooks/ui-builder-hooks.mjs';
14
16
  import { uiBuilderLocalization } from '../../localization/index.mjs';
15
17
  import { defaultComponentRegistry } from '../../registry.mjs';
16
18
 
19
+ function buildRegistryDescription(registry) {
20
+ const lines = [];
21
+ for (const [name, entry] of Object.entries(registry)) {
22
+ let propsLine = "";
23
+ try {
24
+ const shape = entry.schema?.shape;
25
+ if (shape) {
26
+ const fields = Object.keys(shape).join(", ");
27
+ propsLine = ` \u2014 props: ${fields}`;
28
+ }
29
+ } catch {
30
+ }
31
+ lines.push(`- ${name}${propsLine}`);
32
+ }
33
+ return lines.join("\n");
34
+ }
35
+ function buildPageDescription(id, slug, layers, registry) {
36
+ const header = id ? `UI Builder \u2014 editing page (slug: "${slug}")` : "UI Builder \u2014 creating new page";
37
+ const layersJson = JSON.stringify(layers, null, 2);
38
+ const registryDesc = buildRegistryDescription(registry);
39
+ const layerFormat = `Each layer: { id: string, type: string, name: string, props: Record<string,any>, children?: ComponentLayer[] | string }`;
40
+ const full = [
41
+ header,
42
+ "",
43
+ `## Current Layers (${layers.length})`,
44
+ layersJson,
45
+ "",
46
+ `## Available Component Types`,
47
+ registryDesc,
48
+ "",
49
+ `## ComponentLayer format`,
50
+ layerFormat
51
+ ].join("\n");
52
+ if (full.length <= 16e3) return full;
53
+ const overhead = [
54
+ header,
55
+ "",
56
+ `## Current Layers (${layers.length})`,
57
+ "",
58
+ "",
59
+ `## Available Component Types`,
60
+ registryDesc,
61
+ "",
62
+ `## ComponentLayer format`,
63
+ layerFormat
64
+ ].join("\n").length + 30;
65
+ const budget = Math.max(0, 16e3 - overhead);
66
+ const truncatedLayers = layersJson.length > budget ? layersJson.slice(0, budget) + "\n...(truncated)" : layersJson;
67
+ return [
68
+ header,
69
+ "",
70
+ `## Current Layers (${layers.length})`,
71
+ truncatedLayers,
72
+ "",
73
+ `## Available Component Types`,
74
+ registryDesc,
75
+ "",
76
+ `## ComponentLayer format`,
77
+ layerFormat
78
+ ].join("\n");
79
+ }
17
80
  function slugify(str) {
18
81
  return str.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
19
82
  }
@@ -70,6 +133,32 @@ function PageBuilderPageContent({
70
133
  const [layers, setLayers] = useState(existingLayers);
71
134
  const [variables, setVariables] = useState(existingVariables);
72
135
  const [autoSlug, setAutoSlug] = useState(!id);
136
+ useRegisterPageAIContext({
137
+ routeName: id ? "ui-builder-edit-page" : "ui-builder-new-page",
138
+ pageDescription: buildPageDescription(id, slug, layers, componentRegistry),
139
+ suggestions: [
140
+ "Add a hero section",
141
+ "Add a 3-column feature grid",
142
+ "Make the layout full-width",
143
+ "Add a card with a title, description, and button",
144
+ "Replace the layout with a centered single-column design"
145
+ ],
146
+ clientTools: {
147
+ updatePageLayers: async ({ layers: newLayers }) => {
148
+ const store = useLayerStore.getState();
149
+ store.initialize(
150
+ newLayers,
151
+ store.selectedPageId || newLayers[0]?.id,
152
+ void 0,
153
+ store.variables
154
+ );
155
+ return {
156
+ success: true,
157
+ message: `Applied ${newLayers.length} layer(s) to the page`
158
+ };
159
+ }
160
+ }
161
+ });
73
162
  const handleLayersChange = useCallback(
74
163
  (newLayers) => {
75
164
  setLayers(newLayers);
@@ -2,6 +2,11 @@
2
2
 
3
3
  const client = require('better-call/client');
4
4
 
5
+ function isConnectionError(err) {
6
+ if (!(err instanceof Error)) return false;
7
+ const code = err.cause?.code ?? err.code;
8
+ return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
9
+ }
5
10
  function createApiClient(options) {
6
11
  const { baseURL = "", basePath = "/" } = options ?? {};
7
12
  const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
@@ -14,3 +19,4 @@ function createApiClient(options) {
14
19
  }
15
20
 
16
21
  exports.createApiClient = createApiClient;
22
+ exports.isConnectionError = isConnectionError;
@@ -1,5 +1,10 @@
1
1
  import { createClient } from 'better-call/client';
2
2
 
3
+ function isConnectionError(err) {
4
+ if (!(err instanceof Error)) return false;
5
+ const code = err.cause?.code ?? err.code;
6
+ return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed") || err.message.includes("ERR_CONNECTION_REFUSED") || code === "ECONNREFUSED" || code === "ERR_CONNECTION_REFUSED";
7
+ }
3
8
  function createApiClient(options) {
4
9
  const { baseURL = "", basePath = "/" } = options ?? {};
5
10
  const normalizedBaseURL = baseURL ? baseURL.replace(/\/$/, "") : "";
@@ -11,4 +16,4 @@ function createApiClient(options) {
11
16
  });
12
17
  }
13
18
 
14
- export { createApiClient };
19
+ export { createApiClient, isConnectionError };
@@ -1,4 +1,4 @@
1
- export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.CMh_EdxW.cjs';
1
+ export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.DWoCZff7.cjs';
2
2
  import { Adapter } from '@btst/db';
3
3
  import { C as Conversation, M as Message } from '../../../shared/stack.Be1QIHEn.cjs';
4
4
  import '@tanstack/react-query';
@@ -1,4 +1,4 @@
1
- export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.Dg09R0oB.mjs';
1
+ export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.DTDxgFj8.mjs';
2
2
  import { Adapter } from '@btst/db';
3
3
  import { C as Conversation, M as Message } from '../../../shared/stack.Be1QIHEn.mjs';
4
4
  import '@tanstack/react-query';
@@ -1,4 +1,4 @@
1
- export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.BeSm90va.js';
1
+ export { e as AiChatApiRouter, b as AiChatBackendConfig, A as AiChatBackendHooks, a as AiChatMode, C as ChatApiContext, d as aiChatBackendPlugin, c as createAiChatQueryKeys } from '../../../shared/stack.BEn34wW6.js';
2
2
  import { Adapter } from '@btst/db';
3
3
  import { C as Conversation, M as Message } from '../../../shared/stack.Be1QIHEn.js';
4
4
  import '@tanstack/react-query';
@@ -1,4 +1,4 @@
1
- export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.DaOcgmrM.cjs';
1
+ export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.BV9hnvu4.cjs';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { FallbackProps } from 'react-error-boundary';
4
4
  import 'ai';
@@ -1,4 +1,4 @@
1
- export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.DaOcgmrM.mjs';
1
+ export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.BV9hnvu4.mjs';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { FallbackProps } from 'react-error-boundary';
4
4
  import 'ai';
@@ -1,4 +1,4 @@
1
- export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.DaOcgmrM.js';
1
+ export { i as ChatInput, C as ChatInterface, e as ChatLayout, f as ChatLayoutProps, h as ChatMessage, g as ChatSidebar, j as ToolCallDisplay } from '../../../../shared/stack.BV9hnvu4.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { FallbackProps } from 'react-error-boundary';
4
4
  import 'ai';
@@ -0,0 +1,92 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ const jsxRuntime = require('react/jsx-runtime');
5
+ const React = require('react');
6
+
7
+ const PageAIAPIContext = React.createContext(null);
8
+ const PageAIVersionContext = React.createContext(0);
9
+ function PageAIContextProvider({
10
+ children
11
+ }) {
12
+ const registrationsRef = React.useRef(/* @__PURE__ */ new Map());
13
+ const insertionOrderRef = React.useRef([]);
14
+ const [version, setVersion] = React.useState(0);
15
+ const bumpVersion = React.useCallback(() => setVersion((v) => v + 1), []);
16
+ const register = React.useCallback(
17
+ (id, config) => {
18
+ registrationsRef.current.set(id, config);
19
+ insertionOrderRef.current = insertionOrderRef.current.filter(
20
+ (k) => k !== id
21
+ );
22
+ insertionOrderRef.current.push(id);
23
+ bumpVersion();
24
+ },
25
+ [bumpVersion]
26
+ );
27
+ const unregister = React.useCallback(
28
+ (id) => {
29
+ registrationsRef.current.delete(id);
30
+ insertionOrderRef.current = insertionOrderRef.current.filter(
31
+ (k) => k !== id
32
+ );
33
+ bumpVersion();
34
+ },
35
+ [bumpVersion]
36
+ );
37
+ const getActive = React.useCallback(() => {
38
+ const order = insertionOrderRef.current;
39
+ if (order.length === 0) return null;
40
+ const lastId = order[order.length - 1];
41
+ if (!lastId) return null;
42
+ return registrationsRef.current.get(lastId) ?? null;
43
+ }, []);
44
+ const api = React.useMemo(
45
+ () => ({ register, unregister, getActive }),
46
+ [register, unregister, getActive]
47
+ );
48
+ return /* @__PURE__ */ jsxRuntime.jsx(PageAIAPIContext.Provider, { value: api, children: /* @__PURE__ */ jsxRuntime.jsx(PageAIVersionContext.Provider, { value: version, children }) });
49
+ }
50
+ function useRegisterPageAIContext(config) {
51
+ const ctx = React.useContext(PageAIAPIContext);
52
+ const id = React.useId();
53
+ const configRef = React.useRef(config);
54
+ configRef.current = config;
55
+ React.useEffect(() => {
56
+ if (!ctx || !configRef.current) return;
57
+ ctx.register(id, {
58
+ get routeName() {
59
+ return configRef.current?.routeName ?? "";
60
+ },
61
+ get pageDescription() {
62
+ return configRef.current?.pageDescription ?? "";
63
+ },
64
+ get suggestions() {
65
+ return configRef.current?.suggestions;
66
+ },
67
+ get clientTools() {
68
+ return configRef.current?.clientTools;
69
+ }
70
+ });
71
+ return () => {
72
+ ctx.unregister(id);
73
+ };
74
+ }, [
75
+ ctx,
76
+ id,
77
+ config === null,
78
+ config?.routeName,
79
+ config?.pageDescription,
80
+ JSON.stringify(config?.suggestions)
81
+ ]);
82
+ }
83
+ function usePageAIContext() {
84
+ React.useContext(PageAIVersionContext);
85
+ const ctx = React.useContext(PageAIAPIContext);
86
+ if (!ctx) return null;
87
+ return ctx.getActive();
88
+ }
89
+
90
+ exports.PageAIContextProvider = PageAIContextProvider;
91
+ exports.usePageAIContext = usePageAIContext;
92
+ exports.useRegisterPageAIContext = useRegisterPageAIContext;
@@ -0,0 +1,84 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * A client-side tool handler — receives the AI's tool call args and returns a result.
5
+ * The result is sent back to the model so it can continue the conversation.
6
+ */
7
+ type PageAIClientTool = (args: any) => Promise<{
8
+ success: boolean;
9
+ message?: string;
10
+ }>;
11
+ /**
12
+ * Configuration registered by a page to provide AI context and capabilities.
13
+ * Any component in the tree can call useRegisterPageAIContext with this config.
14
+ */
15
+ interface PageAIContextConfig {
16
+ /**
17
+ * Identifier for the current route/page (e.g. "blog-post", "ui-builder-edit-page").
18
+ * Shown as a badge in the chat header.
19
+ */
20
+ routeName: string;
21
+ /**
22
+ * Human-readable description of the current page and its content.
23
+ * Injected into the AI system prompt so it understands what the user is looking at.
24
+ * Capped at 8,000 characters server-side.
25
+ */
26
+ pageDescription: string;
27
+ /**
28
+ * Optional suggested prompts shown as quick-action chips in the chat empty state.
29
+ * These augment (not replace) any static suggestions configured in plugin overrides.
30
+ */
31
+ suggestions?: string[];
32
+ /**
33
+ * Client-side tool handlers keyed by tool name.
34
+ * When the AI calls a tool by this name, the handler is invoked with the tool args.
35
+ * The result is sent back to the model via addToolResult.
36
+ *
37
+ * Tool schemas must be registered server-side via enablePageTools + clientToolSchemas
38
+ * in aiChatBackendPlugin (built-in tools like fillBlogForm are pre-registered).
39
+ */
40
+ clientTools?: Record<string, PageAIClientTool>;
41
+ }
42
+ /**
43
+ * Provider that enables route-aware AI context across the app.
44
+ *
45
+ * Place this at the root layout — above all StackProviders — so it spans
46
+ * both your main app tree and any chat modals rendered as parallel/intercept routes.
47
+ *
48
+ * @example
49
+ * // app/layout.tsx
50
+ * import { PageAIContextProvider } from "@btst/stack/plugins/ai-chat/client/context"
51
+ *
52
+ * export default function RootLayout({ children }) {
53
+ * return <PageAIContextProvider>{children}</PageAIContextProvider>
54
+ * }
55
+ */
56
+ declare function PageAIContextProvider({ children, }: {
57
+ children: React.ReactNode;
58
+ }): react_jsx_runtime.JSX.Element;
59
+ /**
60
+ * Register page AI context from any component.
61
+ * The registration is cleaned up automatically when the component unmounts.
62
+ *
63
+ * Pass `null` to conditionally disable context (e.g. while data is loading).
64
+ *
65
+ * @example
66
+ * // Blog post page
67
+ * useRegisterPageAIContext(post ? {
68
+ * routeName: "blog-post",
69
+ * pageDescription: `Blog post: "${post.title}"\n\n${post.content?.slice(0, 16000)}`,
70
+ * suggestions: ["Summarize this post", "What are the key takeaways?"],
71
+ * } : null)
72
+ */
73
+ declare function useRegisterPageAIContext(config: PageAIContextConfig | null): void;
74
+ /**
75
+ * Read the currently active page AI context.
76
+ * Returns null when no page has registered context, or when PageAIContextProvider
77
+ * is not in the tree.
78
+ *
79
+ * Used internally by ChatInterface to inject context into requests.
80
+ */
81
+ declare function usePageAIContext(): PageAIContextConfig | null;
82
+
83
+ export { PageAIContextProvider, usePageAIContext, useRegisterPageAIContext };
84
+ export type { PageAIClientTool, PageAIContextConfig };
@@ -0,0 +1,84 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ /**
4
+ * A client-side tool handler — receives the AI's tool call args and returns a result.
5
+ * The result is sent back to the model so it can continue the conversation.
6
+ */
7
+ type PageAIClientTool = (args: any) => Promise<{
8
+ success: boolean;
9
+ message?: string;
10
+ }>;
11
+ /**
12
+ * Configuration registered by a page to provide AI context and capabilities.
13
+ * Any component in the tree can call useRegisterPageAIContext with this config.
14
+ */
15
+ interface PageAIContextConfig {
16
+ /**
17
+ * Identifier for the current route/page (e.g. "blog-post", "ui-builder-edit-page").
18
+ * Shown as a badge in the chat header.
19
+ */
20
+ routeName: string;
21
+ /**
22
+ * Human-readable description of the current page and its content.
23
+ * Injected into the AI system prompt so it understands what the user is looking at.
24
+ * Capped at 8,000 characters server-side.
25
+ */
26
+ pageDescription: string;
27
+ /**
28
+ * Optional suggested prompts shown as quick-action chips in the chat empty state.
29
+ * These augment (not replace) any static suggestions configured in plugin overrides.
30
+ */
31
+ suggestions?: string[];
32
+ /**
33
+ * Client-side tool handlers keyed by tool name.
34
+ * When the AI calls a tool by this name, the handler is invoked with the tool args.
35
+ * The result is sent back to the model via addToolResult.
36
+ *
37
+ * Tool schemas must be registered server-side via enablePageTools + clientToolSchemas
38
+ * in aiChatBackendPlugin (built-in tools like fillBlogForm are pre-registered).
39
+ */
40
+ clientTools?: Record<string, PageAIClientTool>;
41
+ }
42
+ /**
43
+ * Provider that enables route-aware AI context across the app.
44
+ *
45
+ * Place this at the root layout — above all StackProviders — so it spans
46
+ * both your main app tree and any chat modals rendered as parallel/intercept routes.
47
+ *
48
+ * @example
49
+ * // app/layout.tsx
50
+ * import { PageAIContextProvider } from "@btst/stack/plugins/ai-chat/client/context"
51
+ *
52
+ * export default function RootLayout({ children }) {
53
+ * return <PageAIContextProvider>{children}</PageAIContextProvider>
54
+ * }
55
+ */
56
+ declare function PageAIContextProvider({ children, }: {
57
+ children: React.ReactNode;
58
+ }): react_jsx_runtime.JSX.Element;
59
+ /**
60
+ * Register page AI context from any component.
61
+ * The registration is cleaned up automatically when the component unmounts.
62
+ *
63
+ * Pass `null` to conditionally disable context (e.g. while data is loading).
64
+ *
65
+ * @example
66
+ * // Blog post page
67
+ * useRegisterPageAIContext(post ? {
68
+ * routeName: "blog-post",
69
+ * pageDescription: `Blog post: "${post.title}"\n\n${post.content?.slice(0, 16000)}`,
70
+ * suggestions: ["Summarize this post", "What are the key takeaways?"],
71
+ * } : null)
72
+ */
73
+ declare function useRegisterPageAIContext(config: PageAIContextConfig | null): void;
74
+ /**
75
+ * Read the currently active page AI context.
76
+ * Returns null when no page has registered context, or when PageAIContextProvider
77
+ * is not in the tree.
78
+ *
79
+ * Used internally by ChatInterface to inject context into requests.
80
+ */
81
+ declare function usePageAIContext(): PageAIContextConfig | null;
82
+
83
+ export { PageAIContextProvider, usePageAIContext, useRegisterPageAIContext };
84
+ export type { PageAIClientTool, PageAIContextConfig };