@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
@@ -1,6 +1,7 @@
1
1
  import { isLoopbackBindHost, isWildcardBindHost } from "@elizaos/shared";
2
2
  import { getElectrobunRendererRpc } from "../bridge/electrobun-rpc.js";
3
3
  import { isElectrobunRuntime } from "../bridge/electrobun-runtime.js";
4
+ import { isDesktopExternalHttpApiBaseUrl } from "./desktop-external-api-base.js";
4
5
  import { bodyToString, fetchAgentTransport, headersToRecord, methodAllowsBody, } from "./transport.js";
5
6
  function isExternalPlainHttpUrl(url) {
6
7
  try {
@@ -13,33 +14,6 @@ function isExternalPlainHttpUrl(url) {
13
14
  return false;
14
15
  }
15
16
  }
16
- function getConfiguredExternalApiBaseOrigin() {
17
- if (typeof window === "undefined")
18
- return null;
19
- const value = window
20
- .__ELIZA_DESKTOP_EXTERNAL_API_BASE__;
21
- if (typeof value !== "string" || !value.trim())
22
- return null;
23
- try {
24
- const parsed = new URL(value);
25
- return parsed.protocol === "http:" ? parsed.origin : null;
26
- }
27
- catch {
28
- return null;
29
- }
30
- }
31
- function isConfiguredExternalApiBaseUrl(url) {
32
- const allowedOrigin = getConfiguredExternalApiBaseOrigin();
33
- if (!allowedOrigin)
34
- return false;
35
- try {
36
- const parsed = new URL(url);
37
- return parsed.protocol === "http:" && parsed.origin === allowedOrigin;
38
- }
39
- catch {
40
- return false;
41
- }
42
- }
43
17
  const desktopHttpTransport = {
44
18
  async request(url, init, context) {
45
19
  const rpc = getElectrobunRendererRpc();
@@ -70,7 +44,7 @@ const desktopHttpTransport = {
70
44
  };
71
45
  export function desktopHttpTransportForUrl(url) {
72
46
  return isElectrobunRuntime() &&
73
- (isExternalPlainHttpUrl(url) || isConfiguredExternalApiBaseUrl(url))
47
+ (isExternalPlainHttpUrl(url) || isDesktopExternalHttpApiBaseUrl(url))
74
48
  ? desktopHttpTransport
75
49
  : null;
76
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"i18n-locale-client.d.ts","sourceRoot":"","sources":["../../../../../src/api/i18n-locale-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAS7D;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAazE"}
1
+ {"version":3,"file":"i18n-locale-client.d.ts","sourceRoot":"","sources":["../../../../../src/api/i18n-locale-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAqB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAkB7D;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAczE"}
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { getBootConfig } from "../config/boot-config.js";
10
10
  import { normalizeLanguage } from "../i18n/index.js";
11
+ import { supportsFullAppShellRoutes } from "./app-shell-capabilities.js";
11
12
  import { fetchWithCsrf } from "./csrf-client.js";
12
13
  function localeBase() {
13
14
  if (typeof window === "undefined")
@@ -15,11 +16,22 @@ function localeBase() {
15
16
  const apiBase = getBootConfig().apiBase;
16
17
  return apiBase ? apiBase.replace(/\/$/, "") : window.location.origin;
17
18
  }
19
+ function shouldFetchSuggestedLanguage() {
20
+ if (typeof window === "undefined")
21
+ return false;
22
+ const apiBase = getBootConfig().apiBase;
23
+ if (apiBase)
24
+ return supportsFullAppShellRoutes(apiBase);
25
+ const host = window.location.hostname.toLowerCase();
26
+ return host !== "localhost" && host !== "127.0.0.1" && host !== "::1";
27
+ }
18
28
  /**
19
29
  * Fetch the server's suggested UI language. Returns `null` when the endpoint
20
30
  * is unreachable or the server has no confident suggestion (advisory only).
21
31
  */
22
32
  export async function fetchSuggestedLanguage() {
33
+ if (!shouldFetchSuggestedLanguage())
34
+ return null;
23
35
  let res;
24
36
  try {
25
37
  res = await fetchWithCsrf(`${localeBase()}/api/i18n/locale`);
@@ -1 +1 @@
1
- {"version":3,"file":"billing-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/billing/components/billing-tab.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,UAAU,CAAC;AAiBlB,UAAU,eAAe;IACvB,IAAI,EAAE,WAAW,CAAC;CACnB;AASD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe,2CA2cnD;AAED,YAAY,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"billing-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/billing/components/billing-tab.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuBH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,UAAU,CAAC;AAiBlB,UAAU,eAAe;IACvB,IAAI,EAAE,WAAW,CAAC;CACnB;AASD,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE,eAAe,2CA2cnD;AAED,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -11,7 +11,7 @@
11
11
  */
12
12
  "use client";
13
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
- import { BrandCard, CornerBrackets, Input } from "@elizaos/ui/cloud-ui";
14
+ import { BrandButton, BrandCard, CornerBrackets, Input, Label, } from "@elizaos/ui/cloud-ui";
15
15
  import { AlertCircle, CheckCircle, CreditCard, Loader2, Wallet, } from "lucide-react";
16
16
  import { lazy, Suspense, useCallback, useEffect, useState } from "react";
17
17
  import { useNavigate } from "react-router-dom";
@@ -181,19 +181,16 @@ export function BillingTab({ user }) {
181
181
  ? "bg-[#FF5800] border-[#FF5800] text-white"
182
182
  : "bg-transparent border-[rgba(255,255,255,0.2)] text-white/60 hover:border-[rgba(255,255,255,0.4)]"}`, children: [_jsx(CreditCard, { className: "h-4 w-4" }), t("cloud.billingTab.card", { defaultValue: "Card" })] }), _jsxs("button", { type: "button", onClick: () => setPaymentMethod("crypto"), className: `flex items-center gap-2 px-4 py-2 font-mono text-sm border transition-colors ${paymentMethod === "crypto"
183
183
  ? "bg-[#FF5800] border-[#FF5800] text-white"
184
- : "bg-transparent border-[rgba(255,255,255,0.2)] text-white/60 hover:border-[rgba(255,255,255,0.4)]"}`, children: [_jsx(Wallet, { className: "h-4 w-4" }), t("cloud.billingTab.crypto", { defaultValue: "Crypto" })] })] })), _jsxs("div", { className: "flex flex-col sm:flex-row items-stretch gap-4", children: [_jsxs("div", { className: "relative flex-1 max-w-xs", children: [_jsx("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-[#717171] font-mono z-10 pointer-events-none", children: "$" }), _jsx(Input, { type: "number", step: "1", min: AMOUNT_LIMITS.MIN, max: AMOUNT_LIMITS.MAX, value: purchaseAmount, onChange: (e) => setPurchaseAmount(e.target.value), className: "pl-7 bg-[rgba(29,29,29,0.3)] border border-[rgba(255,255,255,0.15)] text-[#e1e1e1] h-11 font-mono", placeholder: "0.00", disabled: isProcessingCheckout })] }), (paymentMethod !== "crypto" ||
185
- !cryptoStatus?.directWallet?.enabled) && (_jsxs("button", { type: "button", onClick: handleBuyCredits, disabled: !isValidAmount || isProcessingCheckout, className: "relative bg-[#e1e1e1] px-6 py-2.5 overflow-hidden hover:bg-white transition-colors w-full sm:w-auto flex-shrink-0 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2", children: [_jsx("div", { className: "absolute inset-0 opacity-20 bg-repeat pointer-events-none", style: {
186
- backgroundImage: `url(/assets/settings/pattern-6px-flip.png)`,
187
- backgroundSize: "2.915576934814453px 2.915576934814453px",
188
- } }), isProcessingCheckout ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin text-black relative z-10" }), _jsx("span", { className: "relative z-10 text-black font-mono font-medium text-base whitespace-nowrap", children: t("cloud.billingTab.redirecting", {
189
- defaultValue: "Redirecting...",
190
- }) })] })) : (_jsx("span", { className: "relative z-10 text-black font-mono font-medium text-base whitespace-nowrap", children: paymentMethod === "crypto"
191
- ? t("cloud.billingTab.payWithCrypto", {
192
- defaultValue: "Pay with Crypto",
193
- })
194
- : t("cloud.billingTab.buyCredits", {
195
- defaultValue: "Buy credits",
196
- }) }))] }))] }), purchaseAmount && !isValidAmount && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-red-400", children: [_jsx(AlertCircle, { className: "h-4 w-4" }), _jsx("span", { className: "font-mono", children: amountValue === null || amountValue < AMOUNT_LIMITS.MIN
184
+ : "bg-transparent border-[rgba(255,255,255,0.2)] text-white/60 hover:border-[rgba(255,255,255,0.4)]"}`, children: [_jsx(Wallet, { className: "h-4 w-4" }), t("cloud.billingTab.crypto", { defaultValue: "Crypto" })] })] })), _jsxs("div", { className: "flex flex-col sm:flex-row items-stretch sm:items-end gap-4", children: [_jsxs("div", { className: "flex-1 max-w-xs", children: [_jsx(Label, { htmlFor: "purchase-amount", className: "mb-1.5 block text-white/60 font-mono text-xs", children: t("cloud.billingTab.amountLabel", {
185
+ defaultValue: "Amount (USD)",
186
+ }) }), _jsxs("div", { className: "relative", children: [_jsx("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-[#717171] font-mono z-10 pointer-events-none", children: "$" }), _jsx(Input, { id: "purchase-amount", type: "number", step: "1", min: AMOUNT_LIMITS.MIN, max: AMOUNT_LIMITS.MAX, value: purchaseAmount, onChange: (e) => setPurchaseAmount(e.target.value), className: "pl-7 bg-[rgba(29,29,29,0.3)] border border-[rgba(255,255,255,0.15)] text-[#e1e1e1] h-11 font-mono", placeholder: "0.00", disabled: isProcessingCheckout })] })] }), (paymentMethod !== "crypto" ||
187
+ !cryptoStatus?.directWallet?.enabled) && (_jsx(BrandButton, { type: "button", variant: "primary", onClick: handleBuyCredits, disabled: !isValidAmount || isProcessingCheckout, className: "h-11 px-6 w-full sm:w-auto flex-shrink-0 font-mono text-base whitespace-nowrap", children: isProcessingCheckout ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), t("cloud.billingTab.redirecting", {
188
+ defaultValue: "Redirecting...",
189
+ })] })) : paymentMethod === "crypto" ? (t("cloud.billingTab.payWithCrypto", {
190
+ defaultValue: "Pay with Crypto",
191
+ })) : (t("cloud.billingTab.buyCredits", {
192
+ defaultValue: "Buy credits",
193
+ })) }))] }), purchaseAmount && !isValidAmount && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-red-400", children: [_jsx(AlertCircle, { className: "h-4 w-4" }), _jsx("span", { className: "font-mono", children: amountValue === null || amountValue < AMOUNT_LIMITS.MIN
197
194
  ? t("cloud.billingTab.minAmount", {
198
195
  min: AMOUNT_LIMITS.MIN,
199
196
  defaultValue: "Minimum amount is $" + "{{min}}",
@@ -1 +1 @@
1
- {"version":3,"file":"discord-gateway-connection.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/connectors/discord-gateway-connection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuIH,wBAAgB,wBAAwB,4CAukCvC"}
1
+ {"version":3,"file":"discord-gateway-connection.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/connectors/discord-gateway-connection.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgKH,wBAAgB,wBAAwB,4CA6lCvC"}
@@ -22,6 +22,24 @@ import { Label } from "../../components/ui/label.js";
22
22
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../../components/ui/select.js";
23
23
  import { ApiError, api, apiFetch } from "../lib/api-client.js";
24
24
  import { useCloudT } from "../shell/CloudI18nProvider.js";
25
+ function normalizeCharacters(agents) {
26
+ return (agents ?? []).flatMap((agent) => {
27
+ if (typeof agent.id !== "string" || agent.id.length === 0)
28
+ return [];
29
+ return [
30
+ {
31
+ id: agent.id,
32
+ name: typeof agent.name === "string" && agent.name.length > 0
33
+ ? agent.name
34
+ : agent.id,
35
+ },
36
+ ];
37
+ });
38
+ }
39
+ async function fetchRuntimeCharacters(signal) {
40
+ const data = await api("/api/agents", { signal, skipAuth: true });
41
+ return normalizeCharacters(data.agents);
42
+ }
25
43
  function apiErrorMessage(error, fallback) {
26
44
  if (error instanceof ApiError) {
27
45
  const body = error.body;
@@ -89,14 +107,30 @@ export function DiscordGatewayConnection() {
89
107
  try {
90
108
  const data = await api("/api/v1/dashboard", { signal });
91
109
  if (!signal?.aborted) {
92
- setCharacters(data.agents?.map((a) => ({ id: a.id, name: a.name })) || []);
110
+ const nextCharacters = normalizeCharacters(data.agents);
111
+ const fallbackCharacters = nextCharacters.length > 0
112
+ ? nextCharacters
113
+ : await fetchRuntimeCharacters(signal);
114
+ if (!signal?.aborted) {
115
+ setCharacters(fallbackCharacters);
116
+ setCharacterId((current) => current || fallbackCharacters[0]?.id || "");
117
+ }
93
118
  }
94
119
  }
95
120
  catch {
96
121
  if (!signal?.aborted) {
97
- toast.error(t("cloud.discord.fetchCharactersFailed", {
98
- defaultValue: "Failed to fetch characters",
99
- }));
122
+ try {
123
+ const fallbackCharacters = await fetchRuntimeCharacters(signal);
124
+ if (!signal?.aborted) {
125
+ setCharacters(fallbackCharacters);
126
+ setCharacterId((current) => current || fallbackCharacters[0]?.id || "");
127
+ }
128
+ }
129
+ catch {
130
+ toast.error(t("cloud.discord.fetchCharactersFailed", {
131
+ defaultValue: "Failed to fetch characters",
132
+ }));
133
+ }
100
134
  }
101
135
  }
102
136
  finally {
@@ -454,7 +488,7 @@ export function DiscordGatewayConnection() {
454
488
  defaultValue: "Select a character...",
455
489
  }) }) }), _jsx(SelectContent, { children: characters.length === 0 ? (_jsx(SelectItem, { value: "none", disabled: true, children: t("cloud.discord.noCharactersAvailable", {
456
490
  defaultValue: "No characters available",
457
- }) })) : (characters.map((char) => (_jsx(SelectItem, { value: char.id, children: char.name }, char.id)))) })] }), _jsx(Button, { variant: "outline", size: "icon", onClick: handleRefreshCharacters, disabled: isLoadingCharacters, title: t("cloud.discord.refreshCharacters", {
491
+ }) })) : (characters.map((char) => (_jsx(SelectItem, { value: char.id, children: char.name }, char.id)))) })] }, characterId || "discord-gateway-character-unselected"), _jsx(Button, { variant: "outline", size: "icon", onClick: handleRefreshCharacters, disabled: isLoadingCharacters, title: t("cloud.discord.refreshCharacters", {
458
492
  defaultValue: "Refresh characters",
459
493
  }), children: _jsx(RefreshCw, { className: `h-4 w-4 ${isLoadingCharacters ? "animate-spin" : ""}` }) })] }), _jsx("p", { className: "text-xs text-muted-foreground", children: t("cloud.discord.characterHint", {
460
494
  defaultValue: "The AI character that will respond to messages",
@@ -40,6 +40,15 @@ export { WhatsAppConnection } from "./whatsapp-connection.js";
40
40
  * planned active-server-kind branch unifies them.
41
41
  */
42
42
  export declare const CLOUD_CONNECTORS_SECTION_ID = "cloud-connectors";
43
+ /**
44
+ * Settings-section adapter for the cloud connectors surface.
45
+ *
46
+ * The standalone cloud route is already rendered under CloudRouterShell, which
47
+ * supplies query/i18n/auth providers. Settings sections render inside the
48
+ * app-shell settings registry instead, so this adapter provides the cloud stack
49
+ * before mounting the canonical connectors body.
50
+ */
51
+ export declare function CloudConnectorsSettingsSection(): React.JSX.Element;
43
52
  /**
44
53
  * Register the cloud connectors surface as a Settings section under the "agent"
45
54
  * group. Idempotent (the registry replaces by id). Call from the host's cloud
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/connectors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAOH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAa7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/connectors/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE3D;;;;GAIG;AACH,eAAO,MAAM,2BAA2B,qBAAqB,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAMlE;AAED;;;;;GAKG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAa7D"}
@@ -25,7 +25,9 @@
25
25
  * - Discord: `GET/POST /api/v1/discord/connections`, `PATCH/DELETE /api/v1/discord/connections/:id`, `GET /api/v1/dashboard` (character list)
26
26
  */
27
27
  import { Plug } from "lucide-react";
28
+ import { createElement } from "react";
28
29
  import { registerSettingsSection } from "../../components/settings/settings-section-registry.js";
30
+ import { CloudSettingsSectionShell } from "../settings/CloudSettingsSectionShell.js";
29
31
  import { registerCloudRoute } from "../shell/cloud-route-registry.js";
30
32
  import { CloudConnectorsSection } from "./CloudConnectorsSection.js";
31
33
  export { BlooioConnection } from "./blooio-connection.js";
@@ -44,6 +46,17 @@ export { WhatsAppConnection } from "./whatsapp-connection.js";
44
46
  * planned active-server-kind branch unifies them.
45
47
  */
46
48
  export const CLOUD_CONNECTORS_SECTION_ID = "cloud-connectors";
49
+ /**
50
+ * Settings-section adapter for the cloud connectors surface.
51
+ *
52
+ * The standalone cloud route is already rendered under CloudRouterShell, which
53
+ * supplies query/i18n/auth providers. Settings sections render inside the
54
+ * app-shell settings registry instead, so this adapter provides the cloud stack
55
+ * before mounting the canonical connectors body.
56
+ */
57
+ export function CloudConnectorsSettingsSection() {
58
+ return createElement(CloudSettingsSectionShell, null, createElement(CloudConnectorsSection));
59
+ }
47
60
  /**
48
61
  * Register the cloud connectors surface as a Settings section under the "agent"
49
62
  * group. Idempotent (the registry replaces by id). Call from the host's cloud
@@ -61,7 +74,7 @@ export function registerCloudConnectorsSettingsSection() {
61
74
  group: "agent",
62
75
  titleKey: "settings.sections.cloudConnectors.title",
63
76
  defaultTitle: "Cloud Connectors",
64
- Component: CloudConnectorsSection,
77
+ Component: CloudConnectorsSettingsSection,
65
78
  });
66
79
  }
67
80
  // Register the standalone cloud route at import time. The cloud-frontend OAuth
@@ -13,6 +13,15 @@ import type { ConversationHandoffResult } from "./conversation-handoff.js";
13
13
  *
14
14
  * `start` is a thunk so the caller owns the supervisor args (agent id, bases,
15
15
  * token, `onSwitch` rebind) and this module stays decoupled + unit-testable.
16
+ *
17
+ * `onSwitchSucceeded` is the gated success hook (PR4): it fires ONLY on a
18
+ * terminal `switched`/`switched-empty` — i.e. the dedicated is confirmed live
19
+ * and the transcript was copied + the client repointed onto it. It is the ONLY
20
+ * safe moment to delete the transient shared bridge; on `timed-out`/`failed`
21
+ * (or a thrown supervisor) the user is STILL on the shared adapter, so the hook
22
+ * is deliberately NOT called and the shared bridge is kept. Best-effort: a
23
+ * throw here is swallowed (a failed shared-delete just leaks a row — never
24
+ * un-switches the user).
16
25
  */
17
- export declare function runCloudAgentHandoff(agentId: string, start: () => Promise<ConversationHandoffResult>): void;
26
+ export declare function runCloudAgentHandoff(agentId: string, start: () => Promise<ConversationHandoffResult>, onSwitchSucceeded?: () => void | Promise<void>): void;
18
27
  //# sourceMappingURL=run-cloud-agent-handoff.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-cloud-agent-handoff.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/handoff/run-cloud-agent-handoff.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,GAC9C,IAAI,CAsBN"}
1
+ {"version":3,"file":"run-cloud-agent-handoff.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/handoff/run-cloud-agent-handoff.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAExE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,EAC/C,iBAAiB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAC7C,IAAI,CA8BN"}
@@ -13,8 +13,17 @@ import { CLOUD_HANDOFF_RETRY_EVENT, dispatchCloudHandoffPhase, } from "../../eve
13
13
  *
14
14
  * `start` is a thunk so the caller owns the supervisor args (agent id, bases,
15
15
  * token, `onSwitch` rebind) and this module stays decoupled + unit-testable.
16
+ *
17
+ * `onSwitchSucceeded` is the gated success hook (PR4): it fires ONLY on a
18
+ * terminal `switched`/`switched-empty` — i.e. the dedicated is confirmed live
19
+ * and the transcript was copied + the client repointed onto it. It is the ONLY
20
+ * safe moment to delete the transient shared bridge; on `timed-out`/`failed`
21
+ * (or a thrown supervisor) the user is STILL on the shared adapter, so the hook
22
+ * is deliberately NOT called and the shared bridge is kept. Best-effort: a
23
+ * throw here is swallowed (a failed shared-delete just leaks a row — never
24
+ * un-switches the user).
16
25
  */
17
- export function runCloudAgentHandoff(agentId, start) {
26
+ export function runCloudAgentHandoff(agentId, start, onSwitchSucceeded) {
18
27
  dispatchCloudHandoffPhase({ agentId, phase: "migrating" });
19
28
  start()
20
29
  .then((result) => {
@@ -25,8 +34,16 @@ export function runCloudAgentHandoff(agentId, start) {
25
34
  ...(result.error ? { error: result.error } : {}),
26
35
  });
27
36
  if (result.status === "timed-out" || result.status === "failed") {
28
- armRetry(agentId, start);
37
+ armRetry(agentId, start, onSwitchSucceeded);
38
+ return;
29
39
  }
40
+ // Terminal SUCCESS (`switched`/`switched-empty`): the dedicated is live,
41
+ // the transcript is on it, and the client already repointed. Now — and
42
+ // ONLY now — is the shared bridge safe to delete.
43
+ void Promise.resolve(onSwitchSucceeded?.()).catch(() => {
44
+ // Fire-and-forget: a failed shared-delete leaks a row, never strands
45
+ // the (already switched) user. The supervisor logs the detail.
46
+ });
30
47
  })
31
48
  .catch((err) => {
32
49
  dispatchCloudHandoffPhase({
@@ -34,18 +51,37 @@ export function runCloudAgentHandoff(agentId, start) {
34
51
  phase: "failed",
35
52
  error: err instanceof Error ? err.message : String(err),
36
53
  });
37
- armRetry(agentId, start);
54
+ armRetry(agentId, start, onSwitchSucceeded);
38
55
  });
39
56
  }
40
- function armRetry(agentId, start) {
57
+ /**
58
+ * How long an armed retry listener stays live before it self-cleans. A handoff
59
+ * that fails and is never retried would otherwise leak its
60
+ * {@link CLOUD_HANDOFF_RETRY_EVENT} listener for the page lifetime; a flapping
61
+ * one would stack a new listener per failure. The TTL bounds both: the user has
62
+ * a generous window to hit retry, after which the listener is dropped.
63
+ */
64
+ const RETRY_ARM_TTL_MS = 10 * 60_000;
65
+ function armRetry(agentId, start, onSwitchSucceeded) {
41
66
  if (typeof window === "undefined")
42
67
  return;
68
+ // Bind the listener to an AbortController so it's removable two ways: when the
69
+ // retry actually fires (one-shot), AND on a TTL timeout if it never does. The
70
+ // `{ signal }` option means a single abort() detaches the listener — no need
71
+ // to hold the handler ref for removeEventListener.
72
+ const ac = new AbortController();
73
+ const ttl = setTimeout(() => ac.abort(), RETRY_ARM_TTL_MS);
43
74
  const onRetry = (event) => {
44
75
  const detail = event.detail;
45
76
  if (detail?.agentId !== agentId)
46
77
  return;
47
- window.removeEventListener(CLOUD_HANDOFF_RETRY_EVENT, onRetry);
48
- runCloudAgentHandoff(agentId, start);
78
+ clearTimeout(ttl);
79
+ ac.abort();
80
+ // Thread the gated delete through the retry: a handoff that fails first and
81
+ // succeeds on retry must still delete the shared bridge on the success leg.
82
+ runCloudAgentHandoff(agentId, start, onSwitchSucceeded);
49
83
  };
50
- window.addEventListener(CLOUD_HANDOFF_RETRY_EVENT, onRetry);
84
+ window.addEventListener(CLOUD_HANDOFF_RETRY_EVENT, onRetry, {
85
+ signal: ac.signal,
86
+ });
51
87
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Silently re-point the live client from the shared bridge to the dedicated
3
+ * agent — the handoff's "invisible switch".
4
+ *
5
+ * This is the handoff-ONLY alternative to `switchAgentProfile`. The global
6
+ * profile switch (`AppContext.tsx`) intentionally:
7
+ * - `clearAllChatDrafts()` — wipes the composer (conversation ids are
8
+ * per-account, so a manual account switch can't carry a draft over), and
9
+ * - dispatches `SWITCH_AGENT` — which re-enters the startup coordinator
10
+ * (`ready → polling-backend`), a phase that is NOT shell-paintable, so
11
+ * `App.tsx` swaps the whole shell for `<StartupScreen/>` (the full-screen
12
+ * flash).
13
+ * Both are correct for a manual switch but WRONG for the handoff: the dedicated
14
+ * agent already holds the copied transcript on the SAME conversation id, the
15
+ * user is mid-conversation, and the composer may hold an unsent draft. So the
16
+ * handoff re-points in place instead:
17
+ * - persist the dedicated as the active server + profile (so a reboot restores
18
+ * the dedicated, not the shared bridge),
19
+ * - re-point the API/WS base seamlessly via `client.repointBaseUrl` (which
20
+ * reconnects the WS in place — no visible drop, no coordinator re-entry),
21
+ * - set the bearer token,
22
+ * and DELIBERATELY does NOT clear drafts and does NOT dispatch `SWITCH_AGENT`.
23
+ * The chat surface stays mounted on the same conversation id throughout.
24
+ */
25
+ export declare function silentlyRepointToDedicated(opts: {
26
+ /** The dedicated agent's container base (REST + WS host). */
27
+ containerBase: string;
28
+ /** Bearer token (Steward JWT) — same one the shared bridge used. */
29
+ authToken: string;
30
+ /** The dedicated agent id — persisted so a reboot restores the dedicated. */
31
+ dedicatedAgentId: string;
32
+ }): void;
33
+ //# sourceMappingURL=silent-repoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"silent-repoint.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/handoff/silent-repoint.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CA+BP"}
@@ -0,0 +1,55 @@
1
+ import { client } from "../../api/index.js";
2
+ import { addAgentProfile, createPersistedActiveServer, savePersistedActiveServer, } from "../../state/index.js";
3
+ /**
4
+ * Silently re-point the live client from the shared bridge to the dedicated
5
+ * agent — the handoff's "invisible switch".
6
+ *
7
+ * This is the handoff-ONLY alternative to `switchAgentProfile`. The global
8
+ * profile switch (`AppContext.tsx`) intentionally:
9
+ * - `clearAllChatDrafts()` — wipes the composer (conversation ids are
10
+ * per-account, so a manual account switch can't carry a draft over), and
11
+ * - dispatches `SWITCH_AGENT` — which re-enters the startup coordinator
12
+ * (`ready → polling-backend`), a phase that is NOT shell-paintable, so
13
+ * `App.tsx` swaps the whole shell for `<StartupScreen/>` (the full-screen
14
+ * flash).
15
+ * Both are correct for a manual switch but WRONG for the handoff: the dedicated
16
+ * agent already holds the copied transcript on the SAME conversation id, the
17
+ * user is mid-conversation, and the composer may hold an unsent draft. So the
18
+ * handoff re-points in place instead:
19
+ * - persist the dedicated as the active server + profile (so a reboot restores
20
+ * the dedicated, not the shared bridge),
21
+ * - re-point the API/WS base seamlessly via `client.repointBaseUrl` (which
22
+ * reconnects the WS in place — no visible drop, no coordinator re-entry),
23
+ * - set the bearer token,
24
+ * and DELIBERATELY does NOT clear drafts and does NOT dispatch `SWITCH_AGENT`.
25
+ * The chat surface stays mounted on the same conversation id throughout.
26
+ */
27
+ export function silentlyRepointToDedicated(opts) {
28
+ const { containerBase, authToken, dedicatedAgentId } = opts;
29
+ // Persist the dedicated as the restorable active server. Keyed by the
30
+ // dedicated id so a re-boot restores the dedicated agent, not the now-stale
31
+ // shared bridge.
32
+ const server = createPersistedActiveServer({
33
+ kind: "cloud",
34
+ id: `cloud:${dedicatedAgentId}`,
35
+ apiBase: containerBase,
36
+ accessToken: authToken,
37
+ });
38
+ savePersistedActiveServer(server);
39
+ // Register + activate the dedicated profile WITHOUT going through
40
+ // switchAgentProfile (which would clear drafts + dispatch SWITCH_AGENT).
41
+ // addAgentProfile sets it active in the registry and persists before
42
+ // returning, so no separate activation step is needed.
43
+ addAgentProfile({
44
+ kind: "cloud",
45
+ label: server.label,
46
+ apiBase: containerBase,
47
+ accessToken: authToken,
48
+ });
49
+ // Seamless in-place base swap: re-point the REST base AND reconnect the WS to
50
+ // the dedicated host without a visible disconnect. The transcript was already
51
+ // copied to the dedicated agent by the handoff supervisor, so the live chat
52
+ // surface stays mounted on the same conversation id with no reload.
53
+ client.setToken(authToken);
54
+ client.repointBaseUrl(containerBase);
55
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"AgentDetailPage.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/instances/AgentDetailPage.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AA4EH,MAAM,CAAC,OAAO,UAAU,eAAe,4CA6atC"}
1
+ {"version":3,"file":"AgentDetailPage.d.ts","sourceRoot":"","sources":["../../../../../../src/cloud/instances/AgentDetailPage.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AA2EH,MAAM,CAAC,OAAO,UAAU,eAAe,4CAoatC"}
@@ -6,7 +6,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
6
6
  import { AGENT_PRICING } from "@elizaos/cloud-shared/lib/constants/agent-pricing";
7
7
  import { formatHourlyRate, formatMonthlyEstimate, } from "@elizaos/cloud-shared/lib/constants/agent-pricing-display";
8
8
  import { Badge, DashboardErrorState, DashboardLoadingState, } from "@elizaos/ui/cloud-ui";
9
- import { AlertCircle, ArrowLeft, Cloud, ExternalLink, MessageCircle, Server, Terminal, } from "lucide-react";
9
+ import { AlertCircle, ArrowLeft, Cloud, ExternalLink, Server, Terminal, } from "lucide-react";
10
10
  import { Link, Navigate, useParams } from "react-router-dom";
11
11
  import { ApiError } from "../lib/api-client.js";
12
12
  import { useDocumentTitle } from "../lib/use-document-title.js";
@@ -97,7 +97,7 @@ export default function AgentDetailPage() {
97
97
  const showConnect = !!agent.webUiUrl && agent.status === "running";
98
98
  return (_jsxs("div", { className: "max-w-5xl mx-auto space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Link, { to: "/dashboard/agents", className: "group flex items-center gap-2 text-sm text-white/50 hover:text-white transition-colors", children: [_jsx("div", { className: "flex items-center justify-center w-7 h-7 bg-black/40 group-hover:bg-white/10 transition-colors", children: _jsx(ArrowLeft, { className: "h-3.5 w-3.5" }) }), _jsx("span", { children: t("cloud.agents.detail.backToInstances", {
99
99
  defaultValue: "Instances",
100
- }) })] }), _jsxs("div", { className: "flex items-center gap-2", children: [agent.status === "running" && (_jsxs(Link, { to: `/dashboard/agents/${agent.id}/chat`, className: "inline-flex items-center gap-1.5 h-8 px-3 text-sm font-medium bg-[var(--brand-orange)] text-black hover:bg-foreground hover:text-background transition-colors", children: [_jsx(MessageCircle, { className: "h-3.5 w-3.5" }), t("cloud.agents.detail.chat", { defaultValue: "Chat" })] })), showConnect && _jsx(ElizaConnectButton, { agentId: agent.id })] })] }), _jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "flex items-start gap-4", children: [_jsx("div", { className: "flex items-center justify-center w-12 h-12 border border-[var(--brand-orange)]/25 bg-[var(--brand-orange)]/10 shrink-0", children: isDockerBacked ? (_jsx(Server, { className: "h-6 w-6 text-[var(--brand-orange)]" })) : (_jsx(Cloud, { className: "h-6 w-6 text-[var(--brand-orange)]" })) }), _jsxs("div", { className: "min-w-0 space-y-1.5", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2.5", children: [_jsx("h1", { className: "text-2xl font-semibold text-white truncate", style: { fontFamily: "var(--font-roboto-mono)" }, children: agent.agentName ??
100
+ }) })] }), _jsx("div", { className: "flex items-center gap-2", children: showConnect && _jsx(ElizaConnectButton, { agentId: agent.id }) })] }), _jsx("div", { className: "space-y-4", children: _jsxs("div", { className: "flex items-start gap-4", children: [_jsx("div", { className: "flex items-center justify-center w-12 h-12 border border-[var(--brand-orange)]/25 bg-[var(--brand-orange)]/10 shrink-0", children: isDockerBacked ? (_jsx(Server, { className: "h-6 w-6 text-[var(--brand-orange)]" })) : (_jsx(Cloud, { className: "h-6 w-6 text-[var(--brand-orange)]" })) }), _jsxs("div", { className: "min-w-0 space-y-1.5", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2.5", children: [_jsx("h1", { className: "text-2xl font-semibold text-white truncate", style: { fontFamily: "var(--font-roboto-mono)" }, children: agent.agentName ??
101
101
  t("cloud.agents.detail.unnamedAgent", {
102
102
  defaultValue: "Unnamed Agent",
103
103
  }) }), _jsxs(Badge, { variant: "outline", className: `${badgeColor} text-xs font-medium px-2 py-0.5`, children: [_jsx("span", { className: `inline-block size-1.5 rounded-full mr-1.5 ${dotColor}` }), agent.status] })] }), _jsx("div", { className: "flex items-center gap-3 text-xs text-white/35", children: _jsx("span", { className: "font-mono tabular-nums", children: agent.id }) })] })] }) }), _jsxs("div", { className: "grid grid-cols-2 lg:grid-cols-5 gap-px bg-white/5 border border-white/10", children: [_jsxs("div", { className: "bg-black/60 p-4 space-y-1", children: [_jsx("p", { className: "text-[11px] uppercase tracking-[0.2em] text-white/35", children: t("cloud.agents.detail.statusLabel", { defaultValue: "Status" }) }), _jsx("p", { className: "text-lg font-medium text-white capitalize tabular-nums", style: { fontFamily: "var(--font-roboto-mono)" }, children: agent.status })] }), _jsxs("div", { className: "bg-black/60 p-4 space-y-1", children: [_jsx("p", { className: "text-[11px] uppercase tracking-[0.2em] text-white/35", children: t("cloud.agents.detail.databaseLabel", {
@@ -1 +1 @@
1
- {"version":3,"file":"agent-actions.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/instances/components/agent-actions.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAoBpF,UAAU,sBAAsB;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,kBAAkB,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,aAAa,EACb,MAAM,EACN,QAAQ,GACT,EAAE,sBAAsB,2CAsaxB"}
1
+ {"version":3,"file":"agent-actions.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/instances/components/agent-actions.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAmBpF,UAAU,sBAAsB;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,kBAAkB,CAAC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,aAAa,EACb,MAAM,EACN,QAAQ,GACT,EAAE,sBAAsB,2CAwZxB"}
@@ -13,7 +13,7 @@
13
13
  "use client";
14
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
15
  import { BrandButton, BrandCard } from "@elizaos/ui/cloud-ui";
16
- import { Camera, ExternalLink, Loader2, MessageCircle, Moon, Pause, Play, Sun, Trash2, } from "lucide-react";
16
+ import { Camera, ExternalLink, Loader2, Moon, Pause, Play, Sun, Trash2, } from "lucide-react";
17
17
  import { useRef, useState } from "react";
18
18
  import { useNavigate } from "react-router-dom";
19
19
  import { toast } from "sonner";
@@ -61,7 +61,6 @@ export function ElizaAgentActions({ agentId, executionTier, status, webUiUrl, })
61
61
  const isSleeping = effectiveStatus === "sleeping";
62
62
  const isDedicated = executionTier !== "shared";
63
63
  const hasStandaloneWebUi = isRunning && isDedicated && Boolean(webUiUrl);
64
- const hasDashboardChat = isRunning;
65
64
  // Sleep (deep cold suspend) only applies to dedicated agents with their own
66
65
  // compute slot — shared-runtime agents have nothing to free.
67
66
  const canSleep = isRunning && isDedicated;
@@ -197,8 +196,6 @@ export function ElizaAgentActions({ agentId, executionTier, status, webUiUrl, })
197
196
  defaultValue: "Agent Actions",
198
197
  }) })] }), _jsxs("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [_jsxs("div", { className: "flex flex-wrap gap-3", children: [hasStandaloneWebUi && (_jsxs(BrandButton, { variant: "primary", size: "sm", onClick: () => void openWebUIWithPairing(agentId), children: [_jsx(ExternalLink, { className: "h-4 w-4" }), t("cloud.containers.agentActions.openWebUi", {
199
198
  defaultValue: "Open Web UI",
200
- })] })), hasDashboardChat && (_jsxs(BrandButton, { variant: "primary", size: "sm", onClick: () => navigate(`/dashboard/agents/${agentId}/chat`), children: [_jsx(MessageCircle, { className: "h-4 w-4" }), t("cloud.containers.agentActions.chat", {
201
- defaultValue: "Chat",
202
199
  })] })), isStopped && (_jsxs(BrandButton, { variant: "primary", size: "sm", onClick: () => doAction("resume"), disabled: !!loading || isBusy, children: [loading === "resume" ? (_jsx(Loader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(Play, { className: "h-4 w-4" })), t("cloud.containers.agentActions.resume", {
203
200
  defaultValue: "Resume Agent",
204
201
  })] })), canWake && (_jsxs(BrandButton, { variant: "primary", size: "sm", onClick: () => doAction("wake"), disabled: !!loading || isBusy, children: [loading === "wake" ? (_jsx(Loader2, { className: "h-4 w-4 animate-spin" })) : (_jsx(Sun, { className: "h-4 w-4" })), t("cloud.containers.agentActions.wake", {
@@ -1 +1 @@
1
- {"version":3,"file":"eliza-agents-table.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/instances/components/eliza-agents-table.tsx"],"names":[],"mappings":"AAwEA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,CAAC,EAAE,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,QAAQ,CAAC;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;CAC3B;AAED,UAAU,qBAAqB;IAC7B,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAuGD,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EAAE,gBAAgB,GAC5B,EAAE,qBAAqB,2CA6hCvB"}
1
+ {"version":3,"file":"eliza-agents-table.d.ts","sourceRoot":"","sources":["../../../../../../../src/cloud/instances/components/eliza-agents-table.tsx"],"names":[],"mappings":"AAuEA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,cAAc,CAAC,EAAE,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,QAAQ,CAAC;IAC7E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;IAC1B,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC;CAC3B;AAED,UAAU,qBAAqB;IAC7B,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAuGD,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EAAE,gBAAgB,GAC5B,EAAE,qBAAqB,2CAk/BvB"}
@@ -8,7 +8,7 @@
8
8
  "use client";
9
9
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
10
  import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Badge, DashboardDataList, DashboardDataListDesktop, DashboardDataListFilteredCount, DashboardDataListMobile, DataListEmptyState, Input, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@elizaos/ui/cloud-ui";
11
- import { ArrowUpDown, Boxes, Cloud, ExternalLink, FileText, Loader2, MessageCircle, Pause, Play, Search, Server, Trash2, } from "lucide-react";
11
+ import { ArrowUpDown, Boxes, Cloud, ExternalLink, FileText, Loader2, Pause, Play, Search, Server, Trash2, } from "lucide-react";
12
12
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
13
13
  import { toast } from "sonner";
14
14
  import { useT } from "../lib/i18n.js";
@@ -425,7 +425,6 @@ export function ElizaAgentsTable({ sandboxes: initialSandboxes, }) {
425
425
  const hasStandaloneWebUi = displayStatus === "running" &&
426
426
  sb.execution_tier !== "shared" &&
427
427
  Boolean(sb.canonical_web_ui_url);
428
- const hasDashboardChat = displayStatus === "running";
429
428
  return (_jsxs(TableRow, { className: "hover:bg-white/[0.03] transition-colors border-b border-white/5", children: [_jsx(TableCell, { children: _jsxs("div", { className: "space-y-1", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx("a", { href: `/dashboard/agents/${sb.id}`, className: "font-medium text-white hover:opacity-75 transition-opacity", children: sb.agent_name ??
430
429
  t("cloud.elizaAgentsTable.unnamedAgent", {
431
430
  defaultValue: "Unnamed Agent",
@@ -455,9 +454,6 @@ export function ElizaAgentsTable({ sandboxes: initialSandboxes, }) {
455
454
  defaultValue: "Not provisioned",
456
455
  }) }) }), _jsx(TableCell, { children: hasStandaloneWebUi ? (_jsxs("button", { type: "button", onClick: () => openWebUIWithPairing(sb.id), className: "inline-flex items-center gap-1 text-xs text-white/60 hover:text-white transition-colors bg-transparent border-0 p-0", children: [_jsx(ExternalLink, { className: "h-3 w-3" }), t("cloud.elizaAgentsTable.open", {
457
456
  defaultValue: "Open",
458
- })] })) : hasDashboardChat &&
459
- sb.execution_tier === "shared" ? (_jsxs("a", { href: `/dashboard/agents/${sb.id}/chat`, className: "inline-flex items-center gap-1 text-xs text-white/60 hover:text-white transition-colors", children: [_jsx(MessageCircle, { className: "h-3 w-3" }), t("cloud.elizaAgentsTable.chat", {
460
- defaultValue: "Chat",
461
457
  })] })) : (_jsx("span", { className: "text-xs text-white/20", children: displayStatus === "running" &&
462
458
  sb.execution_tier !== "shared"
463
459
  ? t("cloud.elizaAgentsTable.unavailable", {
@@ -470,8 +466,6 @@ export function ElizaAgentsTable({ sandboxes: initialSandboxes, }) {
470
466
  defaultValue: "View details",
471
467
  }) })] }), hasStandaloneWebUi && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => openWebUIWithPairing(sb.id), className: "p-2 text-white/30 hover:text-white hover:bg-white/10 transition-colors", children: _jsx(ExternalLink, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { className: "bg-neutral-900 border-white/10", children: t("cloud.elizaAgentsTable.openWebUi", {
472
468
  defaultValue: "Open Web UI",
473
- }) })] })), hasDashboardChat && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("a", { href: `/dashboard/agents/${sb.id}/chat`, className: "p-2 text-white/30 hover:text-white hover:bg-white/10 transition-colors", children: _jsx(MessageCircle, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { className: "bg-neutral-900 border-white/10", children: t("cloud.elizaAgentsTable.openChat", {
474
- defaultValue: "Open chat",
475
469
  }) })] })), canStart && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => handleProvision(sb.id), disabled: busy, className: "p-2 text-white/30 hover:text-green-400 hover:bg-green-500/10 transition-colors disabled:opacity-30", children: _jsx(Play, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { className: "bg-neutral-900 border-white/10", children: t("cloud.elizaAgentsTable.resumeAgent", {
476
470
  defaultValue: "Resume agent",
477
471
  }) })] })), canStop && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => handleSuspend(sb.id), disabled: busy, className: "p-2 text-white/30 hover:text-white hover:bg-white/10 transition-colors disabled:opacity-30", children: _jsx(Pause, { className: "h-4 w-4" }) }) }), _jsx(TooltipContent, { className: "bg-neutral-900 border-white/10", children: t("cloud.elizaAgentsTable.suspendAgent", {
@@ -494,7 +488,6 @@ export function ElizaAgentsTable({ sandboxes: initialSandboxes, }) {
494
488
  const hasStandaloneWebUi = displayStatus === "running" &&
495
489
  sb.execution_tier !== "shared" &&
496
490
  Boolean(sb.canonical_web_ui_url);
497
- const hasDashboardChat = displayStatus === "running";
498
491
  return (_jsxs("div", { className: "border border-white/10 bg-black/40 p-4 space-y-3", children: [_jsxs("div", { className: "flex items-start justify-between gap-3", children: [_jsxs("div", { className: "min-w-0 space-y-1", children: [_jsx("a", { href: `/dashboard/agents/${sb.id}`, className: "font-medium text-white hover:opacity-75 transition-opacity block truncate", children: sb.agent_name ??
499
492
  t("cloud.elizaAgentsTable.unnamedAgent", {
500
493
  defaultValue: "Unnamed Agent",
@@ -515,8 +508,6 @@ export function ElizaAgentsTable({ sandboxes: initialSandboxes, }) {
515
508
  defaultValue: "Details",
516
509
  })] }), hasStandaloneWebUi && (_jsxs("button", { type: "button", onClick: () => openWebUIWithPairing(sb.id), className: "flex-1 flex items-center justify-center gap-1.5 py-2 text-xs text-[var(--brand-orange)] hover:bg-white/5 transition-colors", children: [_jsx(ExternalLink, { className: "h-3.5 w-3.5" }), t("cloud.elizaAgentsTable.webUi", {
517
510
  defaultValue: "Web UI",
518
- })] })), hasDashboardChat && (_jsxs("a", { href: `/dashboard/agents/${sb.id}/chat`, className: "flex-1 flex items-center justify-center gap-1.5 py-2 text-xs text-[var(--brand-orange)] hover:bg-white/5 transition-colors", children: [_jsx(MessageCircle, { className: "h-3.5 w-3.5" }), t("cloud.elizaAgentsTable.chat", {
519
- defaultValue: "Chat",
520
511
  })] })), canStart && (_jsx("button", { type: "button", onClick: () => handleProvision(sb.id), disabled: busy, className: "py-2 px-3 text-green-400 hover:bg-green-500/10 transition-colors disabled:opacity-30", children: _jsx(Play, { className: "h-3.5 w-3.5" }) })), canStop && (_jsx("button", { type: "button", onClick: () => handleSuspend(sb.id), disabled: busy, className: "py-2 px-3 text-orange-400 hover:bg-white/5 transition-colors disabled:opacity-30", children: _jsx(Pause, { className: "h-3.5 w-3.5" }) })), _jsx("button", { type: "button", onClick: () => !busy && setDeleteId(sb.id), disabled: isDeleting || busy, className: "py-2 px-3 text-white/30 hover:text-red-400 hover:bg-red-500/10 transition-colors disabled:opacity-30", children: _jsx(Trash2, { className: "h-3.5 w-3.5" }) })] })] }, sb.id));
521
512
  })) })] }), _jsx(AlertDialog, { open: deleteId !== null, onOpenChange: () => setDeleteId(null), children: _jsxs(AlertDialogContent, { className: "bg-neutral-900 border-white/10", children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { className: "text-white", children: t("cloud.elizaAgentsTable.deleteAgentTitle", {
522
513
  defaultValue: "Delete Agent",