@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,250 @@
1
+ /**
2
+ * Chat command utilities — slash command parsing, saved command management,
3
+ * and the typed command registry.
4
+ *
5
+ * Migrated from apps/app/src/chat-commands.ts and command-registry.ts.
6
+ */
7
+
8
+ import type { Tab } from "../navigation";
9
+
10
+ const ROUTINE_CODING_AGENT_RE =
11
+ /^\[.+?\] (?:Approved:|Responded:|Sent keys:|Turn done, continuing:|Idle for \d+[smh])/;
12
+
13
+ // ── Saved custom commands ────────────────────────────────────────────────
14
+
15
+ export const CUSTOM_COMMANDS_STORAGE_KEY = "milady:custom-commands";
16
+
17
+ export interface SavedCustomCommand {
18
+ name: string;
19
+ text: string;
20
+ createdAt: number;
21
+ }
22
+
23
+ function isSavedCustomCommand(value: unknown): value is SavedCustomCommand {
24
+ if (!value || typeof value !== "object") return false;
25
+ const candidate = value as Record<string, unknown>;
26
+ return (
27
+ typeof candidate.name === "string" &&
28
+ typeof candidate.text === "string" &&
29
+ typeof candidate.createdAt === "number"
30
+ );
31
+ }
32
+
33
+ export function loadSavedCustomCommands(): SavedCustomCommand[] {
34
+ try {
35
+ const raw = localStorage.getItem(CUSTOM_COMMANDS_STORAGE_KEY);
36
+ if (!raw) return [];
37
+ const parsed = JSON.parse(raw);
38
+ if (!Array.isArray(parsed)) return [];
39
+ return parsed.filter(isSavedCustomCommand);
40
+ } catch {
41
+ return [];
42
+ }
43
+ }
44
+
45
+ export function saveSavedCustomCommands(commands: SavedCustomCommand[]): void {
46
+ localStorage.setItem(CUSTOM_COMMANDS_STORAGE_KEY, JSON.stringify(commands));
47
+ }
48
+
49
+ export function appendSavedCustomCommand(command: SavedCustomCommand): void {
50
+ const existing = loadSavedCustomCommands();
51
+ existing.push(command);
52
+ saveSavedCustomCommands(existing);
53
+ }
54
+
55
+ export function normalizeSlashCommandName(value: string): string {
56
+ const trimmed = value.trim();
57
+ if (!trimmed) return "";
58
+ const withoutSlash = trimmed.startsWith("/") ? trimmed.slice(1) : trimmed;
59
+ return withoutSlash.trim().toLowerCase();
60
+ }
61
+
62
+ export function expandSavedCustomCommand(
63
+ template: string,
64
+ argsRaw: string,
65
+ ): string {
66
+ const args = argsRaw.trim();
67
+ if (!args) {
68
+ return template;
69
+ }
70
+ if (template.includes("{{args}}")) {
71
+ return template.replaceAll("{{args}}", args);
72
+ }
73
+ return `${template}\n${args}`;
74
+ }
75
+
76
+ export function splitCommandArgs(raw: string): string[] {
77
+ const tokens: string[] = [];
78
+ const re = /"([^"]*)"|'([^']*)'|(\S+)/g;
79
+ let match: RegExpExecArray | null = re.exec(raw);
80
+ while (match) {
81
+ tokens.push(match[1] ?? match[2] ?? match[3] ?? "");
82
+ match = re.exec(raw);
83
+ }
84
+ return tokens;
85
+ }
86
+
87
+ export function isRoutineCodingAgentMessage(message: {
88
+ source?: string;
89
+ text: string;
90
+ }): boolean {
91
+ return (
92
+ message.source === "coding-agent" &&
93
+ ROUTINE_CODING_AGENT_RE.test(message.text)
94
+ );
95
+ }
96
+
97
+ // ── Typed command registry ───────────────────────────────────────────────
98
+
99
+ export type CommandCategory = "agent" | "navigation" | "refresh" | "utility";
100
+
101
+ export interface CommandDef {
102
+ id: string;
103
+ label: string;
104
+ category: CommandCategory;
105
+ /** Keyboard shortcut hint shown in palette / tooltips. */
106
+ shortcut?: string;
107
+ /** Extra hint text (e.g., current state). */
108
+ hint?: string;
109
+ }
110
+
111
+ export interface CommandItem extends CommandDef {
112
+ action: () => void;
113
+ }
114
+
115
+ // Static navigation commands — always present; palette builder binds setTab.
116
+ export const NAV_COMMANDS: readonly { id: string; label: string; tab: Tab }[] =
117
+ [
118
+ { id: "nav-chat", label: "Open Chat", tab: "chat" },
119
+ { id: "nav-apps", label: "Open Apps", tab: "apps" },
120
+ { id: "nav-character", label: "Open Character", tab: "character" },
121
+ { id: "nav-triggers", label: "Open Heartbeats", tab: "triggers" },
122
+ { id: "nav-wallets", label: "Open Wallets", tab: "wallets" },
123
+ { id: "nav-knowledge", label: "Open Knowledge", tab: "knowledge" },
124
+ { id: "nav-connectors", label: "Open Connectors", tab: "connectors" },
125
+ { id: "nav-plugins", label: "Open Plugins", tab: "plugins" },
126
+ { id: "nav-settings", label: "Open Settings", tab: "settings" },
127
+ { id: "nav-database", label: "Open Database", tab: "database" },
128
+ { id: "nav-logs", label: "Open Logs", tab: "logs" },
129
+ { id: "nav-security", label: "Open Security", tab: "security" },
130
+ ] as const;
131
+
132
+ export interface BuildCommandsArgs {
133
+ agentState: string;
134
+ activeGameViewerUrl: string;
135
+ handleStart: () => void;
136
+
137
+ handleRestart: () => void;
138
+ setTab: (tab: Tab) => void;
139
+ setAppsSubTab: () => void;
140
+ loadPlugins: () => void;
141
+ loadSkills: () => void;
142
+ loadLogs: () => void;
143
+ loadWorkbench: () => void;
144
+ handleChatClear: () => void;
145
+ openBugReport: () => void;
146
+ }
147
+
148
+ export function buildCommands(args: BuildCommandsArgs): CommandItem[] {
149
+ const {
150
+ agentState,
151
+ activeGameViewerUrl,
152
+ handleStart,
153
+
154
+ handleRestart,
155
+ setTab,
156
+ setAppsSubTab,
157
+ loadPlugins,
158
+ loadSkills,
159
+ loadLogs,
160
+ loadWorkbench,
161
+ handleChatClear,
162
+ openBugReport,
163
+ } = args;
164
+
165
+ const commands: CommandItem[] = [];
166
+ // Agent control
167
+ if (agentState === "stopped" || agentState === "not_started") {
168
+ commands.push({
169
+ id: "start-agent",
170
+ label: "Start Agent",
171
+ category: "agent",
172
+ action: handleStart,
173
+ });
174
+ }
175
+ commands.push({
176
+ id: "restart-agent",
177
+ label: "Restart Agent",
178
+ category: "agent",
179
+ shortcut: "Ctrl+R",
180
+ action: handleRestart,
181
+ });
182
+
183
+ // Navigation
184
+ for (const nav of NAV_COMMANDS) {
185
+ commands.push({
186
+ id: nav.id,
187
+ label: nav.label,
188
+ category: "navigation",
189
+ action: () => setTab(nav.tab),
190
+ });
191
+ }
192
+
193
+ if (activeGameViewerUrl.trim()) {
194
+ commands.push({
195
+ id: "nav-current-game",
196
+ label: "Open Current Game",
197
+ category: "navigation",
198
+ action: () => {
199
+ setTab("apps");
200
+ setAppsSubTab();
201
+ },
202
+ });
203
+ }
204
+
205
+ // Refresh
206
+ commands.push(
207
+ {
208
+ id: "refresh-plugins",
209
+ label: "Refresh Features",
210
+ category: "refresh",
211
+ action: loadPlugins,
212
+ },
213
+ {
214
+ id: "refresh-skills",
215
+ label: "Refresh Skills",
216
+ category: "refresh",
217
+ action: loadSkills,
218
+ },
219
+ {
220
+ id: "refresh-logs",
221
+ label: "Refresh Logs",
222
+ category: "refresh",
223
+ action: loadLogs,
224
+ },
225
+ {
226
+ id: "refresh-workbench",
227
+ label: "Refresh Workbench",
228
+ category: "refresh",
229
+ action: loadWorkbench,
230
+ },
231
+ );
232
+
233
+ // Utility
234
+ commands.push(
235
+ {
236
+ id: "chat-clear",
237
+ label: "Clear Chat",
238
+ category: "utility",
239
+ action: handleChatClear,
240
+ },
241
+ {
242
+ id: "report-bug",
243
+ label: "Report Bug",
244
+ category: "utility",
245
+ action: openBugReport,
246
+ },
247
+ );
248
+
249
+ return commands;
250
+ }
@@ -0,0 +1,43 @@
1
+ /**
2
+ * PTY session hydration — maps server task data to CodingAgentSession objects.
3
+ *
4
+ * Migrated from apps/app/src/pty-session-hydrate.ts.
5
+ */
6
+
7
+ import type { CodingAgentSession } from "../api/client";
8
+
9
+ /** Statuses that represent a finished session — excluded from hydration. */
10
+ export const TERMINAL_STATUSES = new Set(["completed", "stopped", "error"]);
11
+
12
+ /** Shape of a task object returned by the /api/coding-agents/status endpoint. */
13
+ export interface ServerTask {
14
+ sessionId: string;
15
+ agentType?: string;
16
+ label?: string;
17
+ originalTask?: string;
18
+ workdir?: string;
19
+ status?: string;
20
+ decisionCount?: number;
21
+ autoResolvedCount?: number;
22
+ }
23
+
24
+ /**
25
+ * Filters out terminal sessions and maps server task data to CodingAgentSession objects.
26
+ * Extracted from AppContext so it can be tested independently.
27
+ */
28
+ export function mapServerTasksToSessions(
29
+ tasks: ServerTask[],
30
+ ): CodingAgentSession[] {
31
+ return tasks
32
+ .filter((t) => !TERMINAL_STATUSES.has(t.status ?? ""))
33
+ .map((t) => ({
34
+ sessionId: t.sessionId,
35
+ agentType: t.agentType ?? "claude",
36
+ label: t.label ?? t.sessionId,
37
+ originalTask: t.originalTask ?? "",
38
+ workdir: t.workdir ?? "",
39
+ status: (t.status ?? "active") as CodingAgentSession["status"],
40
+ decisionCount: t.decisionCount ?? 0,
41
+ autoResolvedCount: t.autoResolvedCount ?? 0,
42
+ }));
43
+ }
@@ -0,0 +1,362 @@
1
+ /**
2
+ * AdvancedPageView — container for advanced configuration sub-tabs.
3
+ *
4
+ * Sub-tabs:
5
+ * - Plugins: Feature/connector plugin management
6
+ * - Skills: Custom agent skills
7
+ * - Fine-Tuning: Dataset and model training workflows
8
+ * - Trajectories: LLM call viewer and analysis
9
+ * - Runtime: Runtime object inspection
10
+ * - Databases: Tables/media/vector browser
11
+ * - Lifo: Browser-native terminal sandbox
12
+ * - Logs: Runtime log viewer
13
+ */
14
+
15
+ import {
16
+ DatabasePageView,
17
+ LogsPageView,
18
+ PluginsPageView,
19
+ RuntimeView,
20
+ SkillsView,
21
+ } from "@elizaos/app-core/components";
22
+ import type { Tab } from "@elizaos/app-core/navigation";
23
+ import { useApp } from "@elizaos/app-core/state";
24
+ import React, { type ReactNode, useState } from "react";
25
+ import { CustomActionsView } from "./CustomActionsView";
26
+ import { FineTuningView } from "./FineTuningView";
27
+ import { LifoSandboxView } from "./LifoSandboxView";
28
+ import { TrajectoriesView } from "./TrajectoriesView";
29
+ import { TrajectoryDetailView } from "./TrajectoryDetailView";
30
+
31
+ type SubTab =
32
+ | "plugins"
33
+ | "skills"
34
+ | "fine-tuning"
35
+ | "trajectories"
36
+ | "runtime"
37
+ | "database"
38
+ | "lifo"
39
+ | "logs"
40
+ | "security";
41
+
42
+ const SUB_TABS: Array<{ id: SubTab; label: string; description: string }> = [
43
+ { id: "plugins", label: "Plugins", description: "Features and connectors" },
44
+ { id: "skills", label: "Skills", description: "Custom agent skills" },
45
+ // {
46
+ // id: "fine-tuning",
47
+ // label: "Fine-Tuning",
48
+ // description: "Dataset and model training workflows",
49
+ // },
50
+ {
51
+ id: "trajectories",
52
+ label: "Trajectories",
53
+ description: "LLM call history and analysis",
54
+ },
55
+ {
56
+ id: "runtime",
57
+ label: "Runtime",
58
+ description: "Deep runtime object introspection and load order",
59
+ },
60
+ {
61
+ id: "database",
62
+ label: "Database",
63
+ description: "Tables, media, and vector browser",
64
+ },
65
+ // {
66
+ // id: "lifo",
67
+ // label: "Lifo",
68
+ // description: "Browser-native shell sandbox and file explorer",
69
+ // },
70
+ { id: "logs", label: "Logs", description: "Runtime and service logs" },
71
+ ];
72
+
73
+ const MODAL_SUB_TABS = SUB_TABS.filter(
74
+ (t) => t.id !== "plugins" && t.id !== "skills",
75
+ );
76
+
77
+ const SUBTAB_ICONS: Record<string, ReactNode> = {
78
+ actions: (
79
+ <svg
80
+ width="20"
81
+ height="20"
82
+ viewBox="0 0 24 24"
83
+ fill="none"
84
+ stroke="currentColor"
85
+ strokeWidth="2"
86
+ strokeLinecap="round"
87
+ strokeLinejoin="round"
88
+ aria-hidden="true"
89
+ >
90
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2" />
91
+ </svg>
92
+ ),
93
+ "fine-tuning": (
94
+ <svg
95
+ width="20"
96
+ height="20"
97
+ viewBox="0 0 24 24"
98
+ fill="none"
99
+ stroke="currentColor"
100
+ strokeWidth="2"
101
+ strokeLinecap="round"
102
+ strokeLinejoin="round"
103
+ aria-hidden="true"
104
+ >
105
+ <line x1="4" y1="21" x2="4" y2="14" />
106
+ <line x1="4" y1="10" x2="4" y2="3" />
107
+ <line x1="12" y1="21" x2="12" y2="12" />
108
+ <line x1="12" y1="8" x2="12" y2="3" />
109
+ <line x1="20" y1="21" x2="20" y2="16" />
110
+ <line x1="20" y1="12" x2="20" y2="3" />
111
+ <line x1="1" y1="14" x2="7" y2="14" />
112
+ <line x1="9" y1="8" x2="15" y2="8" />
113
+ <line x1="17" y1="16" x2="23" y2="16" />
114
+ </svg>
115
+ ),
116
+ trajectories: (
117
+ <svg
118
+ width="20"
119
+ height="20"
120
+ viewBox="0 0 24 24"
121
+ fill="none"
122
+ stroke="currentColor"
123
+ strokeWidth="2"
124
+ strokeLinecap="round"
125
+ strokeLinejoin="round"
126
+ aria-hidden="true"
127
+ >
128
+ <circle cx="6" cy="19" r="3" />
129
+ <path d="M9 19h8.5a3.5 3.5 0 0 0 0-7h-11a3.5 3.5 0 0 1 0-7H15" />
130
+ <circle cx="18" cy="5" r="3" />
131
+ </svg>
132
+ ),
133
+ runtime: (
134
+ <svg
135
+ width="20"
136
+ height="20"
137
+ viewBox="0 0 24 24"
138
+ fill="none"
139
+ stroke="currentColor"
140
+ strokeWidth="2"
141
+ strokeLinecap="round"
142
+ strokeLinejoin="round"
143
+ aria-hidden="true"
144
+ >
145
+ <polyline points="4 17 10 11 4 5" />
146
+ <line x1="12" y1="19" x2="20" y2="19" />
147
+ </svg>
148
+ ),
149
+ database: (
150
+ <svg
151
+ width="20"
152
+ height="20"
153
+ viewBox="0 0 24 24"
154
+ fill="none"
155
+ stroke="currentColor"
156
+ strokeWidth="2"
157
+ strokeLinecap="round"
158
+ strokeLinejoin="round"
159
+ aria-hidden="true"
160
+ >
161
+ <ellipse cx="12" cy="5" rx="9" ry="3" />
162
+ <path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
163
+ <path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
164
+ </svg>
165
+ ),
166
+ lifo: (
167
+ <svg
168
+ width="20"
169
+ height="20"
170
+ viewBox="0 0 24 24"
171
+ fill="none"
172
+ stroke="currentColor"
173
+ strokeWidth="2"
174
+ strokeLinecap="round"
175
+ strokeLinejoin="round"
176
+ aria-hidden="true"
177
+ >
178
+ <rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
179
+ <line x1="8" y1="21" x2="16" y2="21" />
180
+ <line x1="12" y1="17" x2="12" y2="21" />
181
+ </svg>
182
+ ),
183
+ logs: (
184
+ <svg
185
+ width="20"
186
+ height="20"
187
+ viewBox="0 0 24 24"
188
+ fill="none"
189
+ stroke="currentColor"
190
+ strokeWidth="2"
191
+ strokeLinecap="round"
192
+ strokeLinejoin="round"
193
+ aria-hidden="true"
194
+ >
195
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
196
+ <polyline points="14 2 14 8 20 8" />
197
+ <line x1="16" y1="13" x2="8" y2="13" />
198
+ <line x1="16" y1="17" x2="8" y2="17" />
199
+ <polyline points="10 9 9 9 8 9" />
200
+ </svg>
201
+ ),
202
+ security: (
203
+ <svg
204
+ width="20"
205
+ height="20"
206
+ viewBox="0 0 24 24"
207
+ fill="none"
208
+ stroke="currentColor"
209
+ strokeWidth="2"
210
+ strokeLinecap="round"
211
+ strokeLinejoin="round"
212
+ aria-hidden="true"
213
+ >
214
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
215
+ </svg>
216
+ ),
217
+ };
218
+
219
+ function mapTabToSubTab(tab: Tab): SubTab {
220
+ switch (tab) {
221
+ case "plugins":
222
+ return "plugins";
223
+ case "skills":
224
+ return "skills";
225
+ case "fine-tuning":
226
+ return "fine-tuning";
227
+ case "trajectories":
228
+ return "trajectories";
229
+ case "runtime":
230
+ return "runtime";
231
+ case "database":
232
+ return "database";
233
+ case "lifo":
234
+ return "lifo";
235
+ case "logs":
236
+ return "logs";
237
+ default:
238
+ return "plugins";
239
+ }
240
+ }
241
+
242
+ export function AdvancedPageView({ inModal }: { inModal?: boolean } = {}) {
243
+ const { tab, setTab } = useApp();
244
+ const [selectedTrajectoryId, setSelectedTrajectoryId] = useState<
245
+ string | null
246
+ >(null);
247
+
248
+ const currentSubTab = mapTabToSubTab(tab);
249
+ const tabs = inModal ? MODAL_SUB_TABS : SUB_TABS;
250
+
251
+ const handleSubTabChange = (subTab: SubTab) => {
252
+ setSelectedTrajectoryId(null);
253
+ setTab(subTab as Tab);
254
+ };
255
+
256
+ const renderContent = () => {
257
+ switch (currentSubTab) {
258
+ case "plugins":
259
+ return <PluginsPageView />;
260
+ case "skills":
261
+ return <SkillsView />;
262
+ case "fine-tuning":
263
+ return <FineTuningView />;
264
+ case "trajectories":
265
+ if (selectedTrajectoryId) {
266
+ return (
267
+ <TrajectoryDetailView
268
+ trajectoryId={selectedTrajectoryId}
269
+ onBack={() => setSelectedTrajectoryId(null)}
270
+ />
271
+ );
272
+ }
273
+ return (
274
+ <TrajectoriesView onSelectTrajectory={setSelectedTrajectoryId} />
275
+ );
276
+ case "runtime":
277
+ return <RuntimeView />;
278
+ case "database":
279
+ return <DatabasePageView />;
280
+ case "lifo":
281
+ return <LifoSandboxView />;
282
+ case "logs":
283
+ return <LogsPageView />;
284
+ default:
285
+ return inModal ? <CustomActionsView /> : <PluginsPageView />;
286
+ }
287
+ };
288
+
289
+ return (
290
+ <div
291
+ className={
292
+ inModal ? "settings-modal-layout" : "flex flex-col h-full min-h-0"
293
+ }
294
+ >
295
+ {inModal ? (
296
+ <nav className="settings-icon-sidebar">
297
+ {tabs.map((subTab) => (
298
+ <button
299
+ key={subTab.id}
300
+ type="button"
301
+ className={`advanced-subtab-btn settings-icon-btn ${currentSubTab === subTab.id ? "is-active" : ""}`}
302
+ onClick={() => handleSubTabChange(subTab.id)}
303
+ title={subTab.description}
304
+ >
305
+ {SUBTAB_ICONS[subTab.id]}
306
+ <span className="settings-icon-label">{subTab.label}</span>
307
+ </button>
308
+ ))}
309
+ </nav>
310
+ ) : (
311
+ <div className="mb-4 shrink-0">
312
+ <div className="flex gap-1 border-b border-border">
313
+ {tabs.map((subTab) => {
314
+ const isActive = currentSubTab === subTab.id;
315
+ return (
316
+ <button
317
+ type="button"
318
+ key={subTab.id}
319
+ className={`advanced-subtab-btn px-4 py-2 text-xs font-medium border-b-2 -mb-px transition-colors ${
320
+ isActive
321
+ ? "border-accent text-txt"
322
+ : "border-transparent text-muted hover:text-txt hover:border-border"
323
+ }`}
324
+ onClick={() => handleSubTabChange(subTab.id)}
325
+ title={subTab.description}
326
+ >
327
+ {subTab.label}
328
+ </button>
329
+ );
330
+ })}
331
+ </div>
332
+ </div>
333
+ )}
334
+
335
+ <div
336
+ className={
337
+ inModal ? "settings-content-area" : "flex-1 min-h-0 overflow-y-auto"
338
+ }
339
+ style={
340
+ inModal
341
+ ? ({
342
+ "--accent": "#7b8fb5",
343
+ "--surface": "rgba(255, 255, 255, 0.06)",
344
+ "--s-accent": "#7b8fb5",
345
+ "--s-text-txt": "#7b8fb5",
346
+ "--s-accent-glow": "rgba(123, 143, 181, 0.35)",
347
+ "--s-accent-subtle": "rgba(123, 143, 181, 0.12)",
348
+ "--s-grid-line": "rgba(123, 143, 181, 0.02)",
349
+ "--s-glow-edge": "rgba(123, 143, 181, 0.08)",
350
+ } as React.CSSProperties)
351
+ : undefined
352
+ }
353
+ >
354
+ {inModal ? (
355
+ <div className="settings-section-pane pt-4">{renderContent()}</div>
356
+ ) : (
357
+ renderContent()
358
+ )}
359
+ </div>
360
+ </div>
361
+ );
362
+ }
@@ -0,0 +1,49 @@
1
+ import type { CodingAgentSession } from "@elizaos/app-core/api";
2
+
3
+ /** Status dot color classes for coding-agent activity. */
4
+ const STATUS_DOT: Record<string, string> = {
5
+ active: "bg-ok",
6
+ tool_running: "bg-accent",
7
+ blocked: "bg-warn",
8
+ error: "bg-danger",
9
+ };
10
+
11
+ const PULSE_STATUSES = new Set(["active", "tool_running"]);
12
+
13
+ /** Derive activity text for sessions hydrated from the server (no lastActivity yet). */
14
+ function deriveActivity(s: CodingAgentSession): string {
15
+ if (s.status === "tool_running" && s.toolDescription) {
16
+ return `Running ${s.toolDescription}`.slice(0, 60);
17
+ }
18
+ if (s.status === "blocked") return "Waiting for input";
19
+ if (s.status === "error") return "Error";
20
+ return "Running";
21
+ }
22
+
23
+ interface AgentActivityBoxProps {
24
+ sessions: CodingAgentSession[];
25
+ }
26
+
27
+ export function AgentActivityBox({ sessions }: AgentActivityBoxProps) {
28
+ if (!sessions || sessions.length === 0) return null;
29
+
30
+ return (
31
+ <div className="border-t border-border px-3 py-1.5 space-y-0.5 z-[1]">
32
+ {sessions.map((s) => (
33
+ <div key={s.sessionId} className="flex items-center gap-1.5 min-w-0">
34
+ <span
35
+ className={`inline-block w-1.5 h-1.5 rounded-full shrink-0 ${
36
+ STATUS_DOT[s.status] ?? "bg-muted"
37
+ }${PULSE_STATUSES.has(s.status) ? " animate-pulse" : ""}`}
38
+ />
39
+ <span className="text-[11px] font-medium text-txt max-w-[120px] truncate shrink-0">
40
+ {s.label}
41
+ </span>
42
+ <span className="text-[11px] text-muted truncate min-w-0">
43
+ {s.lastActivity ?? deriveActivity(s)}
44
+ </span>
45
+ </div>
46
+ ))}
47
+ </div>
48
+ );
49
+ }