@elizaos/ui 2.0.3-beta.5 → 2.0.3-beta.7

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 (232) hide show
  1. package/App.d.ts.map +1 -1
  2. package/App.js +30 -4
  3. package/api/app-shell-capabilities.d.ts +9 -0
  4. package/api/app-shell-capabilities.d.ts.map +1 -0
  5. package/api/app-shell-capabilities.js +39 -0
  6. package/api/auth-client.d.ts.map +1 -1
  7. package/api/auth-client.js +4 -1
  8. package/api/client-agent.d.ts.map +1 -1
  9. package/api/client-agent.js +35 -24
  10. package/api/client-base.d.ts +36 -0
  11. package/api/client-base.d.ts.map +1 -1
  12. package/api/client-base.js +79 -0
  13. package/api/client-chat.d.ts.map +1 -1
  14. package/api/client-chat.js +14 -5
  15. package/api/client-cloud.d.ts +49 -0
  16. package/api/client-cloud.d.ts.map +1 -1
  17. package/api/client-cloud.js +73 -6
  18. package/api/client-local-inference.d.ts.map +1 -1
  19. package/api/client-local-inference.js +5 -1
  20. package/api/desktop-external-api-base.d.ts +4 -0
  21. package/api/desktop-external-api-base.d.ts.map +1 -0
  22. package/api/desktop-external-api-base.js +43 -0
  23. package/api/desktop-http-transport.d.ts.map +1 -1
  24. package/api/desktop-http-transport.js +2 -28
  25. package/api/i18n-locale-client.d.ts.map +1 -1
  26. package/api/i18n-locale-client.js +12 -0
  27. package/cloud/billing/components/billing-tab.d.ts.map +1 -1
  28. package/cloud/billing/components/billing-tab.js +11 -14
  29. package/cloud/connectors/discord-gateway-connection.d.ts.map +1 -1
  30. package/cloud/connectors/discord-gateway-connection.js +39 -5
  31. package/cloud/connectors/index.d.ts +9 -0
  32. package/cloud/connectors/index.d.ts.map +1 -1
  33. package/cloud/connectors/index.js +14 -1
  34. package/cloud/handoff/run-cloud-agent-handoff.d.ts +10 -1
  35. package/cloud/handoff/run-cloud-agent-handoff.d.ts.map +1 -1
  36. package/cloud/handoff/run-cloud-agent-handoff.js +43 -7
  37. package/cloud/handoff/silent-repoint.d.ts +33 -0
  38. package/cloud/handoff/silent-repoint.d.ts.map +1 -0
  39. package/cloud/handoff/silent-repoint.js +55 -0
  40. package/cloud/instances/AgentDetailPage.d.ts.map +1 -1
  41. package/cloud/instances/AgentDetailPage.js +2 -2
  42. package/cloud/instances/components/agent-actions.d.ts.map +1 -1
  43. package/cloud/instances/components/agent-actions.js +1 -4
  44. package/cloud/instances/components/eliza-agents-table.d.ts.map +1 -1
  45. package/cloud/instances/components/eliza-agents-table.js +1 -10
  46. package/cloud/instances/index.d.ts +2 -5
  47. package/cloud/instances/index.d.ts.map +1 -1
  48. package/cloud/instances/index.js +2 -12
  49. package/cloud/organization/invite-member-dialog.d.ts.map +1 -1
  50. package/cloud/organization/invite-member-dialog.js +2 -5
  51. package/cloud/organization/members-tab.d.ts.map +1 -1
  52. package/cloud/organization/members-tab.js +4 -7
  53. package/cloud/public-pages/pages/app-auth/app-authorize-page.d.ts +9 -0
  54. package/cloud/public-pages/pages/app-auth/app-authorize-page.d.ts.map +1 -1
  55. package/cloud/public-pages/pages/app-auth/app-authorize-page.js +11 -1
  56. package/cloud/register-all.d.ts +0 -1
  57. package/cloud/register-all.d.ts.map +1 -1
  58. package/cloud/register-all.js +3 -7
  59. package/cloud/settings/index.d.ts +5 -6
  60. package/cloud/settings/index.d.ts.map +1 -1
  61. package/cloud/settings/index.js +5 -6
  62. package/cloud/settings/register-cloud-settings.d.ts +2 -2
  63. package/cloud/settings/register-cloud-settings.d.ts.map +1 -1
  64. package/cloud/settings/register-cloud-settings.js +127 -121
  65. package/cloud/shell/CloudRouterShell.d.ts.map +1 -1
  66. package/cloud/shell/CloudRouterShell.js +5 -0
  67. package/cloud-ui/components/drawer.d.ts.map +1 -1
  68. package/cloud-ui/components/drawer.js +1 -1
  69. package/cloud-ui/index.d.ts +0 -1
  70. package/cloud-ui/index.d.ts.map +1 -1
  71. package/cloud-ui/index.js +0 -1
  72. package/components/apps/app-identity.helpers.d.ts.map +1 -1
  73. package/components/apps/app-identity.helpers.js +8 -0
  74. package/components/chat/widgets/inbox-unread.d.ts.map +1 -1
  75. package/components/chat/widgets/inbox-unread.js +8 -1
  76. package/components/chat/widgets/needs-attention.d.ts.map +1 -1
  77. package/components/chat/widgets/needs-attention.js +18 -2
  78. package/components/chat/widgets/relationships-attention.d.ts.map +1 -1
  79. package/components/chat/widgets/relationships-attention.js +5 -0
  80. package/components/composites/chat/chat-composer.js +15 -15
  81. package/components/config-ui/ui-renderer.d.ts.map +1 -1
  82. package/components/config-ui/ui-renderer.js +1 -1
  83. package/components/local-inference/useHomeModelStatus.d.ts.map +1 -1
  84. package/components/local-inference/useHomeModelStatus.js +31 -1
  85. package/components/pages/SettingsView.d.ts.map +1 -1
  86. package/components/pages/SettingsView.js +1 -4
  87. package/components/pages/Springboard.d.ts.map +1 -1
  88. package/components/pages/Springboard.js +17 -1
  89. package/components/pages/SpringboardSurface.d.ts.map +1 -1
  90. package/components/pages/SpringboardSurface.js +14 -3
  91. package/components/settings/CloudAgentsSection.d.ts.map +1 -1
  92. package/components/settings/CloudAgentsSection.js +6 -8
  93. package/components/settings/CloudOverviewSection.d.ts +2 -0
  94. package/components/settings/CloudOverviewSection.d.ts.map +1 -0
  95. package/components/settings/CloudOverviewSection.js +81 -0
  96. package/components/settings/ConnectorsSection.d.ts +19 -0
  97. package/components/settings/ConnectorsSection.d.ts.map +1 -1
  98. package/components/settings/ConnectorsSection.js +72 -27
  99. package/components/settings/settings-sections.d.ts.map +1 -1
  100. package/components/settings/settings-sections.js +26 -4
  101. package/components/shell/ComputerUseApprovalOverlay.d.ts.map +1 -1
  102. package/components/shell/ComputerUseApprovalOverlay.js +12 -2
  103. package/components/shell/ContinuousChatOverlay.d.ts.map +1 -1
  104. package/components/shell/ContinuousChatOverlay.js +41 -8
  105. package/components/shell/ShellHeaderControls.d.ts.map +1 -1
  106. package/components/shell/ShellHeaderControls.js +1 -1
  107. package/components/shell/StartupFailureView.d.ts.map +1 -1
  108. package/components/shell/StartupFailureView.js +4 -2
  109. package/components/shell/__e2e__/home-screen-fixture.catalog-stub.d.ts +2 -0
  110. package/components/shell/__e2e__/home-screen-fixture.catalog-stub.d.ts.map +1 -1
  111. package/components/shell/__e2e__/home-screen-fixture.catalog-stub.js +8 -0
  112. package/components/views/ViewTileImage.d.ts +4 -4
  113. package/components/views/ViewTileImage.d.ts.map +1 -1
  114. package/components/views/ViewTileImage.js +26 -9
  115. package/config/boot-config-store.d.ts +10 -0
  116. package/config/boot-config-store.d.ts.map +1 -1
  117. package/config/boot-config-store.js +1 -1
  118. package/first-run/CompactOnboarding.d.ts.map +1 -1
  119. package/first-run/CompactOnboarding.js +4 -2
  120. package/first-run/use-first-run-controller.d.ts +1 -0
  121. package/first-run/use-first-run-controller.d.ts.map +1 -1
  122. package/first-run/use-first-run-controller.js +133 -56
  123. package/hooks/useAvailableViews.d.ts +11 -2
  124. package/hooks/useAvailableViews.d.ts.map +1 -1
  125. package/hooks/useAvailableViews.js +49 -7
  126. package/hooks/useHorizontalPager.d.ts.map +1 -1
  127. package/hooks/useHorizontalPager.js +11 -4
  128. package/hooks/useViewCatalog.d.ts.map +1 -1
  129. package/hooks/useViewCatalog.js +5 -2
  130. package/hooks/view-catalog.d.ts +2 -0
  131. package/hooks/view-catalog.d.ts.map +1 -1
  132. package/hooks/view-catalog.js +1 -0
  133. package/index.d.ts +0 -1
  134. package/index.d.ts.map +1 -1
  135. package/index.js +0 -1
  136. package/layouts/content-layout/content-layout.d.ts.map +1 -1
  137. package/layouts/content-layout/content-layout.js +2 -1
  138. package/package.json +10 -10
  139. package/platform/browser-launch.d.ts.map +1 -1
  140. package/platform/browser-launch.js +2 -0
  141. package/state/AppContext.js +6 -4
  142. package/state/startup-coordinator.d.ts +2 -0
  143. package/state/startup-coordinator.d.ts.map +1 -1
  144. package/state/startup-coordinator.js +8 -0
  145. package/state/startup-first-run-options.d.ts +4 -0
  146. package/state/startup-first-run-options.d.ts.map +1 -0
  147. package/state/startup-first-run-options.js +18 -0
  148. package/state/startup-phase-hydrate.d.ts.map +1 -1
  149. package/state/startup-phase-hydrate.js +25 -14
  150. package/state/startup-phase-poll.d.ts.map +1 -1
  151. package/state/startup-phase-poll.js +60 -0
  152. package/state/startup-phase-restore.d.ts.map +1 -1
  153. package/state/startup-phase-restore.js +6 -19
  154. package/state/types.d.ts +0 -17
  155. package/state/types.d.ts.map +1 -1
  156. package/state/types.js +0 -13
  157. package/state/use-startup-shell-controller.d.ts.map +1 -1
  158. package/state/use-startup-shell-controller.js +3 -2
  159. package/state/useAppShellState.d.ts +5 -1
  160. package/state/useAppShellState.d.ts.map +1 -1
  161. package/state/useAppShellState.js +11 -3
  162. package/state/useChatCallbacks.d.ts +1 -0
  163. package/state/useChatCallbacks.d.ts.map +1 -1
  164. package/state/useChatCallbacks.js +53 -8
  165. package/state/useChatLifecycle.d.ts +1 -0
  166. package/state/useChatLifecycle.d.ts.map +1 -1
  167. package/state/useChatLifecycle.js +2 -2
  168. package/state/useChatSend.d.ts.map +1 -1
  169. package/state/useChatSend.js +72 -8
  170. package/state/useCloudState.d.ts.map +1 -1
  171. package/state/useCloudState.js +29 -1
  172. package/state/useDataLoaders.d.ts.map +1 -1
  173. package/state/useDataLoaders.js +9 -0
  174. package/state/useFirstRunCallbacks.d.ts.map +1 -1
  175. package/state/useFirstRunCallbacks.js +5 -0
  176. package/state/useLifecycleState.d.ts +0 -7
  177. package/state/useLifecycleState.d.ts.map +1 -1
  178. package/state/useLifecycleState.js +0 -24
  179. package/state/usePluginsSkillsState.d.ts +2 -2
  180. package/state/useWalletState.d.ts +3 -1
  181. package/state/useWalletState.d.ts.map +1 -1
  182. package/state/useWalletState.js +4 -2
  183. package/storybook/mock-providers.d.ts.map +1 -1
  184. package/storybook/mock-providers.js +2 -0
  185. package/styles/electrobun-mac-window-drag.css +7 -0
  186. package/widgets/WidgetHost.d.ts.map +1 -1
  187. package/widgets/WidgetHost.js +21 -3
  188. package/cloud/documents/DocumentsRoute.d.ts +0 -21
  189. package/cloud/documents/DocumentsRoute.d.ts.map +0 -1
  190. package/cloud/documents/DocumentsRoute.js +0 -45
  191. package/cloud/documents/DocumentsSection.d.ts +0 -15
  192. package/cloud/documents/DocumentsSection.d.ts.map +0 -1
  193. package/cloud/documents/DocumentsSection.js +0 -18
  194. package/cloud/documents/components/document-list.d.ts +0 -19
  195. package/cloud/documents/components/document-list.d.ts.map +0 -1
  196. package/cloud/documents/components/document-list.js +0 -75
  197. package/cloud/documents/components/document-query.d.ts +0 -15
  198. package/cloud/documents/components/document-query.d.ts.map +0 -1
  199. package/cloud/documents/components/document-query.js +0 -92
  200. package/cloud/documents/components/document-upload.d.ts +0 -16
  201. package/cloud/documents/components/document-upload.d.ts.map +0 -1
  202. package/cloud/documents/components/document-upload.js +0 -180
  203. package/cloud/documents/components/documents-page-client.d.ts +0 -20
  204. package/cloud/documents/components/documents-page-client.d.ts.map +0 -1
  205. package/cloud/documents/components/documents-page-client.js +0 -80
  206. package/cloud/documents/index.d.ts +0 -37
  207. package/cloud/documents/index.d.ts.map +0 -1
  208. package/cloud/documents/index.js +0 -45
  209. package/cloud/documents/lib/agents.d.ts +0 -23
  210. package/cloud/documents/lib/agents.d.ts.map +0 -1
  211. package/cloud/documents/lib/agents.js +0 -26
  212. package/cloud/documents/lib/documents.d.ts +0 -54
  213. package/cloud/documents/lib/documents.d.ts.map +0 -1
  214. package/cloud/documents/lib/documents.js +0 -118
  215. package/cloud/instances/AgentChatPage.d.ts +0 -13
  216. package/cloud/instances/AgentChatPage.d.ts.map +0 -1
  217. package/cloud/instances/AgentChatPage.js +0 -217
  218. package/cloud-ui/components/image-gen/empty-state.d.ts +0 -3
  219. package/cloud-ui/components/image-gen/empty-state.d.ts.map +0 -1
  220. package/cloud-ui/components/image-gen/empty-state.js +0 -12
  221. package/cloud-ui/components/image-gen/enhanced-loading.d.ts +0 -14
  222. package/cloud-ui/components/image-gen/enhanced-loading.d.ts.map +0 -1
  223. package/cloud-ui/components/image-gen/enhanced-loading.js +0 -23
  224. package/cloud-ui/components/image-gen/index.d.ts +0 -5
  225. package/cloud-ui/components/image-gen/index.d.ts.map +0 -1
  226. package/cloud-ui/components/image-gen/index.js +0 -4
  227. package/cloud-ui/components/image-gen/loading-state.d.ts +0 -2
  228. package/cloud-ui/components/image-gen/loading-state.d.ts.map +0 -1
  229. package/cloud-ui/components/image-gen/loading-state.js +0 -11
  230. package/cloud-ui/components/image-gen/prompt-input.d.ts +0 -32
  231. package/cloud-ui/components/image-gen/prompt-input.d.ts.map +0 -1
  232. package/cloud-ui/components/image-gen/prompt-input.js +0 -24
