@btst/stack 1.3.0 → 1.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 (241) hide show
  1. package/README.md +85 -37
  2. package/dist/node_modules/.pnpm/{@radix-ui_react-alert-dialog@1.1.15_@types_react-dom@19.2.2_@types_react@19.2.2__@types_ec789942cd38340bd7362c09e7d34384 → @radix-ui_react-alert-dialog@1.1.15_@types_react-dom@19.2.3_@types_react@19.2.6__@types_4f58c757aa677e233cf96d60fda2f1da}/node_modules/@radix-ui/react-alert-dialog/dist/index.cjs +2 -2
  3. package/dist/node_modules/.pnpm/{@radix-ui_react-alert-dialog@1.1.15_@types_react-dom@19.2.2_@types_react@19.2.2__@types_ec789942cd38340bd7362c09e7d34384 → @radix-ui_react-alert-dialog@1.1.15_@types_react-dom@19.2.3_@types_react@19.2.6__@types_4f58c757aa677e233cf96d60fda2f1da}/node_modules/@radix-ui/react-alert-dialog/dist/index.mjs +2 -2
  4. package/dist/node_modules/.pnpm/{@radix-ui_react-arrow@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@1_9e04309f365863673e44407648bb0cb6 → @radix-ui_react-arrow@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_35df44f6d87656c1401686c91d770dbb}/node_modules/@radix-ui/react-arrow/dist/index.cjs +1 -1
  5. package/dist/node_modules/.pnpm/{@radix-ui_react-arrow@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@1_9e04309f365863673e44407648bb0cb6 → @radix-ui_react-arrow@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_35df44f6d87656c1401686c91d770dbb}/node_modules/@radix-ui/react-arrow/dist/index.mjs +1 -1
  6. package/dist/node_modules/.pnpm/{@radix-ui_react-collection@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_re_6d7c277722b3619c9ee7e64e9a822c45 → @radix-ui_react-collection@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_re_59aa5e150e70a3e7bfb1567148b021b5}/node_modules/@radix-ui/react-collection/dist/index.cjs +2 -2
  7. package/dist/node_modules/.pnpm/{@radix-ui_react-collection@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_re_6d7c277722b3619c9ee7e64e9a822c45 → @radix-ui_react-collection@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_re_59aa5e150e70a3e7bfb1567148b021b5}/node_modules/@radix-ui/react-collection/dist/index.mjs +2 -2
  8. package/dist/node_modules/.pnpm/{@radix-ui_react-dismissable-layer@1.1.11_@types_react-dom@19.2.2_@types_react@19.2.2__@_ca5522e5d45d4722cb9eb5ce53defa61 → @radix-ui_react-dismissable-layer@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@_9ee1db7daf927866cf505b31d40047ad}/node_modules/@radix-ui/react-dismissable-layer/dist/index.cjs +4 -4
  9. package/dist/node_modules/.pnpm/{@radix-ui_react-dismissable-layer@1.1.11_@types_react-dom@19.2.2_@types_react@19.2.2__@_ca5522e5d45d4722cb9eb5ce53defa61 → @radix-ui_react-dismissable-layer@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@_9ee1db7daf927866cf505b31d40047ad}/node_modules/@radix-ui/react-dismissable-layer/dist/index.mjs +4 -4
  10. package/dist/node_modules/.pnpm/@radix-ui_react-dropdown-menu@2.1.16_@types_react-dom@19.2.3_@types_react@19.2.6__@type_a50051c7210b6fbd5be09388bda08578/node_modules/@radix-ui/react-dropdown-menu/dist/index.cjs +282 -0
  11. package/dist/node_modules/.pnpm/@radix-ui_react-dropdown-menu@2.1.16_@types_react-dom@19.2.3_@types_react@19.2.6__@type_a50051c7210b6fbd5be09388bda08578/node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs +247 -0
  12. package/dist/node_modules/.pnpm/{@radix-ui_react-focus-scope@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_r_93de389b3f622f9f764acc8e59ec80c0 → @radix-ui_react-focus-scope@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_r_0a31b7f987af9482d13505312e1a1be9}/node_modules/@radix-ui/react-focus-scope/dist/index.cjs +3 -3
  13. package/dist/node_modules/.pnpm/{@radix-ui_react-focus-scope@1.1.7_@types_react-dom@19.2.2_@types_react@19.2.2__@types_r_93de389b3f622f9f764acc8e59ec80c0 → @radix-ui_react-focus-scope@1.1.7_@types_react-dom@19.2.3_@types_react@19.2.6__@types_r_0a31b7f987af9482d13505312e1a1be9}/node_modules/@radix-ui/react-focus-scope/dist/index.mjs +3 -3
  14. package/dist/node_modules/.pnpm/{@radix-ui_react-id@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-id@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-id/dist/index.cjs +1 -1
  15. package/dist/node_modules/.pnpm/{@radix-ui_react-id@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-id@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-id/dist/index.mjs +1 -1
  16. package/dist/node_modules/.pnpm/@radix-ui_react-menu@2.1.16_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_82ed1fcd848b6984d9291a784d477cf4/node_modules/@radix-ui/react-menu/dist/index.cjs +845 -0
  17. package/dist/node_modules/.pnpm/@radix-ui_react-menu@2.1.16_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@1_82ed1fcd848b6984d9291a784d477cf4/node_modules/@radix-ui/react-menu/dist/index.mjs +799 -0
  18. package/dist/node_modules/.pnpm/{@radix-ui_react-popper@1.2.8_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_d6285b8269ea5d6b59b300f5be279a0c → @radix-ui_react-popper@1.2.8_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_7ac2caae1e39f9ba93d5015614525161}/node_modules/@radix-ui/react-popper/dist/index.cjs +7 -7
  19. package/dist/node_modules/.pnpm/{@radix-ui_react-popper@1.2.8_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_d6285b8269ea5d6b59b300f5be279a0c → @radix-ui_react-popper@1.2.8_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_7ac2caae1e39f9ba93d5015614525161}/node_modules/@radix-ui/react-popper/dist/index.mjs +7 -7
  20. package/dist/node_modules/.pnpm/{@radix-ui_react-portal@1.1.9_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_478b3d5dd4afab1a3dcce7ed1748cb95 → @radix-ui_react-portal@1.1.9_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_1bb4e0f97f86496802d28a2e74e2a8b9}/node_modules/@radix-ui/react-portal/dist/index.cjs +2 -2
  21. package/dist/node_modules/.pnpm/{@radix-ui_react-portal@1.1.9_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_478b3d5dd4afab1a3dcce7ed1748cb95 → @radix-ui_react-portal@1.1.9_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_1bb4e0f97f86496802d28a2e74e2a8b9}/node_modules/@radix-ui/react-portal/dist/index.mjs +2 -2
  22. package/dist/node_modules/.pnpm/@radix-ui_react-presence@1.1.5_@types_react-dom@19.2.3_@types_react@19.2.6__@types_reac_90f8e5c12233caef3399d5fd66452a13/node_modules/@radix-ui/react-presence/dist/index.cjs +147 -0
  23. package/dist/node_modules/.pnpm/@radix-ui_react-presence@1.1.5_@types_react-dom@19.2.3_@types_react@19.2.6__@types_reac_90f8e5c12233caef3399d5fd66452a13/node_modules/@radix-ui/react-presence/dist/index.mjs +131 -0
  24. package/dist/node_modules/.pnpm/@radix-ui_react-roving-focus@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@types_fe1151d1f393bbc1072b24a86dff3a23/node_modules/@radix-ui/react-roving-focus/dist/index.cjs +244 -0
  25. package/dist/node_modules/.pnpm/@radix-ui_react-roving-focus@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@types_fe1151d1f393bbc1072b24a86dff3a23/node_modules/@radix-ui/react-roving-focus/dist/index.mjs +224 -0
  26. package/dist/node_modules/.pnpm/@radix-ui_react-scroll-area@1.2.10_@types_react-dom@19.2.3_@types_react@19.2.6__@types__e3f7735e9b444a10b3bbfd9fe97d44d0/node_modules/@radix-ui/react-scroll-area/dist/index.cjs +742 -0
  27. package/dist/node_modules/.pnpm/@radix-ui_react-scroll-area@1.2.10_@types_react-dom@19.2.3_@types_react@19.2.6__@types__e3f7735e9b444a10b3bbfd9fe97d44d0/node_modules/@radix-ui/react-scroll-area/dist/index.mjs +719 -0
  28. package/dist/node_modules/.pnpm/{@radix-ui_react-select@2.2.6_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_802c3d414c85063bee785fcc98a39c07 → @radix-ui_react-select@2.2.6_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_38dc681bb1f2bcfeb5249d8ca2bc01f5}/node_modules/@radix-ui/react-select/dist/index.cjs +17 -17
  29. package/dist/node_modules/.pnpm/{@radix-ui_react-select@2.2.6_@types_react-dom@19.2.2_@types_react@19.2.2__@types_react@_802c3d414c85063bee785fcc98a39c07 → @radix-ui_react-select@2.2.6_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react@_38dc681bb1f2bcfeb5249d8ca2bc01f5}/node_modules/@radix-ui/react-select/dist/index.mjs +17 -17
  30. package/dist/node_modules/.pnpm/{@radix-ui_react-use-controllable-state@1.2.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-controllable-state@1.2.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-controllable-state/dist/index.cjs +1 -1
  31. package/dist/node_modules/.pnpm/{@radix-ui_react-use-controllable-state@1.2.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-controllable-state@1.2.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-controllable-state/dist/index.mjs +1 -1
  32. package/dist/node_modules/.pnpm/{@radix-ui_react-use-escape-keydown@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-escape-keydown@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-escape-keydown/dist/index.cjs +1 -1
  33. package/dist/node_modules/.pnpm/{@radix-ui_react-use-escape-keydown@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-escape-keydown@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-escape-keydown/dist/index.mjs +1 -1
  34. package/dist/node_modules/.pnpm/{@radix-ui_react-use-size@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-size@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-size/dist/index.cjs +1 -1
  35. package/dist/node_modules/.pnpm/{@radix-ui_react-use-size@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-size@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-size/dist/index.mjs +1 -1
  36. package/dist/node_modules/.pnpm/{@radix-ui_react-visually-hidden@1.2.3_@types_react-dom@19.2.2_@types_react@19.2.2__@typ_a84e98a44624c31e835a98d4b8b0c30d → @radix-ui_react-visually-hidden@1.2.3_@types_react-dom@19.2.3_@types_react@19.2.6__@typ_f453379bbd5a4932ec515167f81be42a}/node_modules/@radix-ui/react-visually-hidden/dist/index.cjs +1 -1
  37. package/dist/node_modules/.pnpm/{@radix-ui_react-visually-hidden@1.2.3_@types_react-dom@19.2.2_@types_react@19.2.2__@typ_a84e98a44624c31e835a98d4b8b0c30d → @radix-ui_react-visually-hidden@1.2.3_@types_react-dom@19.2.3_@types_react@19.2.6__@typ_f453379bbd5a4932ec515167f81be42a}/node_modules/@radix-ui/react-visually-hidden/dist/index.mjs +1 -1
  38. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/component.cjs +1 -1
  39. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/component.mjs +1 -1
  40. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/SideEffect.cjs +2 -2
  41. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/SideEffect.mjs +2 -2
  42. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/UI.cjs +2 -2
  43. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/UI.mjs +2 -2
  44. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/medium.cjs +1 -1
  45. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/medium.mjs +1 -1
  46. package/dist/node_modules/.pnpm/react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0/node_modules/react-remove-scroll/dist/es2015/sidecar.cjs +9 -0
  47. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/sidecar.mjs +1 -1
  48. package/dist/packages/better-stack/src/plugins/ai-chat/api/plugin.cjs +610 -0
  49. package/dist/packages/better-stack/src/plugins/ai-chat/api/plugin.mjs +608 -0
  50. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-input.cjs +221 -0
  51. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-input.mjs +219 -0
  52. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-interface.cjs +315 -0
  53. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-interface.mjs +313 -0
  54. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-layout.cjs +122 -0
  55. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-layout.mjs +120 -0
  56. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-message.cjs +397 -0
  57. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-message.mjs +391 -0
  58. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +227 -0
  59. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +225 -0
  60. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.cjs +31 -0
  61. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.mjs +29 -0
  62. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/index.cjs +11 -0
  63. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/index.mjs +8 -0
  64. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/404-page.cjs +18 -0
  65. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/404-page.mjs +16 -0
  66. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.cjs +39 -0
  67. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.cjs +22 -0
  68. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.mjs +20 -0
  69. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.mjs +37 -0
  70. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/default-error.cjs +18 -0
  71. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/default-error.mjs +16 -0
  72. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/error-placeholder.cjs +26 -0
  73. package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/error-placeholder.mjs +24 -0
  74. package/dist/packages/better-stack/src/plugins/ai-chat/client/hooks/chat-hooks.cjs +199 -0
  75. package/dist/packages/better-stack/src/plugins/ai-chat/client/hooks/chat-hooks.mjs +191 -0
  76. package/dist/packages/better-stack/src/plugins/ai-chat/client/localization/index.cjs +63 -0
  77. package/dist/packages/better-stack/src/plugins/ai-chat/client/localization/index.mjs +61 -0
  78. package/dist/packages/better-stack/src/plugins/ai-chat/client/overrides.cjs +14 -0
  79. package/dist/packages/better-stack/src/plugins/ai-chat/client/overrides.mjs +11 -0
  80. package/dist/packages/better-stack/src/plugins/ai-chat/client/plugin.cjs +241 -0
  81. package/dist/packages/better-stack/src/plugins/ai-chat/client/plugin.mjs +239 -0
  82. package/dist/packages/better-stack/src/plugins/ai-chat/db.cjs +65 -0
  83. package/dist/packages/better-stack/src/plugins/ai-chat/db.mjs +63 -0
  84. package/dist/packages/better-stack/src/plugins/ai-chat/schemas.cjs +42 -0
  85. package/dist/packages/better-stack/src/plugins/ai-chat/schemas.mjs +38 -0
  86. package/dist/packages/better-stack/src/plugins/blog/api/plugin.cjs +8 -2
  87. package/dist/packages/better-stack/src/plugins/blog/api/plugin.mjs +8 -2
  88. package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.cjs +1 -1
  89. package/dist/packages/better-stack/src/plugins/blog/client/components/pages/post-page.internal.mjs +1 -1
  90. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/markdown-content.cjs +12 -309
  91. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/markdown-content.mjs +13 -303
  92. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.cjs +1 -1
  93. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/on-this-page.mjs +1 -1
  94. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/page-wrapper.cjs +2 -2
  95. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/page-wrapper.mjs +2 -2
  96. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/recent-posts-carousel.cjs +2 -2
  97. package/dist/packages/better-stack/src/plugins/blog/client/components/shared/recent-posts-carousel.mjs +2 -2
  98. package/dist/packages/ui/src/components/alert-dialog.cjs +1 -1
  99. package/dist/packages/ui/src/components/alert-dialog.mjs +1 -1
  100. package/dist/packages/{better-stack/src/plugins/blog/client/components/shared/better-blog-attribution.cjs → ui/src/components/better-stack-attribution.cjs} +3 -3
  101. package/dist/packages/{better-stack/src/plugins/blog/client/components/shared/better-blog-attribution.mjs → ui/src/components/better-stack-attribution.mjs} +3 -3
  102. package/dist/packages/ui/src/components/dialog.cjs +14 -0
  103. package/dist/packages/ui/src/components/dialog.mjs +14 -1
  104. package/dist/packages/ui/src/components/dropdown-menu.cjs +67 -0
  105. package/dist/packages/ui/src/components/dropdown-menu.mjs +62 -0
  106. package/dist/packages/ui/src/components/markdown-content.cjs +306 -0
  107. package/dist/packages/ui/src/components/markdown-content.mjs +297 -0
  108. package/dist/packages/ui/src/components/scroll-area.cjs +63 -0
  109. package/dist/packages/ui/src/components/scroll-area.mjs +60 -0
  110. package/dist/packages/ui/src/components/select.cjs +1 -1
  111. package/dist/packages/ui/src/components/select.mjs +1 -1
  112. package/dist/packages/ui/src/components/sheet.cjs +87 -0
  113. package/dist/packages/ui/src/components/sheet.mjs +69 -0
  114. package/dist/plugins/ai-chat/api/index.cjs +9 -0
  115. package/dist/plugins/ai-chat/api/index.d.cts +9 -0
  116. package/dist/plugins/ai-chat/api/index.d.mts +9 -0
  117. package/dist/plugins/ai-chat/api/index.d.ts +9 -0
  118. package/dist/plugins/ai-chat/api/index.mjs +2 -0
  119. package/dist/plugins/ai-chat/client/components/index.cjs +27 -0
  120. package/dist/plugins/ai-chat/client/components/index.d.cts +30 -0
  121. package/dist/plugins/ai-chat/client/components/index.d.mts +30 -0
  122. package/dist/plugins/ai-chat/client/components/index.d.ts +30 -0
  123. package/dist/plugins/ai-chat/client/components/index.mjs +11 -0
  124. package/dist/plugins/ai-chat/client/hooks/index.cjs +13 -0
  125. package/dist/plugins/ai-chat/client/hooks/index.d.cts +98 -0
  126. package/dist/plugins/ai-chat/client/hooks/index.d.mts +98 -0
  127. package/dist/plugins/ai-chat/client/hooks/index.d.ts +98 -0
  128. package/dist/plugins/ai-chat/client/hooks/index.mjs +1 -0
  129. package/dist/plugins/ai-chat/client/index.cjs +19 -0
  130. package/dist/plugins/ai-chat/client/index.d.cts +327 -0
  131. package/dist/plugins/ai-chat/client/index.d.mts +327 -0
  132. package/dist/plugins/ai-chat/client/index.d.ts +327 -0
  133. package/dist/plugins/ai-chat/client/index.mjs +7 -0
  134. package/dist/plugins/ai-chat/client.css +6 -0
  135. package/dist/plugins/ai-chat/query-keys.cjs +60 -0
  136. package/dist/plugins/ai-chat/query-keys.d.cts +478 -0
  137. package/dist/plugins/ai-chat/query-keys.d.mts +478 -0
  138. package/dist/plugins/ai-chat/query-keys.d.ts +478 -0
  139. package/dist/plugins/ai-chat/query-keys.mjs +58 -0
  140. package/dist/plugins/ai-chat/style.css +19 -0
  141. package/dist/plugins/blog/api/index.d.cts +1 -1
  142. package/dist/plugins/blog/api/index.d.mts +1 -1
  143. package/dist/plugins/blog/api/index.d.ts +1 -1
  144. package/dist/plugins/blog/client/components/shared/markdown-content-styles.css +85 -62
  145. package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
  146. package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
  147. package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
  148. package/dist/plugins/blog/client/index.d.cts +1 -1
  149. package/dist/plugins/blog/client/index.d.mts +1 -1
  150. package/dist/plugins/blog/client/index.d.ts +1 -1
  151. package/dist/plugins/blog/query-keys.d.cts +2 -2
  152. package/dist/plugins/blog/query-keys.d.mts +2 -2
  153. package/dist/plugins/blog/query-keys.d.ts +2 -2
  154. package/dist/shared/stack.Be1QIHEn.d.cts +23 -0
  155. package/dist/shared/stack.Be1QIHEn.d.mts +23 -0
  156. package/dist/shared/stack.Be1QIHEn.d.ts +23 -0
  157. package/dist/shared/stack.DorMi9CZ.d.cts +80 -0
  158. package/dist/shared/stack.DorMi9CZ.d.mts +80 -0
  159. package/dist/shared/stack.DorMi9CZ.d.ts +80 -0
  160. package/package.json +61 -3
  161. package/src/plugins/ai-chat/api/index.ts +2 -0
  162. package/src/plugins/ai-chat/api/plugin.ts +1083 -0
  163. package/src/plugins/ai-chat/client/components/chat-input.tsx +295 -0
  164. package/src/plugins/ai-chat/client/components/chat-interface.tsx +455 -0
  165. package/src/plugins/ai-chat/client/components/chat-layout.tsx +160 -0
  166. package/src/plugins/ai-chat/client/components/chat-message.tsx +505 -0
  167. package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +296 -0
  168. package/src/plugins/ai-chat/client/components/index.ts +16 -0
  169. package/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.tsx +57 -0
  170. package/src/plugins/ai-chat/client/components/loading/index.tsx +11 -0
  171. package/src/plugins/ai-chat/client/components/pages/404-page.tsx +27 -0
  172. package/src/plugins/ai-chat/client/components/pages/chat-page.internal.tsx +31 -0
  173. package/src/plugins/ai-chat/client/components/pages/chat-page.tsx +46 -0
  174. package/src/plugins/ai-chat/client/components/shared/default-error.tsx +28 -0
  175. package/src/plugins/ai-chat/client/components/shared/error-placeholder.tsx +22 -0
  176. package/src/plugins/ai-chat/client/hooks/chat-hooks.tsx +349 -0
  177. package/src/plugins/ai-chat/client/hooks/index.tsx +1 -0
  178. package/src/plugins/ai-chat/client/index.ts +14 -0
  179. package/src/plugins/ai-chat/client/localization/index.ts +156 -0
  180. package/src/plugins/ai-chat/client/overrides.ts +170 -0
  181. package/src/plugins/ai-chat/client/plugin.tsx +449 -0
  182. package/src/plugins/ai-chat/client.css +6 -0
  183. package/src/plugins/ai-chat/db.ts +65 -0
  184. package/src/plugins/ai-chat/query-keys.ts +87 -0
  185. package/src/plugins/ai-chat/schemas.ts +40 -0
  186. package/src/plugins/ai-chat/style.css +19 -0
  187. package/src/plugins/ai-chat/types.ts +29 -0
  188. package/src/plugins/blog/api/plugin.ts +10 -4
  189. package/src/plugins/blog/client/components/pages/post-page.internal.tsx +1 -1
  190. package/src/plugins/blog/client/components/shared/markdown-content-styles.css +85 -62
  191. package/src/plugins/blog/client/components/shared/markdown-content.tsx +19 -427
  192. package/src/plugins/blog/client/components/shared/on-this-page.tsx +1 -1
  193. package/src/plugins/blog/client/components/shared/page-wrapper.tsx +2 -2
  194. package/src/plugins/blog/client/components/shared/recent-posts-carousel.tsx +2 -2
  195. package/dist/node_modules/.pnpm/react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0/node_modules/react-remove-scroll/dist/es2015/sidecar.cjs +0 -9
  196. package/src/plugins/blog/client/components/shared/better-blog-attribution.tsx +0 -19
  197. package/dist/node_modules/.pnpm/{@radix-ui_react-compose-refs@1.1.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-compose-refs@1.1.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-compose-refs/dist/index.cjs +0 -0
  198. package/dist/node_modules/.pnpm/{@radix-ui_react-compose-refs@1.1.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-compose-refs@1.1.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-compose-refs/dist/index.mjs +0 -0
  199. package/dist/node_modules/.pnpm/{@radix-ui_react-context@1.1.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-context@1.1.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-context/dist/index.cjs +0 -0
  200. package/dist/node_modules/.pnpm/{@radix-ui_react-context@1.1.2_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-context@1.1.2_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-context/dist/index.mjs +0 -0
  201. package/dist/node_modules/.pnpm/{@radix-ui_react-direction@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-direction@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-direction/dist/index.cjs +0 -0
  202. package/dist/node_modules/.pnpm/{@radix-ui_react-direction@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-direction@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-direction/dist/index.mjs +0 -0
  203. package/dist/node_modules/.pnpm/{@radix-ui_react-focus-guards@1.1.3_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-focus-guards@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-focus-guards/dist/index.cjs +0 -0
  204. package/dist/node_modules/.pnpm/{@radix-ui_react-focus-guards@1.1.3_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-focus-guards@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-focus-guards/dist/index.mjs +0 -0
  205. package/dist/node_modules/.pnpm/{@radix-ui_react-primitive@2.1.3_@types_react-dom@19.2.2_@types_react@19.2.2__@types_rea_bdc15f10281778271ffcbe8dd3cd491e → @radix-ui_react-primitive@2.1.3_@types_react-dom@19.2.3_@types_react@19.2.6__@types_rea_a92a69cb1cb39305138539e4fa72f596}/node_modules/@radix-ui/react-primitive/dist/index.cjs +0 -0
  206. package/dist/node_modules/.pnpm/{@radix-ui_react-primitive@2.1.3_@types_react-dom@19.2.2_@types_react@19.2.2__@types_rea_bdc15f10281778271ffcbe8dd3cd491e → @radix-ui_react-primitive@2.1.3_@types_react-dom@19.2.3_@types_react@19.2.6__@types_rea_a92a69cb1cb39305138539e4fa72f596}/node_modules/@radix-ui/react-primitive/dist/index.mjs +0 -0
  207. package/dist/node_modules/.pnpm/{@radix-ui_react-use-callback-ref@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-callback-ref@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-callback-ref/dist/index.cjs +0 -0
  208. package/dist/node_modules/.pnpm/{@radix-ui_react-use-callback-ref@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-callback-ref@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-callback-ref/dist/index.mjs +0 -0
  209. package/dist/node_modules/.pnpm/{@radix-ui_react-use-layout-effect@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-layout-effect@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-layout-effect/dist/index.cjs +0 -0
  210. package/dist/node_modules/.pnpm/{@radix-ui_react-use-layout-effect@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-layout-effect@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-layout-effect/dist/index.mjs +0 -0
  211. package/dist/node_modules/.pnpm/{@radix-ui_react-use-previous@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-previous@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-previous/dist/index.cjs +0 -0
  212. package/dist/node_modules/.pnpm/{@radix-ui_react-use-previous@1.1.1_@types_react@19.2.2_react@19.2.0 → @radix-ui_react-use-previous@1.1.1_@types_react@19.2.6_react@19.2.0}/node_modules/@radix-ui/react-use-previous/dist/index.mjs +0 -0
  213. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/constants.cjs +0 -0
  214. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/constants.mjs +0 -0
  215. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/utils.cjs +0 -0
  216. package/dist/node_modules/.pnpm/{react-remove-scroll-bar@2.3.8_@types_react@19.2.2_react@19.2.0 → react-remove-scroll-bar@2.3.8_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll-bar/dist/es2015/utils.mjs +0 -0
  217. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/Combination.cjs +0 -0
  218. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/Combination.mjs +0 -0
  219. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.cjs +0 -0
  220. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/aggresiveCapture.mjs +0 -0
  221. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/handleScroll.cjs +0 -0
  222. package/dist/node_modules/.pnpm/{react-remove-scroll@2.7.1_@types_react@19.2.2_react@19.2.0 → react-remove-scroll@2.7.1_@types_react@19.2.6_react@19.2.0}/node_modules/react-remove-scroll/dist/es2015/handleScroll.mjs +0 -0
  223. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/component.cjs +0 -0
  224. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/component.mjs +0 -0
  225. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/hook.cjs +0 -0
  226. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/hook.mjs +0 -0
  227. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/singleton.cjs +0 -0
  228. package/dist/node_modules/.pnpm/{react-style-singleton@2.2.3_@types_react@19.2.2_react@19.2.0 → react-style-singleton@2.2.3_@types_react@19.2.6_react@19.2.0}/node_modules/react-style-singleton/dist/es2015/singleton.mjs +0 -0
  229. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/assignRef.cjs +0 -0
  230. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/assignRef.mjs +0 -0
  231. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/useMergeRef.cjs +0 -0
  232. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/useMergeRef.mjs +0 -0
  233. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/useRef.cjs +0 -0
  234. package/dist/node_modules/.pnpm/{use-callback-ref@1.3.3_@types_react@19.2.2_react@19.2.0 → use-callback-ref@1.3.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-callback-ref/dist/es2015/useRef.mjs +0 -0
  235. package/dist/node_modules/.pnpm/{use-sidecar@1.1.3_@types_react@19.2.2_react@19.2.0 → use-sidecar@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-sidecar/dist/es2015/exports.cjs +0 -0
  236. package/dist/node_modules/.pnpm/{use-sidecar@1.1.3_@types_react@19.2.2_react@19.2.0 → use-sidecar@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-sidecar/dist/es2015/exports.mjs +0 -0
  237. package/dist/node_modules/.pnpm/{use-sidecar@1.1.3_@types_react@19.2.2_react@19.2.0 → use-sidecar@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-sidecar/dist/es2015/medium.cjs +0 -0
  238. package/dist/node_modules/.pnpm/{use-sidecar@1.1.3_@types_react@19.2.2_react@19.2.0 → use-sidecar@1.1.3_@types_react@19.2.6_react@19.2.0}/node_modules/use-sidecar/dist/es2015/medium.mjs +0 -0
  239. package/dist/shared/{stack.DLhzx1-D.d.ts → stack.CcI4sYJP.d.cts} +1 -1
  240. package/dist/shared/{stack.DLhzx1-D.d.cts → stack.CcI4sYJP.d.mts} +1 -1
  241. package/dist/shared/{stack.DLhzx1-D.d.mts → stack.CcI4sYJP.d.ts} +1 -1
@@ -0,0 +1,349 @@
1
+ "use client";
2
+
3
+ import { createApiClient } from "@btst/stack/plugins/client";
4
+ import {
5
+ useMutation,
6
+ useQuery,
7
+ useQueryClient,
8
+ useSuspenseQuery,
9
+ } from "@tanstack/react-query";
10
+ import type { AiChatApiRouter } from "../../api/plugin";
11
+ import {
12
+ createAiChatQueryKeys,
13
+ type ConversationWithMessages,
14
+ } from "../../query-keys";
15
+ import type { SerializedConversation, SerializedMessage } from "../../types";
16
+ import { usePluginOverrides } from "@btst/stack/context";
17
+ import type { AiChatPluginOverrides } from "../overrides";
18
+
19
+ /**
20
+ * Shared React Query configuration for all chat queries
21
+ * Prevents automatic refetching to avoid hydration mismatches in SSR
22
+ */
23
+ const SHARED_QUERY_CONFIG = {
24
+ retry: false,
25
+ refetchOnWindowFocus: false,
26
+ refetchOnMount: false,
27
+ refetchOnReconnect: false,
28
+ staleTime: 1000 * 60 * 5, // 5 minutes
29
+ gcTime: 1000 * 60 * 10, // 10 minutes
30
+ } as const;
31
+
32
+ /**
33
+ * Options for the useConversations hook
34
+ */
35
+ export interface UseConversationsOptions {
36
+ /** Whether to enable the query (default: true) */
37
+ enabled?: boolean;
38
+ }
39
+
40
+ /**
41
+ * Result from the useConversations hook
42
+ */
43
+ export interface UseConversationsResult {
44
+ /** Array of conversations */
45
+ conversations: SerializedConversation[];
46
+ /** Whether the initial load is in progress */
47
+ isLoading: boolean;
48
+ /** Error if the query failed */
49
+ error: Error | null;
50
+ /** Function to refetch the conversations */
51
+ refetch: () => void;
52
+ }
53
+
54
+ /**
55
+ * Hook for fetching all conversations
56
+ */
57
+ export function useConversations(
58
+ options: UseConversationsOptions = {},
59
+ ): UseConversationsResult {
60
+ const { apiBaseURL, apiBasePath, headers } =
61
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
62
+ const client = createApiClient<AiChatApiRouter>({
63
+ baseURL: apiBaseURL,
64
+ basePath: apiBasePath,
65
+ });
66
+ const { enabled = true } = options;
67
+ const queries = createAiChatQueryKeys(client, headers);
68
+
69
+ const listQuery = queries.conversations.list();
70
+
71
+ const { data, isLoading, error, refetch } = useQuery<
72
+ SerializedConversation[],
73
+ Error,
74
+ SerializedConversation[],
75
+ typeof listQuery.queryKey
76
+ >({
77
+ ...listQuery,
78
+ ...SHARED_QUERY_CONFIG,
79
+ enabled: enabled && !!client,
80
+ });
81
+
82
+ return {
83
+ conversations: data ?? [],
84
+ isLoading,
85
+ error,
86
+ refetch,
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Suspense variant of useConversations
92
+ */
93
+ export function useSuspenseConversations(): {
94
+ conversations: SerializedConversation[];
95
+ refetch: () => Promise<unknown>;
96
+ } {
97
+ const { apiBaseURL, apiBasePath, headers } =
98
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
99
+ const client = createApiClient<AiChatApiRouter>({
100
+ baseURL: apiBaseURL,
101
+ basePath: apiBasePath,
102
+ });
103
+ const queries = createAiChatQueryKeys(client, headers);
104
+ const listQuery = queries.conversations.list();
105
+
106
+ const { data, refetch, error, isFetching } = useSuspenseQuery<
107
+ SerializedConversation[],
108
+ Error,
109
+ SerializedConversation[],
110
+ typeof listQuery.queryKey
111
+ >({
112
+ ...listQuery,
113
+ ...SHARED_QUERY_CONFIG,
114
+ });
115
+
116
+ if (error && !isFetching) {
117
+ throw error;
118
+ }
119
+
120
+ return {
121
+ conversations: data ?? [],
122
+ refetch,
123
+ };
124
+ }
125
+
126
+ /**
127
+ * Options for the useConversation hook
128
+ */
129
+ export interface UseConversationOptions {
130
+ /** Whether to enable the query (default: true) */
131
+ enabled?: boolean;
132
+ }
133
+
134
+ /**
135
+ * Result from the useConversation hook
136
+ */
137
+ export interface UseConversationResult {
138
+ /** The conversation with messages, or null if not found */
139
+ conversation: ConversationWithMessages | null;
140
+ /** Whether the conversation is being loaded */
141
+ isLoading: boolean;
142
+ /** Error if the query failed */
143
+ error: Error | null;
144
+ /** Function to refetch the conversation */
145
+ refetch: () => void;
146
+ }
147
+
148
+ /**
149
+ * Hook for fetching a single conversation with messages
150
+ */
151
+ export function useConversation(
152
+ id?: string,
153
+ options: UseConversationOptions = {},
154
+ ): UseConversationResult {
155
+ const { apiBaseURL, apiBasePath, headers } =
156
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
157
+ const client = createApiClient<AiChatApiRouter>({
158
+ baseURL: apiBaseURL,
159
+ basePath: apiBasePath,
160
+ });
161
+ const { enabled = true } = options;
162
+ const queries = createAiChatQueryKeys(client, headers);
163
+
164
+ const detailQuery = queries.conversations.detail(id ?? "");
165
+
166
+ const { data, isLoading, error, refetch } = useQuery<
167
+ ConversationWithMessages | null,
168
+ Error,
169
+ ConversationWithMessages | null,
170
+ typeof detailQuery.queryKey
171
+ >({
172
+ ...detailQuery,
173
+ ...SHARED_QUERY_CONFIG,
174
+ enabled: enabled && !!client && !!id,
175
+ });
176
+
177
+ return {
178
+ conversation: data || null,
179
+ isLoading,
180
+ error,
181
+ refetch,
182
+ };
183
+ }
184
+
185
+ /**
186
+ * Suspense variant of useConversation
187
+ */
188
+ export function useSuspenseConversation(id: string): {
189
+ conversation: ConversationWithMessages | null;
190
+ refetch: () => Promise<unknown>;
191
+ } {
192
+ const { apiBaseURL, apiBasePath, headers } =
193
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
194
+ const client = createApiClient<AiChatApiRouter>({
195
+ baseURL: apiBaseURL,
196
+ basePath: apiBasePath,
197
+ });
198
+ const queries = createAiChatQueryKeys(client, headers);
199
+ const detailQuery = queries.conversations.detail(id);
200
+
201
+ const { data, refetch, error, isFetching } = useSuspenseQuery<
202
+ ConversationWithMessages | null,
203
+ Error,
204
+ ConversationWithMessages | null,
205
+ typeof detailQuery.queryKey
206
+ >({
207
+ ...detailQuery,
208
+ ...SHARED_QUERY_CONFIG,
209
+ });
210
+
211
+ if (error && !isFetching) {
212
+ throw error;
213
+ }
214
+
215
+ return {
216
+ conversation: data || null,
217
+ refetch,
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Hook for creating a new conversation
223
+ */
224
+ export function useCreateConversation() {
225
+ const { refresh, apiBaseURL, apiBasePath } =
226
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
227
+ const client = createApiClient<AiChatApiRouter>({
228
+ baseURL: apiBaseURL,
229
+ basePath: apiBasePath,
230
+ });
231
+ const queryClient = useQueryClient();
232
+ const queries = createAiChatQueryKeys(client);
233
+
234
+ return useMutation<
235
+ SerializedConversation | null,
236
+ Error,
237
+ { id?: string; title?: string }
238
+ >({
239
+ mutationKey: [...queries.conversations._def, "create"],
240
+ mutationFn: async (data) => {
241
+ const response = await client("@post/chat/conversations", {
242
+ method: "POST",
243
+ body: data,
244
+ });
245
+ return response.data as SerializedConversation | null;
246
+ },
247
+ onSuccess: async (created) => {
248
+ // Update list cache
249
+ await queryClient.invalidateQueries({
250
+ queryKey: queries.conversations.list().queryKey,
251
+ });
252
+ // Refresh server-side cache if available
253
+ if (refresh) {
254
+ await refresh();
255
+ }
256
+ },
257
+ });
258
+ }
259
+
260
+ /**
261
+ * Hook for renaming a conversation
262
+ */
263
+ export function useRenameConversation() {
264
+ const { refresh, apiBaseURL, apiBasePath } =
265
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
266
+ const client = createApiClient<AiChatApiRouter>({
267
+ baseURL: apiBaseURL,
268
+ basePath: apiBasePath,
269
+ });
270
+ const queryClient = useQueryClient();
271
+ const queries = createAiChatQueryKeys(client);
272
+
273
+ return useMutation<
274
+ SerializedConversation | null,
275
+ Error,
276
+ { id: string; title: string }
277
+ >({
278
+ mutationKey: [...queries.conversations._def, "rename"],
279
+ mutationFn: async ({ id, title }) => {
280
+ const response = await client("@put/chat/conversations/:id", {
281
+ method: "PUT",
282
+ params: { id },
283
+ body: { title },
284
+ });
285
+ return response.data as SerializedConversation | null;
286
+ },
287
+ onSuccess: async (updated) => {
288
+ // Update detail cache if available
289
+ if (updated?.id) {
290
+ queryClient.setQueryData(
291
+ queries.conversations.detail(updated.id).queryKey,
292
+ (old: ConversationWithMessages | null | undefined) =>
293
+ old ? { ...old, ...updated } : null,
294
+ );
295
+ }
296
+ // Invalidate list
297
+ await queryClient.invalidateQueries({
298
+ queryKey: queries.conversations.list().queryKey,
299
+ });
300
+ if (refresh) {
301
+ await refresh();
302
+ }
303
+ },
304
+ });
305
+ }
306
+
307
+ /**
308
+ * Hook for deleting a conversation
309
+ */
310
+ export function useDeleteConversation() {
311
+ const { refresh, apiBaseURL, apiBasePath } =
312
+ usePluginOverrides<AiChatPluginOverrides>("ai-chat");
313
+ const client = createApiClient<AiChatApiRouter>({
314
+ baseURL: apiBaseURL,
315
+ basePath: apiBasePath,
316
+ });
317
+ const queryClient = useQueryClient();
318
+ const queries = createAiChatQueryKeys(client);
319
+
320
+ return useMutation<{ success: boolean }, Error, { id: string }>({
321
+ mutationKey: [...queries.conversations._def, "delete"],
322
+ mutationFn: async ({ id }) => {
323
+ const response = await client("@delete/chat/conversations/:id", {
324
+ method: "DELETE",
325
+ params: { id },
326
+ });
327
+ return response.data as { success: boolean };
328
+ },
329
+ onSuccess: async (_, { id }) => {
330
+ // Remove from detail cache
331
+ queryClient.removeQueries({
332
+ queryKey: queries.conversations.detail(id).queryKey,
333
+ });
334
+ // Invalidate list
335
+ await queryClient.invalidateQueries({
336
+ queryKey: queries.conversations.list().queryKey,
337
+ });
338
+ if (refresh) {
339
+ await refresh();
340
+ }
341
+ },
342
+ });
343
+ }
344
+
345
+ export type {
346
+ SerializedConversation,
347
+ SerializedMessage,
348
+ ConversationWithMessages,
349
+ };
@@ -0,0 +1 @@
1
+ export * from "./chat-hooks";
@@ -0,0 +1,14 @@
1
+ export { aiChatClientPlugin } from "./plugin";
2
+ export type {
3
+ AiChatClientConfig,
4
+ AiChatClientHooks,
5
+ RouteContext,
6
+ LoaderContext,
7
+ } from "./plugin";
8
+ export type { AiChatPluginOverrides, AllowedFileType } from "./overrides";
9
+ export { DEFAULT_ALLOWED_FILE_TYPES } from "./overrides";
10
+ export { ChatInterface } from "./components/chat-interface";
11
+ export { ChatLayout } from "./components/chat-layout";
12
+ export { ChatSidebar } from "./components/chat-sidebar";
13
+ export { ChatMessage } from "./components/chat-message";
14
+ export { ChatInput } from "./components/chat-input";
@@ -0,0 +1,156 @@
1
+ /**
2
+ * AI Chat plugin localization strings
3
+ */
4
+ export interface AiChatLocalization {
5
+ // Chat interface
6
+ CHAT_PLACEHOLDER: string;
7
+ CHAT_SEND_BUTTON: string;
8
+ CHAT_EMPTY_STATE: string;
9
+ CHAT_LOADING: string;
10
+ CHAT_ERROR: string;
11
+ CHAT_RETRY: string;
12
+
13
+ // Page errors
14
+ CHAT_GENERIC_ERROR_TITLE: string;
15
+ CHAT_GENERIC_ERROR_MESSAGE: string;
16
+ CHAT_PAGE_NOT_FOUND_TITLE: string;
17
+ CHAT_PAGE_NOT_FOUND_DESCRIPTION: string;
18
+
19
+ // Sidebar
20
+ SIDEBAR_TITLE: string;
21
+ SIDEBAR_NEW_CHAT: string;
22
+ SIDEBAR_NO_CONVERSATIONS: string;
23
+ SIDEBAR_SEARCH_PLACEHOLDER: string;
24
+
25
+ // Conversation actions
26
+ CONVERSATION_RENAME: string;
27
+ CONVERSATION_RENAME_PLACEHOLDER: string;
28
+ CONVERSATION_RENAME_SAVE: string;
29
+ CONVERSATION_RENAME_CANCEL: string;
30
+ CONVERSATION_DELETE: string;
31
+ CONVERSATION_DELETE_CONFIRM_TITLE: string;
32
+ CONVERSATION_DELETE_CONFIRM_DESCRIPTION: string;
33
+ CONVERSATION_DELETE_CONFIRM_BUTTON: string;
34
+ CONVERSATION_DELETE_CANCEL: string;
35
+
36
+ // Image upload (legacy)
37
+ IMAGE_UPLOAD_BUTTON: string;
38
+ IMAGE_UPLOAD_UPLOADING: string;
39
+ IMAGE_UPLOAD_ERROR_NOT_IMAGE: string;
40
+ IMAGE_UPLOAD_ERROR_TOO_LARGE: string;
41
+ IMAGE_UPLOAD_SUCCESS: string;
42
+ IMAGE_UPLOAD_FAILURE: string;
43
+
44
+ // File upload
45
+ FILE_UPLOAD_BUTTON: string;
46
+ FILE_UPLOAD_ERROR_TOO_LARGE: string;
47
+ FILE_UPLOAD_SUCCESS: string;
48
+ FILE_UPLOAD_FAILURE: string;
49
+
50
+ // Timestamps
51
+ TIME_JUST_NOW: string;
52
+ TIME_MINUTES_AGO: string;
53
+ TIME_HOURS_AGO: string;
54
+ TIME_YESTERDAY: string;
55
+ TIME_DAYS_AGO: string;
56
+
57
+ // Message actions
58
+ MESSAGE_COPY: string;
59
+ MESSAGE_COPIED: string;
60
+ MESSAGE_RETRY: string;
61
+ MESSAGE_EDIT: string;
62
+ MESSAGE_SAVE: string;
63
+ MESSAGE_CANCEL: string;
64
+
65
+ // Accessibility
66
+ A11Y_USER_MESSAGE: string;
67
+ A11Y_ASSISTANT_MESSAGE: string;
68
+ A11Y_COPY_CODE: string;
69
+ A11Y_CODE_COPIED: string;
70
+ }
71
+
72
+ /**
73
+ * Default English localization strings
74
+ */
75
+ export const AI_CHAT_LOCALIZATION: AiChatLocalization = {
76
+ // Chat interface
77
+ CHAT_PLACEHOLDER: "Type a message...",
78
+ CHAT_SEND_BUTTON: "Send",
79
+ CHAT_EMPTY_STATE: "Start a conversation...",
80
+ CHAT_LOADING: "Thinking...",
81
+ CHAT_ERROR: "Something went wrong. Please try again.",
82
+ CHAT_RETRY: "Retry",
83
+
84
+ // Page errors
85
+ CHAT_GENERIC_ERROR_TITLE: "Something went wrong",
86
+ CHAT_GENERIC_ERROR_MESSAGE:
87
+ "An error occurred while loading the chat. Please try again.",
88
+ CHAT_PAGE_NOT_FOUND_TITLE: "Chat not found",
89
+ CHAT_PAGE_NOT_FOUND_DESCRIPTION:
90
+ "The conversation you're looking for doesn't exist or has been deleted.",
91
+
92
+ // Sidebar
93
+ SIDEBAR_TITLE: "Conversations",
94
+ SIDEBAR_NEW_CHAT: "New chat",
95
+ SIDEBAR_NO_CONVERSATIONS: "No conversations yet",
96
+ SIDEBAR_SEARCH_PLACEHOLDER: "Search conversations...",
97
+
98
+ // Conversation actions
99
+ CONVERSATION_RENAME: "Rename",
100
+ CONVERSATION_RENAME_PLACEHOLDER: "Enter conversation name",
101
+ CONVERSATION_RENAME_SAVE: "Save",
102
+ CONVERSATION_RENAME_CANCEL: "Cancel",
103
+ CONVERSATION_DELETE: "Delete",
104
+ CONVERSATION_DELETE_CONFIRM_TITLE: "Delete conversation",
105
+ CONVERSATION_DELETE_CONFIRM_DESCRIPTION:
106
+ "Are you sure you want to delete this conversation? This action cannot be undone.",
107
+ CONVERSATION_DELETE_CONFIRM_BUTTON: "Delete",
108
+ CONVERSATION_DELETE_CANCEL: "Cancel",
109
+
110
+ // Image upload (legacy)
111
+ IMAGE_UPLOAD_BUTTON: "Attach image",
112
+ IMAGE_UPLOAD_UPLOADING: "Uploading...",
113
+ IMAGE_UPLOAD_ERROR_NOT_IMAGE: "Please select an image file",
114
+ IMAGE_UPLOAD_ERROR_TOO_LARGE: "Image must be less than 4MB",
115
+ IMAGE_UPLOAD_SUCCESS: "Image uploaded",
116
+ IMAGE_UPLOAD_FAILURE: "Failed to upload image",
117
+
118
+ // File upload
119
+ FILE_UPLOAD_BUTTON: "Attach file",
120
+ FILE_UPLOAD_ERROR_TOO_LARGE: "File must be less than 10MB",
121
+ FILE_UPLOAD_SUCCESS: "File attached",
122
+ FILE_UPLOAD_FAILURE: "Failed to attach file",
123
+
124
+ // Timestamps
125
+ TIME_JUST_NOW: "Just now",
126
+ TIME_MINUTES_AGO: "{count} minutes ago",
127
+ TIME_HOURS_AGO: "{count} hours ago",
128
+ TIME_YESTERDAY: "Yesterday",
129
+ TIME_DAYS_AGO: "{count} days ago",
130
+
131
+ // Message actions
132
+ MESSAGE_COPY: "Copy message",
133
+ MESSAGE_COPIED: "Copied!",
134
+ MESSAGE_RETRY: "Retry",
135
+ MESSAGE_EDIT: "Edit message",
136
+ MESSAGE_SAVE: "Save",
137
+ MESSAGE_CANCEL: "Cancel",
138
+
139
+ // Accessibility
140
+ A11Y_USER_MESSAGE: "Your message",
141
+ A11Y_ASSISTANT_MESSAGE: "AI response",
142
+ A11Y_COPY_CODE: "Copy code",
143
+ A11Y_CODE_COPIED: "Code copied",
144
+ };
145
+
146
+ /**
147
+ * Helper function to format localized strings with placeholders
148
+ */
149
+ export function formatLocalized(
150
+ template: string,
151
+ values: Record<string, string | number>,
152
+ ): string {
153
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
154
+ return values[key]?.toString() ?? match;
155
+ });
156
+ }
@@ -0,0 +1,170 @@
1
+ import type { ComponentType } from "react";
2
+ import type { AiChatLocalization } from "./localization";
3
+
4
+ /**
5
+ * Plugin mode for AI Chat
6
+ * - 'authenticated': Conversations persisted with userId (default)
7
+ * - 'public': Stateless chat, no persistence (ideal for public chatbots)
8
+ */
9
+ export type AiChatMode = "authenticated" | "public";
10
+
11
+ /**
12
+ * Allowed file type categories for uploads
13
+ */
14
+ export type AllowedFileType =
15
+ | "image"
16
+ | "text"
17
+ | "pdf"
18
+ | "markdown"
19
+ | "csv"
20
+ | "json";
21
+
22
+ /**
23
+ * Default allowed file types (images only for best AI model compatibility)
24
+ * Consumers can expand this by passing allowedFileTypes in overrides
25
+ */
26
+ export const DEFAULT_ALLOWED_FILE_TYPES: AllowedFileType[] = ["image"];
27
+
28
+ /**
29
+ * MIME type mappings for each file type category
30
+ */
31
+ export const FILE_TYPE_MIME_MAP: Record<AllowedFileType, string[]> = {
32
+ image: ["image/*"],
33
+ text: ["text/plain"],
34
+ markdown: ["text/markdown"],
35
+ csv: ["text/csv"],
36
+ pdf: ["application/pdf"],
37
+ json: ["application/json"],
38
+ };
39
+
40
+ /**
41
+ * Context passed to lifecycle hooks
42
+ */
43
+ export interface RouteContext {
44
+ /** Current route path */
45
+ path: string;
46
+ /** Route parameters (e.g., { id: "abc123" }) */
47
+ params?: Record<string, string>;
48
+ /** Whether rendering on server (true) or client (false) */
49
+ isSSR: boolean;
50
+ /** Additional context properties */
51
+ [key: string]: any;
52
+ }
53
+
54
+ /**
55
+ * Overridable components and functions for the AI Chat plugin
56
+ *
57
+ * External consumers can provide their own implementations of these
58
+ * to customize the behavior for their framework (Next.js, React Router, etc.)
59
+ */
60
+ export interface AiChatPluginOverrides {
61
+ /**
62
+ * Plugin mode - should match backend config
63
+ * @default 'authenticated'
64
+ */
65
+ mode?: AiChatMode;
66
+
67
+ /**
68
+ * API base URL
69
+ */
70
+ apiBaseURL: string;
71
+
72
+ /**
73
+ * API base path
74
+ */
75
+ apiBasePath: string;
76
+
77
+ /**
78
+ * Navigation function for programmatic navigation
79
+ */
80
+ navigate: (path: string) => void | Promise<void>;
81
+
82
+ /**
83
+ * Refresh function to invalidate server-side cache (e.g., Next.js router.refresh())
84
+ */
85
+ refresh?: () => void | Promise<void>;
86
+
87
+ /**
88
+ * Link component for navigation
89
+ */
90
+ Link?: ComponentType<React.ComponentProps<"a"> & Record<string, any>>;
91
+
92
+ /**
93
+ * Image component for displaying images
94
+ */
95
+ Image?: ComponentType<
96
+ React.ImgHTMLAttributes<HTMLImageElement> & Record<string, any>
97
+ >;
98
+
99
+ /**
100
+ * Function used to upload a file and return its URL.
101
+ * Called for images, PDFs, text files, and other supported file types.
102
+ */
103
+ uploadFile?: (file: File) => Promise<string>;
104
+
105
+ /**
106
+ * Allowed file types for upload.
107
+ * By default, all types are enabled: image, text, pdf, markdown, csv, json
108
+ * Set to empty array to disable file uploads entirely.
109
+ * @default ['image', 'text', 'pdf', 'markdown', 'csv', 'json']
110
+ */
111
+ allowedFileTypes?: AllowedFileType[];
112
+
113
+ /**
114
+ * Localization object for the AI Chat plugin
115
+ */
116
+ localization?: Partial<AiChatLocalization>;
117
+
118
+ /**
119
+ * Optional headers to pass with API requests (e.g., for SSR auth)
120
+ */
121
+ headers?: HeadersInit;
122
+
123
+ /**
124
+ * Whether to show the attribution
125
+ * @default true
126
+ */
127
+ showAttribution?: boolean;
128
+
129
+ // ============== Lifecycle Hooks (optional) ==============
130
+
131
+ /**
132
+ * Called when a route is rendered
133
+ * @param routeName - Name of the route (e.g., 'chat', 'chatConversation')
134
+ * @param context - Route context with path, params, etc.
135
+ */
136
+ onRouteRender?: (
137
+ routeName: string,
138
+ context: RouteContext,
139
+ ) => void | Promise<void>;
140
+
141
+ /**
142
+ * Called when a route encounters an error
143
+ * @param routeName - Name of the route
144
+ * @param error - The error that occurred
145
+ * @param context - Route context
146
+ */
147
+ onRouteError?: (
148
+ routeName: string,
149
+ error: Error,
150
+ context: RouteContext,
151
+ ) => void | Promise<void>;
152
+
153
+ /**
154
+ * Called before the chat page is rendered
155
+ * Return false to prevent rendering (e.g., for authorization)
156
+ * @param context - Route context
157
+ */
158
+ onBeforeChatPageRendered?: (context: RouteContext) => boolean;
159
+
160
+ /**
161
+ * Called before a conversation page is rendered
162
+ * Return false to prevent rendering (e.g., for authorization)
163
+ * @param id - The conversation ID
164
+ * @param context - Route context
165
+ */
166
+ onBeforeConversationPageRendered?: (
167
+ id: string,
168
+ context: RouteContext,
169
+ ) => boolean;
170
+ }