@flamingo-stack/openframe-frontend-core 0.0.204 → 0.0.205
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/dist/{chunk-4CWSZPXH.cjs → chunk-24KCAECR.cjs} +9 -9
- package/dist/{chunk-4CWSZPXH.cjs.map → chunk-24KCAECR.cjs.map} +1 -1
- package/dist/chunk-27APPAJN.cjs +24 -0
- package/dist/chunk-27APPAJN.cjs.map +1 -0
- package/dist/{chunk-UC43NICZ.cjs → chunk-664KA5FI.cjs} +2 -35
- package/dist/chunk-664KA5FI.cjs.map +1 -0
- package/dist/chunk-6RZYJICV.cjs +24 -0
- package/dist/chunk-6RZYJICV.cjs.map +1 -0
- package/dist/chunk-7L4DWM7P.js +24 -0
- package/dist/chunk-7L4DWM7P.js.map +1 -0
- package/dist/chunk-BZFW3FOF.cjs +21 -0
- package/dist/chunk-BZFW3FOF.cjs.map +1 -0
- package/dist/{chunk-N57KWHDB.js → chunk-CIPO6DXK.js} +5 -5
- package/dist/chunk-EL5YVPD5.js +21 -0
- package/dist/chunk-EL5YVPD5.js.map +1 -0
- package/dist/{chunk-ARQ4XP64.cjs → chunk-FDCFI7YT.cjs} +40080 -31492
- package/dist/chunk-FDCFI7YT.cjs.map +1 -0
- package/dist/chunk-G7UE6RKV.cjs +121 -0
- package/dist/chunk-G7UE6RKV.cjs.map +1 -0
- package/dist/{chunk-25LVV26X.cjs → chunk-JUZGUQMX.cjs} +178 -50
- package/dist/chunk-JUZGUQMX.cjs.map +1 -0
- package/dist/{chunk-SZPJ5R5B.js → chunk-KSOOKNBG.js} +1 -34
- package/dist/chunk-KSOOKNBG.js.map +1 -0
- package/dist/{chunk-RMB5DVED.cjs → chunk-KUZGEA7U.cjs} +83 -66
- package/dist/chunk-KUZGEA7U.cjs.map +1 -0
- package/dist/chunk-LXC6P2EO.js +63 -0
- package/dist/chunk-LXC6P2EO.js.map +1 -0
- package/dist/chunk-MJNXIEV2.js +24 -0
- package/dist/chunk-MJNXIEV2.js.map +1 -0
- package/dist/{chunk-CPXLQ57U.js → chunk-MVGGXOFA.js} +37 -20
- package/dist/chunk-MVGGXOFA.js.map +1 -0
- package/dist/{chunk-LY34ORX6.js → chunk-O55ZUAX7.js} +39920 -31332
- package/dist/chunk-O55ZUAX7.js.map +1 -0
- package/dist/chunk-OHPI2HRK.js +47 -0
- package/dist/chunk-OHPI2HRK.js.map +1 -0
- package/dist/chunk-PLJLE4A4.js +121 -0
- package/dist/chunk-PLJLE4A4.js.map +1 -0
- package/dist/{chunk-XGL5FKIK.js → chunk-SCN5WFIZ.js} +148 -20
- package/dist/chunk-SCN5WFIZ.js.map +1 -0
- package/dist/chunk-WBR7H6E3.cjs +47 -0
- package/dist/chunk-WBR7H6E3.cjs.map +1 -0
- package/dist/chunk-XL4V2PYG.cjs +63 -0
- package/dist/chunk-XL4V2PYG.cjs.map +1 -0
- package/dist/components/announcement-bar.d.ts.map +1 -1
- package/dist/components/chat/chat-attachment-bar.d.ts +66 -0
- package/dist/components/chat/chat-attachment-bar.d.ts.map +1 -0
- package/dist/components/chat/chat-container.d.ts +21 -1
- package/dist/components/chat/chat-container.d.ts.map +1 -1
- package/dist/components/chat/chat-input.d.ts.map +1 -1
- package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
- package/dist/components/chat/chat-message-list.d.ts.map +1 -1
- package/dist/components/chat/chat-panel-context.d.ts +9 -0
- package/dist/components/chat/chat-panel-context.d.ts.map +1 -0
- package/dist/components/chat/chat-ticket-list.d.ts +1 -1
- package/dist/components/chat/chat-ticket-list.d.ts.map +1 -1
- package/dist/components/chat/embeddable-chat.d.ts +42 -0
- package/dist/components/chat/embeddable-chat.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/admin-content-card.d.ts +34 -0
- package/dist/components/chat/entity-cards/admin-content-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/block-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/blog-card.d.ts +30 -0
- package/dist/components/chat/entity-cards/blog-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts +26 -0
- package/dist/components/chat/entity-cards/blog-image-placeholder.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/campaign-card-admin.d.ts +33 -0
- package/dist/components/chat/entity-cards/campaign-card-admin.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/case-study-card.d.ts +20 -0
- package/dist/components/chat/entity-cards/case-study-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/chat-ticket-item.d.ts.map +1 -0
- package/dist/components/chat/{chat-video-entity-card.d.ts → entity-cards/chat-video-entity-card.d.ts} +1 -1
- package/dist/components/chat/entity-cards/chat-video-entity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/customer-interview-card.d.ts +19 -0
- package/dist/components/chat/entity-cards/customer-interview-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/data-room-doc-card.d.ts +47 -0
- package/dist/components/chat/entity-cards/data-room-doc-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts +119 -0
- package/dist/components/chat/entity-cards/dispatch.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/entity-author-card.d.ts +87 -0
- package/dist/components/chat/entity-cards/entity-author-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/generic-entity-card.d.ts +42 -0
- package/dist/components/chat/entity-cards/generic-entity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/github-activity-card.d.ts +37 -0
- package/dist/components/chat/entity-cards/github-activity-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/hubspot-ticket-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/index.d.ts +32 -0
- package/dist/components/chat/entity-cards/index.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/investor-update-card.d.ts +19 -0
- package/dist/components/chat/entity-cards/investor-update-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts +20 -0
- package/dist/components/chat/entity-cards/onboarding-guide-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts +21 -0
- package/dist/components/chat/entity-cards/product-release-card-defaults.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/product-release-card.d.ts +12 -0
- package/dist/components/chat/entity-cards/product-release-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/program-card-defaults.d.ts +32 -0
- package/dist/components/chat/entity-cards/program-card-defaults.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/program-card.d.ts +37 -0
- package/dist/components/chat/entity-cards/program-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/roadmap-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/roadmap-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts +12 -0
- package/dist/components/chat/entity-cards/roadmap-vote-button.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/slack-message-card.d.ts +28 -0
- package/dist/components/chat/entity-cards/slack-message-card.d.ts.map +1 -0
- package/dist/components/chat/entity-cards/task-type-icon.d.ts +6 -0
- package/dist/components/chat/entity-cards/task-type-icon.d.ts.map +1 -0
- package/dist/components/chat/hooks/index.d.ts +10 -0
- package/dist/components/chat/hooks/index.d.ts.map +1 -1
- package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts +5 -0
- package/dist/components/chat/hooks/use-chat-attachment-image-gallery.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-attachments.d.ts +33 -0
- package/dist/components/chat/hooks/use-chat-attachments.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-card-item.d.ts +7 -0
- package/dist/components/chat/hooks/use-chat-card-item.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat-identity.d.ts +44 -0
- package/dist/components/chat/hooks/use-chat-identity.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-chat.d.ts +30 -0
- package/dist/components/chat/hooks/use-chat.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-close-on-navigation.d.ts +2 -0
- package/dist/components/chat/hooks/use-close-on-navigation.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-embedded-chat.d.ts +174 -0
- package/dist/components/chat/hooks/use-embedded-chat.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-proxied-image-url.d.ts +18 -0
- package/dist/components/chat/hooks/use-proxied-image-url.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-slash-commands.d.ts +32 -0
- package/dist/components/chat/hooks/use-slash-commands.d.ts.map +1 -0
- package/dist/components/chat/hooks/use-sse.d.ts +57 -0
- package/dist/components/chat/hooks/use-sse.d.ts.map +1 -0
- package/dist/components/chat/index.cjs +393 -0
- package/dist/components/chat/index.cjs.map +1 -0
- package/dist/components/chat/index.d.ts +5 -3
- package/dist/components/chat/index.d.ts.map +1 -1
- package/dist/components/chat/index.js +393 -0
- package/dist/components/chat/index.js.map +1 -0
- package/dist/components/chat/nav-link-anchor-via-runtime.d.ts +33 -0
- package/dist/components/chat/nav-link-anchor-via-runtime.d.ts.map +1 -0
- package/dist/components/chat/source-action-button.d.ts +39 -0
- package/dist/components/chat/source-action-button.d.ts.map +1 -0
- package/dist/components/chat/types/chat.types.d.ts +36 -0
- package/dist/components/chat/types/chat.types.d.ts.map +1 -1
- package/dist/components/chat/types/component.types.d.ts +56 -11
- package/dist/components/chat/types/component.types.d.ts.map +1 -1
- package/dist/components/chat/types/entities/blog.d.ts +14 -0
- package/dist/components/chat/types/entities/blog.d.ts.map +1 -0
- package/dist/components/chat/types/entities/case-study.d.ts +10 -0
- package/dist/components/chat/types/entities/case-study.d.ts.map +1 -0
- package/dist/components/chat/types/entities/content-ref.d.ts +23 -0
- package/dist/components/chat/types/entities/content-ref.d.ts.map +1 -0
- package/dist/components/chat/types/entities/customer-interview.d.ts +10 -0
- package/dist/components/chat/types/entities/customer-interview.d.ts.map +1 -0
- package/dist/components/chat/types/entities/data-room-doc.d.ts +37 -0
- package/dist/components/chat/types/entities/data-room-doc.d.ts.map +1 -0
- package/dist/components/chat/types/entities/github-activity.d.ts +29 -0
- package/dist/components/chat/types/entities/github-activity.d.ts.map +1 -0
- package/dist/components/chat/types/entities/hubspot-ticket.d.ts +39 -0
- package/dist/components/chat/types/entities/hubspot-ticket.d.ts.map +1 -0
- package/dist/components/chat/types/entities/index.d.ts +28 -0
- package/dist/components/chat/types/entities/index.d.ts.map +1 -0
- package/dist/components/chat/types/entities/investor-update.d.ts +83 -0
- package/dist/components/chat/types/entities/investor-update.d.ts.map +1 -0
- package/dist/components/chat/types/entities/onboarding-guide.d.ts +79 -0
- package/dist/components/chat/types/entities/onboarding-guide.d.ts.map +1 -0
- package/dist/components/chat/types/entities/program-types.d.ts +303 -0
- package/dist/components/chat/types/entities/program-types.d.ts.map +1 -0
- package/dist/components/chat/types/entities/roadmap-item.d.ts +41 -0
- package/dist/components/chat/types/entities/roadmap-item.d.ts.map +1 -0
- package/dist/components/chat/types/entities/slack-message.d.ts +28 -0
- package/dist/components/chat/types/entities/slack-message.d.ts.map +1 -0
- package/dist/components/chat/types/index.d.ts +1 -0
- package/dist/components/chat/types/index.d.ts.map +1 -1
- package/dist/components/chat/utils/agent-status-message.d.ts +18 -0
- package/dist/components/chat/utils/agent-status-message.d.ts.map +1 -0
- package/dist/components/chat/utils/auto-continuation-directive.d.ts +38 -0
- package/dist/components/chat/utils/auto-continuation-directive.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-attachment-markdown.d.ts +114 -0
- package/dist/components/chat/utils/chat-attachment-markdown.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-authed-fetch.d.ts +13 -0
- package/dist/components/chat/utils/chat-authed-fetch.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-nav-resolution.d.ts +72 -0
- package/dist/components/chat/utils/chat-nav-resolution.d.ts.map +1 -0
- package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts +43 -0
- package/dist/components/chat/utils/chat-proxy-auth-storage.d.ts.map +1 -0
- package/dist/components/chat/utils/chip-action-class.d.ts +16 -0
- package/dist/components/chat/utils/chip-action-class.d.ts.map +1 -0
- package/dist/components/chat/utils/chip-styles.d.ts +32 -0
- package/dist/components/chat/utils/chip-styles.d.ts.map +1 -0
- package/dist/components/chat/utils/clickup-task-type-utils.d.ts +38 -0
- package/dist/components/chat/utils/clickup-task-type-utils.d.ts.map +1 -0
- package/dist/components/chat/utils/compact-card-classes.d.ts +50 -0
- package/dist/components/chat/utils/compact-card-classes.d.ts.map +1 -0
- package/dist/components/chat/utils/decide-new-tab.d.ts +39 -0
- package/dist/components/chat/utils/decide-new-tab.d.ts.map +1 -0
- package/dist/components/chat/utils/external-app-urls.d.ts +14 -0
- package/dist/components/chat/utils/external-app-urls.d.ts.map +1 -0
- package/dist/components/chat/utils/flatten-assistant-content.d.ts +25 -0
- package/dist/components/chat/utils/flatten-assistant-content.d.ts.map +1 -0
- package/dist/components/chat/utils/icon-registry.d.ts +67 -0
- package/dist/components/chat/utils/icon-registry.d.ts.map +1 -0
- package/dist/components/chat/utils/index.d.ts +21 -0
- package/dist/components/chat/utils/index.d.ts.map +1 -1
- package/dist/components/chat/utils/is-cross-origin-url.d.ts +22 -0
- package/dist/components/chat/utils/is-cross-origin-url.d.ts.map +1 -0
- package/dist/components/chat/utils/nav-anchor-props.d.ts +54 -0
- package/dist/components/chat/utils/nav-anchor-props.d.ts.map +1 -0
- package/dist/components/chat/utils/nav-click-handler.d.ts +51 -0
- package/dist/components/chat/utils/nav-click-handler.d.ts.map +1 -0
- package/dist/components/chat/utils/scroll-anchor.d.ts +30 -0
- package/dist/components/chat/utils/scroll-anchor.d.ts.map +1 -0
- package/dist/components/chat/utils/slash-dispatch-utils.d.ts +109 -0
- package/dist/components/chat/utils/slash-dispatch-utils.d.ts.map +1 -0
- package/dist/components/chat/utils/source-icons.d.ts +8 -0
- package/dist/components/chat/utils/source-icons.d.ts.map +1 -0
- package/dist/components/chat/utils/source-row-cta.d.ts +111 -0
- package/dist/components/chat/utils/source-row-cta.d.ts.map +1 -0
- package/dist/components/features/figma-prototype-viewer.d.ts.map +1 -1
- package/dist/components/features/index.cjs +12 -6
- package/dist/components/features/index.cjs.map +1 -1
- package/dist/components/features/index.js +11 -5
- package/dist/components/features/video.d.ts.map +1 -1
- package/dist/components/icons/index.cjs +3 -3
- package/dist/components/icons/index.js +2 -2
- package/dist/components/index.cjs +274 -8
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +273 -7
- package/dist/components/interactive-wrapper.d.ts +3 -3
- package/dist/components/navigation/index.cjs +12 -6
- package/dist/components/navigation/index.cjs.map +1 -1
- package/dist/components/navigation/index.js +11 -5
- package/dist/components/resizable.d.ts +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts +1 -1
- package/dist/components/shared/product-release/product-release-card-skeleton.d.ts.map +1 -1
- package/dist/components/shared/product-release/product-release-card.d.ts +19 -12
- package/dist/components/shared/product-release/product-release-card.d.ts.map +1 -1
- package/dist/components/shared/product-release/release-detail-page.d.ts +2 -4
- package/dist/components/shared/product-release/release-detail-page.d.ts.map +1 -1
- package/dist/components/ui/button/button.d.ts +13 -0
- package/dist/components/ui/button/button.d.ts.map +1 -1
- package/dist/components/ui/dashboard-info-card.d.ts.map +1 -1
- package/dist/components/ui/entity-image.d.ts.map +1 -1
- package/dist/components/ui/file-manager/index.cjs +71 -70
- package/dist/components/ui/file-manager/index.cjs.map +1 -1
- package/dist/components/ui/file-manager/index.js +6 -5
- package/dist/components/ui/file-manager/index.js.map +1 -1
- package/dist/components/ui/hover-dropdown.d.ts +66 -0
- package/dist/components/ui/hover-dropdown.d.ts.map +1 -0
- package/dist/components/ui/index.cjs +276 -6
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +278 -8
- package/dist/components/ui/simple-markdown-renderer.d.ts.map +1 -1
- package/dist/components/ui/square-avatar.d.ts.map +1 -1
- package/dist/contexts/chat-runtime-context.d.ts +109 -0
- package/dist/contexts/chat-runtime-context.d.ts.map +1 -0
- package/dist/contexts/endpoints-runtime-context.d.ts +28 -0
- package/dist/contexts/endpoints-runtime-context.d.ts.map +1 -0
- package/dist/contexts/index.cjs +30 -0
- package/dist/contexts/index.cjs.map +1 -0
- package/dist/contexts/index.d.ts +26 -0
- package/dist/contexts/index.d.ts.map +1 -0
- package/dist/contexts/index.js +30 -0
- package/dist/contexts/index.js.map +1 -0
- package/dist/contexts/use-outer-or-default.d.ts +29 -0
- package/dist/contexts/use-outer-or-default.d.ts.map +1 -0
- package/dist/embed-shims/index.cjs +51 -0
- package/dist/embed-shims/index.cjs.map +1 -0
- package/dist/embed-shims/index.d.ts +31 -0
- package/dist/embed-shims/index.d.ts.map +1 -0
- package/dist/embed-shims/index.js +51 -0
- package/dist/embed-shims/index.js.map +1 -0
- package/dist/embed-shims/next-dynamic.cjs +12 -0
- package/dist/embed-shims/next-dynamic.cjs.map +1 -0
- package/dist/embed-shims/next-dynamic.d.ts +47 -0
- package/dist/embed-shims/next-dynamic.d.ts.map +1 -0
- package/dist/embed-shims/next-dynamic.js +12 -0
- package/dist/embed-shims/next-dynamic.js.map +1 -0
- package/dist/embed-shims/next-image.cjs +12 -0
- package/dist/embed-shims/next-image.cjs.map +1 -0
- package/dist/embed-shims/next-image.d.ts +28 -0
- package/dist/embed-shims/next-image.d.ts.map +1 -0
- package/dist/embed-shims/next-image.js +12 -0
- package/dist/embed-shims/next-image.js.map +1 -0
- package/dist/embed-shims/next-link.cjs +14 -0
- package/dist/embed-shims/next-link.cjs.map +1 -0
- package/dist/embed-shims/next-link.d.ts +22 -0
- package/dist/embed-shims/next-link.d.ts.map +1 -0
- package/dist/embed-shims/next-link.js +14 -0
- package/dist/embed-shims/next-link.js.map +1 -0
- package/dist/embed-shims/next-navigation.cjs +30 -0
- package/dist/embed-shims/next-navigation.cjs.map +1 -0
- package/dist/embed-shims/next-navigation.d.ts +46 -0
- package/dist/embed-shims/next-navigation.d.ts.map +1 -0
- package/dist/embed-shims/next-navigation.js +30 -0
- package/dist/embed-shims/next-navigation.js.map +1 -0
- package/dist/hooks/index.cjs +10 -4
- package/dist/hooks/index.cjs.map +1 -1
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +9 -3
- package/dist/hooks/use-access-code-integration.d.ts +48 -0
- package/dist/hooks/use-access-code-integration.d.ts.map +1 -0
- package/dist/hooks/use-contact-submission.d.ts.map +1 -1
- package/dist/hooks/use-og-placeholder.d.ts +31 -0
- package/dist/hooks/use-og-placeholder.d.ts.map +1 -0
- package/dist/hooks/use-toast.d.ts +1 -1
- package/dist/index.cjs +367 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +378 -18
- package/dist/types/index.cjs.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/access-code-client.d.ts +21 -37
- package/dist/utils/access-code-client.d.ts.map +1 -1
- package/dist/utils/cn.d.ts +0 -27
- package/dist/utils/cn.d.ts.map +1 -1
- package/dist/utils/color-analysis.d.ts +33 -0
- package/dist/utils/color-analysis.d.ts.map +1 -0
- package/dist/utils/date-formatters.d.ts +16 -5
- package/dist/utils/date-formatters.d.ts.map +1 -1
- package/dist/utils/fetch-priority.d.ts +3 -0
- package/dist/utils/fetch-priority.d.ts.map +1 -0
- package/dist/utils/format.d.ts +192 -1
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/image-proxy.d.ts +67 -2
- package/dist/utils/image-proxy.d.ts.map +1 -1
- package/dist/utils/index.cjs +1274 -155
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.ts +19 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1200 -157
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/local-storage-adapter.d.ts +46 -0
- package/dist/utils/local-storage-adapter.d.ts.map +1 -0
- package/dist/utils/source-icons.d.ts +78 -0
- package/dist/utils/source-icons.d.ts.map +1 -0
- package/package.json +29 -2
- package/src/components/announcement-bar.tsx +26 -4
- package/src/components/categories-cart.tsx +1 -1
- package/src/components/chat/chat-attachment-bar.tsx +323 -0
- package/src/components/chat/chat-container.tsx +39 -5
- package/src/components/chat/chat-input.tsx +7 -1
- package/src/components/chat/chat-message-enhanced.tsx +32 -22
- package/src/components/chat/chat-message-list.tsx +53 -4
- package/src/components/chat/chat-panel-context.tsx +37 -0
- package/src/components/chat/chat-ticket-list.tsx +1 -1
- package/src/components/chat/embeddable-chat.tsx +1106 -0
- package/src/components/chat/entity-cards/admin-content-card.tsx +155 -0
- package/src/components/chat/entity-cards/blog-card.tsx +259 -0
- package/src/components/chat/entity-cards/blog-image-placeholder.tsx +52 -0
- package/src/components/chat/entity-cards/campaign-card-admin.tsx +113 -0
- package/src/components/chat/entity-cards/case-study-card.tsx +192 -0
- package/src/components/chat/{chat-ticket-item.tsx → entity-cards/chat-ticket-item.tsx} +2 -2
- package/src/components/chat/{chat-video-entity-card.tsx → entity-cards/chat-video-entity-card.tsx} +2 -2
- package/src/components/chat/entity-cards/customer-interview-card.tsx +211 -0
- package/src/components/chat/entity-cards/data-room-doc-card.tsx +120 -0
- package/src/components/chat/entity-cards/dispatch.tsx +1093 -0
- package/src/components/chat/entity-cards/entity-author-card.tsx +193 -0
- package/src/components/chat/entity-cards/generic-entity-card.tsx +144 -0
- package/src/components/chat/entity-cards/github-activity-card.tsx +305 -0
- package/src/components/chat/entity-cards/hubspot-ticket-card.tsx +205 -0
- package/src/components/chat/entity-cards/index.ts +125 -0
- package/src/components/chat/entity-cards/investor-update-card.tsx +150 -0
- package/src/components/chat/entity-cards/onboarding-guide-card.tsx +326 -0
- package/src/components/chat/entity-cards/product-release-card-defaults.ts +57 -0
- package/src/components/chat/entity-cards/product-release-card.tsx +19 -0
- package/src/components/chat/entity-cards/program-card-defaults.ts +62 -0
- package/src/components/chat/entity-cards/program-card.tsx +451 -0
- package/src/components/chat/entity-cards/roadmap-card.tsx +356 -0
- package/src/components/chat/entity-cards/roadmap-vote-button.tsx +54 -0
- package/src/components/chat/entity-cards/slack-message-card.tsx +182 -0
- package/src/components/chat/entity-cards/task-type-icon.tsx +60 -0
- package/src/components/chat/hooks/index.ts +22 -0
- package/src/components/chat/hooks/use-chat-attachment-image-gallery.tsx +114 -0
- package/src/components/chat/hooks/use-chat-attachments.ts +429 -0
- package/src/components/chat/hooks/use-chat-card-item.ts +102 -0
- package/src/components/chat/hooks/use-chat-identity.ts +139 -0
- package/src/components/chat/hooks/use-chat.ts +501 -0
- package/src/components/chat/hooks/use-close-on-navigation.ts +87 -0
- package/src/components/chat/hooks/use-embedded-chat.ts +1023 -0
- package/src/components/chat/hooks/use-proxied-image-url.ts +31 -0
- package/src/components/chat/hooks/use-slash-commands.ts +106 -0
- package/src/components/chat/hooks/use-sse.ts +143 -0
- package/src/components/chat/index.ts +30 -4
- package/src/components/chat/nav-link-anchor-via-runtime.tsx +72 -0
- package/src/components/chat/source-action-button.tsx +120 -0
- package/src/components/chat/types/chat.types.ts +61 -0
- package/src/components/chat/types/component.types.ts +57 -11
- package/src/components/chat/types/entities/blog.ts +27 -0
- package/src/components/chat/types/entities/case-study.ts +14 -0
- package/src/components/chat/types/entities/content-ref.ts +23 -0
- package/src/components/chat/types/entities/customer-interview.ts +15 -0
- package/src/components/chat/types/entities/data-room-doc.ts +37 -0
- package/src/components/chat/types/entities/github-activity.ts +36 -0
- package/src/components/chat/types/entities/hubspot-ticket.ts +39 -0
- package/src/components/chat/types/entities/index.ts +28 -0
- package/src/components/chat/types/entities/investor-update.ts +100 -0
- package/src/components/chat/types/entities/onboarding-guide.ts +101 -0
- package/src/components/chat/types/entities/program-types.ts +433 -0
- package/src/components/chat/types/entities/roadmap-item.ts +42 -0
- package/src/components/chat/types/entities/slack-message.ts +28 -0
- package/src/components/chat/types/index.ts +1 -0
- package/src/components/chat/utils/agent-status-message.ts +52 -0
- package/src/components/chat/utils/auto-continuation-directive.ts +70 -0
- package/src/components/chat/utils/chat-attachment-markdown.ts +190 -0
- package/src/components/chat/utils/chat-authed-fetch.ts +73 -0
- package/src/components/chat/utils/chat-nav-resolution.ts +151 -0
- package/src/components/chat/utils/chat-proxy-auth-storage.ts +148 -0
- package/src/components/chat/utils/chip-action-class.ts +19 -0
- package/src/components/chat/utils/chip-styles.ts +51 -0
- package/src/components/chat/utils/clickup-task-type-utils.ts +59 -0
- package/src/components/chat/utils/compact-card-classes.ts +97 -0
- package/src/components/chat/utils/decide-new-tab.ts +57 -0
- package/src/components/chat/utils/external-app-urls.ts +19 -0
- package/src/components/chat/utils/flatten-assistant-content.ts +35 -0
- package/src/components/chat/utils/icon-registry.ts +297 -0
- package/src/components/chat/utils/index.ts +133 -0
- package/src/components/chat/utils/is-cross-origin-url.ts +28 -0
- package/src/components/chat/utils/nav-anchor-props.ts +78 -0
- package/src/components/chat/utils/nav-click-handler.ts +81 -0
- package/src/components/chat/utils/scroll-anchor.ts +35 -0
- package/src/components/chat/utils/slash-dispatch-utils.ts +183 -0
- package/src/components/chat/utils/source-icons.ts +14 -0
- package/src/components/chat/utils/source-row-cta.ts +215 -0
- package/src/components/empty-state.tsx +1 -1
- package/src/components/features/board/ticket-card.tsx +1 -1
- package/src/components/features/figma-prototype-viewer.tsx +2 -1
- package/src/components/features/media-gallery-manager.tsx +1 -1
- package/src/components/features/parallax-image-showcase.tsx +1 -1
- package/src/components/features/release-media-manager.tsx +1 -1
- package/src/components/features/seo-editor-preview.tsx +1 -1
- package/src/components/features/video.tsx +54 -3
- package/src/components/footer-waitlist-button.tsx +1 -1
- package/src/components/navigation/header.tsx +1 -1
- package/src/components/shared/onboarding/onboarding-step-card.tsx +1 -1
- package/src/components/shared/product-release/product-release-card-skeleton.tsx +8 -44
- package/src/components/shared/product-release/product-release-card.tsx +31 -116
- package/src/components/shared/product-release/release-detail-page.tsx +12 -16
- package/src/components/ui/actions-menu.tsx +1 -1
- package/src/components/ui/button/button.tsx +41 -11
- package/src/components/ui/button/split-button.tsx +1 -1
- package/src/components/ui/dashboard-info-card.tsx +2 -3
- package/src/components/ui/data-table/data-table-row.tsx +1 -1
- package/src/components/ui/entity-image.tsx +2 -8
- package/src/components/ui/hover-dropdown.tsx +258 -0
- package/src/components/ui/image-gallery-modal.tsx +1 -1
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/markdown-editor.tsx +1 -1
- package/src/components/ui/more-actions-menu.tsx +1 -1
- package/src/components/ui/organization-card.tsx +1 -1
- package/src/components/ui/simple-markdown-renderer.tsx +53 -5
- package/src/components/ui/square-avatar.tsx +3 -12
- package/src/components/ui/tab-navigation.tsx +1 -1
- package/src/components/ui/table/table-row.tsx +1 -1
- package/src/components/unified-filter-logic.tsx +1 -1
- package/src/components/unified-pagination.tsx +1 -1
- package/src/components/user-summary-stub.tsx +1 -1
- package/src/components/vendor-display-button.tsx +1 -1
- package/src/components/vendor-icon.tsx +1 -1
- package/src/contexts/chat-runtime-context.tsx +163 -0
- package/src/contexts/endpoints-runtime-context.tsx +68 -0
- package/src/contexts/index.ts +38 -0
- package/src/contexts/use-outer-or-default.ts +42 -0
- package/src/embed-shims/index.ts +42 -0
- package/src/embed-shims/next-dynamic.tsx +70 -0
- package/src/embed-shims/next-image.tsx +114 -0
- package/src/embed-shims/next-link.tsx +91 -0
- package/src/embed-shims/next-navigation.tsx +201 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/state/use-api-params.ts +1 -1
- package/src/hooks/state/use-query-params.ts +1 -1
- package/src/hooks/use-access-code-integration.ts +107 -0
- package/src/hooks/use-contact-submission.ts +7 -3
- package/src/hooks/use-og-placeholder.ts +45 -0
- package/src/stories/OnboardingStepCard.stories.tsx +140 -0
- package/src/styles/chat-animations.css +65 -0
- package/src/styles/index.css +1 -0
- package/src/utils/access-code-client.ts +32 -75
- package/src/utils/cn.ts +0 -65
- package/src/utils/color-analysis.ts +205 -0
- package/src/utils/date-formatters.ts +54 -11
- package/src/utils/fetch-priority.ts +41 -0
- package/src/utils/format.ts +525 -1
- package/src/utils/image-proxy.ts +127 -7
- package/src/utils/index.ts +145 -5
- package/src/utils/local-storage-adapter.ts +105 -0
- package/src/utils/source-icons.ts +219 -0
- package/dist/chunk-25LVV26X.cjs.map +0 -1
- package/dist/chunk-ARQ4XP64.cjs.map +0 -1
- package/dist/chunk-CPXLQ57U.js.map +0 -1
- package/dist/chunk-LY34ORX6.js.map +0 -1
- package/dist/chunk-RMB5DVED.cjs.map +0 -1
- package/dist/chunk-SZPJ5R5B.js.map +0 -1
- package/dist/chunk-UC43NICZ.cjs.map +0 -1
- package/dist/chunk-XGL5FKIK.js.map +0 -1
- package/dist/components/chat/block-card.d.ts.map +0 -1
- package/dist/components/chat/chat-ticket-item.d.ts.map +0 -1
- package/dist/components/chat/chat-video-entity-card.d.ts.map +0 -1
- package/dist/utils/dynamic-icons.d.ts +0 -26
- package/dist/utils/dynamic-icons.d.ts.map +0 -1
- package/dist/utils/format-relative-time.d.ts +0 -21
- package/dist/utils/format-relative-time.d.ts.map +0 -1
- package/src/utils/.dynamic-icons.md +0 -30
- package/src/utils/.format-relative-time.md +0 -36
- package/src/utils/dynamic-icons.tsx +0 -120
- package/src/utils/format-relative-time.ts +0 -52
- /package/dist/{chunk-N57KWHDB.js.map → chunk-CIPO6DXK.js.map} +0 -0
- /package/dist/components/chat/{block-card.d.ts → entity-cards/block-card.d.ts} +0 -0
- /package/dist/components/chat/{chat-ticket-item.d.ts → entity-cards/chat-ticket-item.d.ts} +0 -0
- /package/src/components/chat/{block-card.tsx → entity-cards/block-card.tsx} +0 -0
|
@@ -0,0 +1,1106 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* EmbeddableChat — lib-portable port of the hub's `<GlobalAskAI>` component.
|
|
5
|
+
*
|
|
6
|
+
* Drops every hub-only import (auth-provider, useNavLink, currentPlatform,
|
|
7
|
+
* tableIdForDocumentType, rag-table-config, etc.) and routes ALL navigation
|
|
8
|
+
* + identity decisions through `useRequiredChatRuntime()`. Host wires the
|
|
9
|
+
* runtime once at root (HubRuntimeProvider in the hub, custom provider in
|
|
10
|
+
* embedders); this component reads from it everywhere.
|
|
11
|
+
*
|
|
12
|
+
* Diff summary vs hub original:
|
|
13
|
+
* - `useAuth()` → `useRequiredChatRuntime().user` (greeting + identity only;
|
|
14
|
+
* the requireAuth render gate is dropped — hub's wrapper handles it).
|
|
15
|
+
* - `currentPlatform()` → `useRequiredChatRuntime().source`.
|
|
16
|
+
* - `useNavLink`/`NavLinkAnchor` → chip-anchor rewrite via
|
|
17
|
+
* `handleChatNavClick` + lib's `NavLinkAnchorViaRuntime`.
|
|
18
|
+
* - `useDocChat(source)` → `useEmbeddedChat()` (reads source from runtime).
|
|
19
|
+
* - `tableIdForDocumentType` import deleted (dead per audit).
|
|
20
|
+
* - `renderChatInlineEntityCard` imported from lib's entity-cards barrel.
|
|
21
|
+
* - `useCloseOnNavigation` signature is `(close, pathname)` — pass `null`
|
|
22
|
+
* because lib has no `usePathname()` and embedders own that decision.
|
|
23
|
+
* - All other hub utilities (chat-attachment-bar, slash-commands fetcher,
|
|
24
|
+
* icon registry, chip-styles, click-utils, etc.) re-resolved against
|
|
25
|
+
* the equivalent lib modules.
|
|
26
|
+
*
|
|
27
|
+
* Public surface — `<EmbeddableChat />` taking the same prop bundle the hub
|
|
28
|
+
* shell passes (minus `requireAuth`, which the hub's wrapper handles), plus
|
|
29
|
+
* an optional `extras` opt-in for the chat-card dispatch helpers that need
|
|
30
|
+
* host-supplied builders (program configs, product-release prop builder).
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
|
34
|
+
import { useControllableState } from '@radix-ui/react-use-controllable-state'
|
|
35
|
+
import * as Dialog from '@radix-ui/react-dialog'
|
|
36
|
+
import { usePreventScroll } from '@react-aria/overlays'
|
|
37
|
+
import { isIOS } from '@react-aria/utils'
|
|
38
|
+
import { VisuallyHidden } from '@radix-ui/react-visually-hidden'
|
|
39
|
+
import { FileText, MessageSquare } from 'lucide-react'
|
|
40
|
+
|
|
41
|
+
import { Button } from '../ui/button'
|
|
42
|
+
import { Card } from '../ui/card'
|
|
43
|
+
import { HoverDropdown, type HoverDropdownItem } from '../ui/hover-dropdown'
|
|
44
|
+
import { MingoIcon } from '../icons'
|
|
45
|
+
|
|
46
|
+
import { ChatHeader, ChatFooter } from './chat-container'
|
|
47
|
+
import { ChatInput } from './chat-input'
|
|
48
|
+
import { ChatMessageList } from './chat-message-list'
|
|
49
|
+
import { ModelDisplay } from './model-display'
|
|
50
|
+
import { SourceActionButton } from './source-action-button'
|
|
51
|
+
import { NavLinkAnchorViaRuntime } from './nav-link-anchor-via-runtime'
|
|
52
|
+
import { ChatAttachmentAddButton, ChatAttachmentChipStrip } from './chat-attachment-bar'
|
|
53
|
+
import { renderChatInlineEntityCard } from './entity-cards/dispatch'
|
|
54
|
+
import type { ChatCardDispatchExtras } from './entity-cards/dispatch'
|
|
55
|
+
|
|
56
|
+
import { useRequiredChatRuntime } from '../../contexts/chat-runtime-context'
|
|
57
|
+
import { useEmbeddedChat, type ChatSource } from './hooks/use-embedded-chat'
|
|
58
|
+
import { useChatAttachments } from './hooks/use-chat-attachments'
|
|
59
|
+
import { useChatAttachmentImageGallery } from './hooks/use-chat-attachment-image-gallery'
|
|
60
|
+
import { useChatIdentity } from './hooks/use-chat-identity'
|
|
61
|
+
import { useCloseOnNavigation } from './hooks/use-close-on-navigation'
|
|
62
|
+
import { fetchSlashCommands, type SlashCommandSummary } from './hooks/use-slash-commands'
|
|
63
|
+
|
|
64
|
+
import type { ChatRef } from './chat-ref.types'
|
|
65
|
+
import type { ChatInputRef, SlashCommandActionId } from './types/component.types'
|
|
66
|
+
import type { Message } from './types/message.types'
|
|
67
|
+
|
|
68
|
+
import { formatChatAttachmentMarkdownForBubble } from './utils/chat-attachment-markdown'
|
|
69
|
+
import { handleChatNavClick } from './utils/nav-click-handler'
|
|
70
|
+
import { computeIsNewTab, newTabAnchorAttrs } from './utils/nav-anchor-props'
|
|
71
|
+
import { resolveHrefForRuntime } from './utils/chat-nav-resolution'
|
|
72
|
+
import { ChatPanelContext, type ChatPanelHandle } from './chat-panel-context'
|
|
73
|
+
import { resolveSourceRowCTA } from './utils/source-row-cta'
|
|
74
|
+
import { chatChipClass } from './utils/chip-styles'
|
|
75
|
+
import { CHIP_ACTION_BUTTON_CLASS } from './utils/chip-action-class'
|
|
76
|
+
import { getIconComponent } from './utils/icon-registry'
|
|
77
|
+
import { getSourceIconName } from './utils/source-icons'
|
|
78
|
+
import { formatSingularLookupInvocation } from './utils/slash-dispatch-utils'
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
// =============================================================================
|
|
82
|
+
// Types
|
|
83
|
+
// =============================================================================
|
|
84
|
+
|
|
85
|
+
/** Lib-side type alias kept inline to avoid leaking the (deprecated) hub
|
|
86
|
+
* `rag-table-config` `DocSource` import. The chat source is always a
|
|
87
|
+
* string id; `useEmbeddedChat` reads it from `runtime.source`. */
|
|
88
|
+
type DocSource = string
|
|
89
|
+
|
|
90
|
+
export interface EmbeddableChatProps {
|
|
91
|
+
/** Base route for in-app doc chip nav (e.g. `/knowledge-base`). When
|
|
92
|
+
* omitted, defaults are derived from `runtime.source`. */
|
|
93
|
+
baseRoute?: string
|
|
94
|
+
/** When the embedder doesn't host a `[...path]` route to render markdown
|
|
95
|
+
* chips against, set this to a platform that does. Chips with
|
|
96
|
+
* `externalUrl: null` resolve to `getBaseUrl(chipBasePlatform) +
|
|
97
|
+
* '/knowledge-base/' + path` and open in a new tab. */
|
|
98
|
+
chipBasePlatform?: string
|
|
99
|
+
/** DB-driven list of enabled RAG table ids (chip catalog filter).
|
|
100
|
+
* Prefetched server-side by the embedder's wrapper. Empty/null → no
|
|
101
|
+
* empty-state chips render. */
|
|
102
|
+
enabledRagTableIds?: ReadonlyArray<string> | null
|
|
103
|
+
/** DB-backed empty-state greeting. Falls back to a generic greeting. */
|
|
104
|
+
emptyStateGreeting?: string | null
|
|
105
|
+
/** DB-backed starter prompts (chips below the greeting). */
|
|
106
|
+
suggestedQueries?: ReadonlyArray<string> | null
|
|
107
|
+
/** Controlled-mode open state. When provided, `onOpenChange` MUST also
|
|
108
|
+
* be provided. Uncontrolled mode is the default. */
|
|
109
|
+
open?: boolean
|
|
110
|
+
/** Controlled-mode change handler. Required when `open` is provided. */
|
|
111
|
+
onOpenChange?: (open: boolean) => void
|
|
112
|
+
/** Initial open state for uncontrolled mode. Ignored if `open` is set. */
|
|
113
|
+
defaultOpen?: boolean
|
|
114
|
+
/** Render the built-in floating "Ask AI" trigger. Defaults to `true`. */
|
|
115
|
+
showInternalTrigger?: boolean
|
|
116
|
+
/** Optional builders for chat-card types whose props live in hub-land
|
|
117
|
+
* (programs + product_release). Forwarded straight to
|
|
118
|
+
* `renderChatInlineEntityCard`. */
|
|
119
|
+
extras?: ChatCardDispatchExtras
|
|
120
|
+
/** Optional callback used by `useEmbeddedChat`'s `displayRef` /
|
|
121
|
+
* `discussRef` flow to translate an LLM document type into the
|
|
122
|
+
* registry table id for entity-id-filtered retrieval. */
|
|
123
|
+
tableIdForDocumentType?: (documentType: string) => string | null
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// =============================================================================
|
|
127
|
+
// Chip href resolution
|
|
128
|
+
// =============================================================================
|
|
129
|
+
|
|
130
|
+
/** Tiny inline replacement for hub's `formatRelativePath`. */
|
|
131
|
+
const formatRelativePath = (p: string): string =>
|
|
132
|
+
p.replace(/^\/+/, '').replace(/\/+$/, '')
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Fallback fan-out when the model didn't cite any source. Show the top-N
|
|
136
|
+
* retrieved sources instead of zero chips. Mirrors Perplexity's behavior.
|
|
137
|
+
*/
|
|
138
|
+
const FALLBACK_TOP_RETRIEVED = 3
|
|
139
|
+
|
|
140
|
+
// =============================================================================
|
|
141
|
+
// Slash-command dispatch
|
|
142
|
+
// =============================================================================
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Single source of truth for slash-command action dispatch. Maps an action
|
|
146
|
+
* id to the corresponding chat-input-ref mutation. Same vocabulary as the
|
|
147
|
+
* hub original.
|
|
148
|
+
*/
|
|
149
|
+
function dispatchSlashCommandAction(
|
|
150
|
+
actionId: SlashCommandActionId,
|
|
151
|
+
cmdId: string,
|
|
152
|
+
ref: React.MutableRefObject<ChatInputRef | null>,
|
|
153
|
+
): void {
|
|
154
|
+
const input = ref.current
|
|
155
|
+
if (!input) return
|
|
156
|
+
switch (actionId) {
|
|
157
|
+
case 'browse':
|
|
158
|
+
input.submit(formatSingularLookupInvocation(cmdId))
|
|
159
|
+
return
|
|
160
|
+
case 'search':
|
|
161
|
+
input.setValue(`/${cmdId} `)
|
|
162
|
+
return
|
|
163
|
+
case 'find': {
|
|
164
|
+
const text = `/${cmdId} ""`
|
|
165
|
+
input.setValueAndCursor(text, text.length - 1)
|
|
166
|
+
return
|
|
167
|
+
}
|
|
168
|
+
case 'display': {
|
|
169
|
+
const text = `/${cmdId} display ""`
|
|
170
|
+
input.setValueAndCursor(text, text.length - 1)
|
|
171
|
+
return
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Resolve the icon for a source chip. `src.sourceRepo` is the
|
|
178
|
+
* `RagTableConfig.id` — looked up via `SOURCE_ICON_NAMES`, then
|
|
179
|
+
* resolved via `ICON_REGISTRY`. Falls back to `<FileText/>` so a
|
|
180
|
+
* misconfigured chip doesn't crash render.
|
|
181
|
+
*/
|
|
182
|
+
function resolveChipIcon(src: ChatSource): React.ReactNode {
|
|
183
|
+
const iconName = getSourceIconName(src.sourceRepo)
|
|
184
|
+
const Icon = iconName ? getIconComponent(iconName) : FileText
|
|
185
|
+
return <Icon className="h-3.5 w-3.5" />
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// =============================================================================
|
|
189
|
+
// SourceChip
|
|
190
|
+
// =============================================================================
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Source chip — TWO affordances per the hub original:
|
|
194
|
+
* 1. Open: click → chip's URL (in-app for docs, new-tab for external).
|
|
195
|
+
* 2. Ask: small `MessageSquare` icon-button on the right → fires
|
|
196
|
+
* `onDiscuss(ref)` to drill into THIS row via `entityIdFilter`.
|
|
197
|
+
*/
|
|
198
|
+
function SourceChip({
|
|
199
|
+
src,
|
|
200
|
+
baseRoute,
|
|
201
|
+
chipBasePlatform,
|
|
202
|
+
onClose,
|
|
203
|
+
onDiscuss,
|
|
204
|
+
}: {
|
|
205
|
+
src: ChatSource
|
|
206
|
+
baseRoute: string
|
|
207
|
+
chipBasePlatform?: string
|
|
208
|
+
onClose: () => void
|
|
209
|
+
onDiscuss?: (ref: ChatRef) => void
|
|
210
|
+
}) {
|
|
211
|
+
const runtime = useRequiredChatRuntime()
|
|
212
|
+
// Single CTA resolver — same icon, same href chain, same ChatRef
|
|
213
|
+
// synthesis the inline card and search-result paths use.
|
|
214
|
+
const cta = resolveSourceRowCTA(
|
|
215
|
+
{
|
|
216
|
+
sourceRepo: src.sourceRepo,
|
|
217
|
+
documentType: src.documentType,
|
|
218
|
+
id: src.id,
|
|
219
|
+
title: src.name,
|
|
220
|
+
externalUrl: src.externalUrl,
|
|
221
|
+
targetPlatform: src.targetPlatform ?? null,
|
|
222
|
+
path: src.path,
|
|
223
|
+
},
|
|
224
|
+
{ baseRoute, chipBasePlatform, currentPlatform: runtime.source },
|
|
225
|
+
)
|
|
226
|
+
const Icon = cta.icon
|
|
227
|
+
const icon = <Icon className="h-3.5 w-3.5" />
|
|
228
|
+
const chipClass = chatChipClass({ tone: 'secondary' })
|
|
229
|
+
|
|
230
|
+
// Single source for the new-tab decision — same `computeIsNewTab` the
|
|
231
|
+
// inline cards consume via `ChatCardLoader`.
|
|
232
|
+
const decideTab = (href: string | null, targetPlatform: string | null) =>
|
|
233
|
+
computeIsNewTab(runtime, href, targetPlatform)
|
|
234
|
+
|
|
235
|
+
// Grouped source — hover/click reveals a dropdown with Open + Ask per row.
|
|
236
|
+
if (src.items && src.items.length > 0) {
|
|
237
|
+
const dropdownItems: HoverDropdownItem[] = src.items.map((item) => {
|
|
238
|
+
const itemCta = resolveSourceRowCTA(
|
|
239
|
+
{
|
|
240
|
+
sourceRepo: src.sourceRepo,
|
|
241
|
+
documentType: item.documentType,
|
|
242
|
+
id: item.id,
|
|
243
|
+
title: item.name,
|
|
244
|
+
externalUrl: item.externalUrl,
|
|
245
|
+
targetPlatform: item.targetPlatform ?? null,
|
|
246
|
+
path: item.path,
|
|
247
|
+
},
|
|
248
|
+
{ baseRoute, chipBasePlatform, currentPlatform: runtime.source },
|
|
249
|
+
)
|
|
250
|
+
const ItemIcon = itemCta.icon
|
|
251
|
+
return {
|
|
252
|
+
label: item.name,
|
|
253
|
+
icon: <ItemIcon className="h-3.5 w-3.5" />,
|
|
254
|
+
href: itemCta.href ?? undefined,
|
|
255
|
+
targetPlatform: itemCta.targetPlatform,
|
|
256
|
+
path: item.path ?? null,
|
|
257
|
+
secondaryAction:
|
|
258
|
+
onDiscuss && itemCta.askable && itemCta.chatRef
|
|
259
|
+
? {
|
|
260
|
+
icon: <MessageSquare />,
|
|
261
|
+
label: `Ask about ${item.name}`,
|
|
262
|
+
onClick: () => onDiscuss(itemCta.chatRef!),
|
|
263
|
+
}
|
|
264
|
+
: undefined,
|
|
265
|
+
}
|
|
266
|
+
})
|
|
267
|
+
|
|
268
|
+
return (
|
|
269
|
+
<HoverDropdown
|
|
270
|
+
items={dropdownItems}
|
|
271
|
+
renderAnchor={({ href, targetPlatform, path, className, children }) => (
|
|
272
|
+
<NavLinkAnchorViaRuntime
|
|
273
|
+
href={href}
|
|
274
|
+
targetPlatform={targetPlatform ?? null}
|
|
275
|
+
path={path}
|
|
276
|
+
className={className}
|
|
277
|
+
>
|
|
278
|
+
{children}
|
|
279
|
+
</NavLinkAnchorViaRuntime>
|
|
280
|
+
)}
|
|
281
|
+
>
|
|
282
|
+
<span className={`${chipClass} cursor-pointer`}>
|
|
283
|
+
{icon}
|
|
284
|
+
<span className="truncate max-w-[160px]">
|
|
285
|
+
[{src.index}] {src.name}
|
|
286
|
+
</span>
|
|
287
|
+
</span>
|
|
288
|
+
</HoverDropdown>
|
|
289
|
+
)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Single-row chip helpers — wrap whatever clickable element each branch
|
|
293
|
+
// produces with the trailing Ask `SourceActionButton`.
|
|
294
|
+
const displayName = src.name || formatRelativePath(src.path)
|
|
295
|
+
const chipBody = (label: string) => (
|
|
296
|
+
<>
|
|
297
|
+
{icon}
|
|
298
|
+
<span className="truncate max-w-[160px]">
|
|
299
|
+
[{src.index}] {label}
|
|
300
|
+
</span>
|
|
301
|
+
</>
|
|
302
|
+
)
|
|
303
|
+
const wrapChip = (clickable: React.ReactNode) => (
|
|
304
|
+
<span className="inline-flex items-center">
|
|
305
|
+
{clickable}
|
|
306
|
+
<SourceActionButton
|
|
307
|
+
chatRef={cta.chatRef}
|
|
308
|
+
onDiscuss={onDiscuss}
|
|
309
|
+
density="inline"
|
|
310
|
+
className="ml-1 -mr-1"
|
|
311
|
+
/>
|
|
312
|
+
</span>
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
// Click handler that routes through chat-runtime AND closes the chat
|
|
316
|
+
// panel ONLY on same-tab navigation. New-tab clicks leave the chat
|
|
317
|
+
// open so the user keeps their context while reading the new tab.
|
|
318
|
+
// Modifier-clicks pass through to the browser's native behavior.
|
|
319
|
+
// Single close model: matches `ChatCardNavWrap` for inline cards.
|
|
320
|
+
const buildClickHandler = (href: string, path: string | null | undefined, targetPlatform: string | null, isNewTab: boolean) =>
|
|
321
|
+
(e: React.MouseEvent<HTMLAnchorElement>) => {
|
|
322
|
+
const handled = handleChatNavClick(e, runtime, { href, path, targetPlatform })
|
|
323
|
+
if (handled && !isNewTab && onClose) onClose()
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Entity chip with a resolved external URL. `resolveHrefForRuntime`
|
|
327
|
+
// applies embed-mode origin prefix so modifier-click / hover-preview
|
|
328
|
+
// / right-click "copy link" all land on the hub origin.
|
|
329
|
+
if (cta.href && !!src.externalUrl) {
|
|
330
|
+
const resolvedHref = resolveHrefForRuntime(cta.href, runtime)
|
|
331
|
+
const isNewTab = decideTab(resolvedHref, cta.targetPlatform ?? null)
|
|
332
|
+
return wrapChip(
|
|
333
|
+
<a
|
|
334
|
+
href={resolvedHref}
|
|
335
|
+
{...newTabAnchorAttrs(isNewTab)}
|
|
336
|
+
onClick={buildClickHandler(resolvedHref, null, cta.targetPlatform ?? null, isNewTab)}
|
|
337
|
+
className={chipClass}
|
|
338
|
+
>
|
|
339
|
+
{chipBody(src.name)}
|
|
340
|
+
</a>,
|
|
341
|
+
)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// In-app navigable doc (markdown / data-room PDF).
|
|
345
|
+
if (cta.href) {
|
|
346
|
+
const resolvedHref = resolveHrefForRuntime(cta.href, runtime)
|
|
347
|
+
const isNewTab = decideTab(resolvedHref, cta.targetPlatform ?? null)
|
|
348
|
+
return wrapChip(
|
|
349
|
+
<a
|
|
350
|
+
href={resolvedHref}
|
|
351
|
+
{...newTabAnchorAttrs(isNewTab)}
|
|
352
|
+
onClick={buildClickHandler(resolvedHref, src.path, cta.targetPlatform ?? null, isNewTab)}
|
|
353
|
+
className={chipClass}
|
|
354
|
+
title={displayName}
|
|
355
|
+
>
|
|
356
|
+
{chipBody(displayName)}
|
|
357
|
+
</a>,
|
|
358
|
+
)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// No openable destination — static label + Ask affordance only.
|
|
362
|
+
return wrapChip(
|
|
363
|
+
<span className={`${chipClass} cursor-default`} title={displayName}>
|
|
364
|
+
{chipBody(displayName)}
|
|
365
|
+
</span>,
|
|
366
|
+
)
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Cited-by-default source chip strip (Perplexity / ChatGPT pattern).
|
|
371
|
+
* Cited rows render first; uncited tail hidden behind an expander.
|
|
372
|
+
*/
|
|
373
|
+
function SourceChips({
|
|
374
|
+
cited,
|
|
375
|
+
uncited,
|
|
376
|
+
baseRoute,
|
|
377
|
+
chipBasePlatform,
|
|
378
|
+
onClose,
|
|
379
|
+
onDiscuss,
|
|
380
|
+
}: {
|
|
381
|
+
cited: ChatSource[]
|
|
382
|
+
uncited: ChatSource[]
|
|
383
|
+
baseRoute: string
|
|
384
|
+
chipBasePlatform?: string
|
|
385
|
+
onClose: () => void
|
|
386
|
+
onDiscuss?: (ref: ChatRef) => void
|
|
387
|
+
}) {
|
|
388
|
+
const [expanded, setExpanded] = useState(false)
|
|
389
|
+
|
|
390
|
+
if (cited.length === 0) {
|
|
391
|
+
const fallback = uncited.slice(0, FALLBACK_TOP_RETRIEVED)
|
|
392
|
+
if (fallback.length === 0) return null
|
|
393
|
+
return (
|
|
394
|
+
<div className="flex flex-col gap-1.5 mt-2 pt-2 border-t border-ods-border">
|
|
395
|
+
<span className="text-[11px] text-ods-text-muted uppercase tracking-wider font-medium">
|
|
396
|
+
Top retrieved sources
|
|
397
|
+
</span>
|
|
398
|
+
<div className="flex flex-wrap gap-1.5">
|
|
399
|
+
{fallback.map((src) => (
|
|
400
|
+
<SourceChip
|
|
401
|
+
key={src.index}
|
|
402
|
+
src={src}
|
|
403
|
+
baseRoute={baseRoute}
|
|
404
|
+
chipBasePlatform={chipBasePlatform}
|
|
405
|
+
onClose={onClose}
|
|
406
|
+
onDiscuss={onDiscuss}
|
|
407
|
+
/>
|
|
408
|
+
))}
|
|
409
|
+
</div>
|
|
410
|
+
</div>
|
|
411
|
+
)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const hiddenCount = uncited.length
|
|
415
|
+
const hasOverflow = hiddenCount > 0
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<div className="flex flex-col gap-1.5 mt-2 pt-2 border-t border-ods-border">
|
|
419
|
+
<span className="text-[11px] text-ods-text-muted uppercase tracking-wider font-medium">
|
|
420
|
+
Sources
|
|
421
|
+
</span>
|
|
422
|
+
<div
|
|
423
|
+
className={`flex flex-wrap gap-1.5 ${expanded ? 'max-h-[200px] overflow-y-auto' : ''}`}
|
|
424
|
+
>
|
|
425
|
+
{cited.map((src) => (
|
|
426
|
+
<SourceChip
|
|
427
|
+
key={src.index}
|
|
428
|
+
src={src}
|
|
429
|
+
baseRoute={baseRoute}
|
|
430
|
+
chipBasePlatform={chipBasePlatform}
|
|
431
|
+
onClose={onClose}
|
|
432
|
+
onDiscuss={onDiscuss}
|
|
433
|
+
/>
|
|
434
|
+
))}
|
|
435
|
+
{expanded &&
|
|
436
|
+
uncited.map((src) => (
|
|
437
|
+
<SourceChip
|
|
438
|
+
key={src.index}
|
|
439
|
+
src={src}
|
|
440
|
+
baseRoute={baseRoute}
|
|
441
|
+
chipBasePlatform={chipBasePlatform}
|
|
442
|
+
onClose={onClose}
|
|
443
|
+
onDiscuss={onDiscuss}
|
|
444
|
+
/>
|
|
445
|
+
))}
|
|
446
|
+
{hasOverflow && (
|
|
447
|
+
<button
|
|
448
|
+
onClick={() => setExpanded(!expanded)}
|
|
449
|
+
className="inline-flex items-center gap-1 px-2 py-0.5 rounded border text-[11px] cursor-pointer transition-colors bg-ods-card border-ods-accent text-ods-accent hover:bg-ods-accent/10"
|
|
450
|
+
aria-expanded={expanded}
|
|
451
|
+
aria-label={
|
|
452
|
+
expanded
|
|
453
|
+
? 'Show fewer sources'
|
|
454
|
+
: `Show ${hiddenCount} additional retrieved sources`
|
|
455
|
+
}
|
|
456
|
+
>
|
|
457
|
+
{expanded
|
|
458
|
+
? 'Show less'
|
|
459
|
+
: `+${hiddenCount} more retrieved ${
|
|
460
|
+
hiddenCount === 1 ? 'source' : 'sources'
|
|
461
|
+
}`}
|
|
462
|
+
</button>
|
|
463
|
+
)}
|
|
464
|
+
</div>
|
|
465
|
+
</div>
|
|
466
|
+
)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// =============================================================================
|
|
470
|
+
// Component
|
|
471
|
+
// =============================================================================
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* EmbeddableChat — the floating "Ask AI" button + Mingo chat panel.
|
|
475
|
+
* Lib-portable port of the hub's `<GlobalAskAI>`.
|
|
476
|
+
*/
|
|
477
|
+
export function EmbeddableChat(props: EmbeddableChatProps) {
|
|
478
|
+
return <EmbeddableChatInner {...props} />
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
function EmbeddableChatInner({
|
|
482
|
+
baseRoute,
|
|
483
|
+
chipBasePlatform,
|
|
484
|
+
enabledRagTableIds = null,
|
|
485
|
+
emptyStateGreeting = null,
|
|
486
|
+
suggestedQueries = null,
|
|
487
|
+
open,
|
|
488
|
+
onOpenChange,
|
|
489
|
+
defaultOpen,
|
|
490
|
+
showInternalTrigger = true,
|
|
491
|
+
extras,
|
|
492
|
+
tableIdForDocumentType,
|
|
493
|
+
}: EmbeddableChatProps) {
|
|
494
|
+
const runtime = useRequiredChatRuntime()
|
|
495
|
+
const source = runtime.source as DocSource
|
|
496
|
+
const commandsUrl = runtime.endpoints.commandsUrl
|
|
497
|
+
// Server-resolved identity — drives the greeting first-name AND the
|
|
498
|
+
// attachment capability flag. Single source of truth: the chat-identity
|
|
499
|
+
// endpoint returns BOTH the auth tier and the resolved user, so the
|
|
500
|
+
// displayed name always matches who the server thinks the user is.
|
|
501
|
+
const { attachmentsEnabled, user: identityUser } = useChatIdentity()
|
|
502
|
+
const viewUrlPrefix = runtime.endpoints.attachmentViewUrlPrefix
|
|
503
|
+
|
|
504
|
+
// Dev-only warning when only one of `open` / `onOpenChange` is set.
|
|
505
|
+
useEffect(() => {
|
|
506
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
507
|
+
const hasOpen = open !== undefined
|
|
508
|
+
const hasHandler = onOpenChange !== undefined
|
|
509
|
+
if (hasOpen !== hasHandler) {
|
|
510
|
+
console.warn(
|
|
511
|
+
'[EmbeddableChat] `open` and `onOpenChange` must both be provided ' +
|
|
512
|
+
'for controlled mode, or both omitted for uncontrolled. ' +
|
|
513
|
+
`Provided: open=${hasOpen}, onOpenChange=${hasHandler}.`,
|
|
514
|
+
)
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}, [open, onOpenChange])
|
|
518
|
+
|
|
519
|
+
const [isOpen = false, setIsOpen] = useControllableState<boolean>({
|
|
520
|
+
prop: open,
|
|
521
|
+
defaultProp: defaultOpen ?? false,
|
|
522
|
+
onChange: onOpenChange,
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
// Suppress chat input auto-focus on touch devices (avoids popping the
|
|
526
|
+
// on-screen keyboard during the bottom-sheet open animation).
|
|
527
|
+
const [autoFocusInput] = useState(() => {
|
|
528
|
+
if (typeof window === 'undefined') return false
|
|
529
|
+
return !window.matchMedia('(pointer: coarse)').matches
|
|
530
|
+
})
|
|
531
|
+
|
|
532
|
+
// iOS scroll-lock — react-aria's two-layer approach plus body fixed-pos.
|
|
533
|
+
// See hub original for the long mechanism comment; logic copied verbatim.
|
|
534
|
+
usePreventScroll({ isDisabled: !isOpen })
|
|
535
|
+
|
|
536
|
+
const navigatingAwayRef = useRef(false)
|
|
537
|
+
|
|
538
|
+
useEffect(() => {
|
|
539
|
+
if (!isOpen) return
|
|
540
|
+
if (typeof window === 'undefined') return
|
|
541
|
+
if (!isIOS()) return
|
|
542
|
+
|
|
543
|
+
navigatingAwayRef.current = false
|
|
544
|
+
|
|
545
|
+
const scrollY = window.scrollY
|
|
546
|
+
const openPathname = window.location.pathname
|
|
547
|
+
const body = document.body
|
|
548
|
+
const prev = {
|
|
549
|
+
position: body.style.position,
|
|
550
|
+
top: body.style.top,
|
|
551
|
+
width: body.style.width,
|
|
552
|
+
}
|
|
553
|
+
body.style.position = 'fixed'
|
|
554
|
+
body.style.top = `-${scrollY}px`
|
|
555
|
+
body.style.width = '100%'
|
|
556
|
+
|
|
557
|
+
return () => {
|
|
558
|
+
body.style.position = prev.position
|
|
559
|
+
body.style.top = prev.top
|
|
560
|
+
body.style.width = prev.width
|
|
561
|
+
if (navigatingAwayRef.current) return
|
|
562
|
+
if (window.location.pathname !== openPathname) return
|
|
563
|
+
window.scrollTo(0, scrollY)
|
|
564
|
+
}
|
|
565
|
+
}, [isOpen])
|
|
566
|
+
|
|
567
|
+
// Imperative handle to the chat input.
|
|
568
|
+
const chatInputRef = useRef<ChatInputRef | null>(null)
|
|
569
|
+
|
|
570
|
+
// Async lookup of the slash-command registry for the current source.
|
|
571
|
+
const [commandsById, setCommandsById] = useState<Map<string, SlashCommandSummary>>(
|
|
572
|
+
() => new Map(),
|
|
573
|
+
)
|
|
574
|
+
const [commandsLoaded, setCommandsLoaded] = useState(false)
|
|
575
|
+
useEffect(() => {
|
|
576
|
+
if (!isOpen) return
|
|
577
|
+
let cancelled = false
|
|
578
|
+
const ctrl = new AbortController()
|
|
579
|
+
setCommandsLoaded(false)
|
|
580
|
+
fetchSlashCommands('', ctrl.signal, commandsUrl)
|
|
581
|
+
.then((commands) => {
|
|
582
|
+
if (cancelled) return
|
|
583
|
+
const map = new Map<string, SlashCommandSummary>()
|
|
584
|
+
for (const cmd of commands) map.set(cmd.id, cmd)
|
|
585
|
+
setCommandsById(map)
|
|
586
|
+
setCommandsLoaded(true)
|
|
587
|
+
})
|
|
588
|
+
.catch((err) => {
|
|
589
|
+
if (!cancelled && (err as Error)?.name !== 'AbortError') {
|
|
590
|
+
console.warn('[embeddable-chat] failed to fetch slash commands:', err)
|
|
591
|
+
setCommandsLoaded(true)
|
|
592
|
+
}
|
|
593
|
+
})
|
|
594
|
+
return () => {
|
|
595
|
+
cancelled = true
|
|
596
|
+
ctrl.abort()
|
|
597
|
+
}
|
|
598
|
+
}, [isOpen, source, commandsUrl])
|
|
599
|
+
|
|
600
|
+
// Slash-command autocomplete config — passed to <ChatInput>.
|
|
601
|
+
const slashCommandsProp = useMemo(
|
|
602
|
+
() => ({
|
|
603
|
+
fetchCommands: (prefix: string, signal?: AbortSignal) =>
|
|
604
|
+
fetchSlashCommands(prefix, signal, commandsUrl),
|
|
605
|
+
resolveSourceIcon: (sourceId: string) => {
|
|
606
|
+
const iconName = getSourceIconName(sourceId)
|
|
607
|
+
if (!iconName) return undefined
|
|
608
|
+
return { Icon: getIconComponent(iconName), label: sourceId }
|
|
609
|
+
},
|
|
610
|
+
onAction: (cmd: SlashCommandSummary, actionId: SlashCommandActionId) => {
|
|
611
|
+
dispatchSlashCommandAction(actionId, cmd.id, chatInputRef)
|
|
612
|
+
},
|
|
613
|
+
}),
|
|
614
|
+
[commandsUrl],
|
|
615
|
+
)
|
|
616
|
+
|
|
617
|
+
// After the open animation finishes we clear the CSS `transform` so
|
|
618
|
+
// `position: fixed` descendants escape the panel's containing block.
|
|
619
|
+
const [animationRest, setAnimationRest] = useState(false)
|
|
620
|
+
useEffect(() => {
|
|
621
|
+
if (!isOpen) setAnimationRest(false)
|
|
622
|
+
}, [isOpen])
|
|
623
|
+
|
|
624
|
+
// Greeting first-name comes from the SERVER-resolved identity (single
|
|
625
|
+
// source of truth — never a client-injected runtime field). Resolution
|
|
626
|
+
// order:
|
|
627
|
+
// 1. `identityUser.firstName` — dedicated optional field from the
|
|
628
|
+
// identity webservice (populated via `X-Chat-First-Name` for
|
|
629
|
+
// bearer-act-as, or by the hub's profile lookup for cookie sessions).
|
|
630
|
+
// 2. `identityUser.name.split(' ')[0]` — legacy fallback for sources
|
|
631
|
+
// that only return a full name. Empty-string-safe (`?.`-chain).
|
|
632
|
+
// 3. `undefined` — anon, loading, or no name available → greeting
|
|
633
|
+
// collapses to the no-name variant `Hey, I'm Mingo`.
|
|
634
|
+
// We coalesce an empty string to `undefined` so the JSX `userName ? …`
|
|
635
|
+
// branch treats `''` the same as missing — embedders that send
|
|
636
|
+
// `firstName: ''` shouldn't render `Hey , I'm Mingo`.
|
|
637
|
+
const userName =
|
|
638
|
+
(identityUser?.firstName?.trim() ||
|
|
639
|
+
identityUser?.name?.split(' ')[0]?.trim()) ||
|
|
640
|
+
undefined
|
|
641
|
+
|
|
642
|
+
const {
|
|
643
|
+
messages: rawMessages,
|
|
644
|
+
isLoading: chatLoading,
|
|
645
|
+
sendMessage,
|
|
646
|
+
discussRef,
|
|
647
|
+
stopMessage,
|
|
648
|
+
clearMessages,
|
|
649
|
+
currentProvider,
|
|
650
|
+
currentModelLabel,
|
|
651
|
+
currentContextWindowMaxTokens,
|
|
652
|
+
currentInputTokens,
|
|
653
|
+
currentOutputTokens,
|
|
654
|
+
currentCacheHitRatePct,
|
|
655
|
+
currentUsageBreakdown,
|
|
656
|
+
displayRef,
|
|
657
|
+
} = useEmbeddedChat({ tableIdForDocumentType })
|
|
658
|
+
|
|
659
|
+
// Chat-attachment hooks (v2 attachment feature).
|
|
660
|
+
const {
|
|
661
|
+
attachments: stagedAttachments,
|
|
662
|
+
readyAttachments,
|
|
663
|
+
hasInflightUploads,
|
|
664
|
+
addFiles: addAttachmentFiles,
|
|
665
|
+
removeAttachment,
|
|
666
|
+
clear: clearAttachments,
|
|
667
|
+
} = useChatAttachments()
|
|
668
|
+
const { panelRef: galleryPanelRef, modal: galleryModal } =
|
|
669
|
+
useChatAttachmentImageGallery()
|
|
670
|
+
|
|
671
|
+
// Resolve base route. Hub default mapping: flamingo → /knowledge-base,
|
|
672
|
+
// anything else → /data-room. Embedders can override per platform.
|
|
673
|
+
const resolvedBaseRoute =
|
|
674
|
+
baseRoute || (source === 'flamingo' ? '/knowledge-base' : '/data-room')
|
|
675
|
+
|
|
676
|
+
const handleClose = useCallback(() => setIsOpen(false), [setIsOpen])
|
|
677
|
+
|
|
678
|
+
const handleNavigationClose = useCallback(() => {
|
|
679
|
+
navigatingAwayRef.current = true
|
|
680
|
+
setIsOpen(false)
|
|
681
|
+
}, [setIsOpen])
|
|
682
|
+
|
|
683
|
+
// Stable panel-level handle for descendants (inline cards via
|
|
684
|
+
// `ChatCardNavWrap` and markdown-body links via
|
|
685
|
+
// `NavLinkAnchorViaRuntime`) to close the panel after same-tab
|
|
686
|
+
// navigation. Uses `handleNavigationClose` (not `handleClose`) so the
|
|
687
|
+
// iOS scroll-restore cleanup effect at the bottom of this file sees
|
|
688
|
+
// `navigatingAwayRef.current = true` and skips restoring the chat's
|
|
689
|
+
// saved scroll position over the freshly-loaded destination page.
|
|
690
|
+
// Source chips already route through `handleNavigationClose`; inline
|
|
691
|
+
// cards now match. New-tab clicks never invoke `closeChat`.
|
|
692
|
+
const chatPanelHandle = useMemo<ChatPanelHandle>(
|
|
693
|
+
() => ({ closeChat: handleNavigationClose }),
|
|
694
|
+
[handleNavigationClose],
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
// Host-provided renderer for inline entity cards — routes through the
|
|
698
|
+
// shared dispatcher in lib's `entity-cards/dispatch.tsx`.
|
|
699
|
+
const renderEntityCard = useCallback(
|
|
700
|
+
(reference: ChatRef): React.ReactNode =>
|
|
701
|
+
renderChatInlineEntityCard(reference, {
|
|
702
|
+
onDiscuss: discussRef,
|
|
703
|
+
onDisplay: displayRef,
|
|
704
|
+
baseRoute: resolvedBaseRoute,
|
|
705
|
+
chipBasePlatform,
|
|
706
|
+
extras,
|
|
707
|
+
}),
|
|
708
|
+
[discussRef, displayRef, resolvedBaseRoute, chipBasePlatform, extras],
|
|
709
|
+
)
|
|
710
|
+
|
|
711
|
+
// Map docMessages → lib's Message type, forwarding chatRefs + scrollAnchor.
|
|
712
|
+
const messages: Message[] = useMemo(
|
|
713
|
+
() =>
|
|
714
|
+
rawMessages.map((m) => ({
|
|
715
|
+
id: m.id,
|
|
716
|
+
role: m.role as 'user' | 'assistant',
|
|
717
|
+
name: m.role === 'assistant' ? 'Mingo AI' : 'You',
|
|
718
|
+
content: m.segments && m.segments.length > 0 ? m.segments : m.content,
|
|
719
|
+
timestamp: new Date(),
|
|
720
|
+
assistantType: m.role === 'assistant' ? ('mingo' as const) : undefined,
|
|
721
|
+
...(m.chatRefs ? { chatRefs: m.chatRefs } : {}),
|
|
722
|
+
...(m.scrollAnchor ? { scrollAnchor: m.scrollAnchor } : {}),
|
|
723
|
+
})),
|
|
724
|
+
[rawMessages],
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
const handleSend = useCallback(
|
|
728
|
+
(text: string) => {
|
|
729
|
+
// Append chat-attachment markdown lines to the user's bubble.
|
|
730
|
+
let augmentedText = text
|
|
731
|
+
if (readyAttachments.length > 0) {
|
|
732
|
+
const markdown = readyAttachments
|
|
733
|
+
.map((att) => formatChatAttachmentMarkdownForBubble(att, viewUrlPrefix))
|
|
734
|
+
.join('')
|
|
735
|
+
augmentedText = `${text}${markdown}`
|
|
736
|
+
}
|
|
737
|
+
sendMessage(augmentedText, {
|
|
738
|
+
...(readyAttachments.length > 0
|
|
739
|
+
? { pendingAttachments: readyAttachments }
|
|
740
|
+
: {}),
|
|
741
|
+
})
|
|
742
|
+
if (readyAttachments.length > 0) {
|
|
743
|
+
clearAttachments()
|
|
744
|
+
}
|
|
745
|
+
},
|
|
746
|
+
[sendMessage, readyAttachments, viewUrlPrefix, clearAttachments],
|
|
747
|
+
)
|
|
748
|
+
|
|
749
|
+
const handleNewChat = useCallback(() => {
|
|
750
|
+
clearMessages()
|
|
751
|
+
}, [clearMessages])
|
|
752
|
+
|
|
753
|
+
const handleOpen = useCallback(() => setIsOpen(true), [setIsOpen])
|
|
754
|
+
|
|
755
|
+
// Close on every pathname change. Lib has no `usePathname()`, so we pass
|
|
756
|
+
// `null` — embedders that want pathname-driven close can wrap this
|
|
757
|
+
// component with their own close-on-navigation effect. The hub mounts
|
|
758
|
+
// `<HubRuntimeProvider>` which already supplies this behavior on the
|
|
759
|
+
// outer shell, so the chat panel close is a single concern here.
|
|
760
|
+
useCloseOnNavigation(handleNavigationClose, null)
|
|
761
|
+
|
|
762
|
+
// Listen for cross-component "open chat with this row" events. Fired by
|
|
763
|
+
// search bars when the user clicks a result with no public URL.
|
|
764
|
+
useEffect(() => {
|
|
765
|
+
const handler = (e: Event) => {
|
|
766
|
+
const detail = (
|
|
767
|
+
e as CustomEvent<{
|
|
768
|
+
source: string
|
|
769
|
+
ref: { type: string; id: string; title: string; url: string | null }
|
|
770
|
+
}>
|
|
771
|
+
).detail
|
|
772
|
+
if (!detail || detail.source !== source) return
|
|
773
|
+
setIsOpen(true)
|
|
774
|
+
setTimeout(() => discussRef(detail.ref as ChatRef), 0)
|
|
775
|
+
}
|
|
776
|
+
window.addEventListener('ask-ai:open-with-ref', handler)
|
|
777
|
+
return () => window.removeEventListener('ask-ai:open-with-ref', handler)
|
|
778
|
+
}, [source, discussRef, setIsOpen])
|
|
779
|
+
|
|
780
|
+
const hasMessages = messages.length > 0
|
|
781
|
+
const sourceLabel = source === 'flamingo' ? 'Knowledge Base' : 'Data Room'
|
|
782
|
+
const greetingText =
|
|
783
|
+
emptyStateGreeting || `Ask me anything about ${sourceLabel.toLowerCase()}.`
|
|
784
|
+
|
|
785
|
+
// Empty-state chip grid — derived directly from the fetched slash commands.
|
|
786
|
+
const enabledSet = useMemo(
|
|
787
|
+
() => (enabledRagTableIds ? new Set<string>(enabledRagTableIds) : null),
|
|
788
|
+
[enabledRagTableIds],
|
|
789
|
+
)
|
|
790
|
+
const chipCommands = useMemo(() => {
|
|
791
|
+
const out: SlashCommandSummary[] = []
|
|
792
|
+
for (const cmd of commandsById.values()) {
|
|
793
|
+
if (cmd.displayOrder === undefined) continue
|
|
794
|
+
if (enabledSet && cmd.primarySourceId && !enabledSet.has(cmd.primarySourceId))
|
|
795
|
+
continue
|
|
796
|
+
out.push(cmd)
|
|
797
|
+
}
|
|
798
|
+
out.sort((a, b) => {
|
|
799
|
+
const ao = a.displayOrder ?? Number.POSITIVE_INFINITY
|
|
800
|
+
const bo = b.displayOrder ?? Number.POSITIVE_INFINITY
|
|
801
|
+
if (ao !== bo) return ao - bo
|
|
802
|
+
return a.id.localeCompare(b.id)
|
|
803
|
+
})
|
|
804
|
+
return out
|
|
805
|
+
}, [commandsById, enabledSet])
|
|
806
|
+
|
|
807
|
+
// Find sources for the last assistant message; split into cited / uncited.
|
|
808
|
+
const lastAssistantMsg = [...rawMessages].reverse().find((m) => m.role === 'assistant')
|
|
809
|
+
const lastSources = useMemo(() => {
|
|
810
|
+
if (chatLoading) return undefined
|
|
811
|
+
const sources = lastAssistantMsg?.sources
|
|
812
|
+
if (!sources || sources.length === 0) return undefined
|
|
813
|
+
const content = lastAssistantMsg?.content || ''
|
|
814
|
+
const citationOrder = [...content.matchAll(/\[(\d+)\]/g)].map((m) =>
|
|
815
|
+
parseInt(m[1], 10),
|
|
816
|
+
)
|
|
817
|
+
const seenOrder = new Map<number, number>()
|
|
818
|
+
citationOrder.forEach((idx) => {
|
|
819
|
+
if (!seenOrder.has(idx)) seenOrder.set(idx, seenOrder.size)
|
|
820
|
+
})
|
|
821
|
+
const cited = sources
|
|
822
|
+
.filter((s) => seenOrder.has(s.index))
|
|
823
|
+
.sort((a, b) => (seenOrder.get(a.index) ?? 0) - (seenOrder.get(b.index) ?? 0))
|
|
824
|
+
const uncited = sources.filter((s) => !seenOrder.has(s.index))
|
|
825
|
+
return { cited, uncited }
|
|
826
|
+
}, [lastAssistantMsg, chatLoading])
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
return (
|
|
830
|
+
<>
|
|
831
|
+
{/* Floating "Ask AI" button — sticky-dock pattern. See hub original
|
|
832
|
+
for the full mechanism explanation. */}
|
|
833
|
+
{showInternalTrigger && (
|
|
834
|
+
<div
|
|
835
|
+
aria-hidden={isOpen}
|
|
836
|
+
className={`sticky bottom-0 h-0 z-[9990] pointer-events-none ${
|
|
837
|
+
isOpen ? 'opacity-0' : 'opacity-100'
|
|
838
|
+
}`}
|
|
839
|
+
>
|
|
840
|
+
<div className="absolute bottom-4 md:bottom-6 right-4 md:right-6">
|
|
841
|
+
<Button
|
|
842
|
+
onClick={handleOpen}
|
|
843
|
+
leftIcon={<MingoIcon className="h-5 w-5" color="currentColor" />}
|
|
844
|
+
tabIndex={isOpen ? -1 : 0}
|
|
845
|
+
className={`shadow-lg !w-auto pointer-events-auto ${
|
|
846
|
+
isOpen ? '!pointer-events-none' : ''
|
|
847
|
+
}`}
|
|
848
|
+
>
|
|
849
|
+
Ask AI
|
|
850
|
+
</Button>
|
|
851
|
+
</div>
|
|
852
|
+
</div>
|
|
853
|
+
)}
|
|
854
|
+
|
|
855
|
+
<Dialog.Root open={isOpen} onOpenChange={(o) => !o && handleClose()}>
|
|
856
|
+
<Dialog.Portal>
|
|
857
|
+
<Dialog.Overlay className="mingo-chat-overlay fixed inset-0 z-[9997] bg-black/50 md:bg-black/20" />
|
|
858
|
+
{/*
|
|
859
|
+
Panel-level handle for descendants (inline cards via
|
|
860
|
+
`ChatCardNavWrap`, markdown-body links via
|
|
861
|
+
`NavLinkAnchorViaRuntime`) to close the panel after same-tab
|
|
862
|
+
navigation. Same-tab clicks fire `closeChat`; new-tab clicks
|
|
863
|
+
leave the panel open while the new tab loads.
|
|
864
|
+
*/}
|
|
865
|
+
<ChatPanelContext.Provider value={chatPanelHandle}>
|
|
866
|
+
<Dialog.Content
|
|
867
|
+
aria-describedby={undefined}
|
|
868
|
+
onAnimationEnd={(e) => {
|
|
869
|
+
if (e.currentTarget === e.target && isOpen) setAnimationRest(true)
|
|
870
|
+
}}
|
|
871
|
+
style={animationRest ? { transform: 'none', animation: 'none' } : undefined}
|
|
872
|
+
className="
|
|
873
|
+
mingo-chat-content
|
|
874
|
+
fixed z-[9998] flex flex-col bg-ods-bg
|
|
875
|
+
focus:outline-none focus-visible:outline-none
|
|
876
|
+
inset-0 h-[100dvh] max-h-[100dvh] shadow-2xl
|
|
877
|
+
md:inset-y-0 md:right-0 md:left-auto md:h-full md:max-h-none md:w-[clamp(480px,50vw,720px)] md:max-w-none md:rounded-l-2xl md:border-l md:border-ods-border
|
|
878
|
+
"
|
|
879
|
+
>
|
|
880
|
+
<VisuallyHidden>
|
|
881
|
+
<Dialog.Title>{sourceLabel} AI Assistant</Dialog.Title>
|
|
882
|
+
</VisuallyHidden>
|
|
883
|
+
|
|
884
|
+
<div className="flex h-full flex-col overflow-hidden">
|
|
885
|
+
<div className="flex-shrink-0 px-5 pt-4">
|
|
886
|
+
<ChatHeader
|
|
887
|
+
userName="Mingo AI"
|
|
888
|
+
userTitle={`${sourceLabel} Assistant`}
|
|
889
|
+
userIcon={<MingoIcon className="h-6 w-6" color="white" />}
|
|
890
|
+
onNewChat={handleNewChat}
|
|
891
|
+
onClose={handleClose}
|
|
892
|
+
showNewChat={hasMessages}
|
|
893
|
+
connectionStatus="connected"
|
|
894
|
+
fullWidth
|
|
895
|
+
className="!rounded-xl"
|
|
896
|
+
/>
|
|
897
|
+
</div>
|
|
898
|
+
|
|
899
|
+
<div
|
|
900
|
+
ref={galleryPanelRef}
|
|
901
|
+
className="flex-1 flex flex-col min-h-0 px-5 py-4"
|
|
902
|
+
>
|
|
903
|
+
{hasMessages ? (
|
|
904
|
+
<div className="flex-1 flex flex-col min-h-0">
|
|
905
|
+
<ChatMessageList
|
|
906
|
+
messages={messages}
|
|
907
|
+
isTyping={chatLoading}
|
|
908
|
+
autoScroll={true}
|
|
909
|
+
assistantType="mingo"
|
|
910
|
+
assistantIcon={<MingoIcon className="h-4 w-4" color="white" />}
|
|
911
|
+
renderEntityCard={renderEntityCard}
|
|
912
|
+
NavLinkAnchor={NavLinkAnchorViaRuntime}
|
|
913
|
+
className="flex-1"
|
|
914
|
+
fullWidth
|
|
915
|
+
/>
|
|
916
|
+
{lastSources &&
|
|
917
|
+
(lastSources.cited.length > 0 ||
|
|
918
|
+
lastSources.uncited.length > 0) &&
|
|
919
|
+
!chatLoading && (
|
|
920
|
+
<div className="flex-shrink-0 pb-2">
|
|
921
|
+
<SourceChips
|
|
922
|
+
cited={lastSources.cited}
|
|
923
|
+
uncited={lastSources.uncited}
|
|
924
|
+
baseRoute={resolvedBaseRoute}
|
|
925
|
+
chipBasePlatform={chipBasePlatform}
|
|
926
|
+
onClose={handleNavigationClose}
|
|
927
|
+
onDiscuss={discussRef}
|
|
928
|
+
/>
|
|
929
|
+
</div>
|
|
930
|
+
)}
|
|
931
|
+
</div>
|
|
932
|
+
) : (
|
|
933
|
+
<div className="flex-1 flex flex-col items-center pt-8 pb-6 overflow-y-auto -mt-4">
|
|
934
|
+
<div className="text-center max-w-md w-full mb-8">
|
|
935
|
+
<MingoIcon
|
|
936
|
+
className="mx-auto mb-4 h-10 w-10"
|
|
937
|
+
color="var(--ods-accent)"
|
|
938
|
+
/>
|
|
939
|
+
<p
|
|
940
|
+
className="text-2xl font-semibold text-ods-text-primary mb-2 tracking-[-0.02em]"
|
|
941
|
+
style={{ fontFamily: 'var(--font-h1-family)' }}
|
|
942
|
+
>
|
|
943
|
+
{userName ? `Hey ${userName}, I'm Mingo` : "Hey, I'm Mingo"}
|
|
944
|
+
</p>
|
|
945
|
+
<p className="text-ods-text-secondary text-sm leading-relaxed">
|
|
946
|
+
{greetingText}
|
|
947
|
+
</p>
|
|
948
|
+
</div>
|
|
949
|
+
|
|
950
|
+
{suggestedQueries && suggestedQueries.length > 0 && (
|
|
951
|
+
<div className="w-full mb-8">
|
|
952
|
+
<p className="text-xs text-ods-text-secondary mb-3 px-1">
|
|
953
|
+
Try asking:
|
|
954
|
+
</p>
|
|
955
|
+
<div className="flex flex-wrap gap-2">
|
|
956
|
+
{suggestedQueries.map((q) => (
|
|
957
|
+
<button
|
|
958
|
+
key={q}
|
|
959
|
+
type="button"
|
|
960
|
+
onClick={() => handleSend(q)}
|
|
961
|
+
className="rounded-full border border-ods-border bg-ods-bg-secondary px-3 py-1.5 text-sm text-ods-text-primary hover:border-ods-accent hover:bg-ods-bg-hover transition-colors"
|
|
962
|
+
>
|
|
963
|
+
{q}
|
|
964
|
+
</button>
|
|
965
|
+
))}
|
|
966
|
+
</div>
|
|
967
|
+
</div>
|
|
968
|
+
)}
|
|
969
|
+
|
|
970
|
+
{(chipCommands.length > 0 || !commandsLoaded) && (
|
|
971
|
+
<div className="w-full">
|
|
972
|
+
<p className="text-xs text-ods-text-secondary mb-3 px-1">
|
|
973
|
+
I can help you with:
|
|
974
|
+
</p>
|
|
975
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
|
976
|
+
{!commandsLoaded &&
|
|
977
|
+
chipCommands.length === 0 &&
|
|
978
|
+
Array.from({ length: 4 }).map((_, i) => (
|
|
979
|
+
<Card
|
|
980
|
+
key={`chip-skeleton-${i}`}
|
|
981
|
+
className="flex items-start gap-3 px-4 py-3 bg-ods-card border-ods-border shadow-none animate-pulse"
|
|
982
|
+
>
|
|
983
|
+
<div className="h-5 w-5 mt-0.5 shrink-0 rounded bg-ods-bg" />
|
|
984
|
+
<div className="min-w-0 flex-1 flex flex-col gap-2">
|
|
985
|
+
<div className="h-4 w-1/2 rounded bg-ods-bg" />
|
|
986
|
+
<div className="h-3 w-3/4 rounded bg-ods-bg/60" />
|
|
987
|
+
</div>
|
|
988
|
+
</Card>
|
|
989
|
+
))}
|
|
990
|
+
{chipCommands.map((cmd) => {
|
|
991
|
+
const Icon = getIconComponent(cmd.iconName)
|
|
992
|
+
const cmdId = cmd.id
|
|
993
|
+
const label = cmd.label ?? `/${cmdId}`
|
|
994
|
+
return (
|
|
995
|
+
<Card
|
|
996
|
+
key={cmdId}
|
|
997
|
+
className="flex flex-col gap-2 px-4 py-3 bg-ods-card border-ods-border shadow-none hover:border-ods-accent/50 transition-colors"
|
|
998
|
+
>
|
|
999
|
+
<div className="flex items-start gap-3">
|
|
1000
|
+
<Icon className="h-5 w-5 mt-0.5 shrink-0 text-ods-text-primary" />
|
|
1001
|
+
<div className="text-sm font-medium text-ods-text-primary truncate flex-1 min-w-0">
|
|
1002
|
+
{label}
|
|
1003
|
+
</div>
|
|
1004
|
+
<span className="font-mono text-[11px] text-ods-text-muted shrink-0 mt-0.5 max-w-[40%] truncate">
|
|
1005
|
+
/{cmdId}
|
|
1006
|
+
</span>
|
|
1007
|
+
</div>
|
|
1008
|
+
{cmd.description && (
|
|
1009
|
+
<p className="text-xs text-ods-text-muted leading-snug line-clamp-2">
|
|
1010
|
+
{cmd.description}
|
|
1011
|
+
</p>
|
|
1012
|
+
)}
|
|
1013
|
+
<div className="flex flex-wrap items-center gap-1.5 -mb-0.5">
|
|
1014
|
+
{cmd.actions.map((action) => (
|
|
1015
|
+
<button
|
|
1016
|
+
key={action.id}
|
|
1017
|
+
type="button"
|
|
1018
|
+
onClick={() =>
|
|
1019
|
+
dispatchSlashCommandAction(
|
|
1020
|
+
action.id,
|
|
1021
|
+
cmdId,
|
|
1022
|
+
chatInputRef,
|
|
1023
|
+
)
|
|
1024
|
+
}
|
|
1025
|
+
aria-label={`${action.label} ${label}`}
|
|
1026
|
+
title={`${action.label} ${label}`}
|
|
1027
|
+
className={CHIP_ACTION_BUTTON_CLASS}
|
|
1028
|
+
>
|
|
1029
|
+
{action.label}
|
|
1030
|
+
</button>
|
|
1031
|
+
))}
|
|
1032
|
+
</div>
|
|
1033
|
+
</Card>
|
|
1034
|
+
)
|
|
1035
|
+
})}
|
|
1036
|
+
</div>
|
|
1037
|
+
</div>
|
|
1038
|
+
)}
|
|
1039
|
+
</div>
|
|
1040
|
+
)}
|
|
1041
|
+
</div>
|
|
1042
|
+
|
|
1043
|
+
<ChatAttachmentChipStrip
|
|
1044
|
+
attachments={stagedAttachments}
|
|
1045
|
+
onRemove={removeAttachment}
|
|
1046
|
+
disabled={chatLoading}
|
|
1047
|
+
/>
|
|
1048
|
+
|
|
1049
|
+
<div
|
|
1050
|
+
className="flex-shrink-0 px-5 pb-4 flex flex-col gap-1"
|
|
1051
|
+
style={{ paddingBottom: 'max(1rem, env(safe-area-inset-bottom))' }}
|
|
1052
|
+
>
|
|
1053
|
+
<ChatFooter className="!p-0" fullWidth>
|
|
1054
|
+
<ChatInput
|
|
1055
|
+
ref={chatInputRef}
|
|
1056
|
+
onSend={handleSend}
|
|
1057
|
+
onStop={stopMessage}
|
|
1058
|
+
sending={chatLoading || hasInflightUploads}
|
|
1059
|
+
placeholder={
|
|
1060
|
+
hasInflightUploads
|
|
1061
|
+
? 'Waiting for uploads to finish…'
|
|
1062
|
+
: 'Ask a question...'
|
|
1063
|
+
}
|
|
1064
|
+
fullWidth
|
|
1065
|
+
className="px-0"
|
|
1066
|
+
reserveAvatarOffset={false}
|
|
1067
|
+
autoFocus={autoFocusInput}
|
|
1068
|
+
slashCommands={slashCommandsProp}
|
|
1069
|
+
/>
|
|
1070
|
+
</ChatFooter>
|
|
1071
|
+
|
|
1072
|
+
<div className="flex items-center gap-2 w-full">
|
|
1073
|
+
<ChatAttachmentAddButton
|
|
1074
|
+
attachmentsEnabled={attachmentsEnabled}
|
|
1075
|
+
attachmentsCount={stagedAttachments.length}
|
|
1076
|
+
onAddFiles={addAttachmentFiles}
|
|
1077
|
+
disabled={chatLoading}
|
|
1078
|
+
/>
|
|
1079
|
+
<div className="flex-1 min-w-0">
|
|
1080
|
+
<ModelDisplay
|
|
1081
|
+
provider={currentProvider ?? 'anthropic'}
|
|
1082
|
+
modelName={currentModelLabel ?? 'Claude'}
|
|
1083
|
+
usedTokens={
|
|
1084
|
+
currentInputTokens != null
|
|
1085
|
+
? (currentInputTokens ?? 0) + (currentOutputTokens ?? 0)
|
|
1086
|
+
: undefined
|
|
1087
|
+
}
|
|
1088
|
+
contextWindow={currentContextWindowMaxTokens ?? undefined}
|
|
1089
|
+
inputTokens={currentInputTokens ?? undefined}
|
|
1090
|
+
outputTokens={currentOutputTokens ?? undefined}
|
|
1091
|
+
hitRatePct={currentCacheHitRatePct ?? undefined}
|
|
1092
|
+
breakdown={currentUsageBreakdown ?? undefined}
|
|
1093
|
+
/>
|
|
1094
|
+
</div>
|
|
1095
|
+
</div>
|
|
1096
|
+
</div>
|
|
1097
|
+
</div>
|
|
1098
|
+
{galleryModal}
|
|
1099
|
+
</Dialog.Content>
|
|
1100
|
+
</ChatPanelContext.Provider>
|
|
1101
|
+
</Dialog.Portal>
|
|
1102
|
+
</Dialog.Root>
|
|
1103
|
+
</>
|
|
1104
|
+
)
|
|
1105
|
+
}
|
|
1106
|
+
|