@compose-market/theme 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/RFAComponent.d.ts +10 -0
- package/dist/components/RFAComponent.d.ts.map +1 -0
- package/dist/components/RFAComponent.js +288 -0
- package/dist/components/RFAComponent.js.map +1 -0
- package/dist/components/RFADetails.d.ts +9 -0
- package/dist/components/RFADetails.d.ts.map +1 -0
- package/dist/components/RFADetails.js +407 -0
- package/dist/components/RFADetails.js.map +1 -0
- package/dist/components/agent-card.d.ts +8 -0
- package/dist/components/agent-card.d.ts.map +1 -0
- package/dist/components/agent-card.js +216 -0
- package/dist/components/agent-card.js.map +1 -0
- package/dist/components/backpack.d.ts +21 -0
- package/dist/components/backpack.d.ts.map +1 -0
- package/dist/components/backpack.js +905 -0
- package/dist/components/backpack.js.map +1 -0
- package/dist/components/blur.d.ts +9 -0
- package/dist/components/blur.d.ts.map +1 -0
- package/dist/components/blur.js +60 -0
- package/dist/components/blur.js.map +1 -0
- package/dist/components/brand/Logo.d.ts +25 -0
- package/dist/components/brand/Logo.d.ts.map +1 -0
- package/dist/components/brand/Logo.js +53 -0
- package/dist/components/brand/Logo.js.map +1 -0
- package/dist/components/brand/index.d.ts +2 -0
- package/dist/components/brand/index.d.ts.map +1 -0
- package/dist/components/brand/index.js +2 -0
- package/dist/components/brand/index.js.map +1 -0
- package/dist/components/chat.d.ts +68 -0
- package/dist/components/chat.d.ts.map +1 -0
- package/dist/components/chat.js +618 -0
- package/dist/components/chat.js.map +1 -0
- package/dist/components/compose/index.d.ts +10 -0
- package/dist/components/compose/index.d.ts.map +1 -0
- package/dist/components/compose/index.js +13 -0
- package/dist/components/compose/index.js.map +1 -0
- package/dist/components/compose/nodes/agent-node.d.ts +11 -0
- package/dist/components/compose/nodes/agent-node.d.ts.map +1 -0
- package/dist/components/compose/nodes/agent-node.js +101 -0
- package/dist/components/compose/nodes/agent-node.js.map +1 -0
- package/dist/components/compose/nodes/hook-node.d.ts +11 -0
- package/dist/components/compose/nodes/hook-node.d.ts.map +1 -0
- package/dist/components/compose/nodes/hook-node.js +100 -0
- package/dist/components/compose/nodes/hook-node.js.map +1 -0
- package/dist/components/compose/nodes/index.d.ts +60 -0
- package/dist/components/compose/nodes/index.d.ts.map +1 -0
- package/dist/components/compose/nodes/index.js +22 -0
- package/dist/components/compose/nodes/index.js.map +1 -0
- package/dist/components/compose/nodes/step-node.d.ts +11 -0
- package/dist/components/compose/nodes/step-node.d.ts.map +1 -0
- package/dist/components/compose/nodes/step-node.js +88 -0
- package/dist/components/compose/nodes/step-node.js.map +1 -0
- package/dist/components/compose/nodes/trigger-node.d.ts +11 -0
- package/dist/components/compose/nodes/trigger-node.d.ts.map +1 -0
- package/dist/components/compose/nodes/trigger-node.js +92 -0
- package/dist/components/compose/nodes/trigger-node.js.map +1 -0
- package/dist/components/compose/overlay.d.ts +26 -0
- package/dist/components/compose/overlay.d.ts.map +1 -0
- package/dist/components/compose/overlay.js +48 -0
- package/dist/components/compose/overlay.js.map +1 -0
- package/dist/components/compose/pickers/agents-picker.d.ts +18 -0
- package/dist/components/compose/pickers/agents-picker.d.ts.map +1 -0
- package/dist/components/compose/pickers/agents-picker.js +180 -0
- package/dist/components/compose/pickers/agents-picker.js.map +1 -0
- package/dist/components/compose/pickers/connector-detail.d.ts +16 -0
- package/dist/components/compose/pickers/connector-detail.d.ts.map +1 -0
- package/dist/components/compose/pickers/connector-detail.js +236 -0
- package/dist/components/compose/pickers/connector-detail.js.map +1 -0
- package/dist/components/compose/pickers/connector-picker.d.ts +13 -0
- package/dist/components/compose/pickers/connector-picker.d.ts.map +1 -0
- package/dist/components/compose/pickers/connector-picker.js +101 -0
- package/dist/components/compose/pickers/connector-picker.js.map +1 -0
- package/dist/components/compose/pickers/index.d.ts +10 -0
- package/dist/components/compose/pickers/index.d.ts.map +1 -0
- package/dist/components/compose/pickers/index.js +10 -0
- package/dist/components/compose/pickers/index.js.map +1 -0
- package/dist/components/compose/pickers/trigger-picker.d.ts +13 -0
- package/dist/components/compose/pickers/trigger-picker.d.ts.map +1 -0
- package/dist/components/compose/pickers/trigger-picker.js +110 -0
- package/dist/components/compose/pickers/trigger-picker.js.map +1 -0
- package/dist/components/compose/toolbox.d.ts +24 -0
- package/dist/components/compose/toolbox.d.ts.map +1 -0
- package/dist/components/compose/toolbox.js +183 -0
- package/dist/components/compose/toolbox.js.map +1 -0
- package/dist/components/connector.d.ts +24 -0
- package/dist/components/connector.d.ts.map +1 -0
- package/dist/components/connector.js +263 -0
- package/dist/components/connector.js.map +1 -0
- package/dist/components/dispenser.d.ts +15 -0
- package/dist/components/dispenser.d.ts.map +1 -0
- package/dist/components/dispenser.js +323 -0
- package/dist/components/dispenser.js.map +1 -0
- package/dist/components/layout/AppLayout.d.ts +60 -0
- package/dist/components/layout/AppLayout.d.ts.map +1 -0
- package/dist/components/layout/AppLayout.js +265 -0
- package/dist/components/layout/AppLayout.js.map +1 -0
- package/dist/components/layout/Layout.d.ts +6 -0
- package/dist/components/layout/Layout.d.ts.map +1 -0
- package/dist/components/layout/Layout.js +186 -0
- package/dist/components/layout/Layout.js.map +1 -0
- package/dist/components/layout/Sidebar.d.ts +3 -0
- package/dist/components/layout/Sidebar.d.ts.map +1 -0
- package/dist/components/layout/Sidebar.js +160 -0
- package/dist/components/layout/Sidebar.js.map +1 -0
- package/dist/components/layout/TopBar.d.ts +6 -0
- package/dist/components/layout/TopBar.d.ts.map +1 -0
- package/dist/components/layout/TopBar.js +36 -0
- package/dist/components/layout/TopBar.js.map +1 -0
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.d.ts.map +1 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/index.js.map +1 -0
- package/dist/components/lyria-player.d.ts +23 -0
- package/dist/components/lyria-player.d.ts.map +1 -0
- package/dist/components/lyria-player.js +241 -0
- package/dist/components/lyria-player.js.map +1 -0
- package/dist/components/manowar-card.d.ts +8 -0
- package/dist/components/manowar-card.d.ts.map +1 -0
- package/dist/components/manowar-card.js +349 -0
- package/dist/components/manowar-card.js.map +1 -0
- package/dist/components/mirror-pane.d.ts +55 -0
- package/dist/components/mirror-pane.d.ts.map +1 -0
- package/dist/components/mirror-pane.js +330 -0
- package/dist/components/mirror-pane.js.map +1 -0
- package/dist/components/model-selector.d.ts +12 -0
- package/dist/components/model-selector.d.ts.map +1 -0
- package/dist/components/model-selector.js +148 -0
- package/dist/components/model-selector.js.map +1 -0
- package/dist/components/output.d.ts +26 -0
- package/dist/components/output.d.ts.map +1 -0
- package/dist/components/output.js +259 -0
- package/dist/components/output.js.map +1 -0
- package/dist/components/partners.d.ts +13 -0
- package/dist/components/partners.d.ts.map +1 -0
- package/dist/components/partners.js +210 -0
- package/dist/components/partners.js.map +1 -0
- package/dist/components/plugin-tester.d.ts +13 -0
- package/dist/components/plugin-tester.d.ts.map +1 -0
- package/dist/components/plugin-tester.js +907 -0
- package/dist/components/plugin-tester.js.map +1 -0
- package/dist/components/session/SessionComponents.d.ts +2 -0
- package/dist/components/session/SessionComponents.d.ts.map +1 -0
- package/dist/components/session/SessionComponents.js +2 -0
- package/dist/components/session/SessionComponents.js.map +1 -0
- package/dist/components/session/index.d.ts +2 -0
- package/dist/components/session/index.d.ts.map +1 -0
- package/dist/components/session/index.js +2 -0
- package/dist/components/session/index.js.map +1 -0
- package/dist/components/session.d.ts +58 -0
- package/dist/components/session.d.ts.map +1 -0
- package/dist/components/session.js +580 -0
- package/dist/components/session.js.map +1 -0
- package/dist/components/share-dialog.d.ts +9 -0
- package/dist/components/share-dialog.d.ts.map +1 -0
- package/dist/components/share-dialog.js +49 -0
- package/dist/components/share-dialog.js.map +1 -0
- package/dist/components/ui/accordion.d.ts +6 -0
- package/dist/components/ui/accordion.d.ts.map +1 -0
- package/dist/components/ui/accordion.js +20 -0
- package/dist/components/ui/accordion.js.map +1 -0
- package/dist/components/ui/alert-dialog.d.ts +20 -0
- package/dist/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/components/ui/alert-dialog.js +29 -0
- package/dist/components/ui/alert-dialog.js.map +1 -0
- package/dist/components/ui/alert.d.ts +5 -0
- package/dist/components/ui/alert.d.ts.map +1 -0
- package/dist/components/ui/alert.js +22 -0
- package/dist/components/ui/alert.js.map +1 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
- package/dist/components/ui/aspect-ratio.js +4 -0
- package/dist/components/ui/aspect-ratio.js.map +1 -0
- package/dist/components/ui/avatar.d.ts +5 -0
- package/dist/components/ui/avatar.d.ts.map +1 -0
- package/dist/components/ui/avatar.js +12 -0
- package/dist/components/ui/avatar.js.map +1 -0
- package/dist/components/ui/badge.d.ts +8 -0
- package/dist/components/ui/badge.d.ts.map +1 -0
- package/dist/components/ui/badge.js +24 -0
- package/dist/components/ui/badge.js.map +1 -0
- package/dist/components/ui/breadcrumb.d.ts +16 -0
- package/dist/components/ui/breadcrumb.d.ts.map +1 -0
- package/dist/components/ui/breadcrumb.js +28 -0
- package/dist/components/ui/breadcrumb.js.map +1 -0
- package/dist/components/ui/button-group.d.ts +10 -0
- package/dist/components/ui/button-group.d.ts.map +1 -0
- package/dist/components/ui/button-group.js +27 -0
- package/dist/components/ui/button-group.js.map +1 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +42 -0
- package/dist/components/ui/button.js.map +1 -0
- package/dist/components/ui/calendar.d.ts +9 -0
- package/dist/components/ui/calendar.d.ts.map +1 -0
- package/dist/components/ui/calendar.js +78 -0
- package/dist/components/ui/calendar.js.map +1 -0
- package/dist/components/ui/card.d.ts +8 -0
- package/dist/components/ui/card.d.ts.map +1 -0
- package/dist/components/ui/card.js +17 -0
- package/dist/components/ui/card.js.map +1 -0
- package/dist/components/ui/carousel.d.ts +9 -0
- package/dist/components/ui/carousel.d.ts.map +1 -0
- package/dist/components/ui/carousel.js +110 -0
- package/dist/components/ui/carousel.js.map +1 -0
- package/dist/components/ui/chart.d.ts +28 -0
- package/dist/components/ui/chart.d.ts.map +1 -0
- package/dist/components/ui/chart.js +168 -0
- package/dist/components/ui/chart.js.map +1 -0
- package/dist/components/ui/checkbox.d.ts +3 -0
- package/dist/components/ui/checkbox.d.ts.map +1 -0
- package/dist/components/ui/checkbox.js +12 -0
- package/dist/components/ui/checkbox.js.map +1 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/collapsible.d.ts.map +1 -0
- package/dist/components/ui/collapsible.js +7 -0
- package/dist/components/ui/collapsible.js.map +1 -0
- package/dist/components/ui/command.d.ts +16 -0
- package/dist/components/ui/command.d.ts.map +1 -0
- package/dist/components/ui/command.js +38 -0
- package/dist/components/ui/command.js.map +1 -0
- package/dist/components/ui/context-menu.d.ts +21 -0
- package/dist/components/ui/context-menu.d.ts.map +1 -0
- package/dist/components/ui/context-menu.js +52 -0
- package/dist/components/ui/context-menu.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +19 -0
- package/dist/components/ui/dialog.d.ts.map +1 -0
- package/dist/components/ui/dialog.js +31 -0
- package/dist/components/ui/dialog.js.map +1 -0
- package/dist/components/ui/drawer.d.ts +23 -0
- package/dist/components/ui/drawer.d.ts.map +1 -0
- package/dist/components/ui/drawer.js +28 -0
- package/dist/components/ui/drawer.js.map +1 -0
- package/dist/components/ui/dropdown-menu.d.ts +21 -0
- package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/components/ui/dropdown-menu.js +55 -0
- package/dist/components/ui/dropdown-menu.js.map +1 -0
- package/dist/components/ui/empty.d.ts +10 -0
- package/dist/components/ui/empty.d.ts.map +1 -0
- package/dist/components/ui/empty.js +33 -0
- package/dist/components/ui/empty.js.map +1 -0
- package/dist/components/ui/field.d.ts +23 -0
- package/dist/components/ui/field.d.ts.map +1 -0
- package/dist/components/ui/field.js +82 -0
- package/dist/components/ui/field.js.map +1 -0
- package/dist/components/ui/form.d.ts +11 -0
- package/dist/components/ui/form.d.ts.map +1 -0
- package/dist/components/ui/form.js +71 -0
- package/dist/components/ui/form.js.map +1 -0
- package/dist/components/ui/hover-card.d.ts +5 -0
- package/dist/components/ui/hover-card.d.ts.map +1 -0
- package/dist/components/ui/hover-card.js +9 -0
- package/dist/components/ui/hover-card.js.map +1 -0
- package/dist/components/ui/index.d.ts +7 -0
- package/dist/components/ui/index.d.ts.map +1 -0
- package/dist/components/ui/index.js +7 -0
- package/dist/components/ui/index.js.map +1 -0
- package/dist/components/ui/input-group.d.ts +13 -0
- package/dist/components/ui/input-group.d.ts.map +1 -0
- package/dist/components/ui/input-group.js +63 -0
- package/dist/components/ui/input-group.js.map +1 -0
- package/dist/components/ui/input-otp.d.ts +6 -0
- package/dist/components/ui/input-otp.d.ts.map +1 -0
- package/dist/components/ui/input-otp.js +25 -0
- package/dist/components/ui/input-otp.js.map +1 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/input.d.ts.map +1 -0
- package/dist/components/ui/input.js +8 -0
- package/dist/components/ui/input.js.map +1 -0
- package/dist/components/ui/item.d.ts +19 -0
- package/dist/components/ui/item.d.ts.map +1 -0
- package/dist/components/ui/item.js +67 -0
- package/dist/components/ui/item.js.map +1 -0
- package/dist/components/ui/kbd.d.ts +4 -0
- package/dist/components/ui/kbd.d.ts.map +1 -0
- package/dist/components/ui/kbd.js +9 -0
- package/dist/components/ui/kbd.js.map +1 -0
- package/dist/components/ui/label.d.ts +3 -0
- package/dist/components/ui/label.d.ts.map +1 -0
- package/dist/components/ui/label.js +10 -0
- package/dist/components/ui/label.js.map +1 -0
- package/dist/components/ui/menubar.d.ts +23 -0
- package/dist/components/ui/menubar.d.ts.map +1 -0
- package/dist/components/ui/menubar.js +64 -0
- package/dist/components/ui/menubar.js.map +1 -0
- package/dist/components/ui/navigation-menu.d.ts +11 -0
- package/dist/components/ui/navigation-menu.d.ts.map +1 -0
- package/dist/components/ui/navigation-menu.js +34 -0
- package/dist/components/ui/navigation-menu.js.map +1 -0
- package/dist/components/ui/network-selector.d.ts +22 -0
- package/dist/components/ui/network-selector.d.ts.map +1 -0
- package/dist/components/ui/network-selector.js +99 -0
- package/dist/components/ui/network-selector.js.map +1 -0
- package/dist/components/ui/pagination.d.ts +29 -0
- package/dist/components/ui/pagination.d.ts.map +1 -0
- package/dist/components/ui/pagination.js +32 -0
- package/dist/components/ui/pagination.js.map +1 -0
- package/dist/components/ui/popover.d.ts +6 -0
- package/dist/components/ui/popover.d.ts.map +1 -0
- package/dist/components/ui/popover.js +12 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/components/ui/progress.d.ts +3 -0
- package/dist/components/ui/progress.d.ts.map +1 -0
- package/dist/components/ui/progress.js +10 -0
- package/dist/components/ui/progress.js.map +1 -0
- package/dist/components/ui/radio-group.d.ts +4 -0
- package/dist/components/ui/radio-group.d.ts.map +1 -0
- package/dist/components/ui/radio-group.js +18 -0
- package/dist/components/ui/radio-group.js.map +1 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/resizable.d.ts.map +1 -0
- package/dist/components/ui/resizable.js +13 -0
- package/dist/components/ui/resizable.js.map +1 -0
- package/dist/components/ui/scroll-area.d.ts +4 -0
- package/dist/components/ui/scroll-area.d.ts.map +1 -0
- package/dist/components/ui/scroll-area.js +19 -0
- package/dist/components/ui/scroll-area.js.map +1 -0
- package/dist/components/ui/select.d.ts +12 -0
- package/dist/components/ui/select.d.ts.map +1 -0
- package/dist/components/ui/select.js +51 -0
- package/dist/components/ui/select.js.map +1 -0
- package/dist/components/ui/separator.d.ts +3 -0
- package/dist/components/ui/separator.d.ts.map +1 -0
- package/dist/components/ui/separator.js +7 -0
- package/dist/components/ui/separator.js.map +1 -0
- package/dist/components/ui/sheet.d.ts +19 -0
- package/dist/components/ui/sheet.d.ts.map +1 -0
- package/dist/components/ui/sheet.js +46 -0
- package/dist/components/ui/sheet.js.map +1 -0
- package/dist/components/ui/sidebar.d.ts +58 -0
- package/dist/components/ui/sidebar.d.ts.map +1 -0
- package/dist/components/ui/sidebar.js +246 -0
- package/dist/components/ui/sidebar.js.map +1 -0
- package/dist/components/ui/skeleton.d.ts +3 -0
- package/dist/components/ui/skeleton.d.ts.map +1 -0
- package/dist/components/ui/skeleton.js +6 -0
- package/dist/components/ui/skeleton.js.map +1 -0
- package/dist/components/ui/slider.d.ts +3 -0
- package/dist/components/ui/slider.d.ts.map +1 -0
- package/dist/components/ui/slider.js +12 -0
- package/dist/components/ui/slider.js.map +1 -0
- package/dist/components/ui/sonner.d.ts +5 -0
- package/dist/components/ui/sonner.d.ts.map +1 -0
- package/dist/components/ui/sonner.js +16 -0
- package/dist/components/ui/sonner.js.map +1 -0
- package/dist/components/ui/spinner.d.ts +3 -0
- package/dist/components/ui/spinner.d.ts.map +1 -0
- package/dist/components/ui/spinner.js +7 -0
- package/dist/components/ui/spinner.js.map +1 -0
- package/dist/components/ui/surface-variant.d.ts +4 -0
- package/dist/components/ui/surface-variant.d.ts.map +1 -0
- package/dist/components/ui/surface-variant.js +10 -0
- package/dist/components/ui/surface-variant.js.map +1 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/switch.d.ts.map +1 -0
- package/dist/components/ui/switch.js +9 -0
- package/dist/components/ui/switch.js.map +1 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/table.d.ts.map +1 -0
- package/dist/components/ui/table.js +22 -0
- package/dist/components/ui/table.js.map +1 -0
- package/dist/components/ui/tabs.d.ts +6 -0
- package/dist/components/ui/tabs.d.ts.map +1 -0
- package/dist/components/ui/tabs.js +13 -0
- package/dist/components/ui/tabs.js.map +1 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/textarea.d.ts.map +1 -0
- package/dist/components/ui/textarea.js +8 -0
- package/dist/components/ui/textarea.js.map +1 -0
- package/dist/components/ui/toast.d.ts +12 -0
- package/dist/components/ui/toast.d.ts.map +1 -0
- package/dist/components/ui/toast.js +35 -0
- package/dist/components/ui/toast.js.map +1 -0
- package/dist/components/ui/toaster.d.ts +2 -0
- package/dist/components/ui/toaster.d.ts.map +1 -0
- package/dist/components/ui/toaster.js +19 -0
- package/dist/components/ui/toaster.js.map +1 -0
- package/dist/components/ui/toggle-group.d.ts +4 -0
- package/dist/components/ui/toggle-group.d.ts.map +1 -0
- package/dist/components/ui/toggle-group.js +27 -0
- package/dist/components/ui/toggle-group.js.map +1 -0
- package/dist/components/ui/toggle.d.ts +4 -0
- package/dist/components/ui/toggle.d.ts.map +1 -0
- package/dist/components/ui/toggle.js +25 -0
- package/dist/components/ui/toggle.js.map +1 -0
- package/dist/components/ui/tooltip.d.ts +6 -0
- package/dist/components/ui/tooltip.d.ts.map +1 -0
- package/dist/components/ui/tooltip.js +13 -0
- package/dist/components/ui/tooltip.js.map +1 -0
- package/dist/components/visual/ManowarField.d.ts +9 -0
- package/dist/components/visual/ManowarField.d.ts.map +1 -0
- package/dist/components/visual/ManowarField.js +111 -0
- package/dist/components/visual/ManowarField.js.map +1 -0
- package/dist/components/warp-form.d.ts +22 -0
- package/dist/components/warp-form.d.ts.map +1 -0
- package/dist/components/warp-form.js +743 -0
- package/dist/components/warp-form.js.map +1 -0
- package/dist/hooks/use-agents.d.ts +17 -0
- package/dist/hooks/use-agents.d.ts.map +1 -0
- package/dist/hooks/use-agents.js +64 -0
- package/dist/hooks/use-agents.js.map +1 -0
- package/dist/hooks/use-api.d.ts +28 -0
- package/dist/hooks/use-api.d.ts.map +1 -0
- package/dist/hooks/use-api.js +114 -0
- package/dist/hooks/use-api.js.map +1 -0
- package/dist/hooks/use-chat.d.ts +64 -0
- package/dist/hooks/use-chat.d.ts.map +1 -0
- package/dist/hooks/use-chat.js +350 -0
- package/dist/hooks/use-chat.js.map +1 -0
- package/dist/hooks/use-coordinator.d.ts +41 -0
- package/dist/hooks/use-coordinator.d.ts.map +1 -0
- package/dist/hooks/use-coordinator.js +110 -0
- package/dist/hooks/use-coordinator.js.map +1 -0
- package/dist/hooks/use-dispenser.d.ts +68 -0
- package/dist/hooks/use-dispenser.d.ts.map +1 -0
- package/dist/hooks/use-dispenser.js +113 -0
- package/dist/hooks/use-dispenser.js.map +1 -0
- package/dist/hooks/use-lyria.d.ts +58 -0
- package/dist/hooks/use-lyria.d.ts.map +1 -0
- package/dist/hooks/use-lyria.js +254 -0
- package/dist/hooks/use-lyria.js.map +1 -0
- package/dist/hooks/use-mobile.d.ts +2 -0
- package/dist/hooks/use-mobile.d.ts.map +1 -0
- package/dist/hooks/use-mobile.js +16 -0
- package/dist/hooks/use-mobile.js.map +1 -0
- package/dist/hooks/use-model.d.ts +34 -0
- package/dist/hooks/use-model.d.ts.map +1 -0
- package/dist/hooks/use-model.js +105 -0
- package/dist/hooks/use-model.js.map +1 -0
- package/dist/hooks/use-motion-governor.d.ts +10 -0
- package/dist/hooks/use-motion-governor.d.ts.map +1 -0
- package/dist/hooks/use-motion-governor.js +63 -0
- package/dist/hooks/use-motion-governor.js.map +1 -0
- package/dist/hooks/use-multichain.d.ts +34 -0
- package/dist/hooks/use-multichain.d.ts.map +1 -0
- package/dist/hooks/use-multichain.js +120 -0
- package/dist/hooks/use-multichain.js.map +1 -0
- package/dist/hooks/use-onchain.d.ts +145 -0
- package/dist/hooks/use-onchain.d.ts.map +1 -0
- package/dist/hooks/use-onchain.js +652 -0
- package/dist/hooks/use-onchain.js.map +1 -0
- package/dist/hooks/use-registry.d.ts +140 -0
- package/dist/hooks/use-registry.d.ts.map +1 -0
- package/dist/hooks/use-registry.js +264 -0
- package/dist/hooks/use-registry.js.map +1 -0
- package/dist/hooks/use-services.d.ts +66 -0
- package/dist/hooks/use-services.d.ts.map +1 -0
- package/dist/hooks/use-services.js +216 -0
- package/dist/hooks/use-services.js.map +1 -0
- package/dist/hooks/use-session.d.ts +36 -0
- package/dist/hooks/use-session.d.ts.map +1 -0
- package/dist/hooks/use-session.js +449 -0
- package/dist/hooks/use-session.js.map +1 -0
- package/dist/hooks/use-sse.d.ts +8 -0
- package/dist/hooks/use-sse.d.ts.map +1 -0
- package/dist/hooks/use-sse.js +86 -0
- package/dist/hooks/use-sse.js.map +1 -0
- package/dist/hooks/use-tabs.d.ts +2 -0
- package/dist/hooks/use-tabs.d.ts.map +1 -0
- package/dist/hooks/use-tabs.js +43 -0
- package/dist/hooks/use-tabs.js.map +1 -0
- package/dist/hooks/use-toast.d.ts +41 -0
- package/dist/hooks/use-toast.d.ts.map +1 -0
- package/dist/hooks/use-toast.js +127 -0
- package/dist/hooks/use-toast.js.map +1 -0
- package/dist/hooks/use-triggers.d.ts +51 -0
- package/dist/hooks/use-triggers.d.ts.map +1 -0
- package/dist/hooks/use-triggers.js +212 -0
- package/dist/hooks/use-triggers.js.map +1 -0
- package/dist/hooks/use-warp.d.ts +53 -0
- package/dist/hooks/use-warp.d.ts.map +1 -0
- package/dist/hooks/use-warp.js +231 -0
- package/dist/hooks/use-warp.js.map +1 -0
- package/dist/hooks/use-workflow.d.ts +40 -0
- package/dist/hooks/use-workflow.d.ts.map +1 -0
- package/dist/hooks/use-workflow.js +358 -0
- package/dist/hooks/use-workflow.js.map +1 -0
- package/dist/lib/agents.d.ts +186 -0
- package/dist/lib/agents.d.ts.map +1 -0
- package/dist/lib/agents.js +633 -0
- package/dist/lib/agents.js.map +1 -0
- package/dist/lib/api.d.ts +224 -0
- package/dist/lib/api.d.ts.map +1 -0
- package/dist/lib/api.js +443 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/chains.d.ts +151 -0
- package/dist/lib/chains.d.ts.map +1 -0
- package/dist/lib/chains.js +297 -0
- package/dist/lib/chains.js.map +1 -0
- package/dist/lib/contracts.d.ts +960 -0
- package/dist/lib/contracts.d.ts.map +1 -0
- package/dist/lib/contracts.js +716 -0
- package/dist/lib/contracts.js.map +1 -0
- package/dist/lib/cronos/aa.d.ts +111 -0
- package/dist/lib/cronos/aa.d.ts.map +1 -0
- package/dist/lib/cronos/aa.js +312 -0
- package/dist/lib/cronos/aa.js.map +1 -0
- package/dist/lib/cronos/facilitator.d.ts +87 -0
- package/dist/lib/cronos/facilitator.d.ts.map +1 -0
- package/dist/lib/cronos/facilitator.js +183 -0
- package/dist/lib/cronos/facilitator.js.map +1 -0
- package/dist/lib/evm.d.ts +45 -0
- package/dist/lib/evm.d.ts.map +1 -0
- package/dist/lib/evm.js +78 -0
- package/dist/lib/evm.js.map +1 -0
- package/dist/lib/mockData.d.ts +26 -0
- package/dist/lib/mockData.d.ts.map +1 -0
- package/dist/lib/mockData.js +89 -0
- package/dist/lib/mockData.js.map +1 -0
- package/dist/lib/models.d.ts +122 -0
- package/dist/lib/models.d.ts.map +1 -0
- package/dist/lib/models.js +174 -0
- package/dist/lib/models.js.map +1 -0
- package/dist/lib/multimodal.d.ts +53 -0
- package/dist/lib/multimodal.d.ts.map +1 -0
- package/dist/lib/multimodal.js +204 -0
- package/dist/lib/multimodal.js.map +1 -0
- package/dist/lib/payment.d.ts +67 -0
- package/dist/lib/payment.d.ts.map +1 -0
- package/dist/lib/payment.js +236 -0
- package/dist/lib/payment.js.map +1 -0
- package/dist/lib/pinata.d.ts +140 -0
- package/dist/lib/pinata.d.ts.map +1 -0
- package/dist/lib/pinata.js +209 -0
- package/dist/lib/pinata.js.map +1 -0
- package/dist/lib/queryClient.d.ts +9 -0
- package/dist/lib/queryClient.d.ts.map +1 -0
- package/dist/lib/queryClient.js +42 -0
- package/dist/lib/queryClient.js.map +1 -0
- package/dist/lib/services.d.ts +164 -0
- package/dist/lib/services.d.ts.map +1 -0
- package/dist/lib/services.js +304 -0
- package/dist/lib/services.js.map +1 -0
- package/dist/lib/share.d.ts +12 -0
- package/dist/lib/share.d.ts.map +1 -0
- package/dist/lib/share.js +39 -0
- package/dist/lib/share.js.map +1 -0
- package/dist/lib/triggers.d.ts +128 -0
- package/dist/lib/triggers.d.ts.map +1 -0
- package/dist/lib/triggers.js +305 -0
- package/dist/lib/triggers.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/visual-system.d.ts +39 -0
- package/dist/lib/visual-system.d.ts.map +1 -0
- package/dist/lib/visual-system.js +129 -0
- package/dist/lib/visual-system.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +2 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,905 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backpack Component
|
|
3
|
+
*
|
|
4
|
+
* User's personal permission and account management popup.
|
|
5
|
+
* Two tabs:
|
|
6
|
+
* - Permissions: Toggle browser permissions (filesystem, camera, mic, etc.)
|
|
7
|
+
* - Connected Accounts: Connect/disconnect external accounts via Composio
|
|
8
|
+
*
|
|
9
|
+
* OAuth is handled entirely by Composio as a credential broker —
|
|
10
|
+
* the app never sees or stores user credentials. Composio manages
|
|
11
|
+
* the full OAuth handshake, token storage, and refresh lifecycle.
|
|
12
|
+
*/
|
|
13
|
+
import { useState, useCallback, useEffect, useRef, useMemo, Fragment } from "react";
|
|
14
|
+
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog";
|
|
15
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
16
|
+
import { Button } from "@/components/ui/button";
|
|
17
|
+
import { Switch } from "@/components/ui/switch";
|
|
18
|
+
import { Badge } from "@/components/ui/badge";
|
|
19
|
+
import { useToast } from "@/hooks/use-toast";
|
|
20
|
+
import { useIsMobile } from "@/hooks/use-mobile";
|
|
21
|
+
import { Backpack, FolderOpen, Camera, Mic, MapPin, Clipboard, Bell, Link2, Shield, Check, Loader2, ExternalLink, RefreshCw, Unplug, Search, X, MessageCircle, Send, QrCode, Smartphone, ArrowLeft, } from "lucide-react";
|
|
22
|
+
const API_BASE = (import.meta.env.VITE_API_URL || "https://api.compose.market").replace(/\/+$/, "");
|
|
23
|
+
const SOCKET_BASE = (import.meta.env.VITE_SOCKET_URL || "wss://services.compose.market/socket").replace(/\/+$/, "");
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Permission Definitions
|
|
26
|
+
// =============================================================================
|
|
27
|
+
const PERMISSION_TYPES = [
|
|
28
|
+
{
|
|
29
|
+
type: "filesystem",
|
|
30
|
+
label: "File System",
|
|
31
|
+
description: "Access files and folders on your device",
|
|
32
|
+
icon: <FolderOpen className="w-4 h-4"/>,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: "camera",
|
|
36
|
+
label: "Camera",
|
|
37
|
+
description: "Use your camera for photos and video",
|
|
38
|
+
icon: <Camera className="w-4 h-4"/>,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
type: "microphone",
|
|
42
|
+
label: "Microphone",
|
|
43
|
+
description: "Record audio with your microphone",
|
|
44
|
+
icon: <Mic className="w-4 h-4"/>,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: "geolocation",
|
|
48
|
+
label: "Location",
|
|
49
|
+
description: "Access your current location",
|
|
50
|
+
icon: <MapPin className="w-4 h-4"/>,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
type: "clipboard",
|
|
54
|
+
label: "Clipboard",
|
|
55
|
+
description: "Read and write to your clipboard",
|
|
56
|
+
icon: <Clipboard className="w-4 h-4"/>,
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
type: "notifications",
|
|
60
|
+
label: "Notifications",
|
|
61
|
+
description: "Send you desktop notifications",
|
|
62
|
+
icon: <Bell className="w-4 h-4"/>,
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
// =============================================================================
|
|
66
|
+
// Featured Provider Definitions (Composio toolkit slugs)
|
|
67
|
+
// =============================================================================
|
|
68
|
+
const FEATURED_PROVIDERS = [
|
|
69
|
+
{
|
|
70
|
+
slug: "gmail",
|
|
71
|
+
name: "Google (Gmail)",
|
|
72
|
+
logo: "https://logos.composio.dev/api/gmail",
|
|
73
|
+
color: "#4285F4",
|
|
74
|
+
description: "Email, Calendar, Drive access",
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
slug: "notion",
|
|
78
|
+
name: "Notion",
|
|
79
|
+
logo: "https://logos.composio.dev/api/notion",
|
|
80
|
+
color: "#000000",
|
|
81
|
+
description: "Pages, databases, content",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
slug: "twitter",
|
|
85
|
+
name: "X (Twitter)",
|
|
86
|
+
logo: "https://logos.composio.dev/api/twitter",
|
|
87
|
+
color: "#000000",
|
|
88
|
+
description: "Tweets, DMs, analytics",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
slug: "github",
|
|
92
|
+
name: "GitHub",
|
|
93
|
+
logo: "https://logos.composio.dev/api/github",
|
|
94
|
+
color: "#24292F",
|
|
95
|
+
description: "Repos, issues, pull requests",
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
slug: "discord",
|
|
99
|
+
name: "Discord",
|
|
100
|
+
logo: "https://logos.composio.dev/api/discord",
|
|
101
|
+
color: "#5865F2",
|
|
102
|
+
description: "Servers, channels, messaging",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
slug: "slack",
|
|
106
|
+
name: "Slack",
|
|
107
|
+
logo: "https://logos.composio.dev/api/slack",
|
|
108
|
+
color: "#4A154B",
|
|
109
|
+
description: "Channels, messages, files",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
slug: "linkedin",
|
|
113
|
+
name: "LinkedIn",
|
|
114
|
+
logo: "https://logos.composio.dev/api/linkedin",
|
|
115
|
+
color: "#0A66C2",
|
|
116
|
+
description: "Profile, connections, posts",
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
slug: "spotify",
|
|
120
|
+
name: "Spotify",
|
|
121
|
+
logo: "https://logos.composio.dev/api/spotify",
|
|
122
|
+
color: "#1DB954",
|
|
123
|
+
description: "Playlists, tracks, playback",
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
slug: "telegram",
|
|
127
|
+
name: "Telegram",
|
|
128
|
+
logo: "https://logos.composio.dev/api/telegram",
|
|
129
|
+
color: "#229ED9",
|
|
130
|
+
description: "Bot messaging & notifications",
|
|
131
|
+
connectionType: "channel",
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
slug: "whatsapp",
|
|
135
|
+
name: "WhatsApp",
|
|
136
|
+
logo: "https://logos.composio.dev/api/whatsapp",
|
|
137
|
+
color: "#25D366",
|
|
138
|
+
description: "Scan QR to link your account",
|
|
139
|
+
connectionType: "channel",
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
export function BackpackDialog({ userId, open, onOpenChange, showTrigger = true }) {
|
|
143
|
+
const { toast } = useToast();
|
|
144
|
+
const isMobile = useIsMobile();
|
|
145
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
146
|
+
const [activeTab, setActiveTab] = useState("permissions");
|
|
147
|
+
const [loadingPermission, setLoadingPermission] = useState(null);
|
|
148
|
+
const [loadingAccount, setLoadingAccount] = useState(null);
|
|
149
|
+
const [refreshing, setRefreshing] = useState(false);
|
|
150
|
+
// Search state
|
|
151
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
152
|
+
const [searchResults, setSearchResults] = useState([]);
|
|
153
|
+
const [searching, setSearching] = useState(false);
|
|
154
|
+
// WhatsApp connect screen state
|
|
155
|
+
const [whatsappScreen, setWhatsappScreen] = useState(null);
|
|
156
|
+
const [whatsappQr, setWhatsappQr] = useState(null);
|
|
157
|
+
const [whatsappQrLoading, setWhatsappQrLoading] = useState(false);
|
|
158
|
+
const [whatsappPairingCode, setWhatsappPairingCode] = useState(null);
|
|
159
|
+
const [whatsappPhoneInput, setWhatsappPhoneInput] = useState("");
|
|
160
|
+
const whatsappWsRef = useRef(null);
|
|
161
|
+
const searchDebounceRef = useRef(null);
|
|
162
|
+
// Permission states (from sessionStorage)
|
|
163
|
+
const [permissions, setPermissions] = useState(() => {
|
|
164
|
+
const stored = {};
|
|
165
|
+
PERMISSION_TYPES.forEach(p => {
|
|
166
|
+
stored[p.type] = sessionStorage.getItem(`consent_${p.type}`) === "granted";
|
|
167
|
+
});
|
|
168
|
+
return stored;
|
|
169
|
+
});
|
|
170
|
+
// Connection states fetched from Composio via backend
|
|
171
|
+
const [connections, setConnections] = useState({});
|
|
172
|
+
const handleOpen = open !== undefined ? open : isOpen;
|
|
173
|
+
const handleOpenChange = onOpenChange || setIsOpen;
|
|
174
|
+
// Effective userId — fallback to anonymous session id
|
|
175
|
+
const effectiveUserId = userId || sessionStorage.getItem("composio_anon_id") || (() => {
|
|
176
|
+
const id = `anon_${crypto.randomUUID()}`;
|
|
177
|
+
sessionStorage.setItem("composio_anon_id", id);
|
|
178
|
+
return id;
|
|
179
|
+
})();
|
|
180
|
+
// ==========================================================================
|
|
181
|
+
// Fetch Connection Status from Backend
|
|
182
|
+
// ==========================================================================
|
|
183
|
+
const fetchConnections = useCallback(async () => {
|
|
184
|
+
try {
|
|
185
|
+
setRefreshing(true);
|
|
186
|
+
const res = await fetch(`${API_BASE}/api/backpack/connections?userId=${encodeURIComponent(effectiveUserId)}`);
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
console.warn("[Backpack] Failed to fetch connections:", res.status);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const data = await res.json();
|
|
192
|
+
const connMap = {};
|
|
193
|
+
// Map Composio connections to our featured providers
|
|
194
|
+
if (data.connections) {
|
|
195
|
+
for (const conn of data.connections) {
|
|
196
|
+
connMap[conn.slug] = conn;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
setConnections(connMap);
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
console.warn("[Backpack] Could not fetch connections:", err);
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
setRefreshing(false);
|
|
206
|
+
}
|
|
207
|
+
}, [effectiveUserId]);
|
|
208
|
+
// Fetch connections when the accounts tab is opened
|
|
209
|
+
useEffect(() => {
|
|
210
|
+
if (handleOpen && activeTab === "accounts") {
|
|
211
|
+
fetchConnections();
|
|
212
|
+
}
|
|
213
|
+
}, [handleOpen, activeTab, fetchConnections]);
|
|
214
|
+
// ==========================================================================
|
|
215
|
+
// Toolkit Search
|
|
216
|
+
// ==========================================================================
|
|
217
|
+
const searchToolkits = useCallback(async (query) => {
|
|
218
|
+
if (!query.trim()) {
|
|
219
|
+
setSearchResults([]);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
setSearching(true);
|
|
223
|
+
try {
|
|
224
|
+
const res = await fetch(`${API_BASE}/api/backpack/toolkits?search=${encodeURIComponent(query)}&limit=15`);
|
|
225
|
+
if (res.ok) {
|
|
226
|
+
const data = await res.json();
|
|
227
|
+
setSearchResults(data.toolkits || []);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
console.warn("[Backpack] Search error:", err);
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
setSearching(false);
|
|
235
|
+
}
|
|
236
|
+
}, []);
|
|
237
|
+
// Debounced search
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
if (searchDebounceRef.current) {
|
|
240
|
+
clearTimeout(searchDebounceRef.current);
|
|
241
|
+
}
|
|
242
|
+
if (!searchQuery.trim()) {
|
|
243
|
+
setSearchResults([]);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
searchDebounceRef.current = setTimeout(() => {
|
|
247
|
+
searchToolkits(searchQuery);
|
|
248
|
+
}, 300);
|
|
249
|
+
return () => {
|
|
250
|
+
if (searchDebounceRef.current)
|
|
251
|
+
clearTimeout(searchDebounceRef.current);
|
|
252
|
+
};
|
|
253
|
+
}, [searchQuery, searchToolkits]);
|
|
254
|
+
// Convert a search result to a ProviderDisplay for the connect flow
|
|
255
|
+
const toolkitToProvider = useCallback((tk) => ({
|
|
256
|
+
slug: tk.slug,
|
|
257
|
+
name: tk.name,
|
|
258
|
+
logo: tk.logo,
|
|
259
|
+
color: "#6366f1",
|
|
260
|
+
description: tk.description?.substring(0, 60) || tk.categories.join(", ") || "Connect account",
|
|
261
|
+
}), []);
|
|
262
|
+
// ==========================================================================
|
|
263
|
+
// Permission Handlers
|
|
264
|
+
// ==========================================================================
|
|
265
|
+
const requestPermission = useCallback(async (type) => {
|
|
266
|
+
setLoadingPermission(type);
|
|
267
|
+
try {
|
|
268
|
+
let granted = false;
|
|
269
|
+
switch (type) {
|
|
270
|
+
case "filesystem":
|
|
271
|
+
if ("showDirectoryPicker" in window) {
|
|
272
|
+
await window.showDirectoryPicker();
|
|
273
|
+
granted = true;
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
throw new Error("File System Access API not supported");
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
case "camera":
|
|
280
|
+
await navigator.mediaDevices.getUserMedia({ video: true });
|
|
281
|
+
granted = true;
|
|
282
|
+
break;
|
|
283
|
+
case "microphone":
|
|
284
|
+
await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
285
|
+
granted = true;
|
|
286
|
+
break;
|
|
287
|
+
case "geolocation":
|
|
288
|
+
await new Promise((resolve, reject) => {
|
|
289
|
+
navigator.geolocation.getCurrentPosition(() => resolve(), reject);
|
|
290
|
+
});
|
|
291
|
+
granted = true;
|
|
292
|
+
break;
|
|
293
|
+
case "clipboard":
|
|
294
|
+
await navigator.clipboard.readText();
|
|
295
|
+
granted = true;
|
|
296
|
+
break;
|
|
297
|
+
case "notifications":
|
|
298
|
+
const result = await Notification.requestPermission();
|
|
299
|
+
granted = result === "granted";
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
if (granted) {
|
|
303
|
+
sessionStorage.setItem(`consent_${type}`, "granted");
|
|
304
|
+
setPermissions(prev => ({ ...prev, [type]: true }));
|
|
305
|
+
toast({ title: "Permission Granted", description: `${type} access enabled.` });
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
toast({
|
|
310
|
+
title: "Permission Denied",
|
|
311
|
+
description: `Could not get ${type} access.`,
|
|
312
|
+
variant: "destructive"
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
finally {
|
|
316
|
+
setLoadingPermission(null);
|
|
317
|
+
}
|
|
318
|
+
}, [toast]);
|
|
319
|
+
const revokePermission = useCallback((type) => {
|
|
320
|
+
sessionStorage.removeItem(`consent_${type}`);
|
|
321
|
+
setPermissions(prev => ({ ...prev, [type]: false }));
|
|
322
|
+
toast({ title: "Permission Revoked", description: `${type} access disabled.` });
|
|
323
|
+
}, [toast]);
|
|
324
|
+
// ==========================================================================
|
|
325
|
+
// OAuth Handlers — Composio Credential Broker
|
|
326
|
+
// ==========================================================================
|
|
327
|
+
const connectAccount = useCallback(async (provider) => {
|
|
328
|
+
setLoadingAccount(provider.slug);
|
|
329
|
+
try {
|
|
330
|
+
// Step 1: Call backend to get OAuth redirect URL from Composio
|
|
331
|
+
const res = await fetch(`${API_BASE}/api/backpack/connect`, {
|
|
332
|
+
method: "POST",
|
|
333
|
+
headers: { "Content-Type": "application/json" },
|
|
334
|
+
body: JSON.stringify({
|
|
335
|
+
userId: effectiveUserId,
|
|
336
|
+
toolkit: provider.slug,
|
|
337
|
+
}),
|
|
338
|
+
});
|
|
339
|
+
if (!res.ok) {
|
|
340
|
+
const err = await res.json().catch(() => ({}));
|
|
341
|
+
throw new Error(err.error || `Failed to initiate connection (${res.status})`);
|
|
342
|
+
}
|
|
343
|
+
const { redirectUrl } = await res.json();
|
|
344
|
+
if (!redirectUrl) {
|
|
345
|
+
throw new Error("No redirect URL returned from server");
|
|
346
|
+
}
|
|
347
|
+
// Step 2: Open Composio's hosted auth page in a popup
|
|
348
|
+
window.open(redirectUrl, `Connect ${provider.name}`, "width=600,height=700,scrollbars=yes");
|
|
349
|
+
// Step 3: Poll the BACKEND for connection status instead of
|
|
350
|
+
// checking popup.closed (which triggers COOP errors on cross-origin popups)
|
|
351
|
+
toast({
|
|
352
|
+
title: "Authentication Started",
|
|
353
|
+
description: `Complete authentication in the popup, then click Refresh.`,
|
|
354
|
+
});
|
|
355
|
+
// Auto-poll status every 3 seconds for up to 2 minutes
|
|
356
|
+
let attempts = 0;
|
|
357
|
+
const maxAttempts = 40; // 40 × 3s = 2min
|
|
358
|
+
const pollInterval = setInterval(async () => {
|
|
359
|
+
attempts++;
|
|
360
|
+
try {
|
|
361
|
+
const statusRes = await fetch(`${API_BASE}/api/backpack/status/${encodeURIComponent(provider.slug)}?userId=${encodeURIComponent(effectiveUserId)}`);
|
|
362
|
+
if (statusRes.ok) {
|
|
363
|
+
const statusData = await statusRes.json();
|
|
364
|
+
if (statusData.connected) {
|
|
365
|
+
clearInterval(pollInterval);
|
|
366
|
+
setConnections(prev => ({
|
|
367
|
+
...prev,
|
|
368
|
+
[provider.slug]: {
|
|
369
|
+
slug: provider.slug,
|
|
370
|
+
name: provider.name,
|
|
371
|
+
connected: true,
|
|
372
|
+
accountId: statusData.accountId,
|
|
373
|
+
},
|
|
374
|
+
}));
|
|
375
|
+
toast({
|
|
376
|
+
title: "Connected!",
|
|
377
|
+
description: `${provider.name} account connected successfully.`,
|
|
378
|
+
});
|
|
379
|
+
setLoadingAccount(null);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
// Ignore poll errors
|
|
385
|
+
}
|
|
386
|
+
if (attempts >= maxAttempts) {
|
|
387
|
+
clearInterval(pollInterval);
|
|
388
|
+
setLoadingAccount(null);
|
|
389
|
+
}
|
|
390
|
+
}, 3000);
|
|
391
|
+
}
|
|
392
|
+
catch (err) {
|
|
393
|
+
console.error("[Backpack] Connection error:", err);
|
|
394
|
+
toast({
|
|
395
|
+
title: "Connection Failed",
|
|
396
|
+
description: err instanceof Error ? err.message : "Could not connect account.",
|
|
397
|
+
variant: "destructive"
|
|
398
|
+
});
|
|
399
|
+
setLoadingAccount(null);
|
|
400
|
+
}
|
|
401
|
+
}, [effectiveUserId, toast]);
|
|
402
|
+
// ==========================================================================
|
|
403
|
+
// Channel-Based Connection (Telegram)
|
|
404
|
+
// ==========================================================================
|
|
405
|
+
const connectTelegram = useCallback(async () => {
|
|
406
|
+
setLoadingAccount("telegram");
|
|
407
|
+
try {
|
|
408
|
+
// Generate a deep link
|
|
409
|
+
const res = await fetch(`${API_BASE}/api/backpack/telegram/link`, {
|
|
410
|
+
method: "POST",
|
|
411
|
+
headers: { "Content-Type": "application/json" },
|
|
412
|
+
body: JSON.stringify({ userId: effectiveUserId }),
|
|
413
|
+
});
|
|
414
|
+
if (!res.ok) {
|
|
415
|
+
const err = await res.json().catch(() => ({}));
|
|
416
|
+
throw new Error(err.error || `Failed to generate link (${res.status})`);
|
|
417
|
+
}
|
|
418
|
+
const { deepLinkUrl } = await res.json();
|
|
419
|
+
// Open Telegram deep link
|
|
420
|
+
window.open(deepLinkUrl, "_blank");
|
|
421
|
+
toast({
|
|
422
|
+
title: "Open Telegram",
|
|
423
|
+
description: 'Tap "Start" in Telegram to connect your account.',
|
|
424
|
+
});
|
|
425
|
+
// Poll for binding confirmation
|
|
426
|
+
let attempts = 0;
|
|
427
|
+
const maxAttempts = 40; // 40 × 3s = 2min
|
|
428
|
+
const pollInterval = setInterval(async () => {
|
|
429
|
+
attempts++;
|
|
430
|
+
try {
|
|
431
|
+
const statusRes = await fetch(`${API_BASE}/api/backpack/telegram/status?userId=${encodeURIComponent(effectiveUserId)}`);
|
|
432
|
+
if (statusRes.ok) {
|
|
433
|
+
const statusData = await statusRes.json();
|
|
434
|
+
if (statusData.bound) {
|
|
435
|
+
clearInterval(pollInterval);
|
|
436
|
+
setConnections(prev => ({
|
|
437
|
+
...prev,
|
|
438
|
+
telegram: {
|
|
439
|
+
slug: "telegram",
|
|
440
|
+
name: "Telegram",
|
|
441
|
+
connected: true,
|
|
442
|
+
},
|
|
443
|
+
}));
|
|
444
|
+
toast({
|
|
445
|
+
title: "Connected!",
|
|
446
|
+
description: "Telegram bot connected successfully.",
|
|
447
|
+
});
|
|
448
|
+
setLoadingAccount(null);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
catch {
|
|
453
|
+
// Ignore poll errors
|
|
454
|
+
}
|
|
455
|
+
if (attempts >= maxAttempts) {
|
|
456
|
+
clearInterval(pollInterval);
|
|
457
|
+
setLoadingAccount(null);
|
|
458
|
+
}
|
|
459
|
+
}, 3000);
|
|
460
|
+
}
|
|
461
|
+
catch (err) {
|
|
462
|
+
console.error("[Backpack] Telegram connection error:", err);
|
|
463
|
+
toast({
|
|
464
|
+
title: "Connection Failed",
|
|
465
|
+
description: err instanceof Error ? err.message : "Could not connect Telegram.",
|
|
466
|
+
variant: "destructive",
|
|
467
|
+
});
|
|
468
|
+
setLoadingAccount(null);
|
|
469
|
+
}
|
|
470
|
+
}, [effectiveUserId, toast]);
|
|
471
|
+
// ==========================================================================
|
|
472
|
+
// Channel-Based Connection (WhatsApp via Baileys WebSocket)
|
|
473
|
+
// ==========================================================================
|
|
474
|
+
const connectWhatsApp = useCallback(() => {
|
|
475
|
+
// Close any existing WS connection
|
|
476
|
+
if (whatsappWsRef.current) {
|
|
477
|
+
whatsappWsRef.current.close();
|
|
478
|
+
whatsappWsRef.current = null;
|
|
479
|
+
}
|
|
480
|
+
setWhatsappScreen("qr");
|
|
481
|
+
setWhatsappQr(null);
|
|
482
|
+
setWhatsappQrLoading(true);
|
|
483
|
+
setLoadingAccount("whatsapp");
|
|
484
|
+
const wsUrl = `${SOCKET_BASE}/whatsapp?userId=${encodeURIComponent(effectiveUserId)}`;
|
|
485
|
+
console.log(`[Backpack] Connecting WhatsApp WebSocket: ${wsUrl}`);
|
|
486
|
+
const ws = new WebSocket(wsUrl);
|
|
487
|
+
whatsappWsRef.current = ws;
|
|
488
|
+
ws.onmessage = (event) => {
|
|
489
|
+
try {
|
|
490
|
+
const msg = JSON.parse(event.data);
|
|
491
|
+
console.log(`[Backpack] WhatsApp WS message:`, msg.type);
|
|
492
|
+
switch (msg.type) {
|
|
493
|
+
case "qr":
|
|
494
|
+
setWhatsappQr(msg.qr);
|
|
495
|
+
setWhatsappQrLoading(false);
|
|
496
|
+
break;
|
|
497
|
+
case "connected":
|
|
498
|
+
setWhatsappScreen(null);
|
|
499
|
+
setWhatsappQr(null);
|
|
500
|
+
setConnections(prev => ({
|
|
501
|
+
...prev,
|
|
502
|
+
whatsapp: {
|
|
503
|
+
slug: "whatsapp",
|
|
504
|
+
name: "WhatsApp",
|
|
505
|
+
connected: true,
|
|
506
|
+
},
|
|
507
|
+
}));
|
|
508
|
+
toast({
|
|
509
|
+
title: "Connected!",
|
|
510
|
+
description: `WhatsApp linked successfully${msg.phoneNumber ? ` (${msg.phoneNumber})` : ""}.`,
|
|
511
|
+
});
|
|
512
|
+
setLoadingAccount(null);
|
|
513
|
+
break;
|
|
514
|
+
case "already_connected":
|
|
515
|
+
setWhatsappScreen(null);
|
|
516
|
+
setConnections(prev => ({
|
|
517
|
+
...prev,
|
|
518
|
+
whatsapp: {
|
|
519
|
+
slug: "whatsapp",
|
|
520
|
+
name: "WhatsApp",
|
|
521
|
+
connected: true,
|
|
522
|
+
},
|
|
523
|
+
}));
|
|
524
|
+
toast({
|
|
525
|
+
title: "Already Connected",
|
|
526
|
+
description: "WhatsApp is already linked.",
|
|
527
|
+
});
|
|
528
|
+
setLoadingAccount(null);
|
|
529
|
+
break;
|
|
530
|
+
case "error":
|
|
531
|
+
console.error(`[Backpack] WhatsApp error:`, msg.message);
|
|
532
|
+
toast({
|
|
533
|
+
title: "Connection Failed",
|
|
534
|
+
description: msg.message || "Could not connect WhatsApp.",
|
|
535
|
+
variant: "destructive",
|
|
536
|
+
});
|
|
537
|
+
setWhatsappScreen(null);
|
|
538
|
+
setWhatsappQrLoading(false);
|
|
539
|
+
setLoadingAccount(null);
|
|
540
|
+
break;
|
|
541
|
+
case "disconnected":
|
|
542
|
+
setWhatsappScreen(null);
|
|
543
|
+
setWhatsappQr(null);
|
|
544
|
+
setLoadingAccount(null);
|
|
545
|
+
break;
|
|
546
|
+
case "reconnecting":
|
|
547
|
+
setWhatsappQrLoading(true);
|
|
548
|
+
setWhatsappQr(null);
|
|
549
|
+
break;
|
|
550
|
+
case "pairing_code_pending":
|
|
551
|
+
setWhatsappPairingCode(null);
|
|
552
|
+
setWhatsappQr(null);
|
|
553
|
+
setWhatsappQrLoading(true);
|
|
554
|
+
break;
|
|
555
|
+
case "pairing_code":
|
|
556
|
+
setWhatsappPairingCode(msg.code);
|
|
557
|
+
setWhatsappQrLoading(false);
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
catch {
|
|
562
|
+
// Ignore malformed messages
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
ws.onerror = () => {
|
|
566
|
+
console.error("[Backpack] WhatsApp WebSocket error");
|
|
567
|
+
toast({
|
|
568
|
+
title: "Connection Error",
|
|
569
|
+
description: "Could not reach WhatsApp service. Try again.",
|
|
570
|
+
variant: "destructive",
|
|
571
|
+
});
|
|
572
|
+
setWhatsappScreen(null);
|
|
573
|
+
setWhatsappQrLoading(false);
|
|
574
|
+
setLoadingAccount(null);
|
|
575
|
+
};
|
|
576
|
+
ws.onclose = () => {
|
|
577
|
+
console.log("[Backpack] WhatsApp WebSocket closed");
|
|
578
|
+
whatsappWsRef.current = null;
|
|
579
|
+
};
|
|
580
|
+
}, [effectiveUserId, toast]);
|
|
581
|
+
const cancelWhatsApp = useCallback(() => {
|
|
582
|
+
if (whatsappWsRef.current) {
|
|
583
|
+
whatsappWsRef.current.close();
|
|
584
|
+
whatsappWsRef.current = null;
|
|
585
|
+
}
|
|
586
|
+
setWhatsappScreen(null);
|
|
587
|
+
setWhatsappQr(null);
|
|
588
|
+
setWhatsappQrLoading(false);
|
|
589
|
+
setWhatsappPairingCode(null);
|
|
590
|
+
setWhatsappPhoneInput("");
|
|
591
|
+
setLoadingAccount(null);
|
|
592
|
+
}, []);
|
|
593
|
+
const disconnectAccount = useCallback(async (provider) => {
|
|
594
|
+
setLoadingAccount(provider.slug);
|
|
595
|
+
try {
|
|
596
|
+
const res = await fetch(`${API_BASE}/api/backpack/disconnect`, {
|
|
597
|
+
method: "POST",
|
|
598
|
+
headers: { "Content-Type": "application/json" },
|
|
599
|
+
body: JSON.stringify({
|
|
600
|
+
userId: effectiveUserId,
|
|
601
|
+
toolkit: provider.slug,
|
|
602
|
+
}),
|
|
603
|
+
});
|
|
604
|
+
if (!res.ok) {
|
|
605
|
+
const err = await res.json().catch(() => ({}));
|
|
606
|
+
throw new Error(err.error || `Failed to disconnect (${res.status})`);
|
|
607
|
+
}
|
|
608
|
+
// Update local state
|
|
609
|
+
setConnections(prev => ({
|
|
610
|
+
...prev,
|
|
611
|
+
[provider.slug]: { ...prev[provider.slug], connected: false, accountId: undefined },
|
|
612
|
+
}));
|
|
613
|
+
toast({
|
|
614
|
+
title: "Disconnected",
|
|
615
|
+
description: `${provider.name} account disconnected.`,
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
catch (err) {
|
|
619
|
+
console.error("[Backpack] Disconnect error:", err);
|
|
620
|
+
toast({
|
|
621
|
+
title: "Disconnect Failed",
|
|
622
|
+
description: err instanceof Error ? err.message : "Could not disconnect account.",
|
|
623
|
+
variant: "destructive"
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
finally {
|
|
627
|
+
setLoadingAccount(null);
|
|
628
|
+
}
|
|
629
|
+
}, [effectiveUserId, toast]);
|
|
630
|
+
// ==========================================================================
|
|
631
|
+
// Filtered search results (exclude featured providers from search)
|
|
632
|
+
// ==========================================================================
|
|
633
|
+
const featuredSlugs = useMemo(() => new Set(FEATURED_PROVIDERS.map(p => p.slug)), []);
|
|
634
|
+
const filteredSearchResults = useMemo(() => searchResults.filter(tk => !featuredSlugs.has(tk.slug)), [searchResults, featuredSlugs]);
|
|
635
|
+
// ==========================================================================
|
|
636
|
+
// Render
|
|
637
|
+
// ==========================================================================
|
|
638
|
+
const grantedPermissionsCount = Object.values(permissions).filter(Boolean).length;
|
|
639
|
+
const connectedAccountsCount = Object.values(connections).filter(c => c.connected).length;
|
|
640
|
+
// Provider card renderer — shared between featured and search results
|
|
641
|
+
const renderProviderCard = (provider) => {
|
|
642
|
+
const connection = connections[provider.slug];
|
|
643
|
+
const isConnected = connection?.connected ?? false;
|
|
644
|
+
const isLoading = loadingAccount === provider.slug;
|
|
645
|
+
const isDisabled = provider.connectionType === "disabled";
|
|
646
|
+
const isChannel = provider.connectionType === "channel";
|
|
647
|
+
return (<Fragment key={provider.slug}>
|
|
648
|
+
<div className={`flex items-center justify-between p-3 rounded-lg bg-zinc-900/50 border border-zinc-800 ${isDisabled ? "opacity-60" : ""}`}>
|
|
649
|
+
<div className="flex items-center gap-3">
|
|
650
|
+
<div className="w-10 h-10 rounded-lg flex items-center justify-center overflow-hidden" style={{ backgroundColor: `${provider.color}15` }}>
|
|
651
|
+
<img src={provider.logo} alt={provider.name} className="w-6 h-6 object-contain" onError={(e) => {
|
|
652
|
+
e.target.style.display = 'none';
|
|
653
|
+
}}/>
|
|
654
|
+
</div>
|
|
655
|
+
<div className="min-w-0 flex-1">
|
|
656
|
+
<div className="text-sm font-medium text-zinc-200 truncate flex items-center gap-1.5">
|
|
657
|
+
{provider.name}
|
|
658
|
+
{provider.badge && (<Badge variant="outline" className="text-[10px] px-1 py-0 border-zinc-600 text-zinc-400 font-normal">
|
|
659
|
+
{provider.badge}
|
|
660
|
+
</Badge>)}
|
|
661
|
+
</div>
|
|
662
|
+
<div className="text-xs text-zinc-500 truncate">
|
|
663
|
+
{isConnected ? (<span className="flex items-center gap-1 text-green-400">
|
|
664
|
+
<Check className="w-3 h-3"/> Connected
|
|
665
|
+
</span>) : (provider.description)}
|
|
666
|
+
</div>
|
|
667
|
+
</div>
|
|
668
|
+
</div>
|
|
669
|
+
|
|
670
|
+
{isDisabled ? (<Button variant="outline" size="sm" disabled className="shrink-0 ml-2 opacity-50">
|
|
671
|
+
<MessageCircle className="w-3 h-3 mr-1"/>
|
|
672
|
+
Soon
|
|
673
|
+
</Button>) : (<Button variant={isConnected ? "destructive" : "outline"} size="sm" disabled={isLoading} className="shrink-0 ml-2" onClick={() => {
|
|
674
|
+
if (isConnected) {
|
|
675
|
+
disconnectAccount(provider);
|
|
676
|
+
}
|
|
677
|
+
else if (isChannel && provider.slug === "telegram") {
|
|
678
|
+
connectTelegram();
|
|
679
|
+
}
|
|
680
|
+
else if (isChannel && provider.slug === "whatsapp") {
|
|
681
|
+
connectWhatsApp();
|
|
682
|
+
}
|
|
683
|
+
else {
|
|
684
|
+
connectAccount(provider);
|
|
685
|
+
}
|
|
686
|
+
}}>
|
|
687
|
+
{isLoading ? (<Loader2 className="w-4 h-4 animate-spin"/>) : isConnected ? (<>
|
|
688
|
+
<Unplug className="w-3 h-3 mr-1"/>
|
|
689
|
+
Disconnect
|
|
690
|
+
</>) : isChannel && provider.slug === "whatsapp" ? (<>
|
|
691
|
+
<QrCode className="w-3 h-3 mr-1"/>
|
|
692
|
+
Scan QR
|
|
693
|
+
</>) : isChannel ? (<>
|
|
694
|
+
<Send className="w-3 h-3 mr-1"/>
|
|
695
|
+
Link Bot
|
|
696
|
+
</>) : (<>
|
|
697
|
+
<ExternalLink className="w-3 h-3 mr-1"/>
|
|
698
|
+
Connect
|
|
699
|
+
</>)}
|
|
700
|
+
</Button>)}
|
|
701
|
+
</div>
|
|
702
|
+
|
|
703
|
+
{/* WhatsApp QR Code inline display */}
|
|
704
|
+
{/* Removed inline QR display */}
|
|
705
|
+
</Fragment>);
|
|
706
|
+
};
|
|
707
|
+
return (<Dialog open={handleOpen} onOpenChange={handleOpenChange}>
|
|
708
|
+
{showTrigger && (<DialogTrigger asChild>
|
|
709
|
+
<Button variant="outline" size="sm" className="gap-2">
|
|
710
|
+
<Backpack className="w-4 h-4"/>
|
|
711
|
+
Backpack
|
|
712
|
+
</Button>
|
|
713
|
+
</DialogTrigger>)}
|
|
714
|
+
|
|
715
|
+
<DialogContent className="sm:max-w-lg max-h-[85vh] overflow-hidden flex flex-col">
|
|
716
|
+
<DialogHeader>
|
|
717
|
+
<DialogTitle className="flex items-center gap-2">
|
|
718
|
+
<Backpack className="w-5 h-5 text-fuchsia-400"/>
|
|
719
|
+
Your Backpack
|
|
720
|
+
</DialogTitle>
|
|
721
|
+
<DialogDescription>
|
|
722
|
+
Manage permissions and connected accounts for AI agents.
|
|
723
|
+
</DialogDescription>
|
|
724
|
+
</DialogHeader>
|
|
725
|
+
|
|
726
|
+
{/* ========== WhatsApp Dedicated Connection Screen ========== */}
|
|
727
|
+
{whatsappScreen ? (<div className="flex-1 flex flex-col gap-4 py-2">
|
|
728
|
+
<Button variant="ghost" size="sm" className="self-start gap-1.5 text-zinc-400 hover:text-zinc-200 -ml-2" onClick={cancelWhatsApp}>
|
|
729
|
+
<ArrowLeft className="w-4 h-4"/>
|
|
730
|
+
Back
|
|
731
|
+
</Button>
|
|
732
|
+
|
|
733
|
+
<div className="flex items-center gap-3 mb-2">
|
|
734
|
+
<div className="w-12 h-12 rounded-xl flex items-center justify-center" style={{ backgroundColor: "#25D36615" }}>
|
|
735
|
+
<img src="https://logos.composio.dev/api/whatsapp" alt="WhatsApp" className="w-7 h-7 object-contain"/>
|
|
736
|
+
</div>
|
|
737
|
+
<div>
|
|
738
|
+
<h3 className="text-base font-semibold text-zinc-100">Connect WhatsApp</h3>
|
|
739
|
+
<p className="text-xs text-zinc-400">
|
|
740
|
+
{isMobile
|
|
741
|
+
? "Link your WhatsApp account"
|
|
742
|
+
: "Scan with your phone to link"}
|
|
743
|
+
</p>
|
|
744
|
+
</div>
|
|
745
|
+
</div>
|
|
746
|
+
|
|
747
|
+
<div className="flex flex-col items-center gap-4 py-2">
|
|
748
|
+
{isMobile ? (
|
|
749
|
+
/* ===== Mobile: Phone pairing code ===== */
|
|
750
|
+
whatsappPairingCode ? (<div className="flex flex-col items-center gap-4 py-4">
|
|
751
|
+
<div className="text-sm text-zinc-300 text-center">
|
|
752
|
+
Enter this code in WhatsApp to link:
|
|
753
|
+
</div>
|
|
754
|
+
<div className="font-mono text-3xl font-bold tracking-[0.3em] text-green-400 bg-zinc-900 px-6 py-4 rounded-xl border border-zinc-700">
|
|
755
|
+
{whatsappPairingCode}
|
|
756
|
+
</div>
|
|
757
|
+
<p className="text-xs text-zinc-500 text-center">
|
|
758
|
+
WhatsApp → Linked Devices → Link a Device
|
|
759
|
+
</p>
|
|
760
|
+
<div className="flex items-center gap-2 text-xs text-zinc-600">
|
|
761
|
+
<Loader2 className="w-3 h-3 animate-spin"/>
|
|
762
|
+
Waiting for pairing...
|
|
763
|
+
</div>
|
|
764
|
+
</div>) : whatsappQrLoading ? (<div className="flex flex-col items-center gap-3 py-8">
|
|
765
|
+
<Loader2 className="w-10 h-10 animate-spin text-green-500"/>
|
|
766
|
+
<span className="text-sm text-zinc-400">Generating pairing code...</span>
|
|
767
|
+
</div>) : (<form className="flex flex-col items-center gap-4 py-2 w-full max-w-xs" onSubmit={(e) => {
|
|
768
|
+
e.preventDefault();
|
|
769
|
+
const phone = whatsappPhoneInput.replace(/[^0-9]/g, "");
|
|
770
|
+
if (phone.length < 10)
|
|
771
|
+
return;
|
|
772
|
+
if (whatsappWsRef.current?.readyState === WebSocket.OPEN) {
|
|
773
|
+
whatsappWsRef.current.send(JSON.stringify({ type: "pair_phone", phone }));
|
|
774
|
+
}
|
|
775
|
+
}}>
|
|
776
|
+
<p className="text-xs text-zinc-500 text-center leading-relaxed">
|
|
777
|
+
Enter your full number with country code (no + or spaces).
|
|
778
|
+
It's only used to generate a one-time linking code.
|
|
779
|
+
Compose never stores or shares your data.
|
|
780
|
+
</p>
|
|
781
|
+
<input type="tel" placeholder="e.g. 14155551234" value={whatsappPhoneInput} onChange={(e) => setWhatsappPhoneInput(e.target.value)} className="w-full px-4 py-2.5 rounded-lg bg-zinc-900 border border-zinc-700 text-zinc-100 text-center font-mono text-lg placeholder:text-zinc-600 focus:outline-none focus:border-green-500 transition-colors" autoFocus/>
|
|
782
|
+
<Button type="submit" disabled={whatsappPhoneInput.replace(/[^0-9]/g, "").length < 10} className="w-full bg-green-600 hover:bg-green-700 text-white">
|
|
783
|
+
Get Linking Code
|
|
784
|
+
</Button>
|
|
785
|
+
</form>)) : (
|
|
786
|
+
/* ===== Desktop: QR code scanning ===== */
|
|
787
|
+
<>
|
|
788
|
+
{whatsappQrLoading ? (<div className="flex flex-col items-center gap-3 py-8">
|
|
789
|
+
<Loader2 className="w-10 h-10 animate-spin text-green-500"/>
|
|
790
|
+
<span className="text-sm text-zinc-400">Generating QR code...</span>
|
|
791
|
+
</div>) : whatsappQr ? (<>
|
|
792
|
+
<div className="p-4 rounded-xl bg-white">
|
|
793
|
+
<img src={whatsappQr.startsWith("data:") ? whatsappQr : `data:image/png;base64,${whatsappQr}`} alt="Scan with WhatsApp" className="w-52 h-52 object-contain"/>
|
|
794
|
+
</div>
|
|
795
|
+
<div className="flex flex-col items-center gap-1.5">
|
|
796
|
+
<div className="flex items-center gap-2 text-sm text-zinc-300">
|
|
797
|
+
<Smartphone className="w-4 h-4 text-green-400"/>
|
|
798
|
+
Scan with WhatsApp
|
|
799
|
+
</div>
|
|
800
|
+
<p className="text-xs text-zinc-500 text-center">
|
|
801
|
+
Open WhatsApp → Settings → Linked Devices → Link a Device
|
|
802
|
+
</p>
|
|
803
|
+
</div>
|
|
804
|
+
<div className="flex items-center gap-2 text-xs text-zinc-600 mt-2">
|
|
805
|
+
<Loader2 className="w-3 h-3 animate-spin"/>
|
|
806
|
+
Waiting for scan...
|
|
807
|
+
</div>
|
|
808
|
+
</>) : (<div className="text-sm text-zinc-400 py-4">
|
|
809
|
+
QR code not available. Please try again.
|
|
810
|
+
</div>)}
|
|
811
|
+
</>)}
|
|
812
|
+
</div>
|
|
813
|
+
</div>) : (<>
|
|
814
|
+
|
|
815
|
+
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col overflow-hidden">
|
|
816
|
+
<TabsList className="grid w-full grid-cols-2">
|
|
817
|
+
<TabsTrigger value="permissions" className="gap-2">
|
|
818
|
+
<Shield className="w-4 h-4"/>
|
|
819
|
+
Permissions
|
|
820
|
+
{grantedPermissionsCount > 0 && (<Badge variant="secondary" className="ml-1 text-xs px-1.5">
|
|
821
|
+
{grantedPermissionsCount}
|
|
822
|
+
</Badge>)}
|
|
823
|
+
</TabsTrigger>
|
|
824
|
+
<TabsTrigger value="accounts" className="gap-2">
|
|
825
|
+
<Link2 className="w-4 h-4"/>
|
|
826
|
+
Accounts
|
|
827
|
+
{connectedAccountsCount > 0 && (<Badge variant="secondary" className="ml-1 text-xs px-1.5">
|
|
828
|
+
{connectedAccountsCount}
|
|
829
|
+
</Badge>)}
|
|
830
|
+
</TabsTrigger>
|
|
831
|
+
</TabsList>
|
|
832
|
+
|
|
833
|
+
{/* Permissions Tab */}
|
|
834
|
+
<TabsContent value="permissions" className="flex-1 overflow-y-auto mt-4 space-y-3">
|
|
835
|
+
{PERMISSION_TYPES.map(perm => (<div key={perm.type} className="flex items-center justify-between p-3 rounded-lg bg-zinc-900/50 border border-zinc-800">
|
|
836
|
+
<div className="flex items-center gap-3">
|
|
837
|
+
<div className="p-2 rounded-md bg-zinc-800 text-zinc-400">
|
|
838
|
+
{perm.icon}
|
|
839
|
+
</div>
|
|
840
|
+
<div>
|
|
841
|
+
<div className="text-sm font-medium text-zinc-200">{perm.label}</div>
|
|
842
|
+
<div className="text-xs text-zinc-500">{perm.description}</div>
|
|
843
|
+
</div>
|
|
844
|
+
</div>
|
|
845
|
+
|
|
846
|
+
{loadingPermission === perm.type ? (<Loader2 className="w-4 h-4 animate-spin text-fuchsia-400"/>) : (<Switch checked={permissions[perm.type]} onCheckedChange={(checked) => {
|
|
847
|
+
if (checked) {
|
|
848
|
+
requestPermission(perm.type);
|
|
849
|
+
}
|
|
850
|
+
else {
|
|
851
|
+
revokePermission(perm.type);
|
|
852
|
+
}
|
|
853
|
+
}}/>)}
|
|
854
|
+
</div>))}
|
|
855
|
+
</TabsContent>
|
|
856
|
+
|
|
857
|
+
{/* Connected Accounts Tab */}
|
|
858
|
+
<TabsContent value="accounts" className="flex-1 overflow-y-auto mt-4 space-y-3">
|
|
859
|
+
{/* Search + Refresh row */}
|
|
860
|
+
<div className="flex items-center gap-2 mb-2">
|
|
861
|
+
<div className="relative flex-1">
|
|
862
|
+
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-zinc-500"/>
|
|
863
|
+
<input type="text" placeholder="Search 870+ integrations..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} className="w-full h-8 pl-8 pr-8 text-sm bg-zinc-900/80 border border-zinc-700 rounded-md text-zinc-200 placeholder:text-zinc-500 focus:outline-none focus:border-fuchsia-500/50 focus:ring-1 focus:ring-fuchsia-500/20 transition-colors"/>
|
|
864
|
+
{searchQuery && (<button onClick={() => setSearchQuery("")} className="absolute right-2 top-1/2 -translate-y-1/2 text-zinc-500 hover:text-zinc-300">
|
|
865
|
+
<X className="w-3.5 h-3.5"/>
|
|
866
|
+
</button>)}
|
|
867
|
+
</div>
|
|
868
|
+
<Button variant="ghost" size="sm" className="h-8 px-2 text-xs text-zinc-400 hover:text-zinc-200 shrink-0" onClick={fetchConnections} disabled={refreshing}>
|
|
869
|
+
<RefreshCw className={`w-3 h-3 mr-1 ${refreshing ? "animate-spin" : ""}`}/>
|
|
870
|
+
Refresh
|
|
871
|
+
</Button>
|
|
872
|
+
</div>
|
|
873
|
+
|
|
874
|
+
{/* Search results */}
|
|
875
|
+
{searchQuery.trim() && (<div className="space-y-2">
|
|
876
|
+
{searching && (<div className="flex items-center justify-center py-4 text-zinc-500 text-sm">
|
|
877
|
+
<Loader2 className="w-4 h-4 animate-spin mr-2"/>
|
|
878
|
+
Searching...
|
|
879
|
+
</div>)}
|
|
880
|
+
{!searching && filteredSearchResults.length === 0 && searchResults.length === 0 && (<div className="text-center py-4 text-zinc-500 text-sm">
|
|
881
|
+
No integrations found for "{searchQuery}"
|
|
882
|
+
</div>)}
|
|
883
|
+
{filteredSearchResults.map(tk => renderProviderCard(toolkitToProvider(tk)))}
|
|
884
|
+
{filteredSearchResults.length > 0 && (<div className="border-t border-zinc-800 my-3"/>)}
|
|
885
|
+
</div>)}
|
|
886
|
+
|
|
887
|
+
{/* Featured Providers */}
|
|
888
|
+
{(!searchQuery.trim() || filteredSearchResults.length > 0 || searchResults.some(sr => featuredSlugs.has(sr.slug))) && (<>
|
|
889
|
+
{searchQuery.trim() && (<div className="text-xs font-medium text-zinc-500 uppercase tracking-wider mb-2">
|
|
890
|
+
Popular
|
|
891
|
+
</div>)}
|
|
892
|
+
{FEATURED_PROVIDERS.map(provider => renderProviderCard(provider))}
|
|
893
|
+
</>)}
|
|
894
|
+
|
|
895
|
+
<p className="text-xs text-zinc-500 text-center pt-4">
|
|
896
|
+
Compose Market never sees or stores your tokens.
|
|
897
|
+
</p>
|
|
898
|
+
</TabsContent>
|
|
899
|
+
</Tabs>
|
|
900
|
+
</>)}
|
|
901
|
+
</DialogContent>
|
|
902
|
+
</Dialog>);
|
|
903
|
+
}
|
|
904
|
+
export default BackpackDialog;
|
|
905
|
+
//# sourceMappingURL=backpack.js.map
|