@elizaos/app-core 2.0.0-alpha.52 → 2.0.0-alpha.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1108) hide show
  1. package/{dist/actions → actions}/character.d.ts +2 -2
  2. package/{dist/actions → actions}/character.d.ts.map +1 -1
  3. package/{dist/actions → actions}/cloud.d.ts +2 -2
  4. package/{dist/actions → actions}/cloud.d.ts.map +1 -1
  5. package/{dist/actions → actions}/lifecycle.d.ts +3 -3
  6. package/{dist/actions → actions}/lifecycle.d.ts.map +1 -1
  7. package/{dist/actions → actions}/lifecycle.js +1 -1
  8. package/{dist/actions → actions}/triggers.d.ts +2 -2
  9. package/{dist/actions → actions}/triggers.d.ts.map +1 -1
  10. package/{dist/api → api}/client.d.ts +5 -5
  11. package/{dist/api → api}/client.d.ts.map +1 -1
  12. package/{dist/api → api}/client.js +20 -20
  13. package/{dist/bridge → bridge}/capacitor-bridge.d.ts +10 -10
  14. package/{dist/bridge → bridge}/capacitor-bridge.d.ts.map +1 -1
  15. package/{dist/bridge → bridge}/capacitor-bridge.js +7 -7
  16. package/{dist/bridge → bridge}/electrobun-rpc.js +1 -1
  17. package/{dist/bridge → bridge}/plugin-bridge.d.ts +4 -4
  18. package/{dist/bridge → bridge}/plugin-bridge.d.ts.map +1 -1
  19. package/{dist/bridge → bridge}/plugin-bridge.js +1 -1
  20. package/{dist/bridge → bridge}/storage-bridge.js +3 -3
  21. package/{dist/chat → chat}/index.d.ts +1 -1
  22. package/{dist/chat → chat}/index.d.ts.map +1 -1
  23. package/{dist/chat → chat}/index.js +1 -1
  24. package/{dist/components → components}/BugReportModal.js +1 -1
  25. package/{dist/components → components}/CommandPalette.js +1 -1
  26. package/{dist/components → components}/CompanionSceneHost.js +1 -1
  27. package/{dist/components → components}/ElizaCloudDashboard.js +2 -2
  28. package/{dist/components → components}/EmotePicker.js +2 -2
  29. package/{dist/components → components}/GlobalEmoteOverlay.js +4 -4
  30. package/{dist/components → components}/PairingView.js +1 -1
  31. package/{dist/components → components}/ProviderSwitcher.js +16 -16
  32. package/{dist/components → components}/SecretsView.js +1 -1
  33. package/{dist/components → components}/StartupFailureView.js +1 -1
  34. package/{dist/components → components}/StreamView.js +4 -4
  35. package/{dist/components → components}/StripeEmbeddedCheckout.js +2 -2
  36. package/{dist/components → components}/SubscriptionStatus.js +1 -1
  37. package/{dist/components → components}/VoiceConfigView.js +1 -1
  38. package/{dist/components → components}/avatar/VrmEngine.js +1 -1
  39. package/{dist/components → components}/avatar/VrmViewer.d.ts +1 -1
  40. package/{dist/components → components}/avatar/VrmViewer.d.ts.map +1 -1
  41. package/{dist/components → components}/avatar/VrmViewer.js +3 -3
  42. package/{dist/components → components}/companion/walletUtils.d.ts +1 -1
  43. package/{dist/components → components}/companion/walletUtils.d.ts.map +1 -1
  44. package/{dist/components → components}/companion/walletUtils.js +1 -1
  45. package/{dist/components → components}/format.d.ts +1 -1
  46. package/{dist/components → components}/format.js +1 -1
  47. package/{dist/components → components}/permissions/StreamingPermissions.js +1 -1
  48. package/{dist/components → components}/stream/StatusBar.js +2 -2
  49. package/{dist/components → components}/stream/overlays/useOverlayLayout.d.ts +1 -1
  50. package/{dist/components → components}/stream/overlays/useOverlayLayout.js +2 -2
  51. package/events/index.d.ts +42 -0
  52. package/events/index.d.ts.map +1 -0
  53. package/{dist/events → events}/index.js +16 -16
  54. package/{dist/hooks → hooks}/useRetakeCapture.js +1 -1
  55. package/{src/i18n → i18n}/locales/en.json +9 -9
  56. package/{src/i18n → i18n}/locales/es.json +10 -10
  57. package/{src/i18n → i18n}/locales/ko.json +9 -9
  58. package/{src/i18n → i18n}/locales/pt.json +9 -9
  59. package/{src/i18n → i18n}/locales/zh-CN.json +10 -10
  60. package/{dist/navigation → navigation}/index.js +1 -1
  61. package/package.json +142 -52
  62. package/{dist/platform → platform}/browser-launch.js +1 -1
  63. package/{dist/platform → platform}/init.d.ts +1 -1
  64. package/{dist/platform → platform}/init.d.ts.map +1 -1
  65. package/{dist/platform → platform}/init.js +5 -5
  66. package/{dist/platform → platform}/lifo.d.ts +1 -1
  67. package/{dist/platform → platform}/lifo.d.ts.map +1 -1
  68. package/{dist/platform → platform}/lifo.js +1 -1
  69. package/{dist/state → state}/AppContext.js +14 -14
  70. package/{dist/state → state}/onboarding-resume.js +1 -1
  71. package/{dist/state → state}/persistence.js +11 -11
  72. package/{dist/state → state}/vrm.d.ts +1 -1
  73. package/{dist/state → state}/vrm.d.ts.map +1 -1
  74. package/{dist/state → state}/vrm.js +6 -6
  75. package/{dist/utils → utils}/asset-url.d.ts +1 -1
  76. package/{dist/utils → utils}/asset-url.js +2 -2
  77. package/.turbo/turbo-build.log +0 -12
  78. package/LICENSE +0 -21
  79. package/dist/events/index.d.ts +0 -42
  80. package/dist/events/index.d.ts.map +0 -1
  81. package/dist/i18n/locales/en.json +0 -1195
  82. package/dist/i18n/locales/es.json +0 -1195
  83. package/dist/i18n/locales/ko.json +0 -1195
  84. package/dist/i18n/locales/pt.json +0 -1195
  85. package/dist/i18n/locales/zh-CN.json +0 -1195
  86. package/src/App.tsx +0 -498
  87. package/src/actions/character.test.ts +0 -139
  88. package/src/actions/character.ts +0 -152
  89. package/src/actions/chat-helpers.ts +0 -100
  90. package/src/actions/cloud.ts +0 -59
  91. package/src/actions/index.ts +0 -12
  92. package/src/actions/lifecycle.ts +0 -175
  93. package/src/actions/onboarding.ts +0 -42
  94. package/src/actions/triggers.ts +0 -190
  95. package/src/ambient.d.ts +0 -16
  96. package/src/api/client.ts +0 -5339
  97. package/src/api/index.ts +0 -1
  98. package/src/autonomy/index.ts +0 -477
  99. package/src/bridge/capacitor-bridge.ts +0 -295
  100. package/src/bridge/electrobun-rpc.ts +0 -58
  101. package/src/bridge/electrobun-runtime.ts +0 -28
  102. package/src/bridge/index.ts +0 -5
  103. package/src/bridge/native-plugins.ts +0 -134
  104. package/src/bridge/plugin-bridge.ts +0 -352
  105. package/src/bridge/storage-bridge.ts +0 -162
  106. package/src/chat/index.ts +0 -250
  107. package/src/coding/index.ts +0 -43
  108. package/src/components/AdvancedPageView.tsx +0 -362
  109. package/src/components/AgentActivityBox.tsx +0 -49
  110. package/src/components/ApiKeyConfig.tsx +0 -224
  111. package/src/components/AppsPageView.tsx +0 -52
  112. package/src/components/AppsView.tsx +0 -293
  113. package/src/components/AvatarLoader.tsx +0 -92
  114. package/src/components/AvatarSelector.tsx +0 -223
  115. package/src/components/BscTradePanel.tsx +0 -549
  116. package/src/components/BugReportModal.tsx +0 -499
  117. package/src/components/CharacterView.tsx +0 -1814
  118. package/src/components/ChatAvatar.test.ts +0 -97
  119. package/src/components/ChatAvatar.tsx +0 -147
  120. package/src/components/ChatComposer.tsx +0 -330
  121. package/src/components/ChatMessage.tsx +0 -448
  122. package/src/components/ChatModalView.test.tsx +0 -118
  123. package/src/components/ChatModalView.tsx +0 -125
  124. package/src/components/ChatView.tsx +0 -992
  125. package/src/components/CloudSourceControls.tsx +0 -80
  126. package/src/components/CodingAgentSettingsSection.tsx +0 -538
  127. package/src/components/CommandPalette.tsx +0 -284
  128. package/src/components/CompanionSceneHost.tsx +0 -497
  129. package/src/components/CompanionShell.tsx +0 -31
  130. package/src/components/CompanionView.tsx +0 -109
  131. package/src/components/ConfigPageView.tsx +0 -762
  132. package/src/components/ConfigSaveFooter.tsx +0 -41
  133. package/src/components/ConfirmModal.tsx +0 -379
  134. package/src/components/ConnectionFailedBanner.tsx +0 -91
  135. package/src/components/ConnectorsPageView.tsx +0 -13
  136. package/src/components/ConversationsSidebar.tsx +0 -279
  137. package/src/components/CustomActionEditor.tsx +0 -1127
  138. package/src/components/CustomActionsPanel.tsx +0 -288
  139. package/src/components/CustomActionsView.tsx +0 -322
  140. package/src/components/DatabasePageView.tsx +0 -55
  141. package/src/components/DatabaseView.tsx +0 -814
  142. package/src/components/ElizaCloudDashboard.tsx +0 -1696
  143. package/src/components/EmotePicker.tsx +0 -529
  144. package/src/components/ErrorBoundary.tsx +0 -76
  145. package/src/components/FineTuningView.tsx +0 -1080
  146. package/src/components/GameView.tsx +0 -551
  147. package/src/components/GameViewOverlay.tsx +0 -133
  148. package/src/components/GlobalEmoteOverlay.tsx +0 -152
  149. package/src/components/Header.test.tsx +0 -413
  150. package/src/components/Header.tsx +0 -403
  151. package/src/components/HeartbeatsView.tsx +0 -1003
  152. package/src/components/InventoryView.tsx +0 -388
  153. package/src/components/KnowledgeView.tsx +0 -1128
  154. package/src/components/LanguageDropdown.tsx +0 -188
  155. package/src/components/LifoMonitorPanel.tsx +0 -196
  156. package/src/components/LifoSandboxView.tsx +0 -499
  157. package/src/components/LoadingScreen.tsx +0 -112
  158. package/src/components/LogsPageView.tsx +0 -17
  159. package/src/components/LogsView.tsx +0 -239
  160. package/src/components/MediaGalleryView.tsx +0 -433
  161. package/src/components/MediaSettingsSection.tsx +0 -893
  162. package/src/components/MessageContent.tsx +0 -815
  163. package/src/components/OnboardingWizard.test.tsx +0 -104
  164. package/src/components/OnboardingWizard.tsx +0 -206
  165. package/src/components/PairingView.tsx +0 -110
  166. package/src/components/PermissionsSection.tsx +0 -1186
  167. package/src/components/PluginsPageView.tsx +0 -9
  168. package/src/components/PluginsView.tsx +0 -3165
  169. package/src/components/ProviderSwitcher.tsx +0 -905
  170. package/src/components/RestartBanner.tsx +0 -76
  171. package/src/components/RuntimeView.tsx +0 -460
  172. package/src/components/SaveCommandModal.tsx +0 -211
  173. package/src/components/SecretsView.tsx +0 -569
  174. package/src/components/SettingsView.tsx +0 -825
  175. package/src/components/ShellOverlays.tsx +0 -41
  176. package/src/components/ShortcutsOverlay.tsx +0 -155
  177. package/src/components/SkillsView.tsx +0 -1435
  178. package/src/components/StartupFailureView.tsx +0 -63
  179. package/src/components/StreamView.tsx +0 -483
  180. package/src/components/StripeEmbeddedCheckout.tsx +0 -155
  181. package/src/components/SubscriptionStatus.tsx +0 -640
  182. package/src/components/SystemWarningBanner.tsx +0 -71
  183. package/src/components/ThemeToggle.tsx +0 -100
  184. package/src/components/TrajectoriesView.tsx +0 -526
  185. package/src/components/TrajectoryDetailView.tsx +0 -426
  186. package/src/components/TriggersView.tsx +0 -1
  187. package/src/components/VectorBrowserView.tsx +0 -1633
  188. package/src/components/VoiceConfigView.tsx +0 -674
  189. package/src/components/VrmStage.test.ts +0 -219
  190. package/src/components/VrmStage.tsx +0 -432
  191. package/src/components/WhatsAppQrOverlay.tsx +0 -230
  192. package/src/components/__tests__/chainConfig.test.ts +0 -220
  193. package/src/components/apps/AppDetailPane.tsx +0 -242
  194. package/src/components/apps/AppsCatalogGrid.tsx +0 -137
  195. package/src/components/apps/extensions/registry.ts +0 -13
  196. package/src/components/apps/extensions/types.ts +0 -9
  197. package/src/components/apps/helpers.ts +0 -43
  198. package/src/components/avatar/VrmAnimationLoader.test.ts +0 -164
  199. package/src/components/avatar/VrmAnimationLoader.ts +0 -151
  200. package/src/components/avatar/VrmBlinkController.ts +0 -118
  201. package/src/components/avatar/VrmCameraManager.ts +0 -407
  202. package/src/components/avatar/VrmEngine.ts +0 -2696
  203. package/src/components/avatar/VrmFootShadow.ts +0 -96
  204. package/src/components/avatar/VrmViewer.tsx +0 -421
  205. package/src/components/avatar/__tests__/VrmCameraManager.test.ts +0 -168
  206. package/src/components/avatar/__tests__/VrmEngine.test.ts +0 -1574
  207. package/src/components/avatar/mixamoVRMRigMap.ts +0 -62
  208. package/src/components/avatar/retargetMixamoFbxToVrm.ts +0 -144
  209. package/src/components/avatar/retargetMixamoGltfToVrm.ts +0 -119
  210. package/src/components/chainConfig.ts +0 -380
  211. package/src/components/companion/CompanionHeader.tsx +0 -47
  212. package/src/components/companion/CompanionSceneHost.tsx +0 -5
  213. package/src/components/companion/VrmStage.tsx +0 -2
  214. package/src/components/companion/__tests__/walletUtils.test.ts +0 -742
  215. package/src/components/companion/walletUtils.ts +0 -290
  216. package/src/components/companion-shell-styles.test.ts +0 -142
  217. package/src/components/companion-shell-styles.ts +0 -270
  218. package/src/components/confirm-delete-control.tsx +0 -69
  219. package/src/components/conversations/ConversationListItem.tsx +0 -185
  220. package/src/components/conversations/conversation-utils.ts +0 -151
  221. package/src/components/format.ts +0 -131
  222. package/src/components/index.ts +0 -94
  223. package/src/components/inventory/CopyableAddress.tsx +0 -41
  224. package/src/components/inventory/InventoryToolbar.tsx +0 -142
  225. package/src/components/inventory/NftGrid.tsx +0 -99
  226. package/src/components/inventory/TokenLogo.tsx +0 -71
  227. package/src/components/inventory/TokensTable.tsx +0 -216
  228. package/src/components/inventory/constants.ts +0 -170
  229. package/src/components/inventory/index.ts +0 -29
  230. package/src/components/inventory/media-url.test.ts +0 -38
  231. package/src/components/inventory/media-url.ts +0 -36
  232. package/src/components/inventory/useInventoryData.ts +0 -460
  233. package/src/components/knowledge-upload-image.ts +0 -215
  234. package/src/components/labels.ts +0 -46
  235. package/src/components/onboarding/ActivateStep.tsx +0 -30
  236. package/src/components/onboarding/ConnectionStep.tsx +0 -1530
  237. package/src/components/onboarding/IdentityStep.tsx +0 -272
  238. package/src/components/onboarding/OnboardingPanel.tsx +0 -39
  239. package/src/components/onboarding/OnboardingStepNav.tsx +0 -31
  240. package/src/components/onboarding/PermissionsStep.tsx +0 -20
  241. package/src/components/onboarding/RpcStep.tsx +0 -402
  242. package/src/components/permissions/PermissionIcon.tsx +0 -25
  243. package/src/components/permissions/StreamingPermissions.tsx +0 -413
  244. package/src/components/plugins/showcase-data.ts +0 -481
  245. package/src/components/shared/ShellHeaderControls.tsx +0 -193
  246. package/src/components/shared-companion-scene-context.ts +0 -15
  247. package/src/components/skeletons.tsx +0 -88
  248. package/src/components/stream/ActivityFeed.tsx +0 -113
  249. package/src/components/stream/AvatarPip.tsx +0 -10
  250. package/src/components/stream/ChatContent.tsx +0 -126
  251. package/src/components/stream/ChatTicker.tsx +0 -55
  252. package/src/components/stream/IdleContent.tsx +0 -73
  253. package/src/components/stream/StatusBar.tsx +0 -469
  254. package/src/components/stream/StreamSettings.tsx +0 -506
  255. package/src/components/stream/StreamTerminal.tsx +0 -94
  256. package/src/components/stream/StreamVoiceConfig.tsx +0 -160
  257. package/src/components/stream/helpers.ts +0 -134
  258. package/src/components/stream/overlays/OverlayLayer.tsx +0 -75
  259. package/src/components/stream/overlays/built-in/ActionTickerWidget.tsx +0 -64
  260. package/src/components/stream/overlays/built-in/AlertPopupWidget.tsx +0 -87
  261. package/src/components/stream/overlays/built-in/BrandingWidget.tsx +0 -51
  262. package/src/components/stream/overlays/built-in/CustomHtmlWidget.tsx +0 -105
  263. package/src/components/stream/overlays/built-in/PeonGlassWidget.tsx +0 -265
  264. package/src/components/stream/overlays/built-in/PeonHudWidget.tsx +0 -247
  265. package/src/components/stream/overlays/built-in/PeonSakuraWidget.tsx +0 -278
  266. package/src/components/stream/overlays/built-in/ThoughtBubbleWidget.tsx +0 -77
  267. package/src/components/stream/overlays/built-in/ViewerCountWidget.tsx +0 -46
  268. package/src/components/stream/overlays/built-in/index.ts +0 -13
  269. package/src/components/stream/overlays/registry.ts +0 -22
  270. package/src/components/stream/overlays/types.ts +0 -90
  271. package/src/components/stream/overlays/useOverlayLayout.ts +0 -218
  272. package/src/components/trajectory-format.ts +0 -50
  273. package/src/components/ui-badges.tsx +0 -109
  274. package/src/components/ui-switch.tsx +0 -57
  275. package/src/components/vector-browser-three.ts +0 -27
  276. package/src/config/config-catalog.ts +0 -1092
  277. package/src/config/config-field.tsx +0 -1924
  278. package/src/config/config-renderer.tsx +0 -734
  279. package/src/config/index.ts +0 -11
  280. package/src/config/ui-renderer.tsx +0 -1751
  281. package/src/config/ui-spec.ts +0 -256
  282. package/src/events/index.ts +0 -89
  283. package/src/hooks/index.ts +0 -13
  284. package/src/hooks/useBugReport.tsx +0 -43
  285. package/src/hooks/useCanvasWindow.ts +0 -372
  286. package/src/hooks/useChatAvatarVoice.ts +0 -111
  287. package/src/hooks/useContextMenu.ts +0 -127
  288. package/src/hooks/useKeyboardShortcuts.ts +0 -86
  289. package/src/hooks/useLifoSync.ts +0 -143
  290. package/src/hooks/useMemoryMonitor.ts +0 -334
  291. package/src/hooks/useRenderGuard.ts +0 -43
  292. package/src/hooks/useRetakeCapture.ts +0 -67
  293. package/src/hooks/useStreamPopoutNavigation.ts +0 -27
  294. package/src/hooks/useTimeout.ts +0 -37
  295. package/src/hooks/useVoiceChat.ts +0 -1440
  296. package/src/hooks/useWhatsAppPairing.ts +0 -123
  297. package/src/i18n/index.ts +0 -76
  298. package/src/i18n/messages.ts +0 -21
  299. package/src/index.ts +0 -6
  300. package/src/navigation/index.ts +0 -282
  301. package/src/navigation.test.ts +0 -189
  302. package/src/onboarding-config.test.ts +0 -104
  303. package/src/onboarding-config.ts +0 -114
  304. package/src/platform/browser-launch.test.ts +0 -94
  305. package/src/platform/browser-launch.ts +0 -149
  306. package/src/platform/index.ts +0 -58
  307. package/src/platform/init.ts +0 -236
  308. package/src/platform/lifo.ts +0 -225
  309. package/src/providers/index.ts +0 -99
  310. package/src/state/AppContext.tsx +0 -5869
  311. package/src/state/index.ts +0 -6
  312. package/src/state/internal.ts +0 -86
  313. package/src/state/onboarding-resume.test.ts +0 -135
  314. package/src/state/onboarding-resume.ts +0 -263
  315. package/src/state/parsers.test.ts +0 -124
  316. package/src/state/parsers.ts +0 -309
  317. package/src/state/persistence.ts +0 -320
  318. package/src/state/shell-routing.ts +0 -32
  319. package/src/state/types.ts +0 -696
  320. package/src/state/ui-preferences.ts +0 -3
  321. package/src/state/useApp.ts +0 -23
  322. package/src/state/vrm.ts +0 -76
  323. package/src/stories/AppMockProvider.tsx +0 -32
  324. package/src/stories/ChatEmptyState.stories.tsx +0 -27
  325. package/src/stories/ChatMessage.stories.tsx +0 -115
  326. package/src/stories/CompanionHeader.stories.tsx +0 -74
  327. package/src/stories/CompanionView.stories.tsx +0 -33
  328. package/src/stories/ConversationListItem.stories.tsx +0 -102
  329. package/src/stories/TypingIndicator.stories.tsx +0 -28
  330. package/src/types/index.ts +0 -715
  331. package/src/types/react-test-renderer.d.ts +0 -45
  332. package/src/utils/asset-url.ts +0 -110
  333. package/src/utils/assistant-text.ts +0 -172
  334. package/src/utils/clipboard.ts +0 -41
  335. package/src/utils/desktop-dialogs.ts +0 -80
  336. package/src/utils/index.ts +0 -6
  337. package/src/utils/number-parsing.ts +0 -125
  338. package/src/utils/openExternalUrl.ts +0 -20
  339. package/src/utils/spoken-text.ts +0 -65
  340. package/src/utils/streaming-text.ts +0 -120
  341. package/src/voice/index.ts +0 -1
  342. package/src/voice/types.ts +0 -197
  343. package/src/wallet-rpc.ts +0 -176
  344. package/test/app/AppContext.pty-sessions.test.tsx +0 -143
  345. package/test/app/MessageContent.test.tsx +0 -366
  346. package/test/app/PermissionsOnboarding.test.tsx +0 -356
  347. package/test/app/PermissionsSection.test.tsx +0 -573
  348. package/test/app/advanced-trajectory-fine-tuning.e2e.test.ts +0 -397
  349. package/test/app/agent-activity-box.test.tsx +0 -132
  350. package/test/app/agent-transfer-lock.test.ts +0 -274
  351. package/test/app/api-client-electron-fallback.test.ts +0 -139
  352. package/test/app/api-client-timeout.test.ts +0 -75
  353. package/test/app/api-client-ws.test.ts +0 -98
  354. package/test/app/api-client.ws-max-reconnect.test.ts +0 -139
  355. package/test/app/api-client.ws-reconnect.test.ts +0 -157
  356. package/test/app/app-context-autonomy-events.test.ts +0 -478
  357. package/test/app/apps-page-view.test.ts +0 -114
  358. package/test/app/apps-view.test.ts +0 -591
  359. package/test/app/autonomous-workflows.e2e.test.ts +0 -765
  360. package/test/app/autonomy-events.test.ts +0 -150
  361. package/test/app/avatar-selector.test.tsx +0 -52
  362. package/test/app/bsc-trade-panel.test.tsx +0 -134
  363. package/test/app/bug-report-modal.test.tsx +0 -353
  364. package/test/app/character-customization.e2e.test.ts +0 -1199
  365. package/test/app/chat-advanced-features.e2e.test.ts +0 -706
  366. package/test/app/chat-composer.test.tsx +0 -181
  367. package/test/app/chat-language-header.test.ts +0 -64
  368. package/test/app/chat-message.test.tsx +0 -222
  369. package/test/app/chat-modal-view.test.tsx +0 -191
  370. package/test/app/chat-routine-filter.test.ts +0 -96
  371. package/test/app/chat-send-lock.test.ts +0 -1465
  372. package/test/app/chat-stream-api-client.test.tsx +0 -390
  373. package/test/app/chat-view-game-modal.test.tsx +0 -661
  374. package/test/app/chat-view.test.tsx +0 -877
  375. package/test/app/cloud-api.e2e.test.ts +0 -258
  376. package/test/app/cloud-login-flow.e2e.test.ts +0 -494
  377. package/test/app/cloud-login-lock.test.ts +0 -412
  378. package/test/app/command-palette.test.tsx +0 -184
  379. package/test/app/command-registry.test.ts +0 -75
  380. package/test/app/companion-greeting-wave.test.tsx +0 -431
  381. package/test/app/companion-stale-conversation.test.tsx +0 -447
  382. package/test/app/companion-view.test.tsx +0 -690
  383. package/test/app/confirm-delete-control.test.ts +0 -79
  384. package/test/app/confirm-modal.test.tsx +0 -219
  385. package/test/app/connectors-ui.e2e.test.ts +0 -508
  386. package/test/app/conversations-sidebar-game-modal.test.tsx +0 -265
  387. package/test/app/conversations-sidebar.test.tsx +0 -185
  388. package/test/app/custom-actions-smoke.test.ts +0 -387
  389. package/test/app/custom-avatar-api-client.test.ts +0 -207
  390. package/test/app/desktop-utils.test.ts +0 -145
  391. package/test/app/electrobun-rpc-bridge.test.ts +0 -83
  392. package/test/app/events.test.ts +0 -88
  393. package/test/app/export-import-flows.e2e.test.ts +0 -700
  394. package/test/app/fine-tuning-view.test.ts +0 -471
  395. package/test/app/game-view-auth-session.test.tsx +0 -187
  396. package/test/app/game-view.test.ts +0 -444
  397. package/test/app/global-emote-overlay.test.tsx +0 -106
  398. package/test/app/header-status.test.tsx +0 -149
  399. package/test/app/i18n.test.ts +0 -152
  400. package/test/app/inventory-bsc-view.test.ts +0 -940
  401. package/test/app/knowledge-ui.e2e.test.ts +0 -762
  402. package/test/app/knowledge-upload-helpers.test.ts +0 -124
  403. package/test/app/lifecycle-lock.test.ts +0 -267
  404. package/test/app/lifo-popout-utils.test.ts +0 -208
  405. package/test/app/lifo-safe-endpoint.test.ts +0 -34
  406. package/test/app/loading-screen.test.tsx +0 -45
  407. package/test/app/memory-monitor.test.ts +0 -332
  408. package/test/app/navigation.test.tsx +0 -22
  409. package/test/app/onboarding-finish-lock.test.ts +0 -673
  410. package/test/app/onboarding-language.test.tsx +0 -160
  411. package/test/app/onboarding-steps.test.tsx +0 -375
  412. package/test/app/open-external-url.test.ts +0 -65
  413. package/test/app/pages-navigation-smoke.e2e.test.ts +0 -638
  414. package/test/app/pairing-lock.test.ts +0 -260
  415. package/test/app/pairing-view.test.tsx +0 -74
  416. package/test/app/permissions-section.test.ts +0 -432
  417. package/test/app/plugin-bridge.test.ts +0 -109
  418. package/test/app/plugins-ui.e2e.test.ts +0 -605
  419. package/test/app/plugins-view-game-modal.test.tsx +0 -687
  420. package/test/app/plugins-view-toggle-restart.test.ts +0 -129
  421. package/test/app/provider-dropdown-default.test.tsx +0 -300
  422. package/test/app/restart-banner.test.tsx +0 -197
  423. package/test/app/retake-capture.test.ts +0 -84
  424. package/test/app/sandbox-api-client.test.ts +0 -108
  425. package/test/app/save-command-modal.test.tsx +0 -109
  426. package/test/app/secrets-view.test.tsx +0 -92
  427. package/test/app/settings-control-styles.test.tsx +0 -142
  428. package/test/app/settings-reset.e2e.test.ts +0 -726
  429. package/test/app/settings-sections.e2e.test.ts +0 -614
  430. package/test/app/shared-format.test.ts +0 -44
  431. package/test/app/shared-switch.test.ts +0 -69
  432. package/test/app/shell-mode-switching.e2e.test.ts +0 -840
  433. package/test/app/shell-mode-tab-memory.test.tsx +0 -58
  434. package/test/app/shell-overlays.test.tsx +0 -50
  435. package/test/app/shortcuts-overlay.test.tsx +0 -111
  436. package/test/app/sse-interruption.test.ts +0 -122
  437. package/test/app/startup-asset-missing.e2e.test.ts +0 -126
  438. package/test/app/startup-backend-missing.e2e.test.ts +0 -118
  439. package/test/app/startup-chat.e2e.test.ts +0 -322
  440. package/test/app/startup-conversation-restore.test.tsx +0 -381
  441. package/test/app/startup-failure-view.test.tsx +0 -103
  442. package/test/app/startup-onboarding.e2e.test.ts +0 -618
  443. package/test/app/startup-timeout.test.tsx +0 -80
  444. package/test/app/startup-token-401.e2e.test.ts +0 -103
  445. package/test/app/stream-helpers.test.ts +0 -46
  446. package/test/app/stream-popout-navigation.test.tsx +0 -41
  447. package/test/app/stream-status-bar.test.tsx +0 -89
  448. package/test/app/theme-toggle.test.tsx +0 -33
  449. package/test/app/training-api-client.test.ts +0 -128
  450. package/test/app/trajectories-view.test.tsx +0 -220
  451. package/test/app/triggers-api-client.test.ts +0 -77
  452. package/test/app/triggers-navigation.test.ts +0 -113
  453. package/test/app/triggers-view.e2e.test.ts +0 -675
  454. package/test/app/update-channel-lock.test.ts +0 -259
  455. package/test/app/vector-browser.async-cleanup.test.tsx +0 -367
  456. package/test/app/vector-browser.e2e.test.ts +0 -653
  457. package/test/app/vrm-stage.test.tsx +0 -351
  458. package/test/app/vrm-viewer.test.tsx +0 -298
  459. package/test/app/wallet-api-save-lock.test.ts +0 -299
  460. package/test/app/wallet-hooks.test.ts +0 -405
  461. package/test/app/wallet-ui-flows.e2e.test.ts +0 -556
  462. package/test/avatar/asset-url.test.ts +0 -90
  463. package/test/avatar/avatar-selector.test.ts +0 -173
  464. package/test/avatar/mixamo-vrm-rig-map.test.ts +0 -111
  465. package/test/avatar/voice-chat-streaming-text.test.ts +0 -96
  466. package/test/avatar/voice-chat.test.ts +0 -391
  467. package/test/browser-extension/README.md +0 -138
  468. package/test/browser-extension/test-harness.ts +0 -499
  469. package/test/capacitor-plugins.e2e.test.ts +0 -168
  470. package/test/test-types.ts +0 -5
  471. package/test/ui/command-palette-commands.test.ts +0 -57
  472. package/test/ui/ui-renderer.test.ts +0 -39
  473. package/test/utils/assistant-text.test.ts +0 -68
  474. package/test/utils/streaming-text.test.ts +0 -89
  475. package/tsconfig.build.json +0 -19
  476. package/tsconfig.json +0 -20
  477. package/tsconfig.typecheck.json +0 -12
  478. /package/{dist/App.d.ts → App.d.ts} +0 -0
  479. /package/{dist/App.d.ts.map → App.d.ts.map} +0 -0
  480. /package/{dist/App.js → App.js} +0 -0
  481. /package/{dist/actions → actions}/character.js +0 -0
  482. /package/{dist/actions → actions}/chat-helpers.d.ts +0 -0
  483. /package/{dist/actions → actions}/chat-helpers.d.ts.map +0 -0
  484. /package/{dist/actions → actions}/chat-helpers.js +0 -0
  485. /package/{dist/actions → actions}/cloud.js +0 -0
  486. /package/{dist/actions → actions}/index.d.ts +0 -0
  487. /package/{dist/actions → actions}/index.d.ts.map +0 -0
  488. /package/{dist/actions → actions}/index.js +0 -0
  489. /package/{dist/actions → actions}/onboarding.d.ts +0 -0
  490. /package/{dist/actions → actions}/onboarding.d.ts.map +0 -0
  491. /package/{dist/actions → actions}/onboarding.js +0 -0
  492. /package/{dist/actions → actions}/triggers.js +0 -0
  493. /package/{dist/api → api}/index.d.ts +0 -0
  494. /package/{dist/api → api}/index.d.ts.map +0 -0
  495. /package/{dist/api → api}/index.js +0 -0
  496. /package/{dist/autonomy → autonomy}/index.d.ts +0 -0
  497. /package/{dist/autonomy → autonomy}/index.d.ts.map +0 -0
  498. /package/{dist/autonomy → autonomy}/index.js +0 -0
  499. /package/{dist/bridge → bridge}/electrobun-rpc.d.ts +0 -0
  500. /package/{dist/bridge → bridge}/electrobun-rpc.d.ts.map +0 -0
  501. /package/{dist/bridge → bridge}/electrobun-runtime.d.ts +0 -0
  502. /package/{dist/bridge → bridge}/electrobun-runtime.d.ts.map +0 -0
  503. /package/{dist/bridge → bridge}/electrobun-runtime.js +0 -0
  504. /package/{dist/bridge → bridge}/index.d.ts +0 -0
  505. /package/{dist/bridge → bridge}/index.d.ts.map +0 -0
  506. /package/{dist/bridge → bridge}/index.js +0 -0
  507. /package/{dist/bridge → bridge}/native-plugins.d.ts +0 -0
  508. /package/{dist/bridge → bridge}/native-plugins.d.ts.map +0 -0
  509. /package/{dist/bridge → bridge}/native-plugins.js +0 -0
  510. /package/{dist/bridge → bridge}/storage-bridge.d.ts +0 -0
  511. /package/{dist/bridge → bridge}/storage-bridge.d.ts.map +0 -0
  512. /package/{dist/coding → coding}/index.d.ts +0 -0
  513. /package/{dist/coding → coding}/index.d.ts.map +0 -0
  514. /package/{dist/coding → coding}/index.js +0 -0
  515. /package/{dist/components → components}/AdvancedPageView.d.ts +0 -0
  516. /package/{dist/components → components}/AdvancedPageView.d.ts.map +0 -0
  517. /package/{dist/components → components}/AdvancedPageView.js +0 -0
  518. /package/{dist/components → components}/AgentActivityBox.d.ts +0 -0
  519. /package/{dist/components → components}/AgentActivityBox.d.ts.map +0 -0
  520. /package/{dist/components → components}/AgentActivityBox.js +0 -0
  521. /package/{dist/components → components}/ApiKeyConfig.d.ts +0 -0
  522. /package/{dist/components → components}/ApiKeyConfig.d.ts.map +0 -0
  523. /package/{dist/components → components}/ApiKeyConfig.js +0 -0
  524. /package/{dist/components → components}/AppsPageView.d.ts +0 -0
  525. /package/{dist/components → components}/AppsPageView.d.ts.map +0 -0
  526. /package/{dist/components → components}/AppsPageView.js +0 -0
  527. /package/{dist/components → components}/AppsView.d.ts +0 -0
  528. /package/{dist/components → components}/AppsView.d.ts.map +0 -0
  529. /package/{dist/components → components}/AppsView.js +0 -0
  530. /package/{dist/components → components}/AvatarLoader.d.ts +0 -0
  531. /package/{dist/components → components}/AvatarLoader.d.ts.map +0 -0
  532. /package/{dist/components → components}/AvatarLoader.js +0 -0
  533. /package/{dist/components → components}/AvatarSelector.d.ts +0 -0
  534. /package/{dist/components → components}/AvatarSelector.d.ts.map +0 -0
  535. /package/{dist/components → components}/AvatarSelector.js +0 -0
  536. /package/{dist/components → components}/BscTradePanel.d.ts +0 -0
  537. /package/{dist/components → components}/BscTradePanel.d.ts.map +0 -0
  538. /package/{dist/components → components}/BscTradePanel.js +0 -0
  539. /package/{dist/components → components}/BugReportModal.d.ts +0 -0
  540. /package/{dist/components → components}/BugReportModal.d.ts.map +0 -0
  541. /package/{dist/components → components}/CharacterView.d.ts +0 -0
  542. /package/{dist/components → components}/CharacterView.d.ts.map +0 -0
  543. /package/{dist/components → components}/CharacterView.js +0 -0
  544. /package/{dist/components → components}/ChatAvatar.d.ts +0 -0
  545. /package/{dist/components → components}/ChatAvatar.d.ts.map +0 -0
  546. /package/{dist/components → components}/ChatAvatar.js +0 -0
  547. /package/{dist/components → components}/ChatComposer.d.ts +0 -0
  548. /package/{dist/components → components}/ChatComposer.d.ts.map +0 -0
  549. /package/{dist/components → components}/ChatComposer.js +0 -0
  550. /package/{dist/components → components}/ChatMessage.d.ts +0 -0
  551. /package/{dist/components → components}/ChatMessage.d.ts.map +0 -0
  552. /package/{dist/components → components}/ChatMessage.js +0 -0
  553. /package/{dist/components → components}/ChatModalView.d.ts +0 -0
  554. /package/{dist/components → components}/ChatModalView.d.ts.map +0 -0
  555. /package/{dist/components → components}/ChatModalView.js +0 -0
  556. /package/{dist/components → components}/ChatView.d.ts +0 -0
  557. /package/{dist/components → components}/ChatView.d.ts.map +0 -0
  558. /package/{dist/components → components}/ChatView.js +0 -0
  559. /package/{dist/components → components}/CloudSourceControls.d.ts +0 -0
  560. /package/{dist/components → components}/CloudSourceControls.d.ts.map +0 -0
  561. /package/{dist/components → components}/CloudSourceControls.js +0 -0
  562. /package/{dist/components → components}/CodingAgentSettingsSection.d.ts +0 -0
  563. /package/{dist/components → components}/CodingAgentSettingsSection.d.ts.map +0 -0
  564. /package/{dist/components → components}/CodingAgentSettingsSection.js +0 -0
  565. /package/{dist/components → components}/CommandPalette.d.ts +0 -0
  566. /package/{dist/components → components}/CommandPalette.d.ts.map +0 -0
  567. /package/{dist/components → components}/CompanionSceneHost.d.ts +0 -0
  568. /package/{dist/components → components}/CompanionSceneHost.d.ts.map +0 -0
  569. /package/{dist/components → components}/CompanionShell.d.ts +0 -0
  570. /package/{dist/components → components}/CompanionShell.d.ts.map +0 -0
  571. /package/{dist/components → components}/CompanionShell.js +0 -0
  572. /package/{dist/components → components}/CompanionView.d.ts +0 -0
  573. /package/{dist/components → components}/CompanionView.d.ts.map +0 -0
  574. /package/{dist/components → components}/CompanionView.js +0 -0
  575. /package/{dist/components → components}/ConfigPageView.d.ts +0 -0
  576. /package/{dist/components → components}/ConfigPageView.d.ts.map +0 -0
  577. /package/{dist/components → components}/ConfigPageView.js +0 -0
  578. /package/{dist/components → components}/ConfigSaveFooter.d.ts +0 -0
  579. /package/{dist/components → components}/ConfigSaveFooter.d.ts.map +0 -0
  580. /package/{dist/components → components}/ConfigSaveFooter.js +0 -0
  581. /package/{dist/components → components}/ConfirmModal.d.ts +0 -0
  582. /package/{dist/components → components}/ConfirmModal.d.ts.map +0 -0
  583. /package/{dist/components → components}/ConfirmModal.js +0 -0
  584. /package/{dist/components → components}/ConnectionFailedBanner.d.ts +0 -0
  585. /package/{dist/components → components}/ConnectionFailedBanner.d.ts.map +0 -0
  586. /package/{dist/components → components}/ConnectionFailedBanner.js +0 -0
  587. /package/{dist/components → components}/ConnectorsPageView.d.ts +0 -0
  588. /package/{dist/components → components}/ConnectorsPageView.d.ts.map +0 -0
  589. /package/{dist/components → components}/ConnectorsPageView.js +0 -0
  590. /package/{dist/components → components}/ConversationsSidebar.d.ts +0 -0
  591. /package/{dist/components → components}/ConversationsSidebar.d.ts.map +0 -0
  592. /package/{dist/components → components}/ConversationsSidebar.js +0 -0
  593. /package/{dist/components → components}/CustomActionEditor.d.ts +0 -0
  594. /package/{dist/components → components}/CustomActionEditor.d.ts.map +0 -0
  595. /package/{dist/components → components}/CustomActionEditor.js +0 -0
  596. /package/{dist/components → components}/CustomActionsPanel.d.ts +0 -0
  597. /package/{dist/components → components}/CustomActionsPanel.d.ts.map +0 -0
  598. /package/{dist/components → components}/CustomActionsPanel.js +0 -0
  599. /package/{dist/components → components}/CustomActionsView.d.ts +0 -0
  600. /package/{dist/components → components}/CustomActionsView.d.ts.map +0 -0
  601. /package/{dist/components → components}/CustomActionsView.js +0 -0
  602. /package/{dist/components → components}/DatabasePageView.d.ts +0 -0
  603. /package/{dist/components → components}/DatabasePageView.d.ts.map +0 -0
  604. /package/{dist/components → components}/DatabasePageView.js +0 -0
  605. /package/{dist/components → components}/DatabaseView.d.ts +0 -0
  606. /package/{dist/components → components}/DatabaseView.d.ts.map +0 -0
  607. /package/{dist/components → components}/DatabaseView.js +0 -0
  608. /package/{dist/components → components}/ElizaCloudDashboard.d.ts +0 -0
  609. /package/{dist/components → components}/ElizaCloudDashboard.d.ts.map +0 -0
  610. /package/{dist/components → components}/EmotePicker.d.ts +0 -0
  611. /package/{dist/components → components}/EmotePicker.d.ts.map +0 -0
  612. /package/{dist/components → components}/ErrorBoundary.d.ts +0 -0
  613. /package/{dist/components → components}/ErrorBoundary.d.ts.map +0 -0
  614. /package/{dist/components → components}/ErrorBoundary.js +0 -0
  615. /package/{dist/components → components}/FineTuningView.d.ts +0 -0
  616. /package/{dist/components → components}/FineTuningView.d.ts.map +0 -0
  617. /package/{dist/components → components}/FineTuningView.js +0 -0
  618. /package/{dist/components → components}/GameView.d.ts +0 -0
  619. /package/{dist/components → components}/GameView.d.ts.map +0 -0
  620. /package/{dist/components → components}/GameView.js +0 -0
  621. /package/{dist/components → components}/GameViewOverlay.d.ts +0 -0
  622. /package/{dist/components → components}/GameViewOverlay.d.ts.map +0 -0
  623. /package/{dist/components → components}/GameViewOverlay.js +0 -0
  624. /package/{dist/components → components}/GlobalEmoteOverlay.d.ts +0 -0
  625. /package/{dist/components → components}/GlobalEmoteOverlay.d.ts.map +0 -0
  626. /package/{dist/components → components}/Header.d.ts +0 -0
  627. /package/{dist/components → components}/Header.d.ts.map +0 -0
  628. /package/{dist/components → components}/Header.js +0 -0
  629. /package/{dist/components → components}/HeartbeatsView.d.ts +0 -0
  630. /package/{dist/components → components}/HeartbeatsView.d.ts.map +0 -0
  631. /package/{dist/components → components}/HeartbeatsView.js +0 -0
  632. /package/{dist/components → components}/InventoryView.d.ts +0 -0
  633. /package/{dist/components → components}/InventoryView.d.ts.map +0 -0
  634. /package/{dist/components → components}/InventoryView.js +0 -0
  635. /package/{dist/components → components}/KnowledgeView.d.ts +0 -0
  636. /package/{dist/components → components}/KnowledgeView.d.ts.map +0 -0
  637. /package/{dist/components → components}/KnowledgeView.js +0 -0
  638. /package/{dist/components → components}/LanguageDropdown.d.ts +0 -0
  639. /package/{dist/components → components}/LanguageDropdown.d.ts.map +0 -0
  640. /package/{dist/components → components}/LanguageDropdown.js +0 -0
  641. /package/{dist/components → components}/LifoMonitorPanel.d.ts +0 -0
  642. /package/{dist/components → components}/LifoMonitorPanel.d.ts.map +0 -0
  643. /package/{dist/components → components}/LifoMonitorPanel.js +0 -0
  644. /package/{dist/components → components}/LifoSandboxView.d.ts +0 -0
  645. /package/{dist/components → components}/LifoSandboxView.d.ts.map +0 -0
  646. /package/{dist/components → components}/LifoSandboxView.js +0 -0
  647. /package/{dist/components → components}/LoadingScreen.d.ts +0 -0
  648. /package/{dist/components → components}/LoadingScreen.d.ts.map +0 -0
  649. /package/{dist/components → components}/LoadingScreen.js +0 -0
  650. /package/{dist/components → components}/LogsPageView.d.ts +0 -0
  651. /package/{dist/components → components}/LogsPageView.d.ts.map +0 -0
  652. /package/{dist/components → components}/LogsPageView.js +0 -0
  653. /package/{dist/components → components}/LogsView.d.ts +0 -0
  654. /package/{dist/components → components}/LogsView.d.ts.map +0 -0
  655. /package/{dist/components → components}/LogsView.js +0 -0
  656. /package/{dist/components → components}/MediaGalleryView.d.ts +0 -0
  657. /package/{dist/components → components}/MediaGalleryView.d.ts.map +0 -0
  658. /package/{dist/components → components}/MediaGalleryView.js +0 -0
  659. /package/{dist/components → components}/MediaSettingsSection.d.ts +0 -0
  660. /package/{dist/components → components}/MediaSettingsSection.d.ts.map +0 -0
  661. /package/{dist/components → components}/MediaSettingsSection.js +0 -0
  662. /package/{dist/components → components}/MessageContent.d.ts +0 -0
  663. /package/{dist/components → components}/MessageContent.d.ts.map +0 -0
  664. /package/{dist/components → components}/MessageContent.js +0 -0
  665. /package/{dist/components → components}/OnboardingWizard.d.ts +0 -0
  666. /package/{dist/components → components}/OnboardingWizard.d.ts.map +0 -0
  667. /package/{dist/components → components}/OnboardingWizard.js +0 -0
  668. /package/{dist/components → components}/PairingView.d.ts +0 -0
  669. /package/{dist/components → components}/PairingView.d.ts.map +0 -0
  670. /package/{dist/components → components}/PermissionsSection.d.ts +0 -0
  671. /package/{dist/components → components}/PermissionsSection.d.ts.map +0 -0
  672. /package/{dist/components → components}/PermissionsSection.js +0 -0
  673. /package/{dist/components → components}/PluginsPageView.d.ts +0 -0
  674. /package/{dist/components → components}/PluginsPageView.d.ts.map +0 -0
  675. /package/{dist/components → components}/PluginsPageView.js +0 -0
  676. /package/{dist/components → components}/PluginsView.d.ts +0 -0
  677. /package/{dist/components → components}/PluginsView.d.ts.map +0 -0
  678. /package/{dist/components → components}/PluginsView.js +0 -0
  679. /package/{dist/components → components}/ProviderSwitcher.d.ts +0 -0
  680. /package/{dist/components → components}/ProviderSwitcher.d.ts.map +0 -0
  681. /package/{dist/components → components}/RestartBanner.d.ts +0 -0
  682. /package/{dist/components → components}/RestartBanner.d.ts.map +0 -0
  683. /package/{dist/components → components}/RestartBanner.js +0 -0
  684. /package/{dist/components → components}/RuntimeView.d.ts +0 -0
  685. /package/{dist/components → components}/RuntimeView.d.ts.map +0 -0
  686. /package/{dist/components → components}/RuntimeView.js +0 -0
  687. /package/{dist/components → components}/SaveCommandModal.d.ts +0 -0
  688. /package/{dist/components → components}/SaveCommandModal.d.ts.map +0 -0
  689. /package/{dist/components → components}/SaveCommandModal.js +0 -0
  690. /package/{dist/components → components}/SecretsView.d.ts +0 -0
  691. /package/{dist/components → components}/SecretsView.d.ts.map +0 -0
  692. /package/{dist/components → components}/SettingsView.d.ts +0 -0
  693. /package/{dist/components → components}/SettingsView.d.ts.map +0 -0
  694. /package/{dist/components → components}/SettingsView.js +0 -0
  695. /package/{dist/components → components}/ShellOverlays.d.ts +0 -0
  696. /package/{dist/components → components}/ShellOverlays.d.ts.map +0 -0
  697. /package/{dist/components → components}/ShellOverlays.js +0 -0
  698. /package/{dist/components → components}/ShortcutsOverlay.d.ts +0 -0
  699. /package/{dist/components → components}/ShortcutsOverlay.d.ts.map +0 -0
  700. /package/{dist/components → components}/ShortcutsOverlay.js +0 -0
  701. /package/{dist/components → components}/SkillsView.d.ts +0 -0
  702. /package/{dist/components → components}/SkillsView.d.ts.map +0 -0
  703. /package/{dist/components → components}/SkillsView.js +0 -0
  704. /package/{dist/components → components}/StartupFailureView.d.ts +0 -0
  705. /package/{dist/components → components}/StartupFailureView.d.ts.map +0 -0
  706. /package/{dist/components → components}/StreamView.d.ts +0 -0
  707. /package/{dist/components → components}/StreamView.d.ts.map +0 -0
  708. /package/{dist/components → components}/StripeEmbeddedCheckout.d.ts +0 -0
  709. /package/{dist/components → components}/StripeEmbeddedCheckout.d.ts.map +0 -0
  710. /package/{dist/components → components}/SubscriptionStatus.d.ts +0 -0
  711. /package/{dist/components → components}/SubscriptionStatus.d.ts.map +0 -0
  712. /package/{dist/components → components}/SystemWarningBanner.d.ts +0 -0
  713. /package/{dist/components → components}/SystemWarningBanner.d.ts.map +0 -0
  714. /package/{dist/components → components}/SystemWarningBanner.js +0 -0
  715. /package/{dist/components → components}/ThemeToggle.d.ts +0 -0
  716. /package/{dist/components → components}/ThemeToggle.d.ts.map +0 -0
  717. /package/{dist/components → components}/ThemeToggle.js +0 -0
  718. /package/{dist/components → components}/TrajectoriesView.d.ts +0 -0
  719. /package/{dist/components → components}/TrajectoriesView.d.ts.map +0 -0
  720. /package/{dist/components → components}/TrajectoriesView.js +0 -0
  721. /package/{dist/components → components}/TrajectoryDetailView.d.ts +0 -0
  722. /package/{dist/components → components}/TrajectoryDetailView.d.ts.map +0 -0
  723. /package/{dist/components → components}/TrajectoryDetailView.js +0 -0
  724. /package/{dist/components → components}/TriggersView.d.ts +0 -0
  725. /package/{dist/components → components}/TriggersView.d.ts.map +0 -0
  726. /package/{dist/components → components}/TriggersView.js +0 -0
  727. /package/{dist/components → components}/VectorBrowserView.d.ts +0 -0
  728. /package/{dist/components → components}/VectorBrowserView.d.ts.map +0 -0
  729. /package/{dist/components → components}/VectorBrowserView.js +0 -0
  730. /package/{dist/components → components}/VoiceConfigView.d.ts +0 -0
  731. /package/{dist/components → components}/VoiceConfigView.d.ts.map +0 -0
  732. /package/{dist/components → components}/VrmStage.d.ts +0 -0
  733. /package/{dist/components → components}/VrmStage.d.ts.map +0 -0
  734. /package/{dist/components → components}/VrmStage.js +0 -0
  735. /package/{dist/components → components}/WhatsAppQrOverlay.d.ts +0 -0
  736. /package/{dist/components → components}/WhatsAppQrOverlay.d.ts.map +0 -0
  737. /package/{dist/components → components}/WhatsAppQrOverlay.js +0 -0
  738. /package/{dist/components → components}/apps/AppDetailPane.d.ts +0 -0
  739. /package/{dist/components → components}/apps/AppDetailPane.d.ts.map +0 -0
  740. /package/{dist/components → components}/apps/AppDetailPane.js +0 -0
  741. /package/{dist/components → components}/apps/AppsCatalogGrid.d.ts +0 -0
  742. /package/{dist/components → components}/apps/AppsCatalogGrid.d.ts.map +0 -0
  743. /package/{dist/components → components}/apps/AppsCatalogGrid.js +0 -0
  744. /package/{dist/components → components}/apps/extensions/registry.d.ts +0 -0
  745. /package/{dist/components → components}/apps/extensions/registry.d.ts.map +0 -0
  746. /package/{dist/components → components}/apps/extensions/registry.js +0 -0
  747. /package/{dist/components → components}/apps/extensions/types.d.ts +0 -0
  748. /package/{dist/components → components}/apps/extensions/types.d.ts.map +0 -0
  749. /package/{dist/components → components}/apps/extensions/types.js +0 -0
  750. /package/{dist/components → components}/apps/helpers.d.ts +0 -0
  751. /package/{dist/components → components}/apps/helpers.d.ts.map +0 -0
  752. /package/{dist/components → components}/apps/helpers.js +0 -0
  753. /package/{dist/components → components}/avatar/VrmAnimationLoader.d.ts +0 -0
  754. /package/{dist/components → components}/avatar/VrmAnimationLoader.d.ts.map +0 -0
  755. /package/{dist/components → components}/avatar/VrmAnimationLoader.js +0 -0
  756. /package/{dist/components → components}/avatar/VrmBlinkController.d.ts +0 -0
  757. /package/{dist/components → components}/avatar/VrmBlinkController.d.ts.map +0 -0
  758. /package/{dist/components → components}/avatar/VrmBlinkController.js +0 -0
  759. /package/{dist/components → components}/avatar/VrmCameraManager.d.ts +0 -0
  760. /package/{dist/components → components}/avatar/VrmCameraManager.d.ts.map +0 -0
  761. /package/{dist/components → components}/avatar/VrmCameraManager.js +0 -0
  762. /package/{dist/components → components}/avatar/VrmEngine.d.ts +0 -0
  763. /package/{dist/components → components}/avatar/VrmEngine.d.ts.map +0 -0
  764. /package/{dist/components → components}/avatar/VrmFootShadow.d.ts +0 -0
  765. /package/{dist/components → components}/avatar/VrmFootShadow.d.ts.map +0 -0
  766. /package/{dist/components → components}/avatar/VrmFootShadow.js +0 -0
  767. /package/{dist/components → components}/avatar/mixamoVRMRigMap.d.ts +0 -0
  768. /package/{dist/components → components}/avatar/mixamoVRMRigMap.d.ts.map +0 -0
  769. /package/{dist/components → components}/avatar/mixamoVRMRigMap.js +0 -0
  770. /package/{dist/components → components}/avatar/retargetMixamoFbxToVrm.d.ts +0 -0
  771. /package/{dist/components → components}/avatar/retargetMixamoFbxToVrm.d.ts.map +0 -0
  772. /package/{dist/components → components}/avatar/retargetMixamoFbxToVrm.js +0 -0
  773. /package/{dist/components → components}/avatar/retargetMixamoGltfToVrm.d.ts +0 -0
  774. /package/{dist/components → components}/avatar/retargetMixamoGltfToVrm.d.ts.map +0 -0
  775. /package/{dist/components → components}/avatar/retargetMixamoGltfToVrm.js +0 -0
  776. /package/{dist/components → components}/chainConfig.d.ts +0 -0
  777. /package/{dist/components → components}/chainConfig.d.ts.map +0 -0
  778. /package/{dist/components → components}/chainConfig.js +0 -0
  779. /package/{dist/components → components}/companion/CompanionHeader.d.ts +0 -0
  780. /package/{dist/components → components}/companion/CompanionHeader.d.ts.map +0 -0
  781. /package/{dist/components → components}/companion/CompanionHeader.js +0 -0
  782. /package/{dist/components → components}/companion/CompanionSceneHost.d.ts +0 -0
  783. /package/{dist/components → components}/companion/CompanionSceneHost.d.ts.map +0 -0
  784. /package/{dist/components → components}/companion/CompanionSceneHost.js +0 -0
  785. /package/{dist/components → components}/companion/VrmStage.d.ts +0 -0
  786. /package/{dist/components → components}/companion/VrmStage.d.ts.map +0 -0
  787. /package/{dist/components → components}/companion/VrmStage.js +0 -0
  788. /package/{dist/components → components}/companion-shell-styles.d.ts +0 -0
  789. /package/{dist/components → components}/companion-shell-styles.d.ts.map +0 -0
  790. /package/{dist/components → components}/companion-shell-styles.js +0 -0
  791. /package/{dist/components → components}/confirm-delete-control.d.ts +0 -0
  792. /package/{dist/components → components}/confirm-delete-control.d.ts.map +0 -0
  793. /package/{dist/components → components}/confirm-delete-control.js +0 -0
  794. /package/{dist/components → components}/conversations/ConversationListItem.d.ts +0 -0
  795. /package/{dist/components → components}/conversations/ConversationListItem.d.ts.map +0 -0
  796. /package/{dist/components → components}/conversations/ConversationListItem.js +0 -0
  797. /package/{dist/components → components}/conversations/conversation-utils.d.ts +0 -0
  798. /package/{dist/components → components}/conversations/conversation-utils.d.ts.map +0 -0
  799. /package/{dist/components → components}/conversations/conversation-utils.js +0 -0
  800. /package/{dist/components → components}/format.d.ts.map +0 -0
  801. /package/{dist/components → components}/index.d.ts +0 -0
  802. /package/{dist/components → components}/index.d.ts.map +0 -0
  803. /package/{dist/components → components}/index.js +0 -0
  804. /package/{dist/components → components}/inventory/CopyableAddress.d.ts +0 -0
  805. /package/{dist/components → components}/inventory/CopyableAddress.d.ts.map +0 -0
  806. /package/{dist/components → components}/inventory/CopyableAddress.js +0 -0
  807. /package/{dist/components → components}/inventory/InventoryToolbar.d.ts +0 -0
  808. /package/{dist/components → components}/inventory/InventoryToolbar.d.ts.map +0 -0
  809. /package/{dist/components → components}/inventory/InventoryToolbar.js +0 -0
  810. /package/{dist/components → components}/inventory/NftGrid.d.ts +0 -0
  811. /package/{dist/components → components}/inventory/NftGrid.d.ts.map +0 -0
  812. /package/{dist/components → components}/inventory/NftGrid.js +0 -0
  813. /package/{dist/components → components}/inventory/TokenLogo.d.ts +0 -0
  814. /package/{dist/components → components}/inventory/TokenLogo.d.ts.map +0 -0
  815. /package/{dist/components → components}/inventory/TokenLogo.js +0 -0
  816. /package/{dist/components → components}/inventory/TokensTable.d.ts +0 -0
  817. /package/{dist/components → components}/inventory/TokensTable.d.ts.map +0 -0
  818. /package/{dist/components → components}/inventory/TokensTable.js +0 -0
  819. /package/{dist/components → components}/inventory/constants.d.ts +0 -0
  820. /package/{dist/components → components}/inventory/constants.d.ts.map +0 -0
  821. /package/{dist/components → components}/inventory/constants.js +0 -0
  822. /package/{dist/components → components}/inventory/index.d.ts +0 -0
  823. /package/{dist/components → components}/inventory/index.d.ts.map +0 -0
  824. /package/{dist/components → components}/inventory/index.js +0 -0
  825. /package/{dist/components → components}/inventory/media-url.d.ts +0 -0
  826. /package/{dist/components → components}/inventory/media-url.d.ts.map +0 -0
  827. /package/{dist/components → components}/inventory/media-url.js +0 -0
  828. /package/{dist/components → components}/inventory/useInventoryData.d.ts +0 -0
  829. /package/{dist/components → components}/inventory/useInventoryData.d.ts.map +0 -0
  830. /package/{dist/components → components}/inventory/useInventoryData.js +0 -0
  831. /package/{dist/components → components}/knowledge-upload-image.d.ts +0 -0
  832. /package/{dist/components → components}/knowledge-upload-image.d.ts.map +0 -0
  833. /package/{dist/components → components}/knowledge-upload-image.js +0 -0
  834. /package/{dist/components → components}/labels.d.ts +0 -0
  835. /package/{dist/components → components}/labels.d.ts.map +0 -0
  836. /package/{dist/components → components}/labels.js +0 -0
  837. /package/{dist/components → components}/onboarding/ActivateStep.d.ts +0 -0
  838. /package/{dist/components → components}/onboarding/ActivateStep.d.ts.map +0 -0
  839. /package/{dist/components → components}/onboarding/ActivateStep.js +0 -0
  840. /package/{dist/components → components}/onboarding/ConnectionStep.d.ts +0 -0
  841. /package/{dist/components → components}/onboarding/ConnectionStep.d.ts.map +0 -0
  842. /package/{dist/components → components}/onboarding/ConnectionStep.js +0 -0
  843. /package/{dist/components → components}/onboarding/IdentityStep.d.ts +0 -0
  844. /package/{dist/components → components}/onboarding/IdentityStep.d.ts.map +0 -0
  845. /package/{dist/components → components}/onboarding/IdentityStep.js +0 -0
  846. /package/{dist/components → components}/onboarding/OnboardingPanel.d.ts +0 -0
  847. /package/{dist/components → components}/onboarding/OnboardingPanel.d.ts.map +0 -0
  848. /package/{dist/components → components}/onboarding/OnboardingPanel.js +0 -0
  849. /package/{dist/components → components}/onboarding/OnboardingStepNav.d.ts +0 -0
  850. /package/{dist/components → components}/onboarding/OnboardingStepNav.d.ts.map +0 -0
  851. /package/{dist/components → components}/onboarding/OnboardingStepNav.js +0 -0
  852. /package/{dist/components → components}/onboarding/PermissionsStep.d.ts +0 -0
  853. /package/{dist/components → components}/onboarding/PermissionsStep.d.ts.map +0 -0
  854. /package/{dist/components → components}/onboarding/PermissionsStep.js +0 -0
  855. /package/{dist/components → components}/onboarding/RpcStep.d.ts +0 -0
  856. /package/{dist/components → components}/onboarding/RpcStep.d.ts.map +0 -0
  857. /package/{dist/components → components}/onboarding/RpcStep.js +0 -0
  858. /package/{dist/components → components}/permissions/PermissionIcon.d.ts +0 -0
  859. /package/{dist/components → components}/permissions/PermissionIcon.d.ts.map +0 -0
  860. /package/{dist/components → components}/permissions/PermissionIcon.js +0 -0
  861. /package/{dist/components → components}/permissions/StreamingPermissions.d.ts +0 -0
  862. /package/{dist/components → components}/permissions/StreamingPermissions.d.ts.map +0 -0
  863. /package/{dist/components → components}/plugins/showcase-data.d.ts +0 -0
  864. /package/{dist/components → components}/plugins/showcase-data.d.ts.map +0 -0
  865. /package/{dist/components → components}/plugins/showcase-data.js +0 -0
  866. /package/{dist/components → components}/shared/ShellHeaderControls.d.ts +0 -0
  867. /package/{dist/components → components}/shared/ShellHeaderControls.d.ts.map +0 -0
  868. /package/{dist/components → components}/shared/ShellHeaderControls.js +0 -0
  869. /package/{dist/components → components}/shared-companion-scene-context.d.ts +0 -0
  870. /package/{dist/components → components}/shared-companion-scene-context.d.ts.map +0 -0
  871. /package/{dist/components → components}/shared-companion-scene-context.js +0 -0
  872. /package/{dist/components → components}/skeletons.d.ts +0 -0
  873. /package/{dist/components → components}/skeletons.d.ts.map +0 -0
  874. /package/{dist/components → components}/skeletons.js +0 -0
  875. /package/{dist/components → components}/stream/ActivityFeed.d.ts +0 -0
  876. /package/{dist/components → components}/stream/ActivityFeed.d.ts.map +0 -0
  877. /package/{dist/components → components}/stream/ActivityFeed.js +0 -0
  878. /package/{dist/components → components}/stream/AvatarPip.d.ts +0 -0
  879. /package/{dist/components → components}/stream/AvatarPip.d.ts.map +0 -0
  880. /package/{dist/components → components}/stream/AvatarPip.js +0 -0
  881. /package/{dist/components → components}/stream/ChatContent.d.ts +0 -0
  882. /package/{dist/components → components}/stream/ChatContent.d.ts.map +0 -0
  883. /package/{dist/components → components}/stream/ChatContent.js +0 -0
  884. /package/{dist/components → components}/stream/ChatTicker.d.ts +0 -0
  885. /package/{dist/components → components}/stream/ChatTicker.d.ts.map +0 -0
  886. /package/{dist/components → components}/stream/ChatTicker.js +0 -0
  887. /package/{dist/components → components}/stream/IdleContent.d.ts +0 -0
  888. /package/{dist/components → components}/stream/IdleContent.d.ts.map +0 -0
  889. /package/{dist/components → components}/stream/IdleContent.js +0 -0
  890. /package/{dist/components → components}/stream/StatusBar.d.ts +0 -0
  891. /package/{dist/components → components}/stream/StatusBar.d.ts.map +0 -0
  892. /package/{dist/components → components}/stream/StreamSettings.d.ts +0 -0
  893. /package/{dist/components → components}/stream/StreamSettings.d.ts.map +0 -0
  894. /package/{dist/components → components}/stream/StreamSettings.js +0 -0
  895. /package/{dist/components → components}/stream/StreamTerminal.d.ts +0 -0
  896. /package/{dist/components → components}/stream/StreamTerminal.d.ts.map +0 -0
  897. /package/{dist/components → components}/stream/StreamTerminal.js +0 -0
  898. /package/{dist/components → components}/stream/StreamVoiceConfig.d.ts +0 -0
  899. /package/{dist/components → components}/stream/StreamVoiceConfig.d.ts.map +0 -0
  900. /package/{dist/components → components}/stream/StreamVoiceConfig.js +0 -0
  901. /package/{dist/components → components}/stream/helpers.d.ts +0 -0
  902. /package/{dist/components → components}/stream/helpers.d.ts.map +0 -0
  903. /package/{dist/components → components}/stream/helpers.js +0 -0
  904. /package/{dist/components → components}/stream/overlays/OverlayLayer.d.ts +0 -0
  905. /package/{dist/components → components}/stream/overlays/OverlayLayer.d.ts.map +0 -0
  906. /package/{dist/components → components}/stream/overlays/OverlayLayer.js +0 -0
  907. /package/{dist/components → components}/stream/overlays/built-in/ActionTickerWidget.d.ts +0 -0
  908. /package/{dist/components → components}/stream/overlays/built-in/ActionTickerWidget.d.ts.map +0 -0
  909. /package/{dist/components → components}/stream/overlays/built-in/ActionTickerWidget.js +0 -0
  910. /package/{dist/components → components}/stream/overlays/built-in/AlertPopupWidget.d.ts +0 -0
  911. /package/{dist/components → components}/stream/overlays/built-in/AlertPopupWidget.d.ts.map +0 -0
  912. /package/{dist/components → components}/stream/overlays/built-in/AlertPopupWidget.js +0 -0
  913. /package/{dist/components → components}/stream/overlays/built-in/BrandingWidget.d.ts +0 -0
  914. /package/{dist/components → components}/stream/overlays/built-in/BrandingWidget.d.ts.map +0 -0
  915. /package/{dist/components → components}/stream/overlays/built-in/BrandingWidget.js +0 -0
  916. /package/{dist/components → components}/stream/overlays/built-in/CustomHtmlWidget.d.ts +0 -0
  917. /package/{dist/components → components}/stream/overlays/built-in/CustomHtmlWidget.d.ts.map +0 -0
  918. /package/{dist/components → components}/stream/overlays/built-in/CustomHtmlWidget.js +0 -0
  919. /package/{dist/components → components}/stream/overlays/built-in/PeonGlassWidget.d.ts +0 -0
  920. /package/{dist/components → components}/stream/overlays/built-in/PeonGlassWidget.d.ts.map +0 -0
  921. /package/{dist/components → components}/stream/overlays/built-in/PeonGlassWidget.js +0 -0
  922. /package/{dist/components → components}/stream/overlays/built-in/PeonHudWidget.d.ts +0 -0
  923. /package/{dist/components → components}/stream/overlays/built-in/PeonHudWidget.d.ts.map +0 -0
  924. /package/{dist/components → components}/stream/overlays/built-in/PeonHudWidget.js +0 -0
  925. /package/{dist/components → components}/stream/overlays/built-in/PeonSakuraWidget.d.ts +0 -0
  926. /package/{dist/components → components}/stream/overlays/built-in/PeonSakuraWidget.d.ts.map +0 -0
  927. /package/{dist/components → components}/stream/overlays/built-in/PeonSakuraWidget.js +0 -0
  928. /package/{dist/components → components}/stream/overlays/built-in/ThoughtBubbleWidget.d.ts +0 -0
  929. /package/{dist/components → components}/stream/overlays/built-in/ThoughtBubbleWidget.d.ts.map +0 -0
  930. /package/{dist/components → components}/stream/overlays/built-in/ThoughtBubbleWidget.js +0 -0
  931. /package/{dist/components → components}/stream/overlays/built-in/ViewerCountWidget.d.ts +0 -0
  932. /package/{dist/components → components}/stream/overlays/built-in/ViewerCountWidget.d.ts.map +0 -0
  933. /package/{dist/components → components}/stream/overlays/built-in/ViewerCountWidget.js +0 -0
  934. /package/{dist/components → components}/stream/overlays/built-in/index.d.ts +0 -0
  935. /package/{dist/components → components}/stream/overlays/built-in/index.d.ts.map +0 -0
  936. /package/{dist/components → components}/stream/overlays/built-in/index.js +0 -0
  937. /package/{dist/components → components}/stream/overlays/registry.d.ts +0 -0
  938. /package/{dist/components → components}/stream/overlays/registry.d.ts.map +0 -0
  939. /package/{dist/components → components}/stream/overlays/registry.js +0 -0
  940. /package/{dist/components → components}/stream/overlays/types.d.ts +0 -0
  941. /package/{dist/components → components}/stream/overlays/types.d.ts.map +0 -0
  942. /package/{dist/components → components}/stream/overlays/types.js +0 -0
  943. /package/{dist/components → components}/stream/overlays/useOverlayLayout.d.ts.map +0 -0
  944. /package/{dist/components → components}/trajectory-format.d.ts +0 -0
  945. /package/{dist/components → components}/trajectory-format.d.ts.map +0 -0
  946. /package/{dist/components → components}/trajectory-format.js +0 -0
  947. /package/{dist/components → components}/ui-badges.d.ts +0 -0
  948. /package/{dist/components → components}/ui-badges.d.ts.map +0 -0
  949. /package/{dist/components → components}/ui-badges.js +0 -0
  950. /package/{dist/components → components}/ui-switch.d.ts +0 -0
  951. /package/{dist/components → components}/ui-switch.d.ts.map +0 -0
  952. /package/{dist/components → components}/ui-switch.js +0 -0
  953. /package/{dist/components → components}/vector-browser-three.d.ts +0 -0
  954. /package/{dist/components → components}/vector-browser-three.d.ts.map +0 -0
  955. /package/{dist/components → components}/vector-browser-three.js +0 -0
  956. /package/{dist/config → config}/config-catalog.d.ts +0 -0
  957. /package/{dist/config → config}/config-catalog.d.ts.map +0 -0
  958. /package/{dist/config → config}/config-catalog.js +0 -0
  959. /package/{dist/config → config}/config-field.d.ts +0 -0
  960. /package/{dist/config → config}/config-field.d.ts.map +0 -0
  961. /package/{dist/config → config}/config-field.js +0 -0
  962. /package/{dist/config → config}/config-renderer.d.ts +0 -0
  963. /package/{dist/config → config}/config-renderer.d.ts.map +0 -0
  964. /package/{dist/config → config}/config-renderer.js +0 -0
  965. /package/{dist/config → config}/index.d.ts +0 -0
  966. /package/{dist/config → config}/index.d.ts.map +0 -0
  967. /package/{dist/config → config}/index.js +0 -0
  968. /package/{dist/config → config}/ui-renderer.d.ts +0 -0
  969. /package/{dist/config → config}/ui-renderer.d.ts.map +0 -0
  970. /package/{dist/config → config}/ui-renderer.js +0 -0
  971. /package/{dist/config → config}/ui-spec.d.ts +0 -0
  972. /package/{dist/config → config}/ui-spec.d.ts.map +0 -0
  973. /package/{dist/config → config}/ui-spec.js +0 -0
  974. /package/{dist/hooks → hooks}/index.d.ts +0 -0
  975. /package/{dist/hooks → hooks}/index.d.ts.map +0 -0
  976. /package/{dist/hooks → hooks}/index.js +0 -0
  977. /package/{dist/hooks → hooks}/useBugReport.d.ts +0 -0
  978. /package/{dist/hooks → hooks}/useBugReport.d.ts.map +0 -0
  979. /package/{dist/hooks → hooks}/useBugReport.js +0 -0
  980. /package/{dist/hooks → hooks}/useCanvasWindow.d.ts +0 -0
  981. /package/{dist/hooks → hooks}/useCanvasWindow.d.ts.map +0 -0
  982. /package/{dist/hooks → hooks}/useCanvasWindow.js +0 -0
  983. /package/{dist/hooks → hooks}/useChatAvatarVoice.d.ts +0 -0
  984. /package/{dist/hooks → hooks}/useChatAvatarVoice.d.ts.map +0 -0
  985. /package/{dist/hooks → hooks}/useChatAvatarVoice.js +0 -0
  986. /package/{dist/hooks → hooks}/useContextMenu.d.ts +0 -0
  987. /package/{dist/hooks → hooks}/useContextMenu.d.ts.map +0 -0
  988. /package/{dist/hooks → hooks}/useContextMenu.js +0 -0
  989. /package/{dist/hooks → hooks}/useKeyboardShortcuts.d.ts +0 -0
  990. /package/{dist/hooks → hooks}/useKeyboardShortcuts.d.ts.map +0 -0
  991. /package/{dist/hooks → hooks}/useKeyboardShortcuts.js +0 -0
  992. /package/{dist/hooks → hooks}/useLifoSync.d.ts +0 -0
  993. /package/{dist/hooks → hooks}/useLifoSync.d.ts.map +0 -0
  994. /package/{dist/hooks → hooks}/useLifoSync.js +0 -0
  995. /package/{dist/hooks → hooks}/useMemoryMonitor.d.ts +0 -0
  996. /package/{dist/hooks → hooks}/useMemoryMonitor.d.ts.map +0 -0
  997. /package/{dist/hooks → hooks}/useMemoryMonitor.js +0 -0
  998. /package/{dist/hooks → hooks}/useRenderGuard.d.ts +0 -0
  999. /package/{dist/hooks → hooks}/useRenderGuard.d.ts.map +0 -0
  1000. /package/{dist/hooks → hooks}/useRenderGuard.js +0 -0
  1001. /package/{dist/hooks → hooks}/useRetakeCapture.d.ts +0 -0
  1002. /package/{dist/hooks → hooks}/useRetakeCapture.d.ts.map +0 -0
  1003. /package/{dist/hooks → hooks}/useStreamPopoutNavigation.d.ts +0 -0
  1004. /package/{dist/hooks → hooks}/useStreamPopoutNavigation.d.ts.map +0 -0
  1005. /package/{dist/hooks → hooks}/useStreamPopoutNavigation.js +0 -0
  1006. /package/{dist/hooks → hooks}/useTimeout.d.ts +0 -0
  1007. /package/{dist/hooks → hooks}/useTimeout.d.ts.map +0 -0
  1008. /package/{dist/hooks → hooks}/useTimeout.js +0 -0
  1009. /package/{dist/hooks → hooks}/useVoiceChat.d.ts +0 -0
  1010. /package/{dist/hooks → hooks}/useVoiceChat.d.ts.map +0 -0
  1011. /package/{dist/hooks → hooks}/useVoiceChat.js +0 -0
  1012. /package/{dist/hooks → hooks}/useWhatsAppPairing.d.ts +0 -0
  1013. /package/{dist/hooks → hooks}/useWhatsAppPairing.d.ts.map +0 -0
  1014. /package/{dist/hooks → hooks}/useWhatsAppPairing.js +0 -0
  1015. /package/{dist/i18n → i18n}/index.d.ts +0 -0
  1016. /package/{dist/i18n → i18n}/index.d.ts.map +0 -0
  1017. /package/{dist/i18n → i18n}/index.js +0 -0
  1018. /package/{dist/i18n → i18n}/messages.d.ts +0 -0
  1019. /package/{dist/i18n → i18n}/messages.d.ts.map +0 -0
  1020. /package/{dist/i18n → i18n}/messages.js +0 -0
  1021. /package/{dist/index.d.ts → index.d.ts} +0 -0
  1022. /package/{dist/index.d.ts.map → index.d.ts.map} +0 -0
  1023. /package/{dist/index.js → index.js} +0 -0
  1024. /package/{dist/navigation → navigation}/index.d.ts +0 -0
  1025. /package/{dist/navigation → navigation}/index.d.ts.map +0 -0
  1026. /package/{dist/onboarding-config.d.ts → onboarding-config.d.ts} +0 -0
  1027. /package/{dist/onboarding-config.d.ts.map → onboarding-config.d.ts.map} +0 -0
  1028. /package/{dist/onboarding-config.js → onboarding-config.js} +0 -0
  1029. /package/{dist/platform → platform}/browser-launch.d.ts +0 -0
  1030. /package/{dist/platform → platform}/browser-launch.d.ts.map +0 -0
  1031. /package/{dist/platform → platform}/index.d.ts +0 -0
  1032. /package/{dist/platform → platform}/index.d.ts.map +0 -0
  1033. /package/{dist/platform → platform}/index.js +0 -0
  1034. /package/{dist/providers → providers}/index.d.ts +0 -0
  1035. /package/{dist/providers → providers}/index.d.ts.map +0 -0
  1036. /package/{dist/providers → providers}/index.js +0 -0
  1037. /package/{dist/state → state}/AppContext.d.ts +0 -0
  1038. /package/{dist/state → state}/AppContext.d.ts.map +0 -0
  1039. /package/{dist/state → state}/index.d.ts +0 -0
  1040. /package/{dist/state → state}/index.d.ts.map +0 -0
  1041. /package/{dist/state → state}/index.js +0 -0
  1042. /package/{dist/state → state}/internal.d.ts +0 -0
  1043. /package/{dist/state → state}/internal.d.ts.map +0 -0
  1044. /package/{dist/state → state}/internal.js +0 -0
  1045. /package/{dist/state → state}/onboarding-resume.d.ts +0 -0
  1046. /package/{dist/state → state}/onboarding-resume.d.ts.map +0 -0
  1047. /package/{dist/state → state}/parsers.d.ts +0 -0
  1048. /package/{dist/state → state}/parsers.d.ts.map +0 -0
  1049. /package/{dist/state → state}/parsers.js +0 -0
  1050. /package/{dist/state → state}/persistence.d.ts +0 -0
  1051. /package/{dist/state → state}/persistence.d.ts.map +0 -0
  1052. /package/{dist/state → state}/shell-routing.d.ts +0 -0
  1053. /package/{dist/state → state}/shell-routing.d.ts.map +0 -0
  1054. /package/{dist/state → state}/shell-routing.js +0 -0
  1055. /package/{dist/state → state}/types.d.ts +0 -0
  1056. /package/{dist/state → state}/types.d.ts.map +0 -0
  1057. /package/{dist/state → state}/types.js +0 -0
  1058. /package/{dist/state → state}/ui-preferences.d.ts +0 -0
  1059. /package/{dist/state → state}/ui-preferences.d.ts.map +0 -0
  1060. /package/{dist/state → state}/ui-preferences.js +0 -0
  1061. /package/{dist/state → state}/useApp.d.ts +0 -0
  1062. /package/{dist/state → state}/useApp.d.ts.map +0 -0
  1063. /package/{dist/state → state}/useApp.js +0 -0
  1064. /package/{dist/stories → stories}/AppMockProvider.d.ts +0 -0
  1065. /package/{dist/stories → stories}/AppMockProvider.d.ts.map +0 -0
  1066. /package/{dist/stories → stories}/AppMockProvider.js +0 -0
  1067. /package/{src/styles → styles}/anime.css +0 -0
  1068. /package/{src/styles → styles}/base.css +0 -0
  1069. /package/{src/styles → styles}/onboarding-game.css +0 -0
  1070. /package/{src/styles → styles}/styles.css +0 -0
  1071. /package/{src/styles → styles}/xterm.css +0 -0
  1072. /package/{dist/types → types}/index.d.ts +0 -0
  1073. /package/{dist/types → types}/index.d.ts.map +0 -0
  1074. /package/{dist/types → types}/index.js +0 -0
  1075. /package/{dist/utils → utils}/asset-url.d.ts.map +0 -0
  1076. /package/{dist/utils → utils}/assistant-text.d.ts +0 -0
  1077. /package/{dist/utils → utils}/assistant-text.d.ts.map +0 -0
  1078. /package/{dist/utils → utils}/assistant-text.js +0 -0
  1079. /package/{dist/utils → utils}/clipboard.d.ts +0 -0
  1080. /package/{dist/utils → utils}/clipboard.d.ts.map +0 -0
  1081. /package/{dist/utils → utils}/clipboard.js +0 -0
  1082. /package/{dist/utils → utils}/desktop-dialogs.d.ts +0 -0
  1083. /package/{dist/utils → utils}/desktop-dialogs.d.ts.map +0 -0
  1084. /package/{dist/utils → utils}/desktop-dialogs.js +0 -0
  1085. /package/{dist/utils → utils}/index.d.ts +0 -0
  1086. /package/{dist/utils → utils}/index.d.ts.map +0 -0
  1087. /package/{dist/utils → utils}/index.js +0 -0
  1088. /package/{dist/utils → utils}/number-parsing.d.ts +0 -0
  1089. /package/{dist/utils → utils}/number-parsing.d.ts.map +0 -0
  1090. /package/{dist/utils → utils}/number-parsing.js +0 -0
  1091. /package/{dist/utils → utils}/openExternalUrl.d.ts +0 -0
  1092. /package/{dist/utils → utils}/openExternalUrl.d.ts.map +0 -0
  1093. /package/{dist/utils → utils}/openExternalUrl.js +0 -0
  1094. /package/{dist/utils → utils}/spoken-text.d.ts +0 -0
  1095. /package/{dist/utils → utils}/spoken-text.d.ts.map +0 -0
  1096. /package/{dist/utils → utils}/spoken-text.js +0 -0
  1097. /package/{dist/utils → utils}/streaming-text.d.ts +0 -0
  1098. /package/{dist/utils → utils}/streaming-text.d.ts.map +0 -0
  1099. /package/{dist/utils → utils}/streaming-text.js +0 -0
  1100. /package/{dist/voice → voice}/index.d.ts +0 -0
  1101. /package/{dist/voice → voice}/index.d.ts.map +0 -0
  1102. /package/{dist/voice → voice}/index.js +0 -0
  1103. /package/{dist/voice → voice}/types.d.ts +0 -0
  1104. /package/{dist/voice → voice}/types.d.ts.map +0 -0
  1105. /package/{dist/voice → voice}/types.js +0 -0
  1106. /package/{dist/wallet-rpc.d.ts → wallet-rpc.d.ts} +0 -0
  1107. /package/{dist/wallet-rpc.d.ts.map → wallet-rpc.d.ts.map} +0 -0
  1108. /package/{dist/wallet-rpc.js → wallet-rpc.js} +0 -0