@@ -0,0 +1,81 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Bot, Cloud, CreditCard, KeyRound, Plug, Rocket, Store, } from "lucide-react";
3
+ import { useCallback } from "react";
4
+ import { useAgentElement } from "../../agent-surface/index.js";
5
+ import { useAppSelectorShallow } from "../../state/index.js";
6
+ import { Button } from "../ui/button.js";
7
+ import { SettingsGroup, SettingsRow, SettingsStack } from "./settings-layout.js";
8
+ const CLOUD_FEATURES = [
9
+ {
10
+ icon: Plug,
11
+ label: "Hosted connectors",
12
+ description: "Run Discord, Telegram, Twilio, WhatsApp, Google, and Microsoft connections through hosted Cloud infrastructure.",
13
+ },
14
+ {
15
+ icon: Bot,
16
+ label: "Cloud agents",
17
+ description: "Keep agents online when this Mac is asleep and switch between hosted agents from every device.",
18
+ },
19
+ {
20
+ icon: KeyRound,
21
+ label: "API keys and app publishing",
22
+ description: "Create Cloud API keys, register apps, and connect external products to your agents.",
23
+ },
24
+ {
25
+ icon: CreditCard,
26
+ label: "Credits and billing",
27
+ description: "Use shared Cloud inference, track spend, and configure top-ups from one account.",
28
+ },
29
+ {
30
+ icon: Store,
31
+ label: "Marketplace and monetization",
32
+ description: "Publish apps, sell capabilities, and unlock creator revenue surfaces as they roll out.",
33
+ },
34
+ ];
35
+ export function CloudOverviewSection() {
36
+ const { elizaCloudConnected, elizaCloudLoginBusy, handleCloudLogin, setActionNotice, t, } = useAppSelectorShallow((s) => ({
37
+ elizaCloudConnected: s.elizaCloudConnected,
38
+ elizaCloudLoginBusy: s.elizaCloudLoginBusy,
39
+ handleCloudLogin: s.handleCloudLogin,
40
+ setActionNotice: s.setActionNotice,
41
+ t: s.t,
42
+ }));
43
+ const handleConnect = useCallback(() => {
44
+ void handleCloudLogin().catch((error) => {
45
+ setActionNotice(error instanceof Error ? error.message : "Could not start Cloud login.", "error", 5000);
46
+ });
47
+ }, [handleCloudLogin, setActionNotice]);
48
+ const { ref, agentProps } = useAgentElement({
49
+ id: "cloud-connect",
50
+ role: "button",
51
+ label: elizaCloudConnected ? "Open Eliza Cloud" : "Connect Eliza Cloud",
52
+ group: "cloud",
53
+ status: elizaCloudConnected ? "connected" : "available",
54
+ onActivate: elizaCloudLoginBusy ? undefined : handleConnect,
55
+ });
56
+ return (_jsxs(SettingsStack, { children: [_jsx(SettingsGroup, { title: t("settings.cloudOverview.title", {
57
+ defaultValue: "Eliza Cloud",
58
+ }), description: t("settings.cloudOverview.description", {
59
+ defaultValue: "Keep Milady local-first, then add hosted services when you want always-on agents, managed connectors, publishing, and account-backed inference.",
60
+ }), action: _jsxs(Button, { ref: ref, size: "sm", onClick: handleConnect, disabled: elizaCloudLoginBusy, ...agentProps, children: [_jsx(Cloud, { className: "h-4 w-4", "aria-hidden": true }), elizaCloudLoginBusy
61
+ ? t("settings.cloudOverview.connecting", {
62
+ defaultValue: "Connecting...",
63
+ })
64
+ : elizaCloudConnected
65
+ ? t("settings.cloudOverview.connectedCta", {
66
+ defaultValue: "Cloud connected",
67
+ })
68
+ : t("settings.cloudOverview.connectCta", {
69
+ defaultValue: "Connect Cloud",
70
+ })] }), children: _jsx(SettingsRow, { icon: Rocket, label: t("settings.cloudOverview.localModeLabel", {
71
+ defaultValue: elizaCloudConnected
72
+ ? "Cloud is connected"
73
+ : "Local mode is active",
74
+ }), description: t("settings.cloudOverview.localModeDescription", {
75
+ defaultValue: elizaCloudConnected
76
+ ? "Milady can use Cloud account features while keeping this local runtime available."
77
+ : "This build keeps agent runtime and local connectors on your machine unless you choose to connect Cloud.",
78
+ }) }) }), _jsx(SettingsGroup, { title: t("settings.cloudOverview.unlockTitle", {
79
+ defaultValue: "Unlock with Cloud",
80
+ }), children: CLOUD_FEATURES.map((feature) => (_jsx(SettingsRow, { icon: feature.icon, label: feature.label, description: feature.description }, feature.label))) })] }));
81
+ }
@@ -5,5 +5,24 @@
5
5
  * polymorphism for runtime type branching) explicitly allows this for
