vibesurf 0.2.40__py3-none-any.whl
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.
Potentially problematic release.
This version of vibesurf might be problematic. Click here for more details.
- vibe_surf/__init__.py +12 -0
- vibe_surf/_version.py +34 -0
- vibe_surf/agents/__init__.py +0 -0
- vibe_surf/agents/browser_use_agent.py +820 -0
- vibe_surf/agents/prompts/__init__.py +1 -0
- vibe_surf/agents/prompts/report_writer_prompt.py +73 -0
- vibe_surf/agents/prompts/vibe_surf_prompt.py +218 -0
- vibe_surf/agents/report_writer_agent.py +580 -0
- vibe_surf/agents/vibe_surf_agent.py +1839 -0
- vibe_surf/agents/views.py +123 -0
- vibe_surf/backend/__init__.py +0 -0
- vibe_surf/backend/api/__init__.py +3 -0
- vibe_surf/backend/api/activity.py +245 -0
- vibe_surf/backend/api/agent.py +38 -0
- vibe_surf/backend/api/browser.py +70 -0
- vibe_surf/backend/api/composio.py +1047 -0
- vibe_surf/backend/api/config.py +762 -0
- vibe_surf/backend/api/files.py +331 -0
- vibe_surf/backend/api/models.py +260 -0
- vibe_surf/backend/api/schedule.py +331 -0
- vibe_surf/backend/api/task.py +378 -0
- vibe_surf/backend/api/vibesurf.py +681 -0
- vibe_surf/backend/api/voices.py +481 -0
- vibe_surf/backend/database/__init__.py +13 -0
- vibe_surf/backend/database/manager.py +318 -0
- vibe_surf/backend/database/migrations/v001_initial_schema.sql +118 -0
- vibe_surf/backend/database/migrations/v002_add_agent_mode.sql +6 -0
- vibe_surf/backend/database/migrations/v003_fix_task_status_case.sql +11 -0
- vibe_surf/backend/database/migrations/v004_add_voice_profiles.sql +35 -0
- vibe_surf/backend/database/migrations/v005_add_composio_integration.sql +33 -0
- vibe_surf/backend/database/migrations/v006_add_credentials_table.sql +26 -0
- vibe_surf/backend/database/migrations/v007_add_schedule_table.sql +29 -0
- vibe_surf/backend/database/models.py +289 -0
- vibe_surf/backend/database/queries.py +1682 -0
- vibe_surf/backend/database/schemas.py +100 -0
- vibe_surf/backend/frontend/assets/MCPLangflow-Bzb6g6Zx.png +0 -0
- vibe_surf/backend/frontend/assets/SlackIcon-CE-ahjQZ.js +1 -0
- vibe_surf/backend/frontend/assets/Wikipedia-BINJ6cJv.js +1 -0
- vibe_surf/backend/frontend/assets/Wolfram-sV3o4SbF.js +1 -0
- vibe_surf/backend/frontend/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- vibe_surf/backend/frontend/assets/a-arrow-down-BcX59nU3.js +6 -0
- vibe_surf/backend/frontend/assets/a-arrow-up-CN8sc-6V.js +6 -0
- vibe_surf/backend/frontend/assets/a-large-small-D4z4tJYP.js +6 -0
- vibe_surf/backend/frontend/assets/accessibility-DPNGH_So.js +6 -0
- vibe_surf/backend/frontend/assets/activity-DBaIDOIU.js +6 -0
- vibe_surf/backend/frontend/assets/air-vent-Yxf9hR-e.js +6 -0
- vibe_surf/backend/frontend/assets/airplay-Cuvu9cUw.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-clock-check-Du3BsRJ-.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-clock-minus-BWB_dmGd.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-clock-off-DtnpjTwW.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-clock-plus-CSe6BTX8.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-clock-qHQG131G.js +6 -0
- vibe_surf/backend/frontend/assets/alarm-smoke-D3HVdJHb.js +6 -0
- vibe_surf/backend/frontend/assets/album-CVutl5zk.js +6 -0
- vibe_surf/backend/frontend/assets/align-center-D3KadjPz.js +6 -0
- vibe_surf/backend/frontend/assets/align-center-horizontal-DGTmV9aA.js +6 -0
- vibe_surf/backend/frontend/assets/align-center-vertical-_5fvpuKY.js +6 -0
- vibe_surf/backend/frontend/assets/align-end-horizontal-DPltJfFM.js +6 -0
- vibe_surf/backend/frontend/assets/align-end-vertical-cv9XHMvE.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-distribute-center-QdrwS7dg.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-distribute-end-Bf9IacXs.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-distribute-start-CyGDfN90.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-justify-center-BBV_-6o5.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-justify-end-Bisjrtt3.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-justify-start-D6DNaBNY.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-space-around-DdeziFMB.js +6 -0
- vibe_surf/backend/frontend/assets/align-horizontal-space-between-Cifkmzuk.js +6 -0
- vibe_surf/backend/frontend/assets/align-justify-CaSlCgAY.js +6 -0
- vibe_surf/backend/frontend/assets/align-left-B2G3vNyc.js +6 -0
- vibe_surf/backend/frontend/assets/align-right-MCEgT99B.js +6 -0
- vibe_surf/backend/frontend/assets/align-start-horizontal-OfSL-vcz.js +6 -0
- vibe_surf/backend/frontend/assets/align-start-vertical-Dbqlci_F.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-distribute-center-FcLPQFYH.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-distribute-end-CUDa17Tj.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-distribute-start-CrZvdfpE.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-justify-center-BOp5aU8B.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-justify-end-CYB_ypaq.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-justify-start-DfClLh-A.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-space-around-DNuIeWrp.js +6 -0
- vibe_surf/backend/frontend/assets/align-vertical-space-between-38joduqw.js +6 -0
- vibe_surf/backend/frontend/assets/ambulance-C_ROlhJD.js +6 -0
- vibe_surf/backend/frontend/assets/ampersand-DvScpWJk.js +6 -0
- vibe_surf/backend/frontend/assets/ampersands-Blzum23C.js +6 -0
- vibe_surf/backend/frontend/assets/amphora-DctGCu79.js +6 -0
- vibe_surf/backend/frontend/assets/anchor-BvYXuJxo.js +6 -0
- vibe_surf/backend/frontend/assets/angry-MKPx79NH.js +6 -0
- vibe_surf/backend/frontend/assets/annoyed-CfNKx2hK.js +6 -0
- vibe_surf/backend/frontend/assets/antenna-Dw3k5fr7.js +6 -0
- vibe_surf/backend/frontend/assets/anvil-C8prcEpZ.js +6 -0
- vibe_surf/backend/frontend/assets/aperture--Tp9qCvO.js +6 -0
- vibe_surf/backend/frontend/assets/apify_white-uCJdZkTU.png +0 -0
- vibe_surf/backend/frontend/assets/app-window-Bs6eiKRX.js +6 -0
- vibe_surf/backend/frontend/assets/app-window-mac-A6qCq1Wj.js +6 -0
- vibe_surf/backend/frontend/assets/apple-CENdsQC1.js +6 -0
- vibe_surf/backend/frontend/assets/archive-DoV6rkNe.js +6 -0
- vibe_surf/backend/frontend/assets/archive-restore-C4ruGNaP.js +6 -0
- vibe_surf/backend/frontend/assets/archive-x-FSNb8ZNO.js +6 -0
- vibe_surf/backend/frontend/assets/armchair-lkSJ2diV.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-down-CZfd7k5o.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-down-dash-DZh_9yfN.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-left-Dl76-6oW.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-left-dash-B38PvMCG.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-right-0TeLuAvG.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-right-dash-Br-Q2sOD.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-up-DjoHZ6em.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-big-up-dash-BDk2lJYm.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-0-1-DaONJclu.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-1-0-DRP7zCqR.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-CVHDaeIM.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-a-z-D3LHPEGP.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-from-line-CfhMT8rR.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-left-CDcXzsPn.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-narrow-wide-Dh2ydU3g.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-right-C1zfcmSn.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-to-dot-CBTjQ2b9.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-to-line-D7fITr7U.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-up-CQFDI11z.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-wide-narrow-BBX8pEpl.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-down-z-a-Cj5ts4gv.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-left-DFBlqjCJ.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-left-from-line-DlmghHsU.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-left-right-D2vJTioe.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-left-to-line-mHPr5GnP.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-right-BQgpMdFf.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-right-from-line-BpW80jQb.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-right-left-S3D3MTs3.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-right-to-line-C70Kx0FS.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-0-1-BVQDbCWQ.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-1-0-DyLpNpnM.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-Bt1icfmQ.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-a-z-Y80pIZ0a.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-down-BklRwaY-.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-from-dot-DEWl1PS1.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-from-line-B6KTMhpQ.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-left-DhrKWt_9.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-narrow-wide-Dip17kLc.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-right-Cqh04sEk.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-to-line-BEQShaIO.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-wide-narrow-DIneP_zC.js +6 -0
- vibe_surf/backend/frontend/assets/arrow-up-z-a-B9wbuYNl.js +6 -0
- vibe_surf/backend/frontend/assets/arrows-up-from-line-3AFYhAJM.js +6 -0
- vibe_surf/backend/frontend/assets/asterisk-W0pDx_Rn.js +6 -0
- vibe_surf/backend/frontend/assets/at-sign-DlBejcs3.js +6 -0
- vibe_surf/backend/frontend/assets/atom-OaWlLitB.js +6 -0
- vibe_surf/backend/frontend/assets/audio-lines-CjFpWvOi.js +6 -0
- vibe_surf/backend/frontend/assets/audio-waveform-DuNZMGXb.js +6 -0
- vibe_surf/backend/frontend/assets/award-BukkHO3C.js +6 -0
- vibe_surf/backend/frontend/assets/axe-BUKyB8rX.js +6 -0
- vibe_surf/backend/frontend/assets/axis-3d-D6v4MamZ.js +6 -0
- vibe_surf/backend/frontend/assets/baby-BOnXpUZv.js +6 -0
- vibe_surf/backend/frontend/assets/backpack-6S9rBoLi.js +6 -0
- vibe_surf/backend/frontend/assets/badge-Dm_XCo4W.js +6 -0
- vibe_surf/backend/frontend/assets/badge-alert-BvvmA4mG.js +6 -0
- vibe_surf/backend/frontend/assets/badge-cent-Q-epnYHs.js +6 -0
- vibe_surf/backend/frontend/assets/badge-check-36lbyNM_.js +6 -0
- vibe_surf/backend/frontend/assets/badge-dollar-sign-tj_oF0X-.js +6 -0
- vibe_surf/backend/frontend/assets/badge-euro-D8PbE0bv.js +6 -0
- vibe_surf/backend/frontend/assets/badge-help-BFD5BXO8.js +6 -0
- vibe_surf/backend/frontend/assets/badge-indian-rupee-5080RWGL.js +6 -0
- vibe_surf/backend/frontend/assets/badge-info-COz3SiCZ.js +6 -0
- vibe_surf/backend/frontend/assets/badge-japanese-yen-DFXPoz7u.js +6 -0
- vibe_surf/backend/frontend/assets/badge-minus-BsGaVL3Q.js +6 -0
- vibe_surf/backend/frontend/assets/badge-percent-B4cd7rtn.js +6 -0
- vibe_surf/backend/frontend/assets/badge-plus-Vecq1PGK.js +6 -0
- vibe_surf/backend/frontend/assets/badge-pound-sterling-DLYMYG8U.js +6 -0
- vibe_surf/backend/frontend/assets/badge-russian-ruble-BzNr--Mh.js +6 -0
- vibe_surf/backend/frontend/assets/badge-swiss-franc-Des6zCyZ.js +6 -0
- vibe_surf/backend/frontend/assets/badge-x-CSb9nfC0.js +6 -0
- vibe_surf/backend/frontend/assets/baggage-claim-DDwV8NEi.js +6 -0
- vibe_surf/backend/frontend/assets/ban-BYnCport.js +6 -0
- vibe_surf/backend/frontend/assets/banana-Dfi3HmlS.js +6 -0
- vibe_surf/backend/frontend/assets/bandage-CcKil-EC.js +6 -0
- vibe_surf/backend/frontend/assets/banknote-XCDTM0NN.js +6 -0
- vibe_surf/backend/frontend/assets/banknote-arrow-down-DjVb8CZD.js +6 -0
- vibe_surf/backend/frontend/assets/banknote-arrow-up-C4w7omsx.js +6 -0
- vibe_surf/backend/frontend/assets/banknote-x-CQPrNAnr.js +6 -0
- vibe_surf/backend/frontend/assets/barcode-B0ezXTca.js +6 -0
- vibe_surf/backend/frontend/assets/baseline-CA8GPr3n.js +6 -0
- vibe_surf/backend/frontend/assets/bath-BdiVnLCS.js +6 -0
- vibe_surf/backend/frontend/assets/battery-CvLfXslf.js +6 -0
- vibe_surf/backend/frontend/assets/battery-charging-Bin6EfKA.js +6 -0
- vibe_surf/backend/frontend/assets/battery-full-BNcpthdG.js +6 -0
- vibe_surf/backend/frontend/assets/battery-low-0acbM2TX.js +6 -0
- vibe_surf/backend/frontend/assets/battery-medium-CqQzYkr0.js +6 -0
- vibe_surf/backend/frontend/assets/battery-plus-CeXK9ubJ.js +6 -0
- vibe_surf/backend/frontend/assets/battery-warning-BX1_YAxk.js +6 -0
- vibe_surf/backend/frontend/assets/beaker-CvU60KJI.js +6 -0
- vibe_surf/backend/frontend/assets/bean-DXSFxjpW.js +6 -0
- vibe_surf/backend/frontend/assets/bean-off-C18fYQxg.js +6 -0
- vibe_surf/backend/frontend/assets/bed-BHNMrHmJ.js +6 -0
- vibe_surf/backend/frontend/assets/bed-double-CBJd1xUT.js +6 -0
- vibe_surf/backend/frontend/assets/bed-single-C2P2u_SW.js +6 -0
- vibe_surf/backend/frontend/assets/beef-DZ7YmxJ9.js +6 -0
- vibe_surf/backend/frontend/assets/beer-DoSAYmbT.js +6 -0
- vibe_surf/backend/frontend/assets/beer-off-D2D0Eidd.js +6 -0
- vibe_surf/backend/frontend/assets/bell-CZemSa0A.js +6 -0
- vibe_surf/backend/frontend/assets/bell-dot-2U18M7J_.js +6 -0
- vibe_surf/backend/frontend/assets/bell-electric-O_6RWZVP.js +6 -0
- vibe_surf/backend/frontend/assets/bell-minus-C5OFhKIv.js +6 -0
- vibe_surf/backend/frontend/assets/bell-off-DvNAvSV6.js +6 -0
- vibe_surf/backend/frontend/assets/bell-plus-CtbF4PY7.js +6 -0
- vibe_surf/backend/frontend/assets/bell-ring-2jzOxMlO.js +6 -0
- vibe_surf/backend/frontend/assets/between-horizontal-end-IrrEJxkg.js +6 -0
- vibe_surf/backend/frontend/assets/between-horizontal-start-DB4hrTYq.js +6 -0
- vibe_surf/backend/frontend/assets/between-vertical-end-DeC10NGd.js +6 -0
- vibe_surf/backend/frontend/assets/between-vertical-start-Byocansl.js +6 -0
- vibe_surf/backend/frontend/assets/biceps-flexed-ByGLeOXg.js +6 -0
- vibe_surf/backend/frontend/assets/bike-C2kR3eV7.js +6 -0
- vibe_surf/backend/frontend/assets/binary-ClycWsS0.js +6 -0
- vibe_surf/backend/frontend/assets/binoculars-DJ0HCEbV.js +6 -0
- vibe_surf/backend/frontend/assets/biohazard-DIYTxz4-.js +6 -0
- vibe_surf/backend/frontend/assets/bird-DStHDBlx.js +6 -0
- vibe_surf/backend/frontend/assets/bitcoin-CrUhJt55.js +6 -0
- vibe_surf/backend/frontend/assets/blend-Bf3c4w6z.js +6 -0
- vibe_surf/backend/frontend/assets/blinds-Ni4n5PSf.js +6 -0
- vibe_surf/backend/frontend/assets/blocks-B3WNZe2n.js +6 -0
- vibe_surf/backend/frontend/assets/bluetooth-Ccoiwmlv.js +6 -0
- vibe_surf/backend/frontend/assets/bluetooth-connected-DFiYewdk.js +6 -0
- vibe_surf/backend/frontend/assets/bluetooth-off-CWk55vIU.js +6 -0
- vibe_surf/backend/frontend/assets/bluetooth-searching-B7AZU8fL.js +6 -0
- vibe_surf/backend/frontend/assets/bold-DLSX_sXx.js +6 -0
- vibe_surf/backend/frontend/assets/bolt-BtrJOWZT.js +6 -0
- vibe_surf/backend/frontend/assets/bomb-qB5OKrmG.js +6 -0
- vibe_surf/backend/frontend/assets/bone-CwzjO8Q3.js +6 -0
- vibe_surf/backend/frontend/assets/book-CFsU8BHi.js +6 -0
- vibe_surf/backend/frontend/assets/book-a-CZdxqQip.js +6 -0
- vibe_surf/backend/frontend/assets/book-audio-C4vaYZSH.js +6 -0
- vibe_surf/backend/frontend/assets/book-check-Bcz9b-8J.js +6 -0
- vibe_surf/backend/frontend/assets/book-copy-CXk7oCU5.js +6 -0
- vibe_surf/backend/frontend/assets/book-dashed-emdeAmuI.js +6 -0
- vibe_surf/backend/frontend/assets/book-down-Blr3MxEN.js +6 -0
- vibe_surf/backend/frontend/assets/book-headphones-gUzmqrJf.js +6 -0
- vibe_surf/backend/frontend/assets/book-heart-D0TpFook.js +6 -0
- vibe_surf/backend/frontend/assets/book-image-CDh3XrAm.js +6 -0
- vibe_surf/backend/frontend/assets/book-key-DQV2MwOV.js +6 -0
- vibe_surf/backend/frontend/assets/book-lock-Df4Wh5kT.js +6 -0
- vibe_surf/backend/frontend/assets/book-marked-j4_WwgAf.js +6 -0
- vibe_surf/backend/frontend/assets/book-minus-DhTrzC1g.js +6 -0
- vibe_surf/backend/frontend/assets/book-open-BzAE9-Jg.js +6 -0
- vibe_surf/backend/frontend/assets/book-open-check-Uqc5cpgA.js +6 -0
- vibe_surf/backend/frontend/assets/book-open-text-BWiD6pH2.js +6 -0
- vibe_surf/backend/frontend/assets/book-plus-BSzMVarr.js +6 -0
- vibe_surf/backend/frontend/assets/book-text-CWHsjw1-.js +6 -0
- vibe_surf/backend/frontend/assets/book-type-9PjTGoqg.js +6 -0
- vibe_surf/backend/frontend/assets/book-up-2-B_62ZUyn.js +6 -0
- vibe_surf/backend/frontend/assets/book-up-BNLPeI--.js +6 -0
- vibe_surf/backend/frontend/assets/book-user-BGJrncKZ.js +6 -0
- vibe_surf/backend/frontend/assets/book-x-BIuvvbQ9.js +6 -0
- vibe_surf/backend/frontend/assets/bookmark-C6GKCgas.js +6 -0
- vibe_surf/backend/frontend/assets/bookmark-check-D2v52wS_.js +6 -0
- vibe_surf/backend/frontend/assets/bookmark-minus-5SruaRWe.js +6 -0
- vibe_surf/backend/frontend/assets/bookmark-plus-CDB4EbYF.js +6 -0
- vibe_surf/backend/frontend/assets/bookmark-x-DawiyeWt.js +6 -0
- vibe_surf/backend/frontend/assets/boom-box-CjxUDyUJ.js +6 -0
- vibe_surf/backend/frontend/assets/bot-BcNQyjDe.js +6 -0
- vibe_surf/backend/frontend/assets/bot-message-square-CJLeai4W.js +6 -0
- vibe_surf/backend/frontend/assets/bot-off-CYborYVu.js +6 -0
- vibe_surf/backend/frontend/assets/bow-arrow-DINnk6sV.js +6 -0
- vibe_surf/backend/frontend/assets/box-C8qv4POs.js +6 -0
- vibe_surf/backend/frontend/assets/boxes-C1Wz5G2m.js +6 -0
- vibe_surf/backend/frontend/assets/braces-BL19F0qy.js +6 -0
- vibe_surf/backend/frontend/assets/brackets-DXYKs2wJ.js +6 -0
- vibe_surf/backend/frontend/assets/brain-BuTeWcBr.js +6 -0
- vibe_surf/backend/frontend/assets/brain-circuit-DAr0c9Ig.js +6 -0
- vibe_surf/backend/frontend/assets/brain-cog-C-6ua_E5.js +6 -0
- vibe_surf/backend/frontend/assets/brick-wall-DiRdytpC.js +6 -0
- vibe_surf/backend/frontend/assets/brick-wall-fire-Df58-yW_.js +6 -0
- vibe_surf/backend/frontend/assets/briefcase-BCC8rhM-.js +6 -0
- vibe_surf/backend/frontend/assets/briefcase-business-11K02ygr.js +6 -0
- vibe_surf/backend/frontend/assets/briefcase-conveyor-belt-BGOeI8YI.js +6 -0
- vibe_surf/backend/frontend/assets/briefcase-medical-Cf5O_Vzv.js +6 -0
- vibe_surf/backend/frontend/assets/bring-to-front-DkBhdEDk.js +6 -0
- vibe_surf/backend/frontend/assets/brush-CwwHpx8w.js +6 -0
- vibe_surf/backend/frontend/assets/bubbles-BNDUSsoL.js +6 -0
- vibe_surf/backend/frontend/assets/bug-B-h4nltF.js +6 -0
- vibe_surf/backend/frontend/assets/bug-off-BsFDr1Kw.js +6 -0
- vibe_surf/backend/frontend/assets/bug-play-26tPYeYP.js +6 -0
- vibe_surf/backend/frontend/assets/building-2-B8a5eq3G.js +6 -0
- vibe_surf/backend/frontend/assets/building-D-y2htrY.js +6 -0
- vibe_surf/backend/frontend/assets/bus-eKi5tEc0.js +6 -0
- vibe_surf/backend/frontend/assets/bus-front-UgmZ3AhM.js +6 -0
- vibe_surf/backend/frontend/assets/cable-bgAMwTGl.js +6 -0
- vibe_surf/backend/frontend/assets/cable-car-D4-4YVV_.js +6 -0
- vibe_surf/backend/frontend/assets/cake-CsxUhj7B.js +6 -0
- vibe_surf/backend/frontend/assets/cake-slice-CDFVuMN9.js +6 -0
- vibe_surf/backend/frontend/assets/calculator-DgmhNoBI.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-1-BKz8ZI5j.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-arrow-down-CtgxtU04.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-arrow-up-xRCcun7L.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-check-2-CZSHjt45.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-check-4yXO0khM.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-clock-BakA-x1D.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-cog-CZljoOd5.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-days-ChE7Ny1-.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-fold-BkO7wfLY.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-heart-Dr-9lPi7.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-minus-2-qezZcq9-.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-minus-vz6lNpYY.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-off-BWz43ibw.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-plus-2-XgwhzxSM.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-plus-D3Dch9Uq.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-range-DNVYH5rE.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-search-Cu8Pf1i4.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-sync-CJShUCMN.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-uQc-0CwX.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-x-2-DKrkh_XF.js +6 -0
- vibe_surf/backend/frontend/assets/calendar-x-BAw2jejx.js +6 -0
- vibe_surf/backend/frontend/assets/camera-CeCtO8OS.js +6 -0
- vibe_surf/backend/frontend/assets/camera-off-Dn0VufPW.js +6 -0
- vibe_surf/backend/frontend/assets/candy-C8LKHyd9.js +6 -0
- vibe_surf/backend/frontend/assets/candy-cane-qdqDVt_H.js +6 -0
- vibe_surf/backend/frontend/assets/candy-off-DoNKmYDA.js +6 -0
- vibe_surf/backend/frontend/assets/cannabis-d1YIKR6M.js +6 -0
- vibe_surf/backend/frontend/assets/captions-DLcuaLjj.js +6 -0
- vibe_surf/backend/frontend/assets/captions-off-CSNnDqnT.js +6 -0
- vibe_surf/backend/frontend/assets/car-BNlBq1cc.js +6 -0
- vibe_surf/backend/frontend/assets/car-front-n1ZZ5Nji.js +6 -0
- vibe_surf/backend/frontend/assets/car-taxi-front-Da7GM3x6.js +6 -0
- vibe_surf/backend/frontend/assets/caravan-DNROe0a9.js +6 -0
- vibe_surf/backend/frontend/assets/carrot-ByVO2D43.js +6 -0
- vibe_surf/backend/frontend/assets/case-lower-BNX91uLr.js +6 -0
- vibe_surf/backend/frontend/assets/case-sensitive-QY839cid.js +6 -0
- vibe_surf/backend/frontend/assets/case-upper-DUDhnzhx.js +6 -0
- vibe_surf/backend/frontend/assets/cassette-tape-DnY7y11C.js +6 -0
- vibe_surf/backend/frontend/assets/cast-DL3Ri4Zn.js +6 -0
- vibe_surf/backend/frontend/assets/castle-DoI41Pkw.js +6 -0
- vibe_surf/backend/frontend/assets/cat-Xm6ynrXR.js +6 -0
- vibe_surf/backend/frontend/assets/cctv-DME6qRnE.js +6 -0
- vibe_surf/backend/frontend/assets/chart-area-BGI28u47.js +6 -0
- vibe_surf/backend/frontend/assets/chart-bar-DBV1hPM5.js +6 -0
- vibe_surf/backend/frontend/assets/chart-bar-big-CvJY7AHY.js +6 -0
- vibe_surf/backend/frontend/assets/chart-bar-decreasing-9uwKC-he.js +6 -0
- vibe_surf/backend/frontend/assets/chart-bar-increasing-F1gG2kkZ.js +6 -0
- vibe_surf/backend/frontend/assets/chart-bar-stacked-DbDlBSDo.js +6 -0
- vibe_surf/backend/frontend/assets/chart-candlestick-DTWO94r-.js +6 -0
- vibe_surf/backend/frontend/assets/chart-column-Cdh3ooHC.js +6 -0
- vibe_surf/backend/frontend/assets/chart-column-big-Eh8aDm6L.js +6 -0
- vibe_surf/backend/frontend/assets/chart-column-decreasing-BSuKP6Qc.js +6 -0
- vibe_surf/backend/frontend/assets/chart-column-increasing-BzEsRspx.js +6 -0
- vibe_surf/backend/frontend/assets/chart-column-stacked-Ca6vYEkF.js +6 -0
- vibe_surf/backend/frontend/assets/chart-gantt-BKdYU39i.js +6 -0
- vibe_surf/backend/frontend/assets/chart-line-DN7nBokI.js +6 -0
- vibe_surf/backend/frontend/assets/chart-network-B6aKwyxu.js +6 -0
- vibe_surf/backend/frontend/assets/chart-no-axes-column-BPUq1xmc.js +6 -0
- vibe_surf/backend/frontend/assets/chart-no-axes-column-decreasing-CtSuhRPr.js +6 -0
- vibe_surf/backend/frontend/assets/chart-no-axes-column-increasing-D9Z23RSe.js +6 -0
- vibe_surf/backend/frontend/assets/chart-no-axes-combined-BPIDpAUw.js +6 -0
- vibe_surf/backend/frontend/assets/chart-no-axes-gantt-mstaaDOy.js +6 -0
- vibe_surf/backend/frontend/assets/chart-pie-DHkYI2nd.js +6 -0
- vibe_surf/backend/frontend/assets/chart-scatter-BMUVsxxc.js +6 -0
- vibe_surf/backend/frontend/assets/chart-spline-BQYhzmbs.js +6 -0
- vibe_surf/backend/frontend/assets/check-check-DZ6-FF8V.js +6 -0
- vibe_surf/backend/frontend/assets/chef-hat-DI_R6N2N.js +6 -0
- vibe_surf/backend/frontend/assets/cherry-D00B4bwv.js +6 -0
- vibe_surf/backend/frontend/assets/chevron-first-D-sSlEK9.js +6 -0
- vibe_surf/backend/frontend/assets/chevron-last-AieZfpF5.js +6 -0
- vibe_surf/backend/frontend/assets/chevron-left-mfds1hqE.js +6 -0
- vibe_surf/backend/frontend/assets/chevron-right-Cjbrp9zy.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-down-D3_RigXr.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-down-up-CWJ3Bpey.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-left-DRqjvpLx.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-left-right-ellipsis-BzX-1Cdp.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-left-right-lA1Z637d.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-right-Ceh1Kykn.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-right-left-D0pOkKiz.js +6 -0
- vibe_surf/backend/frontend/assets/chevrons-up-CkJhDtkt.js +6 -0
- vibe_surf/backend/frontend/assets/chrome-B99nQ5T6.js +6 -0
- vibe_surf/backend/frontend/assets/church-CCtCcuUF.js +6 -0
- vibe_surf/backend/frontend/assets/cigarette-DHz-zWI5.js +6 -0
- vibe_surf/backend/frontend/assets/cigarette-off-CWKFWcz-.js +6 -0
- vibe_surf/backend/frontend/assets/circle-alert-BCdP7B9m.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-down-gjAb2XAQ.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-left-B8TL5s92.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-out-down-left-BDZ_mOB3.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-out-down-right-C31JwGaH.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-out-up-left-jLaU6DvQ.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-out-up-right-D2ixwYhA.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-right-C_cagsqv.js +6 -0
- vibe_surf/backend/frontend/assets/circle-arrow-up-Dx87_2P9.js +6 -0
- vibe_surf/backend/frontend/assets/circle-check-C5uPloQF.js +6 -0
- vibe_surf/backend/frontend/assets/circle-check-big-P_p4Wr1K.js +6 -0
- vibe_surf/backend/frontend/assets/circle-chevron-down-C2MiOrG4.js +6 -0
- vibe_surf/backend/frontend/assets/circle-chevron-left-DDuIXpi4.js +6 -0
- vibe_surf/backend/frontend/assets/circle-chevron-right-myMJ4pPe.js +6 -0
- vibe_surf/backend/frontend/assets/circle-chevron-up-De1WbdBl.js +6 -0
- vibe_surf/backend/frontend/assets/circle-dashed-Bl6JELwp.js +6 -0
- vibe_surf/backend/frontend/assets/circle-divide-3_AqIeYz.js +6 -0
- vibe_surf/backend/frontend/assets/circle-dollar-sign-BxcNzUBd.js +6 -0
- vibe_surf/backend/frontend/assets/circle-dot-BxsZo1Nv.js +6 -0
- vibe_surf/backend/frontend/assets/circle-dot-dashed-C9_3fDwg.js +6 -0
- vibe_surf/backend/frontend/assets/circle-ellipsis-y8IPhLQX.js +6 -0
- vibe_surf/backend/frontend/assets/circle-equal-CMS41nZX.js +6 -0
- vibe_surf/backend/frontend/assets/circle-fading-arrow-up-Ctl33k8e.js +6 -0
- vibe_surf/backend/frontend/assets/circle-fading-plus-DcIVZnCm.js +6 -0
- vibe_surf/backend/frontend/assets/circle-gauge-hli3GonG.js +6 -0
- vibe_surf/backend/frontend/assets/circle-help-DhBxmPfs.js +6 -0
- vibe_surf/backend/frontend/assets/circle-minus-DuzoP_Gr.js +6 -0
- vibe_surf/backend/frontend/assets/circle-off-CkMo-mEi.js +6 -0
- vibe_surf/backend/frontend/assets/circle-parking-DObllwiU.js +6 -0
- vibe_surf/backend/frontend/assets/circle-parking-off-Eu8OaFfX.js +6 -0
- vibe_surf/backend/frontend/assets/circle-pause-DWZvbXLh.js +6 -0
- vibe_surf/backend/frontend/assets/circle-percent-Gswg5Dmm.js +6 -0
- vibe_surf/backend/frontend/assets/circle-play-Cs7oMz5r.js +6 -0
- vibe_surf/backend/frontend/assets/circle-plus-BbT0XhZy.js +6 -0
- vibe_surf/backend/frontend/assets/circle-power-DJYAzMhA.js +6 -0
- vibe_surf/backend/frontend/assets/circle-slash-2-C6g9B1d4.js +6 -0
- vibe_surf/backend/frontend/assets/circle-slash-80HmVvSU.js +6 -0
- vibe_surf/backend/frontend/assets/circle-small-BplNmUKo.js +6 -0
- vibe_surf/backend/frontend/assets/circle-stop-X4XHzl3_.js +6 -0
- vibe_surf/backend/frontend/assets/circle-user-CBbX0YUx.js +6 -0
- vibe_surf/backend/frontend/assets/circle-user-round-BKiTCzXI.js +6 -0
- vibe_surf/backend/frontend/assets/circuit-board-DMnzBge-.js +6 -0
- vibe_surf/backend/frontend/assets/citrus-BXZMlaiu.js +6 -0
- vibe_surf/backend/frontend/assets/clapperboard-QI5DhvkW.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-DSAtTHqu.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-check-BZBI9pc5.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-copy-CSl6j3te.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-list-C8QFRlUw.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-minus-BuCbzuoq.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-paste-CQn0LMaW.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-pen-line-Bx0wm5dI.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-pen-q_cqsVmS.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-plus-DwQAo6_l.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-type-BNYyoI1_.js +6 -0
- vibe_surf/backend/frontend/assets/clipboard-x-DZYuwaaG.js +6 -0
- vibe_surf/backend/frontend/assets/clock-1-DgESaKSE.js +6 -0
- vibe_surf/backend/frontend/assets/clock-10-wIgrU8Yj.js +6 -0
- vibe_surf/backend/frontend/assets/clock-11-Buh5WHor.js +6 -0
- vibe_surf/backend/frontend/assets/clock-12-C2gsOQrL.js +6 -0
- vibe_surf/backend/frontend/assets/clock-2-D43KucqT.js +6 -0
- vibe_surf/backend/frontend/assets/clock-3-DYI1jraG.js +6 -0
- vibe_surf/backend/frontend/assets/clock-4-L4e4KHXv.js +6 -0
- vibe_surf/backend/frontend/assets/clock-5-CWJ5YkDs.js +6 -0
- vibe_surf/backend/frontend/assets/clock-6-CtaZof53.js +6 -0
- vibe_surf/backend/frontend/assets/clock-7-asCRJHjv.js +6 -0
- vibe_surf/backend/frontend/assets/clock-8-Cc2qbeiy.js +6 -0
- vibe_surf/backend/frontend/assets/clock-9-Dl4X0vFw.js +6 -0
- vibe_surf/backend/frontend/assets/clock-BYS3KG7-.js +6 -0
- vibe_surf/backend/frontend/assets/clock-alert-Cq_VQBiw.js +6 -0
- vibe_surf/backend/frontend/assets/clock-arrow-down-Bd1H68GK.js +6 -0
- vibe_surf/backend/frontend/assets/clock-arrow-up-BUYARFyu.js +6 -0
- vibe_surf/backend/frontend/assets/clock-fading-DdL2cNkM.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-BMpvy1xk.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-alert-D5XOu8YY.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-cog-CMw4aVSH.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-download-DU72C1pe.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-drizzle-B0XQktr3.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-fog-Bt7bjAbr.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-hail-rqT8jB3i.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-lightning-BBVTdh3m.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-moon-R-fj3ojz.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-moon-rain-yqxneI3M.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-off-yg-ZE-_Q.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-rain-ChHLGe1p.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-rain-wind-JR4JcS7C.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-snow-Cybax_co.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-sun-DkBED-mU.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-sun-rain-B5_9ukkr.js +6 -0
- vibe_surf/backend/frontend/assets/cloud-upload-Cu4ieVcA.js +6 -0
- vibe_surf/backend/frontend/assets/cloudy-BfAjnn1H.js +6 -0
- vibe_surf/backend/frontend/assets/clover-Nay_aOR-.js +6 -0
- vibe_surf/backend/frontend/assets/club-Wma0dWBT.js +6 -0
- vibe_surf/backend/frontend/assets/code-xml-JRyiBJKX.js +6 -0
- vibe_surf/backend/frontend/assets/codepen-Db89gVRb.js +6 -0
- vibe_surf/backend/frontend/assets/codesandbox-6Bi0nwFB.js +6 -0
- vibe_surf/backend/frontend/assets/coffee-BUZkk2WM.js +6 -0
- vibe_surf/backend/frontend/assets/cog-BlUy4pJ6.js +6 -0
- vibe_surf/backend/frontend/assets/coins-Bx_bjmVj.js +6 -0
- vibe_surf/backend/frontend/assets/columns-2-BQVZlGLr.js +6 -0
- vibe_surf/backend/frontend/assets/columns-3-SW5AYOfS.js +6 -0
- vibe_surf/backend/frontend/assets/columns-3-cog-etTCUk7U.js +6 -0
- vibe_surf/backend/frontend/assets/columns-4-BPpIDoQv.js +6 -0
- vibe_surf/backend/frontend/assets/combine-DAkv3eQ-.js +6 -0
- vibe_surf/backend/frontend/assets/command-BCh8jDkv.js +6 -0
- vibe_surf/backend/frontend/assets/compass-B9ZnFYhL.js +6 -0
- vibe_surf/backend/frontend/assets/component-B3rp8m52.js +6 -0
- vibe_surf/backend/frontend/assets/computer-DSXJ82Yq.js +6 -0
- vibe_surf/backend/frontend/assets/concierge-bell-08Utkgj4.js +6 -0
- vibe_surf/backend/frontend/assets/cone-CtuBXsg9.js +6 -0
- vibe_surf/backend/frontend/assets/construction-CW4jHft2.js +6 -0
- vibe_surf/backend/frontend/assets/contact-BEshHPpN.js +6 -0
- vibe_surf/backend/frontend/assets/contact-round-kvYdDXoY.js +6 -0
- vibe_surf/backend/frontend/assets/container-D0OTPthH.js +6 -0
- vibe_surf/backend/frontend/assets/contrast-DnkMkf-y.js +6 -0
- vibe_surf/backend/frontend/assets/cookie-CYld1ib8.js +6 -0
- vibe_surf/backend/frontend/assets/cooking-pot-r3byuDHj.js +6 -0
- vibe_surf/backend/frontend/assets/copy-BmO-mv3j.js +6 -0
- vibe_surf/backend/frontend/assets/copy-check-8SojR2n7.js +6 -0
- vibe_surf/backend/frontend/assets/copy-minus-BgbL-ezu.js +6 -0
- vibe_surf/backend/frontend/assets/copy-plus-pG8nJiZU.js +6 -0
- vibe_surf/backend/frontend/assets/copy-slash-7hvOeX3Q.js +6 -0
- vibe_surf/backend/frontend/assets/copy-x-DEPYUbh1.js +6 -0
- vibe_surf/backend/frontend/assets/copyleft-Ce67b9NQ.js +6 -0
- vibe_surf/backend/frontend/assets/copyright-BfKpdVBw.js +6 -0
- vibe_surf/backend/frontend/assets/corner-down-left-Dphkqh8j.js +6 -0
- vibe_surf/backend/frontend/assets/corner-down-right-Dq07c5k_.js +6 -0
- vibe_surf/backend/frontend/assets/corner-left-down-CxWh_26z.js +6 -0
- vibe_surf/backend/frontend/assets/corner-left-up-BLgQomz0.js +6 -0
- vibe_surf/backend/frontend/assets/corner-right-down-tYY2AfHr.js +6 -0
- vibe_surf/backend/frontend/assets/corner-right-up-Bj9fzWl1.js +6 -0
- vibe_surf/backend/frontend/assets/corner-up-left-m22RfGo1.js +6 -0
- vibe_surf/backend/frontend/assets/corner-up-right-CodaZCnS.js +6 -0
- vibe_surf/backend/frontend/assets/cpu-Bu0IGxWB.js +6 -0
- vibe_surf/backend/frontend/assets/creative-commons-j_bcx2B-.js +6 -0
- vibe_surf/backend/frontend/assets/credit-card-CIdSlGyt.js +6 -0
- vibe_surf/backend/frontend/assets/croissant-m9Tzpn6-.js +6 -0
- vibe_surf/backend/frontend/assets/crop-BT5n_BDw.js +6 -0
- vibe_surf/backend/frontend/assets/cross-WahXWLmu.js +6 -0
- vibe_surf/backend/frontend/assets/crosshair-Detaeusf.js +6 -0
- vibe_surf/backend/frontend/assets/crown-BIIqN4tU.js +6 -0
- vibe_surf/backend/frontend/assets/cuboid-COMWL8KE.js +6 -0
- vibe_surf/backend/frontend/assets/cup-soda-DHRt3-v6.js +6 -0
- vibe_surf/backend/frontend/assets/currency-B82qjXmb.js +6 -0
- vibe_surf/backend/frontend/assets/cylinder-CgY0_Sr-.js +6 -0
- vibe_surf/backend/frontend/assets/dam-TTB5VJyi.js +6 -0
- vibe_surf/backend/frontend/assets/database-CIFWjgNY.js +6 -0
- vibe_surf/backend/frontend/assets/database-backup-CvRH8XaW.js +6 -0
- vibe_surf/backend/frontend/assets/database-zap-CiKnHfeB.js +6 -0
- vibe_surf/backend/frontend/assets/decimals-arrow-left-BioOtsdm.js +6 -0
- vibe_surf/backend/frontend/assets/decimals-arrow-right-Cx4cszFW.js +6 -0
- vibe_surf/backend/frontend/assets/delete-BAdtbBtM.js +6 -0
- vibe_surf/backend/frontend/assets/dessert-DkIzBH7A.js +6 -0
- vibe_surf/backend/frontend/assets/diameter-CvVdrBrk.js +6 -0
- vibe_surf/backend/frontend/assets/diamond-BXgkzyFD.js +6 -0
- vibe_surf/backend/frontend/assets/diamond-minus-D79h5E4F.js +6 -0
- vibe_surf/backend/frontend/assets/diamond-percent-DFTgIUWX.js +6 -0
- vibe_surf/backend/frontend/assets/diamond-plus-C_6l6Egb.js +6 -0
- vibe_surf/backend/frontend/assets/dice-1-BYNZMiRy.js +6 -0
- vibe_surf/backend/frontend/assets/dice-2-BNbymABr.js +6 -0
- vibe_surf/backend/frontend/assets/dice-3-Dd1JuSvv.js +6 -0
- vibe_surf/backend/frontend/assets/dice-4-D8TCA-54.js +6 -0
- vibe_surf/backend/frontend/assets/dice-5-CUoUzy4y.js +6 -0
- vibe_surf/backend/frontend/assets/dice-6-B_kWm-vM.js +6 -0
- vibe_surf/backend/frontend/assets/dices-XLW7VfCr.js +6 -0
- vibe_surf/backend/frontend/assets/diff-R28hcSRc.js +6 -0
- vibe_surf/backend/frontend/assets/disc-2-C5DTPMUd.js +6 -0
- vibe_surf/backend/frontend/assets/disc-3-BtEvZMjh.js +6 -0
- vibe_surf/backend/frontend/assets/disc-CKAPWmCy.js +6 -0
- vibe_surf/backend/frontend/assets/disc-album-cuvuWfA9.js +6 -0
- vibe_surf/backend/frontend/assets/divide-BxQmQals.js +6 -0
- vibe_surf/backend/frontend/assets/dna-D0iYcnjp.js +6 -0
- vibe_surf/backend/frontend/assets/dna-off-ErTou38f.js +6 -0
- vibe_surf/backend/frontend/assets/dock-BkchtLNf.js +6 -0
- vibe_surf/backend/frontend/assets/dog-JA5MF7gp.js +6 -0
- vibe_surf/backend/frontend/assets/dollar-sign-S9eSDOrJ.js +6 -0
- vibe_surf/backend/frontend/assets/donut-BqRrNkvP.js +6 -0
- vibe_surf/backend/frontend/assets/door-closed-B-MrGb6q.js +6 -0
- vibe_surf/backend/frontend/assets/door-open-Br3vbfpG.js +6 -0
- vibe_surf/backend/frontend/assets/dot-DXfRbuM0.js +6 -0
- vibe_surf/backend/frontend/assets/drafting-compass-DMXHtO4G.js +6 -0
- vibe_surf/backend/frontend/assets/drama-Dubi2dNu.js +6 -0
- vibe_surf/backend/frontend/assets/dribbble-DOzityvb.js +6 -0
- vibe_surf/backend/frontend/assets/drill-BQ0EsUsX.js +6 -0
- vibe_surf/backend/frontend/assets/droplet-off-ButGxGdH.js +6 -0
- vibe_surf/backend/frontend/assets/droplet-son-_skj.js +6 -0
- vibe_surf/backend/frontend/assets/droplets-BZ2YfVSA.js +6 -0
- vibe_surf/backend/frontend/assets/drum-BQx6BFpe.js +6 -0
- vibe_surf/backend/frontend/assets/drumstick-3-rUtwNB.js +6 -0
- vibe_surf/backend/frontend/assets/dumbbell-BthFc0AJ.js +6 -0
- vibe_surf/backend/frontend/assets/ear-kW9YKHKv.js +6 -0
- vibe_surf/backend/frontend/assets/ear-off-C9aEMiZV.js +6 -0
- vibe_surf/backend/frontend/assets/earth-B5AfETae.js +6 -0
- vibe_surf/backend/frontend/assets/earth-lock-acG4NArC.js +6 -0
- vibe_surf/backend/frontend/assets/eclipse-JDjKYV0j.js +6 -0
- vibe_surf/backend/frontend/assets/egg-BJX5S-yO.js +6 -0
- vibe_surf/backend/frontend/assets/egg-fried-CzdJ94z0.js +6 -0
- vibe_surf/backend/frontend/assets/egg-off-DFZTyisV.js +6 -0
- vibe_surf/backend/frontend/assets/ellipsis-Do5QGxdF.js +6 -0
- vibe_surf/backend/frontend/assets/ellipsis-vertical-DL3lXNkl.js +6 -0
- vibe_surf/backend/frontend/assets/equal-CSbKMjR9.js +6 -0
- vibe_surf/backend/frontend/assets/equal-approximately-D-_zKTi0.js +6 -0
- vibe_surf/backend/frontend/assets/equal-not-BEN-hLun.js +6 -0
- vibe_surf/backend/frontend/assets/eraser-EqIxcp-G.js +6 -0
- vibe_surf/backend/frontend/assets/ethernet-port-Ctq9b8YM.js +6 -0
- vibe_surf/backend/frontend/assets/euro-CUlQSiXf.js +6 -0
- vibe_surf/backend/frontend/assets/expand-LQdF_-l7.js +6 -0
- vibe_surf/backend/frontend/assets/eye-B14urkBb.js +6 -0
- vibe_surf/backend/frontend/assets/eye-closed-BpcKXvvZ.js +6 -0
- vibe_surf/backend/frontend/assets/eye-off-B-I1bzN-.js +6 -0
- vibe_surf/backend/frontend/assets/facebook-DMySCi-p.js +6 -0
- vibe_surf/backend/frontend/assets/factory-Bd6MRr0-.js +6 -0
- vibe_surf/backend/frontend/assets/fan-tVwUdYtX.js +6 -0
- vibe_surf/backend/frontend/assets/fast-forward-CY4W38Jf.js +6 -0
- vibe_surf/backend/frontend/assets/feather-C553H-qS.js +6 -0
- vibe_surf/backend/frontend/assets/fence-BJNMd5m7.js +6 -0
- vibe_surf/backend/frontend/assets/ferris-wheel-oHPMJGEQ.js +6 -0
- vibe_surf/backend/frontend/assets/figma-C9tPiFb3.js +6 -0
- vibe_surf/backend/frontend/assets/file-AzAzVrMs.js +6 -0
- vibe_surf/backend/frontend/assets/file-archive-CIMp0jPK.js +6 -0
- vibe_surf/backend/frontend/assets/file-audio-2-D6PqsNui.js +6 -0
- vibe_surf/backend/frontend/assets/file-audio-B3MBbrsx.js +6 -0
- vibe_surf/backend/frontend/assets/file-axis-3d-CAs3JLL4.js +6 -0
- vibe_surf/backend/frontend/assets/file-badge-2-BigpxEa4.js +6 -0
- vibe_surf/backend/frontend/assets/file-badge-DxxBNe6I.js +6 -0
- vibe_surf/backend/frontend/assets/file-box-CFM_ZS8C.js +6 -0
- vibe_surf/backend/frontend/assets/file-chart-column-DW7tDtSF.js +6 -0
- vibe_surf/backend/frontend/assets/file-chart-column-increasing-Dqw2rkcp.js +6 -0
- vibe_surf/backend/frontend/assets/file-chart-line-B55e6iQr.js +6 -0
- vibe_surf/backend/frontend/assets/file-chart-pie-bx6xE3zh.js +6 -0
- vibe_surf/backend/frontend/assets/file-check-2-O19xL6zZ.js +6 -0
- vibe_surf/backend/frontend/assets/file-check-BW8E_U7M.js +6 -0
- vibe_surf/backend/frontend/assets/file-clock-CJ7TCW3g.js +6 -0
- vibe_surf/backend/frontend/assets/file-code-2-IWdjGkQV.js +6 -0
- vibe_surf/backend/frontend/assets/file-code-C8Cb2eAQ.js +6 -0
- vibe_surf/backend/frontend/assets/file-cog-D7zwEbXQ.js +6 -0
- vibe_surf/backend/frontend/assets/file-diff-Cd4QjfxS.js +6 -0
- vibe_surf/backend/frontend/assets/file-digit-D4o35Lws.js +6 -0
- vibe_surf/backend/frontend/assets/file-down-CvhBfQai.js +6 -0
- vibe_surf/backend/frontend/assets/file-heart-SAbeQl04.js +6 -0
- vibe_surf/backend/frontend/assets/file-image-n3F2ES2d.js +6 -0
- vibe_surf/backend/frontend/assets/file-input-BF2fJ0HZ.js +6 -0
- vibe_surf/backend/frontend/assets/file-json-2-CHFMlqRM.js +6 -0
- vibe_surf/backend/frontend/assets/file-json-GQx3fsvD.js +6 -0
- vibe_surf/backend/frontend/assets/file-key-2-D4vSersB.js +6 -0
- vibe_surf/backend/frontend/assets/file-key-DoCfAot9.js +6 -0
- vibe_surf/backend/frontend/assets/file-lock-2-D5yc4s9S.js +6 -0
- vibe_surf/backend/frontend/assets/file-lock-fbh0rbzY.js +6 -0
- vibe_surf/backend/frontend/assets/file-minus-2-jZ3pDR5C.js +6 -0
- vibe_surf/backend/frontend/assets/file-minus-uXOKmAYW.js +6 -0
- vibe_surf/backend/frontend/assets/file-music-YA3-0ItN.js +6 -0
- vibe_surf/backend/frontend/assets/file-output-CXDuHwjv.js +6 -0
- vibe_surf/backend/frontend/assets/file-pen-B16K0rIH.js +6 -0
- vibe_surf/backend/frontend/assets/file-pen-line-Dec_HNbe.js +6 -0
- vibe_surf/backend/frontend/assets/file-plus-2-Wj25GYBI.js +6 -0
- vibe_surf/backend/frontend/assets/file-plus-Bv2RaOy_.js +6 -0
- vibe_surf/backend/frontend/assets/file-question-CBnhbTUy.js +6 -0
- vibe_surf/backend/frontend/assets/file-scan-C4l__2lp.js +6 -0
- vibe_surf/backend/frontend/assets/file-search-2-B_BQLrOO.js +6 -0
- vibe_surf/backend/frontend/assets/file-search-igYKSOot.js +6 -0
- vibe_surf/backend/frontend/assets/file-sliders-BC6jqY7m.js +6 -0
- vibe_surf/backend/frontend/assets/file-spreadsheet-8zeuwOFy.js +6 -0
- vibe_surf/backend/frontend/assets/file-stack-CEbrflgS.js +6 -0
- vibe_surf/backend/frontend/assets/file-symlink-Ce64x_q-.js +6 -0
- vibe_surf/backend/frontend/assets/file-terminal-DEMjlYPH.js +6 -0
- vibe_surf/backend/frontend/assets/file-text-qsRAxrKg.js +6 -0
- vibe_surf/backend/frontend/assets/file-type-2-rdAUx0k-.js +6 -0
- vibe_surf/backend/frontend/assets/file-type-Bo0mvnlr.js +6 -0
- vibe_surf/backend/frontend/assets/file-up-ChCUFvtC.js +6 -0
- vibe_surf/backend/frontend/assets/file-user-DeJOcc6w.js +6 -0
- vibe_surf/backend/frontend/assets/file-video-2-NeLUHxWj.js +6 -0
- vibe_surf/backend/frontend/assets/file-video-M49YI2mS.js +6 -0
- vibe_surf/backend/frontend/assets/file-volume-2-Bde2Kb7U.js +6 -0
- vibe_surf/backend/frontend/assets/file-volume-up1R-zQ1.js +6 -0
- vibe_surf/backend/frontend/assets/file-warning-DNllVKxU.js +6 -0
- vibe_surf/backend/frontend/assets/file-x-2-CHaW7ofd.js +6 -0
- vibe_surf/backend/frontend/assets/file-x-Ct2jUMMo.js +6 -0
- vibe_surf/backend/frontend/assets/files-CvndfhQ4.js +6 -0
- vibe_surf/backend/frontend/assets/film-y1VzEOGa.js +6 -0
- vibe_surf/backend/frontend/assets/fingerprint-BI6dfzhE.js +6 -0
- vibe_surf/backend/frontend/assets/fire-extinguisher--s4lJQsf.js +6 -0
- vibe_surf/backend/frontend/assets/fish-off-D3GNjlTn.js +6 -0
- vibe_surf/backend/frontend/assets/fish-s2So_Zeq.js +6 -0
- vibe_surf/backend/frontend/assets/fish-symbol-CYjqO11h.js +6 -0
- vibe_surf/backend/frontend/assets/flag-C27BL99d.js +6 -0
- vibe_surf/backend/frontend/assets/flag-off-CMKWJ8l8.js +6 -0
- vibe_surf/backend/frontend/assets/flag-triangle-left-B0Zzobci.js +6 -0
- vibe_surf/backend/frontend/assets/flag-triangle-right-BYX5OyAO.js +6 -0
- vibe_surf/backend/frontend/assets/flame-BZdffZJx.js +6 -0
- vibe_surf/backend/frontend/assets/flame-kindling-B1qjw-qo.js +6 -0
- vibe_surf/backend/frontend/assets/flashlight-D7kNRs0V.js +6 -0
- vibe_surf/backend/frontend/assets/flashlight-off-Dc1MMZFO.js +6 -0
- vibe_surf/backend/frontend/assets/flask-conical-ChF2JmZu.js +6 -0
- vibe_surf/backend/frontend/assets/flask-conical-off-DegTh8gS.js +6 -0
- vibe_surf/backend/frontend/assets/flask-round-CK1-Ik6i.js +6 -0
- vibe_surf/backend/frontend/assets/flip-horizontal-2-Dn8i_KV0.js +6 -0
- vibe_surf/backend/frontend/assets/flip-horizontal-CuVvaraZ.js +6 -0
- vibe_surf/backend/frontend/assets/flip-vertical-2-rFYdErLA.js +6 -0
- vibe_surf/backend/frontend/assets/flip-vertical-B90WGgH0.js +6 -0
- vibe_surf/backend/frontend/assets/flower-2-C_TT89UG.js +6 -0
- vibe_surf/backend/frontend/assets/flower-CO6QACmS.js +6 -0
- vibe_surf/backend/frontend/assets/focus-D26Oa74J.js +6 -0
- vibe_surf/backend/frontend/assets/fold-horizontal-CBIHGZ0q.js +6 -0
- vibe_surf/backend/frontend/assets/fold-vertical-CD7tvqYt.js +6 -0
- vibe_surf/backend/frontend/assets/folder-Cf5LgRi0.js +6 -0
- vibe_surf/backend/frontend/assets/folder-archive-eaqS6DPc.js +6 -0
- vibe_surf/backend/frontend/assets/folder-check-BKYRcZZr.js +6 -0
- vibe_surf/backend/frontend/assets/folder-clock-DfstD_8t.js +6 -0
- vibe_surf/backend/frontend/assets/folder-closed-CQt1KGRd.js +6 -0
- vibe_surf/backend/frontend/assets/folder-code-D-UAjp3e.js +6 -0
- vibe_surf/backend/frontend/assets/folder-cog-8jmE8SgB.js +6 -0
- vibe_surf/backend/frontend/assets/folder-dot-BCaqBqPg.js +6 -0
- vibe_surf/backend/frontend/assets/folder-down-DRl1_ZDB.js +6 -0
- vibe_surf/backend/frontend/assets/folder-git-2-DctBKaC9.js +6 -0
- vibe_surf/backend/frontend/assets/folder-git-CgxiRK0t.js +6 -0
- vibe_surf/backend/frontend/assets/folder-heart-D6REuieU.js +6 -0
- vibe_surf/backend/frontend/assets/folder-input-C12iWWhu.js +6 -0
- vibe_surf/backend/frontend/assets/folder-kanban-GZtaS_8J.js +6 -0
- vibe_surf/backend/frontend/assets/folder-key-afzRqgkz.js +6 -0
- vibe_surf/backend/frontend/assets/folder-lock-BcLNHqg8.js +6 -0
- vibe_surf/backend/frontend/assets/folder-minus-CvtpPjpU.js +6 -0
- vibe_surf/backend/frontend/assets/folder-open-DupkgJt1.js +6 -0
- vibe_surf/backend/frontend/assets/folder-open-dot-Cxfuxe--.js +6 -0
- vibe_surf/backend/frontend/assets/folder-output-Cg4BpiEV.js +6 -0
- vibe_surf/backend/frontend/assets/folder-pen-DwS7aPNO.js +6 -0
- vibe_surf/backend/frontend/assets/folder-plus-2lTMhR3O.js +6 -0
- vibe_surf/backend/frontend/assets/folder-root-C8WxCnE2.js +6 -0
- vibe_surf/backend/frontend/assets/folder-search-2-Ci-RbLN6.js +6 -0
- vibe_surf/backend/frontend/assets/folder-search-DrXJcjXi.js +6 -0
- vibe_surf/backend/frontend/assets/folder-symlink-BnpH1nVs.js +6 -0
- vibe_surf/backend/frontend/assets/folder-sync-C8-HdePM.js +6 -0
- vibe_surf/backend/frontend/assets/folder-tree-CqSaz8mh.js +6 -0
- vibe_surf/backend/frontend/assets/folder-up-s-mV4gUm.js +6 -0
- vibe_surf/backend/frontend/assets/folder-x-DyHE15uU.js +6 -0
- vibe_surf/backend/frontend/assets/folders-BsPXE9jo.js +6 -0
- vibe_surf/backend/frontend/assets/footprints-D-XXhokZ.js +6 -0
- vibe_surf/backend/frontend/assets/forklift-MYwqGUlF.js +6 -0
- vibe_surf/backend/frontend/assets/forward-0FCU5gw7.js +6 -0
- vibe_surf/backend/frontend/assets/frame-D8alLdea.js +6 -0
- vibe_surf/backend/frontend/assets/framer-DNjQaa1J.js +6 -0
- vibe_surf/backend/frontend/assets/frown-BE0OTdKG.js +6 -0
- vibe_surf/backend/frontend/assets/fuel-mXmAr8TO.js +6 -0
- vibe_surf/backend/frontend/assets/fullscreen-NqXN2Xu7.js +6 -0
- vibe_surf/backend/frontend/assets/funnel-DC0c1Jih.js +6 -0
- vibe_surf/backend/frontend/assets/funnel-plus-Doo-nNYi.js +6 -0
- vibe_surf/backend/frontend/assets/funnel-x-BkmZkEbi.js +6 -0
- vibe_surf/backend/frontend/assets/gallery-horizontal-BaQJYKLC.js +6 -0
- vibe_surf/backend/frontend/assets/gallery-horizontal-end-BWNtYXQf.js +6 -0
- vibe_surf/backend/frontend/assets/gallery-thumbnails-4tJCu6Bt.js +6 -0
- vibe_surf/backend/frontend/assets/gallery-vertical-end-F0Ry7RoI.js +6 -0
- vibe_surf/backend/frontend/assets/gallery-vertical-gD2KGFqY.js +6 -0
- vibe_surf/backend/frontend/assets/gamepad-2-DBi5t2On.js +6 -0
- vibe_surf/backend/frontend/assets/gamepad-8df6ey2A.js +6 -0
- vibe_surf/backend/frontend/assets/gauge-BKZLQcLt.js +6 -0
- vibe_surf/backend/frontend/assets/gavel-CLgRmYF8.js +6 -0
- vibe_surf/backend/frontend/assets/gem-M00EoNdV.js +6 -0
- vibe_surf/backend/frontend/assets/ghost-CEfBnyKY.js +6 -0
- vibe_surf/backend/frontend/assets/gift-BjGURCYr.js +6 -0
- vibe_surf/backend/frontend/assets/git-branch-BOK0DnKM.js +6 -0
- vibe_surf/backend/frontend/assets/git-branch-plus-Duz02qvz.js +6 -0
- vibe_surf/backend/frontend/assets/git-commit-horizontal-DXh9abTq.js +6 -0
- vibe_surf/backend/frontend/assets/git-commit-vertical-8IUR92zC.js +6 -0
- vibe_surf/backend/frontend/assets/git-compare-Bbxv-OD3.js +6 -0
- vibe_surf/backend/frontend/assets/git-compare-arrows-ULo-Y57B.js +6 -0
- vibe_surf/backend/frontend/assets/git-fork-wi2CvjEp.js +6 -0
- vibe_surf/backend/frontend/assets/git-graph-CWjPQ35V.js +6 -0
- vibe_surf/backend/frontend/assets/git-merge-BhyoIeLJ.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-BLS97ZSf.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-arrow-DNZCE5xe.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-closed-8STT9TyU.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-create-DR3c4qrX.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-create-arrow-BOgAjTFS.js +6 -0
- vibe_surf/backend/frontend/assets/git-pull-request-draft-D_pN85AJ.js +6 -0
- vibe_surf/backend/frontend/assets/github-DB1aZt0L.js +6 -0
- vibe_surf/backend/frontend/assets/gitlab-BMP4NP3r.js +6 -0
- vibe_surf/backend/frontend/assets/glass-water-BEC0MS3z.js +6 -0
- vibe_surf/backend/frontend/assets/glasses-CfTHXtX7.js +6 -0
- vibe_surf/backend/frontend/assets/globe-Dqq-nhcy.js +6 -0
- vibe_surf/backend/frontend/assets/globe-lock-BfeWqRWO.js +6 -0
- vibe_surf/backend/frontend/assets/goal-C-PhIQ4S.js +6 -0
- vibe_surf/backend/frontend/assets/grab-DdIFtKhV.js +6 -0
- vibe_surf/backend/frontend/assets/graduation-cap-CwxzapTt.js +6 -0
- vibe_surf/backend/frontend/assets/grape-BrXELEz9.js +6 -0
- vibe_surf/backend/frontend/assets/grid-2x2-D8v9ysk4.js +6 -0
- vibe_surf/backend/frontend/assets/grid-2x2-check-CSZSWQ5C.js +6 -0
- vibe_surf/backend/frontend/assets/grid-2x2-plus-01llG4f2.js +6 -0
- vibe_surf/backend/frontend/assets/grid-2x2-x-D0_11tKc.js +6 -0
- vibe_surf/backend/frontend/assets/grid-3x3-CquAt5Fe.js +6 -0
- vibe_surf/backend/frontend/assets/grip-DzkE91_C.js +6 -0
- vibe_surf/backend/frontend/assets/grip-horizontal-9smTJuh8.js +6 -0
- vibe_surf/backend/frontend/assets/grip-vertical-BazF71zy.js +6 -0
- vibe_surf/backend/frontend/assets/group-DJPqVGM9.js +6 -0
- vibe_surf/backend/frontend/assets/guitar-Bj7040UW.js +6 -0
- vibe_surf/backend/frontend/assets/ham-DqF9nY3K.js +6 -0
- vibe_surf/backend/frontend/assets/hammer-D5nCkk93.js +6 -0
- vibe_surf/backend/frontend/assets/hand-D3aHt5Jp.js +6 -0
- vibe_surf/backend/frontend/assets/hand-coins-DgGrUIw3.js +6 -0
- vibe_surf/backend/frontend/assets/hand-heart-D-ejt1w9.js +6 -0
- vibe_surf/backend/frontend/assets/hand-helping-BJx7aYP8.js +6 -0
- vibe_surf/backend/frontend/assets/hand-metal-D_9PgLDn.js +6 -0
- vibe_surf/backend/frontend/assets/hand-platter-B6MPED_R.js +6 -0
- vibe_surf/backend/frontend/assets/handshake-5mCL50jm.js +6 -0
- vibe_surf/backend/frontend/assets/hard-drive-D06Pr4Fr.js +6 -0
- vibe_surf/backend/frontend/assets/hard-drive-download-DV7i6zaz.js +6 -0
- vibe_surf/backend/frontend/assets/hard-drive-upload-qc50ymdt.js +6 -0
- vibe_surf/backend/frontend/assets/hard-hat-BHAORALK.js +6 -0
- vibe_surf/backend/frontend/assets/hash-DTUBYWfA.js +6 -0
- vibe_surf/backend/frontend/assets/haze-VZL9k3sN.js +6 -0
- vibe_surf/backend/frontend/assets/hdmi-port-De943wKH.js +6 -0
- vibe_surf/backend/frontend/assets/heading-1-BYwnxWwH.js +6 -0
- vibe_surf/backend/frontend/assets/heading-2-CqPhfYl0.js +6 -0
- vibe_surf/backend/frontend/assets/heading-3-CANI8m_-.js +6 -0
- vibe_surf/backend/frontend/assets/heading-4-BeqLaVrS.js +6 -0
- vibe_surf/backend/frontend/assets/heading-5-EhtPwD0Y.js +6 -0
- vibe_surf/backend/frontend/assets/heading-6-CzA0Vq0D.js +6 -0
- vibe_surf/backend/frontend/assets/heading-COny31IM.js +6 -0
- vibe_surf/backend/frontend/assets/headphone-off-XcT4H0Th.js +6 -0
- vibe_surf/backend/frontend/assets/headphones-INSavdLi.js +6 -0
- vibe_surf/backend/frontend/assets/headset-D46LhOQp.js +6 -0
- vibe_surf/backend/frontend/assets/heart-CnQaegyS.js +6 -0
- vibe_surf/backend/frontend/assets/heart-crack-CSaApcMZ.js +6 -0
- vibe_surf/backend/frontend/assets/heart-handshake-gpn_t0P6.js +6 -0
- vibe_surf/backend/frontend/assets/heart-minus-ByA4Xc3z.js +6 -0
- vibe_surf/backend/frontend/assets/heart-off-BaAxT8OM.js +6 -0
- vibe_surf/backend/frontend/assets/heart-plus-DsNgHyPq.js +6 -0
- vibe_surf/backend/frontend/assets/heart-pulse-mu0bRWr9.js +6 -0
- vibe_surf/backend/frontend/assets/heater-BZJRpXix.js +6 -0
- vibe_surf/backend/frontend/assets/hexagon-BOkIK8t8.js +6 -0
- vibe_surf/backend/frontend/assets/highlighter-BFjuqmg3.js +6 -0
- vibe_surf/backend/frontend/assets/history-Dc5zUj7o.js +6 -0
- vibe_surf/backend/frontend/assets/hop-BP2c2w0o.js +6 -0
- vibe_surf/backend/frontend/assets/hop-off-DvtutUIk.js +6 -0
- vibe_surf/backend/frontend/assets/hospital-CnB07zSL.js +6 -0
- vibe_surf/backend/frontend/assets/hotel-DcrYKMCA.js +6 -0
- vibe_surf/backend/frontend/assets/hourglass-5XoIreir.js +6 -0
- vibe_surf/backend/frontend/assets/house-7K0Log2X.js +6 -0
- vibe_surf/backend/frontend/assets/house-plug-BpGlsdom.js +6 -0
- vibe_surf/backend/frontend/assets/house-plus-CZa5w2xG.js +6 -0
- vibe_surf/backend/frontend/assets/house-wifi-D7WgCkxh.js +6 -0
- vibe_surf/backend/frontend/assets/ice-cream-bowl-CVO-vDDu.js +6 -0
- vibe_surf/backend/frontend/assets/ice-cream-cone-Be2L7luj.js +6 -0
- vibe_surf/backend/frontend/assets/id-card-DuJWEfZ1.js +6 -0
- vibe_surf/backend/frontend/assets/image-BHKjD-UF.js +6 -0
- vibe_surf/backend/frontend/assets/image-down-BxsvaSTP.js +6 -0
- vibe_surf/backend/frontend/assets/image-minus-BTyo6N_c.js +6 -0
- vibe_surf/backend/frontend/assets/image-off-CYgis6fN.js +6 -0
- vibe_surf/backend/frontend/assets/image-play-BH02lW6y.js +6 -0
- vibe_surf/backend/frontend/assets/image-plus-_CPkoXgl.js +6 -0
- vibe_surf/backend/frontend/assets/image-up-Ck7H6ALp.js +6 -0
- vibe_surf/backend/frontend/assets/image-upscale-BKY8Ql1Y.js +6 -0
- vibe_surf/backend/frontend/assets/images-C7PaOMX8.js +6 -0
- vibe_surf/backend/frontend/assets/import-XtX00yjR.js +6 -0
- vibe_surf/backend/frontend/assets/inbox-CHp1G1Tn.js +6 -0
- vibe_surf/backend/frontend/assets/indent-decrease-DTtNKMfY.js +6 -0
- vibe_surf/backend/frontend/assets/indent-increase-DInW8D_x.js +6 -0
- vibe_surf/backend/frontend/assets/index-1QRDbRlx.js +1 -0
- vibe_surf/backend/frontend/assets/index-2WLZ-LFU.js +1 -0
- vibe_surf/backend/frontend/assets/index-41veksKc.js +1 -0
- vibe_surf/backend/frontend/assets/index-9d3lQ4Wj.js +1 -0
- vibe_surf/backend/frontend/assets/index-A-NnAKzY.js +1 -0
- vibe_surf/backend/frontend/assets/index-B0uEIchy.js +1 -0
- vibe_surf/backend/frontend/assets/index-B6ckts6e.js +1 -0
- vibe_surf/backend/frontend/assets/index-B8eJzoCm.js +1 -0
- vibe_surf/backend/frontend/assets/index-BAjcuT2A.js +1 -0
- vibe_surf/backend/frontend/assets/index-BDpVuW9l.js +1 -0
- vibe_surf/backend/frontend/assets/index-BEzSx8JL.js +1 -0
- vibe_surf/backend/frontend/assets/index-BFZ6c4-2.js +1 -0
- vibe_surf/backend/frontend/assets/index-BHwpyLDU.js +1 -0
- vibe_surf/backend/frontend/assets/index-BJzwrRH0.js +1 -0
- vibe_surf/backend/frontend/assets/index-BKwrPgkD.js +1 -0
- vibe_surf/backend/frontend/assets/index-BLAOHAiB.js +1 -0
- vibe_surf/backend/frontend/assets/index-BMJN1BeZ.js +1 -0
- vibe_surf/backend/frontend/assets/index-BM_pQz6b.js +1 -0
- vibe_surf/backend/frontend/assets/index-BNGDVeR7.js +1 -0
- vibe_surf/backend/frontend/assets/index-BO1wzOz3.js +1 -0
- vibe_surf/backend/frontend/assets/index-BPwUN4EA.js +1 -0
- vibe_surf/backend/frontend/assets/index-BUpWUGFt.js +1 -0
- vibe_surf/backend/frontend/assets/index-BVOgCkqk.js +1 -0
- vibe_surf/backend/frontend/assets/index-BX8uYJvf.js +1 -0
- vibe_surf/backend/frontend/assets/index-BXwmSa5j.js +1 -0
- vibe_surf/backend/frontend/assets/index-BY5nAT18.js +1 -0
- vibe_surf/backend/frontend/assets/index-BZsjXFd9.js +1 -0
- vibe_surf/backend/frontend/assets/index-BaQ12pVy.js +1 -0
- vibe_surf/backend/frontend/assets/index-Bdh85PFk.js +1 -0
- vibe_surf/backend/frontend/assets/index-BdxAovDe.js +1 -0
- vibe_surf/backend/frontend/assets/index-BevOJcfm.js +1 -0
- vibe_surf/backend/frontend/assets/index-BhbPDv-7.js +20 -0
- vibe_surf/backend/frontend/assets/index-Bi2_nzSq.js +1 -0
- vibe_surf/backend/frontend/assets/index-BjuAKp39.js +1 -0
- vibe_surf/backend/frontend/assets/index-BkWReKus.js +1 -0
- vibe_surf/backend/frontend/assets/index-BlT0iN5E.css +1 -0
- vibe_surf/backend/frontend/assets/index-Bn_YwEX1.js +1 -0
- vibe_surf/backend/frontend/assets/index-BopyFI9_.js +1 -0
- vibe_surf/backend/frontend/assets/index-Bq-mBfcp.js +205 -0
- vibe_surf/backend/frontend/assets/index-BtNGro4J.js +1 -0
- vibe_surf/backend/frontend/assets/index-BtRUEqM8.js +1 -0
- vibe_surf/backend/frontend/assets/index-BvcS9R2I.js +1 -0
- vibe_surf/backend/frontend/assets/index-ByRMlFrn.js +1 -0
- vibe_surf/backend/frontend/assets/index-ByweJ-ba.js +1 -0
- vibe_surf/backend/frontend/assets/index-C-CvySwp.js +1 -0
- vibe_surf/backend/frontend/assets/index-C3Yoqcx6.js +2 -0
- vibe_surf/backend/frontend/assets/index-C3xUW7lX.js +1 -0
- vibe_surf/backend/frontend/assets/index-C6oR7Fin.js +1 -0
- vibe_surf/backend/frontend/assets/index-C6punO8E.js +1 -0
- vibe_surf/backend/frontend/assets/index-C7fGwI5N.js +1 -0
- vibe_surf/backend/frontend/assets/index-C9339APM.js +7427 -0
- vibe_surf/backend/frontend/assets/index-CAFKIjNb.js +1 -0
- vibe_surf/backend/frontend/assets/index-CEGDW591.js +1 -0
- vibe_surf/backend/frontend/assets/index-CGzeT9Yq.js +1 -0
- vibe_surf/backend/frontend/assets/index-CH-Snzdw.js +1 -0
- vibe_surf/backend/frontend/assets/index-CIFNJDFM.js +2723 -0
- vibe_surf/backend/frontend/assets/index-CNHcFn3X.js +1 -0
- vibe_surf/backend/frontend/assets/index-CP_bbwDH.js +1 -0
- vibe_surf/backend/frontend/assets/index-CQVSfKD9.js +1 -0
- vibe_surf/backend/frontend/assets/index-CaWx5V5s.js +1 -0
- vibe_surf/backend/frontend/assets/index-Cb0tGz07.js +1 -0
- vibe_surf/backend/frontend/assets/index-CbHKDInE.js +1 -0
- vibe_surf/backend/frontend/assets/index-CePGA63r.js +1 -0
- vibe_surf/backend/frontend/assets/index-CfUNPxF7.js +1 -0
- vibe_surf/backend/frontend/assets/index-CpUW-lWU.js +1 -0
- vibe_surf/backend/frontend/assets/index-Cscpd5G3.js +1 -0
- vibe_surf/backend/frontend/assets/index-Ct7oS9uE.js +1 -0
- vibe_surf/backend/frontend/assets/index-Cx_W-gua.js +1 -0
- vibe_surf/backend/frontend/assets/index-D-gd0ZjH.js +1 -0
- vibe_surf/backend/frontend/assets/index-D1366-Ey.js +1 -0
- vibe_surf/backend/frontend/assets/index-D1Rf-jZG.js +1 -0
- vibe_surf/backend/frontend/assets/index-D2RFrg2r.js +1 -0
- vibe_surf/backend/frontend/assets/index-D3_azQSf.js +108 -0
- vibe_surf/backend/frontend/assets/index-D5eASxXP.js +1 -0
- vibe_surf/backend/frontend/assets/index-D9fl0TdK.js +1 -0
- vibe_surf/backend/frontend/assets/index-DCiLjNmU.js +1 -0
- vibe_surf/backend/frontend/assets/index-DCxdgdvG.js +1 -0
- vibe_surf/backend/frontend/assets/index-DGXaF1oB.js +1 -0
- vibe_surf/backend/frontend/assets/index-DHy7kSom.js +1 -0
- vibe_surf/backend/frontend/assets/index-DKH6KC9o.js +1 -0
- vibe_surf/backend/frontend/assets/index-DKjZ06Bc.js +1 -0
- vibe_surf/backend/frontend/assets/index-DQ5b8TQ5.js +1 -0
- vibe_surf/backend/frontend/assets/index-DQPs4Zqk.js +1 -0
- vibe_surf/backend/frontend/assets/index-DSykqFxk.js +13 -0
- vibe_surf/backend/frontend/assets/index-DVXnylY4.js +1 -0
- vibe_surf/backend/frontend/assets/index-DWberIXV.js +1 -0
- vibe_surf/backend/frontend/assets/index-DWq2xFSF.js +1 -0
- vibe_surf/backend/frontend/assets/index-DWrrUV4U.js +1 -0
- vibe_surf/backend/frontend/assets/index-DXK7n3cr.js +1 -0
- vibe_surf/backend/frontend/assets/index-DYtHFNkM.js +1 -0
- vibe_surf/backend/frontend/assets/index-D_v35WKd.js +1 -0
- vibe_surf/backend/frontend/assets/index-Dbs5qCFv.js +1 -0
- vibe_surf/backend/frontend/assets/index-DcdjKErJ.js +1 -0
- vibe_surf/backend/frontend/assets/index-DeGB92Vc.js +1 -0
- vibe_surf/backend/frontend/assets/index-DfkDcbqO.js +1 -0
- vibe_surf/backend/frontend/assets/index-Dg5uvyoa.js +1 -0
- vibe_surf/backend/frontend/assets/index-DjuYMrz5.js +1 -0
- vibe_surf/backend/frontend/assets/index-Djz3krhV.js +1 -0
- vibe_surf/backend/frontend/assets/index-DtEKUsaA.js +1 -0
- vibe_surf/backend/frontend/assets/index-DtKEeqjg.js +1 -0
- vibe_surf/backend/frontend/assets/index-DtO-Tei2.js +1 -0
- vibe_surf/backend/frontend/assets/index-DuMKqLcc.js +1 -0
- vibe_surf/backend/frontend/assets/index-DwqWXmr0.js +1 -0
- vibe_surf/backend/frontend/assets/index-Dxb4Fp5u.js +1 -0
- vibe_surf/backend/frontend/assets/index-ElUTfe6y.js +1 -0
- vibe_surf/backend/frontend/assets/index-F4DPTTmW.js +21 -0
- vibe_surf/backend/frontend/assets/index-F7N4-tp0.js +1 -0
- vibe_surf/backend/frontend/assets/index-FM3NE49p.js +1 -0
- vibe_surf/backend/frontend/assets/index-HXgxnl2q.js +1 -0
- vibe_surf/backend/frontend/assets/index-HY6HZeH-.js +1 -0
- vibe_surf/backend/frontend/assets/index-JU1gFC-s.js +1 -0
- vibe_surf/backend/frontend/assets/index-PsRZzqdR.js +1 -0
- vibe_surf/backend/frontend/assets/index-Q9VIxKEz.js +1 -0
- vibe_surf/backend/frontend/assets/index-RroJUq2p.js +1 -0
- vibe_surf/backend/frontend/assets/index-UE8QCPYd.js +1 -0
- vibe_surf/backend/frontend/assets/index-VdxoDWfx.js +1 -0
- vibe_surf/backend/frontend/assets/index-YIS8NPcp.js +1 -0
- vibe_surf/backend/frontend/assets/index-ZBnWfhuO.js +1 -0
- vibe_surf/backend/frontend/assets/index-_00eK0dx.js +1 -0
- vibe_surf/backend/frontend/assets/index-ciR61sXL.js +1 -0
- vibe_surf/backend/frontend/assets/index-hvkkGC_C.js +1 -0
- vibe_surf/backend/frontend/assets/index-iirYVAS4.js +1 -0
- vibe_surf/backend/frontend/assets/index-irsZgDst.js +1 -0
- vibe_surf/backend/frontend/assets/index-lJyWjBrf.js +1 -0
- vibe_surf/backend/frontend/assets/index-lpqC0HtC.js +1 -0
- vibe_surf/backend/frontend/assets/index-lr6s8TRd.js +1 -0
- vibe_surf/backend/frontend/assets/index-nikO1i2M.js +1 -0
- vibe_surf/backend/frontend/assets/index-rOe1xSiI.js +1 -0
- vibe_surf/backend/frontend/assets/index-tWBGHnad.js +1 -0
- vibe_surf/backend/frontend/assets/index-tsFLmLrl.js +1 -0
- vibe_surf/backend/frontend/assets/index-u-It3BPJ.js +1 -0
- vibe_surf/backend/frontend/assets/index-u7tDY3oQ.js +1 -0
- vibe_surf/backend/frontend/assets/indian-rupee-rcG3I_ik.js +6 -0
- vibe_surf/backend/frontend/assets/infinity-D2vde04W.js +6 -0
- vibe_surf/backend/frontend/assets/info-DCBxRgu8.js +6 -0
- vibe_surf/backend/frontend/assets/inspection-panel-D1NHUrhL.js +6 -0
- vibe_surf/backend/frontend/assets/instagram-CJjKKid7.js +6 -0
- vibe_surf/backend/frontend/assets/italic-4Xc96EXs.js +6 -0
- vibe_surf/backend/frontend/assets/iteration-ccw-Bv46VJuw.js +6 -0
- vibe_surf/backend/frontend/assets/iteration-cw-D1aiWDvA.js +6 -0
- vibe_surf/backend/frontend/assets/japanese-yen-iCW2ETCz.js +6 -0
- vibe_surf/backend/frontend/assets/joystick-DpYFj9GD.js +6 -0
- vibe_surf/backend/frontend/assets/kanban-Bi2WetF9.js +6 -0
- vibe_surf/backend/frontend/assets/key-CVsuJN4n.js +6 -0
- vibe_surf/backend/frontend/assets/key-round-DnXQqmxg.js +6 -0
- vibe_surf/backend/frontend/assets/key-square-C923Z847.js +6 -0
- vibe_surf/backend/frontend/assets/keyboard-CbihMjR7.js +6 -0
- vibe_surf/backend/frontend/assets/keyboard-music-z9LKvpAM.js +6 -0
- vibe_surf/backend/frontend/assets/keyboard-off-7iFjxyhx.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-BtrnuKcM.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-ceiling-BC1utsWI.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-desk-pkAXfQ8j.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-floor-vTmpCx0w.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-wall-down-lOG8ziR3.js +6 -0
- vibe_surf/backend/frontend/assets/lamp-wall-up-CZPE8AI2.js +6 -0
- vibe_surf/backend/frontend/assets/land-plot-C8hHfhfO.js +6 -0
- vibe_surf/backend/frontend/assets/landmark-f1Ab1l9u.js +6 -0
- vibe_surf/backend/frontend/assets/languages-CRCZA8-s.js +6 -0
- vibe_surf/backend/frontend/assets/laptop-DSbK7NcM.js +6 -0
- vibe_surf/backend/frontend/assets/laptop-minimal-DasoCoN2.js +6 -0
- vibe_surf/backend/frontend/assets/laptop-minimal-check-lZ_bsJ5w.js +6 -0
- vibe_surf/backend/frontend/assets/lasso-DlJ-otu7.js +6 -0
- vibe_surf/backend/frontend/assets/lasso-select-BYwDXrvF.js +6 -0
- vibe_surf/backend/frontend/assets/laugh-C4s0yYY7.js +6 -0
- vibe_surf/backend/frontend/assets/layers-2-37YpnxFQ.js +6 -0
- vibe_surf/backend/frontend/assets/layers-DE4bYq54.js +6 -0
- vibe_surf/backend/frontend/assets/layout-dashboard-BwQq8lH9.js +6 -0
- vibe_surf/backend/frontend/assets/layout-grid-D3mog0PH.js +6 -0
- vibe_surf/backend/frontend/assets/layout-list-hbueXQMH.js +6 -0
- vibe_surf/backend/frontend/assets/layout-panel-left-DqWFlQAM.js +6 -0
- vibe_surf/backend/frontend/assets/layout-panel-top-CTffvfmV.js +6 -0
- vibe_surf/backend/frontend/assets/layout-template-DGqYJhgj.js +6 -0
- vibe_surf/backend/frontend/assets/lazyIconImports-Dp0wlOKL.js +2 -0
- vibe_surf/backend/frontend/assets/leaf-DmquW3E7.js +6 -0
- vibe_surf/backend/frontend/assets/leafy-green-BznFobCL.js +6 -0
- vibe_surf/backend/frontend/assets/lectern-DqoFltAf.js +6 -0
- vibe_surf/backend/frontend/assets/letter-text-DO4JCJop.js +6 -0
- vibe_surf/backend/frontend/assets/library-CIMhvcn4.js +6 -0
- vibe_surf/backend/frontend/assets/library-big-CZ8lXboA.js +6 -0
- vibe_surf/backend/frontend/assets/life-buoy-7TSJy9Vb.js +6 -0
- vibe_surf/backend/frontend/assets/ligature-DBcaOHJh.js +6 -0
- vibe_surf/backend/frontend/assets/lightbulb-off-DbjjujiQ.js +6 -0
- vibe_surf/backend/frontend/assets/lightbulb-qkF0YBSU.js +6 -0
- vibe_surf/backend/frontend/assets/link-2-DcH4c4Zc.js +6 -0
- vibe_surf/backend/frontend/assets/link-2-off-DZtuwC5E.js +6 -0
- vibe_surf/backend/frontend/assets/link-DESoaZbo.js +6 -0
- vibe_surf/backend/frontend/assets/linkedin-JjhHmfb4.js +6 -0
- vibe_surf/backend/frontend/assets/list-BrsM64GA.js +6 -0
- vibe_surf/backend/frontend/assets/list-check-CtjFfEK5.js +6 -0
- vibe_surf/backend/frontend/assets/list-checks-DxI2RAHU.js +6 -0
- vibe_surf/backend/frontend/assets/list-collapse-D36HfFAg.js +6 -0
- vibe_surf/backend/frontend/assets/list-end-CnJtPKq2.js +6 -0
- vibe_surf/backend/frontend/assets/list-filter-DQxcz9Im.js +6 -0
- vibe_surf/backend/frontend/assets/list-filter-plus-1zWKh3Nm.js +6 -0
- vibe_surf/backend/frontend/assets/list-minus-CyVCCiP_.js +6 -0
- vibe_surf/backend/frontend/assets/list-music-D2HdEP57.js +6 -0
- vibe_surf/backend/frontend/assets/list-ordered-CI7Q_Z9U.js +6 -0
- vibe_surf/backend/frontend/assets/list-plus-I-ukKH95.js +6 -0
- vibe_surf/backend/frontend/assets/list-restart-BOmwZvpJ.js +6 -0
- vibe_surf/backend/frontend/assets/list-start-s5mFyIxZ.js +6 -0
- vibe_surf/backend/frontend/assets/list-todo-D3I3apKU.js +6 -0
- vibe_surf/backend/frontend/assets/list-tree-dyo6CmDo.js +6 -0
- vibe_surf/backend/frontend/assets/list-video-CDQAsx2G.js +6 -0
- vibe_surf/backend/frontend/assets/list-x-D9NZrtY3.js +6 -0
- vibe_surf/backend/frontend/assets/loader-CZ21EXUH.js +6 -0
- vibe_surf/backend/frontend/assets/loader-circle-BAGc2Gyq.js +6 -0
- vibe_surf/backend/frontend/assets/loader-pinwheel-oc0KDAfx.js +6 -0
- vibe_surf/backend/frontend/assets/locate-fixed-D_gZAi7M.js +6 -0
- vibe_surf/backend/frontend/assets/locate-off-BguB-1e7.js +6 -0
- vibe_surf/backend/frontend/assets/locate-zrCi8zTL.js +6 -0
- vibe_surf/backend/frontend/assets/location-edit-DUKBaV8w.js +6 -0
- vibe_surf/backend/frontend/assets/lock-BIBTiJVb.js +6 -0
- vibe_surf/backend/frontend/assets/lock-keyhole-DfdvlImE.js +6 -0
- vibe_surf/backend/frontend/assets/lock-keyhole-open-BipWMyE2.js +6 -0
- vibe_surf/backend/frontend/assets/lock-open-hTIIUDhX.js +6 -0
- vibe_surf/backend/frontend/assets/log-in-MUY14PK3.js +6 -0
- vibe_surf/backend/frontend/assets/log-out-N9vOM_hV.js +6 -0
- vibe_surf/backend/frontend/assets/logo_dark-_nccwgMn.png +0 -0
- vibe_surf/backend/frontend/assets/logo_light-DKZjS8CD.png +0 -0
- vibe_surf/backend/frontend/assets/logs-xWQAk8xE.js +6 -0
- vibe_surf/backend/frontend/assets/lollipop-BfATjFdL.js +6 -0
- vibe_surf/backend/frontend/assets/luggage-C1usgXJA.js +6 -0
- vibe_surf/backend/frontend/assets/magnet-D4uLriLI.js +6 -0
- vibe_surf/backend/frontend/assets/mail-D1FO7Cd4.js +6 -0
- vibe_surf/backend/frontend/assets/mail-check-Ci8WpRcY.js +6 -0
- vibe_surf/backend/frontend/assets/mail-minus-BLSsQTLT.js +6 -0
- vibe_surf/backend/frontend/assets/mail-open-CDCHTm4u.js +6 -0
- vibe_surf/backend/frontend/assets/mail-plus-B7daS-9R.js +6 -0
- vibe_surf/backend/frontend/assets/mail-question-BOoY5VoI.js +6 -0
- vibe_surf/backend/frontend/assets/mail-search-lWL0T5KM.js +6 -0
- vibe_surf/backend/frontend/assets/mail-warning-C1kPMLkO.js +6 -0
- vibe_surf/backend/frontend/assets/mail-x-BbCGpB0U.js +6 -0
- vibe_surf/backend/frontend/assets/mailbox-BelIMLh1.js +6 -0
- vibe_surf/backend/frontend/assets/mails-XSNGLIg6.js +6 -0
- vibe_surf/backend/frontend/assets/map-BPfRs5M-.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-Bo9rjzwT.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-check-inside-BOCQ9hdx.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-check-lZYfidYB.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-house-BAzpMjxM.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-minus-e1pq_tox.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-minus-inside-bYTcKr95.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-off-COQWPB1x.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-plus-BkWI2rar.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-plus-inside-BROwcC6D.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-x-D2Ku6Hux.js +6 -0
- vibe_surf/backend/frontend/assets/map-pin-x-inside-BgzSyApf.js +6 -0
- vibe_surf/backend/frontend/assets/map-pinned-BujJSPdd.js +6 -0
- vibe_surf/backend/frontend/assets/map-plus-B6j30feS.js +6 -0
- vibe_surf/backend/frontend/assets/mars-DYINnF77.js +6 -0
- vibe_surf/backend/frontend/assets/mars-stroke-CBsC9ZKU.js +6 -0
- vibe_surf/backend/frontend/assets/martini-CXUAUOfs.js +6 -0
- vibe_surf/backend/frontend/assets/maximize-BFF7J1ik.js +6 -0
- vibe_surf/backend/frontend/assets/medal-DgHUWfiy.js +6 -0
- vibe_surf/backend/frontend/assets/megaphone-ChknVYgu.js +6 -0
- vibe_surf/backend/frontend/assets/megaphone-off-B2DuwOZL.js +6 -0
- vibe_surf/backend/frontend/assets/meh-BkI_z7Fm.js +6 -0
- vibe_surf/backend/frontend/assets/memory-stick-jnV8BZ8U.js +6 -0
- vibe_surf/backend/frontend/assets/menu-BGWdm1VM.js +6 -0
- vibe_surf/backend/frontend/assets/merge-0CrgnCFa.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-Nfutonhc.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-code-eh8g5zEn.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-dashed-134APd-i.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-heart-CCfEj0L4.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-more-NvNEYrao.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-off-D9JSF2R5.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-plus-CxUrzbkE.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-question-B1AjvIzW.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-reply-Cq_LGdpm.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-warning-CJZzVFuj.js +6 -0
- vibe_surf/backend/frontend/assets/message-circle-x-CFaT7HUf.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-TdNl2hum.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-code-HRbe8Bot.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-dashed-DV41vJ2v.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-diff-D1P5SKIl.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-dot-CLfBOSjb.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-heart-Cx9wpKea.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-lock-CGv0fUwZ.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-more-BTf56lQh.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-off-CAuO9gJt.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-plus-DIt_XzdR.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-quote-BpZpFxZD.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-reply-CJyI4MAQ.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-share-DARwiA0s.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-text-huSgEB4l.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-warning-BW-imgi9.js +6 -0
- vibe_surf/backend/frontend/assets/message-square-x-DlDleCY5.js +6 -0
- vibe_surf/backend/frontend/assets/messages-square-BdxEbF0a.js +6 -0
- vibe_surf/backend/frontend/assets/mic-B4lpPP8o.js +6 -0
- vibe_surf/backend/frontend/assets/mic-off-BDjkMW2k.js +6 -0
- vibe_surf/backend/frontend/assets/mic-vocal-DjTJgrSN.js +6 -0
- vibe_surf/backend/frontend/assets/microchip-D9WgoQgG.js +6 -0
- vibe_surf/backend/frontend/assets/microscope-DhRdwj9u.js +6 -0
- vibe_surf/backend/frontend/assets/microwave-Cx-cktmw.js +6 -0
- vibe_surf/backend/frontend/assets/milestone-Bn4J2gZ5.js +6 -0
- vibe_surf/backend/frontend/assets/milk-BwNuvCod.js +6 -0
- vibe_surf/backend/frontend/assets/milk-off-B7Czys2l.js +6 -0
- vibe_surf/backend/frontend/assets/minimize-2-Dyq0b2X5.js +6 -0
- vibe_surf/backend/frontend/assets/minimize-DpN4-eh5.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-BMDueoJx.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-check-B0ttZdSb.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-cog-DSEVRX-K.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-dot-C1rbXtsC.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-down-UsHNCHWw.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-off-BWHYFnFW.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-pause-VlURf6A2.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-play-CtvDdBj_.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-smartphone-BVRCMILq.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-speaker-DaVpljSK.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-stop-B1XZqOHJ.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-up-6o6KBdRy.js +6 -0
- vibe_surf/backend/frontend/assets/monitor-x-DkPYSebu.js +6 -0
- vibe_surf/backend/frontend/assets/moon-BxM64e9B.js +6 -0
- vibe_surf/backend/frontend/assets/moon-star-Bn6pq89P.js +6 -0
- vibe_surf/backend/frontend/assets/mountain-Dn-Uh29Q.js +6 -0
- vibe_surf/backend/frontend/assets/mountain-snow-DDguiGic.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-Ccu5uzLi.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-off-DyDEs3d2.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-pointer-2-D09hD9PW.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-pointer-Cv_qu4W9.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-pointer-ban-CyBqBoaN.js +6 -0
- vibe_surf/backend/frontend/assets/mouse-pointer-click-DjkLOlDc.js +6 -0
- vibe_surf/backend/frontend/assets/move-3d-CWvVC7tH.js +6 -0
- vibe_surf/backend/frontend/assets/move-CbFVB4UI.js +6 -0
- vibe_surf/backend/frontend/assets/move-diagonal-2-BJhYv952.js +6 -0
- vibe_surf/backend/frontend/assets/move-diagonal-BpdDHzBj.js +6 -0
- vibe_surf/backend/frontend/assets/move-down-CnVNMo5w.js +6 -0
- vibe_surf/backend/frontend/assets/move-down-left-Cm2dVHob.js +6 -0
- vibe_surf/backend/frontend/assets/move-down-right-DgtW1zsA.js +6 -0
- vibe_surf/backend/frontend/assets/move-horizontal-DEZvvuZ9.js +6 -0
- vibe_surf/backend/frontend/assets/move-left-Bsp9OXAN.js +6 -0
- vibe_surf/backend/frontend/assets/move-right-b3MvEDOZ.js +6 -0
- vibe_surf/backend/frontend/assets/move-up-left-CyLKc6_v.js +6 -0
- vibe_surf/backend/frontend/assets/move-up-q3QjQGGI.js +6 -0
- vibe_surf/backend/frontend/assets/move-up-right-CVzYXW8M.js +6 -0
- vibe_surf/backend/frontend/assets/move-vertical-BLDKghbu.js +6 -0
- vibe_surf/backend/frontend/assets/music-2-Cv7wxsen.js +6 -0
- vibe_surf/backend/frontend/assets/music-3-BAMkh7cd.js +6 -0
- vibe_surf/backend/frontend/assets/music-4-CxEbsNyP.js +6 -0
- vibe_surf/backend/frontend/assets/music-DI2LJ1pr.js +6 -0
- vibe_surf/backend/frontend/assets/navigation-2-CN7e4Syo.js +6 -0
- vibe_surf/backend/frontend/assets/navigation-2-off-Xfvx3297.js +6 -0
- vibe_surf/backend/frontend/assets/navigation-CTZ2PK8B.js +6 -0
- vibe_surf/backend/frontend/assets/navigation-off-CA0_QNZ8.js +6 -0
- vibe_surf/backend/frontend/assets/network-DJgCGMs5.js +6 -0
- vibe_surf/backend/frontend/assets/newspaper-CncK5ZAP.js +6 -0
- vibe_surf/backend/frontend/assets/nfc-DHkaG7f6.js +6 -0
- vibe_surf/backend/frontend/assets/non-binary-DrHfkDpx.js +6 -0
- vibe_surf/backend/frontend/assets/notebook-Bu_56sbo.js +6 -0
- vibe_surf/backend/frontend/assets/notebook-pen-BfNCvEsp.js +6 -0
- vibe_surf/backend/frontend/assets/notebook-tabs-DXKJLdw0.js +6 -0
- vibe_surf/backend/frontend/assets/notebook-text-CLDwqJL4.js +6 -0
- vibe_surf/backend/frontend/assets/notepad-text-BzId44ui.js +6 -0
- vibe_surf/backend/frontend/assets/notepad-text-dashed-C2ifxTJ-.js +6 -0
- vibe_surf/backend/frontend/assets/nut-BflOPXDH.js +6 -0
- vibe_surf/backend/frontend/assets/nut-off-C7f4vuBh.js +6 -0
- vibe_surf/backend/frontend/assets/octagon-Cy5B14LK.js +6 -0
- vibe_surf/backend/frontend/assets/octagon-alert-BQnnyMAR.js +6 -0
- vibe_surf/backend/frontend/assets/octagon-minus-D4t-g_gW.js +6 -0
- vibe_surf/backend/frontend/assets/octagon-pause-D4ADMFHJ.js +6 -0
- vibe_surf/backend/frontend/assets/octagon-x-3lOoF8Wy.js +6 -0
- vibe_surf/backend/frontend/assets/omega-CAb2Yotb.js +6 -0
- vibe_surf/backend/frontend/assets/option-CIxLb5L5.js +6 -0
- vibe_surf/backend/frontend/assets/orbit-Cyp4vT1A.js +6 -0
- vibe_surf/backend/frontend/assets/origami-Bp-6CC8X.js +6 -0
- vibe_surf/backend/frontend/assets/package-2-CF7BAidm.js +6 -0
- vibe_surf/backend/frontend/assets/package-check-DKVi-M6g.js +6 -0
- vibe_surf/backend/frontend/assets/package-dwDgaGhA.js +6 -0
- vibe_surf/backend/frontend/assets/package-minus-mNyMzPhU.js +6 -0
- vibe_surf/backend/frontend/assets/package-open-D4CXb1O6.js +6 -0
- vibe_surf/backend/frontend/assets/package-plus-Dy5MsZf9.js +6 -0
- vibe_surf/backend/frontend/assets/package-search-1aN1Tfbn.js +6 -0
- vibe_surf/backend/frontend/assets/package-x-Br_OiHp7.js +6 -0
- vibe_surf/backend/frontend/assets/paint-bucket-BgqBhtcr.js +6 -0
- vibe_surf/backend/frontend/assets/paint-roller-BKJO-A3W.js +6 -0
- vibe_surf/backend/frontend/assets/paintbrush-Dr3zosPE.js +6 -0
- vibe_surf/backend/frontend/assets/paintbrush-vertical-C_SF0K9Y.js +6 -0
- vibe_surf/backend/frontend/assets/palette-cqdkJAwD.js +6 -0
- vibe_surf/backend/frontend/assets/panel-bottom-close-LR-vRGYT.js +6 -0
- vibe_surf/backend/frontend/assets/panel-bottom-dashed-DZpxppGi.js +6 -0
- vibe_surf/backend/frontend/assets/panel-bottom-open-BIDVhq4g.js +6 -0
- vibe_surf/backend/frontend/assets/panel-bottom-qNgkDPPB.js +6 -0
- vibe_surf/backend/frontend/assets/panel-left-close-jbvRjJyH.js +6 -0
- vibe_surf/backend/frontend/assets/panel-left-dashed-CGafwEEz.js +6 -0
- vibe_surf/backend/frontend/assets/panel-left-open-RdnDP8SA.js +6 -0
- vibe_surf/backend/frontend/assets/panel-right-DG2JkT_r.js +6 -0
- vibe_surf/backend/frontend/assets/panel-right-close-ON0hPuYG.js +6 -0
- vibe_surf/backend/frontend/assets/panel-right-dashed-BWDVhMO-.js +6 -0
- vibe_surf/backend/frontend/assets/panel-right-open-CKshqOyf.js +6 -0
- vibe_surf/backend/frontend/assets/panel-top-Dmxz_Mfs.js +6 -0
- vibe_surf/backend/frontend/assets/panel-top-close-DONOva6Y.js +6 -0
- vibe_surf/backend/frontend/assets/panel-top-dashed-D0pzC4ED.js +6 -0
- vibe_surf/backend/frontend/assets/panel-top-open-u6AKby5v.js +6 -0
- vibe_surf/backend/frontend/assets/panels-left-bottom-_pyxxhnv.js +6 -0
- vibe_surf/backend/frontend/assets/panels-right-bottom-DqdulV5k.js +6 -0
- vibe_surf/backend/frontend/assets/panels-top-left-8p6VuUOb.js +6 -0
- vibe_surf/backend/frontend/assets/paperclip-BlUFsNqR.js +6 -0
- vibe_surf/backend/frontend/assets/parentheses-CRp6hYJ6.js +6 -0
- vibe_surf/backend/frontend/assets/parking-meter-BKs-9jbh.js +6 -0
- vibe_surf/backend/frontend/assets/party-popper-DbzkvAli.js +6 -0
- vibe_surf/backend/frontend/assets/paw-print-BbMlkOEO.js +6 -0
- vibe_surf/backend/frontend/assets/pc-case-BSIAwfze.js +6 -0
- vibe_surf/backend/frontend/assets/pen-D9TSq5aq.js +6 -0
- vibe_surf/backend/frontend/assets/pen-line-C3NzRPd3.js +6 -0
- vibe_surf/backend/frontend/assets/pen-off-D05y9ref.js +6 -0
- vibe_surf/backend/frontend/assets/pen-tool-D9p9RNoA.js +6 -0
- vibe_surf/backend/frontend/assets/pencil-BKpQNzvp.js +6 -0
- vibe_surf/backend/frontend/assets/pencil-line-Bdq6780_.js +6 -0
- vibe_surf/backend/frontend/assets/pencil-off-CZ7lI3k0.js +6 -0
- vibe_surf/backend/frontend/assets/pencil-ruler-D2QniS9D.js +6 -0
- vibe_surf/backend/frontend/assets/pentagon-CL0P-2Be.js +6 -0
- vibe_surf/backend/frontend/assets/percent-BM6Kl-Hu.js +6 -0
- vibe_surf/backend/frontend/assets/person-standing-CpyRtsce.js +6 -0
- vibe_surf/backend/frontend/assets/philippine-peso-D5bFWvtm.js +6 -0
- vibe_surf/backend/frontend/assets/phone-K9-s3Bu6.js +6 -0
- vibe_surf/backend/frontend/assets/phone-call-BMuuoOHh.js +6 -0
- vibe_surf/backend/frontend/assets/phone-forwarded-D-nD-ssq.js +6 -0
- vibe_surf/backend/frontend/assets/phone-incoming-Ct97uBnX.js +6 -0
- vibe_surf/backend/frontend/assets/phone-missed-Dl1yFHA8.js +6 -0
- vibe_surf/backend/frontend/assets/phone-off-CIIiW4DK.js +6 -0
- vibe_surf/backend/frontend/assets/phone-outgoing-Bn21zfLf.js +6 -0
- vibe_surf/backend/frontend/assets/pi-KBaiCIkJ.js +6 -0
- vibe_surf/backend/frontend/assets/piano-Cor-6BQM.js +6 -0
- vibe_surf/backend/frontend/assets/pickaxe-JX5oJ1hy.js +6 -0
- vibe_surf/backend/frontend/assets/picture-in-picture-2-CSmStCZ4.js +6 -0
- vibe_surf/backend/frontend/assets/picture-in-picture-yDdZDNRC.js +6 -0
- vibe_surf/backend/frontend/assets/piggy-bank-D9sTa-am.js +6 -0
- vibe_surf/backend/frontend/assets/pilcrow-B6Aeks47.js +6 -0
- vibe_surf/backend/frontend/assets/pilcrow-left-BQvCcQzh.js +6 -0
- vibe_surf/backend/frontend/assets/pilcrow-right-CrxOjUOh.js +6 -0
- vibe_surf/backend/frontend/assets/pill-DhPudta1.js +6 -0
- vibe_surf/backend/frontend/assets/pill-bottle-BCzORdwx.js +6 -0
- vibe_surf/backend/frontend/assets/pin-MT9TvItb.js +6 -0
- vibe_surf/backend/frontend/assets/pin-off-C4sFwE93.js +6 -0
- vibe_surf/backend/frontend/assets/pipette-BE16X0Zc.js +6 -0
- vibe_surf/backend/frontend/assets/pizza-Cwfm_kaE.js +6 -0
- vibe_surf/backend/frontend/assets/plane-Ct0cOHRo.js +6 -0
- vibe_surf/backend/frontend/assets/plane-landing-Ct4oV7kn.js +6 -0
- vibe_surf/backend/frontend/assets/plane-takeoff-IjpPtaS6.js +6 -0
- vibe_surf/backend/frontend/assets/plug-2-Cn9EdPUM.js +6 -0
- vibe_surf/backend/frontend/assets/plug-pQlGzx_B.js +6 -0
- vibe_surf/backend/frontend/assets/plug-zap-9nF6PFtm.js +6 -0
- vibe_surf/backend/frontend/assets/pocket-3pOTAnEC.js +6 -0
- vibe_surf/backend/frontend/assets/pocket-knife-TKmUVvO9.js +6 -0
- vibe_surf/backend/frontend/assets/podcast-BHXE6S9W.js +6 -0
- vibe_surf/backend/frontend/assets/pointer-BzZXhAOc.js +6 -0
- vibe_surf/backend/frontend/assets/pointer-off-CC5B3RYl.js +6 -0
- vibe_surf/backend/frontend/assets/popcorn-COypVWGN.js +6 -0
- vibe_surf/backend/frontend/assets/popsicle-CmV5g-9P.js +6 -0
- vibe_surf/backend/frontend/assets/pound-sterling-CRW7qDBu.js +6 -0
- vibe_surf/backend/frontend/assets/power-CeN1_ifF.js +6 -0
- vibe_surf/backend/frontend/assets/power-off-DnruOFHO.js +6 -0
- vibe_surf/backend/frontend/assets/presentation-BBhZ1T90.js +6 -0
- vibe_surf/backend/frontend/assets/printer-J_X9y3GJ.js +6 -0
- vibe_surf/backend/frontend/assets/printer-check-Xrof9OPX.js +6 -0
- vibe_surf/backend/frontend/assets/projector-Cr7pbU9O.js +6 -0
- vibe_surf/backend/frontend/assets/proportions-Bt_oONAD.js +6 -0
- vibe_surf/backend/frontend/assets/puzzle-BEB9dtqG.js +6 -0
- vibe_surf/backend/frontend/assets/pyramid-B63D_xCq.js +6 -0
- vibe_surf/backend/frontend/assets/qr-code-DD65EP-q.js +6 -0
- vibe_surf/backend/frontend/assets/quote-DGI0FmFV.js +6 -0
- vibe_surf/backend/frontend/assets/rabbit-BAAJvAQ1.js +6 -0
- vibe_surf/backend/frontend/assets/radar-DiWFjDof.js +6 -0
- vibe_surf/backend/frontend/assets/radiation-6S246_qf.js +6 -0
- vibe_surf/backend/frontend/assets/radical-B4h5Vjr-.js +6 -0
- vibe_surf/backend/frontend/assets/radio-DNjlx2h6.js +6 -0
- vibe_surf/backend/frontend/assets/radio-receiver-DVXCb1C2.js +6 -0
- vibe_surf/backend/frontend/assets/radio-tower-DUKttK3Q.js +6 -0
- vibe_surf/backend/frontend/assets/radius-NH2Pgs7n.js +6 -0
- vibe_surf/backend/frontend/assets/rail-symbol-y_83HZIX.js +6 -0
- vibe_surf/backend/frontend/assets/rainbow-ex4up0y_.js +6 -0
- vibe_surf/backend/frontend/assets/rat-DVSQEhd7.js +6 -0
- vibe_surf/backend/frontend/assets/ratio-Dv-gnu5W.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-DKZm1LWG.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-cent-5S25Pz-Y.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-euro-BtPm6Ent.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-indian-rupee-DUF2ASWh.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-japanese-yen-DYwfBDPz.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-pound-sterling-Dz03w-I-.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-russian-ruble-BPvEoyQB.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-swiss-franc-CE5V9HAu.js +6 -0
- vibe_surf/backend/frontend/assets/receipt-text-4jJUDNZL.js +6 -0
- vibe_surf/backend/frontend/assets/rectangle-ellipsis-CiMEZA-s.js +6 -0
- vibe_surf/backend/frontend/assets/rectangle-goggles-BbvMYFz0.js +6 -0
- vibe_surf/backend/frontend/assets/rectangle-horizontal-BBRMxKxu.js +6 -0
- vibe_surf/backend/frontend/assets/rectangle-vertical-CeoWO5KM.js +6 -0
- vibe_surf/backend/frontend/assets/recycle-BtU0aG4p.js +6 -0
- vibe_surf/backend/frontend/assets/redo-2-DluCWtO8.js +6 -0
- vibe_surf/backend/frontend/assets/redo-D-cP_Hkn.js +6 -0
- vibe_surf/backend/frontend/assets/redo-dot-D3AdCDPV.js +6 -0
- vibe_surf/backend/frontend/assets/refresh-ccw-PanlYmNP.js +6 -0
- vibe_surf/backend/frontend/assets/refresh-ccw-dot-BtKETZVW.js +6 -0
- vibe_surf/backend/frontend/assets/refresh-cw-2F9M9WA-.js +6 -0
- vibe_surf/backend/frontend/assets/refresh-cw-off-DfcoyDb0.js +6 -0
- vibe_surf/backend/frontend/assets/refrigerator-CjKO5bNs.js +6 -0
- vibe_surf/backend/frontend/assets/regex-DSjHOCWp.js +6 -0
- vibe_surf/backend/frontend/assets/remove-formatting-DNhVuOyu.js +6 -0
- vibe_surf/backend/frontend/assets/repeat-1-BWnjf3uj.js +6 -0
- vibe_surf/backend/frontend/assets/repeat-2-DtYtXQSH.js +6 -0
- vibe_surf/backend/frontend/assets/repeat-Bxz0odhG.js +6 -0
- vibe_surf/backend/frontend/assets/replace-BfkipbaZ.js +6 -0
- vibe_surf/backend/frontend/assets/replace-all-PgS4Wej3.js +6 -0
- vibe_surf/backend/frontend/assets/reply-B5lewwtx.js +6 -0
- vibe_surf/backend/frontend/assets/reply-all-0VOGnNa3.js +6 -0
- vibe_surf/backend/frontend/assets/rewind-BP7_fsYl.js +6 -0
- vibe_surf/backend/frontend/assets/ribbon-CCR_MZmZ.js +6 -0
- vibe_surf/backend/frontend/assets/robot-BsccFpqT.png +0 -0
- vibe_surf/backend/frontend/assets/rocket-BvI5E0xM.js +6 -0
- vibe_surf/backend/frontend/assets/rocking-chair-D9ciQaG2.js +6 -0
- vibe_surf/backend/frontend/assets/roller-coaster-CIYjsFvO.js +6 -0
- vibe_surf/backend/frontend/assets/rotate-3d-57_lqlxh.js +6 -0
- vibe_surf/backend/frontend/assets/rotate-ccw-Dv0afAgn.js +6 -0
- vibe_surf/backend/frontend/assets/rotate-ccw-key-BEfjwpDz.js +6 -0
- vibe_surf/backend/frontend/assets/rotate-ccw-square-DQw5wuXQ.js +6 -0
- vibe_surf/backend/frontend/assets/rotate-cw-square-BBVduPLL.js +6 -0
- vibe_surf/backend/frontend/assets/route-Cb5rOsHB.js +6 -0
- vibe_surf/backend/frontend/assets/route-off-DCvXXstI.js +6 -0
- vibe_surf/backend/frontend/assets/router-DY3g0wJU.js +6 -0
- vibe_surf/backend/frontend/assets/rows-2-aV0bv01v.js +6 -0
- vibe_surf/backend/frontend/assets/rows-3-YFUDa1KS.js +6 -0
- vibe_surf/backend/frontend/assets/rows-4---Zyqbpk.js +6 -0
- vibe_surf/backend/frontend/assets/rss-CXFLSLBN.js +6 -0
- vibe_surf/backend/frontend/assets/ruler-DqorlT-h.js +6 -0
- vibe_surf/backend/frontend/assets/ruler-dimension-line-7m0vG2Ir.js +6 -0
- vibe_surf/backend/frontend/assets/russian-ruble-C32P06TU.js +6 -0
- vibe_surf/backend/frontend/assets/sailboat-C0UyBVmA.js +6 -0
- vibe_surf/backend/frontend/assets/salad-DJ2OeKQ0.js +6 -0
- vibe_surf/backend/frontend/assets/sandwich-CWDihFSJ.js +6 -0
- vibe_surf/backend/frontend/assets/satellite-DWJiZMc4.js +6 -0
- vibe_surf/backend/frontend/assets/satellite-dish-CyKhq7bX.js +6 -0
- vibe_surf/backend/frontend/assets/saudi-riyal-CDMN7EuW.js +6 -0
- vibe_surf/backend/frontend/assets/save-Sf21IaPS.js +6 -0
- vibe_surf/backend/frontend/assets/save-all-CazGJB6d.js +6 -0
- vibe_surf/backend/frontend/assets/save-off-ClLS86SR.js +6 -0
- vibe_surf/backend/frontend/assets/scale-3d-BO2k-FAS.js +6 -0
- vibe_surf/backend/frontend/assets/scale-B1BMBPHE.js +6 -0
- vibe_surf/backend/frontend/assets/scaling-6FiHXVNt.js +6 -0
- vibe_surf/backend/frontend/assets/scan-BociKTm7.js +6 -0
- vibe_surf/backend/frontend/assets/scan-barcode-9a0RKd9F.js +6 -0
- vibe_surf/backend/frontend/assets/scan-eye-B4Fq_o4w.js +6 -0
- vibe_surf/backend/frontend/assets/scan-face-CQxrOJRg.js +6 -0
- vibe_surf/backend/frontend/assets/scan-heart-gC97XkVz.js +6 -0
- vibe_surf/backend/frontend/assets/scan-line-QZz3wllu.js +6 -0
- vibe_surf/backend/frontend/assets/scan-qr-code-CL7m0Abc.js +6 -0
- vibe_surf/backend/frontend/assets/scan-search-B5fLui1I.js +6 -0
- vibe_surf/backend/frontend/assets/scan-text-lBsygGB9.js +6 -0
- vibe_surf/backend/frontend/assets/school-CJrzwRC4.js +6 -0
- vibe_surf/backend/frontend/assets/scissors-line-dashed-BE64co8i.js +6 -0
- vibe_surf/backend/frontend/assets/scissors-pEw6Xaqr.js +6 -0
- vibe_surf/backend/frontend/assets/screen-share-BK2OnDwg.js +6 -0
- vibe_surf/backend/frontend/assets/screen-share-off-BXzQiMup.js +6 -0
- vibe_surf/backend/frontend/assets/scroll-DOu3NpFe.js +6 -0
- vibe_surf/backend/frontend/assets/scroll-text-Bkt7Rmng.js +6 -0
- vibe_surf/backend/frontend/assets/search-check-BijeS6tH.js +6 -0
- vibe_surf/backend/frontend/assets/search-code-DwYE8wkC.js +6 -0
- vibe_surf/backend/frontend/assets/search-slash-D0kKoqoN.js +6 -0
- vibe_surf/backend/frontend/assets/search-x-O8nHs6x_.js +6 -0
- vibe_surf/backend/frontend/assets/section-CDcMqQkw.js +6 -0
- vibe_surf/backend/frontend/assets/send-18rqzjQL.js +6 -0
- vibe_surf/backend/frontend/assets/send-horizontal-BlS3LSk8.js +6 -0
- vibe_surf/backend/frontend/assets/send-to-back-pQRkI1lQ.js +6 -0
- vibe_surf/backend/frontend/assets/separator-horizontal-DITxbxBK.js +6 -0
- vibe_surf/backend/frontend/assets/separator-vertical-s3Z8KVZ1.js +6 -0
- vibe_surf/backend/frontend/assets/server-BOW7Qnvk.js +6 -0
- vibe_surf/backend/frontend/assets/server-cog-BXqD_2iC.js +6 -0
- vibe_surf/backend/frontend/assets/server-crash-CdPSdSgW.js +6 -0
- vibe_surf/backend/frontend/assets/server-off-CRJxmnrh.js +6 -0
- vibe_surf/backend/frontend/assets/settings-2-CJHcPvMS.js +6 -0
- vibe_surf/backend/frontend/assets/settings-Bj8QCFrW.js +6 -0
- vibe_surf/backend/frontend/assets/shapes-DE19P8VB.js +6 -0
- vibe_surf/backend/frontend/assets/share-2-D_f9E9OI.js +6 -0
- vibe_surf/backend/frontend/assets/share-Dl2kwbyK.js +6 -0
- vibe_surf/backend/frontend/assets/sheet-D-7Wal14.js +6 -0
- vibe_surf/backend/frontend/assets/shell-CBntfIeY.js +6 -0
- vibe_surf/backend/frontend/assets/shield--hABef9x.js +6 -0
- vibe_surf/backend/frontend/assets/shield-alert-B4tE7sej.js +6 -0
- vibe_surf/backend/frontend/assets/shield-ban-CeAW94aR.js +6 -0
- vibe_surf/backend/frontend/assets/shield-check-BE77dRZh.js +6 -0
- vibe_surf/backend/frontend/assets/shield-ellipsis-09A4HS03.js +6 -0
- vibe_surf/backend/frontend/assets/shield-half-DKJcQwtx.js +6 -0
- vibe_surf/backend/frontend/assets/shield-minus-Bwqn7bCD.js +6 -0
- vibe_surf/backend/frontend/assets/shield-off-CNWzwcox.js +6 -0
- vibe_surf/backend/frontend/assets/shield-plus-DWaKzpCt.js +6 -0
- vibe_surf/backend/frontend/assets/shield-question-D_4Yva8t.js +6 -0
- vibe_surf/backend/frontend/assets/shield-user-B9IXYUW_.js +6 -0
- vibe_surf/backend/frontend/assets/shield-x-CiykLrl6.js +6 -0
- vibe_surf/backend/frontend/assets/ship-BScV8-bd.js +6 -0
- vibe_surf/backend/frontend/assets/ship-wheel-Djpjm-Ds.js +6 -0
- vibe_surf/backend/frontend/assets/shirt-BQYiVewb.js +6 -0
- vibe_surf/backend/frontend/assets/shopping-bag-CHEQVXZe.js +6 -0
- vibe_surf/backend/frontend/assets/shopping-basket-BN8OQ-W2.js +6 -0
- vibe_surf/backend/frontend/assets/shopping-cart-CrWWcNX6.js +6 -0
- vibe_surf/backend/frontend/assets/shovel-OV8umLfu.js +6 -0
- vibe_surf/backend/frontend/assets/shower-head-Bx7v6ZlC.js +6 -0
- vibe_surf/backend/frontend/assets/shredder-DqB2N_G-.js +6 -0
- vibe_surf/backend/frontend/assets/shrimp-uvf6awsH.js +6 -0
- vibe_surf/backend/frontend/assets/shrink-D_H8kRaB.js +6 -0
- vibe_surf/backend/frontend/assets/shrub-CkCwsaYP.js +6 -0
- vibe_surf/backend/frontend/assets/shuffle-Fq0KJO-a.js +6 -0
- vibe_surf/backend/frontend/assets/sigma-BR8bMoDL.js +6 -0
- vibe_surf/backend/frontend/assets/signal-TOctv2i0.js +6 -0
- vibe_surf/backend/frontend/assets/signal-high-u_iVhz3W.js +6 -0
- vibe_surf/backend/frontend/assets/signal-low-CLoQeV0B.js +6 -0
- vibe_surf/backend/frontend/assets/signal-medium-AwY8Ntei.js +6 -0
- vibe_surf/backend/frontend/assets/signal-zero-BEXPbo5k.js +6 -0
- vibe_surf/backend/frontend/assets/signature-Cgbo04nK.js +6 -0
- vibe_surf/backend/frontend/assets/signpost-BumCuKy8.js +6 -0
- vibe_surf/backend/frontend/assets/signpost-big-BRDDJu7l.js +6 -0
- vibe_surf/backend/frontend/assets/siren-Dmc1QgzA.js +6 -0
- vibe_surf/backend/frontend/assets/skip-back-DYGAhVaZ.js +6 -0
- vibe_surf/backend/frontend/assets/skip-forward-Cmo14QdF.js +6 -0
- vibe_surf/backend/frontend/assets/skull-C7f59NOY.js +6 -0
- vibe_surf/backend/frontend/assets/slack-BZCH_jmq.js +6 -0
- vibe_surf/backend/frontend/assets/slash-D508NrMk.js +6 -0
- vibe_surf/backend/frontend/assets/slice-X7STCda9.js +6 -0
- vibe_surf/backend/frontend/assets/sliders-horizontal-CfzazJ4Z.js +6 -0
- vibe_surf/backend/frontend/assets/sliders-vertical-CDP8j0-D.js +6 -0
- vibe_surf/backend/frontend/assets/smartphone-charging-BbvzdjcK.js +6 -0
- vibe_surf/backend/frontend/assets/smartphone-nfc-BUwpyAe9.js +6 -0
- vibe_surf/backend/frontend/assets/smartphone-vlXaYd7G.js +6 -0
- vibe_surf/backend/frontend/assets/smile-WIoPOV75.js +6 -0
- vibe_surf/backend/frontend/assets/smile-plus-C7_2KI6t.js +6 -0
- vibe_surf/backend/frontend/assets/snail-DiXb1jdv.js +6 -0
- vibe_surf/backend/frontend/assets/snowflake-DbaQxR5F.js +6 -0
- vibe_surf/backend/frontend/assets/sofa-3gaNXRHk.js +6 -0
- vibe_surf/backend/frontend/assets/soup-BJWMbLNe.js +6 -0
- vibe_surf/backend/frontend/assets/space-BgZ7M3kc.js +6 -0
- vibe_surf/backend/frontend/assets/spade-DmCswPx6.js +6 -0
- vibe_surf/backend/frontend/assets/sparkle-BcIeelqq.js +6 -0
- vibe_surf/backend/frontend/assets/sparkles-EZvTd48X.js +6 -0
- vibe_surf/backend/frontend/assets/speaker-cy8pASlT.js +6 -0
- vibe_surf/backend/frontend/assets/speech-D2DBEjZh.js +6 -0
- vibe_surf/backend/frontend/assets/spell-check-2-CT6j-nnq.js +6 -0
- vibe_surf/backend/frontend/assets/spell-check-BLpw53aW.js +6 -0
- vibe_surf/backend/frontend/assets/spline-Dj4_WV_J.js +6 -0
- vibe_surf/backend/frontend/assets/spline-pointer-B70ZX6Jx.js +6 -0
- vibe_surf/backend/frontend/assets/split-BUN_2DPl.js +6 -0
- vibe_surf/backend/frontend/assets/spray-can--CM3S7I1.js +6 -0
- vibe_surf/backend/frontend/assets/sprout-DHRMaLE1.js +6 -0
- vibe_surf/backend/frontend/assets/square-D8mSOgWq.js +6 -0
- vibe_surf/backend/frontend/assets/square-activity-HHBbub6x.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-down-DNqGulvF.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-down-left-mkEWcF4d.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-down-right-BWWZbJCm.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-left-DJJcrIld.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-out-down-left-C4KWrLml.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-out-down-right-CDptR_XX.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-out-up-left-BwHPp6UO.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-out-up-right-tzaptCUV.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-right-DVcoFdqS.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-up-BupGJOnJ.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-up-left-w635cnEo.js +6 -0
- vibe_surf/backend/frontend/assets/square-arrow-up-right-C1ac-f2n.js +6 -0
- vibe_surf/backend/frontend/assets/square-asterisk-D6Cym7Xv.js +6 -0
- vibe_surf/backend/frontend/assets/square-bottom-dashed-scissors-BVNT9RSH.js +6 -0
- vibe_surf/backend/frontend/assets/square-chart-gantt-C3dcJ6sg.js +6 -0
- vibe_surf/backend/frontend/assets/square-check-S6hpNtFK.js +6 -0
- vibe_surf/backend/frontend/assets/square-check-big-D9upq6ft.js +6 -0
- vibe_surf/backend/frontend/assets/square-chevron-down-BA97_sqV.js +6 -0
- vibe_surf/backend/frontend/assets/square-chevron-left-CLiOdSzb.js +6 -0
- vibe_surf/backend/frontend/assets/square-chevron-right-t-igHrA_.js +6 -0
- vibe_surf/backend/frontend/assets/square-chevron-up-CbvwXecv.js +6 -0
- vibe_surf/backend/frontend/assets/square-code-DUqDccm-.js +6 -0
- vibe_surf/backend/frontend/assets/square-dashed-DAZVB5Ow.js +6 -0
- vibe_surf/backend/frontend/assets/square-dashed-bottom-DIHrivbQ.js +6 -0
- vibe_surf/backend/frontend/assets/square-dashed-bottom-code-BurWoYrF.js +6 -0
- vibe_surf/backend/frontend/assets/square-dashed-kanban-DJ3Nf0yW.js +6 -0
- vibe_surf/backend/frontend/assets/square-dashed-mouse-pointer-D83fN529.js +6 -0
- vibe_surf/backend/frontend/assets/square-divide-DfK2w5k3.js +6 -0
- vibe_surf/backend/frontend/assets/square-dot-E08KHmsT.js +6 -0
- vibe_surf/backend/frontend/assets/square-equal-DmilLTYr.js +6 -0
- vibe_surf/backend/frontend/assets/square-function-Bmr5-y7k.js +6 -0
- vibe_surf/backend/frontend/assets/square-kanban-C_Y3PzRd.js +6 -0
- vibe_surf/backend/frontend/assets/square-library-Bljg4ak_.js +6 -0
- vibe_surf/backend/frontend/assets/square-m-Bm5eCYFz.js +6 -0
- vibe_surf/backend/frontend/assets/square-menu-2PwZ-t8v.js +6 -0
- vibe_surf/backend/frontend/assets/square-minus-DB2rsSIh.js +6 -0
- vibe_surf/backend/frontend/assets/square-mouse-pointer-Yggd861r.js +6 -0
- vibe_surf/backend/frontend/assets/square-parking-0BMseCWh.js +6 -0
- vibe_surf/backend/frontend/assets/square-parking-off-wL1Aoald.js +6 -0
- vibe_surf/backend/frontend/assets/square-pen-DUgkyJvx.js +6 -0
- vibe_surf/backend/frontend/assets/square-percent-D1N2DxXQ.js +6 -0
- vibe_surf/backend/frontend/assets/square-pi-BAB-yOqi.js +6 -0
- vibe_surf/backend/frontend/assets/square-pilcrow-YTTQD0YQ.js +6 -0
- vibe_surf/backend/frontend/assets/square-play-D0CcTkr2.js +6 -0
- vibe_surf/backend/frontend/assets/square-plus-BdjiqtXM.js +6 -0
- vibe_surf/backend/frontend/assets/square-power-8LY4_Isa.js +6 -0
- vibe_surf/backend/frontend/assets/square-radical-DC1m2SHK.js +6 -0
- vibe_surf/backend/frontend/assets/square-round-corner-CYVVFjQx.js +6 -0
- vibe_surf/backend/frontend/assets/square-scissors-BZUPjoru.js +6 -0
- vibe_surf/backend/frontend/assets/square-sigma-CTgs2Ekn.js +6 -0
- vibe_surf/backend/frontend/assets/square-slash-DoZz--aG.js +6 -0
- vibe_surf/backend/frontend/assets/square-split-horizontal-C5VA-YKL.js +6 -0
- vibe_surf/backend/frontend/assets/square-split-vertical-br-5Oe8V.js +6 -0
- vibe_surf/backend/frontend/assets/square-square-D-S2fMQV.js +6 -0
- vibe_surf/backend/frontend/assets/square-stack-BpnJ--p7.js +6 -0
- vibe_surf/backend/frontend/assets/square-terminal-D1xyM5zr.js +6 -0
- vibe_surf/backend/frontend/assets/square-user-BM_UbMq8.js +6 -0
- vibe_surf/backend/frontend/assets/square-user-round-BjbE9Ex0.js +6 -0
- vibe_surf/backend/frontend/assets/square-x-ndOAHZyv.js +6 -0
- vibe_surf/backend/frontend/assets/squares-exclude-i1Cuf4eN.js +6 -0
- vibe_surf/backend/frontend/assets/squares-intersect-B_KkkCiA.js +6 -0
- vibe_surf/backend/frontend/assets/squares-subtract-0Gqt-l9r.js +6 -0
- vibe_surf/backend/frontend/assets/squares-unite-fFpeFJy_.js +6 -0
- vibe_surf/backend/frontend/assets/squircle-BWK1XIab.js +6 -0
- vibe_surf/backend/frontend/assets/squirrel-BemFtLhO.js +6 -0
- vibe_surf/backend/frontend/assets/stamp-n1s-2-vi.js +6 -0
- vibe_surf/backend/frontend/assets/star-JqPDEQO0.js +6 -0
- vibe_surf/backend/frontend/assets/star-half-Ctp-6K3f.js +6 -0
- vibe_surf/backend/frontend/assets/star-off-DTrat8iZ.js +6 -0
- vibe_surf/backend/frontend/assets/step-back-_f3vl_Mc.js +6 -0
- vibe_surf/backend/frontend/assets/step-forward-U0c2umRC.js +6 -0
- vibe_surf/backend/frontend/assets/stethoscope-BcOEujBx.js +6 -0
- vibe_surf/backend/frontend/assets/sticker-BUUkREla.js +6 -0
- vibe_surf/backend/frontend/assets/sticky-note-Dau-uEqX.js +6 -0
- vibe_surf/backend/frontend/assets/store-CDDYJAqq.js +6 -0
- vibe_surf/backend/frontend/assets/stretch-horizontal-C7d6gxZ-.js +6 -0
- vibe_surf/backend/frontend/assets/stretch-vertical-DwZ7L62M.js +6 -0
- vibe_surf/backend/frontend/assets/strikethrough-tErW_78t.js +6 -0
- vibe_surf/backend/frontend/assets/subscript-AEnn7z1-.js +6 -0
- vibe_surf/backend/frontend/assets/sun-CUhBOUww.js +6 -0
- vibe_surf/backend/frontend/assets/sun-dim-mjCyc7b-.js +6 -0
- vibe_surf/backend/frontend/assets/sun-medium-BlmZvs1P.js +6 -0
- vibe_surf/backend/frontend/assets/sun-moon-DNDzmGy_.js +6 -0
- vibe_surf/backend/frontend/assets/sun-snow-btXFhvOs.js +6 -0
- vibe_surf/backend/frontend/assets/sunrise-BPn0BvIU.js +6 -0
- vibe_surf/backend/frontend/assets/sunset-Bn6AsuaW.js +6 -0
- vibe_surf/backend/frontend/assets/superscript-CCWWx6fn.js +6 -0
- vibe_surf/backend/frontend/assets/swatch-book-DAO0_j5l.js +6 -0
- vibe_surf/backend/frontend/assets/swiss-franc-DvPAMwVi.js +6 -0
- vibe_surf/backend/frontend/assets/switch-camera-DDK45wsa.js +6 -0
- vibe_surf/backend/frontend/assets/sword-CdjQ03Nx.js +6 -0
- vibe_surf/backend/frontend/assets/swords-DwnTqFFL.js +6 -0
- vibe_surf/backend/frontend/assets/syringe-DMHMk3I_.js +6 -0
- vibe_surf/backend/frontend/assets/table-2-fXlN5mfo.js +6 -0
- vibe_surf/backend/frontend/assets/table-DywCQdAx.js +6 -0
- vibe_surf/backend/frontend/assets/table-cells-merge-1rBoZbUH.js +6 -0
- vibe_surf/backend/frontend/assets/table-cells-split-DvDXy8Zk.js +6 -0
- vibe_surf/backend/frontend/assets/table-columns-split-5lVHYUrA.js +6 -0
- vibe_surf/backend/frontend/assets/table-of-contents-CiE6KpvH.js +6 -0
- vibe_surf/backend/frontend/assets/table-properties-C5MLGyyn.js +6 -0
- vibe_surf/backend/frontend/assets/table-rows-split-6tWPhAGA.js +6 -0
- vibe_surf/backend/frontend/assets/tablet-onVj1N8V.js +6 -0
- vibe_surf/backend/frontend/assets/tablet-smartphone-Dy1zcLBR.js +6 -0
- vibe_surf/backend/frontend/assets/tablets-TV4RvSqQ.js +6 -0
- vibe_surf/backend/frontend/assets/tag-COdo6PC1.js +6 -0
- vibe_surf/backend/frontend/assets/tags-C_PyXxvo.js +6 -0
- vibe_surf/backend/frontend/assets/tally-1-TLUCkMfT.js +6 -0
- vibe_surf/backend/frontend/assets/tally-2-40s-WtRw.js +6 -0
- vibe_surf/backend/frontend/assets/tally-3-Cr7c6JyQ.js +6 -0
- vibe_surf/backend/frontend/assets/tally-4-CgMb3kf-.js +6 -0
- vibe_surf/backend/frontend/assets/tally-5-BYhkAnpk.js +6 -0
- vibe_surf/backend/frontend/assets/tangent-Cch1S25B.js +6 -0
- vibe_surf/backend/frontend/assets/target-BxbxOJBi.js +6 -0
- vibe_surf/backend/frontend/assets/telescope-DB7CDRtv.js +6 -0
- vibe_surf/backend/frontend/assets/temp-pat-1-BDqu2wpz.png +0 -0
- vibe_surf/backend/frontend/assets/temp-pat-2-C_RVvOE_.png +0 -0
- vibe_surf/backend/frontend/assets/temp-pat-3-Ci-rp5-q.png +0 -0
- vibe_surf/backend/frontend/assets/temp-pat-m-1-D-qJT-j4.png +0 -0
- vibe_surf/backend/frontend/assets/temp-pat-m-2-BFhrICvh.png +0 -0
- vibe_surf/backend/frontend/assets/temp-pat-m-3-BJIIbDxb.png +0 -0
- vibe_surf/backend/frontend/assets/tent-CipD8dRg.js +6 -0
- vibe_surf/backend/frontend/assets/tent-tree-HUvCq3o8.js +6 -0
- vibe_surf/backend/frontend/assets/terminal-CfniKHGt.js +6 -0
- vibe_surf/backend/frontend/assets/test-tube-DcBZWnPV.js +6 -0
- vibe_surf/backend/frontend/assets/test-tube-diagonal-DLDAq2x-.js +6 -0
- vibe_surf/backend/frontend/assets/test-tubes-DEqLhART.js +6 -0
- vibe_surf/backend/frontend/assets/text-CjNHL8YY.js +6 -0
- vibe_surf/backend/frontend/assets/text-cursor-Bfyx77E0.js +6 -0
- vibe_surf/backend/frontend/assets/text-cursor-input-DEntniNC.js +6 -0
- vibe_surf/backend/frontend/assets/text-quote-CuHDE9wz.js +6 -0
- vibe_surf/backend/frontend/assets/text-search-BVoMtXGi.js +6 -0
- vibe_surf/backend/frontend/assets/text-select-C5UoP5L8.js +6 -0
- vibe_surf/backend/frontend/assets/theater-5p2oJrBR.js +6 -0
- vibe_surf/backend/frontend/assets/thermometer-UK9pmYRI.js +6 -0
- vibe_surf/backend/frontend/assets/thermometer-snowflake-kQI9FMjj.js +6 -0
- vibe_surf/backend/frontend/assets/thermometer-sun-DFR8N7SP.js +6 -0
- vibe_surf/backend/frontend/assets/thumbs-down-D9fAJ2gG.js +6 -0
- vibe_surf/backend/frontend/assets/thumbs-up-DoKS_oaD.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-Cesz_aOn.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-check-hrSzboJJ.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-minus-DSlyjy1m.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-percent-B1fhQdh4.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-plus-Dimk4-uQ.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-slash-BbNYJCVm.js +6 -0
- vibe_surf/backend/frontend/assets/ticket-x-DZmFrk6f.js +6 -0
- vibe_surf/backend/frontend/assets/tickets-oFgC5KK5.js +6 -0
- vibe_surf/backend/frontend/assets/tickets-plane-7zFRiAsP.js +6 -0
- vibe_surf/backend/frontend/assets/timer-Dus7G8uq.js +6 -0
- vibe_surf/backend/frontend/assets/timer-off-DwuoxoCG.js +6 -0
- vibe_surf/backend/frontend/assets/timer-reset-6QQ9CB1x.js +6 -0
- vibe_surf/backend/frontend/assets/toggle-left-CP39bKF1.js +6 -0
- vibe_surf/backend/frontend/assets/toggle-right-BKQovK3O.js +6 -0
- vibe_surf/backend/frontend/assets/toilet-BBNGmlkm.js +6 -0
- vibe_surf/backend/frontend/assets/tornado-CmCC8lkh.js +6 -0
- vibe_surf/backend/frontend/assets/torus-DksvYfUU.js +6 -0
- vibe_surf/backend/frontend/assets/touchpad-B_iE1cT_.js +6 -0
- vibe_surf/backend/frontend/assets/touchpad-off-C3NRWKvk.js +6 -0
- vibe_surf/backend/frontend/assets/tower-control-C9XxmqPK.js +6 -0
- vibe_surf/backend/frontend/assets/toy-brick-BAWK5m2R.js +6 -0
- vibe_surf/backend/frontend/assets/tractor-ZemWoG5M.js +6 -0
- vibe_surf/backend/frontend/assets/traffic-cone-CQQptVNY.js +6 -0
- vibe_surf/backend/frontend/assets/train-front-C6IEoUQj.js +6 -0
- vibe_surf/backend/frontend/assets/train-front-tunnel-CRzVUubn.js +6 -0
- vibe_surf/backend/frontend/assets/train-track-DQ1Jx75q.js +6 -0
- vibe_surf/backend/frontend/assets/tram-front-CKDE6nBl.js +6 -0
- vibe_surf/backend/frontend/assets/transgender-DRQWjJQq.js +6 -0
- vibe_surf/backend/frontend/assets/trash-C7FJQWXt.js +6 -0
- vibe_surf/backend/frontend/assets/tree-deciduous-C_NdJWmQ.js +6 -0
- vibe_surf/backend/frontend/assets/tree-palm-rAQ0YuEF.js +6 -0
- vibe_surf/backend/frontend/assets/tree-pine-BC-4ht4p.js +6 -0
- vibe_surf/backend/frontend/assets/trees-Br8pDJw0.js +6 -0
- vibe_surf/backend/frontend/assets/trello-BQynNo87.js +6 -0
- vibe_surf/backend/frontend/assets/trending-down-m6hdRTZC.js +6 -0
- vibe_surf/backend/frontend/assets/trending-up-DEzTc77q.js +6 -0
- vibe_surf/backend/frontend/assets/trending-up-down-CdmVa8T1.js +6 -0
- vibe_surf/backend/frontend/assets/triangle-DxElnb7f.js +6 -0
- vibe_surf/backend/frontend/assets/triangle-alert-BmgW8WWD.js +6 -0
- vibe_surf/backend/frontend/assets/triangle-dashed-fyl8Ux-f.js +6 -0
- vibe_surf/backend/frontend/assets/triangle-right-Bn5gxIA-.js +6 -0
- vibe_surf/backend/frontend/assets/trophy-gb1-2rUo.js +6 -0
- vibe_surf/backend/frontend/assets/truck-CyEUIB3S.js +6 -0
- vibe_surf/backend/frontend/assets/truck-electric-C_IB9gt8.js +6 -0
- vibe_surf/backend/frontend/assets/turtle-JiowR0Q_.js +6 -0
- vibe_surf/backend/frontend/assets/tv-B0tAK-iR.js +6 -0
- vibe_surf/backend/frontend/assets/tv-minimal-BzNmtVcb.js +6 -0
- vibe_surf/backend/frontend/assets/tv-minimal-play-DY3HMhTZ.js +6 -0
- vibe_surf/backend/frontend/assets/twitch-X3gysvi1.js +6 -0
- vibe_surf/backend/frontend/assets/twitter-DgWlCFbw.js +6 -0
- vibe_surf/backend/frontend/assets/type-CbzhcXZj.js +6 -0
- vibe_surf/backend/frontend/assets/type-outline-EJOgqfeY.js +6 -0
- vibe_surf/backend/frontend/assets/umbrella-2CrWS8G9.js +6 -0
- vibe_surf/backend/frontend/assets/umbrella-off-wnubYDr5.js +6 -0
- vibe_surf/backend/frontend/assets/underline-kox2pBOb.js +6 -0
- vibe_surf/backend/frontend/assets/undo-2-CMFxk0AM.js +6 -0
- vibe_surf/backend/frontend/assets/undo-BB6rCcPu.js +6 -0
- vibe_surf/backend/frontend/assets/undo-dot-PizHjiGF.js +6 -0
- vibe_surf/backend/frontend/assets/unfold-horizontal-DJYCPLbF.js +6 -0
- vibe_surf/backend/frontend/assets/unfold-vertical-xsaYrtue.js +6 -0
- vibe_surf/backend/frontend/assets/ungroup-COP2DC2I.js +6 -0
- vibe_surf/backend/frontend/assets/university-Bydtu_C0.js +6 -0
- vibe_surf/backend/frontend/assets/unlink-2-CGh6udmI.js +6 -0
- vibe_surf/backend/frontend/assets/unlink-Cl0N-H5R.js +6 -0
- vibe_surf/backend/frontend/assets/unplug-CvUy0kbs.js +6 -0
- vibe_surf/backend/frontend/assets/upload-CsiQhdGb.js +6 -0
- vibe_surf/backend/frontend/assets/usb-DgJciZ8D.js +6 -0
- vibe_surf/backend/frontend/assets/use-post-add-user-X-JStdcv.js +1 -0
- vibe_surf/backend/frontend/assets/user-check-oTj-oMD1.js +6 -0
- vibe_surf/backend/frontend/assets/user-cog-De5lo6V4.js +6 -0
- vibe_surf/backend/frontend/assets/user-lock-Cd6PZI_W.js +6 -0
- vibe_surf/backend/frontend/assets/user-minus-Bk4X5ZEo.js +6 -0
- vibe_surf/backend/frontend/assets/user-pen-DdI66MUk.js +6 -0
- vibe_surf/backend/frontend/assets/user-plus-CU5763YF.js +6 -0
- vibe_surf/backend/frontend/assets/user-rQhBQtW6.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-Balh9Ngi.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-check-CNnGyjh3.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-cog-cytI9ohB.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-minus-BPLiMNlF.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-pen-DYmI1nrr.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-plus-vC9pdrP-.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-search-B7B-daNE.js +6 -0
- vibe_surf/backend/frontend/assets/user-round-x-DyuI5YoS.js +6 -0
- vibe_surf/backend/frontend/assets/user-search-BKYbqUOf.js +6 -0
- vibe_surf/backend/frontend/assets/user-x-DJ3ciRY5.js +6 -0
- vibe_surf/backend/frontend/assets/users-BuFcoxWH.js +6 -0
- vibe_surf/backend/frontend/assets/users-round-Bmf9zVDL.js +6 -0
- vibe_surf/backend/frontend/assets/utensils-DbpPXdpJ.js +6 -0
- vibe_surf/backend/frontend/assets/utensils-crossed-aDCkAivJ.js +6 -0
- vibe_surf/backend/frontend/assets/utility-pole-Bc7lymCy.js +6 -0
- vibe_surf/backend/frontend/assets/vanilla-picker-B6E6ObS_.js +8 -0
- vibe_surf/backend/frontend/assets/variable-DyXUbeWo.js +6 -0
- vibe_surf/backend/frontend/assets/vault-BBLLA0yD.js +6 -0
- vibe_surf/backend/frontend/assets/vegan-DkXrMg_9.js +6 -0
- vibe_surf/backend/frontend/assets/venetian-mask-DSF__6pM.js +6 -0
- vibe_surf/backend/frontend/assets/venus-BqrM2Wbm.js +6 -0
- vibe_surf/backend/frontend/assets/venus-and-mars-CocpgQS_.js +6 -0
- vibe_surf/backend/frontend/assets/vibrate-CSaEPSAw.js +6 -0
- vibe_surf/backend/frontend/assets/vibrate-off-BkeOYWie.js +6 -0
- vibe_surf/backend/frontend/assets/video-CDDAj1Mz.js +6 -0
- vibe_surf/backend/frontend/assets/video-off-BSlBZ5ca.js +6 -0
- vibe_surf/backend/frontend/assets/videotape-ChK7t0IE.js +6 -0
- vibe_surf/backend/frontend/assets/view-BTeYNd7e.js +6 -0
- vibe_surf/backend/frontend/assets/voicemail-DXRJxFC2.js +6 -0
- vibe_surf/backend/frontend/assets/volleyball-0jePXF2X.js +6 -0
- vibe_surf/backend/frontend/assets/volume-1-CBKuT4gx.js +6 -0
- vibe_surf/backend/frontend/assets/volume-CJ3kb1UJ.js +6 -0
- vibe_surf/backend/frontend/assets/volume-off-Drh6kI0N.js +6 -0
- vibe_surf/backend/frontend/assets/vote-D7rR24Uv.js +6 -0
- vibe_surf/backend/frontend/assets/wallet-cards-BmUXKVPo.js +6 -0
- vibe_surf/backend/frontend/assets/wallet-minimal-CfQ29GXX.js +6 -0
- vibe_surf/backend/frontend/assets/wallet-odbnitLx.js +6 -0
- vibe_surf/backend/frontend/assets/wallpaper--aY9LRKu.js +6 -0
- vibe_surf/backend/frontend/assets/wand-XfMLbt7W.js +6 -0
- vibe_surf/backend/frontend/assets/wand-sparkles-EKZGPSQU.js +6 -0
- vibe_surf/backend/frontend/assets/warehouse-CQb33kTK.js +6 -0
- vibe_surf/backend/frontend/assets/washing-machine-BcdChWag.js +6 -0
- vibe_surf/backend/frontend/assets/watch-BAxj0MpS.js +6 -0
- vibe_surf/backend/frontend/assets/waves-DSxAAEDo.js +6 -0
- vibe_surf/backend/frontend/assets/waves-ladder-CQM5bq9O.js +6 -0
- vibe_surf/backend/frontend/assets/waypoints-X-1I6GAF.js +6 -0
- vibe_surf/backend/frontend/assets/webcam-D0M9jAcy.js +6 -0
- vibe_surf/backend/frontend/assets/webhook-B4-tv0Ay.js +6 -0
- vibe_surf/backend/frontend/assets/webhook-off-DgBYoB9w.js +6 -0
- vibe_surf/backend/frontend/assets/weight-CbJjMaGD.js +6 -0
- vibe_surf/backend/frontend/assets/wheat-DRqMfslQ.js +6 -0
- vibe_surf/backend/frontend/assets/wheat-off-DN3CMot9.js +6 -0
- vibe_surf/backend/frontend/assets/whole-word-rys0-nDs.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-B6YlXqZQ.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-high-BN7s1tEO.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-low-DqS_NT9C.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-off-CRhK1VN6.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-pen-gMAH3nO9.js +6 -0
- vibe_surf/backend/frontend/assets/wifi-zero-CL35Rk1s.js +6 -0
- vibe_surf/backend/frontend/assets/wind-CABDXl30.js +6 -0
- vibe_surf/backend/frontend/assets/wind-arrow-down-CCe6Rj-A.js +6 -0
- vibe_surf/backend/frontend/assets/wine-CADKMVqu.js +6 -0
- vibe_surf/backend/frontend/assets/wine-off-DKIC96cS.js +6 -0
- vibe_surf/backend/frontend/assets/workflow-l7VJgDwH.js +6 -0
- vibe_surf/backend/frontend/assets/worm-Bd0iMQEP.js +6 -0
- vibe_surf/backend/frontend/assets/wrap-text-Cunt4p5D.js +6 -0
- vibe_surf/backend/frontend/assets/wrench-dRH2B7Yl.js +6 -0
- vibe_surf/backend/frontend/assets/youtube-DMk3ysts.js +6 -0
- vibe_surf/backend/frontend/assets/zap-DLlvIcB2.js +6 -0
- vibe_surf/backend/frontend/assets/zap-off-Bxyq6wwx.js +6 -0
- vibe_surf/backend/frontend/favicon.ico +0 -0
- vibe_surf/backend/frontend/index.html +24 -0
- vibe_surf/backend/frontend/manifest.json +31 -0
- vibe_surf/backend/llm_config.py +225 -0
- vibe_surf/backend/main.py +793 -0
- vibe_surf/backend/shared_state.py +1110 -0
- vibe_surf/backend/utils/__init__.py +7 -0
- vibe_surf/backend/utils/encryption.py +172 -0
- vibe_surf/backend/utils/llm_factory.py +274 -0
- vibe_surf/backend/utils/utils.py +42 -0
- vibe_surf/backend/utils/workflow_converter.py +570 -0
- vibe_surf/backend/voice_model_config.py +25 -0
- vibe_surf/browser/__init__.py +8 -0
- vibe_surf/browser/agen_browser_profile.py +136 -0
- vibe_surf/browser/agent_browser_session.py +1244 -0
- vibe_surf/browser/browser_manager.py +268 -0
- vibe_surf/browser/find_page_element.py +1100 -0
- vibe_surf/browser/page_operations.py +222 -0
- vibe_surf/browser/utils.py +785 -0
- vibe_surf/browser/watchdogs/__init__.py +0 -0
- vibe_surf/browser/watchdogs/action_watchdog.py +109 -0
- vibe_surf/browser/watchdogs/dom_watchdog.py +249 -0
- vibe_surf/chrome_extension/background.js +908 -0
- vibe_surf/chrome_extension/config.js +56 -0
- vibe_surf/chrome_extension/content.js +745 -0
- vibe_surf/chrome_extension/dev-reload.js +47 -0
- vibe_surf/chrome_extension/icons/logo.icns +0 -0
- vibe_surf/chrome_extension/icons/logo.png +0 -0
- vibe_surf/chrome_extension/manifest.json +70 -0
- vibe_surf/chrome_extension/permission-iframe.html +38 -0
- vibe_surf/chrome_extension/permission-request.html +104 -0
- vibe_surf/chrome_extension/popup.html +134 -0
- vibe_surf/chrome_extension/scripts/api-client.js +755 -0
- vibe_surf/chrome_extension/scripts/file-manager.js +523 -0
- vibe_surf/chrome_extension/scripts/history-manager.js +658 -0
- vibe_surf/chrome_extension/scripts/main.js +547 -0
- vibe_surf/chrome_extension/scripts/markdown-it.min.js +3 -0
- vibe_surf/chrome_extension/scripts/modal-manager.js +496 -0
- vibe_surf/chrome_extension/scripts/news-carousel.js +543 -0
- vibe_surf/chrome_extension/scripts/permission-iframe-request.js +188 -0
- vibe_surf/chrome_extension/scripts/permission-request.js +118 -0
- vibe_surf/chrome_extension/scripts/session-manager.js +800 -0
- vibe_surf/chrome_extension/scripts/settings-general.js +483 -0
- vibe_surf/chrome_extension/scripts/settings-integrations.js +998 -0
- vibe_surf/chrome_extension/scripts/settings-manager.js +275 -0
- vibe_surf/chrome_extension/scripts/settings-profiles.js +1330 -0
- vibe_surf/chrome_extension/scripts/settings-workflow.js +3530 -0
- vibe_surf/chrome_extension/scripts/ui-manager.js +3799 -0
- vibe_surf/chrome_extension/scripts/user-settings-storage.js +422 -0
- vibe_surf/chrome_extension/scripts/version.js +3 -0
- vibe_surf/chrome_extension/scripts/voice-recorder.js +514 -0
- vibe_surf/chrome_extension/scripts/workflow-recorder.js +651 -0
- vibe_surf/chrome_extension/sidepanel.html +1200 -0
- vibe_surf/chrome_extension/styles/activity.css +934 -0
- vibe_surf/chrome_extension/styles/animations.css +471 -0
- vibe_surf/chrome_extension/styles/base.css +76 -0
- vibe_surf/chrome_extension/styles/components.css +1044 -0
- vibe_surf/chrome_extension/styles/history-modal.css +791 -0
- vibe_surf/chrome_extension/styles/input.css +760 -0
- vibe_surf/chrome_extension/styles/layout.css +247 -0
- vibe_surf/chrome_extension/styles/news-carousel.css +530 -0
- vibe_surf/chrome_extension/styles/responsive.css +454 -0
- vibe_surf/chrome_extension/styles/settings-environment.css +303 -0
- vibe_surf/chrome_extension/styles/settings-forms.css +389 -0
- vibe_surf/chrome_extension/styles/settings-integrations.css +945 -0
- vibe_surf/chrome_extension/styles/settings-modal.css +145 -0
- vibe_surf/chrome_extension/styles/settings-profiles.css +244 -0
- vibe_surf/chrome_extension/styles/settings-responsive.css +176 -0
- vibe_surf/chrome_extension/styles/settings-utilities.css +25 -0
- vibe_surf/chrome_extension/styles/settings-workflow.css +3013 -0
- vibe_surf/chrome_extension/styles/variables.css +105 -0
- vibe_surf/cli.py +562 -0
- vibe_surf/common.py +35 -0
- vibe_surf/langflow/__init__.py +0 -0
- vibe_surf/langflow/__main__.py +954 -0
- vibe_surf/langflow/alembic/README +1 -0
- vibe_surf/langflow/alembic/env.py +124 -0
- vibe_surf/langflow/alembic/script.py.mako +31 -0
- vibe_surf/langflow/alembic/versions/006b3990db50_add_unique_constraints.py +66 -0
- vibe_surf/langflow/alembic/versions/012fb73ac359_add_folder_table.py +82 -0
- vibe_surf/langflow/alembic/versions/0882f9657f22_encrypt_existing_mcp_auth_settings_.py +122 -0
- vibe_surf/langflow/alembic/versions/0ae3a2674f32_update_the_columns_that_need_to_change_.py +71 -0
- vibe_surf/langflow/alembic/versions/0b8757876a7c_.py +32 -0
- vibe_surf/langflow/alembic/versions/0d60fcbd4e8e_create_vertex_builds_table.py +51 -0
- vibe_surf/langflow/alembic/versions/1a110b568907_replace_credential_table_with_variable.py +66 -0
- vibe_surf/langflow/alembic/versions/1b8b740a6fa3_remove_fk_constraint_in_message_.py +337 -0
- vibe_surf/langflow/alembic/versions/1c79524817ed_add_unique_constraints_per_user_in_.py +43 -0
- vibe_surf/langflow/alembic/versions/1cb603706752_modify_uniqueness_constraint_on_file_.py +279 -0
- vibe_surf/langflow/alembic/versions/1d90f8a0efe1_update_description_columns_type.py +71 -0
- vibe_surf/langflow/alembic/versions/1eab2c3eb45e_event_error.py +53 -0
- vibe_surf/langflow/alembic/versions/1ef9c4f3765d_.py +54 -0
- vibe_surf/langflow/alembic/versions/1f4d6df60295_add_default_fields_column.py +43 -0
- vibe_surf/langflow/alembic/versions/260dbcc8b680_adds_tables.py +151 -0
- vibe_surf/langflow/alembic/versions/29fe8f1f806b_add_missing_index.py +44 -0
- vibe_surf/langflow/alembic/versions/2ac71eb9c3ae_adds_credential_table.py +55 -0
- vibe_surf/langflow/alembic/versions/3162e83e485f_add_auth_settings_to_folder_and_merge.py +58 -0
- vibe_surf/langflow/alembic/versions/3bb0ddf32dfb_add_unique_constraints_per_user_in_flow_.py +55 -0
- vibe_surf/langflow/alembic/versions/4e5980a44eaa_fix_date_times_again.py +124 -0
- vibe_surf/langflow/alembic/versions/58b28437a398_modify_nullable.py +66 -0
- vibe_surf/langflow/alembic/versions/5ace73a7f223_new_remove_table_upgrade_op.py +39 -0
- vibe_surf/langflow/alembic/versions/631faacf5da2_add_webhook_columns.py +45 -0
- vibe_surf/langflow/alembic/versions/63b9c451fd30_add_icon_and_icon_bg_color_to_flow.py +50 -0
- vibe_surf/langflow/alembic/versions/66f72f04a1de_add_mcp_support_with_project_settings_.py +54 -0
- vibe_surf/langflow/alembic/versions/67cc006d50bf_add_profile_image_column.py +57 -0
- vibe_surf/langflow/alembic/versions/6e7b581b5648_fix_nullable.py +59 -0
- vibe_surf/langflow/alembic/versions/7843803a87b5_store_updates.py +55 -0
- vibe_surf/langflow/alembic/versions/79e675cb6752_change_datetime_type.py +124 -0
- vibe_surf/langflow/alembic/versions/7d2162acc8b2_adds_updated_at_and_folder_cols.py +74 -0
- vibe_surf/langflow/alembic/versions/90be8e2ed91e_create_transactions_table.py +51 -0
- vibe_surf/langflow/alembic/versions/93e2705fa8d6_add_column_save_path_to_flow.py +43 -0
- vibe_surf/langflow/alembic/versions/a72f5cf9c2f9_add_endpoint_name_col.py +52 -0
- vibe_surf/langflow/alembic/versions/b2fa308044b5_add_unique_constraints.py +101 -0
- vibe_surf/langflow/alembic/versions/bc2f01c40e4a_new_fixes.py +73 -0
- vibe_surf/langflow/alembic/versions/c153816fd85f_set_name_and_value_to_not_nullable.py +52 -0
- vibe_surf/langflow/alembic/versions/d066bfd22890_add_message_table.py +52 -0
- vibe_surf/langflow/alembic/versions/d2d475a1f7c0_add_tags_column_to_flow.py +41 -0
- vibe_surf/langflow/alembic/versions/d37bc4322900_drop_single_constraint_on_files_name_.py +169 -0
- vibe_surf/langflow/alembic/versions/d3dbf656a499_add_gradient_column_in_flow.py +41 -0
- vibe_surf/langflow/alembic/versions/d9a6ea21edcd_rename_default_folder.py +75 -0
- vibe_surf/langflow/alembic/versions/dd9e0804ebd1_add_v2_file_table.py +49 -0
- vibe_surf/langflow/alembic/versions/e3162c1804e6_add_persistent_locked_state.py +43 -0
- vibe_surf/langflow/alembic/versions/e3bc869fa272_fix_nullable.py +68 -0
- vibe_surf/langflow/alembic/versions/e56d87f8994a_add_optins_column_to_user.py +38 -0
- vibe_surf/langflow/alembic/versions/e5a65ecff2cd_nullable_in_vertex_build.py +49 -0
- vibe_surf/langflow/alembic/versions/eb5866d51fd2_change_columns_to_be_nullable.py +31 -0
- vibe_surf/langflow/alembic/versions/eb5e72293a8e_add_error_and_edit_flags_to_message.py +49 -0
- vibe_surf/langflow/alembic/versions/f3b2d1f1002d_add_column_access_type_to_flow.py +37 -0
- vibe_surf/langflow/alembic/versions/f5ee9749d1a6_user_id_can_be_null_in_flow.py +42 -0
- vibe_surf/langflow/alembic/versions/fd531f8868b1_fix_credential_table.py +60 -0
- vibe_surf/langflow/alembic.ini +113 -0
- vibe_surf/langflow/api/__init__.py +5 -0
- vibe_surf/langflow/api/build.py +557 -0
- vibe_surf/langflow/api/disconnect.py +31 -0
- vibe_surf/langflow/api/health_check_router.py +65 -0
- vibe_surf/langflow/api/limited_background_tasks.py +29 -0
- vibe_surf/langflow/api/log_router.py +103 -0
- vibe_surf/langflow/api/router.py +63 -0
- vibe_surf/langflow/api/schemas.py +14 -0
- vibe_surf/langflow/api/utils.py +381 -0
- vibe_surf/langflow/api/v1/__init__.py +41 -0
- vibe_surf/langflow/api/v1/api_key.py +88 -0
- vibe_surf/langflow/api/v1/auth_helpers.py +75 -0
- vibe_surf/langflow/api/v1/base.py +50 -0
- vibe_surf/langflow/api/v1/callback.py +136 -0
- vibe_surf/langflow/api/v1/chat.py +675 -0
- vibe_surf/langflow/api/v1/endpoints.py +800 -0
- vibe_surf/langflow/api/v1/files.py +193 -0
- vibe_surf/langflow/api/v1/flows.py +579 -0
- vibe_surf/langflow/api/v1/folders.py +95 -0
- vibe_surf/langflow/api/v1/knowledge_bases.py +452 -0
- vibe_surf/langflow/api/v1/login.py +166 -0
- vibe_surf/langflow/api/v1/mcp.py +137 -0
- vibe_surf/langflow/api/v1/mcp_projects.py +1230 -0
- vibe_surf/langflow/api/v1/mcp_utils.py +348 -0
- vibe_surf/langflow/api/v1/monitor.py +203 -0
- vibe_surf/langflow/api/v1/openai_responses.py +561 -0
- vibe_surf/langflow/api/v1/projects.py +447 -0
- vibe_surf/langflow/api/v1/schemas.py +488 -0
- vibe_surf/langflow/api/v1/starter_projects.py +17 -0
- vibe_surf/langflow/api/v1/store.py +182 -0
- vibe_surf/langflow/api/v1/users.py +146 -0
- vibe_surf/langflow/api/v1/validate.py +48 -0
- vibe_surf/langflow/api/v1/variable.py +106 -0
- vibe_surf/langflow/api/v1/voice_mode.py +1375 -0
- vibe_surf/langflow/api/v2/__init__.py +7 -0
- vibe_surf/langflow/api/v2/files.py +532 -0
- vibe_surf/langflow/api/v2/mcp.py +330 -0
- vibe_surf/langflow/base/__init__.py +0 -0
- vibe_surf/langflow/base/agents/__init__.py +0 -0
- vibe_surf/langflow/base/agents/agent.py +267 -0
- vibe_surf/langflow/base/agents/callback.py +130 -0
- vibe_surf/langflow/base/agents/context.py +109 -0
- vibe_surf/langflow/base/agents/crewai/__init__.py +0 -0
- vibe_surf/langflow/base/agents/crewai/crew.py +231 -0
- vibe_surf/langflow/base/agents/crewai/tasks.py +12 -0
- vibe_surf/langflow/base/agents/default_prompts.py +23 -0
- vibe_surf/langflow/base/agents/errors.py +15 -0
- vibe_surf/langflow/base/agents/events.py +346 -0
- vibe_surf/langflow/base/agents/utils.py +205 -0
- vibe_surf/langflow/base/astra_assistants/__init__.py +0 -0
- vibe_surf/langflow/base/astra_assistants/util.py +171 -0
- vibe_surf/langflow/base/chains/__init__.py +0 -0
- vibe_surf/langflow/base/chains/model.py +19 -0
- vibe_surf/langflow/base/composio/__init__.py +0 -0
- vibe_surf/langflow/base/composio/composio_base.py +1304 -0
- vibe_surf/langflow/base/compressors/__init__.py +0 -0
- vibe_surf/langflow/base/compressors/model.py +60 -0
- vibe_surf/langflow/base/constants.py +46 -0
- vibe_surf/langflow/base/curl/__init__.py +0 -0
- vibe_surf/langflow/base/curl/parse.py +188 -0
- vibe_surf/langflow/base/data/__init__.py +5 -0
- vibe_surf/langflow/base/data/base_file.py +698 -0
- vibe_surf/langflow/base/data/docling_utils.py +280 -0
- vibe_surf/langflow/base/data/utils.py +198 -0
- vibe_surf/langflow/base/document_transformers/__init__.py +0 -0
- vibe_surf/langflow/base/document_transformers/model.py +43 -0
- vibe_surf/langflow/base/embeddings/__init__.py +0 -0
- vibe_surf/langflow/base/embeddings/aiml_embeddings.py +62 -0
- vibe_surf/langflow/base/embeddings/model.py +26 -0
- vibe_surf/langflow/base/flow_processing/__init__.py +0 -0
- vibe_surf/langflow/base/flow_processing/utils.py +86 -0
- vibe_surf/langflow/base/huggingface/__init__.py +0 -0
- vibe_surf/langflow/base/huggingface/model_bridge.py +133 -0
- vibe_surf/langflow/base/io/__init__.py +0 -0
- vibe_surf/langflow/base/io/chat.py +20 -0
- vibe_surf/langflow/base/io/text.py +22 -0
- vibe_surf/langflow/base/knowledge_bases/__init__.py +0 -0
- vibe_surf/langflow/base/knowledge_bases/knowledge_base_utils.py +137 -0
- vibe_surf/langflow/base/langchain_utilities/__init__.py +0 -0
- vibe_surf/langflow/base/langchain_utilities/model.py +35 -0
- vibe_surf/langflow/base/langchain_utilities/spider_constants.py +1 -0
- vibe_surf/langflow/base/langwatch/__init__.py +0 -0
- vibe_surf/langflow/base/langwatch/utils.py +18 -0
- vibe_surf/langflow/base/mcp/__init__.py +0 -0
- vibe_surf/langflow/base/mcp/constants.py +2 -0
- vibe_surf/langflow/base/mcp/util.py +1544 -0
- vibe_surf/langflow/base/memory/__init__.py +0 -0
- vibe_surf/langflow/base/memory/memory.py +49 -0
- vibe_surf/langflow/base/memory/model.py +38 -0
- vibe_surf/langflow/base/models/__init__.py +3 -0
- vibe_surf/langflow/base/models/aiml_constants.py +51 -0
- vibe_surf/langflow/base/models/anthropic_constants.py +49 -0
- vibe_surf/langflow/base/models/aws_constants.py +151 -0
- vibe_surf/langflow/base/models/chat_result.py +76 -0
- vibe_surf/langflow/base/models/google_generative_ai_constants.py +70 -0
- vibe_surf/langflow/base/models/groq_constants.py +134 -0
- vibe_surf/langflow/base/models/model.py +375 -0
- vibe_surf/langflow/base/models/model_input_constants.py +299 -0
- vibe_surf/langflow/base/models/model_metadata.py +41 -0
- vibe_surf/langflow/base/models/model_utils.py +8 -0
- vibe_surf/langflow/base/models/novita_constants.py +35 -0
- vibe_surf/langflow/base/models/ollama_constants.py +49 -0
- vibe_surf/langflow/base/models/openai_constants.py +121 -0
- vibe_surf/langflow/base/models/sambanova_constants.py +18 -0
- vibe_surf/langflow/base/processing/__init__.py +0 -0
- vibe_surf/langflow/base/prompts/__init__.py +0 -0
- vibe_surf/langflow/base/prompts/api_utils.py +224 -0
- vibe_surf/langflow/base/prompts/utils.py +61 -0
- vibe_surf/langflow/base/textsplitters/__init__.py +0 -0
- vibe_surf/langflow/base/textsplitters/model.py +28 -0
- vibe_surf/langflow/base/tools/__init__.py +0 -0
- vibe_surf/langflow/base/tools/base.py +26 -0
- vibe_surf/langflow/base/tools/component_tool.py +324 -0
- vibe_surf/langflow/base/tools/constants.py +49 -0
- vibe_surf/langflow/base/tools/flow_tool.py +131 -0
- vibe_surf/langflow/base/tools/run_flow.py +227 -0
- vibe_surf/langflow/base/vectorstores/__init__.py +0 -0
- vibe_surf/langflow/base/vectorstores/model.py +193 -0
- vibe_surf/langflow/base/vectorstores/utils.py +22 -0
- vibe_surf/langflow/base/vectorstores/vector_store_connection_decorator.py +52 -0
- vibe_surf/langflow/cli/__init__.py +0 -0
- vibe_surf/langflow/cli/progress.py +233 -0
- vibe_surf/langflow/components/FAISS/__init__.py +34 -0
- vibe_surf/langflow/components/FAISS/faiss.py +111 -0
- vibe_surf/langflow/components/Notion/__init__.py +19 -0
- vibe_surf/langflow/components/Notion/add_content_to_page.py +269 -0
- vibe_surf/langflow/components/Notion/create_page.py +94 -0
- vibe_surf/langflow/components/Notion/list_database_properties.py +68 -0
- vibe_surf/langflow/components/Notion/list_pages.py +122 -0
- vibe_surf/langflow/components/Notion/list_users.py +77 -0
- vibe_surf/langflow/components/Notion/page_content_viewer.py +93 -0
- vibe_surf/langflow/components/Notion/search.py +111 -0
- vibe_surf/langflow/components/Notion/update_page_property.py +114 -0
- vibe_surf/langflow/components/__init__.py +270 -0
- vibe_surf/langflow/components/_importing.py +37 -0
- vibe_surf/langflow/components/agentql/__init__.py +3 -0
- vibe_surf/langflow/components/agentql/agentql_api.py +151 -0
- vibe_surf/langflow/components/agents/__init__.py +4 -0
- vibe_surf/langflow/components/agents/agent.py +608 -0
- vibe_surf/langflow/components/agents/mcp_component.py +511 -0
- vibe_surf/langflow/components/aiml/__init__.py +37 -0
- vibe_surf/langflow/components/aiml/aiml.py +115 -0
- vibe_surf/langflow/components/aiml/aiml_embeddings.py +37 -0
- vibe_surf/langflow/components/amazon/__init__.py +36 -0
- vibe_surf/langflow/components/amazon/amazon_bedrock_embedding.py +109 -0
- vibe_surf/langflow/components/amazon/amazon_bedrock_model.py +124 -0
- vibe_surf/langflow/components/amazon/s3_bucket_uploader.py +211 -0
- vibe_surf/langflow/components/anthropic/__init__.py +34 -0
- vibe_surf/langflow/components/anthropic/anthropic.py +187 -0
- vibe_surf/langflow/components/apify/__init__.py +5 -0
- vibe_surf/langflow/components/apify/apify_actor.py +325 -0
- vibe_surf/langflow/components/arxiv/__init__.py +3 -0
- vibe_surf/langflow/components/arxiv/arxiv.py +163 -0
- vibe_surf/langflow/components/assemblyai/__init__.py +46 -0
- vibe_surf/langflow/components/assemblyai/assemblyai_get_subtitles.py +83 -0
- vibe_surf/langflow/components/assemblyai/assemblyai_lemur.py +183 -0
- vibe_surf/langflow/components/assemblyai/assemblyai_list_transcripts.py +95 -0
- vibe_surf/langflow/components/assemblyai/assemblyai_poll_transcript.py +72 -0
- vibe_surf/langflow/components/assemblyai/assemblyai_start_transcript.py +188 -0
- vibe_surf/langflow/components/azure/__init__.py +37 -0
- vibe_surf/langflow/components/azure/azure_openai.py +95 -0
- vibe_surf/langflow/components/azure/azure_openai_embeddings.py +83 -0
- vibe_surf/langflow/components/baidu/__init__.py +32 -0
- vibe_surf/langflow/components/baidu/baidu_qianfan_chat.py +113 -0
- vibe_surf/langflow/components/bing/__init__.py +3 -0
- vibe_surf/langflow/components/bing/bing_search_api.py +61 -0
- vibe_surf/langflow/components/cassandra/__init__.py +40 -0
- vibe_surf/langflow/components/cassandra/cassandra.py +264 -0
- vibe_surf/langflow/components/cassandra/cassandra_chat.py +92 -0
- vibe_surf/langflow/components/cassandra/cassandra_graph.py +238 -0
- vibe_surf/langflow/components/chains/__init__.py +0 -0
- vibe_surf/langflow/components/chroma/__init__.py +34 -0
- vibe_surf/langflow/components/chroma/chroma.py +169 -0
- vibe_surf/langflow/components/cleanlab/__init__.py +40 -0
- vibe_surf/langflow/components/cleanlab/cleanlab_evaluator.py +157 -0
- vibe_surf/langflow/components/cleanlab/cleanlab_rag_evaluator.py +254 -0
- vibe_surf/langflow/components/cleanlab/cleanlab_remediator.py +131 -0
- vibe_surf/langflow/components/clickhouse/__init__.py +34 -0
- vibe_surf/langflow/components/clickhouse/clickhouse.py +135 -0
- vibe_surf/langflow/components/cloudflare/__init__.py +32 -0
- vibe_surf/langflow/components/cloudflare/cloudflare.py +81 -0
- vibe_surf/langflow/components/cohere/__init__.py +40 -0
- vibe_surf/langflow/components/cohere/cohere_embeddings.py +81 -0
- vibe_surf/langflow/components/cohere/cohere_models.py +46 -0
- vibe_surf/langflow/components/cohere/cohere_rerank.py +51 -0
- vibe_surf/langflow/components/composio/__init__.py +73 -0
- vibe_surf/langflow/components/composio/composio_api.py +279 -0
- vibe_surf/langflow/components/composio/dropbox_compnent.py +11 -0
- vibe_surf/langflow/components/composio/github_composio.py +11 -0
- vibe_surf/langflow/components/composio/gmail_composio.py +38 -0
- vibe_surf/langflow/components/composio/googlecalendar_composio.py +11 -0
- vibe_surf/langflow/components/composio/googlemeet_composio.py +11 -0
- vibe_surf/langflow/components/composio/googletasks_composio.py +8 -0
- vibe_surf/langflow/components/composio/linear_composio.py +11 -0
- vibe_surf/langflow/components/composio/outlook_composio.py +11 -0
- vibe_surf/langflow/components/composio/reddit_composio.py +11 -0
- vibe_surf/langflow/components/composio/slack_composio.py +11 -0
- vibe_surf/langflow/components/composio/slackbot_composio.py +11 -0
- vibe_surf/langflow/components/composio/supabase_composio.py +11 -0
- vibe_surf/langflow/components/composio/todoist_composio.py +11 -0
- vibe_surf/langflow/components/composio/youtube_composio.py +11 -0
- vibe_surf/langflow/components/confluence/__init__.py +3 -0
- vibe_surf/langflow/components/confluence/confluence.py +84 -0
- vibe_surf/langflow/components/couchbase/__init__.py +34 -0
- vibe_surf/langflow/components/couchbase/couchbase.py +102 -0
- vibe_surf/langflow/components/crewai/__init__.py +49 -0
- vibe_surf/langflow/components/crewai/crewai.py +108 -0
- vibe_surf/langflow/components/crewai/hierarchical_crew.py +47 -0
- vibe_surf/langflow/components/crewai/hierarchical_task.py +45 -0
- vibe_surf/langflow/components/crewai/sequential_crew.py +53 -0
- vibe_surf/langflow/components/crewai/sequential_task.py +74 -0
- vibe_surf/langflow/components/crewai/sequential_task_agent.py +144 -0
- vibe_surf/langflow/components/custom_component/__init__.py +34 -0
- vibe_surf/langflow/components/custom_component/custom_component.py +31 -0
- vibe_surf/langflow/components/data/__init__.py +25 -0
- vibe_surf/langflow/components/data/api_request.py +555 -0
- vibe_surf/langflow/components/data/csv_to_data.py +96 -0
- vibe_surf/langflow/components/data/directory.py +113 -0
- vibe_surf/langflow/components/data/file.py +632 -0
- vibe_surf/langflow/components/data/json_to_data.py +99 -0
- vibe_surf/langflow/components/data/news_search.py +164 -0
- vibe_surf/langflow/components/data/rss.py +69 -0
- vibe_surf/langflow/components/data/sql_executor.py +99 -0
- vibe_surf/langflow/components/data/url.py +299 -0
- vibe_surf/langflow/components/data/web_search.py +112 -0
- vibe_surf/langflow/components/data/webhook.py +56 -0
- vibe_surf/langflow/components/datastax/__init__.py +70 -0
- vibe_surf/langflow/components/datastax/astra_assistant_manager.py +306 -0
- vibe_surf/langflow/components/datastax/astra_db.py +68 -0
- vibe_surf/langflow/components/datastax/astra_vectorize.py +122 -0
- vibe_surf/langflow/components/datastax/astradb_cql.py +314 -0
- vibe_surf/langflow/components/datastax/astradb_graph.py +326 -0
- vibe_surf/langflow/components/datastax/astradb_tool.py +418 -0
- vibe_surf/langflow/components/datastax/astradb_vectorstore.py +1292 -0
- vibe_surf/langflow/components/datastax/create_assistant.py +58 -0
- vibe_surf/langflow/components/datastax/create_thread.py +32 -0
- vibe_surf/langflow/components/datastax/dotenv.py +35 -0
- vibe_surf/langflow/components/datastax/get_assistant.py +37 -0
- vibe_surf/langflow/components/datastax/getenvvar.py +30 -0
- vibe_surf/langflow/components/datastax/graph_rag.py +141 -0
- vibe_surf/langflow/components/datastax/hcd.py +314 -0
- vibe_surf/langflow/components/datastax/list_assistants.py +25 -0
- vibe_surf/langflow/components/datastax/run.py +89 -0
- vibe_surf/langflow/components/deactivated/__init__.py +19 -0
- vibe_surf/langflow/components/deactivated/amazon_kendra.py +66 -0
- vibe_surf/langflow/components/deactivated/chat_litellm_model.py +158 -0
- vibe_surf/langflow/components/deactivated/code_block_extractor.py +26 -0
- vibe_surf/langflow/components/deactivated/documents_to_data.py +22 -0
- vibe_surf/langflow/components/deactivated/embed.py +16 -0
- vibe_surf/langflow/components/deactivated/extract_key_from_data.py +46 -0
- vibe_surf/langflow/components/deactivated/json_document_builder.py +59 -0
- vibe_surf/langflow/components/deactivated/list_flows.py +20 -0
- vibe_surf/langflow/components/deactivated/merge_data.py +93 -0
- vibe_surf/langflow/components/deactivated/message.py +37 -0
- vibe_surf/langflow/components/deactivated/metal.py +54 -0
- vibe_surf/langflow/components/deactivated/multi_query.py +59 -0
- vibe_surf/langflow/components/deactivated/retriever.py +43 -0
- vibe_surf/langflow/components/deactivated/selective_passthrough.py +77 -0
- vibe_surf/langflow/components/deactivated/should_run_next.py +40 -0
- vibe_surf/langflow/components/deactivated/split_text.py +63 -0
- vibe_surf/langflow/components/deactivated/store_message.py +24 -0
- vibe_surf/langflow/components/deactivated/sub_flow.py +124 -0
- vibe_surf/langflow/components/deactivated/vectara_self_query.py +76 -0
- vibe_surf/langflow/components/deactivated/vector_store.py +24 -0
- vibe_surf/langflow/components/deepseek/__init__.py +34 -0
- vibe_surf/langflow/components/deepseek/deepseek.py +136 -0
- vibe_surf/langflow/components/docling/__init__.py +43 -0
- vibe_surf/langflow/components/docling/chunk_docling_document.py +186 -0
- vibe_surf/langflow/components/docling/docling_inline.py +249 -0
- vibe_surf/langflow/components/docling/docling_remote.py +192 -0
- vibe_surf/langflow/components/docling/export_docling_document.py +117 -0
- vibe_surf/langflow/components/documentloaders/__init__.py +0 -0
- vibe_surf/langflow/components/duckduckgo/__init__.py +3 -0
- vibe_surf/langflow/components/duckduckgo/duck_duck_go_search_run.py +92 -0
- vibe_surf/langflow/components/elastic/__init__.py +37 -0
- vibe_surf/langflow/components/elastic/elasticsearch.py +267 -0
- vibe_surf/langflow/components/elastic/opensearch.py +243 -0
- vibe_surf/langflow/components/embeddings/__init__.py +37 -0
- vibe_surf/langflow/components/embeddings/similarity.py +77 -0
- vibe_surf/langflow/components/embeddings/text_embedder.py +65 -0
- vibe_surf/langflow/components/exa/__init__.py +3 -0
- vibe_surf/langflow/components/exa/exa_search.py +68 -0
- vibe_surf/langflow/components/firecrawl/__init__.py +43 -0
- vibe_surf/langflow/components/firecrawl/firecrawl_crawl_api.py +88 -0
- vibe_surf/langflow/components/firecrawl/firecrawl_extract_api.py +136 -0
- vibe_surf/langflow/components/firecrawl/firecrawl_map_api.py +89 -0
- vibe_surf/langflow/components/firecrawl/firecrawl_scrape_api.py +73 -0
- vibe_surf/langflow/components/git/__init__.py +4 -0
- vibe_surf/langflow/components/git/git.py +262 -0
- vibe_surf/langflow/components/git/gitextractor.py +196 -0
- vibe_surf/langflow/components/glean/__init__.py +3 -0
- vibe_surf/langflow/components/glean/glean_search_api.py +173 -0
- vibe_surf/langflow/components/google/__init__.py +17 -0
- vibe_surf/langflow/components/google/gmail.py +193 -0
- vibe_surf/langflow/components/google/google_bq_sql_executor.py +157 -0
- vibe_surf/langflow/components/google/google_drive.py +92 -0
- vibe_surf/langflow/components/google/google_drive_search.py +152 -0
- vibe_surf/langflow/components/google/google_generative_ai.py +147 -0
- vibe_surf/langflow/components/google/google_generative_ai_embeddings.py +141 -0
- vibe_surf/langflow/components/google/google_oauth_token.py +89 -0
- vibe_surf/langflow/components/google/google_search_api_core.py +68 -0
- vibe_surf/langflow/components/groq/__init__.py +34 -0
- vibe_surf/langflow/components/groq/groq.py +140 -0
- vibe_surf/langflow/components/helpers/__init__.py +52 -0
- vibe_surf/langflow/components/helpers/calculator_core.py +89 -0
- vibe_surf/langflow/components/helpers/create_list.py +40 -0
- vibe_surf/langflow/components/helpers/current_date.py +42 -0
- vibe_surf/langflow/components/helpers/id_generator.py +42 -0
- vibe_surf/langflow/components/helpers/memory.py +253 -0
- vibe_surf/langflow/components/helpers/output_parser.py +46 -0
- vibe_surf/langflow/components/helpers/store_message.py +91 -0
- vibe_surf/langflow/components/homeassistant/__init__.py +7 -0
- vibe_surf/langflow/components/homeassistant/home_assistant_control.py +152 -0
- vibe_surf/langflow/components/homeassistant/list_home_assistant_states.py +137 -0
- vibe_surf/langflow/components/huggingface/__init__.py +37 -0
- vibe_surf/langflow/components/huggingface/huggingface.py +199 -0
- vibe_surf/langflow/components/huggingface/huggingface_inference_api.py +106 -0
- vibe_surf/langflow/components/ibm/__init__.py +34 -0
- vibe_surf/langflow/components/ibm/watsonx.py +203 -0
- vibe_surf/langflow/components/ibm/watsonx_embeddings.py +135 -0
- vibe_surf/langflow/components/icosacomputing/__init__.py +5 -0
- vibe_surf/langflow/components/icosacomputing/combinatorial_reasoner.py +84 -0
- vibe_surf/langflow/components/input_output/__init__.py +38 -0
- vibe_surf/langflow/components/input_output/chat.py +99 -0
- vibe_surf/langflow/components/input_output/chat_output.py +169 -0
- vibe_surf/langflow/components/input_output/text.py +27 -0
- vibe_surf/langflow/components/input_output/text_output.py +29 -0
- vibe_surf/langflow/components/jigsawstack/__init__.py +23 -0
- vibe_surf/langflow/components/jigsawstack/ai_scrape.py +126 -0
- vibe_surf/langflow/components/jigsawstack/ai_web_search.py +136 -0
- vibe_surf/langflow/components/jigsawstack/file_read.py +115 -0
- vibe_surf/langflow/components/jigsawstack/file_upload.py +94 -0
- vibe_surf/langflow/components/jigsawstack/image_generation.py +205 -0
- vibe_surf/langflow/components/jigsawstack/nsfw.py +60 -0
- vibe_surf/langflow/components/jigsawstack/object_detection.py +124 -0
- vibe_surf/langflow/components/jigsawstack/sentiment.py +112 -0
- vibe_surf/langflow/components/jigsawstack/text_to_sql.py +90 -0
- vibe_surf/langflow/components/jigsawstack/text_translate.py +77 -0
- vibe_surf/langflow/components/jigsawstack/vocr.py +107 -0
- vibe_surf/langflow/components/knowledge_bases/__init__.py +34 -0
- vibe_surf/langflow/components/knowledge_bases/ingestion.py +697 -0
- vibe_surf/langflow/components/knowledge_bases/retrieval.py +264 -0
- vibe_surf/langflow/components/langchain_utilities/__init__.py +109 -0
- vibe_surf/langflow/components/langchain_utilities/character.py +53 -0
- vibe_surf/langflow/components/langchain_utilities/conversation.py +52 -0
- vibe_surf/langflow/components/langchain_utilities/csv_agent.py +107 -0
- vibe_surf/langflow/components/langchain_utilities/fake_embeddings.py +26 -0
- vibe_surf/langflow/components/langchain_utilities/html_link_extractor.py +35 -0
- vibe_surf/langflow/components/langchain_utilities/json_agent.py +45 -0
- vibe_surf/langflow/components/langchain_utilities/langchain_hub.py +126 -0
- vibe_surf/langflow/components/langchain_utilities/language_recursive.py +49 -0
- vibe_surf/langflow/components/langchain_utilities/language_semantic.py +138 -0
- vibe_surf/langflow/components/langchain_utilities/llm_checker.py +39 -0
- vibe_surf/langflow/components/langchain_utilities/llm_math.py +42 -0
- vibe_surf/langflow/components/langchain_utilities/natural_language.py +61 -0
- vibe_surf/langflow/components/langchain_utilities/openai_tools.py +53 -0
- vibe_surf/langflow/components/langchain_utilities/openapi.py +48 -0
- vibe_surf/langflow/components/langchain_utilities/recursive_character.py +60 -0
- vibe_surf/langflow/components/langchain_utilities/retrieval_qa.py +83 -0
- vibe_surf/langflow/components/langchain_utilities/runnable_executor.py +137 -0
- vibe_surf/langflow/components/langchain_utilities/self_query.py +80 -0
- vibe_surf/langflow/components/langchain_utilities/spider.py +142 -0
- vibe_surf/langflow/components/langchain_utilities/sql.py +40 -0
- vibe_surf/langflow/components/langchain_utilities/sql_database.py +35 -0
- vibe_surf/langflow/components/langchain_utilities/sql_generator.py +78 -0
- vibe_surf/langflow/components/langchain_utilities/tool_calling.py +59 -0
- vibe_surf/langflow/components/langchain_utilities/vector_store_info.py +49 -0
- vibe_surf/langflow/components/langchain_utilities/vector_store_router.py +33 -0
- vibe_surf/langflow/components/langchain_utilities/xml_agent.py +71 -0
- vibe_surf/langflow/components/langwatch/__init__.py +3 -0
- vibe_surf/langflow/components/langwatch/langwatch.py +278 -0
- vibe_surf/langflow/components/link_extractors/__init__.py +0 -0
- vibe_surf/langflow/components/lmstudio/__init__.py +34 -0
- vibe_surf/langflow/components/lmstudio/lmstudioembeddings.py +89 -0
- vibe_surf/langflow/components/lmstudio/lmstudiomodel.py +129 -0
- vibe_surf/langflow/components/logic/__init__.py +52 -0
- vibe_surf/langflow/components/logic/conditional_router.py +208 -0
- vibe_surf/langflow/components/logic/data_conditional_router.py +126 -0
- vibe_surf/langflow/components/logic/flow_tool.py +111 -0
- vibe_surf/langflow/components/logic/listen.py +29 -0
- vibe_surf/langflow/components/logic/loop.py +141 -0
- vibe_surf/langflow/components/logic/notify.py +88 -0
- vibe_surf/langflow/components/logic/pass_message.py +36 -0
- vibe_surf/langflow/components/logic/run_flow.py +71 -0
- vibe_surf/langflow/components/logic/sub_flow.py +115 -0
- vibe_surf/langflow/components/maritalk/__init__.py +32 -0
- vibe_surf/langflow/components/maritalk/maritalk.py +52 -0
- vibe_surf/langflow/components/mem0/__init__.py +3 -0
- vibe_surf/langflow/components/mem0/mem0_chat_memory.py +136 -0
- vibe_surf/langflow/components/milvus/__init__.py +34 -0
- vibe_surf/langflow/components/milvus/milvus.py +115 -0
- vibe_surf/langflow/components/mistral/__init__.py +37 -0
- vibe_surf/langflow/components/mistral/mistral.py +114 -0
- vibe_surf/langflow/components/mistral/mistral_embeddings.py +58 -0
- vibe_surf/langflow/components/models/__init__.py +34 -0
- vibe_surf/langflow/components/models/embedding_model.py +114 -0
- vibe_surf/langflow/components/models/language_model.py +144 -0
- vibe_surf/langflow/components/mongodb/__init__.py +34 -0
- vibe_surf/langflow/components/mongodb/mongodb_atlas.py +213 -0
- vibe_surf/langflow/components/needle/__init__.py +3 -0
- vibe_surf/langflow/components/needle/needle.py +104 -0
- vibe_surf/langflow/components/notdiamond/__init__.py +36 -0
- vibe_surf/langflow/components/notdiamond/notdiamond.py +228 -0
- vibe_surf/langflow/components/novita/__init__.py +32 -0
- vibe_surf/langflow/components/novita/novita.py +130 -0
- vibe_surf/langflow/components/nvidia/__init__.py +57 -0
- vibe_surf/langflow/components/nvidia/nvidia.py +151 -0
- vibe_surf/langflow/components/nvidia/nvidia_embedding.py +77 -0
- vibe_surf/langflow/components/nvidia/nvidia_ingest.py +317 -0
- vibe_surf/langflow/components/nvidia/nvidia_rerank.py +63 -0
- vibe_surf/langflow/components/nvidia/system_assist.py +65 -0
- vibe_surf/langflow/components/olivya/__init__.py +3 -0
- vibe_surf/langflow/components/olivya/olivya.py +116 -0
- vibe_surf/langflow/components/ollama/__init__.py +37 -0
- vibe_surf/langflow/components/ollama/ollama.py +330 -0
- vibe_surf/langflow/components/ollama/ollama_embeddings.py +106 -0
- vibe_surf/langflow/components/openai/__init__.py +37 -0
- vibe_surf/langflow/components/openai/openai.py +100 -0
- vibe_surf/langflow/components/openai/openai_chat_model.py +158 -0
- vibe_surf/langflow/components/openrouter/__init__.py +32 -0
- vibe_surf/langflow/components/openrouter/openrouter.py +202 -0
- vibe_surf/langflow/components/output_parsers/__init__.py +0 -0
- vibe_surf/langflow/components/perplexity/__init__.py +34 -0
- vibe_surf/langflow/components/perplexity/perplexity.py +75 -0
- vibe_surf/langflow/components/pgvector/__init__.py +34 -0
- vibe_surf/langflow/components/pgvector/pgvector.py +72 -0
- vibe_surf/langflow/components/pinecone/__init__.py +34 -0
- vibe_surf/langflow/components/pinecone/pinecone.py +134 -0
- vibe_surf/langflow/components/processing/__init__.py +117 -0
- vibe_surf/langflow/components/processing/alter_metadata.py +109 -0
- vibe_surf/langflow/components/processing/batch_run.py +205 -0
- vibe_surf/langflow/components/processing/combine_text.py +40 -0
- vibe_surf/langflow/components/processing/converter.py +150 -0
- vibe_surf/langflow/components/processing/create_data.py +111 -0
- vibe_surf/langflow/components/processing/data_operations.py +438 -0
- vibe_surf/langflow/components/processing/data_to_dataframe.py +71 -0
- vibe_surf/langflow/components/processing/dataframe_operations.py +310 -0
- vibe_surf/langflow/components/processing/extract_key.py +54 -0
- vibe_surf/langflow/components/processing/filter_data.py +43 -0
- vibe_surf/langflow/components/processing/filter_data_values.py +89 -0
- vibe_surf/langflow/components/processing/json_cleaner.py +104 -0
- vibe_surf/langflow/components/processing/lambda_filter.py +154 -0
- vibe_surf/langflow/components/processing/llm_router.py +499 -0
- vibe_surf/langflow/components/processing/merge_data.py +91 -0
- vibe_surf/langflow/components/processing/message_to_data.py +37 -0
- vibe_surf/langflow/components/processing/parse_data.py +71 -0
- vibe_surf/langflow/components/processing/parse_dataframe.py +69 -0
- vibe_surf/langflow/components/processing/parse_json_data.py +91 -0
- vibe_surf/langflow/components/processing/parser.py +143 -0
- vibe_surf/langflow/components/processing/prompt.py +67 -0
- vibe_surf/langflow/components/processing/python_repl_core.py +98 -0
- vibe_surf/langflow/components/processing/regex.py +83 -0
- vibe_surf/langflow/components/processing/save_file.py +208 -0
- vibe_surf/langflow/components/processing/select_data.py +49 -0
- vibe_surf/langflow/components/processing/split_text.py +141 -0
- vibe_surf/langflow/components/processing/structured_output.py +206 -0
- vibe_surf/langflow/components/processing/update_data.py +161 -0
- vibe_surf/langflow/components/qdrant/__init__.py +34 -0
- vibe_surf/langflow/components/qdrant/qdrant.py +109 -0
- vibe_surf/langflow/components/redis/__init__.py +37 -0
- vibe_surf/langflow/components/redis/redis.py +89 -0
- vibe_surf/langflow/components/redis/redis_chat.py +43 -0
- vibe_surf/langflow/components/sambanova/__init__.py +32 -0
- vibe_surf/langflow/components/sambanova/sambanova.py +84 -0
- vibe_surf/langflow/components/scrapegraph/__init__.py +40 -0
- vibe_surf/langflow/components/scrapegraph/scrapegraph_markdownify_api.py +64 -0
- vibe_surf/langflow/components/scrapegraph/scrapegraph_search_api.py +64 -0
- vibe_surf/langflow/components/scrapegraph/scrapegraph_smart_scraper_api.py +71 -0
- vibe_surf/langflow/components/searchapi/__init__.py +36 -0
- vibe_surf/langflow/components/searchapi/search.py +79 -0
- vibe_surf/langflow/components/serpapi/__init__.py +3 -0
- vibe_surf/langflow/components/serpapi/serp.py +115 -0
- vibe_surf/langflow/components/serper/__init__.py +3 -0
- vibe_surf/langflow/components/serper/google_serper_api_core.py +74 -0
- vibe_surf/langflow/components/supabase/__init__.py +37 -0
- vibe_surf/langflow/components/supabase/supabase.py +76 -0
- vibe_surf/langflow/components/tavily/__init__.py +4 -0
- vibe_surf/langflow/components/tavily/tavily_extract.py +117 -0
- vibe_surf/langflow/components/tavily/tavily_search.py +212 -0
- vibe_surf/langflow/components/textsplitters/__init__.py +0 -0
- vibe_surf/langflow/components/toolkits/__init__.py +0 -0
- vibe_surf/langflow/components/tools/__init__.py +66 -0
- vibe_surf/langflow/components/tools/calculator.py +104 -0
- vibe_surf/langflow/components/tools/python_code_structured_tool.py +328 -0
- vibe_surf/langflow/components/tools/python_repl.py +98 -0
- vibe_surf/langflow/components/tools/search_api.py +88 -0
- vibe_surf/langflow/components/tools/searxng.py +145 -0
- vibe_surf/langflow/components/tools/serp_api.py +120 -0
- vibe_surf/langflow/components/tools/tavily_search_tool.py +345 -0
- vibe_surf/langflow/components/tools/wikidata_api.py +103 -0
- vibe_surf/langflow/components/tools/wikipedia_api.py +50 -0
- vibe_surf/langflow/components/tools/yahoo_finance.py +125 -0
- vibe_surf/langflow/components/twelvelabs/__init__.py +52 -0
- vibe_surf/langflow/components/twelvelabs/convert_astra_results.py +84 -0
- vibe_surf/langflow/components/twelvelabs/pegasus_index.py +311 -0
- vibe_surf/langflow/components/twelvelabs/split_video.py +291 -0
- vibe_surf/langflow/components/twelvelabs/text_embeddings.py +57 -0
- vibe_surf/langflow/components/twelvelabs/twelvelabs_pegasus.py +408 -0
- vibe_surf/langflow/components/twelvelabs/video_embeddings.py +100 -0
- vibe_surf/langflow/components/twelvelabs/video_file.py +179 -0
- vibe_surf/langflow/components/unstructured/__init__.py +3 -0
- vibe_surf/langflow/components/unstructured/unstructured.py +121 -0
- vibe_surf/langflow/components/upstash/__init__.py +34 -0
- vibe_surf/langflow/components/upstash/upstash.py +124 -0
- vibe_surf/langflow/components/vectara/__init__.py +37 -0
- vibe_surf/langflow/components/vectara/vectara.py +97 -0
- vibe_surf/langflow/components/vectara/vectara_rag.py +164 -0
- vibe_surf/langflow/components/vectorstores/__init__.py +34 -0
- vibe_surf/langflow/components/vectorstores/local_db.py +262 -0
- vibe_surf/langflow/components/vertexai/__init__.py +37 -0
- vibe_surf/langflow/components/vertexai/vertexai.py +71 -0
- vibe_surf/langflow/components/vertexai/vertexai_embeddings.py +67 -0
- vibe_surf/langflow/components/weaviate/__init__.py +34 -0
- vibe_surf/langflow/components/weaviate/weaviate.py +89 -0
- vibe_surf/langflow/components/wikipedia/__init__.py +4 -0
- vibe_surf/langflow/components/wikipedia/wikidata.py +86 -0
- vibe_surf/langflow/components/wikipedia/wikipedia.py +53 -0
- vibe_surf/langflow/components/wolframalpha/__init__.py +3 -0
- vibe_surf/langflow/components/wolframalpha/wolfram_alpha_api.py +54 -0
- vibe_surf/langflow/components/xai/__init__.py +32 -0
- vibe_surf/langflow/components/xai/xai.py +167 -0
- vibe_surf/langflow/components/youtube/__init__.py +52 -0
- vibe_surf/langflow/components/youtube/channel.py +227 -0
- vibe_surf/langflow/components/youtube/comments.py +231 -0
- vibe_surf/langflow/components/youtube/playlist.py +33 -0
- vibe_surf/langflow/components/youtube/search.py +120 -0
- vibe_surf/langflow/components/youtube/trending.py +285 -0
- vibe_surf/langflow/components/youtube/video_details.py +263 -0
- vibe_surf/langflow/components/youtube/youtube_transcripts.py +118 -0
- vibe_surf/langflow/components/zep/__init__.py +3 -0
- vibe_surf/langflow/components/zep/zep.py +45 -0
- vibe_surf/langflow/core/__init__.py +0 -0
- vibe_surf/langflow/core/celery_app.py +11 -0
- vibe_surf/langflow/core/celeryconfig.py +18 -0
- vibe_surf/langflow/custom/__init__.py +4 -0
- vibe_surf/langflow/custom/attributes.py +87 -0
- vibe_surf/langflow/custom/code_parser/__init__.py +3 -0
- vibe_surf/langflow/custom/code_parser/code_parser.py +361 -0
- vibe_surf/langflow/custom/custom_component/__init__.py +0 -0
- vibe_surf/langflow/custom/custom_component/base_component.py +118 -0
- vibe_surf/langflow/custom/custom_component/component.py +1742 -0
- vibe_surf/langflow/custom/custom_component/component_with_cache.py +8 -0
- vibe_surf/langflow/custom/custom_component/custom_component.py +552 -0
- vibe_surf/langflow/custom/dependency_analyzer.py +165 -0
- vibe_surf/langflow/custom/directory_reader/__init__.py +3 -0
- vibe_surf/langflow/custom/directory_reader/directory_reader.py +359 -0
- vibe_surf/langflow/custom/directory_reader/utils.py +171 -0
- vibe_surf/langflow/custom/eval.py +12 -0
- vibe_surf/langflow/custom/schema.py +32 -0
- vibe_surf/langflow/custom/tree_visitor.py +21 -0
- vibe_surf/langflow/custom/utils.py +868 -0
- vibe_surf/langflow/events/__init__.py +0 -0
- vibe_surf/langflow/events/event_manager.py +108 -0
- vibe_surf/langflow/exceptions/__init__.py +0 -0
- vibe_surf/langflow/exceptions/api.py +34 -0
- vibe_surf/langflow/exceptions/component.py +17 -0
- vibe_surf/langflow/exceptions/serialization.py +56 -0
- vibe_surf/langflow/field_typing/__init__.py +91 -0
- vibe_surf/langflow/field_typing/constants.py +137 -0
- vibe_surf/langflow/field_typing/range_spec.py +33 -0
- vibe_surf/langflow/graph/__init__.py +6 -0
- vibe_surf/langflow/graph/edge/__init__.py +0 -0
- vibe_surf/langflow/graph/edge/base.py +277 -0
- vibe_surf/langflow/graph/edge/schema.py +119 -0
- vibe_surf/langflow/graph/edge/utils.py +0 -0
- vibe_surf/langflow/graph/graph/__init__.py +0 -0
- vibe_surf/langflow/graph/graph/ascii.py +202 -0
- vibe_surf/langflow/graph/graph/base.py +2242 -0
- vibe_surf/langflow/graph/graph/constants.py +58 -0
- vibe_surf/langflow/graph/graph/runnable_vertices_manager.py +133 -0
- vibe_surf/langflow/graph/graph/schema.py +53 -0
- vibe_surf/langflow/graph/graph/state_model.py +66 -0
- vibe_surf/langflow/graph/graph/utils.py +1024 -0
- vibe_surf/langflow/graph/schema.py +75 -0
- vibe_surf/langflow/graph/state/__init__.py +0 -0
- vibe_surf/langflow/graph/state/model.py +237 -0
- vibe_surf/langflow/graph/utils.py +229 -0
- vibe_surf/langflow/graph/vertex/__init__.py +0 -0
- vibe_surf/langflow/graph/vertex/base.py +811 -0
- vibe_surf/langflow/graph/vertex/constants.py +0 -0
- vibe_surf/langflow/graph/vertex/exceptions.py +4 -0
- vibe_surf/langflow/graph/vertex/param_handler.py +255 -0
- vibe_surf/langflow/graph/vertex/schema.py +27 -0
- vibe_surf/langflow/graph/vertex/utils.py +19 -0
- vibe_surf/langflow/graph/vertex/vertex_types.py +489 -0
- vibe_surf/langflow/helpers/__init__.py +3 -0
- vibe_surf/langflow/helpers/base_model.py +71 -0
- vibe_surf/langflow/helpers/custom.py +13 -0
- vibe_surf/langflow/helpers/data.py +206 -0
- vibe_surf/langflow/helpers/flow.py +359 -0
- vibe_surf/langflow/helpers/folders.py +26 -0
- vibe_surf/langflow/helpers/user.py +27 -0
- vibe_surf/langflow/initial_setup/__init__.py +0 -0
- vibe_surf/langflow/initial_setup/constants.py +2 -0
- vibe_surf/langflow/initial_setup/load.py +21 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-01.svg +102 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-02.svg +135 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-03.svg +126 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-04.svg +132 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-05.svg +151 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-06.svg +132 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-07.svg +138 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-08.svg +125 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-09.svg +137 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-10.svg +109 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-11.svg +140 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-12.svg +99 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-13.svg +118 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-14.svg +99 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-15.svg +90 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-16.svg +106 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-17.svg +97 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-18.svg +128 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-19.svg +100 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-20.svg +101 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-21.svg +134 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-22.svg +127 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-23.svg +120 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-24.svg +110 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-25.svg +79 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-26.svg +98 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-01-27.svg +113 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-01.svg +113 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-02.svg +167 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-03.svg +91 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-04.svg +114 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-05.svg +71 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-06.svg +105 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-07.svg +101 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-08.svg +92 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-09.svg +91 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-10.svg +110 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-11.svg +102 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-12.svg +92 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-13.svg +77 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-14.svg +99 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-15.svg +81 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-16.svg +91 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-17.svg +100 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-18.svg +99 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-19.svg +155 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-20.svg +110 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-21.svg +128 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-22.svg +90 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-23.svg +117 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-24.svg +100 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-25.svg +97 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-26.svg +105 -0
- vibe_surf/langflow/initial_setup/profile_pictures/People/People Avatar-02-27.svg +82 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/026-alien.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/027-satellite.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/028-alien.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/029-telescope.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/030-books.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/031-planet.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/032-constellation.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/033-planet.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/034-alien.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/035-globe.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/036-eclipse.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/037-meteor.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/038-eclipse.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/039-Asteroid.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/040-mission.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/041-spaceship.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/042-space shuttle.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/043-space shuttle.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/044-rocket.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/045-astronaut.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/046-rocket.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/047-computer.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/048-satellite.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/049-astronaut.svg +1 -0
- vibe_surf/langflow/initial_setup/profile_pictures/Space/050-space robot.svg +1 -0
- vibe_surf/langflow/initial_setup/setup.py +1108 -0
- vibe_surf/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json +1976 -0
- vibe_surf/langflow/initial_setup/starter_projects/Basic Prompting.json +1051 -0
- vibe_surf/langflow/initial_setup/starter_projects/Blog Writer.json +1529 -0
- vibe_surf/langflow/initial_setup/starter_projects/Custom Component Generator.json +2671 -0
- vibe_surf/langflow/initial_setup/starter_projects/Document Q&A.json +1522 -0
- vibe_surf/langflow/initial_setup/starter_projects/Financial Report Parser.json +1418 -0
- vibe_surf/langflow/initial_setup/starter_projects/Hybrid Search RAG.json +2718 -0
- vibe_surf/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json +1884 -0
- vibe_surf/langflow/initial_setup/starter_projects/Instagram Copywriter.json +3069 -0
- vibe_surf/langflow/initial_setup/starter_projects/Invoice Summarizer.json +1666 -0
- vibe_surf/langflow/initial_setup/starter_projects/Knowledge Ingestion.json +1042 -0
- vibe_surf/langflow/initial_setup/starter_projects/Knowledge Retrieval.json +630 -0
- vibe_surf/langflow/initial_setup/starter_projects/Market Research.json +2532 -0
- vibe_surf/langflow/initial_setup/starter_projects/Meeting Summary.json +3263 -0
- vibe_surf/langflow/initial_setup/starter_projects/Memory Chatbot.json +1419 -0
- vibe_surf/langflow/initial_setup/starter_projects/News Aggregator.json +1835 -0
- vibe_surf/langflow/initial_setup/starter_projects/Nvidia Remix.json +4866 -0
- vibe_surf/langflow/initial_setup/starter_projects/Pok/303/251dex Agent.json" +1739 -0
- vibe_surf/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json +2243 -0
- vibe_surf/langflow/initial_setup/starter_projects/Price Deal Finder.json +2099 -0
- vibe_surf/langflow/initial_setup/starter_projects/Research Agent.json +3032 -0
- vibe_surf/langflow/initial_setup/starter_projects/Research Translation Loop.json +1616 -0
- vibe_surf/langflow/initial_setup/starter_projects/SEO Keyword Generator.json +1091 -0
- vibe_surf/langflow/initial_setup/starter_projects/SaaS Pricing.json +1416 -0
- vibe_surf/langflow/initial_setup/starter_projects/Search agent.json +1455 -0
- vibe_surf/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json +4101 -0
- vibe_surf/langflow/initial_setup/starter_projects/Simple Agent.json +1841 -0
- vibe_surf/langflow/initial_setup/starter_projects/Social Media Agent.json +1759 -0
- vibe_surf/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json +2557 -0
- vibe_surf/langflow/initial_setup/starter_projects/Travel Planning Agents.json +3448 -0
- vibe_surf/langflow/initial_setup/starter_projects/Twitter Thread Generator.json +1978 -0
- vibe_surf/langflow/initial_setup/starter_projects/Vector Store RAG.json +4850 -0
- vibe_surf/langflow/initial_setup/starter_projects/Youtube Analysis.json +2734 -0
- vibe_surf/langflow/initial_setup/starter_projects/__init__.py +19 -0
- vibe_surf/langflow/initial_setup/starter_projects/basic_prompting.py +28 -0
- vibe_surf/langflow/initial_setup/starter_projects/blog_writer.py +46 -0
- vibe_surf/langflow/initial_setup/starter_projects/complex_agent.py +96 -0
- vibe_surf/langflow/initial_setup/starter_projects/document_qa.py +39 -0
- vibe_surf/langflow/initial_setup/starter_projects/hierarchical_tasks_agent.py +69 -0
- vibe_surf/langflow/initial_setup/starter_projects/memory_chatbot.py +31 -0
- vibe_surf/langflow/initial_setup/starter_projects/sequential_tasks_agent.py +97 -0
- vibe_surf/langflow/initial_setup/starter_projects/vector_store_rag.py +61 -0
- vibe_surf/langflow/inputs/__init__.py +68 -0
- vibe_surf/langflow/inputs/constants.py +2 -0
- vibe_surf/langflow/inputs/input_mixin.py +312 -0
- vibe_surf/langflow/inputs/inputs.py +706 -0
- vibe_surf/langflow/inputs/utils.py +32 -0
- vibe_surf/langflow/inputs/validators.py +19 -0
- vibe_surf/langflow/interface/__init__.py +0 -0
- vibe_surf/langflow/interface/components.py +496 -0
- vibe_surf/langflow/interface/importing/__init__.py +5 -0
- vibe_surf/langflow/interface/importing/utils.py +39 -0
- vibe_surf/langflow/interface/initialize/__init__.py +3 -0
- vibe_surf/langflow/interface/initialize/loading.py +200 -0
- vibe_surf/langflow/interface/listing.py +26 -0
- vibe_surf/langflow/interface/run.py +45 -0
- vibe_surf/langflow/interface/utils.py +112 -0
- vibe_surf/langflow/io/__init__.py +63 -0
- vibe_surf/langflow/io/schema.py +304 -0
- vibe_surf/langflow/langflow_launcher.py +51 -0
- vibe_surf/langflow/legacy_custom/__init__.py +0 -0
- vibe_surf/langflow/legacy_custom/customs.py +16 -0
- vibe_surf/langflow/load/__init__.py +12 -0
- vibe_surf/langflow/load/load.py +250 -0
- vibe_surf/langflow/load/utils.py +126 -0
- vibe_surf/langflow/logging/__init__.py +4 -0
- vibe_surf/langflow/logging/logger.py +407 -0
- vibe_surf/langflow/logging/setup.py +16 -0
- vibe_surf/langflow/main.py +550 -0
- vibe_surf/langflow/memory.py +326 -0
- vibe_surf/langflow/middleware.py +59 -0
- vibe_surf/langflow/processing/__init__.py +0 -0
- vibe_surf/langflow/processing/process.py +216 -0
- vibe_surf/langflow/processing/utils.py +25 -0
- vibe_surf/langflow/py.typed +0 -0
- vibe_surf/langflow/schema/__init__.py +6 -0
- vibe_surf/langflow/schema/artifact.py +82 -0
- vibe_surf/langflow/schema/content_block.py +62 -0
- vibe_surf/langflow/schema/content_types.py +91 -0
- vibe_surf/langflow/schema/data.py +306 -0
- vibe_surf/langflow/schema/dataframe.py +206 -0
- vibe_surf/langflow/schema/dotdict.py +71 -0
- vibe_surf/langflow/schema/encoders.py +13 -0
- vibe_surf/langflow/schema/graph.py +47 -0
- vibe_surf/langflow/schema/image.py +128 -0
- vibe_surf/langflow/schema/log.py +33 -0
- vibe_surf/langflow/schema/message.py +483 -0
- vibe_surf/langflow/schema/openai_responses_schemas.py +74 -0
- vibe_surf/langflow/schema/playground_events.py +182 -0
- vibe_surf/langflow/schema/properties.py +39 -0
- vibe_surf/langflow/schema/schema.py +121 -0
- vibe_surf/langflow/schema/serialize.py +14 -0
- vibe_surf/langflow/schema/table.py +140 -0
- vibe_surf/langflow/schema/validators.py +114 -0
- vibe_surf/langflow/serialization/__init__.py +3 -0
- vibe_surf/langflow/serialization/constants.py +2 -0
- vibe_surf/langflow/serialization/serialization.py +320 -0
- vibe_surf/langflow/server.py +70 -0
- vibe_surf/langflow/services/__init__.py +4 -0
- vibe_surf/langflow/services/auth/__init__.py +0 -0
- vibe_surf/langflow/services/auth/factory.py +15 -0
- vibe_surf/langflow/services/auth/mcp_encryption.py +120 -0
- vibe_surf/langflow/services/auth/service.py +15 -0
- vibe_surf/langflow/services/auth/utils.py +583 -0
- vibe_surf/langflow/services/base.py +28 -0
- vibe_surf/langflow/services/cache/__init__.py +12 -0
- vibe_surf/langflow/services/cache/base.py +183 -0
- vibe_surf/langflow/services/cache/disk.py +95 -0
- vibe_surf/langflow/services/cache/factory.py +44 -0
- vibe_surf/langflow/services/cache/service.py +355 -0
- vibe_surf/langflow/services/cache/utils.py +169 -0
- vibe_surf/langflow/services/chat/__init__.py +0 -0
- vibe_surf/langflow/services/chat/cache.py +150 -0
- vibe_surf/langflow/services/chat/config.py +2 -0
- vibe_surf/langflow/services/chat/factory.py +11 -0
- vibe_surf/langflow/services/chat/schema.py +10 -0
- vibe_surf/langflow/services/chat/service.py +67 -0
- vibe_surf/langflow/services/database/__init__.py +0 -0
- vibe_surf/langflow/services/database/factory.py +21 -0
- vibe_surf/langflow/services/database/models/__init__.py +19 -0
- vibe_surf/langflow/services/database/models/api_key/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/api_key/crud.py +74 -0
- vibe_surf/langflow/services/database/models/api_key/model.py +66 -0
- vibe_surf/langflow/services/database/models/base.py +17 -0
- vibe_surf/langflow/services/database/models/file/__init__.py +5 -0
- vibe_surf/langflow/services/database/models/file/crud.py +14 -0
- vibe_surf/langflow/services/database/models/file/model.py +19 -0
- vibe_surf/langflow/services/database/models/flow/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/flow/model.py +283 -0
- vibe_surf/langflow/services/database/models/flow/schema.py +6 -0
- vibe_surf/langflow/services/database/models/flow/utils.py +42 -0
- vibe_surf/langflow/services/database/models/folder/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/folder/constants.py +2 -0
- vibe_surf/langflow/services/database/models/folder/model.py +61 -0
- vibe_surf/langflow/services/database/models/folder/pagination_model.py +10 -0
- vibe_surf/langflow/services/database/models/folder/utils.py +45 -0
- vibe_surf/langflow/services/database/models/message/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/message/crud.py +26 -0
- vibe_surf/langflow/services/database/models/message/model.py +182 -0
- vibe_surf/langflow/services/database/models/transactions/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/transactions/crud.py +82 -0
- vibe_surf/langflow/services/database/models/transactions/model.py +65 -0
- vibe_surf/langflow/services/database/models/user/__init__.py +8 -0
- vibe_surf/langflow/services/database/models/user/crud.py +69 -0
- vibe_surf/langflow/services/database/models/user/model.py +82 -0
- vibe_surf/langflow/services/database/models/variable/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/variable/model.py +73 -0
- vibe_surf/langflow/services/database/models/vertex_builds/__init__.py +3 -0
- vibe_surf/langflow/services/database/models/vertex_builds/crud.py +145 -0
- vibe_surf/langflow/services/database/models/vertex_builds/model.py +83 -0
- vibe_surf/langflow/services/database/service.py +485 -0
- vibe_surf/langflow/services/database/session.py +62 -0
- vibe_surf/langflow/services/database/utils.py +88 -0
- vibe_surf/langflow/services/deps.py +259 -0
- vibe_surf/langflow/services/factory.py +88 -0
- vibe_surf/langflow/services/flow/__init__.py +0 -0
- vibe_surf/langflow/services/flow/flow_runner.py +265 -0
- vibe_surf/langflow/services/job_queue/__init__.py +0 -0
- vibe_surf/langflow/services/job_queue/factory.py +11 -0
- vibe_surf/langflow/services/job_queue/service.py +328 -0
- vibe_surf/langflow/services/manager.py +149 -0
- vibe_surf/langflow/services/mcp_composer/__init__.py +6 -0
- vibe_surf/langflow/services/mcp_composer/factory.py +15 -0
- vibe_surf/langflow/services/mcp_composer/service.py +591 -0
- vibe_surf/langflow/services/schema.py +23 -0
- vibe_surf/langflow/services/session/__init__.py +0 -0
- vibe_surf/langflow/services/session/factory.py +18 -0
- vibe_surf/langflow/services/session/service.py +63 -0
- vibe_surf/langflow/services/session/utils.py +18 -0
- vibe_surf/langflow/services/settings/__init__.py +3 -0
- vibe_surf/langflow/services/settings/auth.py +133 -0
- vibe_surf/langflow/services/settings/base.py +587 -0
- vibe_surf/langflow/services/settings/constants.py +34 -0
- vibe_surf/langflow/services/settings/factory.py +22 -0
- vibe_surf/langflow/services/settings/feature_flags.py +11 -0
- vibe_surf/langflow/services/settings/manager.py +49 -0
- vibe_surf/langflow/services/settings/service.py +32 -0
- vibe_surf/langflow/services/settings/utils.py +40 -0
- vibe_surf/langflow/services/shared_component_cache/__init__.py +0 -0
- vibe_surf/langflow/services/shared_component_cache/factory.py +18 -0
- vibe_surf/langflow/services/shared_component_cache/service.py +7 -0
- vibe_surf/langflow/services/socket/__init__.py +0 -0
- vibe_surf/langflow/services/socket/factory.py +20 -0
- vibe_surf/langflow/services/socket/service.py +84 -0
- vibe_surf/langflow/services/socket/utils.py +112 -0
- vibe_surf/langflow/services/state/__init__.py +0 -0
- vibe_surf/langflow/services/state/factory.py +16 -0
- vibe_surf/langflow/services/state/service.py +82 -0
- vibe_surf/langflow/services/storage/__init__.py +0 -0
- vibe_surf/langflow/services/storage/constants.py +28 -0
- vibe_surf/langflow/services/storage/factory.py +30 -0
- vibe_surf/langflow/services/storage/local.py +127 -0
- vibe_surf/langflow/services/storage/s3.py +105 -0
- vibe_surf/langflow/services/storage/service.py +51 -0
- vibe_surf/langflow/services/storage/utils.py +5 -0
- vibe_surf/langflow/services/store/__init__.py +0 -0
- vibe_surf/langflow/services/store/exceptions.py +25 -0
- vibe_surf/langflow/services/store/factory.py +20 -0
- vibe_surf/langflow/services/store/schema.py +74 -0
- vibe_surf/langflow/services/store/service.py +600 -0
- vibe_surf/langflow/services/store/utils.py +67 -0
- vibe_surf/langflow/services/task/__init__.py +0 -0
- vibe_surf/langflow/services/task/backends/__init__.py +0 -0
- vibe_surf/langflow/services/task/backends/anyio.py +117 -0
- vibe_surf/langflow/services/task/backends/base.py +15 -0
- vibe_surf/langflow/services/task/backends/celery.py +29 -0
- vibe_surf/langflow/services/task/factory.py +14 -0
- vibe_surf/langflow/services/task/service.py +40 -0
- vibe_surf/langflow/services/task/temp_flow_cleanup.py +136 -0
- vibe_surf/langflow/services/task/utils.py +23 -0
- vibe_surf/langflow/services/telemetry/__init__.py +0 -0
- vibe_surf/langflow/services/telemetry/factory.py +20 -0
- vibe_surf/langflow/services/telemetry/opentelemetry.py +253 -0
- vibe_surf/langflow/services/telemetry/schema.py +45 -0
- vibe_surf/langflow/services/telemetry/service.py +281 -0
- vibe_surf/langflow/services/tracing/__init__.py +0 -0
- vibe_surf/langflow/services/tracing/arize_phoenix.py +375 -0
- vibe_surf/langflow/services/tracing/base.py +71 -0
- vibe_surf/langflow/services/tracing/factory.py +20 -0
- vibe_surf/langflow/services/tracing/langfuse.py +170 -0
- vibe_surf/langflow/services/tracing/langsmith.py +208 -0
- vibe_surf/langflow/services/tracing/langwatch.py +185 -0
- vibe_surf/langflow/services/tracing/opik.py +235 -0
- vibe_surf/langflow/services/tracing/schema.py +20 -0
- vibe_surf/langflow/services/tracing/service.py +460 -0
- vibe_surf/langflow/services/tracing/traceloop.py +244 -0
- vibe_surf/langflow/services/tracing/utils.py +29 -0
- vibe_surf/langflow/services/utils.py +246 -0
- vibe_surf/langflow/services/variable/__init__.py +0 -0
- vibe_surf/langflow/services/variable/base.py +119 -0
- vibe_surf/langflow/services/variable/constants.py +2 -0
- vibe_surf/langflow/services/variable/factory.py +28 -0
- vibe_surf/langflow/services/variable/kubernetes.py +204 -0
- vibe_surf/langflow/services/variable/kubernetes_secrets.py +193 -0
- vibe_surf/langflow/services/variable/service.py +195 -0
- vibe_surf/langflow/settings.py +12 -0
- vibe_surf/langflow/template/__init__.py +10 -0
- vibe_surf/langflow/template/field/__init__.py +0 -0
- vibe_surf/langflow/template/field/base.py +257 -0
- vibe_surf/langflow/template/field/prompt.py +2 -0
- vibe_surf/langflow/template/frontend_node/__init__.py +6 -0
- vibe_surf/langflow/template/frontend_node/base.py +214 -0
- vibe_surf/langflow/template/frontend_node/constants.py +65 -0
- vibe_surf/langflow/template/frontend_node/custom_components.py +97 -0
- vibe_surf/langflow/template/template/__init__.py +0 -0
- vibe_surf/langflow/template/template/base.py +99 -0
- vibe_surf/langflow/template/utils.py +217 -0
- vibe_surf/langflow/type_extraction/__init__.py +0 -0
- vibe_surf/langflow/type_extraction/type_extraction.py +78 -0
- vibe_surf/langflow/utils/__init__.py +0 -0
- vibe_surf/langflow/utils/async_helpers.py +42 -0
- vibe_surf/langflow/utils/component_utils.py +147 -0
- vibe_surf/langflow/utils/compression.py +19 -0
- vibe_surf/langflow/utils/concurrency.py +60 -0
- vibe_surf/langflow/utils/connection_string_parser.py +8 -0
- vibe_surf/langflow/utils/constants.py +205 -0
- vibe_surf/langflow/utils/data_structure.py +212 -0
- vibe_surf/langflow/utils/image.py +102 -0
- vibe_surf/langflow/utils/lazy_load.py +15 -0
- vibe_surf/langflow/utils/migration.py +61 -0
- vibe_surf/langflow/utils/payload.py +84 -0
- vibe_surf/langflow/utils/schemas.py +117 -0
- vibe_surf/langflow/utils/template_validation.py +284 -0
- vibe_surf/langflow/utils/util.py +479 -0
- vibe_surf/langflow/utils/util_strings.py +56 -0
- vibe_surf/langflow/utils/validate.py +489 -0
- vibe_surf/langflow/utils/version.py +72 -0
- vibe_surf/langflow/utils/voice_utils.py +92 -0
- vibe_surf/langflow/worker.py +37 -0
- vibe_surf/llm/__init__.py +21 -0
- vibe_surf/llm/openai_compatible.py +372 -0
- vibe_surf/logger.py +99 -0
- vibe_surf/telemetry/__init__.py +60 -0
- vibe_surf/telemetry/service.py +113 -0
- vibe_surf/telemetry/views.py +188 -0
- vibe_surf/tools/__init__.py +0 -0
- vibe_surf/tools/browser_use_tools.py +492 -0
- vibe_surf/tools/composio_client.py +458 -0
- vibe_surf/tools/file_system.py +437 -0
- vibe_surf/tools/finance_tools.py +629 -0
- vibe_surf/tools/mcp_client.py +84 -0
- vibe_surf/tools/report_writer_tools.py +22 -0
- vibe_surf/tools/utils.py +1793 -0
- vibe_surf/tools/vibesurf_registry.py +52 -0
- vibe_surf/tools/vibesurf_tools.py +2277 -0
- vibe_surf/tools/views.py +365 -0
- vibe_surf/tools/voice_asr.py +125 -0
- vibe_surf/tools/website_api/__init__.py +0 -0
- vibe_surf/tools/website_api/douyin/__init__.py +0 -0
- vibe_surf/tools/website_api/douyin/client.py +848 -0
- vibe_surf/tools/website_api/douyin/helpers.py +239 -0
- vibe_surf/tools/website_api/newsnow/__init__.py +0 -0
- vibe_surf/tools/website_api/newsnow/client.py +385 -0
- vibe_surf/tools/website_api/newsnow/helpers.py +118 -0
- vibe_surf/tools/website_api/newsnow/sources.json +385 -0
- vibe_surf/tools/website_api/weibo/__init__.py +0 -0
- vibe_surf/tools/website_api/weibo/client.py +767 -0
- vibe_surf/tools/website_api/weibo/helpers.py +997 -0
- vibe_surf/tools/website_api/xhs/__init__.py +0 -0
- vibe_surf/tools/website_api/xhs/client.py +804 -0
- vibe_surf/tools/website_api/xhs/helpers.py +302 -0
- vibe_surf/tools/website_api/youtube/__init__.py +32 -0
- vibe_surf/tools/website_api/youtube/client.py +1267 -0
- vibe_surf/tools/website_api/youtube/helpers.py +420 -0
- vibe_surf/utils.py +34 -0
- vibe_surf/workflows/AIGC/genai_image_generator.py +284 -0
- vibe_surf/workflows/AIGC/media_viewer.py +127 -0
- vibe_surf/workflows/AIGC/vertex_image_generator.py +259 -0
- vibe_surf/workflows/Browser/browser_click_element.py +195 -0
- vibe_surf/workflows/Browser/browser_download_media.py +113 -0
- vibe_surf/workflows/Browser/browser_drag_drop.py +81 -0
- vibe_surf/workflows/Browser/browser_evaluate_js.py +178 -0
- vibe_surf/workflows/Browser/browser_extract_content.py +197 -0
- vibe_surf/workflows/Browser/browser_focus_element.py +153 -0
- vibe_surf/workflows/Browser/browser_generate_js.py +85 -0
- vibe_surf/workflows/Browser/browser_go_back.py +45 -0
- vibe_surf/workflows/Browser/browser_go_forward.py +44 -0
- vibe_surf/workflows/Browser/browser_hover_element.py +154 -0
- vibe_surf/workflows/Browser/browser_html_content.py +73 -0
- vibe_surf/workflows/Browser/browser_input_text.py +169 -0
- vibe_surf/workflows/Browser/browser_navigate.py +50 -0
- vibe_surf/workflows/Browser/browser_new_tab.py +50 -0
- vibe_surf/workflows/Browser/browser_page_info.py +67 -0
- vibe_surf/workflows/Browser/browser_press_key.py +51 -0
- vibe_surf/workflows/Browser/browser_reload.py +44 -0
- vibe_surf/workflows/Browser/browser_scroll.py +99 -0
- vibe_surf/workflows/Browser/browser_search.py +88 -0
- vibe_surf/workflows/Browser/browser_select_options.py +94 -0
- vibe_surf/workflows/Browser/browser_session.py +54 -0
- vibe_surf/workflows/Browser/browser_take_screenshot.py +127 -0
- vibe_surf/workflows/Browser/browser_upload_file.py +182 -0
- vibe_surf/workflows/Browser/browser_wait.py +46 -0
- vibe_surf/workflows/Browser/close_browser_session.py +51 -0
- vibe_surf/workflows/FileSystem/extract_content_from_file.py +112 -0
- vibe_surf/workflows/FileSystem/load_json.py +136 -0
- vibe_surf/workflows/Integrations/composio_api.py +279 -0
- vibe_surf/workflows/Integrations/douyin.py +232 -0
- vibe_surf/workflows/Integrations/dropbox_compnent.py +11 -0
- vibe_surf/workflows/Integrations/github_composio.py +11 -0
- vibe_surf/workflows/Integrations/gmail_composio.py +38 -0
- vibe_surf/workflows/Integrations/googlecalendar_composio.py +11 -0
- vibe_surf/workflows/Integrations/googlemeet_composio.py +11 -0
- vibe_surf/workflows/Integrations/googletasks_composio.py +8 -0
- vibe_surf/workflows/Integrations/linear_composio.py +11 -0
- vibe_surf/workflows/Integrations/newsnow.py +121 -0
- vibe_surf/workflows/Integrations/outlook_composio.py +11 -0
- vibe_surf/workflows/Integrations/reddit_composio.py +11 -0
- vibe_surf/workflows/Integrations/slack_composio.py +11 -0
- vibe_surf/workflows/Integrations/slackbot_composio.py +11 -0
- vibe_surf/workflows/Integrations/supabase_composio.py +11 -0
- vibe_surf/workflows/Integrations/todoist_composio.py +11 -0
- vibe_surf/workflows/Integrations/weibo.py +244 -0
- vibe_surf/workflows/Integrations/xiaohongshu.py +229 -0
- vibe_surf/workflows/Integrations/yahoo.py +103 -0
- vibe_surf/workflows/Integrations/youtube.py +251 -0
- vibe_surf/workflows/Integrations/youtube_composio.py +11 -0
- vibe_surf/workflows/VibeSurf/advanced_search.py +115 -0
- vibe_surf/workflows/VibeSurf/browser_use_agent.py +150 -0
- vibe_surf/workflows/VibeSurf/llm_profiles.py +103 -0
- vibe_surf/workflows/VibeSurf/select_dataframe.py +44 -0
- vibe_surf/workflows/VibeSurf/structured_output.py +154 -0
- vibe_surf/workflows/VibeSurf/variable_manager.py +140 -0
- vibe_surf/workflows/VibeSurf/vibesurf_agent.py +113 -0
- vibesurf-0.2.40.dist-info/METADATA +432 -0
- vibesurf-0.2.40.dist-info/RECORD +2921 -0
- vibesurf-0.2.40.dist-info/WHEEL +5 -0
- vibesurf-0.2.40.dist-info/entry_points.txt +2 -0
- vibesurf-0.2.40.dist-info/licenses/LICENSE +22 -0
- vibesurf-0.2.40.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,3799 @@
|
|
|
1
|
+
// UI Manager - Core UI management and session interaction
|
|
2
|
+
// Coordinates with specialized modules for settings, history, files, and modals
|
|
3
|
+
|
|
4
|
+
class VibeSurfUIManager {
|
|
5
|
+
constructor(sessionManager, apiClient) {
|
|
6
|
+
this.sessionManager = sessionManager;
|
|
7
|
+
this.apiClient = apiClient;
|
|
8
|
+
this.elements = {};
|
|
9
|
+
this.state = {
|
|
10
|
+
isLoading: false,
|
|
11
|
+
isTaskRunning: false,
|
|
12
|
+
taskInfo: null
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// Initialize specialized managers
|
|
16
|
+
this.settingsManager = null;
|
|
17
|
+
this.historyManager = null;
|
|
18
|
+
this.fileManager = null;
|
|
19
|
+
this.modalManager = null;
|
|
20
|
+
this.voiceRecorder = null;
|
|
21
|
+
this.newsCarousel = null;
|
|
22
|
+
|
|
23
|
+
// Initialize user settings storage
|
|
24
|
+
this.userSettingsStorage = null;
|
|
25
|
+
|
|
26
|
+
// Track if we're currently restoring selections to prevent override
|
|
27
|
+
this.isRestoringSelections = false;
|
|
28
|
+
|
|
29
|
+
this.bindElements();
|
|
30
|
+
this.initializeTabSelector(); // Initialize tab selector before binding events
|
|
31
|
+
this.initializeSkillSelector(); // Initialize skill selector
|
|
32
|
+
this.initializeManagers();
|
|
33
|
+
this.bindEvents();
|
|
34
|
+
this.setupSessionListeners();
|
|
35
|
+
this.initializeSocialLinks();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
bindElements() {
|
|
39
|
+
// Main UI elements
|
|
40
|
+
this.elements = {
|
|
41
|
+
// Header elements
|
|
42
|
+
newSessionBtn: document.getElementById('new-session-btn'),
|
|
43
|
+
upgradeBtn: document.getElementById('upgrade-btn'),
|
|
44
|
+
historyBtn: document.getElementById('history-btn'),
|
|
45
|
+
settingsBtn: document.getElementById('settings-btn'),
|
|
46
|
+
|
|
47
|
+
// Session info
|
|
48
|
+
sessionId: document.getElementById('session-id'),
|
|
49
|
+
copySessionBtn: document.getElementById('copy-session-btn'),
|
|
50
|
+
|
|
51
|
+
// Activity area
|
|
52
|
+
activityLog: document.getElementById('activity-log'),
|
|
53
|
+
|
|
54
|
+
// Control panel
|
|
55
|
+
controlPanel: document.getElementById('control-panel'),
|
|
56
|
+
cancelBtn: document.getElementById('cancel-btn'),
|
|
57
|
+
resumeBtn: document.getElementById('resume-btn'),
|
|
58
|
+
terminateBtn: document.getElementById('terminate-btn'),
|
|
59
|
+
|
|
60
|
+
// Input area
|
|
61
|
+
llmProfileSelect: document.getElementById('llm-profile-select'),
|
|
62
|
+
agentModeSelect: document.getElementById('agent-mode-select'),
|
|
63
|
+
taskInput: document.getElementById('task-input'),
|
|
64
|
+
sendBtn: document.getElementById('send-btn'),
|
|
65
|
+
voiceRecordBtn: document.getElementById('voice-record-btn'),
|
|
66
|
+
|
|
67
|
+
// Tab selector elements
|
|
68
|
+
tabSelectorDropdown: document.getElementById('tab-selector-dropdown'),
|
|
69
|
+
tabSelectorCancel: document.getElementById('tab-selector-cancel'),
|
|
70
|
+
tabSelectorConfirm: document.getElementById('tab-selector-confirm'),
|
|
71
|
+
selectAllTabs: document.getElementById('select-all-tabs'),
|
|
72
|
+
tabOptionsList: document.getElementById('tab-options-list'),
|
|
73
|
+
|
|
74
|
+
// Skill selector elements
|
|
75
|
+
skillSelectorDropdown: document.getElementById('skill-selector-dropdown'),
|
|
76
|
+
skillOptionsList: document.getElementById('skill-options-list'),
|
|
77
|
+
|
|
78
|
+
// Loading
|
|
79
|
+
loadingOverlay: document.getElementById('loading-overlay')
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Validate critical elements
|
|
83
|
+
const criticalElements = ['activityLog', 'taskInput', 'sendBtn', 'sessionId'];
|
|
84
|
+
for (const key of criticalElements) {
|
|
85
|
+
if (!this.elements[key]) {
|
|
86
|
+
console.error(`[UIManager] Critical element not found: ${key}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
initializeManagers() {
|
|
92
|
+
try {
|
|
93
|
+
// Initialize modal manager first (others may depend on it)
|
|
94
|
+
this.modalManager = new VibeSurfModalManager();
|
|
95
|
+
|
|
96
|
+
// Initialize user settings storage
|
|
97
|
+
this.userSettingsStorage = new VibeSurfUserSettingsStorage();
|
|
98
|
+
|
|
99
|
+
// Initialize voice recorder
|
|
100
|
+
this.voiceRecorder = new VibeSurfVoiceRecorder(this.apiClient);
|
|
101
|
+
this.setupVoiceRecorderCallbacks();
|
|
102
|
+
|
|
103
|
+
// Initialize news carousel
|
|
104
|
+
console.log('[UIManager] Creating NewsCarouselManager...');
|
|
105
|
+
this.newsCarousel = new NewsCarouselManager(this.apiClient);
|
|
106
|
+
console.log('[UIManager] NewsCarouselManager created:', !!this.newsCarousel);
|
|
107
|
+
|
|
108
|
+
// Initialize other managers
|
|
109
|
+
this.settingsManager = new VibeSurfSettingsManager(this.apiClient);
|
|
110
|
+
this.historyManager = new VibeSurfHistoryManager(this.apiClient);
|
|
111
|
+
this.fileManager = new VibeSurfFileManager(this.sessionManager);
|
|
112
|
+
|
|
113
|
+
// Set up inter-manager communication
|
|
114
|
+
this.setupManagerEvents();
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('[UIManager] Failed to initialize managers:', error);
|
|
119
|
+
this.showNotification('Failed to initialize UI components', 'error');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
setupManagerEvents() {
|
|
124
|
+
// Settings Manager Events
|
|
125
|
+
this.settingsManager.on('profilesUpdated', () => {
|
|
126
|
+
// Only update the profile select if we're not in the middle of restoring selections
|
|
127
|
+
// This prevents the profilesUpdated event from overriding user selections during initialization
|
|
128
|
+
if (!this.isRestoringSelections) {
|
|
129
|
+
this.updateLLMProfileSelect();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Also update voice button state when profiles are updated (ASR profiles might have changed)
|
|
133
|
+
this.updateVoiceButtonState();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
this.settingsManager.on('notification', (data) => {
|
|
137
|
+
this.showNotification(data.message, data.type);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
this.settingsManager.on('loading', (data) => {
|
|
141
|
+
if (data.hide) {
|
|
142
|
+
this.hideLoading();
|
|
143
|
+
} else {
|
|
144
|
+
this.showLoading(data.message);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
this.settingsManager.on('error', (data) => {
|
|
149
|
+
console.error('[UIManager] Settings error:', data.error);
|
|
150
|
+
this.showNotification(data.message || 'Settings error occurred', 'error');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
this.settingsManager.on('confirmDeletion', (data) => {
|
|
154
|
+
this.modalManager.showConfirmModal(
|
|
155
|
+
'Delete Profile',
|
|
156
|
+
`Are you sure you want to delete the ${data.type} profile "${data.profileId}"? This action cannot be undone.`,
|
|
157
|
+
{
|
|
158
|
+
confirmText: 'Delete',
|
|
159
|
+
cancelText: 'Cancel',
|
|
160
|
+
type: 'danger',
|
|
161
|
+
onConfirm: () => {
|
|
162
|
+
if (data.callback) data.callback();
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
this.settingsManager.on('selectNewDefault', (data) => {
|
|
169
|
+
const options = data.otherProfiles.map(profile =>
|
|
170
|
+
`<option value="${profile.profile_name}">${profile.profile_name}</option>`
|
|
171
|
+
).join('');
|
|
172
|
+
|
|
173
|
+
const modalData = this.modalManager.createModal(`
|
|
174
|
+
<div class="select-default-modal">
|
|
175
|
+
<p>You are deleting the default LLM profile. Please select a new default profile:</p>
|
|
176
|
+
<select id="new-default-select" class="form-select">
|
|
177
|
+
${options}
|
|
178
|
+
</select>
|
|
179
|
+
<div class="modal-footer">
|
|
180
|
+
<button class="btn-secondary cancel-btn">Cancel</button>
|
|
181
|
+
<button class="btn-primary confirm-btn">Set as Default & Delete</button>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
`, {
|
|
185
|
+
title: 'Select New Default Profile'
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const select = document.getElementById('new-default-select');
|
|
189
|
+
const confirmBtn = modalData.modal.querySelector('.confirm-btn');
|
|
190
|
+
const cancelBtn = modalData.modal.querySelector('.cancel-btn');
|
|
191
|
+
|
|
192
|
+
confirmBtn.addEventListener('click', () => {
|
|
193
|
+
const newDefaultId = select.value;
|
|
194
|
+
if (newDefaultId && data.callback) {
|
|
195
|
+
data.callback(newDefaultId);
|
|
196
|
+
}
|
|
197
|
+
modalData.close();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
cancelBtn.addEventListener('click', () => {
|
|
201
|
+
modalData.close();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// History Manager Events
|
|
206
|
+
this.historyManager.on('loadSession', (data) => {
|
|
207
|
+
this.loadSession(data.sessionId);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
this.historyManager.on('loading', (data) => {
|
|
211
|
+
if (data.hide) {
|
|
212
|
+
this.hideLoading();
|
|
213
|
+
} else {
|
|
214
|
+
this.showLoading(data.message);
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
this.historyManager.on('notification', (data) => {
|
|
219
|
+
this.showNotification(data.message, data.type);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
this.historyManager.on('error', (data) => {
|
|
223
|
+
console.error('[UIManager] History error:', data.error);
|
|
224
|
+
this.showNotification(data.message || 'History error occurred', 'error');
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// File Manager Events
|
|
228
|
+
this.fileManager.on('loading', (data) => {
|
|
229
|
+
if (data.hide) {
|
|
230
|
+
this.hideLoading();
|
|
231
|
+
} else {
|
|
232
|
+
this.showLoading(data.message);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
this.fileManager.on('notification', (data) => {
|
|
237
|
+
this.showNotification(data.message, data.type);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
this.fileManager.on('error', (data) => {
|
|
241
|
+
console.error('[UIManager] File error:', data.error);
|
|
242
|
+
this.showNotification(data.message || 'File error occurred', 'error');
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Modal Manager Events (if needed for future extensions)
|
|
246
|
+
this.modalManager.on('modalClosed', (data) => {
|
|
247
|
+
// Handle modal close events if needed
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Voice Recorder Callbacks
|
|
252
|
+
setupVoiceRecorderCallbacks() {
|
|
253
|
+
this.voiceRecorder.setCallbacks({
|
|
254
|
+
onRecordingStart: () => {
|
|
255
|
+
console.log('[UIManager] Voice recording started');
|
|
256
|
+
this.updateVoiceRecordingUI(true);
|
|
257
|
+
},
|
|
258
|
+
onRecordingStop: (audioBlob, duration) => {
|
|
259
|
+
console.log(`[UIManager] Voice recording stopped after ${duration}ms`);
|
|
260
|
+
this.updateVoiceRecordingUI(false);
|
|
261
|
+
},
|
|
262
|
+
onTranscriptionComplete: (transcribedText, result) => {
|
|
263
|
+
console.log(`[UIManager] Transcription completed: "${transcribedText}"`);
|
|
264
|
+
this.handleTranscriptionComplete(transcribedText);
|
|
265
|
+
},
|
|
266
|
+
onTranscriptionError: (errorMessage, errorType) => {
|
|
267
|
+
console.error(`[UIManager] Transcription error: ${errorMessage}`);
|
|
268
|
+
this.handleTranscriptionError(errorMessage, errorType);
|
|
269
|
+
},
|
|
270
|
+
onDurationUpdate: (formattedDuration, durationMs) => {
|
|
271
|
+
this.updateRecordingDuration(formattedDuration, durationMs);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Update voice recording UI state
|
|
277
|
+
updateVoiceRecordingUI(isRecording) {
|
|
278
|
+
if (this.elements.voiceRecordBtn) {
|
|
279
|
+
if (isRecording) {
|
|
280
|
+
this.elements.voiceRecordBtn.classList.add('recording');
|
|
281
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Stop Recording');
|
|
282
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', 'Recording... Click to stop');
|
|
283
|
+
} else {
|
|
284
|
+
this.elements.voiceRecordBtn.classList.remove('recording');
|
|
285
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Voice Input');
|
|
286
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', 'Click to start voice recording');
|
|
287
|
+
|
|
288
|
+
// Clear duration display
|
|
289
|
+
this.updateRecordingDuration('0:00', 0);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Update recording duration display
|
|
295
|
+
updateRecordingDuration(formattedDuration, durationMs) {
|
|
296
|
+
if (this.elements.voiceRecordBtn) {
|
|
297
|
+
// Update the tooltip with duration
|
|
298
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', `Recording... ${formattedDuration} - Click to stop`);
|
|
299
|
+
|
|
300
|
+
// Create or update duration display element
|
|
301
|
+
let durationElement = this.elements.voiceRecordBtn.querySelector('.recording-duration');
|
|
302
|
+
if (!durationElement) {
|
|
303
|
+
durationElement = document.createElement('div');
|
|
304
|
+
durationElement.className = 'recording-duration';
|
|
305
|
+
this.elements.voiceRecordBtn.appendChild(durationElement);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
durationElement.textContent = formattedDuration;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Handle transcription completion
|
|
313
|
+
handleTranscriptionComplete(transcribedText) {
|
|
314
|
+
if (!this.elements.taskInput) {
|
|
315
|
+
console.error('[UIManager] Task input element not found');
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Insert transcribed text into the input field
|
|
320
|
+
const currentValue = this.elements.taskInput.value;
|
|
321
|
+
const cursorPosition = this.elements.taskInput.selectionStart;
|
|
322
|
+
|
|
323
|
+
// Insert at cursor position or append to end
|
|
324
|
+
const beforeCursor = currentValue.substring(0, cursorPosition);
|
|
325
|
+
const afterCursor = currentValue.substring(cursorPosition);
|
|
326
|
+
const newValue = beforeCursor + transcribedText + afterCursor;
|
|
327
|
+
|
|
328
|
+
this.elements.taskInput.value = newValue;
|
|
329
|
+
|
|
330
|
+
// Trigger input change event for validation and auto-resize
|
|
331
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
332
|
+
|
|
333
|
+
// Set cursor position after the inserted text
|
|
334
|
+
const newCursorPosition = cursorPosition + transcribedText.length;
|
|
335
|
+
this.elements.taskInput.setSelectionRange(newCursorPosition, newCursorPosition);
|
|
336
|
+
this.elements.taskInput.focus();
|
|
337
|
+
|
|
338
|
+
this.showNotification('Voice transcription completed', 'success');
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Handle transcription errors
|
|
342
|
+
handleTranscriptionError(errorMessage, errorType) {
|
|
343
|
+
let userMessage = 'Voice transcription failed';
|
|
344
|
+
|
|
345
|
+
if (errorType === 'recording') {
|
|
346
|
+
userMessage = `Recording failed: ${errorMessage}`;
|
|
347
|
+
} else if (errorType === 'transcription') {
|
|
348
|
+
if (errorMessage.includes('No active ASR profiles')) {
|
|
349
|
+
userMessage = 'No voice recognition profiles configured. Please set up an ASR profile in Settings > Voice.';
|
|
350
|
+
} else {
|
|
351
|
+
userMessage = `Transcription failed: ${errorMessage}`;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
this.showNotification(userMessage, 'error');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
bindEvents() {
|
|
359
|
+
// Header buttons
|
|
360
|
+
this.elements.newSessionBtn?.addEventListener('click', this.handleNewSession.bind(this));
|
|
361
|
+
this.elements.upgradeBtn?.addEventListener('click', this.handleUpgrade.bind(this));
|
|
362
|
+
this.elements.historyBtn?.addEventListener('click', this.handleShowHistory.bind(this));
|
|
363
|
+
this.elements.settingsBtn?.addEventListener('click', this.handleShowSettings.bind(this));
|
|
364
|
+
|
|
365
|
+
// Session controls
|
|
366
|
+
this.elements.copySessionBtn?.addEventListener('click', this.handleCopySession.bind(this));
|
|
367
|
+
|
|
368
|
+
// Task controls
|
|
369
|
+
this.elements.cancelBtn?.addEventListener('click', this.handleCancelTask.bind(this));
|
|
370
|
+
this.elements.resumeBtn?.addEventListener('click', this.handleResumeTask.bind(this));
|
|
371
|
+
this.elements.terminateBtn?.addEventListener('click', this.handleTerminateTask.bind(this));
|
|
372
|
+
|
|
373
|
+
// Input handling
|
|
374
|
+
this.elements.sendBtn?.addEventListener('click', this.handleSendTask.bind(this));
|
|
375
|
+
this.elements.voiceRecordBtn?.addEventListener('click', this.handleVoiceRecord.bind(this));
|
|
376
|
+
|
|
377
|
+
// Task input handling
|
|
378
|
+
this.elements.taskInput?.addEventListener('keydown', this.handleTaskInputKeydown.bind(this));
|
|
379
|
+
this.elements.taskInput?.addEventListener('input', this.handleTaskInputChange.bind(this));
|
|
380
|
+
|
|
381
|
+
// LLM profile selection handling
|
|
382
|
+
this.elements.llmProfileSelect?.addEventListener('change', this.handleLlmProfileChange.bind(this));
|
|
383
|
+
|
|
384
|
+
// Agent mode selection handling
|
|
385
|
+
this.elements.agentModeSelect?.addEventListener('change', this.handleAgentModeChange.bind(this));
|
|
386
|
+
|
|
387
|
+
// Initialize auto-resize for textarea
|
|
388
|
+
if (this.elements.taskInput) {
|
|
389
|
+
this.autoResizeTextarea(this.elements.taskInput);
|
|
390
|
+
// Set initial send button state
|
|
391
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Bind initial task suggestions if present
|
|
395
|
+
this.bindTaskSuggestionEvents();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
setupSessionListeners() {
|
|
399
|
+
// Listen to session manager events
|
|
400
|
+
this.sessionManager.on('sessionCreated', this.handleSessionCreated.bind(this));
|
|
401
|
+
this.sessionManager.on('sessionLoaded', this.handleSessionLoaded.bind(this));
|
|
402
|
+
this.sessionManager.on('taskSubmitted', this.handleTaskSubmitted.bind(this));
|
|
403
|
+
this.sessionManager.on('taskPaused', this.handleTaskPaused.bind(this));
|
|
404
|
+
this.sessionManager.on('taskResumed', this.handleTaskResumed.bind(this));
|
|
405
|
+
this.sessionManager.on('taskStopped', this.handleTaskStopped.bind(this));
|
|
406
|
+
this.sessionManager.on('taskCompleted', this.handleTaskCompleted.bind(this));
|
|
407
|
+
this.sessionManager.on('newActivity', this.handleNewActivity.bind(this));
|
|
408
|
+
this.sessionManager.on('pollingStarted', this.handlePollingStarted.bind(this));
|
|
409
|
+
this.sessionManager.on('pollingStopped', this.handlePollingStopped.bind(this));
|
|
410
|
+
this.sessionManager.on('sessionError', this.handleSessionError.bind(this));
|
|
411
|
+
this.sessionManager.on('taskError', this.handleTaskError.bind(this));
|
|
412
|
+
|
|
413
|
+
// Start periodic task status check
|
|
414
|
+
this.startTaskStatusMonitoring();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Session event handlers
|
|
418
|
+
handleSessionCreated(data) {
|
|
419
|
+
console.log('[UIManager] handleSessionCreated called, sessionId:', data.sessionId);
|
|
420
|
+
this.updateSessionDisplay(data.sessionId);
|
|
421
|
+
this.clearActivityLog();
|
|
422
|
+
this.showWelcomeMessage();
|
|
423
|
+
this.updateControlPanel('ready');
|
|
424
|
+
|
|
425
|
+
// Show news carousel on session creation (including initial load)
|
|
426
|
+
console.log('[UIManager] Checking newsCarousel:', !!this.newsCarousel);
|
|
427
|
+
if (this.newsCarousel) {
|
|
428
|
+
console.log('[UIManager] Showing and initializing news carousel...');
|
|
429
|
+
this.newsCarousel.show();
|
|
430
|
+
this.newsCarousel.initialize().then(() => {
|
|
431
|
+
console.log('[UIManager] News carousel initialized successfully');
|
|
432
|
+
}).catch(error => {
|
|
433
|
+
console.error('[UIManager] Error initializing news carousel:', error);
|
|
434
|
+
});
|
|
435
|
+
} else {
|
|
436
|
+
console.warn('[UIManager] newsCarousel is not initialized');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
handleSessionLoaded(data) {
|
|
441
|
+
// Update session display
|
|
442
|
+
this.updateSessionDisplay(data.sessionId);
|
|
443
|
+
|
|
444
|
+
// Load and display activity logs
|
|
445
|
+
const activityLogs = this.sessionManager.getActivityLogs();
|
|
446
|
+
this.displayActivityLogs(activityLogs);
|
|
447
|
+
|
|
448
|
+
// Update control panel
|
|
449
|
+
const taskStatus = this.sessionManager.getTaskStatus();
|
|
450
|
+
if (taskStatus) {
|
|
451
|
+
this.updateControlPanel(taskStatus);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
handleTaskSubmitted(data) {
|
|
456
|
+
|
|
457
|
+
this.updateControlPanel('running');
|
|
458
|
+
this.clearTaskInput();
|
|
459
|
+
|
|
460
|
+
// Hide news carousel when task starts
|
|
461
|
+
if (this.newsCarousel) {
|
|
462
|
+
this.newsCarousel.hide();
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
handleTaskPaused(data) {
|
|
467
|
+
this.updateControlPanel('paused');
|
|
468
|
+
// Force update UI for paused state - explicitly enable input
|
|
469
|
+
this.forceUpdateUIForPausedState();
|
|
470
|
+
this.showNotification('Task paused successfully', 'info');
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
handleTaskResumed(data) {
|
|
474
|
+
this.updateControlPanel('running');
|
|
475
|
+
// Force update UI for running state - disable input
|
|
476
|
+
this.forceUpdateUIForRunningState();
|
|
477
|
+
this.showNotification('Task resumed successfully', 'info');
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
handleTaskStopped(data) {
|
|
481
|
+
this.updateControlPanel('ready');
|
|
482
|
+
this.showNotification('Task stopped successfully', 'info');
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
handleTaskCompleted(data) {
|
|
486
|
+
|
|
487
|
+
|
|
488
|
+
const message = data.status === 'done' ? 'Task completed successfully!' : 'Task completed with errors';
|
|
489
|
+
const type = data.status === 'done' ? 'success' : 'error';
|
|
490
|
+
|
|
491
|
+
// Check if we need to respect minimum visibility period
|
|
492
|
+
if (this.controlPanelMinVisibilityActive) {
|
|
493
|
+
|
|
494
|
+
const remainingTime = 1000;
|
|
495
|
+
setTimeout(() => {
|
|
496
|
+
|
|
497
|
+
this.updateControlPanel('ready');
|
|
498
|
+
}, remainingTime);
|
|
499
|
+
} else {
|
|
500
|
+
|
|
501
|
+
this.updateControlPanel('ready');
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
this.showNotification(message, type);
|
|
505
|
+
|
|
506
|
+
// Clear uploaded files when task is completed
|
|
507
|
+
this.fileManager.clearUploadedFiles();
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
handleNewActivity(data) {
|
|
511
|
+
this.addActivityLog(data.activity);
|
|
512
|
+
this.scrollActivityToBottom();
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
handlePollingStarted(data) {
|
|
516
|
+
// Could add polling indicator here
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
handlePollingStopped(data) {
|
|
520
|
+
// Could remove polling indicator here
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
handleSessionError(data) {
|
|
524
|
+
console.error('[UIManager] Session error:', data.error);
|
|
525
|
+
this.showNotification(`Session error: ${data.error}`, 'error');
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
handleTaskError(data) {
|
|
529
|
+
console.error('[UIManager] Task error:', data.error);
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
// Check if this is an LLM connection failure
|
|
533
|
+
if (data.error && typeof data.error === 'object' && data.error.error === 'llm_connection_failed') {
|
|
534
|
+
|
|
535
|
+
// Show LLM connection failed modal instead of generic notification
|
|
536
|
+
this.showLLMConnectionFailedModal(data.error);
|
|
537
|
+
this.updateControlPanel('ready'); // Reset UI since task failed to start
|
|
538
|
+
return;
|
|
539
|
+
} else if (data.error && typeof data.error === 'string' && data.error.includes('llm_connection_failed')) {
|
|
540
|
+
|
|
541
|
+
// Handle case where error is a string containing the error type
|
|
542
|
+
this.showLLMConnectionFailedModal({
|
|
543
|
+
message: data.error,
|
|
544
|
+
llm_profile: 'unknown'
|
|
545
|
+
});
|
|
546
|
+
this.updateControlPanel('ready'); // Reset UI since task failed to start
|
|
547
|
+
return;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Default error handling for other types of errors
|
|
551
|
+
this.showNotification(`Task error: ${data.error}`, 'error');
|
|
552
|
+
|
|
553
|
+
this.updateControlPanel('error');
|
|
554
|
+
|
|
555
|
+
// Optional: Verify task status after a delay
|
|
556
|
+
setTimeout(() => {
|
|
557
|
+
this.checkTaskStatus().then(status => {
|
|
558
|
+
if (!status.isRunning) {
|
|
559
|
+
|
|
560
|
+
this.updateControlPanel('ready');
|
|
561
|
+
} else {
|
|
562
|
+
|
|
563
|
+
}
|
|
564
|
+
}).catch(err => {
|
|
565
|
+
console.warn('[UIManager] Could not verify task status after error:', err);
|
|
566
|
+
});
|
|
567
|
+
}, 1000);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Task Status Monitoring
|
|
571
|
+
async checkTaskStatus() {
|
|
572
|
+
try {
|
|
573
|
+
const statusCheck = await this.apiClient.checkTaskRunning();
|
|
574
|
+
const wasRunning = this.state.isTaskRunning;
|
|
575
|
+
|
|
576
|
+
this.state.isTaskRunning = statusCheck.isRunning;
|
|
577
|
+
this.state.taskInfo = statusCheck.taskInfo;
|
|
578
|
+
|
|
579
|
+
// Update UI state when task status changes
|
|
580
|
+
if (wasRunning !== statusCheck.isRunning) {
|
|
581
|
+
this.updateUIForTaskStatus(statusCheck.isRunning);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
return statusCheck;
|
|
585
|
+
} catch (error) {
|
|
586
|
+
console.error('[UIManager] Failed to check task status:', error);
|
|
587
|
+
return { isRunning: false, taskInfo: null };
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
startTaskStatusMonitoring() {
|
|
592
|
+
// Check task status every 500ms
|
|
593
|
+
this.taskStatusInterval = setInterval(() => {
|
|
594
|
+
this.checkTaskStatus();
|
|
595
|
+
}, 500);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
stopTaskStatusMonitoring() {
|
|
599
|
+
if (this.taskStatusInterval) {
|
|
600
|
+
clearInterval(this.taskStatusInterval);
|
|
601
|
+
this.taskStatusInterval = null;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
updateUIForTaskStatus(isRunning) {
|
|
606
|
+
const taskStatus = this.sessionManager.getTaskStatus();
|
|
607
|
+
const isPaused = taskStatus === 'paused';
|
|
608
|
+
|
|
609
|
+
// Disable/enable input elements based on task status
|
|
610
|
+
if (this.elements.taskInput) {
|
|
611
|
+
// Allow input when paused or not running
|
|
612
|
+
this.elements.taskInput.disabled = isRunning && !isPaused;
|
|
613
|
+
if (isPaused) {
|
|
614
|
+
this.elements.taskInput.placeholder = 'Add additional information or guidance...';
|
|
615
|
+
} else if (isRunning) {
|
|
616
|
+
this.elements.taskInput.placeholder = 'Task is running - please wait...';
|
|
617
|
+
} else {
|
|
618
|
+
this.elements.taskInput.placeholder = 'Ask anything (/ for skills, @ to specify tab)';
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
if (this.elements.sendBtn) {
|
|
623
|
+
// Enable send button when paused or when can submit new task
|
|
624
|
+
this.elements.sendBtn.disabled = (isRunning && !isPaused) || (!isPaused && !this.canSubmitTask()) || (isPaused && !this.canAddNewTask());
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (this.elements.llmProfileSelect) {
|
|
628
|
+
// Allow LLM profile change only when not running
|
|
629
|
+
this.elements.llmProfileSelect.disabled = isRunning && !isPaused;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (this.elements.agentModeSelect) {
|
|
633
|
+
// Allow agent mode change only when not running
|
|
634
|
+
this.elements.agentModeSelect.disabled = isRunning && !isPaused;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Update voice record button state - disable during task execution unless paused
|
|
638
|
+
if (this.elements.voiceRecordBtn) {
|
|
639
|
+
const shouldDisableVoice = isRunning && !isPaused;
|
|
640
|
+
this.elements.voiceRecordBtn.disabled = shouldDisableVoice;
|
|
641
|
+
if (shouldDisableVoice) {
|
|
642
|
+
this.elements.voiceRecordBtn.classList.add('task-running-disabled');
|
|
643
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Voice input disabled while task is running');
|
|
644
|
+
} else {
|
|
645
|
+
this.elements.voiceRecordBtn.classList.remove('task-running-disabled');
|
|
646
|
+
if (this.elements.voiceRecordBtn.classList.contains('recording')) {
|
|
647
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Recording... Click to stop');
|
|
648
|
+
} else {
|
|
649
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Click to start voice recording');
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
// Update file manager state - keep disabled during pause (as per requirement)
|
|
655
|
+
this.fileManager.setEnabled(!isRunning);
|
|
656
|
+
|
|
657
|
+
// Also disable header buttons when task is running (but not when paused)
|
|
658
|
+
const headerButtons = [
|
|
659
|
+
this.elements.newSessionBtn,
|
|
660
|
+
this.elements.historyBtn,
|
|
661
|
+
this.elements.settingsBtn
|
|
662
|
+
];
|
|
663
|
+
|
|
664
|
+
headerButtons.forEach(button => {
|
|
665
|
+
if (button) {
|
|
666
|
+
const shouldDisable = isRunning && !isPaused;
|
|
667
|
+
button.disabled = shouldDisable;
|
|
668
|
+
if (shouldDisable) {
|
|
669
|
+
button.classList.add('task-running-disabled');
|
|
670
|
+
button.setAttribute('title', 'Disabled while task is running');
|
|
671
|
+
} else {
|
|
672
|
+
button.classList.remove('task-running-disabled');
|
|
673
|
+
button.removeAttribute('title');
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
forceUpdateUIForPausedState() {
|
|
680
|
+
|
|
681
|
+
// Enable input during pause
|
|
682
|
+
if (this.elements.taskInput) {
|
|
683
|
+
this.elements.taskInput.disabled = false;
|
|
684
|
+
this.elements.taskInput.placeholder = 'Add additional information or guidance...';
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (this.elements.sendBtn) {
|
|
688
|
+
const hasText = this.elements.taskInput?.value.trim().length > 0;
|
|
689
|
+
this.elements.sendBtn.disabled = !hasText;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
// Enable voice record button during pause
|
|
693
|
+
if (this.elements.voiceRecordBtn) {
|
|
694
|
+
this.elements.voiceRecordBtn.disabled = false;
|
|
695
|
+
this.elements.voiceRecordBtn.classList.remove('task-running-disabled');
|
|
696
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Click to start voice recording');
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// Keep LLM profile disabled during pause (user doesn't need to change it)
|
|
700
|
+
if (this.elements.llmProfileSelect) {
|
|
701
|
+
this.elements.llmProfileSelect.disabled = true;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
// Keep agent mode disabled during pause (user doesn't need to change it)
|
|
705
|
+
if (this.elements.agentModeSelect) {
|
|
706
|
+
this.elements.agentModeSelect.disabled = true;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// Keep file manager disabled during pause
|
|
710
|
+
this.fileManager.setEnabled(false);
|
|
711
|
+
|
|
712
|
+
// Keep header buttons disabled during pause (only input, send, and voice should be available)
|
|
713
|
+
const headerButtons = [
|
|
714
|
+
this.elements.newSessionBtn,
|
|
715
|
+
this.elements.historyBtn,
|
|
716
|
+
this.elements.settingsBtn
|
|
717
|
+
];
|
|
718
|
+
|
|
719
|
+
headerButtons.forEach(button => {
|
|
720
|
+
if (button) {
|
|
721
|
+
button.disabled = true;
|
|
722
|
+
button.classList.add('task-running-disabled');
|
|
723
|
+
button.setAttribute('title', 'Disabled during pause - only input, send, and voice input are available');
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
forceUpdateUIForRunningState() {
|
|
729
|
+
|
|
730
|
+
|
|
731
|
+
// Disable input during running
|
|
732
|
+
if (this.elements.taskInput) {
|
|
733
|
+
this.elements.taskInput.disabled = true;
|
|
734
|
+
this.elements.taskInput.placeholder = 'Task is running - please wait...';
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
if (this.elements.sendBtn) {
|
|
738
|
+
this.elements.sendBtn.disabled = true;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (this.elements.llmProfileSelect) {
|
|
742
|
+
this.elements.llmProfileSelect.disabled = true;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
if (this.elements.agentModeSelect) {
|
|
746
|
+
this.elements.agentModeSelect.disabled = true;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// Disable voice record button during running
|
|
750
|
+
if (this.elements.voiceRecordBtn) {
|
|
751
|
+
this.elements.voiceRecordBtn.disabled = true;
|
|
752
|
+
this.elements.voiceRecordBtn.classList.add('task-running-disabled');
|
|
753
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Voice input disabled while task is running');
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
// Update file manager state
|
|
757
|
+
this.fileManager.setEnabled(false);
|
|
758
|
+
|
|
759
|
+
// Disable header buttons when task is running
|
|
760
|
+
const headerButtons = [
|
|
761
|
+
this.elements.newSessionBtn,
|
|
762
|
+
this.elements.historyBtn,
|
|
763
|
+
this.elements.settingsBtn
|
|
764
|
+
];
|
|
765
|
+
|
|
766
|
+
headerButtons.forEach(button => {
|
|
767
|
+
if (button) {
|
|
768
|
+
button.disabled = true;
|
|
769
|
+
button.classList.add('task-running-disabled');
|
|
770
|
+
button.setAttribute('title', 'Disabled while task is running');
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
canSubmitTask() {
|
|
776
|
+
const hasText = this.elements.taskInput?.value.trim().length > 0;
|
|
777
|
+
const llmProfile = this.elements.llmProfileSelect?.value;
|
|
778
|
+
const hasLlmProfile = llmProfile && llmProfile.trim() !== '';
|
|
779
|
+
return hasText && hasLlmProfile && !this.state.isTaskRunning;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
canAddNewTask() {
|
|
783
|
+
const hasText = this.elements.taskInput?.value.trim().length > 0;
|
|
784
|
+
return hasText;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
async showTaskRunningWarning(action) {
|
|
788
|
+
const taskInfo = this.state.taskInfo;
|
|
789
|
+
const taskId = taskInfo?.task_id || 'unknown';
|
|
790
|
+
const sessionId = taskInfo?.session_id || 'unknown';
|
|
791
|
+
|
|
792
|
+
return this.modalManager.showConfirmModalAsync(
|
|
793
|
+
'Task Currently Running',
|
|
794
|
+
`A task is currently ${taskInfo?.status || 'running'}. You must stop the current task before you can ${action}.`,
|
|
795
|
+
{
|
|
796
|
+
confirmText: 'Stop Current Task',
|
|
797
|
+
cancelText: 'Cancel',
|
|
798
|
+
type: 'danger',
|
|
799
|
+
onConfirm: async () => {
|
|
800
|
+
try {
|
|
801
|
+
await this.sessionManager.stopTask('User wants to perform new action');
|
|
802
|
+
return true;
|
|
803
|
+
} catch (error) {
|
|
804
|
+
this.showNotification(`Failed to stop task: ${error.message}`, 'error');
|
|
805
|
+
return false;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// UI Action Handlers
|
|
813
|
+
async handleNewSession() {
|
|
814
|
+
// Enhanced task running check
|
|
815
|
+
const statusCheck = await this.checkTaskStatus();
|
|
816
|
+
if (statusCheck.isRunning) {
|
|
817
|
+
const canProceed = await this.showTaskRunningWarning('create a new session');
|
|
818
|
+
if (!canProceed) return;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
try {
|
|
822
|
+
this.showLoading('Creating new session...');
|
|
823
|
+
|
|
824
|
+
const sessionId = await this.sessionManager.createSession();
|
|
825
|
+
|
|
826
|
+
this.hideLoading();
|
|
827
|
+
} catch (error) {
|
|
828
|
+
this.hideLoading();
|
|
829
|
+
this.showNotification(`Failed to create session: ${error.message}`, 'error');
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
async handleShowHistory() {
|
|
834
|
+
// Enhanced task running check
|
|
835
|
+
const statusCheck = await this.checkTaskStatus();
|
|
836
|
+
if (statusCheck.isRunning) {
|
|
837
|
+
const canProceed = await this.showTaskRunningWarning('view session history');
|
|
838
|
+
if (!canProceed) return;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
this.historyManager.showHistory();
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
async handleShowSettings() {
|
|
845
|
+
// Enhanced task running check
|
|
846
|
+
const statusCheck = await this.checkTaskStatus();
|
|
847
|
+
if (statusCheck.isRunning) {
|
|
848
|
+
const canProceed = await this.showTaskRunningWarning('access settings');
|
|
849
|
+
if (!canProceed) return;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
this.settingsManager.showSettings();
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
async handleShowLLMSettings() {
|
|
856
|
+
// Enhanced task running check
|
|
857
|
+
const statusCheck = await this.checkTaskStatus();
|
|
858
|
+
if (statusCheck.isRunning) {
|
|
859
|
+
const canProceed = await this.showTaskRunningWarning('access settings');
|
|
860
|
+
if (!canProceed) return;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// Show settings and navigate directly to LLM profiles tab
|
|
864
|
+
this.settingsManager.showSettings();
|
|
865
|
+
|
|
866
|
+
// Switch to LLM profiles tab after settings are shown
|
|
867
|
+
setTimeout(() => {
|
|
868
|
+
const llmTab = document.querySelector('.settings-tab[data-tab="llm-profiles"]');
|
|
869
|
+
if (llmTab) {
|
|
870
|
+
llmTab.click();
|
|
871
|
+
}
|
|
872
|
+
}, 100);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
async handleCopySession() {
|
|
876
|
+
const sessionId = this.sessionManager.getCurrentSessionId();
|
|
877
|
+
|
|
878
|
+
if (!sessionId) {
|
|
879
|
+
this.showNotification('No active session to copy', 'warning');
|
|
880
|
+
return;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
try {
|
|
884
|
+
await navigator.clipboard.writeText(sessionId);
|
|
885
|
+
this.showNotification('Session ID copied to clipboard!', 'success');
|
|
886
|
+
} catch (error) {
|
|
887
|
+
console.error('[UIManager] Failed to copy session ID:', error);
|
|
888
|
+
this.showNotification('Failed to copy session ID', 'error');
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// Upgrade Handler
|
|
893
|
+
async handleUpgrade() {
|
|
894
|
+
try {
|
|
895
|
+
console.log('[UIManager] Getting extension path...');
|
|
896
|
+
|
|
897
|
+
// Get extension path from backend
|
|
898
|
+
const pathResponse = await this.apiClient.getExtensionPath();
|
|
899
|
+
const extensionPath = pathResponse.extension_path;
|
|
900
|
+
|
|
901
|
+
console.log('[UIManager] Extension path:', extensionPath);
|
|
902
|
+
|
|
903
|
+
// Copy path to clipboard
|
|
904
|
+
await navigator.clipboard.writeText(extensionPath);
|
|
905
|
+
|
|
906
|
+
console.log('[UIManager] Extension path copied to clipboard');
|
|
907
|
+
|
|
908
|
+
// Open extension directory as file:// URL
|
|
909
|
+
const fileUrl = `file://${extensionPath}`;
|
|
910
|
+
const fileResult = await chrome.runtime.sendMessage({
|
|
911
|
+
type: 'OPEN_FILE_URL',
|
|
912
|
+
data: { fileUrl: fileUrl }
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
if (!fileResult || !fileResult.success) {
|
|
916
|
+
console.warn('[UIManager] Failed to open extension directory:', fileResult?.error);
|
|
917
|
+
} else {
|
|
918
|
+
console.log('[UIManager] Successfully opened extension directory tab:', fileResult.tabId);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// Open chrome://extensions in a new tab
|
|
922
|
+
const extensionsResult = await chrome.runtime.sendMessage({
|
|
923
|
+
type: 'OPEN_FILE_URL',
|
|
924
|
+
data: { fileUrl: 'chrome://extensions' }
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
if (!extensionsResult || !extensionsResult.success) {
|
|
928
|
+
console.warn('[UIManager] Failed to open chrome://extensions:', extensionsResult?.error);
|
|
929
|
+
} else {
|
|
930
|
+
console.log('[UIManager] Successfully opened chrome://extensions tab:', extensionsResult.tabId);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// Show notification
|
|
934
|
+
this.showNotification(`Extension path copied to clipboard. Extension directory and Chrome extensions page opened.`, 'success');
|
|
935
|
+
|
|
936
|
+
} catch (error) {
|
|
937
|
+
console.error('[UIManager] Failed to get extension path:', error);
|
|
938
|
+
this.showNotification(`Failed to get extension path: ${error.message}`, 'error');
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// Voice Recording UI Handler
|
|
943
|
+
async handleVoiceRecord() {
|
|
944
|
+
// Check if voice recording is supported
|
|
945
|
+
if (!this.voiceRecorder.isSupported()) {
|
|
946
|
+
this.showNotification('Voice recording is not supported in your browser', 'error');
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Check if ASR profiles are available before allowing recording
|
|
951
|
+
const isVoiceAvailable = await this.voiceRecorder.isVoiceRecordingAvailable();
|
|
952
|
+
if (!isVoiceAvailable) {
|
|
953
|
+
console.log('[UIManager] No ASR profiles available, showing configuration modal');
|
|
954
|
+
this.showVoiceProfileRequiredModal('configure');
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
// Enhanced task status check - disable recording during task execution unless paused
|
|
959
|
+
const taskStatus = this.sessionManager.getTaskStatus();
|
|
960
|
+
const isTaskRunning = this.state.isTaskRunning;
|
|
961
|
+
|
|
962
|
+
if (isTaskRunning && taskStatus !== 'paused') {
|
|
963
|
+
this.showNotification('Cannot record voice while task is running. Stop the current task or wait for it to complete.', 'warning');
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Additional check: if task is paused, allow voice input but show info message
|
|
968
|
+
if (isTaskRunning && taskStatus === 'paused') {
|
|
969
|
+
console.log('[UIManager] Task is paused, allowing voice input');
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
// Check if voice button is disabled due to missing ASR profiles
|
|
973
|
+
if (this.elements.voiceRecordBtn && this.elements.voiceRecordBtn.classList.contains('voice-disabled')) {
|
|
974
|
+
console.log('[UIManager] Voice button is disabled due to missing ASR profiles, showing modal');
|
|
975
|
+
this.showVoiceProfileRequiredModal('configure');
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
try {
|
|
980
|
+
if (this.voiceRecorder.isCurrentlyRecording()) {
|
|
981
|
+
// Stop recording
|
|
982
|
+
console.log('[UIManager] Stopping voice recording');
|
|
983
|
+
await this.voiceRecorder.stopRecording();
|
|
984
|
+
} else {
|
|
985
|
+
// Start recording
|
|
986
|
+
console.log('[UIManager] Starting voice recording');
|
|
987
|
+
|
|
988
|
+
// Request microphone permission first
|
|
989
|
+
try {
|
|
990
|
+
// For Chrome extensions, ensure we have proper user gesture context
|
|
991
|
+
console.log('[UIManager] Requesting microphone permission with user gesture context');
|
|
992
|
+
|
|
993
|
+
// Add a small delay to ensure user gesture is properly registered
|
|
994
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
995
|
+
|
|
996
|
+
const hasPermission = await this.voiceRecorder.requestMicrophonePermission();
|
|
997
|
+
if (!hasPermission) {
|
|
998
|
+
this.showNotification('Microphone permission denied. Please allow microphone access to use voice input.', 'error');
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
} catch (permissionError) {
|
|
1002
|
+
console.error('[UIManager] Microphone permission error:', permissionError);
|
|
1003
|
+
|
|
1004
|
+
// Handle different types of permission errors with detailed guidance
|
|
1005
|
+
let errorMessage = 'Microphone permission denied';
|
|
1006
|
+
let detailedHelp = '';
|
|
1007
|
+
|
|
1008
|
+
if (permissionError.name === 'MicrophonePermissionError') {
|
|
1009
|
+
errorMessage = permissionError.message;
|
|
1010
|
+
if (permissionError.userAction) {
|
|
1011
|
+
detailedHelp = permissionError.userAction;
|
|
1012
|
+
}
|
|
1013
|
+
} else if (permissionError.name === 'NotAllowedError') {
|
|
1014
|
+
errorMessage = 'Microphone access was denied by your browser.';
|
|
1015
|
+
detailedHelp = 'Please check your browser permissions and try again. You may need to allow microphone access in your browser settings.';
|
|
1016
|
+
} else {
|
|
1017
|
+
errorMessage = `Microphone access error: ${permissionError.message}`;
|
|
1018
|
+
detailedHelp = 'Please ensure your browser allows microphone access and that a microphone is connected.';
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Show detailed error message
|
|
1022
|
+
const fullMessage = detailedHelp ? `${errorMessage}\n\n${detailedHelp}` : errorMessage;
|
|
1023
|
+
this.showNotification(fullMessage, 'error');
|
|
1024
|
+
|
|
1025
|
+
// Also log detailed error for debugging
|
|
1026
|
+
console.error('[UIManager] Detailed microphone permission error:', {
|
|
1027
|
+
name: permissionError.name,
|
|
1028
|
+
message: permissionError.message,
|
|
1029
|
+
userAction: permissionError.userAction,
|
|
1030
|
+
originalError: permissionError.originalError
|
|
1031
|
+
});
|
|
1032
|
+
|
|
1033
|
+
this.updateVoiceRecordingUI(false);
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// Start recording
|
|
1038
|
+
await this.voiceRecorder.startRecording();
|
|
1039
|
+
}
|
|
1040
|
+
} catch (error) {
|
|
1041
|
+
console.error('[UIManager] Voice recording error:', error);
|
|
1042
|
+
this.showNotification(`Voice recording failed: ${error.message}`, 'error');
|
|
1043
|
+
this.updateVoiceRecordingUI(false);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
async handleSendTask() {
|
|
1048
|
+
const taskDescription = this.elements.taskInput?.value.trim();
|
|
1049
|
+
|
|
1050
|
+
if (!taskDescription) {
|
|
1051
|
+
this.showNotification('Please enter a task description', 'warning');
|
|
1052
|
+
this.elements.taskInput?.focus();
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
try {
|
|
1057
|
+
// Check task status from session manager first (more reliable than API check)
|
|
1058
|
+
const sessionTaskStatus = this.sessionManager.getTaskStatus();
|
|
1059
|
+
const isPaused = sessionTaskStatus === 'paused';
|
|
1060
|
+
|
|
1061
|
+
console.log('[UIManager] handleSendTask - session task status:', sessionTaskStatus, 'isPaused:', isPaused);
|
|
1062
|
+
|
|
1063
|
+
if (isPaused) {
|
|
1064
|
+
// Handle adding new task to paused execution
|
|
1065
|
+
|
|
1066
|
+
await this.sessionManager.addNewTaskToPaused(taskDescription);
|
|
1067
|
+
|
|
1068
|
+
// Clear the input after successful addition
|
|
1069
|
+
this.clearTaskInput();
|
|
1070
|
+
this.showNotification('Additional information added to the task', 'success');
|
|
1071
|
+
|
|
1072
|
+
// Automatically resume the task after adding new information
|
|
1073
|
+
|
|
1074
|
+
await this.sessionManager.resumeTask('Auto-resume after adding new task information');
|
|
1075
|
+
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// For non-paused states, check if any task is running
|
|
1080
|
+
const statusCheck = await this.checkTaskStatus();
|
|
1081
|
+
if (statusCheck.isRunning) {
|
|
1082
|
+
const canProceed = await this.showTaskRunningWarning('send a new task');
|
|
1083
|
+
if (!canProceed) {
|
|
1084
|
+
this.showNotification('Cannot send task while another task is running. Please stop the current task first.', 'warning');
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
const llmProfile = this.elements.llmProfileSelect?.value;
|
|
1090
|
+
|
|
1091
|
+
// Check if LLM profile is selected
|
|
1092
|
+
if (!llmProfile || llmProfile.trim() === '') {
|
|
1093
|
+
// Check if there are any LLM profiles available
|
|
1094
|
+
const profiles = this.settingsManager.getLLMProfiles();
|
|
1095
|
+
if (profiles.length === 0) {
|
|
1096
|
+
// No LLM profiles configured at all
|
|
1097
|
+
this.showLLMProfileRequiredModal('configure');
|
|
1098
|
+
} else {
|
|
1099
|
+
// LLM profiles exist but none selected
|
|
1100
|
+
this.showLLMProfileRequiredModal('select');
|
|
1101
|
+
}
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// Immediately clear welcome message and show user request
|
|
1106
|
+
this.clearWelcomeMessage();
|
|
1107
|
+
|
|
1108
|
+
const taskData = {
|
|
1109
|
+
task_description: taskDescription,
|
|
1110
|
+
llm_profile_name: llmProfile,
|
|
1111
|
+
agent_mode: this.elements.agentModeSelect?.value || 'thinking'
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
// Add uploaded files path if any
|
|
1115
|
+
const filePath = this.fileManager.getUploadedFilesForTask();
|
|
1116
|
+
if (filePath) {
|
|
1117
|
+
taskData.upload_files_path = filePath;
|
|
1118
|
+
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// Add selected tabs information if any
|
|
1122
|
+
const selectedTabsData = this.getSelectedTabsForTask();
|
|
1123
|
+
if (selectedTabsData) {
|
|
1124
|
+
taskData.selected_tabs = selectedTabsData;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// Add selected skills information if any
|
|
1128
|
+
const selectedSkillsData = this.getSelectedSkillsForTask();
|
|
1129
|
+
if (selectedSkillsData) {
|
|
1130
|
+
taskData.selected_skills = selectedSkillsData;
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
|
|
1134
|
+
await this.sessionManager.submitTask(taskData);
|
|
1135
|
+
|
|
1136
|
+
// Clear uploaded files after successful task submission
|
|
1137
|
+
this.fileManager.clearUploadedFiles();
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
// Check if this is an LLM connection failure from API response
|
|
1140
|
+
if (error.data && error.data.error === 'llm_connection_failed') {
|
|
1141
|
+
this.showLLMConnectionFailedModal(error.data);
|
|
1142
|
+
} else {
|
|
1143
|
+
this.showNotification(`Failed to submit task: ${error.message}`, 'error');
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
async handleCancelTask() {
|
|
1149
|
+
try {
|
|
1150
|
+
await this.sessionManager.pauseTask('User clicked cancel');
|
|
1151
|
+
} catch (error) {
|
|
1152
|
+
this.showNotification(`Failed to cancel task: ${error.message}`, 'error');
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
async handleResumeTask() {
|
|
1157
|
+
try {
|
|
1158
|
+
await this.sessionManager.resumeTask('User clicked resume');
|
|
1159
|
+
} catch (error) {
|
|
1160
|
+
this.showNotification(`Failed to resume task: ${error.message}`, 'error');
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
async handleTerminateTask() {
|
|
1165
|
+
try {
|
|
1166
|
+
// Temporarily stop task status monitoring during terminate to avoid conflicts
|
|
1167
|
+
const wasMonitoring = !!this.taskStatusInterval;
|
|
1168
|
+
if (wasMonitoring) {
|
|
1169
|
+
this.stopTaskStatusMonitoring();
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
await this.sessionManager.stopTask('User clicked terminate');
|
|
1173
|
+
|
|
1174
|
+
// Restart monitoring after a brief delay if it was running
|
|
1175
|
+
if (wasMonitoring) {
|
|
1176
|
+
setTimeout(() => {
|
|
1177
|
+
this.startTaskStatusMonitoring();
|
|
1178
|
+
}, 1000);
|
|
1179
|
+
}
|
|
1180
|
+
} catch (error) {
|
|
1181
|
+
// Only show error notification for actual failures, not status conflicts
|
|
1182
|
+
if (!error.message.includes('status') && !error.message.includes('running')) {
|
|
1183
|
+
this.showNotification(`Failed to terminate task: ${error.message}`, 'error');
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
handleTaskInputKeydown(event) {
|
|
1189
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
1190
|
+
event.preventDefault();
|
|
1191
|
+
this.handleSendTask();
|
|
1192
|
+
return;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// Handle tab token deletion
|
|
1196
|
+
if (event.key === 'Backspace' || event.key === 'Delete') {
|
|
1197
|
+
if (this.handleTabTokenDeletion(event)) {
|
|
1198
|
+
event.preventDefault();
|
|
1199
|
+
return;
|
|
1200
|
+
}
|
|
1201
|
+
// Also handle skill token deletion
|
|
1202
|
+
if (this.handleSkillTokenDeletion(event)) {
|
|
1203
|
+
event.preventDefault();
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// Handle Tab key for skill auto-completion when only one skill matches
|
|
1209
|
+
if (event.key === 'Tab' && this.skillSelectorState.isVisible) {
|
|
1210
|
+
if (this.skillSelectorState.filteredSkills.length === 1) {
|
|
1211
|
+
event.preventDefault();
|
|
1212
|
+
this.selectSkill(this.skillSelectorState.filteredSkills[0]);
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
handleTabTokenDeletion(event) {
|
|
1218
|
+
const input = event.target;
|
|
1219
|
+
const cursorPos = input.selectionStart;
|
|
1220
|
+
const text = input.value;
|
|
1221
|
+
|
|
1222
|
+
// Unicode markers for tab tokens
|
|
1223
|
+
const startMarker = '\u200B'; // Zero-width space
|
|
1224
|
+
const endMarker = '\u200C'; // Zero-width non-joiner
|
|
1225
|
+
|
|
1226
|
+
let tokenStart = -1;
|
|
1227
|
+
let tokenEnd = -1;
|
|
1228
|
+
|
|
1229
|
+
if (event.key === 'Backspace') {
|
|
1230
|
+
// Only delete if cursor is directly adjacent to end of token
|
|
1231
|
+
// Check if the character immediately before cursor is an endMarker
|
|
1232
|
+
if (cursorPos > 0 && text[cursorPos - 1] === endMarker) {
|
|
1233
|
+
tokenEnd = cursorPos; // Include the marker
|
|
1234
|
+
// Find the corresponding start marker backwards
|
|
1235
|
+
for (let j = cursorPos - 2; j >= 0; j--) {
|
|
1236
|
+
if (text[j] === startMarker) {
|
|
1237
|
+
tokenStart = j;
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
} else if (event.key === 'Delete') {
|
|
1243
|
+
// Only delete if cursor is directly adjacent to start of token
|
|
1244
|
+
// Check if the character immediately at cursor is a startMarker
|
|
1245
|
+
if (cursorPos < text.length && text[cursorPos] === startMarker) {
|
|
1246
|
+
tokenStart = cursorPos;
|
|
1247
|
+
// Find the corresponding end marker forwards
|
|
1248
|
+
for (let j = cursorPos + 1; j < text.length; j++) {
|
|
1249
|
+
if (text[j] === endMarker) {
|
|
1250
|
+
tokenEnd = j + 1; // Include the marker
|
|
1251
|
+
break;
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
// If we found a complete token, delete it
|
|
1258
|
+
if (tokenStart !== -1 && tokenEnd !== -1) {
|
|
1259
|
+
const beforeToken = text.substring(0, tokenStart);
|
|
1260
|
+
const afterToken = text.substring(tokenEnd);
|
|
1261
|
+
input.value = beforeToken + afterToken;
|
|
1262
|
+
input.setSelectionRange(tokenStart, tokenStart);
|
|
1263
|
+
|
|
1264
|
+
// Trigger input change event for validation
|
|
1265
|
+
this.handleTaskInputChange({ target: input });
|
|
1266
|
+
|
|
1267
|
+
return true; // Prevent default behavior
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
return false; // Allow default behavior
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
handleSkillTokenDeletion(event) {
|
|
1274
|
+
const input = event.target;
|
|
1275
|
+
const cursorPos = input.selectionStart;
|
|
1276
|
+
const text = input.value;
|
|
1277
|
+
|
|
1278
|
+
// Unicode markers for skill tokens
|
|
1279
|
+
const startMarker = '\u200D'; // Zero-width joiner
|
|
1280
|
+
const endMarker = '\u200E'; // Left-to-right mark
|
|
1281
|
+
|
|
1282
|
+
let tokenStart = -1;
|
|
1283
|
+
let tokenEnd = -1;
|
|
1284
|
+
|
|
1285
|
+
if (event.key === 'Backspace') {
|
|
1286
|
+
// Only delete if cursor is directly adjacent to end of token
|
|
1287
|
+
if (cursorPos > 0 && text[cursorPos - 1] === endMarker) {
|
|
1288
|
+
tokenEnd = cursorPos; // Include the marker
|
|
1289
|
+
// Find the corresponding start marker backwards
|
|
1290
|
+
for (let j = cursorPos - 2; j >= 0; j--) {
|
|
1291
|
+
if (text[j] === startMarker) {
|
|
1292
|
+
tokenStart = j;
|
|
1293
|
+
break;
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
} else if (event.key === 'Delete') {
|
|
1298
|
+
// Only delete if cursor is directly adjacent to start of token
|
|
1299
|
+
if (cursorPos < text.length && text[cursorPos] === startMarker) {
|
|
1300
|
+
tokenStart = cursorPos;
|
|
1301
|
+
// Find the corresponding end marker forwards
|
|
1302
|
+
for (let j = cursorPos + 1; j < text.length; j++) {
|
|
1303
|
+
if (text[j] === endMarker) {
|
|
1304
|
+
tokenEnd = j + 1; // Include the marker
|
|
1305
|
+
break;
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
// If we found a complete token, delete it
|
|
1312
|
+
if (tokenStart !== -1 && tokenEnd !== -1) {
|
|
1313
|
+
const beforeToken = text.substring(0, tokenStart);
|
|
1314
|
+
const afterToken = text.substring(tokenEnd);
|
|
1315
|
+
input.value = beforeToken + afterToken;
|
|
1316
|
+
input.setSelectionRange(tokenStart, tokenStart);
|
|
1317
|
+
|
|
1318
|
+
// Trigger input change event for validation
|
|
1319
|
+
this.handleTaskInputChange({ target: input });
|
|
1320
|
+
|
|
1321
|
+
return true; // Prevent default behavior
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
return false; // Allow default behavior
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
async handleLlmProfileChange(event) {
|
|
1328
|
+
const selectedProfile = event.target.value;
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
|
|
1332
|
+
try {
|
|
1333
|
+
// Save the selected LLM profile to user settings storage
|
|
1334
|
+
if (this.userSettingsStorage) {
|
|
1335
|
+
|
|
1336
|
+
await this.userSettingsStorage.setSelectedLlmProfile(selectedProfile);
|
|
1337
|
+
|
|
1338
|
+
|
|
1339
|
+
// Verify the save
|
|
1340
|
+
const verified = await this.userSettingsStorage.getSelectedLlmProfile();
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
// Also save to localStorage as backup for browser restart scenarios
|
|
1344
|
+
localStorage.setItem('vibesurf-llm-profile-backup', selectedProfile);
|
|
1345
|
+
|
|
1346
|
+
} else {
|
|
1347
|
+
console.warn('[UIManager] userSettingsStorage not available for LLM profile save');
|
|
1348
|
+
}
|
|
1349
|
+
} catch (error) {
|
|
1350
|
+
console.error('[UIManager] Failed to save LLM profile selection:', error);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
// Re-validate send button state when LLM profile changes
|
|
1354
|
+
if (this.elements.taskInput) {
|
|
1355
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
async handleAgentModeChange(event) {
|
|
1360
|
+
const selectedMode = event.target.value;
|
|
1361
|
+
|
|
1362
|
+
|
|
1363
|
+
|
|
1364
|
+
try {
|
|
1365
|
+
// Save the selected agent mode to user settings storage
|
|
1366
|
+
if (this.userSettingsStorage) {
|
|
1367
|
+
|
|
1368
|
+
await this.userSettingsStorage.setSelectedAgentMode(selectedMode);
|
|
1369
|
+
|
|
1370
|
+
|
|
1371
|
+
// Verify the save
|
|
1372
|
+
const verified = await this.userSettingsStorage.getSelectedAgentMode();
|
|
1373
|
+
|
|
1374
|
+
|
|
1375
|
+
// Also save to localStorage as backup for browser restart scenarios
|
|
1376
|
+
localStorage.setItem('vibesurf-agent-mode-backup', selectedMode);
|
|
1377
|
+
|
|
1378
|
+
} else {
|
|
1379
|
+
console.warn('[UIManager] userSettingsStorage not available for agent mode save');
|
|
1380
|
+
}
|
|
1381
|
+
} catch (error) {
|
|
1382
|
+
console.error('[UIManager] Failed to save agent mode selection:', error);
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
// Re-validate send button state when agent mode changes
|
|
1386
|
+
if (this.elements.taskInput) {
|
|
1387
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
handleTaskInputChange(event) {
|
|
1392
|
+
const hasText = event.target.value.trim().length > 0;
|
|
1393
|
+
const textarea = event.target;
|
|
1394
|
+
const llmProfile = this.elements.llmProfileSelect?.value;
|
|
1395
|
+
const hasLlmProfile = llmProfile && llmProfile.trim() !== '';
|
|
1396
|
+
const taskStatus = this.sessionManager.getTaskStatus();
|
|
1397
|
+
const isPaused = taskStatus === 'paused';
|
|
1398
|
+
|
|
1399
|
+
// Check for @ character to trigger tab selector
|
|
1400
|
+
this.handleTabSelectorInput(event);
|
|
1401
|
+
|
|
1402
|
+
// Check for / character to trigger skill selector
|
|
1403
|
+
this.handleSkillSelectorInput(event);
|
|
1404
|
+
|
|
1405
|
+
// Update send button state - special handling for pause state
|
|
1406
|
+
if (this.elements.sendBtn) {
|
|
1407
|
+
if (isPaused) {
|
|
1408
|
+
// In pause state, only require text (no LLM profile needed for adding new info)
|
|
1409
|
+
this.elements.sendBtn.disabled = !hasText;
|
|
1410
|
+
} else {
|
|
1411
|
+
// In normal state, require both text and LLM profile and no running task
|
|
1412
|
+
this.elements.sendBtn.disabled = !(hasText && hasLlmProfile && !this.state.isTaskRunning);
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// Auto-resize textarea based on content
|
|
1417
|
+
this.autoResizeTextarea(textarea);
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
autoResizeTextarea(textarea) {
|
|
1421
|
+
if (!textarea) return;
|
|
1422
|
+
|
|
1423
|
+
// Reset height to auto to get the natural scrollHeight
|
|
1424
|
+
textarea.style.height = 'auto';
|
|
1425
|
+
|
|
1426
|
+
// Calculate the new height based on content
|
|
1427
|
+
const minHeight = 44; // Min height from CSS
|
|
1428
|
+
const maxHeight = 200; // Max height from CSS
|
|
1429
|
+
const newHeight = Math.max(minHeight, Math.min(maxHeight, textarea.scrollHeight));
|
|
1430
|
+
|
|
1431
|
+
// Apply the new height
|
|
1432
|
+
textarea.style.height = newHeight + 'px';
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
// UI Display Methods
|
|
1436
|
+
updateSessionDisplay(sessionId) {
|
|
1437
|
+
|
|
1438
|
+
if (this.elements.sessionId) {
|
|
1439
|
+
this.elements.sessionId.textContent = sessionId || '-';
|
|
1440
|
+
|
|
1441
|
+
} else {
|
|
1442
|
+
console.error('[UIManager] Session ID element not found');
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
updateControlPanel(status) {
|
|
1447
|
+
const panel = this.elements.controlPanel;
|
|
1448
|
+
const cancelBtn = this.elements.cancelBtn;
|
|
1449
|
+
const resumeBtn = this.elements.resumeBtn;
|
|
1450
|
+
const terminateBtn = this.elements.terminateBtn;
|
|
1451
|
+
|
|
1452
|
+
console.log(`[UIManager] updateControlPanel called with status: ${status}`);
|
|
1453
|
+
|
|
1454
|
+
if (!panel) {
|
|
1455
|
+
console.error('[UIManager] Control panel element not found');
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
// Clear any existing auto-hide timeout
|
|
1460
|
+
if (this.controlPanelTimeout) {
|
|
1461
|
+
clearTimeout(this.controlPanelTimeout);
|
|
1462
|
+
this.controlPanelTimeout = null;
|
|
1463
|
+
}
|
|
1464
|
+
|
|
1465
|
+
switch (status) {
|
|
1466
|
+
case 'ready':
|
|
1467
|
+
|
|
1468
|
+
panel.classList.add('hidden');
|
|
1469
|
+
panel.classList.remove('error-state');
|
|
1470
|
+
break;
|
|
1471
|
+
|
|
1472
|
+
case 'running':
|
|
1473
|
+
|
|
1474
|
+
panel.classList.remove('hidden');
|
|
1475
|
+
panel.classList.remove('error-state');
|
|
1476
|
+
cancelBtn?.classList.remove('hidden');
|
|
1477
|
+
resumeBtn?.classList.add('hidden');
|
|
1478
|
+
terminateBtn?.classList.add('hidden');
|
|
1479
|
+
|
|
1480
|
+
// For fast-completing tasks, ensure minimum visibility duration
|
|
1481
|
+
this.ensureMinimumControlPanelVisibility();
|
|
1482
|
+
break;
|
|
1483
|
+
|
|
1484
|
+
case 'paused':
|
|
1485
|
+
|
|
1486
|
+
panel.classList.remove('hidden');
|
|
1487
|
+
panel.classList.remove('error-state');
|
|
1488
|
+
cancelBtn?.classList.add('hidden');
|
|
1489
|
+
resumeBtn?.classList.remove('hidden');
|
|
1490
|
+
terminateBtn?.classList.remove('hidden');
|
|
1491
|
+
break;
|
|
1492
|
+
|
|
1493
|
+
case 'error':
|
|
1494
|
+
|
|
1495
|
+
panel.classList.remove('hidden');
|
|
1496
|
+
panel.classList.add('error-state');
|
|
1497
|
+
cancelBtn?.classList.remove('hidden');
|
|
1498
|
+
resumeBtn?.classList.add('hidden');
|
|
1499
|
+
terminateBtn?.classList.remove('hidden');
|
|
1500
|
+
break;
|
|
1501
|
+
|
|
1502
|
+
case 'done':
|
|
1503
|
+
case 'completed':
|
|
1504
|
+
case 'finished':
|
|
1505
|
+
console.log(`[UIManager] Task completed with status: ${status}, hiding panel after delay`);
|
|
1506
|
+
// Treat as ready state
|
|
1507
|
+
panel.classList.add('hidden');
|
|
1508
|
+
panel.classList.remove('error-state');
|
|
1509
|
+
break;
|
|
1510
|
+
|
|
1511
|
+
default:
|
|
1512
|
+
console.log(`[UIManager] Unknown control panel status: ${status}, hiding panel`);
|
|
1513
|
+
panel.classList.add('hidden');
|
|
1514
|
+
panel.classList.remove('error-state');
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
ensureMinimumControlPanelVisibility() {
|
|
1519
|
+
// Set a flag to prevent immediate hiding of control panel for fast tasks
|
|
1520
|
+
this.controlPanelMinVisibilityActive = true;
|
|
1521
|
+
|
|
1522
|
+
// Clear the flag after minimum visibility period (2 seconds)
|
|
1523
|
+
setTimeout(() => {
|
|
1524
|
+
this.controlPanelMinVisibilityActive = false;
|
|
1525
|
+
|
|
1526
|
+
}, 2000);
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
clearActivityLog() {
|
|
1530
|
+
if (this.elements.activityLog) {
|
|
1531
|
+
// Don't clear the news carousel - preserve it
|
|
1532
|
+
const newsCarousel = this.elements.activityLog.querySelector('#news-carousel-container');
|
|
1533
|
+
|
|
1534
|
+
// Clear all content
|
|
1535
|
+
this.elements.activityLog.innerHTML = '';
|
|
1536
|
+
|
|
1537
|
+
// Restore the news carousel if it existed
|
|
1538
|
+
if (newsCarousel) {
|
|
1539
|
+
this.elements.activityLog.appendChild(newsCarousel);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
clearWelcomeMessage() {
|
|
1545
|
+
if (this.elements.activityLog) {
|
|
1546
|
+
const welcomeMsg = this.elements.activityLog.querySelector('.welcome-message');
|
|
1547
|
+
if (welcomeMsg) {
|
|
1548
|
+
welcomeMsg.remove();
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
showWelcomeMessage() {
|
|
1554
|
+
const welcomeHTML = `
|
|
1555
|
+
<div class="welcome-message">
|
|
1556
|
+
<div class="welcome-text">
|
|
1557
|
+
<h4>Welcome to VibeSurf</h4>
|
|
1558
|
+
<p>Let's vibe surfing the world with AI automation</p>
|
|
1559
|
+
</div>
|
|
1560
|
+
<div class="quick-tasks">
|
|
1561
|
+
<div class="task-suggestion" data-task="research">
|
|
1562
|
+
<div class="task-icon">🔍</div>
|
|
1563
|
+
<div class="task-content">
|
|
1564
|
+
<div class="task-title">Research Founders</div>
|
|
1565
|
+
<div class="task-description">Search information about AI browser assistant: VibeSurf, write a brief report</div>
|
|
1566
|
+
</div>
|
|
1567
|
+
</div>
|
|
1568
|
+
</div>
|
|
1569
|
+
</div>
|
|
1570
|
+
`;
|
|
1571
|
+
|
|
1572
|
+
if (this.elements.activityLog) {
|
|
1573
|
+
// Preserve the news carousel
|
|
1574
|
+
const newsCarousel = this.elements.activityLog.querySelector('#news-carousel-container');
|
|
1575
|
+
|
|
1576
|
+
// Set the welcome message
|
|
1577
|
+
this.elements.activityLog.innerHTML = welcomeHTML;
|
|
1578
|
+
|
|
1579
|
+
// Append the news carousel at the end (after welcome message)
|
|
1580
|
+
if (newsCarousel) {
|
|
1581
|
+
this.elements.activityLog.appendChild(newsCarousel);
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
this.bindTaskSuggestionEvents();
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
bindTaskSuggestionEvents() {
|
|
1589
|
+
const taskSuggestions = document.querySelectorAll('.task-suggestion');
|
|
1590
|
+
|
|
1591
|
+
taskSuggestions.forEach(suggestion => {
|
|
1592
|
+
suggestion.addEventListener('click', () => {
|
|
1593
|
+
const taskDescription = suggestion.querySelector('.task-description').textContent;
|
|
1594
|
+
|
|
1595
|
+
// Populate task input with suggestion (only description, no title prefix)
|
|
1596
|
+
if (this.elements.taskInput) {
|
|
1597
|
+
this.elements.taskInput.value = taskDescription;
|
|
1598
|
+
this.elements.taskInput.focus();
|
|
1599
|
+
|
|
1600
|
+
// Trigger input change event for validation and auto-resize
|
|
1601
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
1602
|
+
|
|
1603
|
+
// Auto-send the task
|
|
1604
|
+
setTimeout(() => {
|
|
1605
|
+
this.handleSendTask();
|
|
1606
|
+
}, 100); // Small delay to ensure input processing is complete
|
|
1607
|
+
}
|
|
1608
|
+
});
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
displayActivityLogs(logs) {
|
|
1613
|
+
this.clearActivityLog();
|
|
1614
|
+
|
|
1615
|
+
if (logs.length === 0) {
|
|
1616
|
+
this.showWelcomeMessage();
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
logs.forEach(log => this.addActivityLog(log));
|
|
1621
|
+
|
|
1622
|
+
// Bind link click handlers to all existing activity items after loading
|
|
1623
|
+
this.bindLinkHandlersToAllActivityItems();
|
|
1624
|
+
|
|
1625
|
+
this.scrollActivityToBottom();
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
bindLinkHandlersToAllActivityItems() {
|
|
1629
|
+
// Bind link click handlers to all existing activity items
|
|
1630
|
+
const activityItems = this.elements.activityLog.querySelectorAll('.activity-item');
|
|
1631
|
+
activityItems.forEach(item => {
|
|
1632
|
+
this.bindLinkClickHandlers(item);
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
addActivityLog(activityData) {
|
|
1637
|
+
// Filter out "done" status messages from UI display only
|
|
1638
|
+
const agentStatus = activityData.agent_status || activityData.status || '';
|
|
1639
|
+
|
|
1640
|
+
// Filter done messages that are just status updates without meaningful content
|
|
1641
|
+
if (agentStatus.toLowerCase() === 'done') {
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
if (this.elements.activityLog) {
|
|
1646
|
+
// Remove welcome message if present
|
|
1647
|
+
const welcomeMsg = this.elements.activityLog.querySelector('.welcome-message');
|
|
1648
|
+
if (welcomeMsg) {
|
|
1649
|
+
welcomeMsg.remove();
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
// Check if this is a suggestion_tasks message
|
|
1653
|
+
if (agentStatus.toLowerCase() === 'suggestion_tasks') {
|
|
1654
|
+
// For suggestion_tasks, only show suggestion cards, not the normal message
|
|
1655
|
+
// But the message is still kept in session manager's logs for proper indexing
|
|
1656
|
+
this.addSuggestionTaskCards(activityData);
|
|
1657
|
+
} else {
|
|
1658
|
+
// For all other messages, show the normal activity item
|
|
1659
|
+
const activityItem = this.createActivityItem(activityData);
|
|
1660
|
+
this.elements.activityLog.appendChild(activityItem);
|
|
1661
|
+
activityItem.classList.add('fade-in');
|
|
1662
|
+
|
|
1663
|
+
// Bind copy button functionality
|
|
1664
|
+
this.bindCopyButtonEvent(activityItem, activityData);
|
|
1665
|
+
|
|
1666
|
+
// Bind link click handlers to prevent extension freezing
|
|
1667
|
+
this.bindLinkClickHandlers(activityItem);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
addSuggestionTaskCards(activityData) {
|
|
1673
|
+
const agentMsg = activityData.agent_msg || activityData.message || '';
|
|
1674
|
+
|
|
1675
|
+
if (!agentMsg || typeof agentMsg !== 'string') {
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
// Parse tasks by splitting on newlines and filtering empty lines
|
|
1680
|
+
const tasks = agentMsg.split('\n')
|
|
1681
|
+
.map(task => task.trim())
|
|
1682
|
+
.filter(task => task.length > 0);
|
|
1683
|
+
|
|
1684
|
+
if (tasks.length === 0) {
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
// Create suggestion cards container
|
|
1689
|
+
const suggestionsContainer = document.createElement('div');
|
|
1690
|
+
suggestionsContainer.className = 'suggestion-tasks-container';
|
|
1691
|
+
|
|
1692
|
+
// Add header for suggestion cards
|
|
1693
|
+
const headerElement = document.createElement('div');
|
|
1694
|
+
headerElement.className = 'suggestion-tasks-header';
|
|
1695
|
+
headerElement.innerHTML = `
|
|
1696
|
+
<h4>Suggestion Follow-Up Tasks</h4>
|
|
1697
|
+
`;
|
|
1698
|
+
suggestionsContainer.appendChild(headerElement);
|
|
1699
|
+
|
|
1700
|
+
// Create cards container
|
|
1701
|
+
const cardsContainer = document.createElement('div');
|
|
1702
|
+
cardsContainer.className = 'suggestion-cards';
|
|
1703
|
+
|
|
1704
|
+
// Create individual task cards
|
|
1705
|
+
tasks.forEach((task, index) => {
|
|
1706
|
+
const taskCard = document.createElement('div');
|
|
1707
|
+
taskCard.className = 'suggestion-task-card';
|
|
1708
|
+
taskCard.setAttribute('data-task', task);
|
|
1709
|
+
taskCard.setAttribute('data-index', index);
|
|
1710
|
+
|
|
1711
|
+
taskCard.innerHTML = `
|
|
1712
|
+
<div class="suggestion-card-icon">
|
|
1713
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1714
|
+
<path d="M9 12L11 14L15 10M21 12C21 16.9706 16.9706 21 12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1715
|
+
</svg>
|
|
1716
|
+
</div>
|
|
1717
|
+
<div class="suggestion-card-content">
|
|
1718
|
+
<div class="suggestion-task-text">${this.escapeHtml(task)}</div>
|
|
1719
|
+
</div>
|
|
1720
|
+
<div class="suggestion-card-arrow">
|
|
1721
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1722
|
+
<path d="M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
1723
|
+
</svg>
|
|
1724
|
+
</div>
|
|
1725
|
+
`;
|
|
1726
|
+
|
|
1727
|
+
// Add click event handler
|
|
1728
|
+
taskCard.addEventListener('click', (e) => {
|
|
1729
|
+
e.preventDefault();
|
|
1730
|
+
this.handleSuggestionTaskClick(task);
|
|
1731
|
+
});
|
|
1732
|
+
|
|
1733
|
+
cardsContainer.appendChild(taskCard);
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
suggestionsContainer.appendChild(cardsContainer);
|
|
1737
|
+
|
|
1738
|
+
// Add the suggestions container to the activity log
|
|
1739
|
+
if (this.elements.activityLog) {
|
|
1740
|
+
this.elements.activityLog.appendChild(suggestionsContainer);
|
|
1741
|
+
suggestionsContainer.classList.add('fade-in');
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
handleSuggestionTaskClick(taskDescription) {
|
|
1746
|
+
|
|
1747
|
+
|
|
1748
|
+
// First check if task is running
|
|
1749
|
+
if (this.state.isTaskRunning) {
|
|
1750
|
+
this.showNotification('Cannot submit task while another task is running', 'warning');
|
|
1751
|
+
return;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
// Check if LLM profile is selected
|
|
1755
|
+
const llmProfile = this.elements.llmProfileSelect?.value;
|
|
1756
|
+
if (!llmProfile || llmProfile.trim() === '') {
|
|
1757
|
+
this.showLLMProfileRequiredModal('select');
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
// Set the task description in the input first
|
|
1762
|
+
if (!this.elements.taskInput) {
|
|
1763
|
+
console.error('[UIManager] Task input element not found');
|
|
1764
|
+
this.showNotification('Task input not available', 'error');
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
|
|
1769
|
+
this.elements.taskInput.value = taskDescription;
|
|
1770
|
+
this.elements.taskInput.focus();
|
|
1771
|
+
|
|
1772
|
+
// Trigger input change event for validation and auto-resize
|
|
1773
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
1774
|
+
|
|
1775
|
+
// Auto-submit the task after a short delay
|
|
1776
|
+
setTimeout(() => {
|
|
1777
|
+
|
|
1778
|
+
this.handleSendTask();
|
|
1779
|
+
}, 100);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
escapeHtml(text) {
|
|
1783
|
+
const div = document.createElement('div');
|
|
1784
|
+
div.textContent = text;
|
|
1785
|
+
return div.innerHTML;
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
createActivityItem(data) {
|
|
1789
|
+
const item = document.createElement('div');
|
|
1790
|
+
|
|
1791
|
+
// Extract activity data with correct keys
|
|
1792
|
+
const agentName = data.agent_name || 'system';
|
|
1793
|
+
const agentStatus = data.agent_status || data.status || 'info';
|
|
1794
|
+
const agentMsg = data.agent_msg || data.message || data.action_description || 'No description';
|
|
1795
|
+
|
|
1796
|
+
// Use backend timestamp if available, otherwise generate frontend timestamp
|
|
1797
|
+
let timestamp;
|
|
1798
|
+
if (data.timestamp) {
|
|
1799
|
+
timestamp = new Date(data.timestamp).toLocaleString();
|
|
1800
|
+
} else {
|
|
1801
|
+
timestamp = new Date().toLocaleString();
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
// Extract token and cost information
|
|
1805
|
+
const totalTokens = data.total_tokens;
|
|
1806
|
+
const totalCost = data.total_cost;
|
|
1807
|
+
|
|
1808
|
+
// Determine if this is a user message (should be on the right)
|
|
1809
|
+
const isUser = agentName.toLowerCase() === 'user';
|
|
1810
|
+
|
|
1811
|
+
// Set CSS classes based on agent type and status
|
|
1812
|
+
item.className = `activity-item ${isUser ? 'user-message' : 'agent-message'} ${agentStatus}`;
|
|
1813
|
+
|
|
1814
|
+
// Build metadata display (timestamp, tokens, cost)
|
|
1815
|
+
let metadataHtml = `<span class="message-time">${timestamp}</span>`;
|
|
1816
|
+
|
|
1817
|
+
if (totalTokens !== undefined || totalCost !== undefined) {
|
|
1818
|
+
metadataHtml += '<span class="message-metrics">';
|
|
1819
|
+
if (totalTokens !== undefined) {
|
|
1820
|
+
metadataHtml += `<span class="metric-item">tokens: ${totalTokens}</span>`;
|
|
1821
|
+
}
|
|
1822
|
+
if (totalCost !== undefined) {
|
|
1823
|
+
// Format cost to 4 decimal places
|
|
1824
|
+
const formattedCost = typeof totalCost === 'number' ? totalCost.toFixed(4) : parseFloat(totalCost || 0).toFixed(4);
|
|
1825
|
+
metadataHtml += `<span class="metric-item">cost: $${formattedCost}</span>`;
|
|
1826
|
+
}
|
|
1827
|
+
metadataHtml += '</span>';
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
// Create the message structure similar to chat interface
|
|
1831
|
+
item.innerHTML = `
|
|
1832
|
+
<div class="message-container ${isUser ? 'user-container' : 'agent-container'}">
|
|
1833
|
+
<div class="message-header">
|
|
1834
|
+
<span class="agent-name">${agentName}</span>
|
|
1835
|
+
<div class="message-metadata">${metadataHtml}</div>
|
|
1836
|
+
</div>
|
|
1837
|
+
<div class="message-bubble ${isUser ? 'user-bubble' : 'agent-bubble'}">
|
|
1838
|
+
<div class="message-status">
|
|
1839
|
+
<span class="status-indicator ${agentStatus}">${this.getStatusIcon(agentStatus)}</span>
|
|
1840
|
+
<span class="status-text">${agentStatus}</span>
|
|
1841
|
+
</div>
|
|
1842
|
+
<div class="message-content">
|
|
1843
|
+
${this.formatActivityContent(agentMsg)}
|
|
1844
|
+
</div>
|
|
1845
|
+
<button class="copy-message-btn" title="Copy message">
|
|
1846
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
1847
|
+
<path d="M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1ZM19 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H19C20.1 23 21 22.1 21 21V7C21 5.9 20.1 5 19 5ZM19 21H8V7H19V21Z" fill="currentColor"/>
|
|
1848
|
+
</svg>
|
|
1849
|
+
</button>
|
|
1850
|
+
</div>
|
|
1851
|
+
</div>
|
|
1852
|
+
`;
|
|
1853
|
+
|
|
1854
|
+
return item;
|
|
1855
|
+
}
|
|
1856
|
+
|
|
1857
|
+
bindCopyButtonEvent(activityItem, activityData) {
|
|
1858
|
+
const copyBtn = activityItem.querySelector('.copy-message-btn');
|
|
1859
|
+
|
|
1860
|
+
if (copyBtn) {
|
|
1861
|
+
copyBtn.addEventListener('click', async (e) => {
|
|
1862
|
+
e.preventDefault();
|
|
1863
|
+
e.stopPropagation();
|
|
1864
|
+
|
|
1865
|
+
await this.copyMessageToClipboard(activityData);
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
bindLinkClickHandlers(activityItem) {
|
|
1871
|
+
// Handle all link clicks within activity items to prevent extension freezing
|
|
1872
|
+
const links = activityItem.querySelectorAll('a');
|
|
1873
|
+
|
|
1874
|
+
links.forEach(link => {
|
|
1875
|
+
// Check if handler is already attached to prevent double binding
|
|
1876
|
+
if (link.hasAttribute('data-link-handler-attached')) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
link.setAttribute('data-link-handler-attached', 'true');
|
|
1881
|
+
|
|
1882
|
+
link.addEventListener('click', async (e) => {
|
|
1883
|
+
console.log('[VibeSurf] Link click event detected:', e);
|
|
1884
|
+
|
|
1885
|
+
// Comprehensive event prevention
|
|
1886
|
+
e.preventDefault();
|
|
1887
|
+
e.stopPropagation();
|
|
1888
|
+
e.stopImmediatePropagation(); // Prevent any other handlers
|
|
1889
|
+
|
|
1890
|
+
// Remove href temporarily to prevent default browser behavior
|
|
1891
|
+
const originalHref = link.getAttribute('href');
|
|
1892
|
+
const dataFilePath = link.getAttribute('data-file-path');
|
|
1893
|
+
link.setAttribute('href', '#');
|
|
1894
|
+
|
|
1895
|
+
// Use data-file-path if available (for file:// links), otherwise use href
|
|
1896
|
+
const targetUrl = dataFilePath || originalHref;
|
|
1897
|
+
if (!targetUrl || (targetUrl === '#' && !dataFilePath)) return;
|
|
1898
|
+
|
|
1899
|
+
// Debounce - prevent rapid repeated clicks
|
|
1900
|
+
if (link.hasAttribute('data-link-processing')) {
|
|
1901
|
+
console.log('[VibeSurf] Link already processing, ignoring duplicate click');
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
link.setAttribute('data-link-processing', 'true');
|
|
1906
|
+
|
|
1907
|
+
try {
|
|
1908
|
+
console.log('[VibeSurf] Processing link:', targetUrl);
|
|
1909
|
+
|
|
1910
|
+
// Handle file:// links using existing logic
|
|
1911
|
+
if (targetUrl.startsWith('file://')) {
|
|
1912
|
+
await this.handleFileLinkClick(targetUrl);
|
|
1913
|
+
}
|
|
1914
|
+
// Handle HTTP/HTTPS links
|
|
1915
|
+
else if (targetUrl.startsWith('http://') || targetUrl.startsWith('https://')) {
|
|
1916
|
+
await this.handleHttpLinkClick(targetUrl);
|
|
1917
|
+
}
|
|
1918
|
+
// Handle other protocols or relative URLs
|
|
1919
|
+
else {
|
|
1920
|
+
await this.handleOtherLinkClick(targetUrl);
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
console.log('[VibeSurf] Link processed successfully:', targetUrl);
|
|
1924
|
+
} catch (error) {
|
|
1925
|
+
console.error('[VibeSurf] Error handling link click:', error);
|
|
1926
|
+
this.showNotification(`Failed to open link: ${error.message}`, 'error');
|
|
1927
|
+
} finally {
|
|
1928
|
+
// Restore original href
|
|
1929
|
+
link.setAttribute('href', originalHref);
|
|
1930
|
+
|
|
1931
|
+
// Remove processing flag after a short delay
|
|
1932
|
+
setTimeout(() => {
|
|
1933
|
+
link.removeAttribute('data-link-processing');
|
|
1934
|
+
}, 1000);
|
|
1935
|
+
}
|
|
1936
|
+
});
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
async handleFileLinkClick(fileUrl) {
|
|
1941
|
+
console.log('[UIManager] Opening file URL:', fileUrl);
|
|
1942
|
+
|
|
1943
|
+
// Use the background script to handle file URLs
|
|
1944
|
+
const result = await chrome.runtime.sendMessage({
|
|
1945
|
+
type: 'OPEN_FILE_URL',
|
|
1946
|
+
data: { fileUrl }
|
|
1947
|
+
});
|
|
1948
|
+
|
|
1949
|
+
if (!result.success) {
|
|
1950
|
+
throw new Error(result.error || 'Failed to open file');
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
async handleHttpLinkClick(url) {
|
|
1955
|
+
console.log('[VibeSurf] Opening HTTP URL:', url);
|
|
1956
|
+
|
|
1957
|
+
try {
|
|
1958
|
+
// Open HTTP/HTTPS links in a new tab
|
|
1959
|
+
const result = await chrome.runtime.sendMessage({
|
|
1960
|
+
type: 'OPEN_FILE_URL',
|
|
1961
|
+
data: { fileUrl: url }
|
|
1962
|
+
});
|
|
1963
|
+
|
|
1964
|
+
console.log('[VibeSurf] Background script response:', result);
|
|
1965
|
+
|
|
1966
|
+
if (!result || !result.success) {
|
|
1967
|
+
throw new Error(result?.error || 'Failed to create tab for URL');
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
console.log('[VibeSurf] Successfully opened tab:', result.tabId);
|
|
1971
|
+
} catch (error) {
|
|
1972
|
+
console.error('[VibeSurf] Error opening HTTP URL:', error);
|
|
1973
|
+
throw error;
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
async handleOtherLinkClick(url) {
|
|
1978
|
+
console.log('[UIManager] Opening other URL:', url);
|
|
1979
|
+
|
|
1980
|
+
// For relative URLs or other protocols, try to open in new tab
|
|
1981
|
+
try {
|
|
1982
|
+
// Use the background script to handle URL opening
|
|
1983
|
+
const result = await chrome.runtime.sendMessage({
|
|
1984
|
+
type: 'OPEN_FILE_URL',
|
|
1985
|
+
data: { fileUrl: url }
|
|
1986
|
+
});
|
|
1987
|
+
|
|
1988
|
+
if (!result.success) {
|
|
1989
|
+
throw new Error(result.error || 'Failed to open URL');
|
|
1990
|
+
}
|
|
1991
|
+
} catch (error) {
|
|
1992
|
+
// If the background script method fails, try to construct absolute URL
|
|
1993
|
+
if (!url.startsWith('http')) {
|
|
1994
|
+
try {
|
|
1995
|
+
const absoluteUrl = new URL(url, window.location.href).href;
|
|
1996
|
+
const result = await chrome.runtime.sendMessage({
|
|
1997
|
+
type: 'OPEN_FILE_URL',
|
|
1998
|
+
data: { fileUrl: absoluteUrl }
|
|
1999
|
+
});
|
|
2000
|
+
|
|
2001
|
+
if (!result.success) {
|
|
2002
|
+
throw new Error(result.error || 'Failed to open absolute URL');
|
|
2003
|
+
}
|
|
2004
|
+
} catch (urlError) {
|
|
2005
|
+
throw new Error(`Failed to open URL: ${urlError.message}`);
|
|
2006
|
+
}
|
|
2007
|
+
} else {
|
|
2008
|
+
throw error;
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
async copyMessageToClipboard(activityData) {
|
|
2014
|
+
try {
|
|
2015
|
+
// Extract only the message content (no agent info or timestamps)
|
|
2016
|
+
const agentMsg = activityData.agent_msg || activityData.message || activityData.action_description || 'No description';
|
|
2017
|
+
|
|
2018
|
+
// Convert to plain text
|
|
2019
|
+
let messageText = '';
|
|
2020
|
+
if (typeof agentMsg === 'object') {
|
|
2021
|
+
messageText = JSON.stringify(agentMsg, null, 2);
|
|
2022
|
+
} else {
|
|
2023
|
+
messageText = String(agentMsg);
|
|
2024
|
+
// Strip HTML tags for plain text copy
|
|
2025
|
+
messageText = messageText.replace(/<[^>]*>/g, '');
|
|
2026
|
+
// Decode HTML entities
|
|
2027
|
+
messageText = messageText
|
|
2028
|
+
.replace(/&/g, '&')
|
|
2029
|
+
.replace(/</g, '<')
|
|
2030
|
+
.replace(/>/g, '>')
|
|
2031
|
+
.replace(/"/g, '"')
|
|
2032
|
+
.replace(/'/g, "'")
|
|
2033
|
+
.replace(/ /g, ' ')
|
|
2034
|
+
.replace(/&#(\d+);/g, (match, dec) => String.fromCharCode(dec))
|
|
2035
|
+
.replace(/<br\s*\/?>/gi, '\n') // Convert <br> tags to newlines
|
|
2036
|
+
.replace(/\s+/g, ' ') // Normalize whitespace
|
|
2037
|
+
.trim(); // Remove leading/trailing whitespace
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
// Check clipboard API availability
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
// Try multiple clipboard methods
|
|
2046
|
+
let copySuccess = false;
|
|
2047
|
+
let lastError = null;
|
|
2048
|
+
|
|
2049
|
+
// Method 1: Chrome extension messaging approach
|
|
2050
|
+
try {
|
|
2051
|
+
|
|
2052
|
+
await new Promise((resolve, reject) => {
|
|
2053
|
+
chrome.runtime.sendMessage({
|
|
2054
|
+
type: 'COPY_TO_CLIPBOARD',
|
|
2055
|
+
text: messageText
|
|
2056
|
+
}, (response) => {
|
|
2057
|
+
if (chrome.runtime.lastError) {
|
|
2058
|
+
reject(new Error(chrome.runtime.lastError.message));
|
|
2059
|
+
} else if (response && response.success) {
|
|
2060
|
+
resolve();
|
|
2061
|
+
} else {
|
|
2062
|
+
reject(new Error('Extension messaging copy failed'));
|
|
2063
|
+
}
|
|
2064
|
+
});
|
|
2065
|
+
});
|
|
2066
|
+
copySuccess = true;
|
|
2067
|
+
|
|
2068
|
+
} catch (extensionError) {
|
|
2069
|
+
console.warn('[UIManager] Chrome extension messaging failed:', extensionError);
|
|
2070
|
+
lastError = extensionError;
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
// Method 2: Modern clipboard API (if extension method failed)
|
|
2074
|
+
if (!copySuccess && navigator.clipboard && navigator.clipboard.writeText) {
|
|
2075
|
+
try {
|
|
2076
|
+
|
|
2077
|
+
await navigator.clipboard.writeText(messageText);
|
|
2078
|
+
copySuccess = true;
|
|
2079
|
+
|
|
2080
|
+
} catch (clipboardError) {
|
|
2081
|
+
console.warn('[UIManager] Modern clipboard API failed:', clipboardError);
|
|
2082
|
+
lastError = clipboardError;
|
|
2083
|
+
}
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
// Method 3: Fallback using execCommand
|
|
2087
|
+
if (!copySuccess) {
|
|
2088
|
+
try {
|
|
2089
|
+
|
|
2090
|
+
const textArea = document.createElement('textarea');
|
|
2091
|
+
textArea.value = messageText;
|
|
2092
|
+
textArea.style.position = 'fixed';
|
|
2093
|
+
textArea.style.left = '-999999px';
|
|
2094
|
+
textArea.style.top = '-999999px';
|
|
2095
|
+
textArea.style.opacity = '0';
|
|
2096
|
+
document.body.appendChild(textArea);
|
|
2097
|
+
textArea.focus();
|
|
2098
|
+
textArea.select();
|
|
2099
|
+
textArea.setSelectionRange(0, textArea.value.length);
|
|
2100
|
+
|
|
2101
|
+
const success = document.execCommand('copy');
|
|
2102
|
+
document.body.removeChild(textArea);
|
|
2103
|
+
|
|
2104
|
+
if (success) {
|
|
2105
|
+
copySuccess = true;
|
|
2106
|
+
|
|
2107
|
+
} else {
|
|
2108
|
+
console.warn('[UIManager] execCommand returned false');
|
|
2109
|
+
}
|
|
2110
|
+
} catch (execError) {
|
|
2111
|
+
console.warn('[UIManager] execCommand fallback failed:', execError);
|
|
2112
|
+
lastError = execError;
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
if (copySuccess) {
|
|
2117
|
+
// Show visual feedback
|
|
2118
|
+
this.showCopyFeedback();
|
|
2119
|
+
|
|
2120
|
+
} else {
|
|
2121
|
+
throw new Error(`All clipboard methods failed. Last error: ${lastError?.message || 'Unknown error'}`);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
} catch (error) {
|
|
2125
|
+
console.error('[UIManager] Failed to copy message:', error);
|
|
2126
|
+
this.showNotification('Copy Fail: ' + error.message, 'error');
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
|
|
2130
|
+
showCopyFeedback() {
|
|
2131
|
+
// Show a brief success notification
|
|
2132
|
+
this.showNotification('Message copied to clipboard!', 'success');
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2135
|
+
getStatusIcon(status) {
|
|
2136
|
+
switch (status.toLowerCase()) {
|
|
2137
|
+
case 'working':
|
|
2138
|
+
return '⚙️';
|
|
2139
|
+
case 'thinking':
|
|
2140
|
+
return '🤔';
|
|
2141
|
+
case 'result':
|
|
2142
|
+
case 'done':
|
|
2143
|
+
return '✅';
|
|
2144
|
+
case 'error':
|
|
2145
|
+
return '❌';
|
|
2146
|
+
case 'paused':
|
|
2147
|
+
return '⏸️';
|
|
2148
|
+
case 'running':
|
|
2149
|
+
return '🔄';
|
|
2150
|
+
case 'request':
|
|
2151
|
+
return '💡';
|
|
2152
|
+
case 'additional_request':
|
|
2153
|
+
return '➕';
|
|
2154
|
+
default:
|
|
2155
|
+
return '💡';
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
formatActivityContent(content) {
|
|
2160
|
+
if (!content) return 'No content';
|
|
2161
|
+
|
|
2162
|
+
// Handle object content
|
|
2163
|
+
if (typeof content === 'object') {
|
|
2164
|
+
return `<pre class="json-content">${JSON.stringify(content, null, 2)}</pre>`;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
// Convert content to string
|
|
2168
|
+
let formattedContent = String(content);
|
|
2169
|
+
|
|
2170
|
+
// Use markdown-it library for proper markdown rendering if available
|
|
2171
|
+
if (typeof markdownit !== 'undefined') {
|
|
2172
|
+
try {
|
|
2173
|
+
// Create markdown-it instance with enhanced options
|
|
2174
|
+
const md = markdownit({
|
|
2175
|
+
html: true, // Enable HTML tags in source
|
|
2176
|
+
breaks: true, // Convert '\n' in paragraphs into <br>
|
|
2177
|
+
linkify: true, // Autoconvert URL-like text to links
|
|
2178
|
+
typographer: true // Enable some language-neutral replacement + quotes beautification
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2181
|
+
// Override link renderer to handle file:// protocol
|
|
2182
|
+
const defaultLinkRenderer = md.renderer.rules.link_open || function(tokens, idx, options, env, renderer) {
|
|
2183
|
+
return renderer.renderToken(tokens, idx, options);
|
|
2184
|
+
};
|
|
2185
|
+
|
|
2186
|
+
md.renderer.rules.link_open = function (tokens, idx, options, env, renderer) {
|
|
2187
|
+
const token = tokens[idx];
|
|
2188
|
+
const href = token.attrGet('href');
|
|
2189
|
+
|
|
2190
|
+
if (href && href.startsWith('file://')) {
|
|
2191
|
+
// Convert file:// links to our custom file-link format
|
|
2192
|
+
token.attrSet('href', '#');
|
|
2193
|
+
token.attrSet('class', 'file-link');
|
|
2194
|
+
token.attrSet('data-file-path', href);
|
|
2195
|
+
token.attrSet('title', `Click to open file: ${href}`);
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
return defaultLinkRenderer(tokens, idx, options, env, renderer);
|
|
2199
|
+
};
|
|
2200
|
+
|
|
2201
|
+
// Add task list support manually (markdown-it doesn't have built-in task lists)
|
|
2202
|
+
formattedContent = this.preprocessTaskLists(formattedContent);
|
|
2203
|
+
|
|
2204
|
+
// Pre-process both regular file paths and file:// markdown links
|
|
2205
|
+
const regularFilePathRegex = /\[([^\]]+)\]\(([^)]*\/[^)]*\.[^)]+)\)/g;
|
|
2206
|
+
const markdownFileLinkRegex = /\[([^\]]+)\]\((file:\/\/[^)]+)\)/g;
|
|
2207
|
+
|
|
2208
|
+
// Handle regular file paths (convert to file:// format)
|
|
2209
|
+
formattedContent = formattedContent.replace(regularFilePathRegex, (match, linkText, filePath) => {
|
|
2210
|
+
// Only process if it looks like a file path (contains / and extension) and not already a URL
|
|
2211
|
+
if (!filePath.startsWith('http') && !filePath.startsWith('file://') && (filePath.includes('/') || filePath.includes('\\'))) {
|
|
2212
|
+
const fileUrl = filePath.startsWith('/') ? `file://${filePath}` : `file:///${filePath}`;
|
|
2213
|
+
return `<a href="${fileUrl}" class="file-link-markdown">${linkText}</a>`;
|
|
2214
|
+
}
|
|
2215
|
+
return match;
|
|
2216
|
+
});
|
|
2217
|
+
|
|
2218
|
+
// Handle file:// links
|
|
2219
|
+
formattedContent = formattedContent.replace(markdownFileLinkRegex, (match, linkText, fileUrl) => {
|
|
2220
|
+
// Convert to HTML format that markdown-it will preserve
|
|
2221
|
+
return `<a href="${fileUrl}" class="file-link-markdown">${linkText}</a>`;
|
|
2222
|
+
});
|
|
2223
|
+
|
|
2224
|
+
// Parse markdown
|
|
2225
|
+
const htmlContent = md.render(formattedContent);
|
|
2226
|
+
|
|
2227
|
+
// Post-process to handle local file path links
|
|
2228
|
+
let processedContent = htmlContent;
|
|
2229
|
+
|
|
2230
|
+
// Convert our pre-processed file:// links to proper file-link format
|
|
2231
|
+
const preProcessedFileLinkRegex = /<a href="(file:\/\/[^"]+)"[^>]*class="file-link-markdown"[^>]*>([^<]*)<\/a>/g;
|
|
2232
|
+
processedContent = processedContent.replace(preProcessedFileLinkRegex, (match, fileUrl, linkText) => {
|
|
2233
|
+
try {
|
|
2234
|
+
// Keep original URL but properly escape HTML attributes
|
|
2235
|
+
// Don't decode/encode to preserve original spaces and special characters
|
|
2236
|
+
const escapedUrl = fileUrl.replace(/"/g, '"');
|
|
2237
|
+
|
|
2238
|
+
return `<a href="#" class="file-link" data-file-path="${escapedUrl}" title="Click to open file: ${linkText}">${linkText}</a>`;
|
|
2239
|
+
} catch (error) {
|
|
2240
|
+
console.error('[UIManager] Error processing pre-processed file:// link:', error);
|
|
2241
|
+
return match;
|
|
2242
|
+
}
|
|
2243
|
+
});
|
|
2244
|
+
|
|
2245
|
+
// Add custom classes and post-process
|
|
2246
|
+
return processedContent
|
|
2247
|
+
.replace(/<pre><code/g, '<pre class="code-block"><code')
|
|
2248
|
+
.replace(/<code>/g, '<code class="inline-code">')
|
|
2249
|
+
.replace(/<table>/g, '<table class="markdown-table">')
|
|
2250
|
+
.replace(/<blockquote>/g, '<blockquote class="markdown-quote">');
|
|
2251
|
+
|
|
2252
|
+
} catch (error) {
|
|
2253
|
+
console.warn('[UIManager] markdown-it parsing failed, falling back to basic formatting:', error);
|
|
2254
|
+
// Fall through to basic formatting
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
// Fallback: Enhanced basic markdown-like formatting
|
|
2259
|
+
formattedContent = this.preprocessTaskLists(formattedContent);
|
|
2260
|
+
|
|
2261
|
+
// Bold text **text**
|
|
2262
|
+
formattedContent = formattedContent.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
|
|
2263
|
+
|
|
2264
|
+
// Italic text *text*
|
|
2265
|
+
formattedContent = formattedContent.replace(/\*(.*?)\*/g, '<em>$1</em>');
|
|
2266
|
+
|
|
2267
|
+
// Code blocks ```code```
|
|
2268
|
+
formattedContent = formattedContent.replace(/```([\s\S]*?)```/g, '<pre class="code-block">$1</pre>');
|
|
2269
|
+
|
|
2270
|
+
// Inline code `code`
|
|
2271
|
+
formattedContent = formattedContent.replace(/`([^`]+)`/g, '<code class="inline-code">$1</code>');
|
|
2272
|
+
|
|
2273
|
+
// Headers
|
|
2274
|
+
formattedContent = formattedContent.replace(/^### (.*$)/gm, '<h3>$1</h3>');
|
|
2275
|
+
formattedContent = formattedContent.replace(/^## (.*$)/gm, '<h2>$1</h2>');
|
|
2276
|
+
formattedContent = formattedContent.replace(/^# (.*$)/gm, '<h1>$1</h1>');
|
|
2277
|
+
|
|
2278
|
+
// Lists - regular
|
|
2279
|
+
formattedContent = formattedContent.replace(/^- (.*$)/gm, '<li>$1</li>');
|
|
2280
|
+
formattedContent = formattedContent.replace(/(<li>.*<\/li>)/s, '<ul>$1</ul>');
|
|
2281
|
+
|
|
2282
|
+
// Convert URLs to links
|
|
2283
|
+
const httpUrlRegex = /(https?:\/\/[^\s]+)/g;
|
|
2284
|
+
formattedContent = formattedContent.replace(httpUrlRegex, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>');
|
|
2285
|
+
|
|
2286
|
+
// Convert newlines to br tags
|
|
2287
|
+
formattedContent = formattedContent.replace(/\n/g, '<br>');
|
|
2288
|
+
|
|
2289
|
+
return formattedContent;
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
preprocessTaskLists(content) {
|
|
2293
|
+
// Convert markdown task lists to HTML checkboxes
|
|
2294
|
+
// - [ ] unchecked task -> checkbox unchecked
|
|
2295
|
+
// - [x] checked task -> checkbox checked
|
|
2296
|
+
// - [X] checked task -> checkbox checked
|
|
2297
|
+
return content
|
|
2298
|
+
.replace(/^- \[ \] (.*)$/gm, '<div class="task-item"><input type="checkbox" disabled> $1</div>')
|
|
2299
|
+
.replace(/^- \[[xX]\] (.*)$/gm, '<div class="task-item"><input type="checkbox" checked disabled> $1</div>');
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
scrollActivityToBottom() {
|
|
2303
|
+
if (this.elements.activityLog) {
|
|
2304
|
+
this.elements.activityLog.scrollTop = this.elements.activityLog.scrollHeight;
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
clearTaskInput() {
|
|
2309
|
+
if (this.elements.taskInput) {
|
|
2310
|
+
this.elements.taskInput.value = '';
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2313
|
+
if (this.elements.sendBtn) {
|
|
2314
|
+
this.elements.sendBtn.disabled = true;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
async loadSession(sessionId) {
|
|
2319
|
+
// Check if task is running
|
|
2320
|
+
if (this.state.isTaskRunning) {
|
|
2321
|
+
const canProceed = await this.showTaskRunningWarning('load a different session');
|
|
2322
|
+
if (!canProceed) return;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
try {
|
|
2326
|
+
this.showLoading('Loading session...');
|
|
2327
|
+
|
|
2328
|
+
const success = await this.sessionManager.loadSession(sessionId);
|
|
2329
|
+
|
|
2330
|
+
this.hideLoading();
|
|
2331
|
+
|
|
2332
|
+
if (!success) {
|
|
2333
|
+
this.showNotification('Failed to load session', 'error');
|
|
2334
|
+
}
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
this.hideLoading();
|
|
2337
|
+
this.showNotification(`Failed to load session: ${error.message}`, 'error');
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
|
|
2341
|
+
async updateLLMProfileSelect() {
|
|
2342
|
+
if (!this.elements.llmProfileSelect) return;
|
|
2343
|
+
|
|
2344
|
+
// Preserve current user selection if any (to avoid overriding during profile updates)
|
|
2345
|
+
const currentSelection = this.elements.llmProfileSelect.value;
|
|
2346
|
+
|
|
2347
|
+
const profiles = this.settingsManager.getLLMProfiles();
|
|
2348
|
+
const select = this.elements.llmProfileSelect;
|
|
2349
|
+
select.innerHTML = '';
|
|
2350
|
+
|
|
2351
|
+
if (profiles.length === 0) {
|
|
2352
|
+
// Add placeholder option when no profiles available
|
|
2353
|
+
const placeholderOption = document.createElement('option');
|
|
2354
|
+
placeholderOption.value = '';
|
|
2355
|
+
placeholderOption.textContent = 'No LLM profiles configured - Go to Settings';
|
|
2356
|
+
placeholderOption.disabled = true;
|
|
2357
|
+
placeholderOption.selected = true;
|
|
2358
|
+
select.appendChild(placeholderOption);
|
|
2359
|
+
} else {
|
|
2360
|
+
// Add default empty option
|
|
2361
|
+
const emptyOption = document.createElement('option');
|
|
2362
|
+
emptyOption.value = '';
|
|
2363
|
+
emptyOption.textContent = 'Select LLM Profile...';
|
|
2364
|
+
emptyOption.disabled = true;
|
|
2365
|
+
select.appendChild(emptyOption);
|
|
2366
|
+
|
|
2367
|
+
// Determine selection priority: current selection > saved selection > default profile
|
|
2368
|
+
let targetSelection = currentSelection; // Preserve current selection first
|
|
2369
|
+
|
|
2370
|
+
// If no current selection, get saved selection
|
|
2371
|
+
if (!targetSelection) {
|
|
2372
|
+
try {
|
|
2373
|
+
if (this.userSettingsStorage) {
|
|
2374
|
+
targetSelection = await this.userSettingsStorage.getSelectedLlmProfile();
|
|
2375
|
+
}
|
|
2376
|
+
} catch (error) {
|
|
2377
|
+
console.error('[UIManager] Failed to get saved LLM profile selection:', error);
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
// Add actual profiles
|
|
2382
|
+
let hasSelectedProfile = false;
|
|
2383
|
+
let hasTargetProfile = false;
|
|
2384
|
+
|
|
2385
|
+
profiles.forEach(profile => {
|
|
2386
|
+
const option = document.createElement('option');
|
|
2387
|
+
option.value = profile.profile_name;
|
|
2388
|
+
option.textContent = profile.profile_name;
|
|
2389
|
+
|
|
2390
|
+
// Check if this profile matches our target selection
|
|
2391
|
+
if (targetSelection && profile.profile_name === targetSelection) {
|
|
2392
|
+
hasTargetProfile = true;
|
|
2393
|
+
}
|
|
2394
|
+
|
|
2395
|
+
select.appendChild(option);
|
|
2396
|
+
});
|
|
2397
|
+
|
|
2398
|
+
// Apply selection based on priority
|
|
2399
|
+
if (hasTargetProfile) {
|
|
2400
|
+
select.value = targetSelection;
|
|
2401
|
+
hasSelectedProfile = true;
|
|
2402
|
+
} else {
|
|
2403
|
+
// Fall back to default profile if target not available
|
|
2404
|
+
const defaultProfile = profiles.find(p => p.is_default);
|
|
2405
|
+
if (defaultProfile) {
|
|
2406
|
+
select.value = defaultProfile.profile_name;
|
|
2407
|
+
hasSelectedProfile = true;
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
}
|
|
2412
|
+
|
|
2413
|
+
// Update send button state if taskInput exists
|
|
2414
|
+
if (this.elements.taskInput) {
|
|
2415
|
+
this.handleTaskInputChange({ target: this.elements.taskInput });
|
|
2416
|
+
}
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
showLLMProfileRequiredModal(action) {
|
|
2420
|
+
const isConfigureAction = action === 'configure';
|
|
2421
|
+
const title = isConfigureAction ? 'LLM Profile Required' : 'Please Select LLM Profile';
|
|
2422
|
+
const message = isConfigureAction
|
|
2423
|
+
? 'No LLM profiles are configured. You need to configure at least one LLM profile before sending tasks.'
|
|
2424
|
+
: 'Please select an LLM profile from the dropdown to proceed with your task.';
|
|
2425
|
+
|
|
2426
|
+
const options = isConfigureAction
|
|
2427
|
+
? {
|
|
2428
|
+
confirmText: 'Open Settings',
|
|
2429
|
+
cancelText: 'Cancel',
|
|
2430
|
+
onConfirm: () => {
|
|
2431
|
+
this.handleShowLLMSettings();
|
|
2432
|
+
}
|
|
2433
|
+
}
|
|
2434
|
+
: {
|
|
2435
|
+
confirmText: 'OK',
|
|
2436
|
+
cancelText: 'Open Settings',
|
|
2437
|
+
onConfirm: () => {
|
|
2438
|
+
this.elements.llmProfileSelect?.focus();
|
|
2439
|
+
},
|
|
2440
|
+
onCancel: () => {
|
|
2441
|
+
this.handleShowLLMSettings();
|
|
2442
|
+
}
|
|
2443
|
+
};
|
|
2444
|
+
|
|
2445
|
+
this.modalManager.showWarningModal(title, message, options);
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
showVoiceProfileRequiredModal(action) {
|
|
2449
|
+
const isConfigureAction = action === 'configure';
|
|
2450
|
+
const title = isConfigureAction ? 'Voice Profile Required' : 'Please Select Voice Profile';
|
|
2451
|
+
const message = isConfigureAction
|
|
2452
|
+
? 'No voice recognition (ASR) profiles are configured. You need to configure at least one voice profile before using voice input.'
|
|
2453
|
+
: 'Please configure a voice recognition profile to use voice input functionality.';
|
|
2454
|
+
|
|
2455
|
+
const options = isConfigureAction
|
|
2456
|
+
? {
|
|
2457
|
+
confirmText: 'Open Voice Settings',
|
|
2458
|
+
cancelText: 'Cancel',
|
|
2459
|
+
onConfirm: () => {
|
|
2460
|
+
this.handleShowVoiceSettings();
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
: {
|
|
2464
|
+
confirmText: 'Open Voice Settings',
|
|
2465
|
+
cancelText: 'Cancel',
|
|
2466
|
+
onConfirm: () => {
|
|
2467
|
+
this.handleShowVoiceSettings();
|
|
2468
|
+
}
|
|
2469
|
+
};
|
|
2470
|
+
|
|
2471
|
+
this.modalManager.showWarningModal(title, message, options);
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
async handleShowVoiceSettings() {
|
|
2475
|
+
// Enhanced task running check
|
|
2476
|
+
const statusCheck = await this.checkTaskStatus();
|
|
2477
|
+
if (statusCheck.isRunning) {
|
|
2478
|
+
const canProceed = await this.showTaskRunningWarning('access voice settings');
|
|
2479
|
+
if (!canProceed) return;
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
// Show settings and navigate directly to Voice profiles tab
|
|
2483
|
+
this.settingsManager.showSettings();
|
|
2484
|
+
|
|
2485
|
+
// Switch to Voice profiles tab after settings are shown
|
|
2486
|
+
setTimeout(() => {
|
|
2487
|
+
const voiceTab = document.querySelector('.settings-tab[data-tab="voice-profiles"]');
|
|
2488
|
+
if (voiceTab) {
|
|
2489
|
+
voiceTab.click();
|
|
2490
|
+
}
|
|
2491
|
+
}, 100);
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
showLLMConnectionFailedModal(errorData) {
|
|
2495
|
+
|
|
2496
|
+
|
|
2497
|
+
const llmProfile = errorData.llm_profile || 'unknown';
|
|
2498
|
+
const errorMessage = errorData.message || 'Cannot connect to LLM API';
|
|
2499
|
+
|
|
2500
|
+
const title = 'LLM Connection Failed';
|
|
2501
|
+
const message = `${errorMessage}\n\nThe LLM profile "${llmProfile}" cannot be reached. Please check your LLM configuration and API credentials.`;
|
|
2502
|
+
|
|
2503
|
+
const options = {
|
|
2504
|
+
confirmText: 'Update LLM Profile',
|
|
2505
|
+
cancelText: 'Cancel',
|
|
2506
|
+
onConfirm: () => {
|
|
2507
|
+
// Navigate to the specific LLM profile edit page
|
|
2508
|
+
this.handleShowLLMProfileSettings(llmProfile);
|
|
2509
|
+
}
|
|
2510
|
+
};
|
|
2511
|
+
|
|
2512
|
+
|
|
2513
|
+
this.modalManager.showWarningModal(title, message, options);
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
async handleShowLLMProfileSettings(profileName) {
|
|
2517
|
+
// Enhanced task running check
|
|
2518
|
+
const statusCheck = await this.checkTaskStatus();
|
|
2519
|
+
if (statusCheck.isRunning) {
|
|
2520
|
+
const canProceed = await this.showTaskRunningWarning('access settings');
|
|
2521
|
+
if (!canProceed) return;
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
// Show settings and navigate to the specific LLM profile
|
|
2525
|
+
this.settingsManager.showSettings();
|
|
2526
|
+
|
|
2527
|
+
// Navigate to LLM profiles section and edit the specific profile
|
|
2528
|
+
// We'll add a method to settings manager to handle this
|
|
2529
|
+
if (this.settingsManager.navigateToLLMProfile) {
|
|
2530
|
+
this.settingsManager.navigateToLLMProfile(profileName);
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
|
|
2534
|
+
// Loading and notifications
|
|
2535
|
+
showLoading(message = 'Loading...') {
|
|
2536
|
+
this.state.isLoading = true;
|
|
2537
|
+
|
|
2538
|
+
if (this.elements.loadingOverlay) {
|
|
2539
|
+
const textElement = this.elements.loadingOverlay.querySelector('.loading-text');
|
|
2540
|
+
if (textElement) {
|
|
2541
|
+
textElement.textContent = message;
|
|
2542
|
+
}
|
|
2543
|
+
this.elements.loadingOverlay.classList.remove('hidden');
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
hideLoading() {
|
|
2548
|
+
this.state.isLoading = false;
|
|
2549
|
+
|
|
2550
|
+
if (this.elements.loadingOverlay) {
|
|
2551
|
+
this.elements.loadingOverlay.classList.add('hidden');
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
showNotification(message, type = 'info') {
|
|
2556
|
+
// Map UI notification types to valid Chrome notification types
|
|
2557
|
+
if(type === "error" || type == "system") {
|
|
2558
|
+
const validTypes = {
|
|
2559
|
+
'info': 'basic',
|
|
2560
|
+
'success': 'basic',
|
|
2561
|
+
'warning': 'basic',
|
|
2562
|
+
'system': 'basic',
|
|
2563
|
+
'error': 'basic',
|
|
2564
|
+
'basic': 'basic',
|
|
2565
|
+
'image': 'image',
|
|
2566
|
+
'list': 'list',
|
|
2567
|
+
'progress': 'progress'
|
|
2568
|
+
};
|
|
2569
|
+
|
|
2570
|
+
const chromeType = validTypes[type] || 'basic';
|
|
2571
|
+
|
|
2572
|
+
// Send notification to background script for display
|
|
2573
|
+
chrome.runtime.sendMessage({
|
|
2574
|
+
type: 'SHOW_NOTIFICATION',
|
|
2575
|
+
data: {
|
|
2576
|
+
title: 'VibeSurf',
|
|
2577
|
+
message,
|
|
2578
|
+
type: chromeType
|
|
2579
|
+
}
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// Restore LLM profile selection from user settings storage
|
|
2585
|
+
async restoreLlmProfileSelection() {
|
|
2586
|
+
try {
|
|
2587
|
+
if (this.userSettingsStorage && this.elements.llmProfileSelect) {
|
|
2588
|
+
// Check current options available
|
|
2589
|
+
const availableOptions = Array.from(this.elements.llmProfileSelect.options).map(opt => opt.value);
|
|
2590
|
+
|
|
2591
|
+
const savedLlmProfile = await this.userSettingsStorage.getSelectedLlmProfile();
|
|
2592
|
+
|
|
2593
|
+
if (savedLlmProfile && savedLlmProfile.trim() !== '') {
|
|
2594
|
+
// Check if the saved profile exists in the current options
|
|
2595
|
+
const option = this.elements.llmProfileSelect.querySelector(`option[value="${savedLlmProfile}"]`);
|
|
2596
|
+
|
|
2597
|
+
if (option) {
|
|
2598
|
+
this.elements.llmProfileSelect.value = savedLlmProfile;
|
|
2599
|
+
} else {
|
|
2600
|
+
console.warn('[UIManager] Saved LLM profile not found in current options:', savedLlmProfile);
|
|
2601
|
+
}
|
|
2602
|
+
} else {
|
|
2603
|
+
// Check localStorage backup for browser restart scenarios
|
|
2604
|
+
const backupProfile = localStorage.getItem('vibesurf-llm-profile-backup');
|
|
2605
|
+
|
|
2606
|
+
if (backupProfile) {
|
|
2607
|
+
const option = this.elements.llmProfileSelect.querySelector(`option[value="${backupProfile}"]`);
|
|
2608
|
+
if (option) {
|
|
2609
|
+
this.elements.llmProfileSelect.value = backupProfile;
|
|
2610
|
+
// Also save it back to Chrome storage
|
|
2611
|
+
await this.userSettingsStorage.setSelectedLlmProfile(backupProfile);
|
|
2612
|
+
} else {
|
|
2613
|
+
console.warn('[UIManager] Backup profile not found in current options:', backupProfile);
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
} else {
|
|
2618
|
+
console.warn('[UIManager] Required components not available - userSettingsStorage:', !!this.userSettingsStorage, 'llmProfileSelect:', !!this.elements.llmProfileSelect);
|
|
2619
|
+
}
|
|
2620
|
+
} catch (error) {
|
|
2621
|
+
console.error('[UIManager] Failed to restore LLM profile selection:', error);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
// Check and update voice button state based on ASR profile availability
|
|
2626
|
+
async updateVoiceButtonState() {
|
|
2627
|
+
if (!this.elements.voiceRecordBtn) return;
|
|
2628
|
+
|
|
2629
|
+
try {
|
|
2630
|
+
const isVoiceAvailable = await this.voiceRecorder.isVoiceRecordingAvailable();
|
|
2631
|
+
|
|
2632
|
+
if (!isVoiceAvailable) {
|
|
2633
|
+
// Add visual indication but keep button enabled for click handling
|
|
2634
|
+
this.elements.voiceRecordBtn.classList.add('voice-disabled');
|
|
2635
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Voice input disabled - No ASR profiles configured. Click to configure.');
|
|
2636
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', 'Voice input disabled - No ASR profiles configured. Click to configure.');
|
|
2637
|
+
} else {
|
|
2638
|
+
// Remove visual indication and restore normal tooltip
|
|
2639
|
+
this.elements.voiceRecordBtn.classList.remove('voice-disabled');
|
|
2640
|
+
if (!this.elements.voiceRecordBtn.classList.contains('recording')) {
|
|
2641
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Click to start voice recording');
|
|
2642
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', 'Click to start voice recording');
|
|
2643
|
+
}
|
|
2644
|
+
}
|
|
2645
|
+
} catch (error) {
|
|
2646
|
+
console.error('[UIManager] Error updating voice button state:', error);
|
|
2647
|
+
// Fallback: add visual indication but keep button enabled
|
|
2648
|
+
this.elements.voiceRecordBtn.classList.add('voice-disabled');
|
|
2649
|
+
this.elements.voiceRecordBtn.setAttribute('title', 'Voice input temporarily unavailable. Click for more info.');
|
|
2650
|
+
this.elements.voiceRecordBtn.setAttribute('data-tooltip', 'Voice input temporarily unavailable. Click for more info.');
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
|
|
2654
|
+
// Initialization
|
|
2655
|
+
async initialize() {
|
|
2656
|
+
try {
|
|
2657
|
+
// Check for microphone permission parameter first (like Doubao AI)
|
|
2658
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
2659
|
+
const enterParam = urlParams.get('enter');
|
|
2660
|
+
|
|
2661
|
+
if (enterParam === 'mic-permission') {
|
|
2662
|
+
console.log('[UIManager] Detected microphone permission request parameter');
|
|
2663
|
+
this.showMicrophonePermissionRequest();
|
|
2664
|
+
return; // Skip normal initialization for permission request
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
this.showLoading('Initializing VibeSurf...');
|
|
2668
|
+
|
|
2669
|
+
// Initialize user settings storage first
|
|
2670
|
+
if (this.userSettingsStorage) {
|
|
2671
|
+
|
|
2672
|
+
await this.userSettingsStorage.initialize();
|
|
2673
|
+
|
|
2674
|
+
} else {
|
|
2675
|
+
console.error('[UIManager] userSettingsStorage not available during initialization');
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
// Load settings data through settings manager
|
|
2679
|
+
|
|
2680
|
+
await this.settingsManager.loadSettingsData();
|
|
2681
|
+
|
|
2682
|
+
|
|
2683
|
+
// Now restore user selections AFTER profiles are loaded but before any other initialization
|
|
2684
|
+
|
|
2685
|
+
this.isRestoringSelections = true;
|
|
2686
|
+
|
|
2687
|
+
try {
|
|
2688
|
+
// Restore LLM profile selection first
|
|
2689
|
+
await this.restoreLlmProfileSelection();
|
|
2690
|
+
|
|
2691
|
+
// Restore agent mode selection
|
|
2692
|
+
await this.restoreAgentModeSelection();
|
|
2693
|
+
} finally {
|
|
2694
|
+
this.isRestoringSelections = false;
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2697
|
+
// Check and update voice button state based on ASR profile availability
|
|
2698
|
+
await this.updateVoiceButtonState();
|
|
2699
|
+
|
|
2700
|
+
// Check version and show upgrade button if needed
|
|
2701
|
+
await this.checkVersionAndShowUpgrade();
|
|
2702
|
+
|
|
2703
|
+
// Don't initialize news carousel on initial load - it will be initialized when user clicks "New Session"
|
|
2704
|
+
// This keeps the extension fast to load
|
|
2705
|
+
|
|
2706
|
+
// Create initial session if none exists
|
|
2707
|
+
if (!this.sessionManager.getCurrentSession()) {
|
|
2708
|
+
await this.sessionManager.createSession();
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
this.hideLoading();
|
|
2712
|
+
|
|
2713
|
+
} catch (error) {
|
|
2714
|
+
this.hideLoading();
|
|
2715
|
+
console.error('[UIManager] Initialization failed:', error);
|
|
2716
|
+
this.showNotification(`Initialization failed: ${error.message}`, 'error');
|
|
2717
|
+
}
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
// Show microphone permission request (like Doubao AI) - simplified approach
|
|
2721
|
+
showMicrophonePermissionRequest() {
|
|
2722
|
+
console.log('[UIManager] Showing simplified microphone permission request');
|
|
2723
|
+
console.log('[UIManager] Current URL:', window.location.href);
|
|
2724
|
+
console.log('[UIManager] URL params:', window.location.search);
|
|
2725
|
+
|
|
2726
|
+
// Simple approach: just try to get permission directly
|
|
2727
|
+
this.requestMicrophonePermissionDirectly();
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
// Direct microphone permission request (simplified like Doubao AI)
|
|
2731
|
+
async requestMicrophonePermissionDirectly() {
|
|
2732
|
+
console.log('[UIManager] Requesting microphone permission directly');
|
|
2733
|
+
|
|
2734
|
+
try {
|
|
2735
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2736
|
+
audio: true,
|
|
2737
|
+
video: false
|
|
2738
|
+
});
|
|
2739
|
+
|
|
2740
|
+
console.log('[UIManager] Microphone permission granted!');
|
|
2741
|
+
|
|
2742
|
+
// Stop the stream immediately (we just need permission)
|
|
2743
|
+
stream.getTracks().forEach(track => track.stop());
|
|
2744
|
+
|
|
2745
|
+
// Send success message back to original tab
|
|
2746
|
+
console.log('[UIManager] Sending success message...');
|
|
2747
|
+
chrome.runtime.sendMessage({
|
|
2748
|
+
type: 'MICROPHONE_PERMISSION_RESULT',
|
|
2749
|
+
granted: true
|
|
2750
|
+
}, (response) => {
|
|
2751
|
+
console.log('[UIManager] Success message response:', response);
|
|
2752
|
+
});
|
|
2753
|
+
|
|
2754
|
+
// Close this tab after a short delay
|
|
2755
|
+
setTimeout(() => {
|
|
2756
|
+
console.log('[UIManager] Closing tab...');
|
|
2757
|
+
window.close();
|
|
2758
|
+
}, 1000);
|
|
2759
|
+
|
|
2760
|
+
} catch (error) {
|
|
2761
|
+
console.error('[UIManager] Microphone permission denied:', error);
|
|
2762
|
+
console.log('[UIManager] Error name:', error.name);
|
|
2763
|
+
console.log('[UIManager] Error message:', error.message);
|
|
2764
|
+
console.log('[UIManager] Error stack:', error.stack);
|
|
2765
|
+
|
|
2766
|
+
// Send error message back to original tab
|
|
2767
|
+
console.log('[UIManager] Sending error message...');
|
|
2768
|
+
chrome.runtime.sendMessage({
|
|
2769
|
+
type: 'MICROPHONE_PERMISSION_RESULT',
|
|
2770
|
+
granted: false,
|
|
2771
|
+
error: error.message,
|
|
2772
|
+
errorName: error.name
|
|
2773
|
+
}, (response) => {
|
|
2774
|
+
console.log('[UIManager] Error message response:', response);
|
|
2775
|
+
});
|
|
2776
|
+
|
|
2777
|
+
// Close this tab after a short delay
|
|
2778
|
+
setTimeout(() => {
|
|
2779
|
+
console.log('[UIManager] Closing tab after error...');
|
|
2780
|
+
window.close();
|
|
2781
|
+
}, 2000);
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
// Restore agent mode selection from user settings storage
|
|
2785
|
+
async restoreAgentModeSelection() {
|
|
2786
|
+
try {
|
|
2787
|
+
|
|
2788
|
+
if (this.userSettingsStorage && this.elements.agentModeSelect) {
|
|
2789
|
+
// Check current options available
|
|
2790
|
+
const availableOptions = Array.from(this.elements.agentModeSelect.options).map(opt => opt.value);
|
|
2791
|
+
|
|
2792
|
+
const savedAgentMode = await this.userSettingsStorage.getSelectedAgentMode();
|
|
2793
|
+
|
|
2794
|
+
if (savedAgentMode && savedAgentMode.trim() !== '') {
|
|
2795
|
+
// Restore any saved agent mode, including 'thinking'
|
|
2796
|
+
this.elements.agentModeSelect.value = savedAgentMode;
|
|
2797
|
+
// Ensure the option is actually selected
|
|
2798
|
+
const option = this.elements.agentModeSelect.querySelector(`option[value="${savedAgentMode}"]`);
|
|
2799
|
+
if (option) {
|
|
2800
|
+
option.selected = true;
|
|
2801
|
+
console.log('[UIManager] Restored agent mode selection:', savedAgentMode);
|
|
2802
|
+
} else {
|
|
2803
|
+
console.warn('[UIManager] Agent mode option not found:', savedAgentMode);
|
|
2804
|
+
}
|
|
2805
|
+
} else {
|
|
2806
|
+
// Check localStorage backup for browser restart scenarios
|
|
2807
|
+
const backupMode = localStorage.getItem('vibesurf-agent-mode-backup');
|
|
2808
|
+
|
|
2809
|
+
if (backupMode) {
|
|
2810
|
+
const option = this.elements.agentModeSelect.querySelector(`option[value="${backupMode}"]`);
|
|
2811
|
+
if (option) {
|
|
2812
|
+
this.elements.agentModeSelect.value = backupMode;
|
|
2813
|
+
// Also save it back to Chrome storage
|
|
2814
|
+
await this.userSettingsStorage.setSelectedAgentMode(backupMode);
|
|
2815
|
+
} else {
|
|
2816
|
+
console.warn('[UIManager] Backup agent mode not found in current options:', backupMode);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
} else {
|
|
2821
|
+
console.warn('[UIManager] Required components not available - userSettingsStorage:', !!this.userSettingsStorage, 'agentModeSelect:', !!this.elements.agentModeSelect);
|
|
2822
|
+
}
|
|
2823
|
+
} catch (error) {
|
|
2824
|
+
console.error('[UIManager] Failed to restore agent mode selection:', error);
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2828
|
+
// Version checking and upgrade button management
|
|
2829
|
+
async checkVersionAndShowUpgrade() {
|
|
2830
|
+
try {
|
|
2831
|
+
console.log('[UIManager] Checking version for upgrade notification...');
|
|
2832
|
+
|
|
2833
|
+
// Get extension version from version.js
|
|
2834
|
+
const extensionVersion = window.VIBESURF_EXTENSION_VERSION;
|
|
2835
|
+
if (!extensionVersion) {
|
|
2836
|
+
console.warn('[UIManager] Extension version not found');
|
|
2837
|
+
return;
|
|
2838
|
+
}
|
|
2839
|
+
|
|
2840
|
+
console.log('[UIManager] Extension version:', extensionVersion);
|
|
2841
|
+
|
|
2842
|
+
// Get VibeSurf backend version from API
|
|
2843
|
+
const versionResponse = await this.apiClient.getVibeSurfVersion();
|
|
2844
|
+
const backendVersion = versionResponse.version;
|
|
2845
|
+
|
|
2846
|
+
if (!backendVersion) {
|
|
2847
|
+
console.warn('[UIManager] Backend version not found');
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
console.log('[UIManager] Backend version:', backendVersion);
|
|
2852
|
+
|
|
2853
|
+
// Compare versions - show upgrade if extension version is different from backend
|
|
2854
|
+
const shouldShowUpgrade = this.compareVersions(extensionVersion, backendVersion);
|
|
2855
|
+
|
|
2856
|
+
if (shouldShowUpgrade) {
|
|
2857
|
+
console.log('[UIManager] Extension version mismatch detected, showing upgrade button');
|
|
2858
|
+
this.showUpgradeButton();
|
|
2859
|
+
} else {
|
|
2860
|
+
console.log('[UIManager] Extension version is up to date');
|
|
2861
|
+
this.hideUpgradeButton();
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
} catch (error) {
|
|
2865
|
+
console.error('[UIManager] Failed to check version:', error);
|
|
2866
|
+
// Don't show upgrade button on error to avoid false positives
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
// Compare versions - returns true if extension needs upgrade
|
|
2871
|
+
compareVersions(extensionVersion, backendVersion) {
|
|
2872
|
+
// Remove any +dev suffix from extension version for comparison
|
|
2873
|
+
const cleanExtensionVersion = extensionVersion.replace(/\+.*$/, '');
|
|
2874
|
+
const cleanBackendVersion = backendVersion.replace(/\+.*$/, '');
|
|
2875
|
+
|
|
2876
|
+
console.log('[UIManager] Comparing versions:', cleanExtensionVersion, 'vs', cleanBackendVersion);
|
|
2877
|
+
|
|
2878
|
+
// Simple string comparison - if they're different, show upgrade
|
|
2879
|
+
// This handles cases where extension is older, newer, or just different
|
|
2880
|
+
return cleanExtensionVersion !== cleanBackendVersion;
|
|
2881
|
+
}
|
|
2882
|
+
|
|
2883
|
+
// Show upgrade button with animation
|
|
2884
|
+
showUpgradeButton() {
|
|
2885
|
+
if (this.elements.upgradeBtn) {
|
|
2886
|
+
this.elements.upgradeBtn.classList.remove('hidden');
|
|
2887
|
+
console.log('[UIManager] Upgrade button shown');
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
|
|
2891
|
+
// Hide upgrade button
|
|
2892
|
+
hideUpgradeButton() {
|
|
2893
|
+
if (this.elements.upgradeBtn) {
|
|
2894
|
+
this.elements.upgradeBtn.classList.add('hidden');
|
|
2895
|
+
console.log('[UIManager] Upgrade button hidden');
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2899
|
+
// Cleanup
|
|
2900
|
+
destroy() {
|
|
2901
|
+
// Prevent multiple cleanup calls
|
|
2902
|
+
if (this.isDestroying) {
|
|
2903
|
+
console.log('[UIManager] Cleanup already in progress, skipping...');
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
this.isDestroying = true;
|
|
2908
|
+
console.log('[UIManager] Destroying UI manager...');
|
|
2909
|
+
|
|
2910
|
+
try {
|
|
2911
|
+
// Stop task status monitoring
|
|
2912
|
+
this.stopTaskStatusMonitoring();
|
|
2913
|
+
|
|
2914
|
+
// Cleanup voice recorder
|
|
2915
|
+
if (this.voiceRecorder) {
|
|
2916
|
+
this.voiceRecorder.cleanup();
|
|
2917
|
+
this.voiceRecorder = null;
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
// Cleanup managers with error handling
|
|
2921
|
+
if (this.settingsManager) {
|
|
2922
|
+
try {
|
|
2923
|
+
if (typeof this.settingsManager.destroy === 'function') {
|
|
2924
|
+
this.settingsManager.destroy();
|
|
2925
|
+
}
|
|
2926
|
+
} catch (error) {
|
|
2927
|
+
console.error('[UIManager] Error destroying settings manager:', error);
|
|
2928
|
+
}
|
|
2929
|
+
this.settingsManager = null;
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
if (this.historyManager) {
|
|
2933
|
+
try {
|
|
2934
|
+
if (typeof this.historyManager.destroy === 'function') {
|
|
2935
|
+
this.historyManager.destroy();
|
|
2936
|
+
}
|
|
2937
|
+
} catch (error) {
|
|
2938
|
+
console.error('[UIManager] Error destroying history manager:', error);
|
|
2939
|
+
}
|
|
2940
|
+
this.historyManager = null;
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
if (this.fileManager) {
|
|
2944
|
+
try {
|
|
2945
|
+
if (typeof this.fileManager.destroy === 'function') {
|
|
2946
|
+
this.fileManager.destroy();
|
|
2947
|
+
}
|
|
2948
|
+
} catch (error) {
|
|
2949
|
+
console.error('[UIManager] Error destroying file manager:', error);
|
|
2950
|
+
}
|
|
2951
|
+
this.fileManager = null;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
if (this.modalManager) {
|
|
2955
|
+
try {
|
|
2956
|
+
if (typeof this.modalManager.destroy === 'function') {
|
|
2957
|
+
this.modalManager.destroy();
|
|
2958
|
+
}
|
|
2959
|
+
} catch (error) {
|
|
2960
|
+
console.error('[UIManager] Error destroying modal manager:', error);
|
|
2961
|
+
}
|
|
2962
|
+
this.modalManager = null;
|
|
2963
|
+
}
|
|
2964
|
+
|
|
2965
|
+
// Clear state
|
|
2966
|
+
this.state = {
|
|
2967
|
+
isLoading: false,
|
|
2968
|
+
isTaskRunning: false,
|
|
2969
|
+
taskInfo: null
|
|
2970
|
+
};
|
|
2971
|
+
|
|
2972
|
+
console.log('[UIManager] UI manager cleanup complete');
|
|
2973
|
+
} catch (error) {
|
|
2974
|
+
console.error('[UIManager] Error during destroy:', error);
|
|
2975
|
+
} finally {
|
|
2976
|
+
this.isDestroying = false;
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
|
|
2980
|
+
// Tab Selector Methods
|
|
2981
|
+
initializeTabSelector() {
|
|
2982
|
+
|
|
2983
|
+
|
|
2984
|
+
// Initialize tab selector state
|
|
2985
|
+
this.tabSelectorState = {
|
|
2986
|
+
isVisible: false,
|
|
2987
|
+
selectedTabs: [],
|
|
2988
|
+
allTabs: [],
|
|
2989
|
+
atPosition: -1 // Position where @ was typed
|
|
2990
|
+
};
|
|
2991
|
+
|
|
2992
|
+
|
|
2993
|
+
|
|
2994
|
+
// Bind tab selector events
|
|
2995
|
+
this.bindTabSelectorEvents();
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
bindTabSelectorEvents() {
|
|
2999
|
+
|
|
3000
|
+
|
|
3001
|
+
|
|
3002
|
+
// Select all radio button
|
|
3003
|
+
this.elements.selectAllTabs?.addEventListener('change', this.handleSelectAllTabs.bind(this));
|
|
3004
|
+
|
|
3005
|
+
// Hide on click outside
|
|
3006
|
+
document.addEventListener('click', (event) => {
|
|
3007
|
+
if (this.tabSelectorState.isVisible &&
|
|
3008
|
+
this.elements.tabSelectorDropdown &&
|
|
3009
|
+
!this.elements.tabSelectorDropdown.contains(event.target) &&
|
|
3010
|
+
!this.elements.taskInput?.contains(event.target)) {
|
|
3011
|
+
this.hideTabSelector();
|
|
3012
|
+
}
|
|
3013
|
+
});
|
|
3014
|
+
|
|
3015
|
+
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
handleTabSelectorInput(event) {
|
|
3019
|
+
// Safety check - ensure tab selector state is initialized
|
|
3020
|
+
if (!this.tabSelectorState) {
|
|
3021
|
+
console.warn('[UIManager] Tab selector state not initialized');
|
|
3022
|
+
return;
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
const inputValue = event.target.value;
|
|
3026
|
+
const cursorPosition = event.target.selectionStart;
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
|
|
3030
|
+
// Check if @ was just typed
|
|
3031
|
+
if (inputValue[cursorPosition - 1] === '@') {
|
|
3032
|
+
|
|
3033
|
+
this.tabSelectorState.atPosition = cursorPosition - 1;
|
|
3034
|
+
this.showTabSelector();
|
|
3035
|
+
} else if (this.tabSelectorState.isVisible) {
|
|
3036
|
+
// Check if @ was deleted - hide tab selector immediately
|
|
3037
|
+
if (this.tabSelectorState.atPosition >= 0 &&
|
|
3038
|
+
(this.tabSelectorState.atPosition >= inputValue.length ||
|
|
3039
|
+
inputValue[this.tabSelectorState.atPosition] !== '@')) {
|
|
3040
|
+
|
|
3041
|
+
this.hideTabSelector();
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
// Hide tab selector if user continues typing after @
|
|
3046
|
+
const textAfterAt = inputValue.substring(this.tabSelectorState.atPosition + 1, cursorPosition);
|
|
3047
|
+
if (textAfterAt.length > 0 && !textAfterAt.match(/^[\s]*$/)) {
|
|
3048
|
+
|
|
3049
|
+
this.hideTabSelector();
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
|
|
3054
|
+
async showTabSelector() {
|
|
3055
|
+
|
|
3056
|
+
|
|
3057
|
+
|
|
3058
|
+
if (!this.elements.tabSelectorDropdown || !this.elements.taskInput) {
|
|
3059
|
+
console.error('[UIManager] Tab selector elements not found', {
|
|
3060
|
+
dropdown: this.elements.tabSelectorDropdown,
|
|
3061
|
+
taskInput: this.elements.taskInput
|
|
3062
|
+
});
|
|
3063
|
+
return;
|
|
3064
|
+
}
|
|
3065
|
+
|
|
3066
|
+
try {
|
|
3067
|
+
|
|
3068
|
+
// Fetch tab data from backend
|
|
3069
|
+
await this.populateTabSelector();
|
|
3070
|
+
|
|
3071
|
+
|
|
3072
|
+
// Position the dropdown relative to the input
|
|
3073
|
+
this.positionTabSelector();
|
|
3074
|
+
|
|
3075
|
+
|
|
3076
|
+
// Show the dropdown with explicit visibility
|
|
3077
|
+
this.elements.tabSelectorDropdown.classList.remove('hidden');
|
|
3078
|
+
this.elements.tabSelectorDropdown.style.display = 'block';
|
|
3079
|
+
this.elements.tabSelectorDropdown.style.visibility = 'visible';
|
|
3080
|
+
this.elements.tabSelectorDropdown.style.opacity = '1';
|
|
3081
|
+
this.tabSelectorState.isVisible = true;
|
|
3082
|
+
|
|
3083
|
+
|
|
3084
|
+
|
|
3085
|
+
|
|
3086
|
+
|
|
3087
|
+
} catch (error) {
|
|
3088
|
+
console.error('[UIManager] Failed to show tab selector:', error);
|
|
3089
|
+
this.showNotification('Failed to load browser tabs', 'error');
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
hideTabSelector() {
|
|
3094
|
+
if (this.elements.tabSelectorDropdown) {
|
|
3095
|
+
this.elements.tabSelectorDropdown.classList.add('hidden');
|
|
3096
|
+
this.elements.tabSelectorDropdown.style.display = 'none'; // Ensure it's hidden
|
|
3097
|
+
}
|
|
3098
|
+
this.tabSelectorState.isVisible = false;
|
|
3099
|
+
this.tabSelectorState.selectedTabs = [];
|
|
3100
|
+
this.tabSelectorState.atPosition = -1;
|
|
3101
|
+
|
|
3102
|
+
|
|
3103
|
+
}
|
|
3104
|
+
|
|
3105
|
+
positionTabSelector() {
|
|
3106
|
+
if (!this.elements.tabSelectorDropdown || !this.elements.taskInput) return;
|
|
3107
|
+
|
|
3108
|
+
const inputRect = this.elements.taskInput.getBoundingClientRect();
|
|
3109
|
+
const dropdown = this.elements.tabSelectorDropdown;
|
|
3110
|
+
|
|
3111
|
+
|
|
3112
|
+
|
|
3113
|
+
// Calculate 90% width of input
|
|
3114
|
+
const dropdownWidth = inputRect.width * 0.9;
|
|
3115
|
+
|
|
3116
|
+
// Position dropdown ABOVE the input (not below)
|
|
3117
|
+
dropdown.style.position = 'fixed';
|
|
3118
|
+
dropdown.style.bottom = `${window.innerHeight - inputRect.top + 5}px`; // Above the input
|
|
3119
|
+
dropdown.style.left = `${inputRect.left + (inputRect.width - dropdownWidth) / 2}px`; // Centered
|
|
3120
|
+
dropdown.style.width = `${dropdownWidth}px`; // 80% of input width
|
|
3121
|
+
dropdown.style.zIndex = '9999';
|
|
3122
|
+
dropdown.style.maxHeight = '300px';
|
|
3123
|
+
dropdown.style.overflowY = 'auto';
|
|
3124
|
+
|
|
3125
|
+
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
async populateTabSelector() {
|
|
3129
|
+
try {
|
|
3130
|
+
|
|
3131
|
+
// Get all tabs and active tab from backend
|
|
3132
|
+
const [allTabsResponse, activeTabResponse] = await Promise.all([
|
|
3133
|
+
this.apiClient.getAllBrowserTabs(),
|
|
3134
|
+
this.apiClient.getActiveBrowserTab()
|
|
3135
|
+
]);
|
|
3136
|
+
|
|
3137
|
+
|
|
3138
|
+
|
|
3139
|
+
const allTabs = allTabsResponse.tabs || allTabsResponse || {};
|
|
3140
|
+
const activeTab = activeTabResponse.tab || activeTabResponse || {};
|
|
3141
|
+
const activeTabId = Object.keys(activeTab)[0];
|
|
3142
|
+
|
|
3143
|
+
|
|
3144
|
+
|
|
3145
|
+
this.tabSelectorState.allTabs = allTabs;
|
|
3146
|
+
|
|
3147
|
+
// Clear existing options
|
|
3148
|
+
if (this.elements.tabOptionsList) {
|
|
3149
|
+
this.elements.tabOptionsList.innerHTML = '';
|
|
3150
|
+
|
|
3151
|
+
} else {
|
|
3152
|
+
console.error('[UIManager] tabOptionsList element not found!');
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
// Add fallback test data if no tabs returned
|
|
3157
|
+
if (Object.keys(allTabs).length === 0) {
|
|
3158
|
+
console.warn('[UIManager] No tabs returned from API, adding test data for debugging');
|
|
3159
|
+
const testTabs = {
|
|
3160
|
+
'test-1': { title: 'Test Tab 1', url: 'https://example.com' },
|
|
3161
|
+
'test-2': { title: 'Test Tab 2', url: 'https://google.com' },
|
|
3162
|
+
'test-3': { title: 'Very Long Tab Title That Should Be Truncated', url: 'https://github.com' }
|
|
3163
|
+
};
|
|
3164
|
+
|
|
3165
|
+
Object.entries(testTabs).forEach(([tabId, tabInfo]) => {
|
|
3166
|
+
const isActive = tabId === 'test-1';
|
|
3167
|
+
|
|
3168
|
+
const option = this.createTabOption(tabId, tabInfo, isActive);
|
|
3169
|
+
this.elements.tabOptionsList.appendChild(option);
|
|
3170
|
+
});
|
|
3171
|
+
|
|
3172
|
+
this.tabSelectorState.allTabs = testTabs;
|
|
3173
|
+
} else {
|
|
3174
|
+
// Add real tab options
|
|
3175
|
+
Object.entries(allTabs).forEach(([tabId, tabInfo]) => {
|
|
3176
|
+
const isActive = tabId === activeTabId;
|
|
3177
|
+
|
|
3178
|
+
const option = this.createTabOption(tabId, tabInfo, isActive);
|
|
3179
|
+
this.elements.tabOptionsList.appendChild(option);
|
|
3180
|
+
});
|
|
3181
|
+
}
|
|
3182
|
+
|
|
3183
|
+
// Reset select all checkbox
|
|
3184
|
+
if (this.elements.selectAllTabs) {
|
|
3185
|
+
this.elements.selectAllTabs.checked = false;
|
|
3186
|
+
}
|
|
3187
|
+
|
|
3188
|
+
|
|
3189
|
+
} catch (error) {
|
|
3190
|
+
console.error('[UIManager] Failed to populate tab selector:', error);
|
|
3191
|
+
throw error;
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
createTabOption(tabId, tabInfo, isActive) {
|
|
3196
|
+
const option = document.createElement('div');
|
|
3197
|
+
option.className = `tab-option ${isActive ? 'active-tab' : ''}`;
|
|
3198
|
+
option.dataset.tabId = tabId;
|
|
3199
|
+
|
|
3200
|
+
// Format title (first 20 characters)
|
|
3201
|
+
const displayTitle = tabInfo.title ?
|
|
3202
|
+
(tabInfo.title.length > 20 ? tabInfo.title.substring(0, 20) + '...' : tabInfo.title) :
|
|
3203
|
+
'Unknown Title';
|
|
3204
|
+
|
|
3205
|
+
option.innerHTML = `
|
|
3206
|
+
<input type="radio" class="tab-radio" id="tab-${tabId}" name="tab-selection" value="${tabId}">
|
|
3207
|
+
<label for="tab-${tabId}" class="tab-label">
|
|
3208
|
+
<span class="tab-id">${tabId}:</span>
|
|
3209
|
+
<span class="tab-title">${this.escapeHtml(displayTitle)}</span>
|
|
3210
|
+
${isActive ? '<span class="active-indicator">(Active)</span>' : ''}
|
|
3211
|
+
</label>
|
|
3212
|
+
`;
|
|
3213
|
+
|
|
3214
|
+
// Add change event to radio button for auto-confirm
|
|
3215
|
+
const radio = option.querySelector('.tab-radio');
|
|
3216
|
+
radio?.addEventListener('change', this.handleTabSelection.bind(this));
|
|
3217
|
+
|
|
3218
|
+
return option;
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3221
|
+
handleTabSelection(event) {
|
|
3222
|
+
const tabId = event.target.value;
|
|
3223
|
+
|
|
3224
|
+
if (event.target.checked) {
|
|
3225
|
+
// For radio buttons, replace the selected tabs array with just this tab
|
|
3226
|
+
this.tabSelectorState.selectedTabs = [tabId];
|
|
3227
|
+
|
|
3228
|
+
|
|
3229
|
+
|
|
3230
|
+
// Auto-confirm selection immediately
|
|
3231
|
+
this.confirmTabSelection();
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
handleSelectAllTabs(event) {
|
|
3236
|
+
if (event.target.checked) {
|
|
3237
|
+
// "Select All" means list all tabs in the input
|
|
3238
|
+
const allTabIds = Object.keys(this.tabSelectorState.allTabs);
|
|
3239
|
+
this.tabSelectorState.selectedTabs = allTabIds;
|
|
3240
|
+
|
|
3241
|
+
|
|
3242
|
+
|
|
3243
|
+
// Auto-confirm selection immediately
|
|
3244
|
+
this.confirmTabSelection();
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
|
|
3248
|
+
updateSelectAllState() {
|
|
3249
|
+
if (!this.elements.selectAllTabs || !this.elements.tabOptionsList) return;
|
|
3250
|
+
|
|
3251
|
+
const checkboxes = this.elements.tabOptionsList.querySelectorAll('.tab-checkbox');
|
|
3252
|
+
const checkedBoxes = this.elements.tabOptionsList.querySelectorAll('.tab-checkbox:checked');
|
|
3253
|
+
|
|
3254
|
+
if (checkboxes.length === 0) {
|
|
3255
|
+
this.elements.selectAllTabs.indeterminate = false;
|
|
3256
|
+
this.elements.selectAllTabs.checked = false;
|
|
3257
|
+
} else if (checkedBoxes.length === checkboxes.length) {
|
|
3258
|
+
this.elements.selectAllTabs.indeterminate = false;
|
|
3259
|
+
this.elements.selectAllTabs.checked = true;
|
|
3260
|
+
} else if (checkedBoxes.length > 0) {
|
|
3261
|
+
this.elements.selectAllTabs.indeterminate = true;
|
|
3262
|
+
this.elements.selectAllTabs.checked = false;
|
|
3263
|
+
} else {
|
|
3264
|
+
this.elements.selectAllTabs.indeterminate = false;
|
|
3265
|
+
this.elements.selectAllTabs.checked = false;
|
|
3266
|
+
}
|
|
3267
|
+
}
|
|
3268
|
+
|
|
3269
|
+
confirmTabSelection() {
|
|
3270
|
+
if (this.tabSelectorState.selectedTabs.length === 0) {
|
|
3271
|
+
this.showNotification('Please select at least one tab', 'warning');
|
|
3272
|
+
return;
|
|
3273
|
+
}
|
|
3274
|
+
|
|
3275
|
+
// Replace @ with selected tabs information
|
|
3276
|
+
this.insertSelectedTabsIntoInput();
|
|
3277
|
+
|
|
3278
|
+
// Hide the selector
|
|
3279
|
+
this.hideTabSelector();
|
|
3280
|
+
|
|
3281
|
+
console.log(`[UIManager] ${this.tabSelectorState.selectedTabs.length} tab(s) selected and confirmed`);
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
insertSelectedTabsIntoInput() {
|
|
3285
|
+
if (!this.elements.taskInput) return;
|
|
3286
|
+
|
|
3287
|
+
const input = this.elements.taskInput;
|
|
3288
|
+
const currentValue = input.value;
|
|
3289
|
+
const atPosition = this.tabSelectorState.atPosition;
|
|
3290
|
+
|
|
3291
|
+
// Use special Unicode characters as boundaries for easy deletion
|
|
3292
|
+
const TAB_START_MARKER = '\u200B'; // Zero-width space
|
|
3293
|
+
const TAB_END_MARKER = '\u200C'; // Zero-width non-joiner
|
|
3294
|
+
|
|
3295
|
+
// Create tab information string in new format: @ tab_id: title[:20]
|
|
3296
|
+
const selectedTabsInfo = this.tabSelectorState.selectedTabs.map(tabId => {
|
|
3297
|
+
const tabInfo = this.tabSelectorState.allTabs[tabId];
|
|
3298
|
+
const displayTitle = tabInfo?.title ?
|
|
3299
|
+
(tabInfo.title.length > 20 ? tabInfo.title.substring(0, 20) + '...' : tabInfo.title) :
|
|
3300
|
+
'Unknown';
|
|
3301
|
+
return `${TAB_START_MARKER}@ ${tabId}: ${displayTitle}${TAB_END_MARKER}`;
|
|
3302
|
+
}).join(' ');
|
|
3303
|
+
|
|
3304
|
+
// Replace @ with tab selection (preserve the @ symbol)
|
|
3305
|
+
const beforeAt = currentValue.substring(0, atPosition);
|
|
3306
|
+
const afterAt = currentValue.substring(atPosition + 1);
|
|
3307
|
+
const newValue = `${beforeAt}${selectedTabsInfo} ${afterAt}`;
|
|
3308
|
+
|
|
3309
|
+
input.value = newValue;
|
|
3310
|
+
|
|
3311
|
+
// Trigger input change event for validation
|
|
3312
|
+
this.handleTaskInputChange({ target: input });
|
|
3313
|
+
|
|
3314
|
+
// Set cursor position after the inserted text
|
|
3315
|
+
const newCursorPosition = beforeAt.length + selectedTabsInfo.length + 1; // Add space
|
|
3316
|
+
input.setSelectionRange(newCursorPosition, newCursorPosition);
|
|
3317
|
+
input.focus();
|
|
3318
|
+
}
|
|
3319
|
+
|
|
3320
|
+
getSelectedTabsForTask() {
|
|
3321
|
+
// Return selected tabs information for task submission
|
|
3322
|
+
if (this.tabSelectorState.selectedTabs.length === 0) {
|
|
3323
|
+
return null;
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
const selectedTabsData = {};
|
|
3327
|
+
this.tabSelectorState.selectedTabs.forEach(tabId => {
|
|
3328
|
+
const tabInfo = this.tabSelectorState.allTabs[tabId];
|
|
3329
|
+
if (tabInfo) {
|
|
3330
|
+
selectedTabsData[tabId] = {
|
|
3331
|
+
url: tabInfo.url,
|
|
3332
|
+
title: tabInfo.title
|
|
3333
|
+
};
|
|
3334
|
+
}
|
|
3335
|
+
});
|
|
3336
|
+
|
|
3337
|
+
return selectedTabsData;
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
// Skill Selector Methods
|
|
3341
|
+
initializeSkillSelector() {
|
|
3342
|
+
// Initialize skill selector state
|
|
3343
|
+
this.skillSelectorState = {
|
|
3344
|
+
isVisible: false,
|
|
3345
|
+
selectedSkills: [],
|
|
3346
|
+
allSkills: [],
|
|
3347
|
+
slashPosition: -1, // Position where / was typed
|
|
3348
|
+
currentFilter: '', // Current filter text after /
|
|
3349
|
+
filteredSkills: [] // Filtered skills based on current input
|
|
3350
|
+
};
|
|
3351
|
+
|
|
3352
|
+
// Bind skill selector events
|
|
3353
|
+
this.bindSkillSelectorEvents();
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
bindSkillSelectorEvents() {
|
|
3357
|
+
// Hide on click outside
|
|
3358
|
+
document.addEventListener('click', (event) => {
|
|
3359
|
+
if (this.skillSelectorState.isVisible &&
|
|
3360
|
+
this.elements.skillSelectorDropdown &&
|
|
3361
|
+
!this.elements.skillSelectorDropdown.contains(event.target) &&
|
|
3362
|
+
!this.elements.taskInput?.contains(event.target)) {
|
|
3363
|
+
this.hideSkillSelector();
|
|
3364
|
+
}
|
|
3365
|
+
});
|
|
3366
|
+
}
|
|
3367
|
+
|
|
3368
|
+
handleSkillSelectorInput(event) {
|
|
3369
|
+
// Safety check - ensure skill selector state is initialized
|
|
3370
|
+
if (!this.skillSelectorState) {
|
|
3371
|
+
console.warn('[UIManager] Skill selector state not initialized');
|
|
3372
|
+
return;
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
const inputValue = event.target.value;
|
|
3376
|
+
const cursorPosition = event.target.selectionStart;
|
|
3377
|
+
|
|
3378
|
+
// Check if / was just typed
|
|
3379
|
+
if (inputValue[cursorPosition - 1] === '/') {
|
|
3380
|
+
this.skillSelectorState.slashPosition = cursorPosition - 1;
|
|
3381
|
+
this.skillSelectorState.currentFilter = '';
|
|
3382
|
+
this.showSkillSelector();
|
|
3383
|
+
} else if (this.skillSelectorState.isVisible) {
|
|
3384
|
+
// Check if / was deleted - hide skill selector immediately
|
|
3385
|
+
if (this.skillSelectorState.slashPosition >= 0 &&
|
|
3386
|
+
(this.skillSelectorState.slashPosition >= inputValue.length ||
|
|
3387
|
+
inputValue[this.skillSelectorState.slashPosition] !== '/')) {
|
|
3388
|
+
this.hideSkillSelector();
|
|
3389
|
+
return;
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
// Update filter based on text after /
|
|
3393
|
+
const textAfterSlash = inputValue.substring(this.skillSelectorState.slashPosition + 1, cursorPosition);
|
|
3394
|
+
|
|
3395
|
+
// Only consider text up to the next space or special character
|
|
3396
|
+
const filterText = textAfterSlash.split(/[\s@]/)[0];
|
|
3397
|
+
|
|
3398
|
+
if (this.skillSelectorState.currentFilter !== filterText) {
|
|
3399
|
+
this.skillSelectorState.currentFilter = filterText;
|
|
3400
|
+
this.filterSkills();
|
|
3401
|
+
}
|
|
3402
|
+
|
|
3403
|
+
// Hide skill selector if user typed a space or moved past the skill context
|
|
3404
|
+
if (textAfterSlash.includes(' ') || textAfterSlash.includes('@')) {
|
|
3405
|
+
this.hideSkillSelector();
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3410
|
+
async showSkillSelector() {
|
|
3411
|
+
if (!this.elements.skillSelectorDropdown || !this.elements.taskInput) {
|
|
3412
|
+
console.error('[UIManager] Skill selector elements not found', {
|
|
3413
|
+
dropdown: this.elements.skillSelectorDropdown,
|
|
3414
|
+
taskInput: this.elements.taskInput
|
|
3415
|
+
});
|
|
3416
|
+
return;
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
try {
|
|
3420
|
+
// Fetch skill data from backend if not already cached
|
|
3421
|
+
if (this.skillSelectorState.allSkills.length === 0) {
|
|
3422
|
+
await this.populateSkillSelector();
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3425
|
+
// Filter skills based on current input
|
|
3426
|
+
this.filterSkills();
|
|
3427
|
+
|
|
3428
|
+
// Position the dropdown relative to the input
|
|
3429
|
+
this.positionSkillSelector();
|
|
3430
|
+
|
|
3431
|
+
// Show the dropdown with explicit visibility
|
|
3432
|
+
this.elements.skillSelectorDropdown.classList.remove('hidden');
|
|
3433
|
+
this.elements.skillSelectorDropdown.style.display = 'block';
|
|
3434
|
+
this.elements.skillSelectorDropdown.style.visibility = 'visible';
|
|
3435
|
+
this.elements.skillSelectorDropdown.style.opacity = '1';
|
|
3436
|
+
this.skillSelectorState.isVisible = true;
|
|
3437
|
+
|
|
3438
|
+
} catch (error) {
|
|
3439
|
+
console.error('[UIManager] Failed to show skill selector:', error);
|
|
3440
|
+
this.showNotification('Failed to load skills', 'error');
|
|
3441
|
+
}
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
hideSkillSelector() {
|
|
3445
|
+
if (this.elements.skillSelectorDropdown) {
|
|
3446
|
+
this.elements.skillSelectorDropdown.classList.add('hidden');
|
|
3447
|
+
this.elements.skillSelectorDropdown.style.display = 'none';
|
|
3448
|
+
}
|
|
3449
|
+
this.skillSelectorState.isVisible = false;
|
|
3450
|
+
this.skillSelectorState.slashPosition = -1;
|
|
3451
|
+
this.skillSelectorState.currentFilter = '';
|
|
3452
|
+
this.skillSelectorState.filteredSkills = [];
|
|
3453
|
+
}
|
|
3454
|
+
|
|
3455
|
+
positionSkillSelector() {
|
|
3456
|
+
if (!this.elements.skillSelectorDropdown || !this.elements.taskInput) return;
|
|
3457
|
+
|
|
3458
|
+
const inputRect = this.elements.taskInput.getBoundingClientRect();
|
|
3459
|
+
const dropdown = this.elements.skillSelectorDropdown;
|
|
3460
|
+
|
|
3461
|
+
// Calculate 90% width of input
|
|
3462
|
+
const dropdownWidth = inputRect.width * 0.9;
|
|
3463
|
+
|
|
3464
|
+
// Position dropdown ABOVE the input (not below)
|
|
3465
|
+
dropdown.style.position = 'fixed';
|
|
3466
|
+
dropdown.style.bottom = `${window.innerHeight - inputRect.top + 5}px`; // Above the input
|
|
3467
|
+
dropdown.style.left = `${inputRect.left + (inputRect.width - dropdownWidth) / 2}px`; // Centered
|
|
3468
|
+
dropdown.style.width = `${dropdownWidth}px`; // 90% of input width
|
|
3469
|
+
dropdown.style.zIndex = '9999';
|
|
3470
|
+
dropdown.style.maxHeight = '300px';
|
|
3471
|
+
dropdown.style.overflowY = 'auto';
|
|
3472
|
+
}
|
|
3473
|
+
|
|
3474
|
+
async populateSkillSelector() {
|
|
3475
|
+
try {
|
|
3476
|
+
console.log('[UIManager] Fetching skills from backend...');
|
|
3477
|
+
// Get all skills from backend
|
|
3478
|
+
const skills = await this.apiClient.getAllSkills();
|
|
3479
|
+
|
|
3480
|
+
console.log('[UIManager] Skills received from backend:', skills);
|
|
3481
|
+
|
|
3482
|
+
if (!skills || !Array.isArray(skills) || skills.length === 0) {
|
|
3483
|
+
console.warn('[UIManager] No skills returned from backend');
|
|
3484
|
+
this.skillSelectorState.allSkills = [];
|
|
3485
|
+
return;
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
this.skillSelectorState.allSkills = skills.map(skillName => ({
|
|
3489
|
+
name: skillName,
|
|
3490
|
+
displayName: skillName // Keep original skill name without transformation
|
|
3491
|
+
}));
|
|
3492
|
+
console.log('[UIManager] Processed skills:', this.skillSelectorState.allSkills);
|
|
3493
|
+
|
|
3494
|
+
} catch (error) {
|
|
3495
|
+
console.error('[UIManager] Failed to populate skill selector:', error);
|
|
3496
|
+
console.error('[UIManager] Error details:', {
|
|
3497
|
+
message: error.message,
|
|
3498
|
+
stack: error.stack,
|
|
3499
|
+
response: error.response,
|
|
3500
|
+
data: error.data
|
|
3501
|
+
});
|
|
3502
|
+
|
|
3503
|
+
// Show error to user
|
|
3504
|
+
this.showNotification(`Failed to load skills: ${error.message}`, 'error');
|
|
3505
|
+
|
|
3506
|
+
// Set empty array instead of fallback test data
|
|
3507
|
+
this.skillSelectorState.allSkills = [];
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
|
|
3511
|
+
filterSkills() {
|
|
3512
|
+
const filter = this.skillSelectorState.currentFilter.toLowerCase();
|
|
3513
|
+
|
|
3514
|
+
if (!filter) {
|
|
3515
|
+
this.skillSelectorState.filteredSkills = this.skillSelectorState.allSkills;
|
|
3516
|
+
} else {
|
|
3517
|
+
this.skillSelectorState.filteredSkills = this.skillSelectorState.allSkills.filter(skill =>
|
|
3518
|
+
skill.name.toLowerCase().startsWith(filter) ||
|
|
3519
|
+
skill.displayName.toLowerCase().startsWith(filter)
|
|
3520
|
+
);
|
|
3521
|
+
}
|
|
3522
|
+
|
|
3523
|
+
this.renderSkillOptions();
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3526
|
+
renderSkillOptions() {
|
|
3527
|
+
if (!this.elements.skillOptionsList) return;
|
|
3528
|
+
|
|
3529
|
+
// Clear existing options
|
|
3530
|
+
this.elements.skillOptionsList.innerHTML = '';
|
|
3531
|
+
|
|
3532
|
+
if (this.skillSelectorState.filteredSkills.length === 0) {
|
|
3533
|
+
const noResults = document.createElement('div');
|
|
3534
|
+
noResults.className = 'skill-option';
|
|
3535
|
+
noResults.innerHTML = '<span class="skill-name">No skills found</span>';
|
|
3536
|
+
noResults.style.opacity = '0.6';
|
|
3537
|
+
noResults.style.cursor = 'not-allowed';
|
|
3538
|
+
this.elements.skillOptionsList.appendChild(noResults);
|
|
3539
|
+
return;
|
|
3540
|
+
}
|
|
3541
|
+
|
|
3542
|
+
// Add skill options
|
|
3543
|
+
this.skillSelectorState.filteredSkills.forEach((skill, index) => {
|
|
3544
|
+
const option = this.createSkillOption(skill, index);
|
|
3545
|
+
this.elements.skillOptionsList.appendChild(option);
|
|
3546
|
+
});
|
|
3547
|
+
}
|
|
3548
|
+
|
|
3549
|
+
createSkillOption(skill, index) {
|
|
3550
|
+
const option = document.createElement('div');
|
|
3551
|
+
option.className = 'skill-option';
|
|
3552
|
+
option.dataset.skillName = skill.name;
|
|
3553
|
+
option.dataset.skillIndex = index;
|
|
3554
|
+
|
|
3555
|
+
option.innerHTML = `
|
|
3556
|
+
<span class="skill-name">${this.escapeHtml(skill.displayName)}</span>
|
|
3557
|
+
`;
|
|
3558
|
+
|
|
3559
|
+
// Add click event for skill selection
|
|
3560
|
+
option.addEventListener('click', () => {
|
|
3561
|
+
this.selectSkill(skill);
|
|
3562
|
+
});
|
|
3563
|
+
|
|
3564
|
+
return option;
|
|
3565
|
+
}
|
|
3566
|
+
|
|
3567
|
+
selectSkill(skill) {
|
|
3568
|
+
if (!this.elements.taskInput) return;
|
|
3569
|
+
|
|
3570
|
+
const input = this.elements.taskInput;
|
|
3571
|
+
const currentValue = input.value;
|
|
3572
|
+
const slashPosition = this.skillSelectorState.slashPosition;
|
|
3573
|
+
|
|
3574
|
+
// Use special Unicode characters as boundaries for easy deletion
|
|
3575
|
+
const SKILL_START_MARKER = '\u200D'; // Zero-width joiner
|
|
3576
|
+
const SKILL_END_MARKER = '\u200E'; // Left-to-right mark
|
|
3577
|
+
|
|
3578
|
+
// Create skill information string
|
|
3579
|
+
const skillInfo = `${SKILL_START_MARKER}/${skill.name}${SKILL_END_MARKER}`;
|
|
3580
|
+
|
|
3581
|
+
// Replace / with skill selection
|
|
3582
|
+
const beforeSlash = currentValue.substring(0, slashPosition);
|
|
3583
|
+
const afterSlash = currentValue.substring(slashPosition + 1 + this.skillSelectorState.currentFilter.length);
|
|
3584
|
+
const newValue = `${beforeSlash}${skillInfo} ${afterSlash}`;
|
|
3585
|
+
|
|
3586
|
+
input.value = newValue;
|
|
3587
|
+
|
|
3588
|
+
// Trigger input change event for validation
|
|
3589
|
+
this.handleTaskInputChange({ target: input });
|
|
3590
|
+
|
|
3591
|
+
// Set cursor position after the inserted text
|
|
3592
|
+
const newCursorPosition = beforeSlash.length + skillInfo.length + 1;
|
|
3593
|
+
input.setSelectionRange(newCursorPosition, newCursorPosition);
|
|
3594
|
+
input.focus();
|
|
3595
|
+
|
|
3596
|
+
// Hide the selector
|
|
3597
|
+
this.hideSkillSelector();
|
|
3598
|
+
}
|
|
3599
|
+
|
|
3600
|
+
getSelectedSkillsForTask() {
|
|
3601
|
+
if (!this.elements.taskInput) return null;
|
|
3602
|
+
|
|
3603
|
+
const inputValue = this.elements.taskInput.value;
|
|
3604
|
+
const SKILL_START_MARKER = '\u200D'; // Zero-width joiner
|
|
3605
|
+
const SKILL_END_MARKER = '\u200E'; // Left-to-right mark
|
|
3606
|
+
|
|
3607
|
+
const skills = [];
|
|
3608
|
+
let startIndex = 0;
|
|
3609
|
+
|
|
3610
|
+
while ((startIndex = inputValue.indexOf(SKILL_START_MARKER, startIndex)) !== -1) {
|
|
3611
|
+
const endIndex = inputValue.indexOf(SKILL_END_MARKER, startIndex);
|
|
3612
|
+
if (endIndex !== -1) {
|
|
3613
|
+
const skillText = inputValue.substring(startIndex + 1, endIndex);
|
|
3614
|
+
if (skillText.startsWith('/')) {
|
|
3615
|
+
skills.push(skillText.substring(1)); // Remove the / prefix
|
|
3616
|
+
}
|
|
3617
|
+
startIndex = endIndex + 1;
|
|
3618
|
+
} else {
|
|
3619
|
+
break;
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
|
|
3623
|
+
return skills.length > 0 ? skills : null;
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
// Initialize social links from config
|
|
3627
|
+
initializeSocialLinks() {
|
|
3628
|
+
const socialLinksContainer = document.getElementById('social-links-container');
|
|
3629
|
+
if (!socialLinksContainer) {
|
|
3630
|
+
console.warn('[UIManager] Social links container not found');
|
|
3631
|
+
return;
|
|
3632
|
+
}
|
|
3633
|
+
|
|
3634
|
+
console.log('[UIManager] Initializing social links...');
|
|
3635
|
+
|
|
3636
|
+
// Get social links from config with fallback
|
|
3637
|
+
let socialLinks = window.VIBESURF_CONFIG?.SOCIAL_LINKS;
|
|
3638
|
+
|
|
3639
|
+
if (!socialLinks) {
|
|
3640
|
+
console.warn('[UIManager] Social links not found in config, using default fallback');
|
|
3641
|
+
socialLinks = {
|
|
3642
|
+
github: "https://github.com/vibesurf-ai/VibeSurf",
|
|
3643
|
+
discord: "https://discord.gg/86SPfhRVbk",
|
|
3644
|
+
x: "https://x.com/warmshao",
|
|
3645
|
+
reportBug: "https://github.com/vibesurf-ai/VibeSurf/issues/new/choose",
|
|
3646
|
+
website: "https://vibe-surf.com/"
|
|
3647
|
+
};
|
|
3648
|
+
} else {
|
|
3649
|
+
console.log('[UIManager] Found social links config:', socialLinks);
|
|
3650
|
+
}
|
|
3651
|
+
|
|
3652
|
+
// Clear existing content
|
|
3653
|
+
socialLinksContainer.innerHTML = '';
|
|
3654
|
+
|
|
3655
|
+
// Handle website link separately by making VibeSurf logo/text clickable
|
|
3656
|
+
const websiteUrl = socialLinks.website;
|
|
3657
|
+
if (websiteUrl) {
|
|
3658
|
+
this.initializeVibeSurfWebsiteLink(websiteUrl);
|
|
3659
|
+
}
|
|
3660
|
+
|
|
3661
|
+
// Create social link elements (excluding website)
|
|
3662
|
+
Object.entries(socialLinks).forEach(([platform, url]) => {
|
|
3663
|
+
if (platform !== 'website') {
|
|
3664
|
+
const link = this.createSocialLink(platform, url);
|
|
3665
|
+
if (link) {
|
|
3666
|
+
socialLinksContainer.appendChild(link);
|
|
3667
|
+
console.log(`[UIManager] Added social link for ${platform}`);
|
|
3668
|
+
}
|
|
3669
|
+
}
|
|
3670
|
+
});
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
// Make VibeSurf text clickable to link to website
|
|
3674
|
+
initializeVibeSurfWebsiteLink(websiteUrl) {
|
|
3675
|
+
// Only find elements that contain "VibeSurf" text specifically
|
|
3676
|
+
const allElements = document.querySelectorAll('*');
|
|
3677
|
+
const vibeSurfTextElements = [];
|
|
3678
|
+
|
|
3679
|
+
allElements.forEach(element => {
|
|
3680
|
+
// Only target elements that contain "VibeSurf" text and are likely text elements
|
|
3681
|
+
if (element.textContent &&
|
|
3682
|
+
element.textContent.trim() === 'VibeSurf' &&
|
|
3683
|
+
element.children.length === 0) { // Only leaf text nodes, not containers
|
|
3684
|
+
vibeSurfTextElements.push(element);
|
|
3685
|
+
}
|
|
3686
|
+
});
|
|
3687
|
+
|
|
3688
|
+
// Make only VibeSurf text elements clickable
|
|
3689
|
+
vibeSurfTextElements.forEach(element => {
|
|
3690
|
+
if (element && !element.querySelector('a')) { // Don't double-wrap already linked elements
|
|
3691
|
+
element.style.cursor = 'pointer';
|
|
3692
|
+
element.style.transition = 'opacity 0.2s ease';
|
|
3693
|
+
element.setAttribute('title', 'Login to early access alpha features');
|
|
3694
|
+
|
|
3695
|
+
// Add hover effect
|
|
3696
|
+
element.addEventListener('mouseenter', () => {
|
|
3697
|
+
element.style.opacity = '0.8';
|
|
3698
|
+
});
|
|
3699
|
+
|
|
3700
|
+
element.addEventListener('mouseleave', () => {
|
|
3701
|
+
element.style.opacity = '1';
|
|
3702
|
+
});
|
|
3703
|
+
|
|
3704
|
+
// Add click handler
|
|
3705
|
+
element.addEventListener('click', (e) => {
|
|
3706
|
+
e.preventDefault();
|
|
3707
|
+
e.stopPropagation();
|
|
3708
|
+
this.openWebsiteLink(websiteUrl);
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
});
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
// Open website link in new tab
|
|
3715
|
+
async openWebsiteLink(url) {
|
|
3716
|
+
try {
|
|
3717
|
+
console.log('[UIManager] Opening VibeSurf website:', url);
|
|
3718
|
+
|
|
3719
|
+
const result = await chrome.runtime.sendMessage({
|
|
3720
|
+
type: 'OPEN_FILE_URL',
|
|
3721
|
+
data: { fileUrl: url }
|
|
3722
|
+
});
|
|
3723
|
+
|
|
3724
|
+
if (!result || !result.success) {
|
|
3725
|
+
throw new Error(result?.error || 'Failed to open website');
|
|
3726
|
+
}
|
|
3727
|
+
|
|
3728
|
+
console.log('[UIManager] Successfully opened website tab:', result.tabId);
|
|
3729
|
+
} catch (error) {
|
|
3730
|
+
console.error('[UIManager] Error opening website:', error);
|
|
3731
|
+
this.showNotification(`Failed to open website: ${error.message}`, 'error');
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
|
|
3735
|
+
// Create individual social link element
|
|
3736
|
+
createSocialLink(platform, url) {
|
|
3737
|
+
const link = document.createElement('a');
|
|
3738
|
+
link.href = url;
|
|
3739
|
+
link.className = 'social-link';
|
|
3740
|
+
link.setAttribute('data-platform', platform);
|
|
3741
|
+
link.setAttribute('target', '_blank');
|
|
3742
|
+
link.setAttribute('rel', 'noopener noreferrer');
|
|
3743
|
+
|
|
3744
|
+
// Set title and tooltip based on platform
|
|
3745
|
+
let title = '';
|
|
3746
|
+
let svg = '';
|
|
3747
|
+
|
|
3748
|
+
switch (platform.toLowerCase()) {
|
|
3749
|
+
case 'github':
|
|
3750
|
+
title = 'GitHub';
|
|
3751
|
+
svg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3752
|
+
<path d="M12 0C5.374 0 0 5.373 0 12c0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z" fill="currentColor"/>
|
|
3753
|
+
</svg>`;
|
|
3754
|
+
break;
|
|
3755
|
+
|
|
3756
|
+
case 'discord':
|
|
3757
|
+
title = 'Discord';
|
|
3758
|
+
svg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3759
|
+
<path d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128 10.2 10.2 0 00.372-.292.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z" fill="currentColor"/>
|
|
3760
|
+
</svg>`;
|
|
3761
|
+
break;
|
|
3762
|
+
|
|
3763
|
+
case 'x':
|
|
3764
|
+
case 'twitter':
|
|
3765
|
+
title = 'X (Twitter)';
|
|
3766
|
+
svg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3767
|
+
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z" fill="currentColor"/>
|
|
3768
|
+
</svg>`;
|
|
3769
|
+
break;
|
|
3770
|
+
|
|
3771
|
+
|
|
3772
|
+
case 'reportbug':
|
|
3773
|
+
title = 'Report Bug';
|
|
3774
|
+
svg = `<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3775
|
+
<path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.42.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z" fill="currentColor"/>
|
|
3776
|
+
</svg>`;
|
|
3777
|
+
break;
|
|
3778
|
+
|
|
3779
|
+
default:
|
|
3780
|
+
console.warn(`[UIManager] Unknown social platform: ${platform}`);
|
|
3781
|
+
return null;
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3784
|
+
link.setAttribute('title', title);
|
|
3785
|
+
link.innerHTML = svg;
|
|
3786
|
+
|
|
3787
|
+
return link;
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
// Export for use in other modules
|
|
3791
|
+
static exportToWindow() {
|
|
3792
|
+
if (typeof window !== 'undefined') {
|
|
3793
|
+
window.VibeSurfUIManager = VibeSurfUIManager;
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
|
|
3798
|
+
// Call the export method
|
|
3799
|
+
VibeSurfUIManager.exportToWindow();
|