@elizaos/app-core 2.0.0-alpha.10

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 (399) hide show
  1. package/LICENSE +21 -0
  2. package/package.json +90 -0
  3. package/src/App.tsx +472 -0
  4. package/src/actions/character.test.ts +139 -0
  5. package/src/actions/character.ts +152 -0
  6. package/src/actions/chat-helpers.ts +100 -0
  7. package/src/actions/cloud.ts +59 -0
  8. package/src/actions/index.ts +12 -0
  9. package/src/actions/lifecycle.ts +175 -0
  10. package/src/actions/onboarding.ts +46 -0
  11. package/src/actions/triggers.ts +190 -0
  12. package/src/ambient.d.ts +16 -0
  13. package/src/api/client.ts +5516 -0
  14. package/src/api/index.ts +1 -0
  15. package/src/autonomy/index.ts +477 -0
  16. package/src/bridge/capacitor-bridge.ts +295 -0
  17. package/src/bridge/electrobun-rpc.ts +58 -0
  18. package/src/bridge/electrobun-runtime.ts +28 -0
  19. package/src/bridge/index.ts +5 -0
  20. package/src/bridge/native-plugins.ts +134 -0
  21. package/src/bridge/plugin-bridge.ts +352 -0
  22. package/src/bridge/storage-bridge.ts +162 -0
  23. package/src/chat/index.ts +250 -0
  24. package/src/coding/index.ts +43 -0
  25. package/src/components/AdvancedPageView.tsx +362 -0
  26. package/src/components/AgentActivityBox.tsx +49 -0
  27. package/src/components/ApiKeyConfig.tsx +224 -0
  28. package/src/components/AppsPageView.tsx +52 -0
  29. package/src/components/AppsView.tsx +293 -0
  30. package/src/components/AvatarLoader.tsx +86 -0
  31. package/src/components/AvatarSelector.tsx +223 -0
  32. package/src/components/BscTradePanel.tsx +549 -0
  33. package/src/components/BugReportModal.tsx +499 -0
  34. package/src/components/CharacterView.tsx +1645 -0
  35. package/src/components/ChatAvatar.test.ts +96 -0
  36. package/src/components/ChatAvatar.tsx +147 -0
  37. package/src/components/ChatComposer.tsx +330 -0
  38. package/src/components/ChatMessage.tsx +448 -0
  39. package/src/components/ChatModalView.test.tsx +118 -0
  40. package/src/components/ChatModalView.tsx +125 -0
  41. package/src/components/ChatView.tsx +992 -0
  42. package/src/components/CloudSourceControls.tsx +80 -0
  43. package/src/components/CodingAgentSettingsSection.tsx +536 -0
  44. package/src/components/CommandPalette.tsx +284 -0
  45. package/src/components/CompanionSceneHost.tsx +497 -0
  46. package/src/components/CompanionShell.tsx +31 -0
  47. package/src/components/CompanionView.tsx +109 -0
  48. package/src/components/ConfigPageView.tsx +758 -0
  49. package/src/components/ConfigSaveFooter.tsx +41 -0
  50. package/src/components/ConfirmModal.tsx +379 -0
  51. package/src/components/ConnectionFailedBanner.tsx +91 -0
  52. package/src/components/ConnectorsPageView.tsx +13 -0
  53. package/src/components/ConversationsSidebar.tsx +279 -0
  54. package/src/components/CustomActionEditor.tsx +1125 -0
  55. package/src/components/CustomActionsPanel.tsx +288 -0
  56. package/src/components/CustomActionsView.tsx +322 -0
  57. package/src/components/DatabasePageView.tsx +55 -0
  58. package/src/components/DatabaseView.tsx +814 -0
  59. package/src/components/ElizaCloudDashboard.tsx +1696 -0
  60. package/src/components/EmotePicker.tsx +529 -0
  61. package/src/components/ErrorBoundary.tsx +76 -0
  62. package/src/components/FineTuningView.tsx +1077 -0
  63. package/src/components/GameView.tsx +552 -0
  64. package/src/components/GameViewOverlay.tsx +133 -0
  65. package/src/components/GlobalEmoteOverlay.tsx +155 -0
  66. package/src/components/Header.test.tsx +413 -0
  67. package/src/components/Header.tsx +403 -0
  68. package/src/components/HeartbeatsView.tsx +1003 -0
  69. package/src/components/InventoryView.tsx +385 -0
  70. package/src/components/KnowledgeView.tsx +1128 -0
  71. package/src/components/LanguageDropdown.tsx +188 -0
  72. package/src/components/LifoMonitorPanel.tsx +196 -0
  73. package/src/components/LifoSandboxView.tsx +499 -0
  74. package/src/components/LoadingScreen.tsx +77 -0
  75. package/src/components/LogsPageView.tsx +17 -0
  76. package/src/components/LogsView.tsx +239 -0
  77. package/src/components/MediaGalleryView.tsx +433 -0
  78. package/src/components/MediaSettingsSection.tsx +893 -0
  79. package/src/components/MessageContent.tsx +815 -0
  80. package/src/components/OnboardingWizard.test.tsx +107 -0
  81. package/src/components/OnboardingWizard.tsx +189 -0
  82. package/src/components/PairingView.tsx +110 -0
  83. package/src/components/PermissionsSection.tsx +1186 -0
  84. package/src/components/PluginsPageView.tsx +9 -0
  85. package/src/components/PluginsView.tsx +3157 -0
  86. package/src/components/ProviderSwitcher.tsx +908 -0
  87. package/src/components/RestartBanner.tsx +76 -0
  88. package/src/components/RuntimeView.tsx +460 -0
  89. package/src/components/SaveCommandModal.tsx +211 -0
  90. package/src/components/SecretsView.tsx +569 -0
  91. package/src/components/SettingsView.tsx +825 -0
  92. package/src/components/ShellOverlays.tsx +41 -0
  93. package/src/components/ShortcutsOverlay.tsx +155 -0
  94. package/src/components/SkillsView.tsx +1435 -0
  95. package/src/components/StartupFailureView.tsx +63 -0
  96. package/src/components/StreamView.tsx +483 -0
  97. package/src/components/StripeEmbeddedCheckout.tsx +155 -0
  98. package/src/components/SubscriptionStatus.tsx +640 -0
  99. package/src/components/SystemWarningBanner.tsx +71 -0
  100. package/src/components/ThemeToggle.tsx +100 -0
  101. package/src/components/TrajectoriesView.tsx +526 -0
  102. package/src/components/TrajectoryDetailView.tsx +426 -0
  103. package/src/components/TriggersView.tsx +1 -0
  104. package/src/components/VectorBrowserView.tsx +1633 -0
  105. package/src/components/VoiceConfigView.tsx +675 -0
  106. package/src/components/VrmStage.test.ts +219 -0
  107. package/src/components/VrmStage.tsx +432 -0
  108. package/src/components/WhatsAppQrOverlay.tsx +230 -0
  109. package/src/components/__tests__/chainConfig.test.ts +220 -0
  110. package/src/components/apps/AppDetailPane.tsx +242 -0
  111. package/src/components/apps/AppsCatalogGrid.tsx +137 -0
  112. package/src/components/apps/extensions/HyperscapeAppDetailPanel.tsx +577 -0
  113. package/src/components/apps/extensions/registry.ts +16 -0
  114. package/src/components/apps/extensions/types.ts +9 -0
  115. package/src/components/apps/helpers.ts +44 -0
  116. package/src/components/avatar/VrmAnimationLoader.test.ts +164 -0
  117. package/src/components/avatar/VrmAnimationLoader.ts +151 -0
  118. package/src/components/avatar/VrmBlinkController.ts +118 -0
  119. package/src/components/avatar/VrmCameraManager.ts +407 -0
  120. package/src/components/avatar/VrmEngine.ts +2678 -0
  121. package/src/components/avatar/VrmFootShadow.ts +96 -0
  122. package/src/components/avatar/VrmViewer.tsx +421 -0
  123. package/src/components/avatar/__tests__/VrmCameraManager.test.ts +168 -0
  124. package/src/components/avatar/__tests__/VrmEngine.test.ts +1574 -0
  125. package/src/components/avatar/mixamoVRMRigMap.ts +62 -0
  126. package/src/components/avatar/retargetMixamoFbxToVrm.ts +144 -0
  127. package/src/components/avatar/retargetMixamoGltfToVrm.ts +119 -0
  128. package/src/components/chainConfig.ts +380 -0
  129. package/src/components/companion/CompanionHeader.tsx +47 -0
  130. package/src/components/companion/CompanionSceneHost.tsx +1 -0
  131. package/src/components/companion/VrmStage.tsx +2 -0
  132. package/src/components/companion/__tests__/walletUtils.test.ts +742 -0
  133. package/src/components/companion/walletUtils.ts +290 -0
  134. package/src/components/companion-shell-styles.test.ts +142 -0
  135. package/src/components/companion-shell-styles.ts +270 -0
  136. package/src/components/confirm-delete-control.tsx +69 -0
  137. package/src/components/conversations/ConversationListItem.tsx +185 -0
  138. package/src/components/conversations/conversation-utils.ts +151 -0
  139. package/src/components/format.ts +131 -0
  140. package/src/components/index.ts +94 -0
  141. package/src/components/inventory/CopyableAddress.tsx +41 -0
  142. package/src/components/inventory/InventoryToolbar.tsx +142 -0
  143. package/src/components/inventory/NftGrid.tsx +99 -0
  144. package/src/components/inventory/TokenLogo.tsx +71 -0
  145. package/src/components/inventory/TokensTable.tsx +216 -0
  146. package/src/components/inventory/constants.ts +170 -0
  147. package/src/components/inventory/index.ts +29 -0
  148. package/src/components/inventory/media-url.test.ts +38 -0
  149. package/src/components/inventory/media-url.ts +36 -0
  150. package/src/components/inventory/useInventoryData.ts +460 -0
  151. package/src/components/knowledge-upload-image.ts +215 -0
  152. package/src/components/labels.ts +46 -0
  153. package/src/components/onboarding/ActivateStep.tsx +30 -0
  154. package/src/components/onboarding/ConnectionStep.tsx +1530 -0
  155. package/src/components/onboarding/IdentityStep.tsx +147 -0
  156. package/src/components/onboarding/OnboardingPanel.tsx +39 -0
  157. package/src/components/onboarding/OnboardingStepNav.tsx +31 -0
  158. package/src/components/onboarding/PermissionsStep.tsx +20 -0
  159. package/src/components/onboarding/RpcStep.tsx +402 -0
  160. package/src/components/onboarding/WakeUpStep.tsx +184 -0
  161. package/src/components/permissions/PermissionIcon.tsx +25 -0
  162. package/src/components/permissions/StreamingPermissions.tsx +413 -0
  163. package/src/components/plugins/showcase-data.ts +481 -0
  164. package/src/components/shared/ShellHeaderControls.tsx +193 -0
  165. package/src/components/shared-companion-scene-context.ts +15 -0
  166. package/src/components/skeletons.tsx +88 -0
  167. package/src/components/stream/ActivityFeed.tsx +113 -0
  168. package/src/components/stream/AvatarPip.tsx +10 -0
  169. package/src/components/stream/ChatContent.tsx +126 -0
  170. package/src/components/stream/ChatTicker.tsx +55 -0
  171. package/src/components/stream/IdleContent.tsx +73 -0
  172. package/src/components/stream/StatusBar.tsx +469 -0
  173. package/src/components/stream/StreamSettings.tsx +506 -0
  174. package/src/components/stream/StreamTerminal.tsx +94 -0
  175. package/src/components/stream/StreamVoiceConfig.tsx +160 -0
  176. package/src/components/stream/helpers.ts +134 -0
  177. package/src/components/stream/overlays/OverlayLayer.tsx +75 -0
  178. package/src/components/stream/overlays/built-in/ActionTickerWidget.tsx +64 -0
  179. package/src/components/stream/overlays/built-in/AlertPopupWidget.tsx +87 -0
  180. package/src/components/stream/overlays/built-in/BrandingWidget.tsx +51 -0
  181. package/src/components/stream/overlays/built-in/CustomHtmlWidget.tsx +105 -0
  182. package/src/components/stream/overlays/built-in/PeonGlassWidget.tsx +265 -0
  183. package/src/components/stream/overlays/built-in/PeonHudWidget.tsx +247 -0
  184. package/src/components/stream/overlays/built-in/PeonSakuraWidget.tsx +278 -0
  185. package/src/components/stream/overlays/built-in/ThoughtBubbleWidget.tsx +77 -0
  186. package/src/components/stream/overlays/built-in/ViewerCountWidget.tsx +46 -0
  187. package/src/components/stream/overlays/built-in/index.ts +13 -0
  188. package/src/components/stream/overlays/registry.ts +22 -0
  189. package/src/components/stream/overlays/types.ts +90 -0
  190. package/src/components/stream/overlays/useOverlayLayout.ts +218 -0
  191. package/src/components/trajectory-format.ts +50 -0
  192. package/src/components/ui-badges.tsx +109 -0
  193. package/src/components/ui-switch.tsx +57 -0
  194. package/src/components/vector-browser-three.ts +27 -0
  195. package/src/config/config-catalog.ts +1092 -0
  196. package/src/config/config-field.tsx +1901 -0
  197. package/src/config/config-renderer.tsx +730 -0
  198. package/src/config/index.ts +11 -0
  199. package/src/config/ui-renderer.tsx +1751 -0
  200. package/src/config/ui-spec.ts +256 -0
  201. package/src/events/index.ts +89 -0
  202. package/src/hooks/index.ts +13 -0
  203. package/src/hooks/useBugReport.tsx +43 -0
  204. package/src/hooks/useCanvasWindow.ts +372 -0
  205. package/src/hooks/useChatAvatarVoice.ts +111 -0
  206. package/src/hooks/useContextMenu.ts +127 -0
  207. package/src/hooks/useKeyboardShortcuts.ts +86 -0
  208. package/src/hooks/useLifoSync.ts +143 -0
  209. package/src/hooks/useMemoryMonitor.ts +334 -0
  210. package/src/hooks/useRenderGuard.ts +43 -0
  211. package/src/hooks/useRetakeCapture.ts +67 -0
  212. package/src/hooks/useStreamPopoutNavigation.ts +27 -0
  213. package/src/hooks/useTimeout.ts +37 -0
  214. package/src/hooks/useVoiceChat.ts +1441 -0
  215. package/src/hooks/useWhatsAppPairing.ts +123 -0
  216. package/src/i18n/index.ts +76 -0
  217. package/src/i18n/locales/en.json +1194 -0
  218. package/src/i18n/locales/es.json +1194 -0
  219. package/src/i18n/locales/ko.json +1194 -0
  220. package/src/i18n/locales/pt.json +1194 -0
  221. package/src/i18n/locales/zh-CN.json +1194 -0
  222. package/src/i18n/messages.ts +21 -0
  223. package/src/index.ts +6 -0
  224. package/src/navigation/index.ts +282 -0
  225. package/src/navigation.test.ts +189 -0
  226. package/src/onboarding-config.test.ts +104 -0
  227. package/src/onboarding-config.ts +114 -0
  228. package/src/platform/browser-launch.test.ts +94 -0
  229. package/src/platform/browser-launch.ts +149 -0
  230. package/src/platform/index.ts +58 -0
  231. package/src/platform/init.ts +236 -0
  232. package/src/platform/lifo.ts +215 -0
  233. package/src/providers/index.ts +99 -0
  234. package/src/state/AppContext.tsx +5846 -0
  235. package/src/state/index.ts +6 -0
  236. package/src/state/internal.ts +86 -0
  237. package/src/state/onboarding-resume.test.ts +135 -0
  238. package/src/state/onboarding-resume.ts +263 -0
  239. package/src/state/parsers.test.ts +124 -0
  240. package/src/state/parsers.ts +308 -0
  241. package/src/state/persistence.ts +321 -0
  242. package/src/state/shell-routing.ts +32 -0
  243. package/src/state/types.ts +701 -0
  244. package/src/state/ui-preferences.ts +3 -0
  245. package/src/state/useApp.ts +23 -0
  246. package/src/state/vrm.ts +76 -0
  247. package/src/stories/AppMockProvider.tsx +32 -0
  248. package/src/stories/ChatEmptyState.stories.tsx +27 -0
  249. package/src/stories/ChatMessage.stories.tsx +115 -0
  250. package/src/stories/CompanionHeader.stories.tsx +74 -0
  251. package/src/stories/CompanionView.stories.tsx +33 -0
  252. package/src/stories/ConversationListItem.stories.tsx +102 -0
  253. package/src/stories/TypingIndicator.stories.tsx +28 -0
  254. package/src/styles/anime.css +6324 -0
  255. package/src/styles/base.css +196 -0
  256. package/src/styles/onboarding-game.css +738 -0
  257. package/src/styles/styles.css +2087 -0
  258. package/src/styles/xterm.css +241 -0
  259. package/src/types/index.ts +715 -0
  260. package/src/types/react-test-renderer.d.ts +45 -0
  261. package/src/utils/asset-url.ts +110 -0
  262. package/src/utils/assistant-text.ts +172 -0
  263. package/src/utils/clipboard.ts +41 -0
  264. package/src/utils/desktop-dialogs.ts +80 -0
  265. package/src/utils/index.ts +6 -0
  266. package/src/utils/number-parsing.ts +125 -0
  267. package/src/utils/openExternalUrl.ts +20 -0
  268. package/src/utils/spoken-text.ts +65 -0
  269. package/src/utils/streaming-text.ts +120 -0
  270. package/src/voice/index.ts +1 -0
  271. package/src/voice/types.ts +197 -0
  272. package/src/wallet-rpc.ts +176 -0
  273. package/test/app/AppContext.pty-sessions.test.tsx +143 -0
  274. package/test/app/MessageContent.test.tsx +326 -0
  275. package/test/app/PermissionsOnboarding.test.tsx +356 -0
  276. package/test/app/PermissionsSection.test.tsx +573 -0
  277. package/test/app/advanced-trajectory-fine-tuning.e2e.test.ts +393 -0
  278. package/test/app/agent-activity-box.test.tsx +132 -0
  279. package/test/app/agent-transfer-lock.test.ts +274 -0
  280. package/test/app/api-client-electron-fallback.test.ts +139 -0
  281. package/test/app/api-client-timeout.test.ts +75 -0
  282. package/test/app/api-client-ws.test.ts +98 -0
  283. package/test/app/api-client.ws-max-reconnect.test.ts +139 -0
  284. package/test/app/api-client.ws-reconnect.test.ts +157 -0
  285. package/test/app/app-context-autonomy-events.test.ts +478 -0
  286. package/test/app/apps-page-view.test.ts +114 -0
  287. package/test/app/apps-view.test.ts +769 -0
  288. package/test/app/autonomous-workflows.e2e.test.ts +765 -0
  289. package/test/app/autonomy-events.test.ts +150 -0
  290. package/test/app/avatar-selector.test.tsx +52 -0
  291. package/test/app/bsc-trade-panel.test.tsx +134 -0
  292. package/test/app/bug-report-modal.test.tsx +353 -0
  293. package/test/app/character-customization.e2e.test.ts +1199 -0
  294. package/test/app/chat-advanced-features.e2e.test.ts +706 -0
  295. package/test/app/chat-composer.test.tsx +181 -0
  296. package/test/app/chat-language-header.test.ts +64 -0
  297. package/test/app/chat-message.test.tsx +222 -0
  298. package/test/app/chat-modal-view.test.tsx +191 -0
  299. package/test/app/chat-routine-filter.test.ts +96 -0
  300. package/test/app/chat-send-lock.test.ts +1465 -0
  301. package/test/app/chat-stream-api-client.test.tsx +390 -0
  302. package/test/app/chat-view-game-modal.test.tsx +661 -0
  303. package/test/app/chat-view.test.tsx +877 -0
  304. package/test/app/cloud-api.e2e.test.ts +258 -0
  305. package/test/app/cloud-login-flow.e2e.test.ts +494 -0
  306. package/test/app/cloud-login-lock.test.ts +411 -0
  307. package/test/app/command-palette.test.tsx +184 -0
  308. package/test/app/command-registry.test.ts +75 -0
  309. package/test/app/companion-greeting-wave.test.tsx +425 -0
  310. package/test/app/companion-stale-conversation.test.tsx +447 -0
  311. package/test/app/companion-view.test.tsx +686 -0
  312. package/test/app/confirm-delete-control.test.ts +79 -0
  313. package/test/app/confirm-modal.test.tsx +219 -0
  314. package/test/app/connectors-ui.e2e.test.ts +508 -0
  315. package/test/app/conversations-sidebar-game-modal.test.tsx +260 -0
  316. package/test/app/conversations-sidebar.test.tsx +160 -0
  317. package/test/app/custom-actions-smoke.test.ts +387 -0
  318. package/test/app/custom-avatar-api-client.test.ts +207 -0
  319. package/test/app/desktop-utils.test.ts +145 -0
  320. package/test/app/electrobun-rpc-bridge.test.ts +83 -0
  321. package/test/app/events.test.ts +88 -0
  322. package/test/app/export-import-flows.e2e.test.ts +700 -0
  323. package/test/app/fine-tuning-view.test.ts +471 -0
  324. package/test/app/game-view-auth-session.test.tsx +186 -0
  325. package/test/app/game-view.test.ts +444 -0
  326. package/test/app/global-emote-overlay.test.tsx +106 -0
  327. package/test/app/header-status.test.tsx +149 -0
  328. package/test/app/i18n.test.ts +152 -0
  329. package/test/app/inventory-bsc-view.test.ts +940 -0
  330. package/test/app/knowledge-ui.e2e.test.ts +762 -0
  331. package/test/app/knowledge-upload-helpers.test.ts +124 -0
  332. package/test/app/lifecycle-lock.test.ts +267 -0
  333. package/test/app/lifo-popout-utils.test.ts +208 -0
  334. package/test/app/lifo-safe-endpoint.test.ts +34 -0
  335. package/test/app/loading-screen.test.tsx +45 -0
  336. package/test/app/memory-monitor.test.ts +332 -0
  337. package/test/app/navigation.test.tsx +22 -0
  338. package/test/app/onboarding-finish-lock.test.ts +663 -0
  339. package/test/app/onboarding-language.test.tsx +160 -0
  340. package/test/app/onboarding-steps.test.tsx +375 -0
  341. package/test/app/open-external-url.test.ts +65 -0
  342. package/test/app/pages-navigation-smoke.e2e.test.ts +633 -0
  343. package/test/app/pairing-lock.test.ts +260 -0
  344. package/test/app/pairing-view.test.tsx +74 -0
  345. package/test/app/permissions-section.test.ts +432 -0
  346. package/test/app/plugin-bridge.test.ts +109 -0
  347. package/test/app/plugins-ui.e2e.test.ts +605 -0
  348. package/test/app/plugins-view-game-modal.test.tsx +650 -0
  349. package/test/app/plugins-view-toggle-restart.test.ts +129 -0
  350. package/test/app/provider-dropdown-default.test.tsx +302 -0
  351. package/test/app/restart-banner.test.tsx +197 -0
  352. package/test/app/retake-capture.test.ts +84 -0
  353. package/test/app/sandbox-api-client.test.ts +108 -0
  354. package/test/app/save-command-modal.test.tsx +109 -0
  355. package/test/app/secrets-view.test.tsx +92 -0
  356. package/test/app/settings-control-styles.test.tsx +142 -0
  357. package/test/app/settings-reset.e2e.test.ts +726 -0
  358. package/test/app/settings-sections.e2e.test.ts +614 -0
  359. package/test/app/shared-format.test.ts +44 -0
  360. package/test/app/shared-switch.test.ts +69 -0
  361. package/test/app/shell-mode-switching.e2e.test.ts +829 -0
  362. package/test/app/shell-mode-tab-memory.test.tsx +58 -0
  363. package/test/app/shell-overlays.test.tsx +50 -0
  364. package/test/app/shortcuts-overlay.test.tsx +111 -0
  365. package/test/app/sse-interruption.test.ts +122 -0
  366. package/test/app/startup-asset-missing.e2e.test.ts +126 -0
  367. package/test/app/startup-backend-missing.e2e.test.ts +118 -0
  368. package/test/app/startup-chat.e2e.test.ts +305 -0
  369. package/test/app/startup-conversation-restore.test.tsx +344 -0
  370. package/test/app/startup-failure-view.test.tsx +103 -0
  371. package/test/app/startup-onboarding.e2e.test.ts +618 -0
  372. package/test/app/startup-timeout.test.tsx +80 -0
  373. package/test/app/startup-token-401.e2e.test.ts +103 -0
  374. package/test/app/stream-helpers.test.ts +46 -0
  375. package/test/app/stream-popout-navigation.test.tsx +41 -0
  376. package/test/app/stream-status-bar.test.tsx +89 -0
  377. package/test/app/theme-toggle.test.tsx +33 -0
  378. package/test/app/training-api-client.test.ts +128 -0
  379. package/test/app/trajectories-view.test.tsx +220 -0
  380. package/test/app/triggers-api-client.test.ts +77 -0
  381. package/test/app/triggers-navigation.test.ts +113 -0
  382. package/test/app/triggers-view.e2e.test.ts +674 -0
  383. package/test/app/update-channel-lock.test.ts +259 -0
  384. package/test/app/vector-browser.async-cleanup.test.tsx +367 -0
  385. package/test/app/vector-browser.e2e.test.ts +653 -0
  386. package/test/app/vrm-stage.test.tsx +351 -0
  387. package/test/app/vrm-viewer.test.tsx +298 -0
  388. package/test/app/wallet-api-save-lock.test.ts +298 -0
  389. package/test/app/wallet-hooks.test.ts +405 -0
  390. package/test/app/wallet-ui-flows.e2e.test.ts +556 -0
  391. package/test/avatar/asset-url.test.ts +90 -0
  392. package/test/avatar/avatar-selector.test.ts +173 -0
  393. package/test/avatar/mixamo-vrm-rig-map.test.ts +111 -0
  394. package/test/avatar/voice-chat-streaming-text.test.ts +96 -0
  395. package/test/avatar/voice-chat.test.ts +391 -0
  396. package/test/ui/command-palette-commands.test.ts +57 -0
  397. package/test/ui/ui-renderer.test.ts +39 -0
  398. package/tsconfig.build.json +19 -0
  399. package/tsconfig.json +20 -0