6
6
  * adapter/target registries.
7
7
  */
8
+ import type { ConnectorMode } from "../connectors/ConnectorModeSelector.helpers.js";
9
+ /**
10
+ * Whether Settings → Connectors should render the generic plugin-config (env
11
+ * credential) form for the selected connector mode.
12
+ *
13
+ * The form is shown ONLY for a `local-config` mode whose setup target is the
14
+ * plugin itself and that actually declares parameters. Every other mode kind —
15
+ * `local-setup` (iMessage Full-Disk-Access status, Signal/WhatsApp QR pairing,
16
+ * Discord/Telegram desktop panels), `plugin-managed` account lists, and
17
+ * `cloud-managed` gateways — keeps its dedicated {@link ConnectorSetupPanel}
18
+ * surface. Gating on the mode KIND rather than the incidental
19
+ * "this plugin declares parameters" is what keeps those dedicated panels
20
+ * reachable instead of being overwritten by a raw env form.
21
+ */
22
+ export declare function shouldRenderConnectorConfigForm(args: {
23
+ managementMode: ConnectorMode["managementMode"];
24
+ hasParameters: boolean;
25
+ setupTargetsPlugin: boolean;
26
+ }): boolean;
8
27
  export declare function ConnectorsSection(): import("react/jsx-runtime").JSX.Element;
9
28
  //# sourceMappingURL=ConnectorsSection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ConnectorsSection.d.ts","sourceRoot":"","sources":["../../../../../../src/components/settings/ConnectorsSection.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAkMH,wBAAgB,iBAAiB,4CAuGhC"}
1
+ {"version":3,"file":"ConnectorsSection.d.ts","sourceRoot":"","sources":["../../../../../../src/components/settings/ConnectorsSection.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6CAA6C,CAAC;AAoBjF;;;;;;;;;;;;GAYG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE;IACpD,cAAc,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;IAChD,aAAa,EAAE,OAAO,CAAC;IACvB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,GAAG,OAAO,CAMV;AA2PD,wBAAgB,iBAAiB,4CAuGhC"}
@@ -6,21 +6,39 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  * polymorphism for runtime type branching) explicitly allows this for
7
7
  * adapter/target registries.
8
8
  */
9
- import { Puzzle } from "lucide-react";
9
+ import { Puzzle, Save } from "lucide-react";
10
10
  import { forwardRef, useCallback, useEffect, useMemo, useRef, useState, } from "react";
11
11
  import { useAgentElement } from "../../agent-surface/index.js";
12
12
  import { clearPendingFocusConnector, FOCUS_CONNECTOR_EVENT, readPendingFocusConnector, } from "../../events/index.js";
13
13
  import { useAppSelector } from "../../state/index.js";
14
- import { BlueBubblesStatusPanel } from "../connectors/BlueBubblesStatusPanel.js";
15
- import { DiscordLocalConnectorPanel } from "../connectors/DiscordLocalConnectorPanel.js";
16
- import { IMessageStatusPanel } from "../connectors/IMessageStatusPanel.js";
17
- import { SignalQrOverlay } from "../connectors/SignalQrOverlay.js";
18
- import { TelegramAccountConnectorPanel } from "../connectors/TelegramAccountConnectorPanel.js";
19
- import { WhatsAppQrOverlay } from "../connectors/WhatsAppQrOverlay.js";
14
+ import { ConnectorModeSelector } from "../connectors/ConnectorModeSelector.js";
15
+ import { useConnectorMode } from "../connectors/ConnectorModeSelector.hooks.js";
16
+ import { ConnectorSetupPanel } from "../connectors/ConnectorSetupPanel.js";
17
+ import { hasConnectorSetupPanel } from "../connectors/ConnectorSetupPanel.helpers.js";
20
18
  import { getBrandIcon } from "../conversations/brand-icons.js";
19
+ import { PluginConfigForm, TelegramPluginConfig, } from "../pages/PluginConfigForm.js";
21
20
  import { ALWAYS_ON_PLUGIN_IDS, iconImageSource, resolveIcon, } from "../pages/plugin-list-utils.js";
21
+ import { Button } from "../ui/button.js";
22
22
  import { Switch } from "../ui/switch.js";
23
23
  import { SettingsGroup, SettingsRow, SettingsStack } from "./settings-layout.js";
