@btst/stack 1.3.1 → 1.4.1
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.
- package/README.md +85 -37
- package/dist/node_modules/.pnpm/@radix-ui_react-accordion@1.2.12_@types_react-dom@19.2.3_@types_react@19.2.6__@types_re_947719a27ff11ec6f09710dd9e85efc5/node_modules/@radix-ui/react-accordion/dist/index.cjs +321 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-accordion@1.2.12_@types_react-dom@19.2.3_@types_react@19.2.6__@types_re_947719a27ff11ec6f09710dd9e85efc5/node_modules/@radix-ui/react-accordion/dist/index.mjs +306 -0
- 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
- 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
- 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
- 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
- package/dist/node_modules/.pnpm/@radix-ui_react-collapsible@1.1.12_@types_react-dom@19.2.3_@types_react@19.2.6__@types__d025a77f62ee83ca6bd8b0ea1f9de738/node_modules/@radix-ui/react-collapsible/dist/index.cjs +168 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-collapsible@1.1.12_@types_react-dom@19.2.3_@types_react@19.2.6__@types__d025a77f62ee83ca6bd8b0ea1f9de738/node_modules/@radix-ui/react-collapsible/dist/index.mjs +146 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/dist/packages/better-stack/src/plugins/ai-chat/api/plugin.cjs +610 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/api/plugin.mjs +608 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-input.cjs +221 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-input.mjs +219 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-interface.cjs +341 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-interface.mjs +339 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-layout.cjs +135 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-layout.mjs +133 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-message.cjs +429 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-message.mjs +423 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-sidebar.cjs +227 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/chat-sidebar.mjs +225 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.cjs +31 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.mjs +29 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/index.cjs +11 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/loading/index.mjs +8 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/404-page.cjs +18 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/404-page.mjs +16 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.cjs +39 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.cjs +22 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.internal.mjs +20 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/pages/chat-page.mjs +37 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/default-error.cjs +18 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/default-error.mjs +16 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/error-placeholder.cjs +26 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/shared/error-placeholder.mjs +24 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/tool-call-display.cjs +123 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/components/tool-call-display.mjs +121 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/hooks/chat-hooks.cjs +199 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/hooks/chat-hooks.mjs +191 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/localization/index.cjs +63 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/localization/index.mjs +61 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/overrides.cjs +14 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/overrides.mjs +11 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/plugin.cjs +241 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/client/plugin.mjs +239 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/db.cjs +65 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/db.mjs +63 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/schemas.cjs +42 -0
- package/dist/packages/better-stack/src/plugins/ai-chat/schemas.mjs +38 -0
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/markdown-content.cjs +12 -309
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/markdown-content.mjs +13 -303
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/page-wrapper.cjs +2 -2
- package/dist/packages/better-stack/src/plugins/blog/client/components/shared/page-wrapper.mjs +2 -2
- package/dist/packages/ui/src/components/accordion.cjs +67 -0
- package/dist/packages/ui/src/components/accordion.mjs +62 -0
- package/dist/packages/ui/src/components/alert-dialog.cjs +1 -1
- package/dist/packages/ui/src/components/alert-dialog.mjs +1 -1
- package/dist/packages/{better-stack/src/plugins/blog/client/components/shared/better-blog-attribution.cjs → ui/src/components/better-stack-attribution.cjs} +3 -3
- package/dist/packages/{better-stack/src/plugins/blog/client/components/shared/better-blog-attribution.mjs → ui/src/components/better-stack-attribution.mjs} +3 -3
- package/dist/packages/ui/src/components/dialog.cjs +14 -0
- package/dist/packages/ui/src/components/dialog.mjs +14 -1
- package/dist/packages/ui/src/components/dropdown-menu.cjs +67 -0
- package/dist/packages/ui/src/components/dropdown-menu.mjs +62 -0
- package/dist/packages/ui/src/components/markdown-content.cjs +306 -0
- package/dist/packages/ui/src/components/markdown-content.mjs +297 -0
- package/dist/packages/ui/src/components/scroll-area.cjs +63 -0
- package/dist/packages/ui/src/components/scroll-area.mjs +60 -0
- package/dist/packages/ui/src/components/select.cjs +1 -1
- package/dist/packages/ui/src/components/select.mjs +1 -1
- package/dist/packages/ui/src/components/sheet.cjs +87 -0
- package/dist/packages/ui/src/components/sheet.mjs +69 -0
- package/dist/plugins/ai-chat/api/index.cjs +9 -0
- package/dist/plugins/ai-chat/api/index.d.cts +9 -0
- package/dist/plugins/ai-chat/api/index.d.mts +9 -0
- package/dist/plugins/ai-chat/api/index.d.ts +9 -0
- package/dist/plugins/ai-chat/api/index.mjs +2 -0
- package/dist/plugins/ai-chat/client/components/index.cjs +29 -0
- package/dist/plugins/ai-chat/client/components/index.d.cts +30 -0
- package/dist/plugins/ai-chat/client/components/index.d.mts +30 -0
- package/dist/plugins/ai-chat/client/components/index.d.ts +30 -0
- package/dist/plugins/ai-chat/client/components/index.mjs +12 -0
- package/dist/plugins/ai-chat/client/hooks/index.cjs +13 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.cts +98 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.mts +98 -0
- package/dist/plugins/ai-chat/client/hooks/index.d.ts +98 -0
- package/dist/plugins/ai-chat/client/hooks/index.mjs +1 -0
- package/dist/plugins/ai-chat/client/index.cjs +21 -0
- package/dist/plugins/ai-chat/client/index.d.cts +156 -0
- package/dist/plugins/ai-chat/client/index.d.mts +156 -0
- package/dist/plugins/ai-chat/client/index.d.ts +156 -0
- package/dist/plugins/ai-chat/client/index.mjs +8 -0
- package/dist/plugins/ai-chat/client.css +6 -0
- package/dist/plugins/ai-chat/query-keys.cjs +60 -0
- package/dist/plugins/ai-chat/query-keys.d.cts +478 -0
- package/dist/plugins/ai-chat/query-keys.d.mts +478 -0
- package/dist/plugins/ai-chat/query-keys.d.ts +478 -0
- package/dist/plugins/ai-chat/query-keys.mjs +58 -0
- package/dist/plugins/ai-chat/style.css +19 -0
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/components/shared/markdown-content-styles.css +91 -62
- package/dist/plugins/blog/client/hooks/index.d.cts +4 -4
- package/dist/plugins/blog/client/hooks/index.d.mts +4 -4
- package/dist/plugins/blog/client/hooks/index.d.ts +4 -4
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +7 -7
- package/dist/plugins/blog/query-keys.d.mts +7 -7
- package/dist/plugins/blog/query-keys.d.ts +7 -7
- package/dist/shared/stack.Be1QIHEn.d.cts +23 -0
- package/dist/shared/stack.Be1QIHEn.d.mts +23 -0
- package/dist/shared/stack.Be1QIHEn.d.ts +23 -0
- package/dist/shared/stack.DaOcgmrM.d.cts +323 -0
- package/dist/shared/stack.DaOcgmrM.d.mts +323 -0
- package/dist/shared/stack.DaOcgmrM.d.ts +323 -0
- package/package.json +59 -1
- package/src/plugins/ai-chat/api/index.ts +2 -0
- package/src/plugins/ai-chat/api/plugin.ts +1083 -0
- package/src/plugins/ai-chat/client/components/chat-input.tsx +295 -0
- package/src/plugins/ai-chat/client/components/chat-interface.tsx +494 -0
- package/src/plugins/ai-chat/client/components/chat-layout.tsx +175 -0
- package/src/plugins/ai-chat/client/components/chat-message.tsx +561 -0
- package/src/plugins/ai-chat/client/components/chat-sidebar.tsx +296 -0
- package/src/plugins/ai-chat/client/components/index.ts +18 -0
- package/src/plugins/ai-chat/client/components/loading/chat-page-skeleton.tsx +57 -0
- package/src/plugins/ai-chat/client/components/loading/index.tsx +11 -0
- package/src/plugins/ai-chat/client/components/pages/404-page.tsx +27 -0
- package/src/plugins/ai-chat/client/components/pages/chat-page.internal.tsx +31 -0
- package/src/plugins/ai-chat/client/components/pages/chat-page.tsx +46 -0
- package/src/plugins/ai-chat/client/components/shared/default-error.tsx +28 -0
- package/src/plugins/ai-chat/client/components/shared/error-placeholder.tsx +22 -0
- package/src/plugins/ai-chat/client/components/tool-call-display.tsx +197 -0
- package/src/plugins/ai-chat/client/hooks/chat-hooks.tsx +349 -0
- package/src/plugins/ai-chat/client/hooks/index.tsx +1 -0
- package/src/plugins/ai-chat/client/index.ts +25 -0
- package/src/plugins/ai-chat/client/localization/index.ts +156 -0
- package/src/plugins/ai-chat/client/overrides.ts +241 -0
- package/src/plugins/ai-chat/client/plugin.tsx +449 -0
- package/src/plugins/ai-chat/client.css +6 -0
- package/src/plugins/ai-chat/db.ts +65 -0
- package/src/plugins/ai-chat/query-keys.ts +87 -0
- package/src/plugins/ai-chat/schemas.ts +40 -0
- package/src/plugins/ai-chat/style.css +19 -0
- package/src/plugins/ai-chat/types.ts +29 -0
- package/src/plugins/blog/client/components/shared/markdown-content-styles.css +91 -62
- package/src/plugins/blog/client/components/shared/markdown-content.tsx +19 -427
- package/src/plugins/blog/client/components/shared/page-wrapper.tsx +2 -2
- 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
- package/src/plugins/blog/client/components/shared/better-blog-attribution.tsx +0 -19
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/dist/shared/{stack.CbuN2zVV.d.ts → stack.CcI4sYJP.d.cts} +3 -3
- package/dist/shared/{stack.CbuN2zVV.d.cts → stack.CcI4sYJP.d.mts} +3 -3
- package/dist/shared/{stack.CbuN2zVV.d.mts → stack.CcI4sYJP.d.ts} +3 -3
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineClientPlugin,
|
|
3
|
+
createApiClient,
|
|
4
|
+
} from "@btst/stack/plugins/client";
|
|
5
|
+
import { createRoute } from "@btst/yar";
|
|
6
|
+
import type { QueryClient } from "@tanstack/react-query";
|
|
7
|
+
import type { AiChatApiRouter } from "../api";
|
|
8
|
+
import { createAiChatQueryKeys } from "../query-keys";
|
|
9
|
+
import type { SerializedConversation, SerializedMessage } from "../types";
|
|
10
|
+
import { ChatLayout } from "./components/chat-layout";
|
|
11
|
+
import type { AiChatMode } from "./overrides";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Context passed to route hooks
|
|
15
|
+
*/
|
|
16
|
+
export interface RouteContext {
|
|
17
|
+
/** Current route path */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Route parameters (e.g., { id: "abc123" }) */
|
|
20
|
+
params?: Record<string, string>;
|
|
21
|
+
/** Whether rendering on server (true) or client (false) */
|
|
22
|
+
isSSR: boolean;
|
|
23
|
+
/** Additional context properties */
|
|
24
|
+
[key: string]: any;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Context passed to loader hooks
|
|
29
|
+
*/
|
|
30
|
+
export interface LoaderContext {
|
|
31
|
+
/** Current route path */
|
|
32
|
+
path: string;
|
|
33
|
+
/** Route parameters (e.g., { id: "abc123" }) */
|
|
34
|
+
params?: Record<string, string>;
|
|
35
|
+
/** Whether rendering on server (true) or client (false) */
|
|
36
|
+
isSSR: boolean;
|
|
37
|
+
/** Base URL for API calls */
|
|
38
|
+
apiBaseURL: string;
|
|
39
|
+
/** Path where the API is mounted */
|
|
40
|
+
apiBasePath: string;
|
|
41
|
+
/** Optional headers for the request */
|
|
42
|
+
headers?: Headers;
|
|
43
|
+
/** Additional context properties */
|
|
44
|
+
[key: string]: any;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Configuration for AI Chat client plugin
|
|
49
|
+
*/
|
|
50
|
+
export interface AiChatClientConfig {
|
|
51
|
+
/** Base URL for API calls (e.g., "http://localhost:3000") */
|
|
52
|
+
apiBaseURL: string;
|
|
53
|
+
/** Path where the API is mounted (e.g., "/api/data") */
|
|
54
|
+
apiBasePath: string;
|
|
55
|
+
/** Base URL of your site for SEO meta tags */
|
|
56
|
+
siteBaseURL: string;
|
|
57
|
+
/** Path where pages are mounted (e.g., "/pages") */
|
|
58
|
+
siteBasePath: string;
|
|
59
|
+
/** React Query client instance for caching */
|
|
60
|
+
queryClient: QueryClient;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Plugin mode - should match backend config
|
|
64
|
+
* - 'authenticated': Full chat with conversation history (default)
|
|
65
|
+
* - 'public': Simple widget mode, no persistence, no sidebar
|
|
66
|
+
* @default 'authenticated'
|
|
67
|
+
*/
|
|
68
|
+
mode?: AiChatMode;
|
|
69
|
+
|
|
70
|
+
/** Optional SEO configuration for meta tags */
|
|
71
|
+
seo?: {
|
|
72
|
+
/** Site name for Open Graph tags */
|
|
73
|
+
siteName?: string;
|
|
74
|
+
/** Default description */
|
|
75
|
+
description?: string;
|
|
76
|
+
/** Locale for Open Graph (e.g., "en_US") */
|
|
77
|
+
locale?: string;
|
|
78
|
+
/** Default image URL for social sharing */
|
|
79
|
+
defaultImage?: string;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/** Optional hooks for customizing behavior */
|
|
83
|
+
hooks?: AiChatClientHooks;
|
|
84
|
+
|
|
85
|
+
/** Optional headers for SSR (e.g., forwarding cookies) */
|
|
86
|
+
headers?: Headers;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Hooks for AI Chat client plugin
|
|
91
|
+
* All hooks are optional and allow consumers to customize behavior
|
|
92
|
+
*/
|
|
93
|
+
export interface AiChatClientHooks {
|
|
94
|
+
/**
|
|
95
|
+
* Called before loading conversations list. Return false to cancel loading.
|
|
96
|
+
* @param context - Loader context with path, params, etc.
|
|
97
|
+
*/
|
|
98
|
+
beforeLoadConversations?: (
|
|
99
|
+
context: LoaderContext,
|
|
100
|
+
) => Promise<boolean> | boolean;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Called after conversations are loaded. Return false to cancel further processing.
|
|
104
|
+
* @param conversations - Array of loaded conversations or null
|
|
105
|
+
* @param context - Loader context
|
|
106
|
+
*/
|
|
107
|
+
afterLoadConversations?: (
|
|
108
|
+
conversations: SerializedConversation[] | null,
|
|
109
|
+
context: LoaderContext,
|
|
110
|
+
) => Promise<boolean> | boolean;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Called before loading a single conversation. Return false to cancel loading.
|
|
114
|
+
* @param id - Conversation ID being loaded
|
|
115
|
+
* @param context - Loader context
|
|
116
|
+
*/
|
|
117
|
+
beforeLoadConversation?: (
|
|
118
|
+
id: string,
|
|
119
|
+
context: LoaderContext,
|
|
120
|
+
) => Promise<boolean> | boolean;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Called after a conversation is loaded. Return false to cancel further processing.
|
|
124
|
+
* @param conversation - Loaded conversation or null if not found
|
|
125
|
+
* @param id - Conversation ID that was requested
|
|
126
|
+
* @param context - Loader context
|
|
127
|
+
*/
|
|
128
|
+
afterLoadConversation?: (
|
|
129
|
+
conversation:
|
|
130
|
+
| (SerializedConversation & { messages: SerializedMessage[] })
|
|
131
|
+
| null,
|
|
132
|
+
id: string,
|
|
133
|
+
context: LoaderContext,
|
|
134
|
+
) => Promise<boolean> | boolean;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Called when a loading error occurs
|
|
138
|
+
* @param error - The error that occurred
|
|
139
|
+
* @param context - Loader context
|
|
140
|
+
*/
|
|
141
|
+
onLoadError?: (error: Error, context: LoaderContext) => Promise<void> | void;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Loader for chat home page (list conversations)
|
|
145
|
+
function createConversationsLoader(config: AiChatClientConfig) {
|
|
146
|
+
return async () => {
|
|
147
|
+
// Skip loading in public mode - no persistence
|
|
148
|
+
if (config.mode === "public") {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (typeof window === "undefined") {
|
|
153
|
+
const { queryClient, apiBasePath, apiBaseURL, hooks, headers } = config;
|
|
154
|
+
|
|
155
|
+
const context: LoaderContext = {
|
|
156
|
+
path: "/chat",
|
|
157
|
+
isSSR: true,
|
|
158
|
+
apiBaseURL,
|
|
159
|
+
apiBasePath,
|
|
160
|
+
headers,
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
// Before hook
|
|
165
|
+
if (hooks?.beforeLoadConversations) {
|
|
166
|
+
const canLoad = await hooks.beforeLoadConversations(context);
|
|
167
|
+
if (!canLoad) {
|
|
168
|
+
throw new Error("Load prevented by beforeLoadConversations hook");
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const client = createApiClient<AiChatApiRouter>({
|
|
173
|
+
baseURL: apiBaseURL,
|
|
174
|
+
basePath: apiBasePath,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const queries = createAiChatQueryKeys(client, headers);
|
|
178
|
+
const listQuery = queries.conversations.list();
|
|
179
|
+
|
|
180
|
+
await queryClient.prefetchQuery(listQuery);
|
|
181
|
+
|
|
182
|
+
// After hook
|
|
183
|
+
if (hooks?.afterLoadConversations) {
|
|
184
|
+
const conversations =
|
|
185
|
+
queryClient.getQueryData<SerializedConversation[]>(
|
|
186
|
+
listQuery.queryKey,
|
|
187
|
+
) || null;
|
|
188
|
+
const canContinue = await hooks.afterLoadConversations(
|
|
189
|
+
conversations,
|
|
190
|
+
context,
|
|
191
|
+
);
|
|
192
|
+
if (canContinue === false) {
|
|
193
|
+
throw new Error("Load prevented by afterLoadConversations hook");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Check for errors
|
|
198
|
+
const queryState = queryClient.getQueryState(listQuery.queryKey);
|
|
199
|
+
if (queryState?.error && hooks?.onLoadError) {
|
|
200
|
+
const error =
|
|
201
|
+
queryState.error instanceof Error
|
|
202
|
+
? queryState.error
|
|
203
|
+
: new Error(String(queryState.error));
|
|
204
|
+
await hooks.onLoadError(error, context);
|
|
205
|
+
}
|
|
206
|
+
} catch (error) {
|
|
207
|
+
if (hooks?.onLoadError) {
|
|
208
|
+
await hooks.onLoadError(error as Error, context);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Loader for single conversation page
|
|
216
|
+
function createConversationLoader(id: string, config: AiChatClientConfig) {
|
|
217
|
+
return async () => {
|
|
218
|
+
if (typeof window === "undefined") {
|
|
219
|
+
const { queryClient, apiBasePath, apiBaseURL, hooks, headers } = config;
|
|
220
|
+
|
|
221
|
+
const context: LoaderContext = {
|
|
222
|
+
path: `/chat/${id}`,
|
|
223
|
+
params: { id },
|
|
224
|
+
isSSR: true,
|
|
225
|
+
apiBaseURL,
|
|
226
|
+
apiBasePath,
|
|
227
|
+
headers,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
// Before hook
|
|
232
|
+
if (hooks?.beforeLoadConversation) {
|
|
233
|
+
const canLoad = await hooks.beforeLoadConversation(id, context);
|
|
234
|
+
if (!canLoad) {
|
|
235
|
+
throw new Error("Load prevented by beforeLoadConversation hook");
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const client = createApiClient<AiChatApiRouter>({
|
|
240
|
+
baseURL: apiBaseURL,
|
|
241
|
+
basePath: apiBasePath,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
const queries = createAiChatQueryKeys(client, headers);
|
|
245
|
+
|
|
246
|
+
// Prefetch both the conversation and the conversations list
|
|
247
|
+
const conversationQuery = queries.conversations.detail(id);
|
|
248
|
+
const listQuery = queries.conversations.list();
|
|
249
|
+
|
|
250
|
+
await Promise.all([
|
|
251
|
+
queryClient.prefetchQuery(conversationQuery),
|
|
252
|
+
queryClient.prefetchQuery(listQuery),
|
|
253
|
+
]);
|
|
254
|
+
|
|
255
|
+
// After hook
|
|
256
|
+
if (hooks?.afterLoadConversation) {
|
|
257
|
+
const conversation =
|
|
258
|
+
queryClient.getQueryData<
|
|
259
|
+
SerializedConversation & { messages: SerializedMessage[] }
|
|
260
|
+
>(conversationQuery.queryKey) || null;
|
|
261
|
+
const canContinue = await hooks.afterLoadConversation(
|
|
262
|
+
conversation,
|
|
263
|
+
id,
|
|
264
|
+
context,
|
|
265
|
+
);
|
|
266
|
+
if (canContinue === false) {
|
|
267
|
+
throw new Error("Load prevented by afterLoadConversation hook");
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Check for errors
|
|
272
|
+
const queryState = queryClient.getQueryState(
|
|
273
|
+
conversationQuery.queryKey,
|
|
274
|
+
);
|
|
275
|
+
if (queryState?.error && hooks?.onLoadError) {
|
|
276
|
+
const error =
|
|
277
|
+
queryState.error instanceof Error
|
|
278
|
+
? queryState.error
|
|
279
|
+
: new Error(String(queryState.error));
|
|
280
|
+
await hooks.onLoadError(error, context);
|
|
281
|
+
}
|
|
282
|
+
} catch (error) {
|
|
283
|
+
if (hooks?.onLoadError) {
|
|
284
|
+
await hooks.onLoadError(error as Error, context);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Meta generator for chat home page
|
|
292
|
+
function createChatHomeMeta(config: AiChatClientConfig) {
|
|
293
|
+
return () => {
|
|
294
|
+
const { siteBaseURL, siteBasePath, seo } = config;
|
|
295
|
+
const fullUrl = `${siteBaseURL}${siteBasePath}/chat`;
|
|
296
|
+
const title = "Chat";
|
|
297
|
+
const description = seo?.description || "Start a conversation with AI";
|
|
298
|
+
|
|
299
|
+
return [
|
|
300
|
+
{ title },
|
|
301
|
+
{ name: "title", content: title },
|
|
302
|
+
{ name: "description", content: description },
|
|
303
|
+
{ name: "robots", content: "noindex, nofollow" }, // Chat pages typically shouldn't be indexed
|
|
304
|
+
|
|
305
|
+
// Open Graph
|
|
306
|
+
{ property: "og:type", content: "website" },
|
|
307
|
+
{ property: "og:title", content: title },
|
|
308
|
+
{ property: "og:description", content: description },
|
|
309
|
+
{ property: "og:url", content: fullUrl },
|
|
310
|
+
...(seo?.siteName
|
|
311
|
+
? [{ property: "og:site_name", content: seo.siteName }]
|
|
312
|
+
: []),
|
|
313
|
+
...(seo?.locale ? [{ property: "og:locale", content: seo.locale }] : []),
|
|
314
|
+
...(seo?.defaultImage
|
|
315
|
+
? [{ property: "og:image", content: seo.defaultImage }]
|
|
316
|
+
: []),
|
|
317
|
+
|
|
318
|
+
// Twitter
|
|
319
|
+
{ name: "twitter:card", content: "summary" },
|
|
320
|
+
{ name: "twitter:title", content: title },
|
|
321
|
+
{ name: "twitter:description", content: description },
|
|
322
|
+
];
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Meta generator for single conversation page
|
|
327
|
+
function createConversationMeta(id: string, config: AiChatClientConfig) {
|
|
328
|
+
return () => {
|
|
329
|
+
const {
|
|
330
|
+
queryClient,
|
|
331
|
+
apiBaseURL,
|
|
332
|
+
apiBasePath,
|
|
333
|
+
siteBaseURL,
|
|
334
|
+
siteBasePath,
|
|
335
|
+
seo,
|
|
336
|
+
} = config;
|
|
337
|
+
const queries = createAiChatQueryKeys(
|
|
338
|
+
createApiClient<AiChatApiRouter>({
|
|
339
|
+
baseURL: apiBaseURL,
|
|
340
|
+
basePath: apiBasePath,
|
|
341
|
+
}),
|
|
342
|
+
);
|
|
343
|
+
|
|
344
|
+
const conversation = queryClient.getQueryData<
|
|
345
|
+
SerializedConversation & { messages: SerializedMessage[] }
|
|
346
|
+
>(queries.conversations.detail(id).queryKey);
|
|
347
|
+
|
|
348
|
+
const fullUrl = `${siteBaseURL}${siteBasePath}/chat/${id}`;
|
|
349
|
+
const title = conversation?.title || "Chat";
|
|
350
|
+
const description = seo?.description || "AI conversation";
|
|
351
|
+
|
|
352
|
+
return [
|
|
353
|
+
{ title },
|
|
354
|
+
{ name: "title", content: title },
|
|
355
|
+
{ name: "description", content: description },
|
|
356
|
+
{ name: "robots", content: "noindex, nofollow" },
|
|
357
|
+
|
|
358
|
+
// Open Graph
|
|
359
|
+
{ property: "og:type", content: "website" },
|
|
360
|
+
{ property: "og:title", content: title },
|
|
361
|
+
{ property: "og:description", content: description },
|
|
362
|
+
{ property: "og:url", content: fullUrl },
|
|
363
|
+
...(seo?.siteName
|
|
364
|
+
? [{ property: "og:site_name", content: seo.siteName }]
|
|
365
|
+
: []),
|
|
366
|
+
|
|
367
|
+
// Twitter
|
|
368
|
+
{ name: "twitter:card", content: "summary" },
|
|
369
|
+
{ name: "twitter:title", content: title },
|
|
370
|
+
];
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* AI Chat client plugin
|
|
376
|
+
* Provides routes, components, and React Query hooks for AI chat
|
|
377
|
+
*
|
|
378
|
+
* @param config - Configuration including queryClient, baseURL, and optional hooks
|
|
379
|
+
*/
|
|
380
|
+
export const aiChatClientPlugin = (config: AiChatClientConfig) => {
|
|
381
|
+
const isPublicMode = config.mode === "public";
|
|
382
|
+
|
|
383
|
+
// Define routes based on mode
|
|
384
|
+
// In public mode, only the base chat route is available
|
|
385
|
+
// In authenticated mode, conversation routes are also available
|
|
386
|
+
if (isPublicMode) {
|
|
387
|
+
return defineClientPlugin({
|
|
388
|
+
name: "ai-chat",
|
|
389
|
+
|
|
390
|
+
routes: () => ({
|
|
391
|
+
// Chat home - simple chat interface without history
|
|
392
|
+
chat: createRoute("/chat", () => ({
|
|
393
|
+
PageComponent: () => (
|
|
394
|
+
<ChatLayout
|
|
395
|
+
apiBaseURL={config.apiBaseURL}
|
|
396
|
+
apiBasePath={config.apiBasePath}
|
|
397
|
+
showSidebar={false}
|
|
398
|
+
/>
|
|
399
|
+
),
|
|
400
|
+
loader: createConversationsLoader(config),
|
|
401
|
+
meta: createChatHomeMeta(config),
|
|
402
|
+
})),
|
|
403
|
+
}),
|
|
404
|
+
|
|
405
|
+
sitemap: async () => [],
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Authenticated mode - full chat with conversation history
|
|
410
|
+
return defineClientPlugin({
|
|
411
|
+
name: "ai-chat",
|
|
412
|
+
|
|
413
|
+
routes: () => ({
|
|
414
|
+
// Chat home - new conversation or list
|
|
415
|
+
chat: createRoute("/chat", () => ({
|
|
416
|
+
PageComponent: () => (
|
|
417
|
+
<ChatLayout
|
|
418
|
+
apiBaseURL={config.apiBaseURL}
|
|
419
|
+
apiBasePath={config.apiBasePath}
|
|
420
|
+
/>
|
|
421
|
+
),
|
|
422
|
+
loader: createConversationsLoader(config),
|
|
423
|
+
meta: createChatHomeMeta(config),
|
|
424
|
+
})),
|
|
425
|
+
|
|
426
|
+
// Existing conversation
|
|
427
|
+
chatConversation: createRoute("/chat/:id", ({ params }) => ({
|
|
428
|
+
PageComponent: () => (
|
|
429
|
+
<ChatLayout
|
|
430
|
+
apiBaseURL={config.apiBaseURL}
|
|
431
|
+
apiBasePath={config.apiBasePath}
|
|
432
|
+
conversationId={params.id}
|
|
433
|
+
/>
|
|
434
|
+
),
|
|
435
|
+
loader: createConversationLoader(params.id, config),
|
|
436
|
+
meta: createConversationMeta(params.id, config),
|
|
437
|
+
})),
|
|
438
|
+
}),
|
|
439
|
+
|
|
440
|
+
// Chat pages typically shouldn't be in sitemap, but we provide the option
|
|
441
|
+
sitemap: async () => {
|
|
442
|
+
// Return empty array - chat conversations are private and shouldn't be indexed
|
|
443
|
+
return [];
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
export type { SerializedConversation, SerializedMessage } from "../types";
|
|
449
|
+
export type { AiChatMode } from "./overrides";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/* AI Chat Plugin Client Styles */
|
|
2
|
+
/* NOTE:
|
|
3
|
+
* Markdown + syntax highlighting styles are imported from code (TS/TSX),
|
|
4
|
+
* matching the blog plugin approach. This avoids brittle nested @import
|
|
5
|
+
* resolution when consumers import `@btst/stack/plugins/ai-chat/css`.
|
|
6
|
+
*/
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { createDbPlugin } from "@btst/db";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* AI Chat plugin schema
|
|
5
|
+
* Defines the database tables for conversations and messages
|
|
6
|
+
*/
|
|
7
|
+
export const aiChatSchema = createDbPlugin("aiChat", {
|
|
8
|
+
conversation: {
|
|
9
|
+
modelName: "conversation",
|
|
10
|
+
fields: {
|
|
11
|
+
id: {
|
|
12
|
+
type: "string",
|
|
13
|
+
required: true,
|
|
14
|
+
unique: true,
|
|
15
|
+
},
|
|
16
|
+
userId: {
|
|
17
|
+
type: "string",
|
|
18
|
+
required: false,
|
|
19
|
+
},
|
|
20
|
+
title: {
|
|
21
|
+
type: "string",
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
createdAt: {
|
|
25
|
+
type: "date",
|
|
26
|
+
defaultValue: () => new Date(),
|
|
27
|
+
},
|
|
28
|
+
updatedAt: {
|
|
29
|
+
type: "date",
|
|
30
|
+
defaultValue: () => new Date(),
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
message: {
|
|
35
|
+
modelName: "message",
|
|
36
|
+
fields: {
|
|
37
|
+
id: {
|
|
38
|
+
type: "string",
|
|
39
|
+
required: true,
|
|
40
|
+
unique: true,
|
|
41
|
+
},
|
|
42
|
+
conversationId: {
|
|
43
|
+
type: "string",
|
|
44
|
+
required: true,
|
|
45
|
+
references: {
|
|
46
|
+
model: "conversation",
|
|
47
|
+
field: "id",
|
|
48
|
+
onDelete: "cascade",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
role: {
|
|
52
|
+
type: "string",
|
|
53
|
+
required: true,
|
|
54
|
+
},
|
|
55
|
+
content: {
|
|
56
|
+
type: "string",
|
|
57
|
+
required: true,
|
|
58
|
+
},
|
|
59
|
+
createdAt: {
|
|
60
|
+
type: "date",
|
|
61
|
+
defaultValue: () => new Date(),
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mergeQueryKeys,
|
|
3
|
+
createQueryKeys,
|
|
4
|
+
} from "@lukemorales/query-key-factory";
|
|
5
|
+
import type { AiChatApiRouter } from "./api";
|
|
6
|
+
import { createApiClient } from "@btst/stack/plugins/client";
|
|
7
|
+
import type { SerializedConversation, SerializedMessage } from "./types";
|
|
8
|
+
|
|
9
|
+
// Helper to check and handle error responses
|
|
10
|
+
function handleResponse<T>(response: unknown): T {
|
|
11
|
+
if (
|
|
12
|
+
typeof response === "object" &&
|
|
13
|
+
response !== null &&
|
|
14
|
+
"error" in response
|
|
15
|
+
) {
|
|
16
|
+
const errorResponse = response as { error?: unknown };
|
|
17
|
+
if (errorResponse.error !== null && errorResponse.error !== undefined) {
|
|
18
|
+
const error = errorResponse.error;
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
if (typeof error === "object" && error !== null) {
|
|
23
|
+
const errorObj = error as Record<string, unknown>;
|
|
24
|
+
const message =
|
|
25
|
+
(typeof errorObj.message === "string" ? errorObj.message : null) ||
|
|
26
|
+
(typeof errorObj.error === "string" ? errorObj.error : null) ||
|
|
27
|
+
JSON.stringify(error);
|
|
28
|
+
throw new Error(message);
|
|
29
|
+
}
|
|
30
|
+
throw new Error(String(error));
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return (response as { data?: T }).data as T;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type ConversationWithMessages = SerializedConversation & {
|
|
37
|
+
messages: SerializedMessage[];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function createAiChatQueryKeys(
|
|
41
|
+
client: ReturnType<typeof createApiClient<AiChatApiRouter>>,
|
|
42
|
+
headers?: HeadersInit,
|
|
43
|
+
) {
|
|
44
|
+
const conversations = createConversationsQueries(client, headers);
|
|
45
|
+
|
|
46
|
+
return mergeQueryKeys(conversations);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function createConversationsQueries(
|
|
50
|
+
client: ReturnType<typeof createApiClient<AiChatApiRouter>>,
|
|
51
|
+
headers?: HeadersInit,
|
|
52
|
+
) {
|
|
53
|
+
return createQueryKeys("conversations", {
|
|
54
|
+
// List all conversations
|
|
55
|
+
list: () => ({
|
|
56
|
+
// NOTE: query-key-factory already namespaces as:
|
|
57
|
+
// ["conversations", "list", ...queryKey]
|
|
58
|
+
// so we use a stable marker (not "list") to avoid ["...","list","list"].
|
|
59
|
+
queryKey: ["all"],
|
|
60
|
+
queryFn: async () => {
|
|
61
|
+
const response = await client("/chat/conversations", {
|
|
62
|
+
method: "GET",
|
|
63
|
+
headers,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const data = handleResponse<SerializedConversation[] | null>(response);
|
|
67
|
+
return data ?? [];
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
|
|
71
|
+
// Get single conversation with messages
|
|
72
|
+
detail: (id: string) => ({
|
|
73
|
+
queryKey: [id],
|
|
74
|
+
queryFn: async () => {
|
|
75
|
+
if (!id) return null;
|
|
76
|
+
|
|
77
|
+
const response = await client("/chat/conversations/:id", {
|
|
78
|
+
method: "GET",
|
|
79
|
+
params: { id },
|
|
80
|
+
headers,
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
return handleResponse<ConversationWithMessages | null>(response);
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const createConversationSchema = z.object({
|
|
4
|
+
id: z.string().optional(),
|
|
5
|
+
title: z.string().optional(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const updateConversationSchema = z.object({
|
|
9
|
+
title: z.string().optional(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const chatRequestSchema = z.object({
|
|
13
|
+
messages: z.array(
|
|
14
|
+
z.union([
|
|
15
|
+
// Format with content string
|
|
16
|
+
z.object({
|
|
17
|
+
role: z.enum(["system", "user", "assistant", "data"]),
|
|
18
|
+
content: z.string(),
|
|
19
|
+
id: z.string().optional(),
|
|
20
|
+
}),
|
|
21
|
+
// Format with parts array (from UIMessage)
|
|
22
|
+
z.object({
|
|
23
|
+
role: z.enum(["system", "user", "assistant", "data"]),
|
|
24
|
+
parts: z.array(
|
|
25
|
+
z
|
|
26
|
+
.object({
|
|
27
|
+
type: z.string(),
|
|
28
|
+
text: z.string().optional(),
|
|
29
|
+
// Allow other properties that might be present
|
|
30
|
+
})
|
|
31
|
+
.loose(),
|
|
32
|
+
),
|
|
33
|
+
id: z.string().optional(),
|
|
34
|
+
metadata: z.any().optional(),
|
|
35
|
+
}),
|
|
36
|
+
]),
|
|
37
|
+
),
|
|
38
|
+
conversationId: z.string().optional(),
|
|
39
|
+
model: z.string().optional(),
|
|
40
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
@import "./client.css";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* AI Chat Plugin CSS - Includes Tailwind class scanning
|
|
5
|
+
*
|
|
6
|
+
* When consumed from npm, Tailwind v4 will automatically scan this package's
|
|
7
|
+
* source files for Tailwind classes. Consumers only need:
|
|
8
|
+
* @import "@btst/stack/plugins/ai-chat/css";
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/* Scan this package's source files for Tailwind classes */
|
|
12
|
+
@source "../../../src/**/*.{ts,tsx}";
|
|
13
|
+
|
|
14
|
+
/* Scan UI package components (when installed as npm package the UI package will be in this dir) */
|
|
15
|
+
@source "../../packages/ui/src";
|
|
16
|
+
|
|
17
|
+
/*
|
|
18
|
+
* alternatively consumer can use @source "../node_modules/@btst/stack/src/**\/*.{ts,tsx}";
|
|
19
|
+
*/
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export type Conversation = {
|
|
2
|
+
id: string;
|
|
3
|
+
userId?: string;
|
|
4
|
+
title: string;
|
|
5
|
+
createdAt: Date;
|
|
6
|
+
updatedAt: Date;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type ConversationWithMessages = Conversation & {
|
|
10
|
+
message?: Message[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export type Message = {
|
|
14
|
+
id: string;
|
|
15
|
+
conversationId: string;
|
|
16
|
+
role: "system" | "user" | "assistant" | "data";
|
|
17
|
+
content: string;
|
|
18
|
+
createdAt: Date;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export interface SerializedConversation
|
|
22
|
+
extends Omit<Conversation, "createdAt" | "updatedAt"> {
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface SerializedMessage extends Omit<Message, "createdAt"> {
|
|
28
|
+
createdAt: string;
|
|
29
|
+
}
|