@@ -0,0 +1,218 @@
1
+ /**
2
+ * React hook for managing the overlay layout.
3
+ *
4
+ * Persistence strategy (dual-layer):
5
+ * 1. **Server API** (`GET/POST /api/stream/overlay-layout`) — authoritative
6
+ * source that persists across headless browser restarts on a VPS.
7
+ * 2. **localStorage** (`milady.stream.overlay-layout.v1`) — fast local cache,
8
+ * used as initial state and fallback when the server is unreachable.
9
+ *
10
+ * On mount the hook loads from localStorage (instant), then fetches from the
11
+ * server. If the server has a layout, it wins. Mutations write to both.
12
+ *
13
+ * When `destinationId` is provided, the hook reads/writes destination-specific
14
+ * storage (both localStorage and server). Falls back to the global default.
15
+ */
16
+
17
+ import { client } from "@elizaos/app-core/api";
18
+ import { useCallback, useEffect, useRef, useState } from "react";
19
+ import { getAllWidgets } from "./registry";
20
+ import type { OverlayLayout, WidgetInstance, WidgetPosition } from "./types";
21
+
22
+ function storageKey(destinationId?: string | null): string {
23
+ const base = "milady.stream.overlay-layout.v1";
24
+ return destinationId ? `${base}.${destinationId}` : base;
25
+ }
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Default layout — ThoughtBubble + Branding enabled, rest disabled
29
+ // ---------------------------------------------------------------------------
30
+
31
+ let _idCounter = 0;
32
+ function localId(): string {
33
+ _idCounter += 1;
34
+ return `w${Date.now().toString(36)}${_idCounter.toString(36)}`;
35
+ }
36
+
37
+ function buildDefaultLayout(): OverlayLayout {
38
+ const widgets: WidgetInstance[] = getAllWidgets().map((def) => ({
39
+ id: localId(),
40
+ type: def.type,
41
+ enabled: def.type === "thought-bubble" || def.type === "branding",
42
+ position: { ...def.defaultPosition },
43
+ zIndex: def.defaultZIndex,
44
+ config: { ...def.defaultConfig },
45
+ }));
46
+
47
+ return { version: 1, name: "Default", widgets };
48
+ }
49
+
50
+ function loadLayoutLocal(destinationId?: string | null): OverlayLayout {
51
+ try {
52
+ const raw = localStorage.getItem(storageKey(destinationId));
53
+ if (raw) {
54
+ const parsed = JSON.parse(raw) as OverlayLayout;
55
+ if (parsed.version === 1 && Array.isArray(parsed.widgets)) return parsed;
56
+ }
57
+ } catch {
58
+ // corrupted — fall through to default
59
+ }
60
+ return buildDefaultLayout();
61
+ }
62
+
63
+ function saveLayoutLocal(
64
+ layout: OverlayLayout,
65
+ destinationId?: string | null,
66
+ ): void {
67
+ try {
68
+ localStorage.setItem(storageKey(destinationId), JSON.stringify(layout));
69
+ } catch {
70
+ // storage full — silently skip
71
+ }
72
+ }
73
+
74
+ /** Best-effort save to server. Non-blocking, non-fatal. */
75
+ function saveLayoutServer(
76
+ layout: OverlayLayout,
77
+ destinationId?: string | null,
78
+ ): void {
79
+ client.saveOverlayLayout(layout, destinationId).catch(() => {
80
+ // Server may be unavailable (e.g. Electron dev mode) — ignore
81
+ });
82
+ }
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // Hook
86
+ // ---------------------------------------------------------------------------
87
+
88
+ export interface UseOverlayLayout {
89
+ layout: OverlayLayout;
90
+ addWidget: (type: string) => void;
91
+ removeWidget: (id: string) => void;
92
+ toggleWidget: (id: string) => void;
93
+ updateWidget: (
94
+ id: string,
95
+ patch: Partial<Pick<WidgetInstance, "position" | "zIndex" | "config">>,
96
+ ) => void;
97
+ moveWidget: (id: string, position: WidgetPosition) => void;
98
+ resetLayout: () => void;
99
+ }
100
+
101
+ export function useOverlayLayout(
102
+ destinationId?: string | null,
103
+ ): UseOverlayLayout {
104
+ const [layout, setLayout] = useState<OverlayLayout>(() =>
105
+ loadLayoutLocal(destinationId),
106
+ );
107
+ const serverFetched = useRef<string | null | undefined>(undefined);
108
+
109
+ // Re-fetch when destinationId changes
110
+ useEffect(() => {
111
+ // Reset to local cache for new destination
112
+ setLayout(loadLayoutLocal(destinationId));
113
+ serverFetched.current = undefined;
114
+ }, [destinationId]);
115
+
116
+ // On mount / destination change: try to fetch authoritative layout from server
117
+ useEffect(() => {
118
+ if (serverFetched.current === destinationId) return;
119
+ serverFetched.current = destinationId;
120
+
121
+ client
122
+ .getOverlayLayout(destinationId)
123
+ .then((res) => {
124
+ const remote = res.layout as OverlayLayout | null;
125
+ if (remote && remote.version === 1 && Array.isArray(remote.widgets)) {
126
+ setLayout(remote);
127
+ saveLayoutLocal(remote, destinationId);
128
+ }
129
+ })
130
+ .catch(() => {
131
+ // Server unavailable — use local/default layout
132
+ });
133
+ }, [destinationId]);
134
+
135
+ // Persist to both layers on change (skip the initial load from useEffect)
136
+ const isInitialMount = useRef(true);
137
+ useEffect(() => {
138
+ if (isInitialMount.current) {
139
+ isInitialMount.current = false;
140
+ return;
141
+ }
142
+ saveLayoutLocal(layout, destinationId);
143
+ saveLayoutServer(layout, destinationId);
144
+ }, [layout, destinationId]);
145
+
146
+ const addWidget = useCallback((type: string) => {
147
+ const defs = getAllWidgets();
148
+ const def = defs.find((d) => d.type === type);
149
+ if (!def) return;
150
+
151
+ const instance: WidgetInstance = {
152
+ id: localId(),
153
+ type: def.type,
154
+ enabled: true,
155
+ position: { ...def.defaultPosition },
156
+ zIndex: def.defaultZIndex,
157
+ config: { ...def.defaultConfig },
158
+ };
159
+
160
+ setLayout((prev) => ({
161
+ ...prev,
162
+ widgets: [...prev.widgets, instance],
163
+ }));
164
+ }, []);
165
+
166
+ const removeWidget = useCallback((id: string) => {
167
+ setLayout((prev) => ({
168
+ ...prev,
169
+ widgets: prev.widgets.filter((w) => w.id !== id),
170
+ }));
171
+ }, []);
172
+
173
+ const toggleWidget = useCallback((id: string) => {
174
+ setLayout((prev) => ({
175
+ ...prev,
176
+ widgets: prev.widgets.map((w) =>
177
+ w.id === id ? { ...w, enabled: !w.enabled } : w,
178
+ ),
179
+ }));
180
+ }, []);
181
+
182
+ const updateWidget = useCallback(
183
+ (
184
+ id: string,
185
+ patch: Partial<Pick<WidgetInstance, "position" | "zIndex" | "config">>,
186
+ ) => {
187
+ setLayout((prev) => ({
188
+ ...prev,
189
+ widgets: prev.widgets.map((w) =>
190
+ w.id === id ? { ...w, ...patch } : w,
191
+ ),
192
+ }));
193
+ },
194
+ [],
195
+ );
196
+
197
+ const moveWidget = useCallback((id: string, position: WidgetPosition) => {
198
+ setLayout((prev) => ({
199
+ ...prev,
200
+ widgets: prev.widgets.map((w) => (w.id === id ? { ...w, position } : w)),
201
+ }));
202
+ }, []);
203
+
204
+ const resetLayout = useCallback(() => {
205
+ const fresh = buildDefaultLayout();
206
+ setLayout(fresh);
207
+ }, []);
208
+
209
+ return {
210
+ layout,
211
+ addWidget,
212
+ removeWidget,
213
+ toggleWidget,
214
+ updateWidget,
215
+ moveWidget,
216
+ resetLayout,
217
+ };
218
+ }
@@ -0,0 +1,50 @@
1
+ export function formatTrajectoryDuration(ms: number | null): string {
2
+ if (ms === null) return "—";
3
+ if (ms < 1000) return `${ms}ms`;
4
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
5
+ return `${(ms / 60000).toFixed(1)}m`;
6
+ }
7
+
8
+ export function formatTrajectoryTimestamp(
9
+ iso: string,
10
+ mode: "smart" | "detailed",
11
+ ): string {
12
+ const date = new Date(iso);
13
+
14
+ if (mode === "smart") {
15
+ const now = new Date();
16
+ const isToday = date.toDateString() === now.toDateString();
17
+
18
+ if (isToday) {
19
+ return date.toLocaleTimeString(undefined, {
20
+ hour: "2-digit",
21
+ minute: "2-digit",
22
+ second: "2-digit",
23
+ });
24
+ }
25
+
26
+ return date.toLocaleString(undefined, {
27
+ month: "short",
28
+ day: "numeric",
29
+ hour: "2-digit",
30
+ minute: "2-digit",
31
+ });
32
+ }
33
+
34
+ return date.toLocaleString(undefined, {
35
+ month: "short",
36
+ day: "numeric",
37
+ hour: "2-digit",
38
+ minute: "2-digit",
39
+ second: "2-digit",
40
+ });
41
+ }
42
+
43
+ export function formatTrajectoryTokenCount(
44
+ count: number | undefined,
45
+ options: { emptyLabel: string },
46
+ ): string {
47
+ if (count === undefined || count === 0) return options.emptyLabel;
48
+ if (count < 1000) return String(count);
49
+ return `${(count / 1000).toFixed(1)}k`;
50
+ }
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Shared UI primitives for compact labels, pills, and status dots.
3
+ */
4
+
5
+ import type { ReactNode } from "react";
6
+
7
+ type StatusTone = "success" | "warning" | "danger" | "muted";
8
+
9
+ type StatusToneStyles = {
10
+ badge: string;
11
+ dot: string;
12
+ };
13
+
14
+ const STATUS_TONES: Record<StatusTone, StatusToneStyles> = {
15
+ success: {
16
+ badge:
17
+ "text-[var(--ok,#16a34a)] border border-[var(--ok,#16a34a)]/30 bg-[var(--ok,#16a34a)]/10",
18
+ dot: "bg-[var(--ok,#16a34a)]",
19
+ },
20
+ warning: {
21
+ badge: "text-[#f59e0b] border border-[#f59e0b]/30 bg-[#f59e0b]/10",
22
+ dot: "bg-[#f59e0b]",
23
+ },
24
+ danger: {
25
+ badge: "text-[#e74c3c] border border-[#e74c3c]/30 bg-[#e74c3c]/10",
26
+ dot: "bg-[#e74c3c]",
27
+ },
28
+ muted: {
29
+ badge: "text-[var(--muted)] border border-[var(--border)] bg-[var(--bg)]",
30
+ dot: "bg-[var(--muted)]",
31
+ },
32
+ };
33
+
34
+ export function statusToneForBoolean(
35
+ condition: boolean,
36
+ onTone: StatusTone = "success",
37
+ offTone: StatusTone = "muted",
38
+ ): StatusTone {
39
+ return condition ? onTone : offTone;
40
+ }
41
+
42
+ export function StatusBadge({
43
+ label,
44
+ tone,
45
+ withDot = false,
46
+ className = "",
47
+ }: {
48
+ label: string;
49
+ tone: StatusTone;
50
+ withDot?: boolean;
51
+ className?: string;
52
+ }) {
53
+ const toneStyles = STATUS_TONES[tone];
54
+ return (
55
+ <span
56
+ className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-sm text-[10px] font-bold uppercase ${toneStyles.badge} ${className}`}
57
+ >
58
+ {withDot && (
59
+ <span className={`w-1.5 h-1.5 rounded-full ${toneStyles.dot}`} />
60
+ )}
61
+ {label}
62
+ </span>
63
+ );
64
+ }
65
+
66
+ export function StatusDot({
67
+ status,
68
+ className = "",
69
+ }: {
70
+ status: string;
71
+ className?: string;
72
+ }) {
73
+ const tone =
74
+ status === "success" || status === "completed" || status === "connected"
75
+ ? "success"
76
+ : status === "error" || status === "failed" || status === "denied"
77
+ ? "danger"
78
+ : "muted";
79
+
80
+ const toneStyles = STATUS_TONES[tone];
81
+ return (
82
+ <span
83
+ className={`inline-block w-2 h-2 rounded-full ${toneStyles.dot} ${className}`}
84
+ />
85
+ );
86
+ }
87
+
88
+ export function StatCard({
89
+ label,
90
+ value,
91
+ accent = false,
92
+ }: {
93
+ label: string;
94
+ value: ReactNode;
95
+ accent?: boolean;
96
+ }) {
97
+ return (
98
+ <div className="flex flex-col items-center justify-center p-3 border border-[var(--border)] bg-[var(--bg)] min-w-[80px]">
99
+ <div
100
+ className={`text-lg font-bold tabular-nums ${accent ? "text-txt" : ""}`}
101
+ >
102
+ {value}
103
+ </div>
104
+ <div className="text-[10px] text-[var(--muted)] uppercase tracking-wide mt-0.5">
105
+ {label}
106
+ </div>
107
+ </div>
108
+ );
109
+ }
@@ -0,0 +1,57 @@
1
+ import type { ButtonHTMLAttributes } from "react";
2
+
3
+ type SwitchSize = "default" | "compact";
4
+
5
+ type SwitchProps = Omit<
6
+ ButtonHTMLAttributes<HTMLButtonElement>,
7
+ "type" | "onChange" | "onClick" | "role" | "aria-checked"
8
+ > & {
9
+ checked: boolean;
10
+ onChange: (next: boolean) => void;
11
+ size?: SwitchSize;
12
+ trackOnClass?: string;
13
+ trackOffClass?: string;
14
+ knobClass?: string;
15
+ disabledClassName?: string;
16
+ };
17
+
18
+ const SIZE_CLASS: Record<SwitchSize, string> = {
19
+ default: "w-10 h-5",
20
+ compact: "w-9 h-5 border-2 border-transparent",
21
+ };
22
+
23
+ const KNOB_TRAVEL_CLASS: Record<SwitchSize, string> = {
24
+ default: "translate-x-5",
25
+ compact: "translate-x-4",
26
+ };
27
+
28
+ export function Switch({
29
+ checked,
30
+ onChange,
31
+ size = "default",
32
+ trackOnClass = "bg-[var(--accent)]",
33
+ trackOffClass = "bg-[var(--border)]",
34
+ knobClass = "bg-white",
35
+ disabledClassName = "opacity-40 cursor-default",
36
+ disabled,
37
+ className = "",
38
+ ...buttonProps
39
+ }: SwitchProps) {
40
+ return (
41
+ <button
42
+ {...buttonProps}
43
+ type="button"
44
+ role="switch"
45
+ aria-checked={checked}
46
+ disabled={disabled}
47
+ className={`relative inline-flex shrink-0 rounded-full transition-colors duration-200 focus:outline-none ${SIZE_CLASS[size]} ${checked ? trackOnClass : trackOffClass} ${disabled ? disabledClassName : "cursor-pointer"} ${className}`}
48
+ onClick={() => {
49
+ if (!disabled) onChange(!checked);
50
+ }}
51
+ >
52
+ <span
53
+ className={`pointer-events-none absolute top-0.5 left-0.5 h-4 w-4 rounded-full transition-transform duration-200 ${knobClass} ${checked ? KNOB_TRAVEL_CLASS[size] : ""}`}
54
+ />
55
+ </button>
56
+ );
57
+ }
@@ -0,0 +1,27 @@
1
+ import * as THREE from "three";
2
+
3
+ export { THREE };
4
+
5
+ type WebGpuRendererCtor = new (options?: {
6
+ antialias?: boolean;
7
+ }) => THREE.WebGLRenderer & { init?: () => Promise<void> };
8
+
9
+ export async function createVectorBrowserRenderer(): Promise<THREE.WebGLRenderer> {
10
+ if (typeof navigator !== "undefined" && navigator.gpu) {
11
+ try {
12
+ const webgpuModule = (await import("three/webgpu")) as unknown as {
13
+ WebGPURenderer?: WebGpuRendererCtor;
14
+ };
15
+ const WebGPURenderer = webgpuModule.WebGPURenderer;
16
+ if (WebGPURenderer) {
17
+ const renderer = new WebGPURenderer({ antialias: true });
18
+ await renderer.init?.();
19
+ return renderer;
20
+ }
21
+ } catch {
22
+ // Fall through to WebGL in environments without WebGPU support.
23
+ }
24
+ }
25
+
26
+ return new THREE.WebGLRenderer({ antialias: true });
27
+ }