24
+ /**
25
+ * Whether Settings → Connectors should render the generic plugin-config (env
26
+ * credential) form for the selected connector mode.
27
+ *
28
+ * The form is shown ONLY for a `local-config` mode whose setup target is the
29
+ * plugin itself and that actually declares parameters. Every other mode kind —
30
+ * `local-setup` (iMessage Full-Disk-Access status, Signal/WhatsApp QR pairing,
31
+ * Discord/Telegram desktop panels), `plugin-managed` account lists, and
32
+ * `cloud-managed` gateways — keeps its dedicated {@link ConnectorSetupPanel}
33
+ * surface. Gating on the mode KIND rather than the incidental
34
+ * "this plugin declares parameters" is what keeps those dedicated panels
35
+ * reachable instead of being overwritten by a raw env form.
36
+ */
37
+ export function shouldRenderConnectorConfigForm(args) {
38
+ return (args.managementMode === "local-config" &&
39
+ args.hasParameters &&
40
+ args.setupTargetsPlugin);
41
+ }
24
42
  function statusTone(plugin) {
25
43
  if (!plugin.enabled)
26
44
  return "off";
@@ -50,38 +68,65 @@ function connectorIcon(plugin) {
50
68
  const icon = resolveIcon(plugin);
51
69
  const imageSrc = typeof icon === "string" ? iconImageSource(icon) : undefined;
52
70
  const Inner = typeof icon === "string" || !icon ? null : icon;
53
- return forwardRef(function ConnectorMedallionIcon({ className }) {
71
+ return forwardRef(function ConnectorMedallionIcon({ className }, ref) {
54
72
  if (Brand)
55
73
  return _jsx(Brand, { className: className });
56
74
  if (imageSrc)
57
75
  return (_jsx("img", { src: imageSrc, alt: "", className: "h-[18px] w-[18px] shrink-0 rounded-sm object-contain" }));
58
76
  const IconComponent = Inner;
59
77
  if (IconComponent)
60
- return _jsx(IconComponent, { className: className });
61
- return _jsx(Puzzle, { className: className, "aria-hidden": true });
78
+ return _jsx(IconComponent, { ref: ref, className: className });
79
+ return _jsx(Puzzle, { ref: ref, className: className, "aria-hidden": true });
62
80
  });
63
81
  }
64
82
  function ConnectorBody({ plugin }) {
65
83
  const t = useAppSelector((s) => s.t);
66
- switch (plugin.id) {
67
- case "telegram":
68
- return _jsx(TelegramAccountConnectorPanel, {});
69
- case "discord":
70
- return _jsx(DiscordLocalConnectorPanel, {});
71
- case "imessage":
72
- return _jsx(IMessageStatusPanel, {});
73
- case "bluebubbles":
74
- return _jsx(BlueBubblesStatusPanel, {});
75
- case "signal":
76
- return _jsx(SignalQrOverlay, {});
77
- case "whatsapp":
78
- return _jsx(WhatsAppQrOverlay, {});
79
- default:
80
- return (_jsx("div", { className: "text-xs-tight text-muted", children: t("settings.sections.connectors.ownSetupSurface", {
84
+ const elizaCloudConnected = useAppSelector((s) => s.elizaCloudConnected);
85
+ const handlePluginConfigSave = useAppSelector((s) => s.handlePluginConfigSave);
86
+ const pluginSaving = useAppSelector((s) => s.pluginSaving);
87
+ const pluginSaveSuccess = useAppSelector((s) => s.pluginSaveSuccess);
88
+ const [pluginConfigs, setPluginConfigs] = useState({});
89
+ const connectorMode = useConnectorMode(plugin.id, { elizaCloudConnected });
90
+ const setupPluginId = connectorMode.setupPluginId;
91
+ const setupPanel = setupPluginId && hasConnectorSetupPanel(setupPluginId) ? (_jsx(ConnectorSetupPanel, { pluginId: setupPluginId })) : null;
92
+ const selectedMode = connectorMode.modes.find((mode) => mode.id === connectorMode.selectedMode);
93
+ const showPluginConfig = shouldRenderConnectorConfigForm({
94
+ managementMode: selectedMode?.managementMode,
95
+ hasParameters: plugin.parameters.length > 0,
96
+ setupTargetsPlugin: setupPluginId === plugin.id,
97
+ });
98
+ const pendingConfig = pluginConfigs[plugin.id] ?? {};
99
+ const hasPendingConfig = Object.keys(pendingConfig).length > 0;
100
+ const isSaving = pluginSaving.has(plugin.id);
101
+ const didSave = pluginSaveSuccess.has(plugin.id);
102
+ const handleParamChange = useCallback((pluginId, paramKey, value) => {
103
+ setPluginConfigs((prev) => ({
104
+ ...prev,
105
+ [pluginId]: { ...prev[pluginId], [paramKey]: value },
106
+ }));
107
+ }, []);
108
+ const handleSave = useCallback(async () => {
109
+ await handlePluginConfigSave(plugin.id, pendingConfig);
110
+ setPluginConfigs((prev) => {
111
+ const next = { ...prev };
112
+ delete next[plugin.id];
113
+ return next;
114
+ });
115
+ }, [handlePluginConfigSave, pendingConfig, plugin.id]);
116
+ return (_jsxs("div", { className: "space-y-4", children: [connectorMode.modes.length > 1 ? (_jsx(ConnectorModeSelector, { connectorId: plugin.id, selectedMode: connectorMode.selectedMode, onModeChange: connectorMode.setSelectedMode, elizaCloudConnected: elizaCloudConnected })) : null, showPluginConfig ? (_jsxs("div", { className: "space-y-3", children: [plugin.id === "telegram" ? (_jsx(TelegramPluginConfig, { plugin: plugin, pluginConfigs: pluginConfigs, onParamChange: handleParamChange })) : (_jsx(PluginConfigForm, { plugin: plugin, pluginConfigs: pluginConfigs, onParamChange: handleParamChange })), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs(Button, { variant: "default", size: "sm", className: "h-8 gap-1.5 rounded-sm px-4 text-xs-tight font-semibold", onClick: () => {
117
+ void handleSave();
118
+ }, disabled: !hasPendingConfig || isSaving, children: [_jsx(Save, { className: "h-3.5 w-3.5", "aria-hidden": "true" }), isSaving
119
+ ? t("common.saving", { defaultValue: "Saving..." })
120
+ : didSave
121
+ ? t("pluginsview.Saved", { defaultValue: "Saved" })
122
+ : t("pluginsview.SaveSettings", {
123
+ defaultValue: "Save settings",
124
+ })] }), plugin.id === "discord" ? (_jsx("span", { className: "text-xs-tight text-muted", children: t("settings.sections.connectors.discordAppIdHint", {
125
+ defaultValue: "Application ID is optional; it is auto-resolved from the bot token when possible.",
126
+ }) })) : null] })] })) : setupPanel ? (setupPanel) : (_jsx("div", { className: "text-xs-tight text-muted", children: t("settings.sections.connectors.ownSetupSurface", {
81
127
  defaultValue: "{{name}} uses its own setup surface.",
82
128
  name: plugin.name,
83
- }) }));
84
- }
129
+ }) }))] }));
85
130
  }