@@ -1,3165 +0,0 @@
1
- /**
2
- * Plugins view — tag-filtered plugin management.
3
- *
4
- * Renders a unified plugin list with searchable/filterable cards and per-plugin settings.
5
- */
6
-
7
- import { Button, Input } from "@elizaos/ui";
8
- import type { LucideIcon } from "lucide-react";
9
- import {
10
- Binary,
11
- BookOpen,
12
- Bot,
13
- Brain,
14
- BrickWall,
15
- Briefcase,
16
- Calendar,
17
- ChevronRight,
18
- Chrome,
19
- Circle,
20
- CircleDashed,
21
- CircleDot,
22
- ClipboardList,
23
- Clock,
24
- Cloud,
25
- Command,
26
- Construction,
27
- CreditCard,
28
- Diamond,
29
- Dna,
30
- Droplets,
31
- Eye,
32
- Feather,
33
- FileKey,
34
- FileText,
35
- Fingerprint,
36
- Gamepad,
37
- Gamepad2,
38
- Github,
39
- Handshake,
40
- Hash,
41
- Layers,
42
- Leaf,
43
- Link,
44
- Lock,
45
- LockKeyhole,
46
- Mail,
47
- MessageCircle,
48
- MessageSquare,
49
- MessagesSquare,
50
- Mic,
51
- Monitor,
52
- MousePointer2,
53
- Package,
54
- PenTool,
55
- Phone,
56
- Pickaxe,
57
- Puzzle,
58
- RefreshCw,
59
- Rss,
60
- ScrollText,
61
- Send,
62
- Server,
63
- Settings,
64
- Shell,
65
- Shuffle,
66
- Smartphone,
67
- Sparkle,
68
- Sparkles,
69
- Square,
70
- Star,
71
- StickyNote,
72
- Target,
73
- Tornado,
74
- TrendingDown,
75
- Triangle,
76
- Twitter,
77
- Video,
78
- Volume2,
79
- Wallet,
80
- Webhook,
81
- Wrench,
82
- Zap,
83
- } from "lucide-react";
84
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
85
- import type { PluginInfo, PluginParamDef } from "../api";
86
- import { client } from "../api";
87
- import {
88
- ConfigRenderer,
89
- defaultRegistry,
90
- type JsonSchemaObject,
91
- } from "../config";
92
- import { useApp } from "../state";
93
- import type { ConfigUiHint } from "../types";
94
- import { openExternalUrl, resolveAppAssetUrl } from "../utils";
95
- import { autoLabel } from "./labels";
96
- import { SHOWCASE_PLUGIN } from "./plugins/showcase-data";
97
- import { WhatsAppQrOverlay } from "./WhatsAppQrOverlay";
98
-
99
- /* ── Always-on plugins (hidden from all views) ────────────────────────── */
100
-
101
- /**
102
- * Plugin IDs hidden from Features/Connectors views.
103
- * Core plugins are visible in Admin > Plugins instead.
104
- */
105
- const ALWAYS_ON_PLUGIN_IDS = new Set([
106
- // Core (always loaded)
107
- "sql",
108
- "local-embedding",
109
- "knowledge",
110
- "agent-skills",
111
- "directives",
112
- "commands",
113
- "personality",
114
- "experience",
115
- // Optional core (shown in admin)
116
- "agent-orchestrator",
117
- "shell",
118
- "plugin-manager",
119
- "cli",
120
- "code",
121
- "edge-tts",
122
- "pdf",
123
- "scratchpad",
124
- "secrets-manager",
125
- "todo",
126
- "trust",
127
- "form",
128
- "goals",
129
- "scheduling",
130
- // Internal / infrastructure
131
- "elizacloud",
132
- "evm",
133
- "memory",
134
- "rolodex",
135
- "tts",
136
- "elevenlabs",
137
- "cron",
138
- "webhooks",
139
- "browser",
140
- "vision",
141
- "computeruse",
142
- ]);
143
-
144
- /* ── Helpers ────────────────────────────────────────────────────────── */
145
-
146
- /** Detect advanced / debug parameters that should be collapsed by default. */
147
- function isAdvancedParam(param: PluginParamDef): boolean {
148
- const k = param.key.toUpperCase();
149
- const d = (param.description ?? "").toLowerCase();
150
- return (
151
- k.includes("EXPERIMENTAL") ||
152
- k.includes("DEBUG") ||
153
- k.includes("VERBOSE") ||
154
- k.includes("TELEMETRY") ||
155
- k.includes("BROWSER_BASE") ||
156
- d.includes("experimental") ||
157
- d.includes("advanced") ||
158
- d.includes("debug")
159
- );
160
- }
161
-
162
- /** Convert PluginParamDef[] to a JSON Schema + ConfigUiHints for ConfigRenderer. */
163
- export function paramsToSchema(
164
- params: PluginParamDef[],
165
- pluginId: string,
166
- ): {
167
- schema: JsonSchemaObject;
168
- hints: Record<string, ConfigUiHint>;
169
- } {
170
- const properties: Record<string, Record<string, unknown>> = {};
171
- const required: string[] = [];
172
- const hints: Record<string, ConfigUiHint> = {};
173
-
174
- for (const p of params) {
175
- // Build JSON Schema property
176
- const prop: Record<string, unknown> = {};
177
- if (p.type === "boolean") {
178
- prop.type = "boolean";
179
- } else if (p.type === "number") {
180
- prop.type = "number";
181
- } else {
182
- prop.type = "string";
183
- }
184
- if (p.description) prop.description = p.description;
185
- if (p.default != null) prop.default = p.default;
186
- if (p.options?.length) {
187
- prop.enum = p.options;
188
- }
189
-
190
- // Auto-detect format from key name
191
- const keyUpper = p.key.toUpperCase();
192
- if (
193
- keyUpper.includes("URL") ||
194
- keyUpper.includes("ENDPOINT") ||
195
- keyUpper.includes("BASE_URL")
196
- ) {
197
- prop.format = "uri";
198
- } else if (keyUpper.includes("EMAIL")) {
199
- prop.format = "email";
200
- } else if (
201
- keyUpper.includes("_DATE") ||
202
- keyUpper.includes("_SINCE") ||
203
- keyUpper.includes("_UNTIL")
204
- ) {
205
- prop.format = "date";
206
- }
207
-
208
- // Auto-detect number types from key patterns
209
- if (keyUpper.includes("PORT") && prop.type === "string") {
210
- prop.type = "number";
211
- } else if (
212
- (keyUpper.includes("TIMEOUT") ||
213
- keyUpper.includes("INTERVAL") ||
214
- keyUpper.includes("_MS")) &&
215
- prop.type === "string"
216
- ) {
217
- prop.type = "number";
218
- } else if (
219
- (keyUpper.includes("COUNT") ||
220
- keyUpper.includes("LIMIT") ||
221
- keyUpper.startsWith("MAX_")) &&
222
- prop.type === "string"
223
- ) {
224
- prop.type = "number";
225
- } else if (
226
- (keyUpper.includes("RETRY") || keyUpper.includes("RETRIES")) &&
227
- prop.type === "string"
228
- ) {
229
- prop.type = "number";
230
- }
231
-
232
- // Auto-detect boolean from key patterns
233
- if (
234
- prop.type === "string" &&
235
- (keyUpper.includes("SHOULD_") ||
236
- keyUpper.endsWith("_ENABLED") ||
237
- keyUpper.endsWith("_DISABLED") ||
238
- keyUpper.startsWith("USE_") ||
239
- keyUpper.startsWith("ALLOW_") ||
240
- keyUpper.startsWith("IS_") ||
241
- keyUpper.startsWith("ENABLE_") ||
242
- keyUpper.startsWith("DISABLE_") ||
243
- keyUpper.startsWith("FORCE_") ||
244
- keyUpper.endsWith("_AUTONOMOUS_MODE"))
245
- ) {
246
- prop.type = "boolean";
247
- }
248
-
249
- // Auto-detect number from key patterns (RATE, DELAY, THRESHOLD, SIZE, TEMPERATURE)
250
- if (
251
- prop.type === "string" &&
252
- (keyUpper.includes("_RATE") ||
253
- keyUpper.includes("DELAY") ||
254
- keyUpper.includes("THRESHOLD") ||
255
- keyUpper.includes("_SIZE") ||
256
- keyUpper.includes("TEMPERATURE") ||
257
- keyUpper.includes("_DEPTH") ||
258
- keyUpper.includes("_PERCENT") ||
259
- keyUpper.includes("_RATIO"))
260
- ) {
261
- prop.type = "number";
262
- }
263
-
264
- // Auto-detect comma-separated lists → array renderer
265
- if (prop.type === "string" && !prop.enum) {
266
- const descLower = (p.description || "").toLowerCase();
267
- const isCommaSep =
268
- descLower.includes("comma-separated") ||
269
- descLower.includes("comma separated");
270
- const isListSuffix =
271
- keyUpper.endsWith("_IDS") ||
272
- keyUpper.endsWith("_CHANNELS") ||
273
- keyUpper.endsWith("_ROOMS") ||
274
- keyUpper.endsWith("_RELAYS") ||
275
- keyUpper.endsWith("_FEEDS") ||
276
- keyUpper.endsWith("_DEXES") ||
277
- keyUpper.endsWith("_WHITELIST") ||
278
- keyUpper.endsWith("_BLACKLIST") ||
279
- keyUpper.endsWith("_ALLOWLIST") ||
280
- keyUpper.endsWith("_SPACES") ||
281
- keyUpper.endsWith("_THREADS") ||
282
- keyUpper.endsWith("_ROLES") ||
283
- keyUpper.endsWith("_TENANTS") ||
284
- keyUpper.endsWith("_DIRS");
285
- if (isCommaSep || isListSuffix) {
286
- prop.type = "array";
287
- prop.items = { type: "string" };
288
- }
289
- }
290
-
291
- // Auto-detect textarea (prompts, instructions, templates, greetings)
292
- if (prop.type === "string" && !prop.enum && !keyUpper.includes("MODEL")) {
293
- if (
294
- keyUpper.includes("INSTRUCTIONS") ||
295
- keyUpper.includes("_GREETING") ||
296
- keyUpper.endsWith("_PROMPT") ||
297
- keyUpper.endsWith("_TEMPLATE") ||
298
- keyUpper.includes("SYSTEM_MESSAGE")
299
- ) {
300
- prop.maxLength = 999;
301
- }
302
- }
303
-
304
- // Auto-detect JSON fields (json-encoded or serialized values)
305
- if (prop.type === "string" && !p.sensitive) {
306
- const descLower = (p.description || "").toLowerCase();
307
- if (
308
- descLower.includes("json-encoded") ||
309
- descLower.includes("json array") ||
310
- descLower.includes("serialized") ||
311
- descLower.includes("json format")
312
- ) {
313
- (prop as Record<string, unknown>).__jsonHint = true;
314
- }
315
- }
316
-
317
- // Auto-detect file/directory paths → file renderer
318
- if (prop.type === "string") {
319
- if (
320
- (keyUpper.endsWith("_PATH") && !keyUpper.includes("WEBHOOK")) ||
321
- keyUpper.endsWith("_DIR") ||
322
- keyUpper.endsWith("_DIRECTORY") ||
323
- keyUpper.endsWith("_FOLDER") ||
324
- keyUpper.endsWith("_FILE")
325
- ) {
326
- (prop as Record<string, unknown>).__fileHint = true;
327
- }
328
- }
329
-
330
- // Auto-detect textarea from long descriptions
331
- if (p.description && p.description.length > 200) {
332
- prop.maxLength = 999;
333
- }
334
-
335
- properties[p.key] = prop;
336
-
337
- if (p.required) required.push(p.key);
338
-
339
- // Build UI hint
340
- const hint: ConfigUiHint = {
341
- label: autoLabel(p.key, pluginId),
342
- sensitive: p.sensitive ?? false,
343
- advanced: isAdvancedParam(p),
344
- };
345
-
346
- // Port numbers — constrain range
347
- if (keyUpper.includes("PORT")) {
348
- hint.min = 1;
349
- hint.max = 65535;
350
- prop.minimum = 1;
351
- prop.maximum = 65535;
352
- }
353
-
354
- // Timeout/interval — show unit
355
- if (
356
- keyUpper.includes("TIMEOUT") ||
357
- keyUpper.includes("INTERVAL") ||
358
- keyUpper.includes("_MS")
359
- ) {
360
- hint.unit = "ms";
361
- prop.minimum = 0;
362
- hint.min = 0;
363
- }
364
-
365
- // Count/limit — non-negative
366
- if (
367
- keyUpper.includes("COUNT") ||
368
- keyUpper.includes("LIMIT") ||
369
- keyUpper.startsWith("MAX_")
370
- ) {
371
- hint.min = 0;
372
- prop.minimum = 0;
373
- }
374
-
375
- // Retry — bounded range
376
- if (keyUpper.includes("RETRY") || keyUpper.includes("RETRIES")) {
377
- hint.min = 0;
378
- hint.max = 100;
379
- prop.minimum = 0;
380
- prop.maximum = 100;
381
- }
382
-
383
- // Debug/verbose/enabled — mark as advanced
384
- if (
385
- keyUpper.includes("DEBUG") ||
386
- keyUpper.includes("VERBOSE") ||
387
- keyUpper.includes("ENABLED")
388
- ) {
389
- hint.advanced = true;
390
- }
391
-
392
- // Model selection — NOT advanced (important user-facing choice)
393
- if (keyUpper.includes("MODEL") && p.options?.length) {
394
- hint.advanced = false;
395
- }
396
-
397
- // Region/zone — suggest common cloud regions when no options provided
398
- if (
399
- (keyUpper.includes("REGION") || keyUpper.includes("ZONE")) &&
400
- !p.options?.length
401
- ) {
402
- hint.type = "select";
403
- hint.options = [
404
- { value: "us-east-1", label: "US East (N. Virginia)" },
405
- { value: "us-west-2", label: "US West (Oregon)" },
406
- { value: "eu-west-1", label: "EU (Ireland)" },
407
- { value: "eu-central-1", label: "EU (Frankfurt)" },
408
- { value: "ap-southeast-1", label: "Asia Pacific (Singapore)" },
409
- { value: "ap-northeast-1", label: "Asia Pacific (Tokyo)" },
410
- ];
411
- }
412
-
413
- // File/directory path → file renderer
414
- if ((prop as Record<string, unknown>).__fileHint) {
415
- hint.type = "file";
416
- delete (prop as Record<string, unknown>).__fileHint;
417
- }
418
-
419
- // JSON-encoded value → json renderer
420
- if ((prop as Record<string, unknown>).__jsonHint) {
421
- hint.type = "json";
422
- delete (prop as Record<string, unknown>).__jsonHint;
423
- }
424
-
425
- // Model name fields — helpful placeholder (overridden by server-provided model options via configUiHints)
426
- if (
427
- keyUpper.includes("MODEL") &&
428
- prop.type === "string" &&
429
- !p.options?.length
430
- ) {
431
- if (!hint.placeholder) {
432
- if (keyUpper.includes("EMBEDDING")) {
433
- hint.placeholder = "e.g., text-embedding-3-small";
434
- } else if (keyUpper.includes("TTS")) {
435
- hint.placeholder = "e.g., tts-1, eleven_multilingual_v2";
436
- } else if (keyUpper.includes("STT")) {
437
- hint.placeholder = "e.g., whisper-1";
438
- } else if (keyUpper.includes("IMAGE")) {
439
- hint.placeholder = "e.g., dall-e-3, gpt-4o";
440
- } else {
441
- hint.placeholder = "e.g., gpt-4o, claude-sonnet-4-20250514";
442
- }
443
- }
444
- }
445
-
446
- // Mode/strategy fields — extract options from description if available
447
- if (
448
- prop.type === "string" &&
449
- !prop.enum &&
450
- !p.sensitive &&
451
- (keyUpper.endsWith("_MODE") || keyUpper.endsWith("_STRATEGY"))
452
- ) {
453
- const desc = p.description ?? "";
454
- // Match "auto | local | mcp" or "filesystem|in-context|sqlite"
455
- const pipeMatch =
456
- desc.match(/:\s*([a-z0-9_-]+(?:\s*[|/]\s*[a-z0-9_-]+)+)/i) ??
457
- desc.match(/\(([a-z0-9_-]+(?:\s*[|/,]\s*[a-z0-9_-]+)+)\)/i);
458
- if (pipeMatch) {
459
- const opts = pipeMatch[1]
460
- .split(/[|/,]/)
461
- .map((s) => s.trim())
462
- .filter(Boolean);
463
- const safeOpts = opts.filter((v) => /^[a-z0-9_-]+$/i.test(v));
464
- if (safeOpts.length >= 2 && safeOpts.length <= 10) {
465
- hint.type = "select";
466
- hint.options = safeOpts.map((v) => ({ value: v, label: v }));
467
- }
468
- } else {
469
- // Match 'polling' or 'webhook' -or- 'env', 'oauth', or 'bearer' style
470
- const quotedOpts = [...desc.matchAll(/'([a-z0-9_-]+)'/gi)].map(
471
- (m) => m[1],
472
- );
473
- const safeQuoted = quotedOpts.filter((v) => /^[a-z0-9_-]+$/i.test(v));
474
- if (safeQuoted.length >= 2 && safeQuoted.length <= 10) {
475
- // Radio for 2 options, select for 3+
476
- hint.type = safeQuoted.length === 2 ? "radio" : "select";
477
- hint.options = safeQuoted.map((v) => ({ value: v, label: v }));
478
- }
479
- }
480
- }
481
-
482
- if (p.description) {
483
- hint.help = p.description;
484
- if (p.default != null) hint.help += ` (default: ${String(p.default)})`;
485
- }
486
- if (p.sensitive)
487
- hint.placeholder = p.isSet ? "******** (already set)" : "Enter value...";
488
- else if (p.default) hint.placeholder = `Default: ${String(p.default)}`;
489
- hints[p.key] = hint;
490
- }
491
-
492
- return {
493
- schema: { type: "object", properties, required } as JsonSchemaObject,
494
- hints,
495
- };
496
- }
497
-
498
- /* ── PluginConfigForm bridge ─────────────────────────────────────────── */
499
-
500
- function PluginConfigForm({
501
- plugin,
502
- pluginConfigs,
503
- onParamChange,
504
- }: {
505
- plugin: PluginInfo;
506
- pluginConfigs: Record<string, Record<string, string>>;
507
- onParamChange: (pluginId: string, paramKey: string, value: string) => void;
508
- }) {
509
- const params = plugin.parameters ?? [];
510
- const { schema, hints: autoHints } = useMemo(
511
- () => paramsToSchema(params, plugin.id),
512
- [params, plugin.id],
513
- );
514
-
515
- // Merge server-provided configUiHints over auto-generated hints.
516
- // Server hints take priority (override auto-generated ones).
517
- const hints = useMemo(() => {
518
- const serverHints = plugin.configUiHints;
519
- if (!serverHints || Object.keys(serverHints).length === 0) return autoHints;
520
- const merged: Record<string, ConfigUiHint> = { ...autoHints };
521
- for (const [key, serverHint] of Object.entries(serverHints)) {
522
- merged[key] = { ...merged[key], ...serverHint };
523
- }
524
- return merged;
525
- }, [autoHints, plugin.configUiHints]);
526
-
527
- // Build values from current config state + existing server values.
528
- // Array-typed fields need comma-separated strings parsed into arrays.
529
- const values = useMemo(() => {
530
- const v: Record<string, unknown> = {};
531
- const props = (schema.properties ?? {}) as Record<
532
- string,
533
- Record<string, unknown>
534
- >;
535
- for (const p of params) {
536
- const isArrayField = props[p.key]?.type === "array";
537
- const configValue = pluginConfigs[plugin.id]?.[p.key];
538
- if (configValue !== undefined) {
539
- if (isArrayField && typeof configValue === "string") {
540
- v[p.key] = configValue
541
- ? configValue
542
- .split(",")
543
- .map((s: string) => s.trim())
544
- .filter(Boolean)
545
- : [];
546
- } else {
547
- v[p.key] = configValue;
548
- }
549
- } else if (p.isSet && !p.sensitive && p.currentValue != null) {
550
- if (isArrayField && typeof p.currentValue === "string") {
551
- v[p.key] = String(p.currentValue)
552
- ? String(p.currentValue)
553
- .split(",")
554
- .map((s: string) => s.trim())
555
- .filter(Boolean)
556
- : [];
557
- } else {
558
- v[p.key] = p.currentValue;
559
- }
560
- }
561
- }
562
- return v;
563
- }, [params, plugin.id, pluginConfigs, schema]);
564
-
565
- const setKeys = useMemo(
566
- () =>
567
- new Set(
568
- params
569
- .filter((p: PluginParamDef) => p.isSet)
570
- .map((p: PluginParamDef) => p.key),
571
- ),
572
- [params],
573
- );
574
-
575
- const handleChange = useCallback(
576
- (key: string, value: unknown) => {
577
- // Join array values back to comma-separated strings for env var storage
578
- const stringValue = Array.isArray(value)
579
- ? value.join(", ")
580
- : String(value ?? "");
581
- onParamChange(plugin.id, key, stringValue);
582
- },
583
- [plugin.id, onParamChange],
584
- );
585
-
586
- return (
587
- <ConfigRenderer
588
- schema={schema}
589
- hints={hints}
590
- values={values}
591
- setKeys={setKeys}
592
- registry={defaultRegistry}
593
- pluginId={plugin.id}
594
- onChange={handleChange}
595
- />
596
- );
597
- }
598
-
599
- /* ── Default Icons ─────────────────────────────────────────────────── */
600
-
601
- const DEFAULT_ICONS: Record<string, LucideIcon> = {
602
- // AI Providers
603
- anthropic: Brain,
604
- "google-genai": Sparkles,
605
- groq: Zap,
606
- "local-ai": Monitor,
607
- ollama: Bot,
608
- openai: CircleDashed,
609
- openrouter: Shuffle,
610
- "vercel-ai-gateway": Triangle,
611
- xai: Hash,
612
- // Connectors — chat & social
613
- discord: MessageCircle,
614
- telegram: Send,
615
- slack: Briefcase,
616
- twitter: Twitter,
617
- whatsapp: Smartphone,
618
- signal: Lock,
619
- imessage: MessageSquare,
620
- bluebubbles: Droplets,
621
- bluesky: Leaf,
622
- farcaster: Circle,
623
- instagram: Video,
624
- nostr: Fingerprint,
625
- twitch: Gamepad2,
626
- matrix: Link,
627
- mattermost: Diamond,
628
- msteams: Square,
629
- "google-chat": MessagesSquare,
630
- feishu: Feather,
631
- line: Circle,
632
- "nextcloud-talk": Cloud,
633
- tlon: Tornado,
634
- zalo: Circle,
635
- zalouser: Circle,
636
- // Features — voice & audio
637
- "edge-tts": Volume2,
638
- elevenlabs: Mic,
639
- tts: Volume2,
640
- "simple-voice": Mic,
641
- "robot-voice": Bot,
642
- // Features — blockchain & finance
643
- evm: Link,
644
- solana: CircleDot,
645
- "auto-trader": TrendingDown,
646
- "lp-manager": Wallet,
647
- "social-alpha": Layers,
648
- polymarket: Gamepad2,
649
- x402: CreditCard,
650
- trust: Handshake,
651
- iq: Puzzle,
652
- // Features — dev tools & infra
653
- cli: Hash,
654
- code: Puzzle,
655
- shell: Shell,
656
- github: Github,
657
- linear: Square,
658
- mcp: Puzzle,
659
- browser: Chrome,
660
- computeruse: MousePointer2,
661
- n8n: Settings,
662
- webhooks: Webhook,
663
- // Features — knowledge & memory
664
- knowledge: BookOpen,
665
- memory: Dna,
666
- "local-embedding": Binary,
667
- pdf: FileText,
668
- "secrets-manager": FileKey,
669
- scratchpad: StickyNote,
670
- rlm: RefreshCw,
671
- // Features — agents & orchestration
672
- "agent-orchestrator": Target,
673
- "agent-skills": Wrench,
674
- "plugin-manager": Package,
675
- "copilot-proxy": Handshake,
676
- directives: ClipboardList,
677
- goals: Target,
678
- "eliza-classic": Bot,
679
- // Features — media & content
680
- vision: Eye,
681
- rss: Rss,
682
- "gmail-watch": Mail,
683
- prose: PenTool,
684
- form: ClipboardList,
685
- // Features — scheduling & automation
686
- cron: Clock,
687
- scheduling: Calendar,
688
- todo: ClipboardList,
689
- commands: Command,
690
- // Features — storage & logging
691
- "s3-storage": Server,
692
- "trajectory-logger": TrendingDown,
693
- experience: Star,
694
- // Features — gaming & misc
695
- minecraft: Pickaxe,
696
- roblox: BrickWall,
697
- babylon: Gamepad,
698
- mysticism: Sparkle,
699
- personality: Target,
700
- moltbook: ScrollText,
701
- tee: LockKeyhole,
702
- blooio: Circle,
703
- acp: Construction,
704
- elizacloud: Cloud,
705
- twilio: Phone,
706
- };
707
-
708
- /** Resolve display icon: explicit plugin.icon, fallback to default map, or null. */
709
- function resolveIcon(p: PluginInfo): LucideIcon | string | null {
710
- if (p.icon) return p.icon;
711
- return DEFAULT_ICONS[p.id] ?? null;
712
- }
713
-
714
- function iconImageSource(icon: string): string | null {
715
- const value = icon.trim();
716
- if (!value) return null;
717
- if (
718
- /^(https?:|data:image\/|blob:|file:|capacitor:|capacitor-electron:|app:|\/|\.\/|\.\.\/)/i.test(
719
- value,
720
- )
721
- ) {
722
- return resolveAppAssetUrl(value);
723
- }
724
- return null;
725
- }
726
-
727
- function getPluginResourceLinks(
728
- plugin: Pick<PluginInfo, "setupGuideUrl" | "homepage" | "repository">,
729
- ): Array<{ key: string; label: string; url: string }> {
730
- const seen = new Set<string>();
731
- const ordered = [
732
- { key: "guide", label: "Setup guide", url: plugin.setupGuideUrl },
733
- { key: "official", label: "Official", url: plugin.homepage },
734
- { key: "source", label: "Source", url: plugin.repository },
735
- ];
736
- return ordered.flatMap((item) => {
737
- const url = item.url?.trim();
738
- if (!url || seen.has(url)) return [];
739
- seen.add(url);
740
- return [{ key: item.key, label: item.label, url }];
741
- });
742
- }
743
-
744
- /* ── Sub-group Classification ──────────────────────────────────────── */
745
-
746
- /** Map plugin IDs to fine-grained sub-groups for the "Feature" category. */
747
- const FEATURE_SUBGROUP: Record<string, string> = {
748
- // Voice & Audio
749
- "edge-tts": "voice",
750
- elevenlabs: "voice",
751
- tts: "voice",
752
- "simple-voice": "voice",
753
- "robot-voice": "voice",
754
- // Blockchain & Finance
755
- evm: "blockchain",
756
- solana: "blockchain",
757
- "auto-trader": "blockchain",
758
- "lp-manager": "blockchain",
759
- "social-alpha": "blockchain",
760
- polymarket: "blockchain",
761
- x402: "blockchain",
762
- trust: "blockchain",
763
- iq: "blockchain",
764
- // Dev Tools & Infrastructure
765
- cli: "devtools",
766
- code: "devtools",
767
- shell: "devtools",
768
- github: "devtools",
769
- linear: "devtools",
770
- mcp: "devtools",
771
- browser: "devtools",
772
- computeruse: "devtools",
773
- n8n: "devtools",
774
- webhooks: "devtools",
775
- // Knowledge & Memory
776
- knowledge: "knowledge",
777
- memory: "knowledge",
778
- "local-embedding": "knowledge",
779
- pdf: "knowledge",
780
- "secrets-manager": "knowledge",
781
- scratchpad: "knowledge",
782
- rlm: "knowledge",
783
- // Agents & Orchestration
784
- "agent-orchestrator": "agents",
785
- "agent-skills": "agents",
786
- "plugin-manager": "agents",
787
- "copilot-proxy": "agents",
788
- directives: "agents",
789
- goals: "agents",
790
- "eliza-classic": "agents",
791
- // Media & Content
792
- vision: "media",
793
- rss: "media",
794
- "gmail-watch": "media",
795
- prose: "media",
796
- form: "media",
797
- // Scheduling & Automation
798
- cron: "automation",
799
- scheduling: "automation",
800
- todo: "automation",
801
- commands: "automation",
802
- // Storage & Logging
803
- "s3-storage": "storage",
804
- "trajectory-logger": "storage",
805
- experience: "storage",
806
- // Gaming & Creative
807
- minecraft: "gaming",
808
- roblox: "gaming",
809
- babylon: "gaming",
810
- mysticism: "gaming",
811
- personality: "gaming",
812
- moltbook: "gaming",
813
- };
814
-
815
- const SUBGROUP_DISPLAY_ORDER = [
816
- "ai-provider",
817
- "connector",
818
- "streaming",
819
- "voice",
820
- "blockchain",
821
- "devtools",
822
- "knowledge",
823
- "agents",
824
- "media",
825
- "automation",
826
- "storage",
827
- "gaming",
828
- "feature-other",
829
- "showcase",
830
- ] as const;
831
-
832
- const SUBGROUP_LABELS: Record<string, string> = {
833
- "ai-provider": "AI Providers",
834
- connector: "Connectors",
835
- voice: "Voice & Audio",
836
- blockchain: "Blockchain & Finance",
837
- devtools: "Dev Tools & Infrastructure",
838
- knowledge: "Knowledge & Memory",
839
- agents: "Agents & Orchestration",
840
- media: "Media & Content",
841
- automation: "Scheduling & Automation",
842
- storage: "Storage & Logging",
843
- gaming: "Gaming & Creative",
844
- "feature-other": "Other Features",
845
- streaming: "Streaming Destinations",
846
- showcase: "Showcase",
847
- };
848
-
849
- const SUBGROUP_NAV_ICONS: Record<string, LucideIcon> = {
850
- all: Package,
851
- "ai-provider": Brain,
852
- connector: MessageCircle,
853
- streaming: Video,
854
- voice: Mic,
855
- blockchain: Wallet,
856
- devtools: Shell,
857
- knowledge: BookOpen,
858
- agents: Target,
859
- media: Eye,
860
- automation: Calendar,
861
- storage: Server,
862
- gaming: Gamepad2,
863
- "feature-other": Puzzle,
864
- showcase: Sparkles,
865
- };
866
-
867
- function subgroupForPlugin(plugin: PluginInfo): string {
868
- if (plugin.id === "__ui-showcase__") return "showcase";
869
- if (plugin.category === "ai-provider") return "ai-provider";
870
- if (plugin.category === "connector") return "connector";
871
- if (plugin.category === "streaming") return "streaming";
872
- return FEATURE_SUBGROUP[plugin.id] ?? "feature-other";
873
- }
874
-
875
- type StatusFilter = "all" | "enabled" | "disabled";
876
- type PluginsViewMode = "all" | "connectors" | "streaming" | "social";
877
- type SubgroupTag = { id: string; label: string; count: number };
878
-
879
- function comparePlugins(left: PluginInfo, right: PluginInfo): number {
880
- if (left.enabled !== right.enabled) return left.enabled ? -1 : 1;
881
- if (left.enabled && right.enabled) {
882
- const leftNeedsConfig =
883
- left.parameters?.some(
884
- (param: PluginParamDef) => param.required && !param.isSet,
885
- ) ?? false;
886
- const rightNeedsConfig =
887
- right.parameters?.some(
888
- (param: PluginParamDef) => param.required && !param.isSet,
889
- ) ?? false;
890
- if (leftNeedsConfig !== rightNeedsConfig) {
891
- return leftNeedsConfig ? -1 : 1;
892
- }
893
- }
894
- return (left.name ?? "").localeCompare(right.name ?? "");
895
- }
896
-
897
- function matchesPluginFilters(
898
- plugin: PluginInfo,
899
- searchLower: string,
900
- statusFilter: StatusFilter,
901
- ): boolean {
902
- const matchesStatus =
903
- statusFilter === "all" ||
904
- (statusFilter === "enabled" && plugin.enabled) ||
905
- (statusFilter === "disabled" && !plugin.enabled);
906
- const matchesSearch =
907
- !searchLower ||
908
- (plugin.name ?? "").toLowerCase().includes(searchLower) ||
909
- (plugin.description ?? "").toLowerCase().includes(searchLower) ||
910
- (plugin.tags ?? []).some((tag) =>
911
- (tag ?? "").toLowerCase().includes(searchLower),
912
- ) ||
913
- plugin.id.toLowerCase().includes(searchLower);
914
- return matchesStatus && matchesSearch;
915
- }
916
-
917
- function sortPlugins(
918
- filteredPlugins: PluginInfo[],
919
- pluginOrder: string[],
920
- allowCustomOrder: boolean,
921
- ): PluginInfo[] {
922
- if (!allowCustomOrder || pluginOrder.length === 0) {
923
- return [...filteredPlugins].sort(comparePlugins);
924
- }
925
-
926
- const orderMap = new Map(pluginOrder.map((id, index) => [id, index]));
927
- return [...filteredPlugins].sort((left, right) => {
928
- const leftIndex = orderMap.get(left.id);
929
- const rightIndex = orderMap.get(right.id);
930
- if (leftIndex != null && rightIndex != null) return leftIndex - rightIndex;
931
- if (leftIndex != null) return -1;
932
- if (rightIndex != null) return 1;
933
- return comparePlugins(left, right);
934
- });
935
- }
936
-
937
- function buildPluginListState(options: {
938
- allowCustomOrder: boolean;
939
- effectiveSearch: string;
940
- effectiveStatusFilter: StatusFilter;
941
- isConnectorLikeMode: boolean;
942
- mode: PluginsViewMode;
943
- pluginOrder: string[];
944
- plugins: PluginInfo[];
945
- showSubgroupFilters: boolean;
946
- subgroupFilter: string;
947
- }): {
948
- categoryPlugins: PluginInfo[];
949
- enabledCount: number;
950
- nonDbPlugins: PluginInfo[];
951
- sorted: PluginInfo[];
952
- subgroupTags: SubgroupTag[];
953
- visiblePlugins: PluginInfo[];
954
- } {
955
- const {
956
- allowCustomOrder,
957
- effectiveSearch,
958
- effectiveStatusFilter,
959
- isConnectorLikeMode,
960
- mode,
961
- pluginOrder,
962
- plugins,
963
- showSubgroupFilters,
964
- subgroupFilter,
965
- } = options;
966
- const categoryPlugins = plugins.filter(
967
- (plugin) =>
968
- plugin.category !== "database" &&
969
- !ALWAYS_ON_PLUGIN_IDS.has(plugin.id) &&
970
- (!isConnectorLikeMode || plugin.category === "connector") &&
971
- (mode !== "streaming" || plugin.category === "streaming"),
972
- );
973
- const nonDbPlugins = [SHOWCASE_PLUGIN, ...categoryPlugins];
974
- const searchLower = effectiveSearch.toLowerCase();
975
- const sorted = sortPlugins(
976
- categoryPlugins.filter((plugin) =>
977
- matchesPluginFilters(plugin, searchLower, effectiveStatusFilter),
978
- ),
979
- pluginOrder,
980
- allowCustomOrder,
981
- );
982
- const enabledCount = categoryPlugins.filter(
983
- (plugin) => plugin.enabled,
984
- ).length;
985
-
986
- const subgroupCounts: Record<string, number> = {};
987
- const visiblePlugins: PluginInfo[] = [];
988
- for (const plugin of sorted) {
989
- const subgroup = subgroupForPlugin(plugin);
990
- subgroupCounts[subgroup] = (subgroupCounts[subgroup] ?? 0) + 1;
991
- if (
992
- !showSubgroupFilters ||
993
- subgroupFilter === "all" ||
994
- subgroup === subgroupFilter
995
- ) {
996
- visiblePlugins.push(plugin);
997
- }
998
- }
999
-
1000
- const subgroupTags = [
1001
- { id: "all", label: "All", count: sorted.length },
1002
- ...SUBGROUP_DISPLAY_ORDER.filter(
1003
- (subgroupId) => (subgroupCounts[subgroupId] ?? 0) > 0,
1004
- ).map((subgroupId) => ({
1005
- id: subgroupId,
1006
- label: SUBGROUP_LABELS[subgroupId],
1007
- count: subgroupCounts[subgroupId] ?? 0,
1008
- })),
1009
- ];
1010
-
1011
- return {
1012
- categoryPlugins,
1013
- enabledCount,
1014
- nonDbPlugins,
1015
- sorted,
1016
- subgroupTags,
1017
- visiblePlugins,
1018
- };
1019
- }
1020
-
1021
- /* ── Shared PluginListView ─────────────────────────────────────────── */
1022
-
1023
- interface PluginListViewProps {
1024
- /** Label used in search placeholder and empty state messages. */
1025
- label: string;
1026
- /** Optional list mode for pre-filtered views like Connectors. */
1027
- mode?: PluginsViewMode;
1028
- /** Whether the view is rendered in a full-screen gamified modal. */
1029
- inModal?: boolean;
1030
- }
1031
-
1032
- function PluginListView({ label, mode = "all", inModal }: PluginListViewProps) {
1033
- const {
1034
- plugins,
1035
- pluginStatusFilter,
1036
- pluginSearch,
1037
- pluginSettingsOpen,
1038
- pluginSaving,
1039
- pluginSaveSuccess,
1040
- loadPlugins,
1041
- handlePluginToggle,
1042
- handlePluginConfigSave,
1043
- setActionNotice,
1044
- setState,
1045
- t,
1046
- } = useApp();
1047
-
1048
- const [pluginConfigs, setPluginConfigs] = useState<
1049
- Record<string, Record<string, string>>
1050
- >({});
1051
- const [testResults, setTestResults] = useState<
1052
- Map<
1053
- string,
1054
- {
1055
- success: boolean;
1056
- message?: string;
1057
- error?: string;
1058
- durationMs: number;
1059
- loading: boolean;
1060
- }
1061
- >
1062
- >(new Map());
1063
- const [addDirOpen, setAddDirOpen] = useState(false);
1064
- const [addDirPath, setAddDirPath] = useState("");
1065
- const [addDirLoading, setAddDirLoading] = useState(false);
1066
- const [installingPlugins, setInstallingPlugins] = useState<Set<string>>(
1067
- new Set(),
1068
- );
1069
- const [installProgress, setInstallProgress] = useState<
1070
- Map<string, { phase: string; message: string }>
1071
- >(new Map());
1072
- const [togglingPlugins, setTogglingPlugins] = useState<Set<string>>(
1073
- new Set(),
1074
- );
1075
- const hasPluginToggleInFlight = togglingPlugins.size > 0;
1076
-
1077
- // ── Drag-to-reorder state ────────────────────────────────────────
1078
- const [pluginOrder, setPluginOrder] = useState<string[]>(() => {
1079
- try {
1080
- const stored = localStorage.getItem("pluginOrder");
1081
- return stored ? JSON.parse(stored) : [];
1082
- } catch {
1083
- return [];
1084
- }
1085
- });
1086
- const [draggingId, setDraggingId] = useState<string | null>(null);
1087
- const [dragOverId, setDragOverId] = useState<string | null>(null);
1088
- const dragRef = useRef<string | null>(null);
1089
- const isSocialMode = mode === "social";
1090
- const isConnectorLikeMode = mode === "connectors" || mode === "social";
1091
- const resultLabel = isSocialMode ? "connectors" : label.toLowerCase();
1092
- const searchPlaceholder = isSocialMode
1093
- ? "Search..."
1094
- : `Search ${label.toLowerCase()}...`;
1095
- const effectiveStatusFilter: StatusFilter =
1096
- isSocialMode && pluginStatusFilter === "disabled"
1097
- ? "all"
1098
- : pluginStatusFilter;
1099
- const effectiveSearch = pluginSearch;
1100
- const showToolbar = true;
1101
- const allowCustomOrder = !isSocialMode;
1102
- const showPluginManagementActions = !isSocialMode;
1103
-
1104
- // Load plugins on mount
1105
- useEffect(() => {
1106
- void loadPlugins();
1107
- }, [loadPlugins]);
1108
-
1109
- // Listen for install progress events via WebSocket
1110
- useEffect(() => {
1111
- const unbind = client.onWsEvent(
1112
- "install-progress",
1113
- (data: Record<string, unknown>) => {
1114
- const pluginName = data.pluginName as string;
1115
- const phase = data.phase as string;
1116
- const message = data.message as string;
1117
- if (!pluginName) return;
1118
- if (phase === "complete" || phase === "error") {
1119
- setInstallProgress((prev) => {
1120
- const next = new Map(prev);
1121
- next.delete(pluginName);
1122
- return next;
1123
- });
1124
- } else {
1125
- setInstallProgress((prev) =>
1126
- new Map(prev).set(pluginName, { phase, message }),
1127
- );
1128
- }
1129
- },
1130
- );
1131
- return unbind;
1132
- }, []);
1133
-
1134
- // Persist custom order
1135
- useEffect(() => {
1136
- if (pluginOrder.length > 0) {
1137
- localStorage.setItem("pluginOrder", JSON.stringify(pluginOrder));
1138
- }
1139
- }, [pluginOrder]);
1140
-
1141
- const [subgroupFilter, setSubgroupFilter] = useState<string>("all");
1142
- const showSubgroupFilters =
1143
- mode !== "connectors" && mode !== "streaming" && mode !== "social";
1144
- const showDesktopSubgroupSidebar = showSubgroupFilters;
1145
- const {
1146
- categoryPlugins,
1147
- enabledCount,
1148
- nonDbPlugins,
1149
- sorted,
1150
- subgroupTags,
1151
- visiblePlugins,
1152
- } = useMemo(
1153
- () =>
1154
- buildPluginListState({
1155
- allowCustomOrder,
1156
- effectiveSearch,
1157
- effectiveStatusFilter,
1158
- isConnectorLikeMode,
1159
- mode,
1160
- pluginOrder,
1161
- plugins,
1162
- showSubgroupFilters,
1163
- subgroupFilter,
1164
- }),
1165
- [
1166
- allowCustomOrder,
1167
- effectiveSearch,
1168
- effectiveStatusFilter,
1169
- isConnectorLikeMode,
1170
- mode,
1171
- pluginOrder,
1172
- plugins,
1173
- showSubgroupFilters,
1174
- subgroupFilter,
1175
- ],
1176
- );
1177
-
1178
- useEffect(() => {
1179
- if (!showSubgroupFilters) return;
1180
- if (subgroupFilter === "all") return;
1181
- if (!subgroupTags.some((tag) => tag.id === subgroupFilter)) {
1182
- setSubgroupFilter("all");
1183
- }
1184
- }, [showSubgroupFilters, subgroupFilter, subgroupTags]);
1185
-
1186
- const renderSubgroupFilterButton = useCallback(
1187
- (
1188
- tag: { id: string; label: string; count: number },
1189
- options?: { sidebar?: boolean },
1190
- ) => {
1191
- const isActive = subgroupFilter === tag.id;
1192
- if (options?.sidebar) {
1193
- const Icon = SUBGROUP_NAV_ICONS[tag.id] ?? Package;
1194
- return (
1195
- <button
1196
- key={tag.id}
1197
- type="button"
1198
- onClick={() => setSubgroupFilter(tag.id)}
1199
- aria-current={isActive ? "page" : undefined}
1200
- className={`flex w-full items-center gap-3 rounded-2xl border px-4 py-3 text-left transition-all duration-200 ${
1201
- isActive
1202
- ? "border-accent/40 bg-accent/12 text-txt shadow-[0_10px_30px_rgba(var(--accent),0.08)]"
1203
- : "border-transparent text-muted hover:border-border/60 hover:bg-card/55 hover:text-txt"
1204
- }`}
1205
- >
1206
- <span
1207
- className={`flex h-10 w-10 shrink-0 items-center justify-center rounded-xl border ${
1208
- isActive
1209
- ? "border-accent/30 bg-accent/18 text-txt-strong"
1210
- : "border-border/50 bg-bg-accent/80 text-muted"
1211
- }`}
1212
- >
1213
- <Icon className="w-4 h-4" />
1214
- </span>
1215
- <span className="min-w-0 flex-1">
1216
- <span className="block text-sm font-semibold leading-snug text-current">
1217
- {tag.label}
1218
- </span>
1219
- </span>
1220
- <span
1221
- className={`rounded-full border px-2 py-0.5 text-[10px] font-mono leading-none ${
1222
- isActive
1223
- ? "border-accent/20 bg-accent/20 text-txt"
1224
- : "border-border/50 bg-black/10 text-muted"
1225
- }`}
1226
- >
1227
- {tag.count}
1228
- </span>
1229
- </button>
1230
- );
1231
- }
1232
-
1233
- return (
1234
- <Button
1235
- key={tag.id}
1236
- variant={isActive ? "default" : "outline"}
1237
- size="sm"
1238
- className={`h-7 px-3 text-[11px] font-bold tracking-wide rounded-lg transition-all ${
1239
- isActive
1240
- ? "shadow-[0_0_10px_rgba(var(--accent),0.2)] border-accent"
1241
- : "bg-card/40 backdrop-blur-sm border-border/40 text-muted hover:text-txt shadow-sm hover:border-accent/30"
1242
- }`}
1243
- onClick={() => setSubgroupFilter(tag.id)}
1244
- >
1245
- {tag.label}
1246
- <span
1247
- className={`ml-1.5 px-1.5 py-0.5 rounded border text-[9px] font-mono leading-none ${isActive ? "bg-black/20 border-black/10" : "bg-black/10 border-white/5"}`}
1248
- >
1249
- {tag.count}
1250
- </span>
1251
- </Button>
1252
- );
1253
- },
1254
- [subgroupFilter],
1255
- );
1256
-
1257
- // ── Handlers ───────────────────────────────────────────────────────
1258
-
1259
- const toggleSettings = (pluginId: string) => {
1260
- const next = new Set<string>();
1261
- if (!pluginSettingsOpen.has(pluginId)) next.add(pluginId);
1262
- setState("pluginSettingsOpen", next);
1263
- };
1264
-
1265
- const handleParamChange = (
1266
- pluginId: string,
1267
- paramKey: string,
1268
- value: string,
1269
- ) => {
1270
- setPluginConfigs((prev) => ({
1271
- ...prev,
1272
- [pluginId]: { ...prev[pluginId], [paramKey]: value },
1273
- }));
1274
- };
1275
-
1276
- const handleConfigSave = async (pluginId: string) => {
1277
- // Showcase plugin: no-op save (it's not a real plugin)
1278
- if (pluginId === "__ui-showcase__") return;
1279
- const config = pluginConfigs[pluginId] ?? {};
1280
- await handlePluginConfigSave(pluginId, config);
1281
- setPluginConfigs((prev) => {
1282
- const next = { ...prev };
1283
- delete next[pluginId];
1284
- return next;
1285
- });
1286
- };
1287
-
1288
- const handleConfigReset = (pluginId: string) => {
1289
- setPluginConfigs((prev) => {
1290
- const next = { ...prev };
1291
- delete next[pluginId];
1292
- return next;
1293
- });
1294
- };
1295
-
1296
- const handleTestConnection = async (pluginId: string) => {
1297
- setTestResults((prev) => {
1298
- const next = new Map(prev);
1299
- next.set(pluginId, { success: false, loading: true, durationMs: 0 });
1300
- return next;
1301
- });
1302
- try {
1303
- const result = await client.testPluginConnection(pluginId);
1304
- setTestResults((prev) => {
1305
- const next = new Map(prev);
1306
- next.set(pluginId, { ...result, loading: false });
1307
- return next;
1308
- });
1309
- } catch (err) {
1310
- setTestResults((prev) => {
1311
- const next = new Map(prev);
1312
- next.set(pluginId, {
1313
- success: false,
1314
- error: err instanceof Error ? err.message : String(err),
1315
- loading: false,
1316
- durationMs: 0,
1317
- });
1318
- return next;
1319
- });
1320
- }
1321
- };
1322
-
1323
- const handleInstallPlugin = async (pluginId: string, npmName: string) => {
1324
- setInstallingPlugins((prev) => new Set(prev).add(pluginId));
1325
- try {
1326
- await client.installRegistryPlugin(npmName);
1327
- await loadPlugins();
1328
- setActionNotice(
1329
- `${npmName} installed. Restart required to activate.`,
1330
- "success",
1331
- );
1332
- } catch (err) {
1333
- setActionNotice(
1334
- `Failed to install ${npmName}: ${err instanceof Error ? err.message : "unknown error"}`,
1335
- "error",
1336
- 3800,
1337
- );
1338
- // Still try to refresh in case install succeeded but restart failed
1339
- try {
1340
- await loadPlugins();
1341
- } catch {
1342
- /* ignore */
1343
- }
1344
- } finally {
1345
- setInstallingPlugins((prev) => {
1346
- const next = new Set(prev);
1347
- next.delete(pluginId);
1348
- return next;
1349
- });
1350
- }
1351
- };
1352
-
1353
- const handleTogglePlugin = useCallback(
1354
- async (pluginId: string, enabled: boolean) => {
1355
- let shouldStart = false;
1356
- setTogglingPlugins((prev) => {
1357
- if (prev.has(pluginId) || prev.size > 0) return prev;
1358
- shouldStart = true;
1359
- return new Set(prev).add(pluginId);
1360
- });
1361
- if (!shouldStart) return;
1362
-
1363
- try {
1364
- await handlePluginToggle(pluginId, enabled);
1365
- } finally {
1366
- setTogglingPlugins((prev) => {
1367
- const next = new Set(prev);
1368
- next.delete(pluginId);
1369
- return next;
1370
- });
1371
- }
1372
- },
1373
- [handlePluginToggle],
1374
- );
1375
-
1376
- const handleOpenPluginExternalUrl = useCallback(
1377
- async (url: string) => {
1378
- try {
1379
- await openExternalUrl(url);
1380
- } catch (err) {
1381
- setActionNotice(
1382
- err instanceof Error ? err.message : "Failed to open external link.",
1383
- "error",
1384
- 4200,
1385
- );
1386
- }
1387
- },
1388
- [setActionNotice],
1389
- );
1390
-
1391
- // ── Add from directory ──────────────────────────────────────────────
1392
-
1393
- const handleAddFromDirectory = async () => {
1394
- const trimmed = addDirPath.trim();
1395
- if (!trimmed) return;
1396
- setAddDirLoading(true);
1397
- try {
1398
- await client.installRegistryPlugin(trimmed);
1399
- await loadPlugins();
1400
- setAddDirPath("");
1401
- setAddDirOpen(false);
1402
- setActionNotice(`Plugin installed from ${trimmed}`, "success");
1403
- } catch (err) {
1404
- setActionNotice(
1405
- `Failed to add plugin: ${err instanceof Error ? err.message : "unknown error"}`,
1406
- "error",
1407
- 3800,
1408
- );
1409
- }
1410
- setAddDirLoading(false);
1411
- };
1412
-
1413
- // ── Drag-to-reorder handlers ─────────────────────────────────────
1414
-
1415
- const handleDragStart = useCallback(
1416
- (e: React.DragEvent, pluginId: string) => {
1417
- dragRef.current = pluginId;
1418
- setDraggingId(pluginId);
1419
- e.dataTransfer.effectAllowed = "move";
1420
- e.dataTransfer.setData("text/plain", pluginId);
1421
- },
1422
- [],
1423
- );
1424
-
1425
- const handleDragOver = useCallback((e: React.DragEvent, pluginId: string) => {
1426
- e.preventDefault();
1427
- e.dataTransfer.dropEffect = "move";
1428
- if (dragRef.current && dragRef.current !== pluginId) {
1429
- setDragOverId(pluginId);
1430
- }
1431
- }, []);
1432
-
1433
- const handleDrop = useCallback(
1434
- (e: React.DragEvent, targetId: string) => {
1435
- e.preventDefault();
1436
- const srcId = dragRef.current;
1437
- if (!srcId || srcId === targetId) {
1438
- dragRef.current = null;
1439
- setDraggingId(null);
1440
- setDragOverId(null);
1441
- return;
1442
- }
1443
- // Materialize current sorted order, then splice
1444
- if (!allowCustomOrder) return;
1445
- setPluginOrder(() => {
1446
- // Build full order: items in custom order first, then any new ones
1447
- const allIds = nonDbPlugins.map((p: PluginInfo) => p.id);
1448
- let ids: string[];
1449
- if (pluginOrder.length > 0) {
1450
- const known = new Set(pluginOrder);
1451
- ids = [...pluginOrder, ...allIds.filter((id) => !known.has(id))];
1452
- } else {
1453
- ids = sorted.map((p: PluginInfo) => p.id);
1454
- // Pad with any nonDbPlugins not currently in sorted (due to filters)
1455
- const inSorted = new Set(ids);
1456
- for (const id of allIds) {
1457
- if (!inSorted.has(id)) ids.push(id);
1458
- }
1459
- }
1460
- const fromIdx = ids.indexOf(srcId);
1461
- const toIdx = ids.indexOf(targetId);
1462
- if (fromIdx === -1 || toIdx === -1) return ids;
1463
- ids.splice(fromIdx, 1);
1464
- ids.splice(toIdx, 0, srcId);
1465
- return ids;
1466
- });
1467
- dragRef.current = null;
1468
- setDraggingId(null);
1469
- setDragOverId(null);
1470
- },
1471
- [allowCustomOrder, nonDbPlugins, pluginOrder, sorted],
1472
- );
1473
-
1474
- const handleDragEnd = useCallback(() => {
1475
- dragRef.current = null;
1476
- setDraggingId(null);
1477
- setDragOverId(null);
1478
- }, []);
1479
-
1480
- const handleResetOrder = useCallback(() => {
1481
- setPluginOrder([]);
1482
- localStorage.removeItem("pluginOrder");
1483
- }, []);
1484
-
1485
- const renderResolvedIcon = useCallback(
1486
- (
1487
- plugin: PluginInfo,
1488
- options?: {
1489
- className?: string;
1490
- emojiClassName?: string;
1491
- },
1492
- ) => {
1493
- const icon = resolveIcon(plugin);
1494
- if (!icon) {
1495
- return <span className={options?.emojiClassName ?? "text-sm"}>🧩</span>;
1496
- }
1497
- if (typeof icon === "string") {
1498
- const imageSrc = iconImageSource(icon);
1499
- return imageSrc ? (
1500
- <img
1501
- src={imageSrc}
1502
- alt=""
1503
- className={
1504
- options?.className ?? "w-5 h-5 rounded-sm object-contain"
1505
- }
1506
- onError={(e) => {
1507
- (e.currentTarget as HTMLImageElement).style.display = "none";
1508
- }}
1509
- />
1510
- ) : (
1511
- <span className={options?.emojiClassName ?? "text-sm"}>{icon}</span>
1512
- );
1513
- }
1514
- const IconComponent = icon;
1515
- return <IconComponent className={options?.className ?? "w-5 h-5"} />;
1516
- },
1517
- [],
1518
- );
1519
-
1520
- // ── Card renderers ────────────────────────────────────────────────
1521
-
1522
- const renderPluginCard = (p: PluginInfo) => {
1523
- const hasParams = p.parameters && p.parameters.length > 0;
1524
- const isOpen = pluginSettingsOpen.has(p.id);
1525
- const setCount = hasParams
1526
- ? p.parameters.filter((param: PluginParamDef) => param.isSet).length
1527
- : 0;
1528
- const totalCount = hasParams ? p.parameters.length : 0;
1529
- const allParamsSet = !hasParams || setCount === totalCount;
1530
- const isShowcase = p.id === "__ui-showcase__";
1531
- const categoryLabel = isShowcase
1532
- ? "showcase"
1533
- : p.category === "ai-provider"
1534
- ? "ai provider"
1535
- : p.category;
1536
-
1537
- const enabledBorder = isShowcase
1538
- ? "border-l-[3px] border-l-accent"
1539
- : p.enabled
1540
- ? !allParamsSet && hasParams
1541
- ? "border-l-[3px] border-l-warn"
1542
- : "border-l-[3px] border-l-accent"
1543
- : "";
1544
- const isToggleBusy = togglingPlugins.has(p.id);
1545
- const toggleDisabled =
1546
- isToggleBusy || (hasPluginToggleInFlight && !isToggleBusy);
1547
-
1548
- const isDragging = draggingId === p.id;
1549
- const isDragOver = dragOverId === p.id && draggingId !== p.id;
1550
- const pluginLinks = getPluginResourceLinks(p);
1551
-
1552
- return (
1553
- <li
1554
- key={p.id}
1555
- draggable={allowCustomOrder}
1556
- onDragStart={
1557
- allowCustomOrder ? (e) => handleDragStart(e, p.id) : undefined
1558
- }
1559
- onDragOver={
1560
- allowCustomOrder ? (e) => handleDragOver(e, p.id) : undefined
1561
- }
1562
- onDrop={allowCustomOrder ? (e) => handleDrop(e, p.id) : undefined}
1563
- onDragEnd={allowCustomOrder ? handleDragEnd : undefined}
1564
- className={`border border-border bg-card transition-colors duration-150 flex flex-col ${enabledBorder} ${
1565
- isOpen ? "ring-1 ring-accent" : "hover:border-accent/40"
1566
- } ${isDragging ? "opacity-30" : ""} ${isDragOver ? "ring-2 ring-accent/60" : ""}`}
1567
- data-plugin-id={p.id}
1568
- >
1569
- {/* Top: drag handle + icon + name + toggle */}
1570
- <div className="flex items-center gap-2 px-3 pt-3 pb-1">
1571
- {allowCustomOrder && (
1572
- <span
1573
- className="text-[10px] text-muted opacity-30 hover:opacity-70 cursor-grab active:cursor-grabbing shrink-0 select-none leading-none"
1574
- title={t("pluginsview.DragToReorder")}
1575
- >
1576
- {t("pluginsview.X2807")}
1577
- </span>
1578
- )}
1579
- <span className="font-bold text-sm flex items-center gap-1.5 min-w-0 truncate flex-1">
1580
- {(() => {
1581
- const icon = resolveIcon(p);
1582
- if (!icon) return null;
1583
- if (typeof icon === "string") {
1584
- const imageSrc = iconImageSource(icon);
1585
- return imageSrc ? (
1586
- <img
1587
- src={imageSrc}
1588
- alt=""
1589
- className="w-5 h-5 rounded-sm object-contain"
1590
- onError={(e) => {
1591
- (e.currentTarget as HTMLImageElement).style.display =
1592
- "none";
1593
- }}
1594
- />
1595
- ) : (
1596
- <span className="text-sm">{icon}</span>
1597
- );
1598
- }
1599
- const IconComponent = icon;
1600
- return <IconComponent className="w-5 h-5" />;
1601
- })()}
1602
- {p.name}
1603
- </span>
1604
- {isShowcase ? (
1605
- <span className="text-[10px] font-bold tracking-wider px-2.5 py-[2px] border border-accent text-txt bg-accent-subtle shrink-0">
1606
- {t("pluginsview.DEMO")}
1607
- </span>
1608
- ) : (
1609
- <button
1610
- type="button"
1611
- data-plugin-toggle={p.id}
1612
- className={`text-[10px] font-bold tracking-wider px-2.5 py-[2px] border transition-colors duration-150 shrink-0 ${
1613
- p.enabled
1614
- ? "bg-accent text-accent-fg border-accent"
1615
- : "bg-transparent text-muted border-border hover:text-txt"
1616
- } ${
1617
- toggleDisabled
1618
- ? "opacity-60 cursor-not-allowed"
1619
- : "cursor-pointer"
1620
- }`}
1621
- onClick={(e) => {
1622
- e.stopPropagation();
1623
- void handleTogglePlugin(p.id, !p.enabled);
1624
- }}
1625
- disabled={toggleDisabled}
1626
- >
1627
- {isToggleBusy ? "APPLYING" : p.enabled ? "ON" : "OFF"}
1628
- </button>
1629
- )}
1630
- </div>
1631
-
1632
- {/* Badges: category + version + loaded status */}
1633
- <div className="flex items-center gap-1.5 px-3 pb-1.5">
1634
- <span className="text-[10px] px-1.5 py-px border border-border bg-surface text-muted lowercase tracking-wide whitespace-nowrap">
1635
- {categoryLabel}
1636
- </span>
1637
- {p.version && (
1638
- <span className="text-[10px] font-mono text-muted opacity-70">
1639
- v{p.version}
1640
- </span>
1641
- )}
1642
- {p.enabled && !p.isActive && !isShowcase && (
1643
- <span
1644
- className={`text-[10px] px-1.5 py-px border lowercase tracking-wide whitespace-nowrap ${
1645
- p.loadError
1646
- ? "border-destructive bg-[rgba(153,27,27,0.04)] text-destructive"
1647
- : "border-warn bg-[rgba(234,179,8,0.06)] text-warn"
1648
- }`}
1649
- title={
1650
- p.loadError || "Plugin is enabled but not loaded in the runtime"
1651
- }
1652
- >
1653
- {p.loadError ? "load failed" : "not installed"}
1654
- </span>
1655
- )}
1656
- {isToggleBusy && (
1657
- <span className="text-[10px] px-1.5 py-px border border-accent bg-accent-subtle text-txt lowercase tracking-wide whitespace-nowrap">
1658
- {t("pluginsview.restarting")}
1659
- </span>
1660
- )}
1661
- </div>
1662
-
1663
- {/* Description — clamped to 3 lines */}
1664
- <p
1665
- className="text-xs text-muted px-3 pb-2 flex-1"
1666
- style={{
1667
- display: "-webkit-box",
1668
- WebkitLineClamp: 3,
1669
- WebkitBoxOrient: "vertical",
1670
- overflow: "hidden",
1671
- }}
1672
- >
1673
- {p.description || "No description available"}
1674
- </p>
1675
-
1676
- {(p.tags?.length ?? 0) > 0 && (
1677
- <div className="flex flex-wrap gap-1.5 px-3 pb-2">
1678
- {p.tags?.slice(0, 4).map((tag) => (
1679
- <span
1680
- key={`${p.id}:${tag}`}
1681
- className="text-[10px] px-1.5 py-px border border-border/50 bg-black/10 text-muted lowercase tracking-wide whitespace-nowrap"
1682
- >
1683
- {tag}
1684
- </span>
1685
- ))}
1686
- </div>
1687
- )}
1688
-
1689
- {pluginLinks.length > 0 && (
1690
- <div className="flex flex-wrap gap-2 px-3 pb-2">
1691
- {pluginLinks.map((link) => (
1692
- <Button
1693
- key={`${p.id}:${link.key}`}
1694
- variant="outline"
1695
- size="sm"
1696
- className="h-6 px-2 text-[10px] font-bold border-border/40 text-muted hover:text-txt hover:border-accent hover:bg-accent/5 backdrop-blur-sm transition-all"
1697
- onClick={(e) => {
1698
- e.stopPropagation();
1699
- void handleOpenPluginExternalUrl(link.url);
1700
- }}
1701
- title={`${link.label}: ${link.url}`}
1702
- >
1703
- {link.label}
1704
- </Button>
1705
- ))}
1706
- </div>
1707
- )}
1708
-
1709
- {/* Bottom bar: config status + settings button */}
1710
- <div className="flex items-center gap-3 px-4 py-3 border-t border-border/40 mt-auto bg-black/5">
1711
- {hasParams && !isShowcase ? (
1712
- <>
1713
- <span
1714
- className={`inline-block w-2 h-2 rounded-full shadow-[0_0_10px_currentColor] shrink-0 ${
1715
- allParamsSet
1716
- ? "bg-ok text-ok"
1717
- : "bg-destructive text-destructive"
1718
- }`}
1719
- />
1720
- <span className="text-[11px] font-bold tracking-wide text-muted">
1721
- {setCount}/{totalCount} {t("pluginsview.configured")}
1722
- </span>
1723
- </>
1724
- ) : !hasParams && !isShowcase ? (
1725
- <span className="text-[11px] font-bold tracking-wide text-muted/60">
1726
- {t("pluginsview.NoConfigNeeded")}
1727
- </span>
1728
- ) : (
1729
- <span className="text-[11px] font-bold tracking-wide text-muted/60">
1730
- {t("pluginsview.23FieldDemos")}
1731
- </span>
1732
- )}
1733
- <div className="flex-1" />
1734
- {p.enabled &&
1735
- !p.isActive &&
1736
- p.npmName &&
1737
- !isShowcase &&
1738
- !p.loadError && (
1739
- <Button
1740
- variant="default"
1741
- size="sm"
1742
- className="h-7 px-3 text-[10px] font-bold tracking-wide shadow-sm max-w-[140px] truncate"
1743
- disabled={installingPlugins.has(p.id)}
1744
- onClick={(e) => {
1745
- e.stopPropagation();
1746
- handleInstallPlugin(p.id, p.npmName ?? "");
1747
- }}
1748
- >
1749
- {installingPlugins.has(p.id)
1750
- ? installProgress.get(p.npmName ?? "")?.message ||
1751
- "Installing..."
1752
- : "Install"}
1753
- </Button>
1754
- )}
1755
- {hasParams && (
1756
- <Button
1757
- variant="ghost"
1758
- size="sm"
1759
- className={`h-7 px-2.5 text-[11px] font-bold transition-all flex items-center gap-1.5 ${
1760
- isOpen
1761
- ? "text-txt bg-accent/10 hover:bg-accent/20"
1762
- : "text-muted hover:text-txt hover:bg-white/5"
1763
- }`}
1764
- onClick={(e) => {
1765
- e.stopPropagation();
1766
- toggleSettings(p.id);
1767
- }}
1768
- title={t("pluginsview.Settings")}
1769
- >
1770
- <span className="text-[14px] leading-none">&#9881;</span>
1771
- <span
1772
- className={`inline-block text-[10px] transition-transform duration-200 ${isOpen ? "rotate-90" : ""}`}
1773
- >
1774
- &#9654;
1775
- </span>
1776
- </Button>
1777
- )}
1778
- </div>
1779
-
1780
- {/* Validation errors */}
1781
- {p.enabled && p.validationErrors && p.validationErrors.length > 0 && (
1782
- <div className="px-3 py-1.5 border-t border-destructive bg-[rgba(153,27,27,0.04)] text-xs">
1783
- {p.validationErrors.map(
1784
- (err: { field: string; message: string }) => (
1785
- <div
1786
- key={`${err.field}:${err.message}`}
1787
- className="text-destructive mb-0.5 text-[10px]"
1788
- >
1789
- {err.field}: {err.message}
1790
- </div>
1791
- ),
1792
- )}
1793
- </div>
1794
- )}
1795
-
1796
- {/* Validation warnings */}
1797
- {p.enabled &&
1798
- p.validationWarnings &&
1799
- p.validationWarnings.length > 0 && (
1800
- <div className="px-3 py-1">
1801
- {p.validationWarnings.map(
1802
- (w: { field: string; message: string }) => (
1803
- <div
1804
- key={`${w.field}:${w.message}`}
1805
- className="text-warn text-[10px]"
1806
- >
1807
- {w.message}
1808
- </div>
1809
- ),
1810
- )}
1811
- </div>
1812
- )}
1813
- </li>
1814
- );
1815
- };
1816
-
1817
- /** Render a grid of plugin cards. */
1818
- const renderPluginGrid = (plugins: PluginInfo[]) => (
1819
- <ul className="grid grid-cols-[repeat(auto-fill,minmax(260px,1fr))] gap-3 m-0 p-0 list-none">
1820
- {plugins.map((p: PluginInfo) => renderPluginCard(p))}
1821
- </ul>
1822
- );
1823
-
1824
- // Resolve the plugin whose settings dialog is currently open.
1825
- // Exclude ai-provider plugins — those are configured in Settings.
1826
- const settingsDialogPlugin =
1827
- Array.from(pluginSettingsOpen)
1828
- .map((id) => nonDbPlugins.find((plugin) => plugin.id === id) ?? null)
1829
- .find((plugin) => (plugin?.parameters?.length ?? 0) > 0) ?? null;
1830
-
1831
- // ── Game-modal state ──────────────────────────────────────────────
1832
- const [gameSelectedId, setGameSelectedId] = useState<string | null>(null);
1833
- const [gameMobileDetail, setGameMobileDetail] = useState(false);
1834
- const gameNarrow =
1835
- typeof window !== "undefined" && typeof window.matchMedia === "function"
1836
- ? window.matchMedia("(max-width: 600px)").matches
1837
- : false;
1838
- const [connectorExpandedIds, setConnectorExpandedIds] = useState<Set<string>>(
1839
- () => new Set(),
1840
- );
1841
- const [connectorSelectedId, setConnectorSelectedId] = useState<string | null>(
1842
- null,
1843
- );
1844
- const [desktopConnectorLayout, setDesktopConnectorLayout] = useState(() =>
1845
- typeof window !== "undefined" && typeof window.matchMedia === "function"
1846
- ? window.matchMedia("(min-width: 1024px)").matches
1847
- : false,
1848
- );
1849
- const connectorSectionRefs = useRef<Record<string, HTMLElement | null>>({});
1850
-
1851
- // Auto-select first visible plugin in game modal
1852
- const gameVisiblePlugins = visiblePlugins.filter(
1853
- (p: PluginInfo) => p.id !== "__ui-showcase__",
1854
- );
1855
- const effectiveGameSelected = gameVisiblePlugins.find(
1856
- (p: PluginInfo) => p.id === gameSelectedId,
1857
- )
1858
- ? gameSelectedId
1859
- : (gameVisiblePlugins[0]?.id ?? null);
1860
- const selectedPlugin =
1861
- gameVisiblePlugins.find(
1862
- (p: PluginInfo) => p.id === effectiveGameSelected,
1863
- ) ?? null;
1864
- const selectedPluginLinks = selectedPlugin
1865
- ? getPluginResourceLinks(selectedPlugin)
1866
- : [];
1867
-
1868
- useEffect(() => {
1869
- if (!isSocialMode || !inModal) return;
1870
- if (pluginStatusFilter !== "disabled") return;
1871
- setState("pluginStatusFilter", "all");
1872
- }, [inModal, isSocialMode, pluginStatusFilter, setState]);
1873
-
1874
- useEffect(() => {
1875
- if (!isSocialMode || !inModal) return;
1876
- if (
1877
- typeof window === "undefined" ||
1878
- typeof window.matchMedia !== "function"
1879
- )
1880
- return;
1881
-
1882
- const media = window.matchMedia("(min-width: 1024px)");
1883
- const syncLayout = () => {
1884
- setDesktopConnectorLayout(media.matches);
1885
- };
1886
-
1887
- syncLayout();
1888
- if (typeof media.addEventListener === "function") {
1889
- media.addEventListener("change", syncLayout);
1890
- return () => media.removeEventListener("change", syncLayout);
1891
- }
1892
-
1893
- media.addListener(syncLayout);
1894
- return () => media.removeListener(syncLayout);
1895
- }, [inModal, isSocialMode]);
1896
-
1897
- useEffect(() => {
1898
- if (!isSocialMode || !inModal) return;
1899
- if (visiblePlugins.length === 0) {
1900
- setConnectorSelectedId(null);
1901
- setConnectorExpandedIds(new Set());
1902
- return;
1903
- }
1904
-
1905
- setConnectorSelectedId((prev) => {
1906
- if (visiblePlugins.some((plugin) => plugin.id === prev)) {
1907
- return prev;
1908
- }
1909
- return desktopConnectorLayout ? (visiblePlugins[0]?.id ?? null) : null;
1910
- });
1911
- }, [desktopConnectorLayout, inModal, isSocialMode, visiblePlugins]);
1912
-
1913
- useEffect(() => {
1914
- if (!isSocialMode || !inModal || !desktopConnectorLayout) return;
1915
- if (!connectorSelectedId) return;
1916
- setConnectorExpandedIds(new Set([connectorSelectedId]));
1917
- }, [connectorSelectedId, desktopConnectorLayout, inModal, isSocialMode]);
1918
-
1919
- useEffect(() => {
1920
- if (!isSocialMode || !inModal || desktopConnectorLayout) return;
1921
- setConnectorExpandedIds(new Set());
1922
- }, [desktopConnectorLayout, inModal, isSocialMode]);
1923
-
1924
- const scrollConnectorIntoView = useCallback((pluginId: string) => {
1925
- const element = connectorSectionRefs.current[pluginId];
1926
- if (element && typeof element.scrollIntoView === "function") {
1927
- element.scrollIntoView({ behavior: "smooth", block: "start" });
1928
- }
1929
- }, []);
1930
-
1931
- const handleConnectorSelect = useCallback(
1932
- (pluginId: string) => {
1933
- setConnectorSelectedId(pluginId);
1934
- setConnectorExpandedIds((prev) => {
1935
- if (desktopConnectorLayout) {
1936
- return new Set([pluginId]);
1937
- }
1938
- const next = new Set(prev);
1939
- next.add(pluginId);
1940
- return next;
1941
- });
1942
- scrollConnectorIntoView(pluginId);
1943
- },
1944
- [desktopConnectorLayout, scrollConnectorIntoView],
1945
- );
1946
-
1947
- const handleConnectorSectionToggle = useCallback(
1948
- (pluginId: string) => {
1949
- setConnectorSelectedId(pluginId);
1950
- let shouldScroll = false;
1951
- setConnectorExpandedIds((prev) => {
1952
- if (desktopConnectorLayout) {
1953
- // Accordion: toggle off if already open, otherwise open this one only
1954
- if (prev.has(pluginId)) return new Set();
1955
- shouldScroll = true;
1956
- return new Set([pluginId]);
1957
- }
1958
- const next = new Set(prev);
1959
- if (next.has(pluginId)) next.delete(pluginId);
1960
- else next.add(pluginId);
1961
- return next;
1962
- });
1963
- if (desktopConnectorLayout && shouldScroll) {
1964
- scrollConnectorIntoView(pluginId);
1965
- }
1966
- },
1967
- [desktopConnectorLayout, scrollConnectorIntoView],
1968
- );
1969
-
1970
- // ── Game-modal render ─────────────────────────────────────────────
1971
- if (inModal && isSocialMode) {
1972
- return (
1973
- <div
1974
- data-testid="plugins-view-social"
1975
- className={`flex min-h-full min-w-0 w-full flex-col bg-bg ${
1976
- desktopConnectorLayout ? "md:flex-row" : ""
1977
- }`}
1978
- >
1979
- {desktopConnectorLayout && (
1980
- <aside
1981
- data-testid="connectors-settings-sidebar"
1982
- className="flex w-[22rem] shrink-0 border-r border-border/50 bg-bg/35 backdrop-blur-xl"
1983
- >
1984
- <div className="flex min-h-full flex-1 flex-col sticky top-0 max-h-screen">
1985
- <div className="border-b border-border/40 px-5 py-5 text-center">
1986
- <div className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted/80">
1987
- Connectors
1988
- </div>
1989
- <div className="mt-2 text-sm text-muted">
1990
- {enabledCount} enabled of {categoryPlugins.length}
1991
- </div>
1992
- </div>
1993
- <nav className="flex-1 space-y-2 overflow-y-auto px-4 py-4">
1994
- {(desktopConnectorLayout
1995
- ? visiblePlugins.filter((plugin) => {
1996
- return plugin.id === connectorSelectedId;
1997
- })
1998
- : visiblePlugins
1999
- ).map((plugin) => {
2000
- const isSelected = connectorSelectedId === plugin.id;
2001
- const isExpanded = connectorExpandedIds.has(plugin.id);
2002
- const isToggleBusy = togglingPlugins.has(plugin.id);
2003
- const toggleDisabled =
2004
- isToggleBusy || (hasPluginToggleInFlight && !isToggleBusy);
2005
-
2006
- return (
2007
- <div
2008
- key={plugin.id}
2009
- className={`flex items-center gap-2 rounded-2xl border px-3 py-2 transition-all ${
2010
- isSelected
2011
- ? "border-accent/40 bg-accent/10 text-txt shadow-[0_10px_30px_rgba(var(--accent),0.08)]"
2012
- : "border-transparent bg-transparent text-muted hover:border-border/60 hover:bg-card/55 hover:text-txt"
2013
- }`}
2014
- >
2015
- <button
2016
- type="button"
2017
- className="flex min-w-0 flex-1 items-center gap-3 text-left"
2018
- onClick={() => handleConnectorSelect(plugin.id)}
2019
- aria-current={isSelected ? "page" : undefined}
2020
- >
2021
- <span
2022
- className={`flex h-8 w-8 shrink-0 items-center justify-center rounded-xl border p-1.5 ${
2023
- isSelected
2024
- ? "border-accent/30 bg-accent/18 text-txt-strong"
2025
- : "border-border/50 bg-bg-accent/80 text-muted"
2026
- }`}
2027
- >
2028
- {renderResolvedIcon(plugin, {
2029
- className:
2030
- "h-4 w-4 shrink-0 rounded-sm object-contain",
2031
- emojiClassName: "text-sm",
2032
- })}
2033
- </span>
2034
- <span className="min-w-0 flex-1 truncate text-sm font-semibold leading-none">
2035
- {plugin.name}
2036
- </span>
2037
- </button>
2038
- <button
2039
- type="button"
2040
- className={`shrink-0 rounded-full border px-2.5 py-1 text-[10px] font-bold tracking-[0.16em] transition-colors ${
2041
- plugin.enabled
2042
- ? "border-accent bg-accent text-accent-fg"
2043
- : "border-border bg-transparent text-muted hover:border-accent/40 hover:text-txt"
2044
- } ${
2045
- toggleDisabled
2046
- ? "cursor-not-allowed opacity-60"
2047
- : "cursor-pointer"
2048
- }`}
2049
- onClick={() =>
2050
- void handleTogglePlugin(plugin.id, !plugin.enabled)
2051
- }
2052
- disabled={toggleDisabled}
2053
- >
2054
- {isToggleBusy ? "..." : plugin.enabled ? "ON" : "OFF"}
2055
- </button>
2056
- <span
2057
- className={`shrink-0 text-muted transition-transform ${
2058
- isExpanded ? "rotate-90" : ""
2059
- }`}
2060
- >
2061
- <ChevronRight className="h-4 w-4" />
2062
- </span>
2063
- </div>
2064
- );
2065
- })}
2066
- </nav>
2067
- </div>
2068
- </aside>
2069
- )}
2070
-
2071
- <div className="min-w-0 flex-1">
2072
- <div className="sticky top-0 z-20 border-b border-border/50 bg-bg/85 px-4 py-4 shadow-[0_12px_30px_rgba(0,0,0,0.14)] backdrop-blur-xl sm:px-6 lg:px-8">
2073
- <div className="mx-auto max-w-5xl">
2074
- <div className="flex flex-col gap-3 sm:flex-row sm:items-center">
2075
- <Input
2076
- type="text"
2077
- className="h-11 w-full rounded-xl border-border/60 bg-card/70 text-sm shadow-sm"
2078
- placeholder="Search connectors..."
2079
- value={pluginSearch}
2080
- onChange={(e) => setState("pluginSearch", e.target.value)}
2081
- />
2082
- <div className="flex shrink-0 gap-1.5 rounded-xl border border-white/5 bg-black/10 p-1">
2083
- {(["all", "enabled"] as const).map((status) => (
2084
- <Button
2085
- key={status}
2086
- variant={
2087
- effectiveStatusFilter === status ? "default" : "ghost"
2088
- }
2089
- size="sm"
2090
- className={`h-8 px-3 text-[11px] font-bold tracking-wide transition-all ${
2091
- effectiveStatusFilter === status
2092
- ? "shadow-sm"
2093
- : "text-muted hover:bg-white/5 hover:text-txt"
2094
- }`}
2095
- onClick={() =>
2096
- setState("pluginStatusFilter", status as StatusFilter)
2097
- }
2098
- >
2099
- {status === "all"
2100
- ? `All (${categoryPlugins.length})`
2101
- : `Enabled (${enabledCount})`}
2102
- </Button>
2103
- ))}
2104
- </div>
2105
- </div>
2106
- </div>
2107
- </div>
2108
-
2109
- <div className="mx-auto max-w-5xl px-4 py-4 sm:px-6 sm:py-5 lg:px-8 lg:py-6">
2110
- {hasPluginToggleInFlight && (
2111
- <div className="mb-4 rounded-2xl border border-accent bg-accent-subtle px-4 py-3 text-[11px] text-txt">
2112
- {t("pluginsview.ApplyingPluginChan")}
2113
- </div>
2114
- )}
2115
-
2116
- {visiblePlugins.length === 0 ? (
2117
- <div className="rounded-2xl border border-dashed border-border px-5 py-10 text-center text-muted">
2118
- {effectiveSearch
2119
- ? "No connectors match your search."
2120
- : "No connectors match your filters."}
2121
- </div>
2122
- ) : (
2123
- <div
2124
- data-testid="connectors-settings-content"
2125
- className="space-y-4"
2126
- >
2127
- {(desktopConnectorLayout
2128
- ? visiblePlugins.filter((p) => p.id === connectorSelectedId)
2129
- : visiblePlugins
2130
- ).map((plugin) => {
2131
- const hasParams =
2132
- (plugin.parameters?.length ?? 0) > 0 &&
2133
- plugin.id !== "__ui-showcase__";
2134
- const isExpanded = connectorExpandedIds.has(plugin.id);
2135
- const isSelected = connectorSelectedId === plugin.id;
2136
- const setCount = hasParams
2137
- ? plugin.parameters.filter((param) => param.isSet).length
2138
- : 0;
2139
- const totalCount = hasParams ? plugin.parameters.length : 0;
2140
- const allParamsSet = !hasParams || setCount === totalCount;
2141
- const isToggleBusy = togglingPlugins.has(plugin.id);
2142
- const toggleDisabled =
2143
- isToggleBusy || (hasPluginToggleInFlight && !isToggleBusy);
2144
- const isSaving = pluginSaving.has(plugin.id);
2145
- const saveSuccess = pluginSaveSuccess.has(plugin.id);
2146
- const testResult = testResults.get(plugin.id);
2147
- const pluginLinks = getPluginResourceLinks(plugin);
2148
-
2149
- return (
2150
- <section
2151
- key={plugin.id}
2152
- ref={(element) => {
2153
- connectorSectionRefs.current[plugin.id] = element;
2154
- }}
2155
- data-testid={`connector-section-${plugin.id}`}
2156
- className={`overflow-hidden rounded-[1.4rem] border bg-card/90 shadow-sm transition-all ${
2157
- isSelected
2158
- ? "border-accent/35 shadow-[0_18px_40px_rgba(var(--accent),0.08)]"
2159
- : "border-border/50"
2160
- }`}
2161
- >
2162
- <div className="flex items-start gap-3 px-4 py-4 sm:px-5">
2163
- <button
2164
- type="button"
2165
- data-testid={`connector-header-${plugin.id}`}
2166
- className="flex min-w-0 flex-1 items-start gap-3 text-left"
2167
- onClick={() =>
2168
- handleConnectorSectionToggle(plugin.id)
2169
- }
2170
- >
2171
- <span
2172
- className={`mt-0.5 flex h-11 w-11 shrink-0 items-center justify-center rounded-2xl border p-2.5 ${
2173
- isSelected
2174
- ? "border-accent/30 bg-accent/18 text-txt-strong"
2175
- : "border-border/50 bg-bg-accent/80 text-muted"
2176
- }`}
2177
- >
2178
- {renderResolvedIcon(plugin, {
2179
- className:
2180
- "h-4 w-4 shrink-0 rounded-sm object-contain",
2181
- emojiClassName: "text-base",
2182
- })}
2183
- </span>
2184
- <span className="min-w-0 flex-1">
2185
- <span className="flex min-w-0 flex-wrap items-center gap-2">
2186
- <span className="truncate text-sm font-semibold text-txt">
2187
- {plugin.name}
2188
- </span>
2189
- <span
2190
- className={`rounded-full border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.14em] ${
2191
- allParamsSet
2192
- ? "border-ok/30 bg-ok/10 text-ok"
2193
- : "border-warn/30 bg-warn/10 text-warn"
2194
- }`}
2195
- >
2196
- {allParamsSet ? "Ready" : "Needs setup"}
2197
- </span>
2198
- {plugin.version && (
2199
- <span className="text-[11px] font-mono text-muted/80">
2200
- v{plugin.version}
2201
- </span>
2202
- )}
2203
- </span>
2204
- <span className="mt-1 block text-sm text-muted">
2205
- {plugin.description || "No description available"}
2206
- </span>
2207
- <span className="mt-2 flex flex-wrap items-center gap-2 text-[11px] text-muted">
2208
- <span>
2209
- {hasParams
2210
- ? `${setCount}/${totalCount} configured`
2211
- : "No configuration needed"}
2212
- </span>
2213
- {plugin.enabled && !plugin.isActive && (
2214
- <span
2215
- className={`rounded-full border px-2 py-0.5 ${
2216
- plugin.loadError
2217
- ? "border-danger/30 bg-danger/10 text-danger"
2218
- : "border-warn/30 bg-warn/10 text-warn"
2219
- }`}
2220
- >
2221
- {plugin.loadError
2222
- ? "Load failed"
2223
- : "Not installed"}
2224
- </span>
2225
- )}
2226
- </span>
2227
- </span>
2228
- </button>
2229
-
2230
- <div className="flex shrink-0 items-center gap-2">
2231
- <button
2232
- type="button"
2233
- className={`rounded-full border px-3 py-1.5 text-[10px] font-bold tracking-[0.16em] transition-colors ${
2234
- plugin.enabled
2235
- ? "border-accent bg-accent text-accent-fg"
2236
- : "border-border bg-transparent text-muted hover:border-accent/40 hover:text-txt"
2237
- } ${
2238
- toggleDisabled
2239
- ? "cursor-not-allowed opacity-60"
2240
- : "cursor-pointer"
2241
- }`}
2242
- onClick={() =>
2243
- void handleTogglePlugin(
2244
- plugin.id,
2245
- !plugin.enabled,
2246
- )
2247
- }
2248
- disabled={toggleDisabled}
2249
- >
2250
- {isToggleBusy
2251
- ? "..."
2252
- : plugin.enabled
2253
- ? "ON"
2254
- : "OFF"}
2255
- </button>
2256
- <button
2257
- type="button"
2258
- className={`flex items-center gap-1 rounded-full border px-3 py-1.5 text-[11px] font-semibold transition-colors ${
2259
- isExpanded
2260
- ? "border-accent/40 bg-accent/10 text-txt"
2261
- : "border-border/50 text-muted hover:border-accent/40 hover:text-txt"
2262
- }`}
2263
- onClick={() =>
2264
- handleConnectorSectionToggle(plugin.id)
2265
- }
2266
- aria-expanded={isExpanded}
2267
- aria-label={`${isExpanded ? "Collapse" : "Expand"} ${plugin.name}`}
2268
- >
2269
- <span>{isExpanded ? "Collapse" : "Expand"}</span>
2270
- <ChevronRight
2271
- className={`h-4 w-4 transition-transform ${
2272
- isExpanded ? "rotate-90" : ""
2273
- }`}
2274
- />
2275
- </button>
2276
- </div>
2277
- </div>
2278
-
2279
- {isExpanded && (
2280
- <div className="border-t border-border/40 bg-black/5 px-4 py-4 sm:px-5">
2281
- {plugin.validationErrors &&
2282
- plugin.validationErrors.length > 0 && (
2283
- <div className="mb-4 rounded-2xl border border-danger/30 bg-danger/10 px-4 py-3 text-sm text-danger">
2284
- {plugin.validationErrors.map((error) => (
2285
- <div
2286
- key={`${plugin.id}:${error.field}:${error.message}`}
2287
- >
2288
- {error.field}: {error.message}
2289
- </div>
2290
- ))}
2291
- </div>
2292
- )}
2293
-
2294
- {plugin.validationWarnings &&
2295
- plugin.validationWarnings.length > 0 && (
2296
- <div className="mb-4 rounded-2xl border border-warn/30 bg-warn/10 px-4 py-3 text-sm text-warn">
2297
- {plugin.validationWarnings.map((warning) => (
2298
- <div
2299
- key={`${plugin.id}:${warning.field}:${warning.message}`}
2300
- >
2301
- {warning.message}
2302
- </div>
2303
- ))}
2304
- </div>
2305
- )}
2306
-
2307
- {pluginLinks.length > 0 && (
2308
- <div className="mb-4 flex flex-wrap gap-2">
2309
- {pluginLinks.map((link) => (
2310
- <Button
2311
- key={`${plugin.id}:${link.key}`}
2312
- variant="outline"
2313
- size="sm"
2314
- className="h-8 rounded-xl border-border/40 bg-card/40 px-3 text-[11px] font-semibold text-muted transition-all hover:border-accent hover:bg-accent/5 hover:text-txt"
2315
- onClick={() => {
2316
- void handleOpenPluginExternalUrl(link.url);
2317
- }}
2318
- title={`${link.label}: ${link.url}`}
2319
- >
2320
- {link.label}
2321
- </Button>
2322
- ))}
2323
- </div>
2324
- )}
2325
-
2326
- {plugin.enabled &&
2327
- !plugin.isActive &&
2328
- plugin.npmName &&
2329
- !plugin.loadError && (
2330
- <div className="mb-4 rounded-2xl border border-warn/30 bg-warn/10 px-4 py-3 text-sm text-txt">
2331
- <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
2332
- <div>
2333
- Install this connector to activate it in the
2334
- runtime.
2335
- </div>
2336
- <Button
2337
- variant="default"
2338
- size="sm"
2339
- className="h-8 rounded-xl px-4 text-[11px] font-bold"
2340
- disabled={installingPlugins.has(plugin.id)}
2341
- onClick={() =>
2342
- handleInstallPlugin(
2343
- plugin.id,
2344
- plugin.npmName ?? "",
2345
- )
2346
- }
2347
- >
2348
- {installingPlugins.has(plugin.id)
2349
- ? installProgress.get(
2350
- plugin.npmName ?? "",
2351
- )?.message || "Installing..."
2352
- : "Install Plugin"}
2353
- </Button>
2354
- </div>
2355
- </div>
2356
- )}
2357
-
2358
- {hasParams ? (
2359
- <div className="space-y-4">
2360
- <PluginConfigForm
2361
- plugin={plugin}
2362
- pluginConfigs={pluginConfigs}
2363
- onParamChange={handleParamChange}
2364
- />
2365
- {plugin.id === "whatsapp" && (
2366
- <WhatsAppQrOverlay accountId="default" />
2367
- )}
2368
- </div>
2369
- ) : (
2370
- <div className="rounded-2xl border border-border/40 bg-card/40 px-4 py-3 text-sm text-muted">
2371
- No configuration needed.
2372
- </div>
2373
- )}
2374
-
2375
- <div className="mt-4 flex flex-wrap items-center gap-2">
2376
- {plugin.isActive && (
2377
- <Button
2378
- variant={
2379
- testResult?.success
2380
- ? "default"
2381
- : testResult?.error
2382
- ? "destructive"
2383
- : "outline"
2384
- }
2385
- size="sm"
2386
- className={`h-8 rounded-xl px-4 text-[11px] font-bold transition-all ${
2387
- testResult?.loading
2388
- ? "cursor-wait opacity-70"
2389
- : testResult?.success
2390
- ? "border-ok bg-ok text-ok-fg hover:bg-ok/90"
2391
- : testResult?.error
2392
- ? "border-danger bg-danger text-danger-fg hover:bg-danger/90"
2393
- : "border-border/40 bg-card/40 hover:border-accent/40"
2394
- }`}
2395
- disabled={testResult?.loading}
2396
- onClick={() =>
2397
- void handleTestConnection(plugin.id)
2398
- }
2399
- >
2400
- {testResult?.loading
2401
- ? "Testing..."
2402
- : testResult?.success
2403
- ? `OK (${testResult.durationMs}ms)`
2404
- : testResult?.error
2405
- ? `Failed: ${testResult.error}`
2406
- : "Test Connection"}
2407
- </Button>
2408
- )}
2409
- {hasParams && (
2410
- <>
2411
- <Button
2412
- variant="ghost"
2413
- size="sm"
2414
- className="h-8 rounded-xl px-4 text-[11px] font-semibold text-muted hover:text-txt"
2415
- onClick={() => handleConfigReset(plugin.id)}
2416
- >
2417
- Reset
2418
- </Button>
2419
- <Button
2420
- variant={
2421
- saveSuccess ? "default" : "secondary"
2422
- }
2423
- size="sm"
2424
- className={`h-8 rounded-xl px-4 text-[11px] font-bold transition-all ${
2425
- saveSuccess
2426
- ? "bg-ok text-ok-fg hover:bg-ok/90"
2427
- : "bg-accent text-accent-fg hover:bg-accent/90"
2428
- }`}
2429
- onClick={() =>
2430
- void handleConfigSave(plugin.id)
2431
- }
2432
- disabled={isSaving}
2433
- >
2434
- {isSaving
2435
- ? "Saving..."
2436
- : saveSuccess
2437
- ? "Saved"
2438
- : "Save Settings"}
2439
- </Button>
2440
- </>
2441
- )}
2442
- </div>
2443
- </div>
2444
- )}
2445
- </section>
2446
- );
2447
- })}
2448
- </div>
2449
- )}
2450
- </div>
2451
- </div>
2452
- </div>
2453
- );
2454
- }
2455
-
2456
- if (inModal) {
2457
- const sectionTitle =
2458
- mode === "social"
2459
- ? "Connectors"
2460
- : mode === "connectors"
2461
- ? "Connectors"
2462
- : label;
2463
- return (
2464
- <div className="plugins-game-modal plugins-game-modal--inline">
2465
- <div
2466
- className={`plugins-game-list-panel${
2467
- gameNarrow && gameMobileDetail ? " is-hidden" : ""
2468
- }`}
2469
- >
2470
- <div className="plugins-game-list-head">
2471
- <div className="plugins-game-section-title">{sectionTitle}</div>
2472
- </div>
2473
- <div className="plugins-game-list-scroll">
2474
- {gameVisiblePlugins.length === 0 ? (
2475
- <div className="plugins-game-list-empty">
2476
- No {resultLabel} {t("pluginsview.found")}
2477
- </div>
2478
- ) : (
2479
- gameVisiblePlugins.map((p: PluginInfo) => (
2480
- <button
2481
- key={p.id}
2482
- type="button"
2483
- className={`plugins-game-card${
2484
- effectiveGameSelected === p.id ? " is-selected" : ""
2485
- }${!p.enabled ? " is-disabled" : ""}`}
2486
- onClick={() => {
2487
- setGameSelectedId(p.id);
2488
- if (gameNarrow) setGameMobileDetail(true);
2489
- }}
2490
- >
2491
- <div className="plugins-game-card-icon-shell">
2492
- <span className="plugins-game-card-icon">
2493
- {(() => {
2494
- const icon = resolveIcon(p);
2495
- if (!icon) return "🧩";
2496
- if (typeof icon === "string") {
2497
- const imageSrc = iconImageSource(icon);
2498
- return imageSrc ? (
2499
- <img
2500
- src={imageSrc}
2501
- alt=""
2502
- className="plugins-game-card-icon"
2503
- style={{ objectFit: "contain" }}
2504
- />
2505
- ) : (
2506
- icon
2507
- );
2508
- }
2509
- const IconComponent = icon;
2510
- return <IconComponent className="w-5 h-5" />;
2511
- })()}
2512
- </span>
2513
- </div>
2514
- <div className="plugins-game-card-body">
2515
- <div className="plugins-game-card-name">{p.name}</div>
2516
- <div className="plugins-game-card-meta">
2517
- <span
2518
- className={`plugins-game-badge ${
2519
- p.enabled ? "is-on" : "is-off"
2520
- }`}
2521
- >
2522
- {p.enabled ? "ON" : "OFF"}
2523
- </span>
2524
- </div>
2525
- </div>
2526
- </button>
2527
- ))
2528
- )}
2529
- </div>
2530
- </div>
2531
- <div
2532
- className={`plugins-game-detail-panel${
2533
- gameNarrow && !gameMobileDetail ? " is-hidden" : ""
2534
- }`}
2535
- >
2536
- {selectedPlugin ? (
2537
- <>
2538
- <div className="plugins-game-detail-head">
2539
- {gameNarrow && (
2540
- <button
2541
- type="button"
2542
- className="plugins-game-back-btn"
2543
- onClick={() => setGameMobileDetail(false)}
2544
- >
2545
- {t("pluginsview.Back")}
2546
- </button>
2547
- )}
2548
- <div className="plugins-game-detail-title-row">
2549
- <div className="plugins-game-detail-icon-shell">
2550
- <span className="plugins-game-detail-icon">
2551
- {(() => {
2552
- const icon = resolveIcon(selectedPlugin);
2553
- if (!icon) return "🧩";
2554
- if (typeof icon === "string") {
2555
- const imageSrc = iconImageSource(icon);
2556
- return imageSrc ? (
2557
- <img
2558
- src={imageSrc}
2559
- alt=""
2560
- className="plugins-game-detail-icon"
2561
- />
2562
- ) : (
2563
- icon
2564
- );
2565
- }
2566
- const IconComponent = icon;
2567
- return <IconComponent className="w-6 h-6" />;
2568
- })()}
2569
- </span>
2570
- </div>
2571
- <div className="plugins-game-detail-main">
2572
- <div className="plugins-game-detail-name">
2573
- {selectedPlugin.name}
2574
- </div>
2575
- {selectedPlugin.version && (
2576
- <span className="plugins-game-version">
2577
- v{selectedPlugin.version}
2578
- </span>
2579
- )}
2580
- </div>
2581
- <button
2582
- type="button"
2583
- className={`plugins-game-toggle ${
2584
- selectedPlugin.enabled ? "is-on" : "is-off"
2585
- }`}
2586
- onClick={() =>
2587
- void handleTogglePlugin(
2588
- selectedPlugin.id,
2589
- !selectedPlugin.enabled,
2590
- )
2591
- }
2592
- disabled={togglingPlugins.has(selectedPlugin.id)}
2593
- >
2594
- {selectedPlugin.enabled ? "ON" : "OFF"}
2595
- </button>
2596
- </div>
2597
- </div>
2598
- <div className="plugins-game-detail-description">
2599
- {selectedPlugin.description}
2600
- </div>
2601
- {(selectedPlugin.tags?.length ?? 0) > 0 && (
2602
- <div className="flex flex-wrap gap-1.5 px-3 pb-3">
2603
- {selectedPlugin.tags?.map((tag) => (
2604
- <span
2605
- key={`${selectedPlugin.id}:${tag}`}
2606
- className="text-[10px] px-1.5 py-px border border-border bg-black/10 text-muted lowercase tracking-wide whitespace-nowrap"
2607
- >
2608
- {tag}
2609
- </span>
2610
- ))}
2611
- </div>
2612
- )}
2613
- {selectedPluginLinks.length > 0 && (
2614
- <div className="plugins-game-detail-links flex flex-wrap gap-2 px-3 pb-3">
2615
- {selectedPluginLinks.map((link) => (
2616
- <button
2617
- key={`${selectedPlugin.id}:${link.key}`}
2618
- type="button"
2619
- className="plugins-game-link-btn border border-border bg-transparent px-2.5 py-1 text-[11px] text-muted transition-colors hover:border-accent hover:text-txt"
2620
- onClick={() => {
2621
- void handleOpenPluginExternalUrl(link.url);
2622
- }}
2623
- >
2624
- {link.label}
2625
- </button>
2626
- ))}
2627
- </div>
2628
- )}
2629
- {selectedPlugin.parameters &&
2630
- selectedPlugin.parameters.length > 0 && (
2631
- <div className="plugins-game-detail-config">
2632
- {selectedPlugin.parameters.map((param: PluginParamDef) => (
2633
- <div key={param.key} id={`field-${param.key}`}>
2634
- <label
2635
- htmlFor={`input-${param.key}`}
2636
- className="text-[11px] tracking-wider text-muted block mb-1"
2637
- >
2638
- {param.key}
2639
- </label>
2640
- <input
2641
- id={`input-${param.key}`}
2642
- type={param.sensitive ? "password" : "text"}
2643
- className="w-full px-2 py-1 text-[12px]"
2644
- placeholder={param.description}
2645
- value={
2646
- pluginConfigs[selectedPlugin.id]?.[param.key] ??
2647
- param.currentValue ??
2648
- ""
2649
- }
2650
- onChange={(e) =>
2651
- handleParamChange(
2652
- selectedPlugin.id,
2653
- param.key,
2654
- e.target.value,
2655
- )
2656
- }
2657
- />
2658
- </div>
2659
- ))}
2660
- </div>
2661
- )}
2662
- <div className="plugins-game-detail-actions">
2663
- <button
2664
- type="button"
2665
- className="plugins-game-action-btn"
2666
- onClick={() => void handleTestConnection(selectedPlugin.id)}
2667
- >
2668
- {t("pluginsview.TestConnection")}
2669
- </button>
2670
- <button
2671
- type="button"
2672
- className={`plugins-game-action-btn plugins-game-save-btn${
2673
- pluginSaveSuccess.has(selectedPlugin.id) ? " is-saved" : ""
2674
- }`}
2675
- onClick={() => void handleConfigSave(selectedPlugin.id)}
2676
- disabled={pluginSaving.has(selectedPlugin.id)}
2677
- >
2678
- {pluginSaving.has(selectedPlugin.id)
2679
- ? "Saving..."
2680
- : pluginSaveSuccess.has(selectedPlugin.id)
2681
- ? "Saved!"
2682
- : "Save"}
2683
- </button>
2684
- </div>
2685
- </>
2686
- ) : (
2687
- <div className="plugins-game-detail-empty">
2688
- <span className="plugins-game-detail-empty-icon">🧩</span>
2689
- <span className="plugins-game-detail-empty-text">
2690
- {t("pluginsview.SelectA")}{" "}
2691
- {isConnectorLikeMode ? "connector" : "plugin"}{" "}
2692
- {t("pluginsview.toC")}
2693
- </span>
2694
- </div>
2695
- )}
2696
- </div>
2697
- </div>
2698
- );
2699
- }
2700
-
2701
- // ── Main render ────────────────────────────────────────────────────
2702
-
2703
- return (
2704
- <div
2705
- data-testid={mode === "social" ? "plugins-view-social" : undefined}
2706
- className={`relative min-h-0 ${showDesktopSubgroupSidebar ? "md:pl-[18rem]" : ""}`}
2707
- >
2708
- {showDesktopSubgroupSidebar && (
2709
- <aside
2710
- className="hidden md:absolute md:left-0 md:top-0 md:block md:w-64"
2711
- data-testid="plugins-subgroup-sidebar"
2712
- >
2713
- <div className="sticky top-0 rounded-[28px] border border-border/50 bg-bg/35 p-5 backdrop-blur-xl shadow-sm">
2714
- <div className="mb-4 text-[11px] font-semibold uppercase tracking-[0.18em] text-muted/80">
2715
- Plugin Types
2716
- </div>
2717
- <nav className="flex flex-col gap-2">
2718
- {subgroupTags.map((tag) =>
2719
- renderSubgroupFilterButton(tag, { sidebar: true }),
2720
- )}
2721
- </nav>
2722
- </div>
2723
- </aside>
2724
- )}
2725
-
2726
- <div className="min-w-0">
2727
- {showToolbar && (
2728
- <div className="flex items-center gap-3 mb-4 flex-wrap">
2729
- <div className="relative flex-1 min-w-[220px]">
2730
- <Input
2731
- type="text"
2732
- name="plugin-search"
2733
- autoComplete="off"
2734
- data-1p-ignore
2735
- data-lpignore="true"
2736
- className="w-full bg-card/60 backdrop-blur-md shadow-inner pr-8 h-9 rounded-xl focus-visible:ring-accent border-border/40"
2737
- placeholder={searchPlaceholder}
2738
- value={pluginSearch}
2739
- onChange={(e) => setState("pluginSearch", e.target.value)}
2740
- />
2741
- {pluginSearch && (
2742
- <Button
2743
- variant="ghost"
2744
- size="icon"
2745
- className="absolute right-1 top-1/2 -translate-y-1/2 w-6 h-6 text-muted hover:text-txt rounded-full"
2746
- onClick={() => setState("pluginSearch", "")}
2747
- title={t("pluginsview.ClearSearch")}
2748
- >
2749
-
2750
- </Button>
2751
- )}
2752
- </div>
2753
-
2754
- <div className="flex gap-1.5 shrink-0 bg-black/10 p-1 rounded-xl border border-white/5">
2755
- {(["all", "enabled"] as const).map((s) => (
2756
- <Button
2757
- key={s}
2758
- variant={pluginStatusFilter === s ? "default" : "ghost"}
2759
- size="sm"
2760
- className={`h-7 px-3 text-[11px] font-bold tracking-wide rounded-lg transition-all ${
2761
- pluginStatusFilter === s
2762
- ? "shadow-sm"
2763
- : "text-muted hover:text-txt hover:bg-white/5"
2764
- }`}
2765
- onClick={() =>
2766
- setState("pluginStatusFilter", s as StatusFilter)
2767
- }
2768
- >
2769
- {s === "all"
2770
- ? `All (${categoryPlugins.length})`
2771
- : `Enabled (${enabledCount})`}
2772
- </Button>
2773
- ))}
2774
- </div>
2775
-
2776
- {allowCustomOrder && pluginOrder.length > 0 && (
2777
- <Button
2778
- variant="outline"
2779
- size="sm"
2780
- className="h-8 px-3 text-[11px] font-bold border-border/40 bg-card/40 backdrop-blur-md shadow-sm rounded-xl shrink-0"
2781
- onClick={handleResetOrder}
2782
- title={t("pluginsview.ResetToDefaultSor")}
2783
- >
2784
- {t("pluginsview.ResetOrder")}
2785
- </Button>
2786
- )}
2787
-
2788
- {showPluginManagementActions && (
2789
- <Button
2790
- variant="secondary"
2791
- size="sm"
2792
- className="h-8 px-4 text-[11px] font-bold tracking-wide border border-accent/30 text-txt bg-accent/10 hover:bg-accent/20 hover:border-accent/50 shadow-sm rounded-xl shrink-0 transition-all"
2793
- onClick={() => setAddDirOpen(true)}
2794
- >
2795
- {t("pluginsview.AddPlugin")}
2796
- </Button>
2797
- )}
2798
- </div>
2799
- )}
2800
-
2801
- {hasPluginToggleInFlight && (
2802
- <div className="mb-3 px-3 py-2 border border-accent bg-accent-subtle text-[11px] text-txt">
2803
- {t("pluginsview.ApplyingPluginChan")}
2804
- </div>
2805
- )}
2806
-
2807
- {showSubgroupFilters && (
2808
- <div
2809
- className="flex items-center gap-2 mb-5 flex-wrap md:hidden"
2810
- data-testid="plugins-subgroup-chips"
2811
- >
2812
- {subgroupTags.map((tag) => renderSubgroupFilterButton(tag))}
2813
- </div>
2814
- )}
2815
-
2816
- {/* Plugin grid */}
2817
- <div className="overflow-y-auto">
2818
- {sorted.length === 0 ? (
2819
- <div className="text-center py-10 px-5 text-muted border border-dashed border-border">
2820
- {effectiveSearch
2821
- ? `No ${resultLabel} match your search.`
2822
- : `No ${resultLabel} available.`}
2823
- </div>
2824
- ) : visiblePlugins.length === 0 ? (
2825
- <div className="text-center py-10 px-5 text-muted border border-dashed border-border">
2826
- {showSubgroupFilters
2827
- ? "No plugins match this tag filter."
2828
- : `No ${resultLabel} match your filters.`}
2829
- </div>
2830
- ) : (
2831
- renderPluginGrid(visiblePlugins)
2832
- )}
2833
- </div>
2834
- </div>
2835
-
2836
- {/* Settings dialog */}
2837
- {settingsDialogPlugin &&
2838
- (() => {
2839
- const p = settingsDialogPlugin;
2840
- const isShowcase = p.id === "__ui-showcase__";
2841
- const isSaving = pluginSaving.has(p.id);
2842
- const saveSuccess = pluginSaveSuccess.has(p.id);
2843
- const categoryLabel = isShowcase
2844
- ? "showcase"
2845
- : p.category === "ai-provider"
2846
- ? "ai provider"
2847
- : p.category;
2848
- return (
2849
- <div
2850
- className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-6 animate-in fade-in duration-200"
2851
- onClick={(e) => {
2852
- if (e.target === e.currentTarget) toggleSettings(p.id);
2853
- }}
2854
- onKeyDown={(e) => {
2855
- if (e.key === "Escape" || e.key === "Enter" || e.key === " ") {
2856
- e.preventDefault();
2857
- toggleSettings(p.id);
2858
- }
2859
- }}
2860
- role="dialog"
2861
- aria-modal="true"
2862
- >
2863
- <div className="w-full max-w-2xl max-h-[85vh] border border-border/50 bg-card/90 shadow-2xl flex flex-col overflow-hidden rounded-2xl backdrop-blur-xl">
2864
- {/* Dialog header */}
2865
- <div className="flex items-center gap-3 px-5 py-4 border-b border-border/30 bg-black/10 shrink-0">
2866
- <span className="font-bold text-base flex items-center gap-2 flex-1 min-w-0 tracking-wide text-txt">
2867
- {(() => {
2868
- const icon = resolveIcon(p);
2869
- if (!icon) return null;
2870
- if (typeof icon === "string") {
2871
- const imageSrc = iconImageSource(icon);
2872
- return imageSrc ? (
2873
- <img
2874
- src={imageSrc}
2875
- alt=""
2876
- className="w-6 h-6 rounded-md object-contain"
2877
- onError={(e) => {
2878
- (
2879
- e.currentTarget as HTMLImageElement
2880
- ).style.display = "none";
2881
- }}
2882
- />
2883
- ) : (
2884
- <span className="text-base">{icon}</span>
2885
- );
2886
- }
2887
- const IconComponent = icon;
2888
- return <IconComponent className="w-6 h-6 text-txt" />;
2889
- })()}
2890
- {p.name}
2891
- </span>
2892
- <span className="text-[10px] px-2 py-0.5 rounded-full border border-border/40 bg-black/20 text-muted lowercase tracking-widest font-bold">
2893
- {categoryLabel}
2894
- </span>
2895
- {p.version && (
2896
- <span className="text-[10px] font-mono text-muted/70">
2897
- v{p.version}
2898
- </span>
2899
- )}
2900
- {isShowcase && (
2901
- <span className="text-[10px] font-bold tracking-widest px-2.5 py-[2px] border border-accent/30 text-txt bg-accent/10 rounded-full">
2902
- {t("pluginsview.DEMO")}
2903
- </span>
2904
- )}
2905
- <Button
2906
- variant="ghost"
2907
- size="icon"
2908
- className="h-8 w-8 text-muted hover:bg-white/10 hover:text-txt rounded-full transition-all shrink-0 ml-2"
2909
- onClick={() => toggleSettings(p.id)}
2910
- >
2911
-
2912
- </Button>
2913
- </div>
2914
-
2915
- {/* Dialog body — scrollable */}
2916
- <div className="overflow-y-auto flex-1 scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent">
2917
- {/* Plugin details */}
2918
- <div className="px-5 pt-4 pb-1 flex items-center gap-3 flex-wrap text-xs text-muted">
2919
- {p.description && (
2920
- <span className="text-[12px] text-muted leading-relaxed">
2921
- {p.description}
2922
- </span>
2923
- )}
2924
- {(p.tags?.length ?? 0) > 0 && (
2925
- <span className="flex items-center gap-1.5 flex-wrap">
2926
- {p.tags?.map((tag) => (
2927
- <span
2928
- key={`${p.id}:${tag}:settings`}
2929
- className="text-[10px] px-1.5 py-px border border-border/40 bg-black/10 text-muted lowercase tracking-wide whitespace-nowrap"
2930
- >
2931
- {tag}
2932
- </span>
2933
- ))}
2934
- </span>
2935
- )}
2936
- </div>
2937
- {(p.npmName || (p.pluginDeps && p.pluginDeps.length > 0)) && (
2938
- <div className="px-5 pb-2 flex items-center gap-3 flex-wrap">
2939
- {p.npmName && (
2940
- <span className="font-mono text-[10px] text-muted opacity-50">
2941
- {p.npmName}
2942
- </span>
2943
- )}
2944
- {p.pluginDeps && p.pluginDeps.length > 0 && (
2945
- <span className="flex items-center gap-1 flex-wrap">
2946
- <span className="text-[10px] text-muted opacity-60">
2947
- {t("pluginsview.dependsOn")}
2948
- </span>
2949
- {p.pluginDeps.map((dep: string) => (
2950
- <span
2951
- key={dep}
2952
- className="text-[10px] px-1.5 py-px border border-border bg-accent-subtle text-muted rounded-sm"
2953
- >
2954
- {dep}
2955
- </span>
2956
- ))}
2957
- </span>
2958
- )}
2959
- </div>
2960
- )}
2961
-
2962
- <div className="px-5 py-3">
2963
- <PluginConfigForm
2964
- plugin={p}
2965
- pluginConfigs={pluginConfigs}
2966
- onParamChange={handleParamChange}
2967
- />
2968
- {p.id === "whatsapp" && (
2969
- <WhatsAppQrOverlay accountId="default" />
2970
- )}
2971
- </div>
2972
- </div>
2973
-
2974
- {/* Dialog footer — actions (hidden for showcase) */}
2975
- {!isShowcase && (
2976
- <div className="flex justify-end gap-3 px-5 py-4 border-t border-border/30 shrink-0 bg-black/10">
2977
- {p.enabled && !p.isActive && p.npmName && !p.loadError && (
2978
- <Button
2979
- variant="default"
2980
- size="sm"
2981
- className="h-8 px-4 text-[11px] font-bold tracking-wide shadow-sm"
2982
- disabled={installingPlugins.has(p.id)}
2983
- onClick={() =>
2984
- handleInstallPlugin(p.id, p.npmName ?? "")
2985
- }
2986
- >
2987
- {installingPlugins.has(p.id)
2988
- ? installProgress.get(p.npmName ?? "")?.message ||
2989
- "Installing..."
2990
- : "Install Plugin"}
2991
- </Button>
2992
- )}
2993
- {p.loadError && (
2994
- <span
2995
- className="px-3 py-1.5 text-[11px] text-danger font-bold tracking-wide"
2996
- title={p.loadError}
2997
- >
2998
- {t("pluginsview.PackageBrokenMis")}
2999
- </span>
3000
- )}
3001
- {p.isActive && (
3002
- <Button
3003
- variant={
3004
- testResults.get(p.id)?.success
3005
- ? "default"
3006
- : testResults.get(p.id)?.error
3007
- ? "destructive"
3008
- : "outline"
3009
- }
3010
- size="sm"
3011
- className={`h-8 px-4 text-[11px] font-bold tracking-wide transition-all ${
3012
- testResults.get(p.id)?.loading
3013
- ? "opacity-70 cursor-wait"
3014
- : testResults.get(p.id)?.success
3015
- ? "bg-ok text-ok-fg border-ok hover:bg-ok/90"
3016
- : testResults.get(p.id)?.error
3017
- ? "bg-danger text-danger-fg border-danger hover:bg-danger/90"
3018
- : "border-border/40 bg-card/40 backdrop-blur-md shadow-sm hover:border-accent/40"
3019
- }`}
3020
- disabled={testResults.get(p.id)?.loading}
3021
- onClick={() => handleTestConnection(p.id)}
3022
- >
3023
- {testResults.get(p.id)?.loading
3024
- ? "Testing..."
3025
- : testResults.get(p.id)?.success
3026
- ? `\u2713 OK (${testResults.get(p.id)?.durationMs}ms)`
3027
- : testResults.get(p.id)?.error
3028
- ? `\u2715 ${testResults.get(p.id)?.error}`
3029
- : "Test Connection"}
3030
- </Button>
3031
- )}
3032
- <Button
3033
- variant="ghost"
3034
- size="sm"
3035
- className="h-8 px-4 text-[12px] font-bold text-muted hover:text-txt transition-all"
3036
- onClick={() => handleConfigReset(p.id)}
3037
- >
3038
- {t("pluginsview.Reset")}
3039
- </Button>
3040
- <Button
3041
- variant={saveSuccess ? "default" : "secondary"}
3042
- size="sm"
3043
- className={`h-8 px-5 text-[12px] font-bold tracking-wide transition-all ${
3044
- saveSuccess
3045
- ? "bg-ok text-ok-fg hover:bg-ok/90"
3046
- : "bg-accent text-accent-fg hover:bg-accent/90 shadow-lg shadow-accent/20"
3047
- }`}
3048
- onClick={() => handleConfigSave(p.id)}
3049
- disabled={isSaving}
3050
- >
3051
- {isSaving
3052
- ? "Saving..."
3053
- : saveSuccess
3054
- ? "\u2713 Saved"
3055
- : "Save Settings"}
3056
- </Button>
3057
- </div>
3058
- )}
3059
- </div>
3060
- </div>
3061
- );
3062
- })()}
3063
-
3064
- {/* Add from directory modal */}
3065
- {addDirOpen && (
3066
- <div
3067
- className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-6 duration-200 animate-in fade-in"
3068
- onClick={(e) => {
3069
- if (e.target === e.currentTarget) {
3070
- setAddDirOpen(false);
3071
- setAddDirPath("");
3072
- }
3073
- }}
3074
- onKeyDown={(e) => {
3075
- if (e.key === "Escape" || e.key === "Enter" || e.key === " ") {
3076
- e.preventDefault();
3077
- setAddDirOpen(false);
3078
- setAddDirPath("");
3079
- }
3080
- }}
3081
- role="dialog"
3082
- aria-modal="true"
3083
- >
3084
- <div className="w-full max-w-md border border-border/50 bg-card/90 backdrop-blur-xl p-6 rounded-2xl shadow-2xl">
3085
- <div className="flex items-center justify-between mb-5">
3086
- <div className="font-bold text-base tracking-wide text-txt">
3087
- {t("pluginsview.AddPlugin1")}
3088
- </div>
3089
- <Button
3090
- variant="ghost"
3091
- size="icon"
3092
- className="h-8 w-8 text-muted hover:bg-white/10 hover:text-txt rounded-full transition-all shrink-0 ml-2"
3093
- onClick={() => {
3094
- setAddDirOpen(false);
3095
- setAddDirPath("");
3096
- }}
3097
- >
3098
-
3099
- </Button>
3100
- </div>
3101
-
3102
- <p className="text-sm font-medium tracking-wide text-muted mb-4">
3103
- {t("pluginsview.EnterThePathToA")}
3104
- </p>
3105
-
3106
- <Input
3107
- type="text"
3108
- className="w-full h-10 px-3 border border-border/40 bg-black/20 text-txt text-[13px] font-mono transition-all duration-150 focus-visible:ring-accent rounded-xl shadow-inner placeholder:text-muted/50"
3109
- placeholder={t("pluginsview.PathToPluginOrP")}
3110
- value={addDirPath}
3111
- onChange={(e) => setAddDirPath(e.target.value)}
3112
- onKeyDown={(e) => {
3113
- if (e.key === "Enter") void handleAddFromDirectory();
3114
- }}
3115
- />
3116
-
3117
- <div className="flex justify-end gap-3 mt-6">
3118
- <Button
3119
- variant="ghost"
3120
- size="sm"
3121
- className="h-8 px-4 text-[12px] font-bold text-muted hover:text-txt transition-all"
3122
- onClick={() => {
3123
- setAddDirOpen(false);
3124
- setAddDirPath("");
3125
- }}
3126
- >
3127
- {t("pluginsview.Cancel")}
3128
- </Button>
3129
- <Button
3130
- variant="default"
3131
- size="sm"
3132
- className="h-8 px-6 text-[12px] font-bold tracking-wide shadow-sm"
3133
- onClick={handleAddFromDirectory}
3134
- disabled={addDirLoading || !addDirPath.trim()}
3135
- >
3136
- {addDirLoading ? "Adding..." : "Add"}
3137
- </Button>
3138
- </div>
3139
- </div>
3140
- </div>
3141
- )}
3142
- </div>
3143
- );
3144
- }
3145
-
3146
- /* ── Exported views ────────────────────────────────────────────────── */
3147
-
3148
- /** Unified plugins view — tag-filtered plugin list. */
3149
- export function PluginsView({
3150
- mode = "all",
3151
- inModal,
3152
- }: {
3153
- mode?: PluginsViewMode;
3154
- inModal?: boolean;
3155
- }) {
3156
- const label =
3157
- mode === "social"
3158
- ? "Connectors"
3159
- : mode === "connectors"
3160
- ? "Connectors"
3161
- : mode === "streaming"
3162
- ? "Streaming"
3163
- : "Plugins";
3164
- return <PluginListView label={label} mode={mode} inModal={inModal} />;
3165
- }