86
131
  function ConnectorEnableSwitch({ plugin, busy, onToggle, }) {
87
132
  const t = useAppSelector((s) => s.t);
@@ -1 +1 @@
1
- {"version":3,"file":"settings-sections.d.ts","sourceRoot":"","sources":["../../../../../../src/components/settings/settings-sections.ts"],"names":[],"mappings":"AAoCA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAEpB,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,CAAC;AACF,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AAEtD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAMvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAK1E,CAAC;AA8IF,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,EAsB9C,CAAC;AAsBL;mEACmE;AACnE,wBAAgB,sBAAsB,IAAI,kBAAkB,EAAE,CAE7D;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GACzD,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GACzD,MAAM,CAER;AAED,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAQvD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK3D"}
1
+ {"version":3,"file":"settings-sections.d.ts","sourceRoot":"","sources":["../../../../../../src/components/settings/settings-sections.ts"],"names":[],"mappings":"AA0CA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EAEpB,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAIrC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,CAAC;AACF,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AAEtD,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAMvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAK1E,CAAC;AA8IF,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,EAAE,kBAAkB,EAsB9C,CAAC;AA4CL;mEACmE;AACnE,wBAAgB,sBAAsB,IAAI,kBAAkB,EAAE,CAE7D;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GACzD,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,GACzD,MAAM,CAER;AAED,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAQvD;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAK3D"}
@@ -1,4 +1,4 @@
1
- import { Archive, Bot, Brain, KeyRound, LayoutGrid, Lock, Mic, Palette, Puzzle, RefreshCw, Server, Shield, ShieldCheck, SlidersHorizontal, User, Wallet, Webhook, } from "lucide-react";
1
+ import { Archive, Bot, Brain, Cloud, KeyRound, LayoutGrid, Lock, Mic, Palette, Puzzle, RefreshCw, Server, Shield, ShieldCheck, SlidersHorizontal, User, Wallet, Webhook, } from "lucide-react";
2
2
  import { ReleaseCenterView } from "../pages/ReleaseCenterView.js";
3
3
  import { AdvancedSection } from "./AdvancedSection.js";
4
4
  import { AppearanceSettingsSection } from "./AppearanceSettingsSection.js";
@@ -6,6 +6,7 @@ import { AppPermissionsSection } from "./AppPermissionsSection.js";
6
6
  import { AppsManagementSection } from "./AppsManagementSection.js";
7
7
  import { CapabilitiesSection } from "./CapabilitiesSection.js";
8
8
  import { CloudAgentsSection } from "./CloudAgentsSection.js";
9
+ import { CloudOverviewSection } from "./CloudOverviewSection.js";
9
10
  import { ConnectorsSection } from "./ConnectorsSection.js";
10
11
  import { IdentitySettingsSection } from "./IdentitySettingsSection.js";
11
12
  import { PermissionsSection } from "./PermissionsSection.js";
@@ -14,6 +15,7 @@ import { RemotePluginHostSection } from "./RemotePluginHostSection.js";
14
15
  import { RuntimeSettingsSection } from "./RuntimeSettingsSection.js";
15
16
  import { SecretsManagerSection } from "./SecretsManagerSection.js";
16
17
  import { SecuritySettingsSection } from "./SecuritySettingsSection.js";
18
+ import { CLOUD_SETTINGS_GROUP_ID, registerSettingsGroup, } from "../../cloud/settings/cloud-settings-group.js";
17
19
  import { SETTINGS_GROUP_LABEL, SETTINGS_GROUP_ORDER, SETTINGS_SECTION_META, } from "./settings-section-meta.js";
18
20
  import { listSettingsSections, registerSettingsSection, } from "./settings-section-registry.js";
19
21
  import { VoiceSectionMount } from "./VoiceSectionMount.js";
@@ -184,10 +186,30 @@ export const SETTINGS_SECTIONS = SETTINGS_SECTION_META.map((meta, index) => {
184
186
  });
185
187
  for (const section of SETTINGS_SECTIONS)
186
188
  registerSettingsSection(section);
189
+ registerSettingsGroup({
190
+ id: CLOUD_SETTINGS_GROUP_ID,
191
+ label: "Cloud",
192
+ order: 1.5,
193
+ });
194
+ registerSettingsSection({
195
+ id: "cloud-overview",
196
+ label: "settings.sections.cloudOverview.label",
197
+ defaultLabel: "Overview",
198
+ icon: Cloud,
199
+ tone: "accent",
200
+ hue: "accent",
201
+ group: CLOUD_SETTINGS_GROUP_ID,
202
+ titleKey: "settings.sections.cloudOverview.title",
203
+ defaultTitle: "Eliza Cloud",
204
+ order: 1.45,
205
+ Component: CloudOverviewSection,
206
+ });
187
207
  // Eliza Cloud agent manager — contributed through the pluggable registry rather
188
208
  // than the canonical META list, so it surfaces in Settings (list / switch /
189
209
  // create+name / delete agents) without changing the built-in section count that
190
- // the dev-route-catalog test pins. Ordered right after the AI Model section.
210
+ // the dev-route-catalog test pins. It lives under the local Cloud group with the
211
+ // upsell overview, while full Cloud-only account/billing/API surfaces remain
212
+ // opt-in through registerCloudSettingsSections().
191
213
  registerSettingsSection({
192
214
  id: "cloud-agents",
193
215
  label: "settings.sections.cloudAgents.label",
@@ -195,10 +217,10 @@ registerSettingsSection({
195
217
  icon: Bot,
196
218
  tone: "accent",
197
219
  hue: "accent",
198
- group: "agent",
220
+ group: CLOUD_SETTINGS_GROUP_ID,
199
221
  titleKey: "settings.sections.cloudAgents.title",
200
222
  defaultTitle: "Eliza Cloud Agents",
201
- order: 1.5,
223
+ order: 1.55,
202
224
  Component: CloudAgentsSection,
203
225
  });
204
226
  /** Every section the Settings view should render — built-ins plus any added by
@@ -1 +1 @@
1
- {"version":3,"file":"ComputerUseApprovalOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ComputerUseApprovalOverlay.tsx"],"names":[],"mappings":"AAkCA,wBAAgB,0BAA0B,mDAoXzC"}
1
+ {"version":3,"file":"ComputerUseApprovalOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ComputerUseApprovalOverlay.tsx"],"names":[],"mappings":"AAmCA,wBAAgB,0BAA0B,mDA+XzC"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { supportsFullAppShellRoutes } from "../../api/app-shell-capabilities.js";
3
4
  import { client } from "../../api/client.js";
4
5
  import { useAppSelector } from "../../state/index.js";
5
6
  import { openEventSource } from "../../utils/event-source.js";
@@ -27,6 +28,7 @@ function approvalStreamUrl() {
27
28
  export function ComputerUseApprovalOverlay() {
28
29
  const setActionNotice = useAppSelector((s) => s.setActionNotice);
29
30
  const t = useAppSelector((s) => s.t);
31
+ const appShellRoutesSupported = supportsFullAppShellRoutes(client.getBaseUrl());
30
32
  const [snapshot, setSnapshot] = useState(EMPTY_SNAPSHOT);
31
33
  const [busyApprovalId, setBusyApprovalId] = useState(null);
32
34
  const [denyTargetId, setDenyTargetId] = useState(null);
@@ -34,14 +36,22 @@ export function ComputerUseApprovalOverlay() {
34
36
  const dialogRef = useRef(null);
35
37
  const previousFocusRef = useRef(null);
36
38
  const refresh = useCallback(async () => {
39
+ if (!appShellRoutesSupported) {
40
+ setSnapshot(EMPTY_SNAPSHOT);
41
+ return;
42
+ }
37
43
  try {
38
44
  setSnapshot(await client.getComputerUseApprovals());
39
45
  }
40
46
  catch {
41
47
  setSnapshot(EMPTY_SNAPSHOT);
42
48
  }
43
- }, []);
49
+ }, [appShellRoutesSupported]);
44
50
  useEffect(() => {
51
+ if (!appShellRoutesSupported) {
52
+ setSnapshot(EMPTY_SNAPSHOT);
53
+ return undefined;
54
+ }
45
55
  let cancelled = false;
46
56
  let pollingTimer = null;
47
57
  let eventSource = null;
@@ -101,7 +111,7 @@ export function ComputerUseApprovalOverlay() {
101
111
  }
102
112
  eventSource?.close();
103
113
  };
104
- }, [refresh]);
114
+ }, [appShellRoutesSupported, refresh]);
105
115
  // Defensive: the snapshot can be partially populated during reconnect/
106
116
  // recovery windows, so `pendingApprovals` may be momentarily undefined.
107
117
  // Never crash the whole app on it — render no cards until it's an array.
@@ -1 +1 @@
1
- {"version":3,"file":"ContinuousChatOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ContinuousChatOverlay.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAc/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAqCnF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA8D7E;;+CAE+C;AAC/C,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,iBAAiB,GACjB,mBAAmB,GACnB,WAAW,CAAC;AAEhB;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAw0B1D,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,SAAmB,EACnB,KAAK,EAAE,SAAS,GACjB,EAAE;IACD,UAAU,EAAE,eAAe,CAAC;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAChC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAknFpB"}
1
+ {"version":3,"file":"ContinuousChatOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ContinuousChatOverlay.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAc/B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAqCnF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA8D7E;;+CAE+C;AAC/C,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,iBAAiB,GACjB,mBAAmB,GACnB,WAAW,CAAC;AAEhB;;;;;;;;GAQG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AA60B1D,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,SAAmB,EACnB,KAAK,EAAE,SAAS,GACjB,EAAE;IACD,UAAU,EAAE,eAAe,CAAC;IAC5B,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,sBAAsB,CAAC;CAChC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CA+oFpB"}
@@ -360,10 +360,12 @@ function useDebouncedTurnStatus(status) {
360
360
  * `speaking`; every other phase is neutral white. No blue anywhere. Degrades to
361
361
  * plain dots when no status has arrived.
362
362
  */
363
- function TurnStatusInner({ status, }) {
363
+ function TurnStatusInner({ status, showLabel = true, }) {
364
364
  const shown = useDebouncedTurnStatus(status);
365
365
  const speaking = shown?.kind === "speaking";
366
- const label = shown && shown.kind !== "thinking" ? turnStatusLabel(shown) : null;
366
+ const label = showLabel && shown && shown.kind !== "thinking"
367
+ ? turnStatusLabel(shown)
368
+ : null;
367
369
  return (_jsxs("span", { className: "inline-flex items-center gap-2", "data-testid": "turn-status-indicator", "data-status-kind": shown?.kind ?? "none", role: "status", "aria-live": "polite", children: [_jsx("span", { className: "flex gap-1.5", "data-testid": "typing-dots", "aria-hidden": "true", children: [0, 1, 2].map((i) => (_jsx("span", { className: cn("h-1.5 w-1.5 animate-pulse rounded-full motion-reduce:animate-none", speaking ? "bg-[rgba(255,190,140,0.9)]" : "bg-white/70"), style: { animationDelay: `${i * 180}ms` } }, i))) }), label ? (_jsx("span", { className: cn("text-[13px] font-medium", speaking ? "text-[rgba(255,200,150,0.95)]" : "text-white/90"), "data-testid": "turn-status-label", children: label })) : null] }));
368
370
  }
369
371
  /**
@@ -480,7 +482,7 @@ const ThreadLine = React.memo(function ThreadLine({ message, floating, reduce, o
480
482
  ? "bg-white/20 text-white"
481
483
  : "bg-white/10 text-white/90"), children: [_jsx("div", { "data-chat-selectable": "true", children: isAssistant &&
482
484
  !message.content.trim() &&
483
- !message.attachments?.length ? (_jsxs(_Fragment, { children: [_jsx(TurnStatusInner, { status: turnStatus ?? null }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null] })) : isUser ? (_jsxs(_Fragment, { children: [_jsx(ThreadLineText, { content: message.content }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(InlineWidgetText, { content: message.content }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null, message.secretRequest ? (_jsx("div", { className: "pointer-events-auto", children: _jsx(SensitiveRequestBlock, { request: message.secretRequest }) })) : null, !suppressReasoning && message.reasoning?.trim() ? (_jsx(ThinkingBlock, { reasoning: message.reasoning })) : null] })) }), _jsx(AnimatePresence, { children: copied ? (_jsx(motion.span, { "data-testid": "thread-line-copied", initial: reduce ? { opacity: 0 } : { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0 }, transition: { duration: reduce ? 0 : 0.18 }, className: "pointer-events-none absolute -top-2 right-2 rounded-full bg-white/90 px-2 py-0.5 text-[11px] font-medium text-black", children: "Copied" }, "copied")) : null })] }) }));
485
+ !message.attachments?.length ? (_jsxs(_Fragment, { children: [_jsx(TurnStatusInner, { status: turnStatus ?? null, showLabel: false }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null] })) : isUser ? (_jsxs(_Fragment, { children: [_jsx(ThreadLineText, { content: message.content }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null] })) : (_jsxs(_Fragment, { children: [_jsx(InlineWidgetText, { content: message.content }), message.attachments?.length ? (_jsx(MessageAttachments, { attachments: message.attachments })) : null, message.secretRequest ? (_jsx("div", { className: "pointer-events-auto", children: _jsx(SensitiveRequestBlock, { request: message.secretRequest }) })) : null, !suppressReasoning && message.reasoning?.trim() ? (_jsx(ThinkingBlock, { reasoning: message.reasoning })) : null] })) }), _jsx(AnimatePresence, { children: copied ? (_jsx(motion.span, { "data-testid": "thread-line-copied", initial: reduce ? { opacity: 0 } : { opacity: 0, y: 4 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0 }, transition: { duration: reduce ? 0 : 0.18 }, className: "pointer-events-none absolute -top-2 right-2 rounded-full bg-white/90 px-2 py-0.5 text-[11px] font-medium text-black", children: "Copied" }, "copied")) : null })] }) }));
484
486
  });
485
487
  export function ContinuousChatOverlay({ controller, agentName = "Eliza", slash: slashProp, }) {
486
488
  const { messages, phase, responding, turnStatus, send, canSend, recording, startRecording, stopRecording, handsFree, toggleHandsFree, transcriptionMode, toggleTranscriptionMode, stopTranscriptionAndMic, setDictationSink, setTranscriptSessionSink, setComposerHasDraft, transcript, needsAudioUnlock, unlockAudio, openSettings, navigateHome, currentTab, clearConversation, stop, modelStatus, } = controller;
@@ -1395,12 +1397,24 @@ export function ContinuousChatOverlay({ controller, agentName = "Eliza", slash:
1395
1397
  ]);
1396
1398
  const closeSheet = React.useCallback(() => {
1397
1399
  draggingRef.current = false;
1398
- stopThreadAnimation();
1399
1400
  stopOpenProgressAnimation();
1400
1401
  setFreeH(null);
1401
1402
  setMaximized(false);
1402
1403
  setMode("input");
1403
- }, [stopThreadAnimation, stopOpenProgressAnimation]);
1404
+ if (reduce) {
1405
+ stopThreadAnimation();
1406
+ threadHeight.set(0);
1407
+ }
1408
+ else {
1409
+ animateThreadHeight(0);
1410
+ }
1411
+ }, [
1412
+ reduce,
1413
+ threadHeight,
1414
+ stopThreadAnimation,
1415
+ stopOpenProgressAnimation,
1416
+ animateThreadHeight,
1417
+ ]);
1404
1418
  // Leaving the chat for Settings/Home: animate OUT of maximize and collapse the
1405
1419
  // sheet (closeSheet un-maximizes + springs the thread height down) BEFORE
1406
1420
  // swapping the page underneath, so it reads as the chat closing into the new
@@ -1463,17 +1477,31 @@ export function ContinuousChatOverlay({ controller, agentName = "Eliza", slash:
1463
1477
  // A detent always clears any free-drag rest height and (since only FULL
1464
1478
  // can be maximized) drops full-bleed when stepping anywhere else.
1465
1479
  draggingRef.current = false;
1466
- stopThreadAnimation();
1467
1480
  setFreeH(null);
1468
1481
  if (to !== "full")
1469
1482
  setMaximized(false);
1470
1483
  // "collapsed" is the input bar (sheet closed); half/full open the thread.
1471
1484
  setMode(to === "collapsed" ? "input" : to);
1485
+ const target = to === "collapsed" ? 0 : to === "half" ? halfH : openH;
1486
+ if (reduce) {
1487
+ stopThreadAnimation();
1488
+ threadHeight.set(target);
1489
+ }
1490
+ else {
1491
+ animateThreadHeight(target);
1492
+ }
1472
1493
  // Stepping all the way down closes the keyboard (the chat is dismissed).
1473
1494
  if (to === "collapsed")
1474
1495
  inputRef.current?.blur();
1475
1496
  detentHaptic();
1476
- }, [stopThreadAnimation]);
1497
+ }, [
1498
+ halfH,
1499
+ openH,
1500
+ reduce,
1501
+ threadHeight,
1502
+ stopThreadAnimation,
1503
+ animateThreadHeight,
1504
+ ]);
1477
1505
  const openFromGrabber = React.useCallback(() => {
1478
1506
  if (hasRevealableThread) {
1479
1507
  preFocusCollapsedRef.current = false;
@@ -2042,6 +2070,11 @@ export function ContinuousChatOverlay({ controller, agentName = "Eliza", slash:
2042
2070
  return;
2043
2071
  }
2044
2072
  if (sheetOpen) {
2073
+ if (composerFocusedAtPressRef.current) {
2074
+ composerFocusedAtPressRef.current = false;
2075
+ dismissKeyboardToPriorState();
2076
+ return;
2077
+ }
2045
2078
  collapse();
2046
2079
  return;
2047
2080
  }
@@ -2245,7 +2278,7 @@ export function ContinuousChatOverlay({ controller, agentName = "Eliza", slash:
2245
2278
  paddingTop: fullBleed
2246
2279
  ? "calc(var(--safe-area-top, 0px) + 0.5rem)"
2247
2280
  : headerPadTop,
2248
- }, className: cn("relative z-10 flex shrink-0 items-center justify-between gap-1.5 overflow-hidden px-3"), children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(HeaderButton, { icon: maximized ? Minimize2 : Maximize2, label: maximized ? "exit full screen" : "full screen", active: maximized, onClick: toggleMaximize, testId: "chat-full-maximize" }), hasThread ? (_jsx(HeaderButton, { icon: conversationCopied ? Check : Copy, label: conversationCopied
2281
+ }, className: cn("relative z-20 flex shrink-0 items-center justify-between gap-1.5 overflow-hidden px-3"), children: [_jsxs("div", { className: "flex items-center gap-1.5", children: [_jsx(HeaderButton, { icon: maximized ? Minimize2 : Maximize2, label: maximized ? "exit full screen" : "full screen", active: maximized, onClick: toggleMaximize, testId: "chat-full-maximize" }), hasThread ? (_jsx(HeaderButton, { icon: conversationCopied ? Check : Copy, label: conversationCopied
2249
2282
  ? "conversation copied"
2250
2283
  : "copy conversation", onClick: handleCopyConversation, testId: "chat-full-copy-conversation" })) : null, _jsx(HeaderButton, { icon: RotateCcw, label: "clear conversation", onClick: () => clearConversation(), testId: "chat-full-clear" })] }), transcriptionMode ? (_jsx("div", { "data-testid": "chat-transcribing-badge", className: "pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 whitespace-nowrap rounded-full bg-[var(--brand-orange,#ff6a00)]/15 px-2.5 py-0.5 text-[11px] font-medium text-[var(--brand-orange,#ff6a00)]", children: "Transcribing \u2014 say \u201Cexit transcription mode\u201D to stop" })) : null, _jsx("div", { className: "flex items-center gap-1.5", children: _jsx(HeaderButton, { icon: LayoutGrid, label: "springboard", onClick: () => navigateAndClose(() => navigateHome?.()), testId: "chat-full-springboard" }) })] })) : null, threadPresented ? (_jsx(motion.div, { "data-testid": "chat-thread", className: cn("relative z-10 min-h-0 w-full shrink grow-0 overflow-hidden",
2251
2284
  // When open, fade the top edge into the glass so the topmost
@@ -1 +1 @@
1
- {"version":3,"file":"ShellHeaderControls.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ShellHeaderControls.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAStD,QAAA,MAAM,2BAA2B,kuBAAyH,CAAC;AAa3J,QAAA,MAAM,mBAAmB;;;;CAIf,CAAC;AAEX,OAAO,EACL,mBAAmB,EACnB,2BAA2B,IAAI,4BAA4B,GAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAKrD,UAAU,wBAAwB;IAChC,eAAe,EAAE,SAAS,CAAC;IAC3B,iBAAiB,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,CAAC,EAAE,qBAAqB,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAChC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACzC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,wGAAwG;IACxG,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,0EAA0E;IAC1E,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6BAA6B,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IACrD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,OAAO,EACP,UAAU,EACV,CAAC,EACD,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,SAAS,EACT,mBAA0B,EAC1B,eAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,6BAA0C,EAC1C,mBAA2B,EAC3B,iBAAiB,EACjB,SAAS,EACT,MAAM,EACN,QAAgB,EAChB,WAAmB,GACpB,EAAE,wBAAwB,2CA6P1B"}
1
+ {"version":3,"file":"ShellHeaderControls.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/ShellHeaderControls.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAStD,QAAA,MAAM,2BAA2B,kuBAAyH,CAAC;AAa3J,QAAA,MAAM,mBAAmB;;;;CAIf,CAAC;AAEX,OAAO,EACL,mBAAmB,EACnB,2BAA2B,IAAI,4BAA4B,GAC5D,CAAC;AAEF,KAAK,qBAAqB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;AAKrD,UAAU,wBAAwB;IAChC,eAAe,EAAE,SAAS,CAAC;IAC3B,iBAAiB,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;IAC7C,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,CAAC,EAAE,qBAAqB,CAAC;IACzB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,mBAAmB,CAAC,EAAE,SAAS,CAAC;IAChC,cAAc,CAAC,EAAE,SAAS,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IACzC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,wGAAwG;IACxG,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,0EAA0E;IAC1E,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,6BAA6B,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IACrD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,OAAO,EACP,UAAU,EACV,CAAC,EACD,QAAQ,EACR,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,SAAS,EACT,mBAA0B,EAC1B,eAA0B,EAC1B,yBAAyB,EACzB,6BAA6B,EAC7B,oBAAoB,EACpB,2BAA2B,EAC3B,wBAAwB,EACxB,qBAAqB,EACrB,6BAA0C,EAC1C,mBAA2B,EAC3B,iBAAiB,EACjB,SAAS,EACT,MAAM,EACN,QAAgB,EAChB,WAAmB,GACpB,EAAE,wBAAwB,2CA8P1B"}
@@ -67,7 +67,7 @@ export function ShellHeaderControls({ activeShellView, onShellViewChange, uiLang
67
67
  return renderNewChatButton(iconOnly);
68
68
  return null;
69
69
  };
70
- return (_jsxs("div", { className: `min-w-0 w-full overflow-visible flex items-center ${className ?? ""}`, "data-no-camera-drag": "true", children: [_jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [showShellViewToggle && (_jsxs("fieldset", { className: SHELL_SEGMENTED_CONTROL_CLASSNAME, "data-testid": "ui-shell-toggle", "data-no-camera-drag": "true", "aria-label": t("aria.switchShellView"), children: [_jsx("legend", { className: "sr-only", children: t("aria.switchShellView") }), shellOptions.map(({ view, label, Icon }, index) => {
70
+ return (_jsxs("div", { className: `min-w-0 w-full overflow-visible flex items-center ${className ?? ""}`, "data-window-titlebar-padding": "true", "data-no-camera-drag": "true", children: [_jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [showShellViewToggle && (_jsxs("fieldset", { className: SHELL_SEGMENTED_CONTROL_CLASSNAME, "data-testid": "ui-shell-toggle", "data-no-camera-drag": "true", "aria-label": t("aria.switchShellView"), children: [_jsx("legend", { className: "sr-only", children: t("aria.switchShellView") }), shellOptions.map(({ view, label, Icon }, index) => {
71
71
  const selected = activeShellView === view;
72
72
  const edgeClass = index === 0
73
73
  ? "rounded-l-xl rounded-r-none"
@@ -1 +1 @@
1
- {"version":3,"file":"StartupFailureView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/StartupFailureView.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA0CrD,UAAU,uBAAuB;IAC/B,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA0BD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,GACR,EAAE,uBAAuB,2CA4FzB"}
1
+ {"version":3,"file":"StartupFailureView.d.ts","sourceRoot":"","sources":["../../../../../../src/components/shell/StartupFailureView.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA0CrD,UAAU,uBAAuB;IAC/B,KAAK,EAAE,iBAAiB,CAAC;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AA0BD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,OAAO,GACR,EAAE,uBAAuB,2CA+GzB"}
@@ -60,7 +60,9 @@ export function StartupFailureView({ error, onRetry, }) {
60
60
  const bugReport = useOptionalBugReport();
61
61
  const reasonLabel = startupReasonLabel(t, error.reason);
62
62
  const startupDraft = buildStartupBugReportDraft(reasonLabel, error);
63
- return (_jsx("div", { className: SCREEN_SHELL_CLASS, children: _jsxs(Card, { className: SCREEN_CARD_CLASS, children: [_jsx(CardHeader, { className: "border-b border-border/10 bg-card pb-6 pt-6", children: _jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("span", { "aria-label": reasonLabel, className: "inline-flex h-9 w-9 items-center justify-center rounded-sm border border-destructive/35 bg-destructive/12 text-destructive", role: "img", title: reasonLabel, children: _jsx(AlertCircle, { className: "h-5 w-5", "aria-hidden": true }) }), _jsxs("h1", { className: "text-xl font-semibold leading-tight text-destructive", children: [t("startupfailureview.StartupFailed"), " ", reasonLabel] })] }) }), _jsxs(CardContent, { className: "flex flex-col gap-5 pt-6", children: [_jsx("p", { className: "text-sm leading-relaxed text-txt", children: error.message }), error.detail ? (_jsxs("section", { className: "space-y-2 rounded-sm border border-border/50 bg-bg/35 p-4", children: [_jsx("div", { className: "text-xs-tight font-semibold uppercase tracking-[0.08em] text-muted", children: t("common.details", { defaultValue: "Details" }) }), _jsx("pre", { className: "max-h-60 overflow-auto rounded-sm border border-border/40 bg-card p-3 text-xs leading-relaxed text-muted whitespace-pre-wrap break-words", children: error.detail })] })) : null, _jsxs("div", { className: "flex flex-col gap-3 pt-4 sm:flex-row sm:items-center", children: [_jsx(Button, { variant: "default", size: "lg", onClick: onRetry, className: "w-full sm:w-auto sm:min-w-[11rem]", children: t("startupfailureview.RetryStartup") }), bugReport ? (_jsx(Button, { variant: "outline", size: "lg", onClick: () => bugReport.open(startupDraft), className: "w-full sm:w-auto sm:min-w-[10rem]", children: t("bugreportmodal.ReportABug") })) : null, error.reason === "backend-unreachable" ? (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", size: "lg", onClick: () => startFreshFirstRunReload(), className: "w-full sm:w-auto sm:min-w-[10rem]", children: t("startupfailureview.StartOver", {
63
+ return (_jsx("div", { className: SCREEN_SHELL_CLASS, children: _jsxs(Card, { className: SCREEN_CARD_CLASS, children: [_jsx(CardHeader, { className: "border-b border-border/10 bg-card pb-6 pt-6", children: _jsxs("div", { className: "flex flex-col gap-4", children: [_jsx("span", { "aria-label": reasonLabel, className: "inline-flex h-9 w-9 items-center justify-center rounded-sm border border-destructive/35 bg-destructive/12 text-destructive", role: "img", title: reasonLabel, children: _jsx(AlertCircle, { className: "h-5 w-5", "aria-hidden": true }) }), _jsxs("h1", { className: "text-xl font-semibold leading-tight text-destructive", children: [t("startupfailureview.StartupFailed"), " ", reasonLabel] })] }) }), _jsxs(CardContent, { className: "flex flex-col gap-5 pt-6", children: [_jsx("p", { className: "text-sm leading-relaxed text-txt", children: error.message }), error.detail ? (_jsxs("section", { className: "space-y-2 rounded-sm border border-border/50 bg-bg/35 p-4", children: [_jsx("div", { className: "text-xs-tight font-semibold uppercase tracking-[0.08em] text-muted", children: t("common.details", { defaultValue: "Details" }) }), _jsx("pre", { className: "max-h-60 overflow-auto rounded-sm border border-border/40 bg-card p-3 text-xs leading-relaxed text-muted whitespace-pre-wrap break-words", children: error.detail })] })) : null, _jsxs("div", { className: "flex flex-col gap-3 pt-4 sm:flex-row sm:items-center", children: [error.reason === "backend-unreachable" ? (_jsx(Button, { variant: "default", size: "lg", onClick: () => startFreshFirstRunReload(), className: "w-full sm:w-auto sm:min-w-[11rem]", "data-testid": "startup-use-cloud", children: t("startupfailureview.ChooseElizaCloud", {
64
+ defaultValue: "Choose Eliza Cloud",
65
+ }) })) : null, _jsx(Button, { variant: error.reason === "backend-unreachable" ? "outline" : "default", size: "lg", onClick: onRetry, className: "w-full sm:w-auto sm:min-w-[11rem]", "data-testid": "startup-retry", children: t("startupfailureview.RetryStartup") }), bugReport ? (_jsx(Button, { variant: "outline", size: "lg", onClick: () => bugReport.open(startupDraft), className: "w-full sm:w-auto sm:min-w-[10rem]", "data-testid": "startup-report-bug", children: t("bugreportmodal.ReportABug") })) : null, error.reason === "backend-unreachable" ? (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", size: "lg", onClick: () => startFreshFirstRunReload(), className: "w-full sm:w-auto sm:min-w-[10rem]", "data-testid": "startup-start-over", children: t("startupfailureview.StartOver", {
64
66
  defaultValue: "Start over",
65
- }) }), _jsx(Button, { variant: "outline", size: "lg", asChild: true, className: "w-full sm:w-auto sm:min-w-[10rem]", children: _jsx("a", { href: branding.appUrl, target: "_blank", rel: "noreferrer", children: t("startupfailureview.OpenApp") }) })] })) : null] })] })] }) }));
67
+ }) }), _jsx(Button, { variant: "outline", size: "lg", asChild: true, className: "w-full sm:w-auto sm:min-w-[10rem]", "data-testid": "startup-open-app", children: _jsx("a", { href: branding.appUrl, target: "_blank", rel: "noreferrer", children: t("startupfailureview.OpenApp") }) })] })) : null] })] })] }) }));
66
68
  }
@@ -4,6 +4,8 @@ export declare function useViewCatalog(): {
4
4
  id: string;
5
5
  label: string;
6
6
  icon: string;
7
+ imageUrl: string;
8
+ fallbackImageUrl: string;
7
9
  hasHero: boolean;
8
10
  modality: string;
9
11
  state: string;
@@ -1 +1 @@
1
- {"version":3,"file":"home-screen-fixture.catalog-stub.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/shell/__e2e__/home-screen-fixture.catalog-stub.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;EAsB7B"}
1
+ {"version":3,"file":"home-screen-fixture.catalog-stub.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/shell/__e2e__/home-screen-fixture.catalog-stub.ts"],"names":[],"mappings":"AAUA,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;EAwB7B"}
@@ -1,3 +1,9 @@
1
+ import { generateViewHeroSvgFor } from "@elizaos/shared";
2
+ const WEATHER_HERO = `data:image/svg+xml,${encodeURIComponent(generateViewHeroSvgFor({
3
+ id: "weather",
4
+ label: "Weather",
5
+ icon: "CloudSun",
6
+ }))}`;
1
7
  export function useViewCatalog() {
2
8
  return {
3
9
  entries: [
@@ -6,6 +12,8 @@ export function useViewCatalog() {
6
12
  id: "weather",
7
13
  label: "Weather",
8
14
  icon: "CloudSun",
15
+ imageUrl: WEATHER_HERO,
16
+ fallbackImageUrl: WEATHER_HERO,
9
17
  hasHero: false,
10
18
  modality: "gui",
11
19
  state: "available",
@@ -2,10 +2,10 @@ import type { ViewEntry } from "../../hooks/view-catalog.js";
2
2
  /**
3
3
  * The shared visual core for view launch surfaces.
4
4
  *
5
- * Springboard tiles are app icons: deterministic colored glyph tiles that stay
6
- * readable at 64px and never look like cropped preview cards. Catalog cards are
7
- * previews: render the concrete hero or generated branded fallback, then fall
8
- * back to a glyph if every image source fails.
5
+ * Springboard tiles are app icons: paint the deterministic glyph tile
6
+ * underneath the concrete hero or generated branded fallback so icons never
7
+ * appear blank while image decoding catches up after a swipe. Catalog cards are
8
+ * previews and use the same image/fallback order at their larger size.
9
9
  *
10
10
  * A load failure emits a `hero-image-error` interaction event (best-effort,
11
11
  * client-only) from preview surfaces so broken hero endpoints are observable
@@ -1 +1 @@
1
- {"version":3,"file":"ViewTileImage.d.ts","sourceRoot":"","sources":["../../../../../../src/components/views/ViewTileImage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAyD1D;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,MAAM,EACN,kBAAkB,EAClB,cAA0B,EAC1B,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,MAAM,EAAE,aAAa,GAAG,cAAc,CAAC;IACvC,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,2CAwEA"}
1
+ {"version":3,"file":"ViewTileImage.d.ts","sourceRoot":"","sources":["../../../../../../src/components/views/ViewTileImage.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAiE1D;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,MAAM,EACN,kBAAkB,EAClB,cAA0B,EAC1B,WAAW,GACZ,EAAE;IACD,KAAK,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,MAAM,EAAE,aAAa,GAAG,cAAc,CAAC;IACvC,+EAA+E;IAC/E,kBAAkB,EAAE,MAAM,CAAC;IAC3B,sCAAsC;IACtC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,2CAqHA"}