@agent-native/core 0.164.4 → 0.164.12

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 (268) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +84 -0
  3. package/corpus/templates/calendar/AGENTS.md +5 -0
  4. package/corpus/templates/calendar/actions/delete-event.ts +1 -1
  5. package/corpus/templates/calendar/actions/delete-events.ts +508 -0
  6. package/corpus/templates/calendar/actions/event-action-helpers.ts +1 -1
  7. package/corpus/templates/calendar/actions/list-events.ts +53 -0
  8. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +36 -47
  9. package/corpus/templates/calendar/app/components/calendar/DayView.tsx +3 -0
  10. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +18 -1
  11. package/corpus/templates/calendar/app/components/calendar/InlineEventPickers.tsx +256 -38
  12. package/corpus/templates/calendar/app/hooks/use-google-auth.ts +43 -3
  13. package/corpus/templates/calendar/app/i18n-data.ts +120 -0
  14. package/corpus/templates/calendar/app/lib/event-form-utils.ts +113 -0
  15. package/corpus/templates/calendar/changelog/2026-08-18-the-agent-can-now-remove-many-meetings-at-once-such-as-every.md +6 -0
  16. package/corpus/templates/calendar/server/handlers/google-auth.ts +119 -3
  17. package/corpus/templates/calendar/server/lib/event-weekday.ts +112 -0
  18. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  19. package/corpus/templates/calendar/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  20. package/corpus/templates/calendar/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  21. package/corpus/templates/calendar/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  22. package/corpus/templates/clips/app/components/player/video-player.tsx +12 -0
  23. package/corpus/templates/clips/app/routes/_app.dictate.tsx +18 -4
  24. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +114 -20
  25. package/corpus/templates/clips/app/routes/share.$shareId.tsx +83 -78
  26. package/corpus/templates/clips/changelog/2026-08-19-clips-nightly-builds-are-available-for-trying-the-latest-upd.md +6 -0
  27. package/corpus/templates/clips/changelog/2026-08-19-social-preview-video-frames.md +1 -0
  28. package/corpus/templates/clips/desktop/README.md +19 -4
  29. package/corpus/templates/clips/desktop/src/app.tsx +78 -16
  30. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -2
  31. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -0
  32. package/corpus/templates/clips/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  33. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.get.ts +41 -3
  34. package/corpus/templates/clips/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  35. package/corpus/templates/clips/server/routes/_agent-native/google/callback.get.ts +22 -1
  36. package/corpus/templates/clips/server/routes/api/clips-updater.json.get.ts +41 -22
  37. package/corpus/templates/factory/AGENTS.md +3 -2
  38. package/corpus/templates/factory/actions/get-factory-graph-version.ts +69 -0
  39. package/corpus/templates/factory/actions/list-factory-automations.ts +4 -0
  40. package/corpus/templates/factory/actions/list-factory-graph-versions.ts +82 -0
  41. package/corpus/templates/factory/actions/restore-factory-graph-version.ts +163 -0
  42. package/corpus/templates/factory/actions/save-factory-graph.ts +93 -60
  43. package/corpus/templates/factory/actions/start-builder-for-item.ts +19 -17
  44. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +100 -36
  45. package/corpus/templates/factory/app/components/factory/FactoryHistoryView.tsx +709 -0
  46. package/corpus/templates/factory/app/components/factory/FactoryInspector.tsx +62 -2
  47. package/corpus/templates/factory/app/components/ui/alert-dialog.tsx +1 -0
  48. package/corpus/templates/factory/app/i18n/en-US.ts +47 -0
  49. package/corpus/templates/factory/app/routes/factory.tsx +324 -61
  50. package/corpus/templates/factory/server/connectors/slack.ts +44 -2
  51. package/corpus/templates/factory/server/plugins/agent-chat.ts +12 -8
  52. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +13 -0
  53. package/corpus/templates/factory/server/triage/slack-client.ts +5 -0
  54. package/corpus/templates/factory/server/triage/slack-poller.ts +72 -4
  55. package/corpus/templates/mail/actions/view-screen.ts +1 -1
  56. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -18
  57. package/corpus/templates/mail/server/handlers/google-auth.ts +125 -24
  58. package/corpus/templates/mail/server/lib/gmail-query.ts +5 -2
  59. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/add-account/auth-url.post.ts +1 -0
  60. package/corpus/templates/mail/server/routes/[base]/_agent-native/google/auth-url.post.ts +1 -0
  61. package/corpus/templates/mail/server/routes/_agent-native/google/add-account/auth-url.post.ts +1 -0
  62. package/corpus/templates/mail/server/routes/_agent-native/google/auth-url.post.ts +1 -0
  63. package/corpus/templates/plan/app/pages/PlansPage.tsx +0 -12
  64. package/corpus/templates/plan/changelog/2026-08-19-plan-prompts-now-guide-you-to-connect-ai-before-sending-and-.md +6 -0
  65. package/corpus/templates/slides/actions/approve-deck-access-request.ts +234 -0
  66. package/corpus/templates/slides/actions/get-deck-access-status.ts +35 -2
  67. package/corpus/templates/slides/actions/request-deck-access.ts +263 -64
  68. package/corpus/templates/slides/app/components/editor/MissingDeckAccessPane.tsx +196 -0
  69. package/corpus/templates/slides/app/components/editor/RequestDeckAccessDialog.tsx +101 -0
  70. package/corpus/templates/slides/app/hooks/use-deck-access.ts +7 -4
  71. package/corpus/templates/slides/app/i18n/en-US.ts +29 -6
  72. package/corpus/templates/slides/app/pages/DeckEditor.tsx +147 -169
  73. package/corpus/templates/slides/app/routes/access-request.approve.tsx +250 -0
  74. package/corpus/templates/slides/server/db/schema.ts +8 -0
  75. package/corpus/templates/slides/server/lib/access-request-email.ts +36 -0
  76. package/corpus/templates/slides/server/lib/emails.ts +26 -0
  77. package/corpus/templates/slides/server/plugins/agent-chat.ts +7 -0
  78. package/corpus/templates/slides/server/plugins/db.ts +50 -0
  79. package/corpus/templates/slides/shared/deck-access.ts +31 -0
  80. package/dist/a2a/task-store.d.ts +1 -0
  81. package/dist/a2a/task-store.js +1 -1
  82. package/dist/agent/observational-memory/store.d.ts +1 -0
  83. package/dist/agent/observational-memory/store.js +1 -1
  84. package/dist/agent/run-store.d.ts +1 -0
  85. package/dist/agent/run-store.js +1 -1
  86. package/dist/agent/tool-approval-store.d.ts +1 -0
  87. package/dist/agent/tool-approval-store.js +1 -1
  88. package/dist/application-state/store.d.ts +1 -0
  89. package/dist/application-state/store.js +1 -1
  90. package/dist/browser-sessions/store.d.ts +1 -0
  91. package/dist/browser-sessions/store.js +1 -1
  92. package/dist/checkpoints/store.d.ts +1 -0
  93. package/dist/checkpoints/store.js +1 -1
  94. package/dist/cli/code-agent-schedules.d.ts +11 -0
  95. package/dist/cli/code-agent-schedules.js +44 -5
  96. package/dist/client/AgentPanel.d.ts +5 -1
  97. package/dist/client/AgentPanel.js +2 -2
  98. package/dist/client/AssistantChat.d.ts +5 -1
  99. package/dist/client/AssistantChat.js +40 -6
  100. package/dist/client/EnvironmentBadge.d.ts +7 -13
  101. package/dist/client/EnvironmentBadge.js +43 -92
  102. package/dist/client/agent-chat/index.d.ts +1 -0
  103. package/dist/client/agent-chat/index.js +1 -0
  104. package/dist/client/agent-chat-adapter.js +76 -50
  105. package/dist/client/app-providers.js +4 -4
  106. package/dist/client/chat/message-components.d.ts +4 -0
  107. package/dist/client/chat/message-components.js +28 -1
  108. package/dist/client/chat/run-recovery.js +26 -0
  109. package/dist/client/chat-first/apps-rail.d.ts +1 -0
  110. package/dist/client/chat-first/apps-rail.js +28 -2
  111. package/dist/client/sse-event-processor.js +13 -8
  112. package/dist/client/use-active-agent-chat-run.d.ts +2 -0
  113. package/dist/client/use-active-agent-chat-run.js +22 -0
  114. package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
  115. package/dist/coding-tools/sandbox/executions-store.js +1 -1
  116. package/dist/collab/awareness-store.d.ts +1 -0
  117. package/dist/collab/awareness-store.js +1 -1
  118. package/dist/collab/routes.d.ts +1 -1
  119. package/dist/collab/storage.d.ts +1 -0
  120. package/dist/collab/storage.js +1 -1
  121. package/dist/collab/struct-routes.d.ts +1 -1
  122. package/dist/db/client.js +3 -3
  123. package/dist/db/ddl-guard.js +8 -0
  124. package/dist/db/migration-runtime.d.ts +23 -0
  125. package/dist/db/migration-runtime.js +41 -0
  126. package/dist/db/migrations.d.ts +1 -2
  127. package/dist/db/migrations.js +2 -24
  128. package/dist/email-catalog/log.d.ts +1 -0
  129. package/dist/email-catalog/log.js +1 -1
  130. package/dist/guards/index.d.ts +1 -0
  131. package/dist/guards/index.js +1 -0
  132. package/dist/guards/release-schema-complete.d.ts +22 -0
  133. package/dist/guards/release-schema-complete.js +144 -0
  134. package/dist/integrations/a2a-continuations-store.d.ts +1 -0
  135. package/dist/integrations/a2a-continuations-store.js +1 -1
  136. package/dist/integrations/awaiting-input-store.d.ts +1 -0
  137. package/dist/integrations/awaiting-input-store.js +1 -1
  138. package/dist/integrations/config-store.d.ts +1 -0
  139. package/dist/integrations/config-store.js +1 -1
  140. package/dist/integrations/controls-store.d.ts +1 -0
  141. package/dist/integrations/controls-store.js +1 -1
  142. package/dist/integrations/identity-links-store.d.ts +1 -0
  143. package/dist/integrations/identity-links-store.js +1 -1
  144. package/dist/integrations/installations-store.d.ts +1 -0
  145. package/dist/integrations/installations-store.js +1 -1
  146. package/dist/integrations/remote-commands-store.d.ts +1 -0
  147. package/dist/integrations/remote-commands-store.js +1 -1
  148. package/dist/integrations/remote-devices-store.d.ts +1 -0
  149. package/dist/integrations/remote-devices-store.js +1 -1
  150. package/dist/integrations/remote-push-store.d.ts +1 -0
  151. package/dist/integrations/remote-push-store.js +1 -1
  152. package/dist/integrations/remote-run-events-store.d.ts +1 -0
  153. package/dist/integrations/remote-run-events-store.js +1 -1
  154. package/dist/integrations/scope-store.d.ts +1 -0
  155. package/dist/integrations/scope-store.js +1 -1
  156. package/dist/integrations/thread-mapping-store.d.ts +1 -0
  157. package/dist/integrations/thread-mapping-store.js +1 -1
  158. package/dist/integrations/usage-budget-store.d.ts +1 -0
  159. package/dist/integrations/usage-budget-store.js +1 -1
  160. package/dist/jobs/background-automation-runner.js +111 -9
  161. package/dist/jobs/run-history.d.ts +1 -0
  162. package/dist/jobs/run-history.js +1 -1
  163. package/dist/jobs/scheduler-health.d.ts +1 -0
  164. package/dist/jobs/scheduler-health.js +1 -1
  165. package/dist/mcp/approval-store.d.ts +1 -0
  166. package/dist/mcp/approval-store.js +1 -1
  167. package/dist/mcp/connect-store.d.ts +1 -0
  168. package/dist/mcp/connect-store.js +1 -1
  169. package/dist/mcp/oauth-store.d.ts +1 -0
  170. package/dist/mcp/oauth-store.js +1 -1
  171. package/dist/notifications/store.d.ts +1 -0
  172. package/dist/notifications/store.js +1 -1
  173. package/dist/oauth-tokens/store.d.ts +1 -0
  174. package/dist/oauth-tokens/store.js +1 -1
  175. package/dist/observability/routes.d.ts +5 -5
  176. package/dist/progress/routes.d.ts +1 -1
  177. package/dist/progress/store.d.ts +1 -0
  178. package/dist/progress/store.js +1 -1
  179. package/dist/provider-api/actions/custom-provider-registration.d.ts +5 -5
  180. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  181. package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
  182. package/dist/provider-api/corpus-jobs-store.js +1 -1
  183. package/dist/provider-api/custom-registry.d.ts +1 -0
  184. package/dist/provider-api/custom-registry.js +1 -1
  185. package/dist/provider-api/quota-governor.d.ts +1 -0
  186. package/dist/provider-api/quota-governor.js +1 -1
  187. package/dist/provider-api/staged-datasets-store.d.ts +1 -0
  188. package/dist/provider-api/staged-datasets-store.js +1 -1
  189. package/dist/resources/handlers.d.ts +3 -3
  190. package/dist/resources/store.d.ts +1 -0
  191. package/dist/resources/store.js +1 -1
  192. package/dist/scripts/dev/index.js +15 -1
  193. package/dist/search/index.js +3 -0
  194. package/dist/secrets/routes.d.ts +9 -9
  195. package/dist/secrets/storage.d.ts +1 -0
  196. package/dist/secrets/storage.js +1 -1
  197. package/dist/server/agent-chat-plugin.js +38 -9
  198. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  199. package/dist/server/agent-teams-run-queue.d.ts +1 -0
  200. package/dist/server/agent-teams-run-queue.js +1 -1
  201. package/dist/server/auth-marketing.js +3 -1
  202. package/dist/server/auth.d.ts +18 -1
  203. package/dist/server/auth.js +370 -154
  204. package/dist/server/embed-session.d.ts +1 -0
  205. package/dist/server/embed-session.js +1 -1
  206. package/dist/server/google-auth-plugin.js +3 -1
  207. package/dist/server/google-oauth.d.ts +10 -0
  208. package/dist/server/google-oauth.js +25 -1
  209. package/dist/server/identity-sso-store.d.ts +1 -0
  210. package/dist/server/identity-sso-store.js +1 -1
  211. package/dist/server/index.d.ts +1 -1
  212. package/dist/server/index.js +1 -1
  213. package/dist/server/onboarding-html.js +200 -31
  214. package/dist/server/poll.d.ts +2 -0
  215. package/dist/server/poll.js +19 -1
  216. package/dist/server/realtime-token.d.ts +1 -1
  217. package/dist/server/release-migrations.js +5 -0
  218. package/dist/server/release-schema.d.ts +46 -0
  219. package/dist/server/release-schema.js +307 -0
  220. package/dist/settings/store.d.ts +1 -0
  221. package/dist/settings/store.js +1 -1
  222. package/dist/shared/environment-lanes.d.ts +28 -0
  223. package/dist/shared/environment-lanes.js +61 -0
  224. package/dist/sharing/actions/share-resource.js +22 -2
  225. package/dist/styles/agent-native.css +17 -15
  226. package/dist/triggers/routes.d.ts +11 -0
  227. package/dist/triggers/routes.js +10 -0
  228. package/dist/usage/alerts-store.d.ts +1 -0
  229. package/dist/usage/alerts-store.js +1 -1
  230. package/dist/usage/store.d.ts +1 -0
  231. package/dist/usage/store.js +1 -1
  232. package/docs/content/actions-access-control.mdx +136 -2
  233. package/docs/content/actions-agent-tools.mdx +101 -0
  234. package/docs/content/actions-defining.mdx +2 -2
  235. package/docs/content/audit-log.mdx +1 -1
  236. package/docs/content/authentication.mdx +1 -1
  237. package/docs/content/cloudflare.mdx +43 -0
  238. package/docs/content/creating-templates.mdx +1 -1
  239. package/docs/content/deploy-an-app.mdx +109 -0
  240. package/docs/content/deployment-environment-variables.mdx +101 -0
  241. package/docs/content/deployment.mdx +125 -792
  242. package/docs/content/docs-components.mdx +2 -2
  243. package/docs/content/environment-variables.mdx +41 -41
  244. package/docs/content/file-uploads.mdx +74 -40
  245. package/docs/content/harness-agents.mdx +2 -2
  246. package/docs/content/internationalization.mdx +61 -65
  247. package/docs/content/key-concepts.mdx +3 -3
  248. package/docs/content/multi-app-workspace.mdx +2 -2
  249. package/docs/content/netlify.mdx +47 -0
  250. package/docs/content/node-docker.mdx +138 -0
  251. package/docs/content/organizations-teams-permissions.mdx +5 -5
  252. package/docs/content/other-platforms.mdx +27 -0
  253. package/docs/content/ssr-caching.mdx +45 -0
  254. package/docs/content/template-assets-developers.mdx +2 -2
  255. package/docs/content/template-chat-developers.mdx +2 -2
  256. package/docs/content/template-content-developers.mdx +2 -2
  257. package/docs/content/{local-file-mode.mdx → template-content-local-files.mdx} +2 -1
  258. package/docs/content/template-content-sync.mdx +2 -2
  259. package/docs/content/toolkit-agent-ux.mdx +1 -1
  260. package/docs/content/toolkit-resources.mdx +2 -2
  261. package/docs/content/updating-ui-in-production.mdx +35 -0
  262. package/docs/content/vercel.mdx +38 -0
  263. package/docs/content/what-is-agent-native.mdx +1 -1
  264. package/docs/content/workspace-deployment.mdx +350 -0
  265. package/package.json +2 -2
  266. package/docs/content/agents.mdx +0 -9
  267. package/docs/content/database.mdx +0 -317
  268. package/docs/content/human-approval.mdx +0 -156
@@ -223,6 +223,10 @@ export interface AgentSidebarProps {
223
223
  apiUrl?: string;
224
224
  /** Runtime surface identity used for server-side chat capabilities. */
225
225
  agentChatSurface?: AgentChatSurfaceKind;
226
+ /** Whether the desktop host is currently showing its unauthenticated identity gate. */
227
+ desktopIdentityUnauthenticated?: AssistantChatProps["desktopIdentityUnauthenticated"];
228
+ /** Whether the desktop host has just established its authenticated identity session. */
229
+ desktopIdentityAuthenticated?: AssistantChatProps["desktopIdentityAuthenticated"];
226
230
  /** Show the chat thread tab row. Default: true. */
227
231
  showTabBar?: MultiTabAssistantChatProps["showTabBar"];
228
232
  /** Keep inline app-opening results inside the current app chat. */
@@ -250,7 +254,7 @@ export interface AgentSidebarProps {
250
254
  * Wraps app content with a toggleable agent sidebar.
251
255
  * Use AgentToggleButton in your header to open/close it.
252
256
  */
253
- export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
257
+ export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
254
258
  /**
255
259
  * Focus the agent chat composer input.
256
260
  * Opens the sidebar if closed, then focuses the text input.
@@ -1418,7 +1418,7 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
1418
1418
  * Wraps app content with a toggleable agent sidebar.
1419
1419
  * Use AgentToggleButton in your header to open/close it.
1420
1420
  */
1421
- export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
1421
+ export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
1422
1422
  const staticHostedHarnessEnabled = isHostedHarnessConfigured(injectedAgentNativeConfig().harness);
1423
1423
  const hostedHarnessQuery = useActionQuery("get-hosted-harness-config", undefined, { enabled: staticHostedHarnessEnabled });
1424
1424
  const hostedHarnessStatus = hostedHarnessQuery.data;
@@ -2059,7 +2059,7 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
2059
2059
  ? "desktop"
2060
2060
  : undefined, "data-agent-sidebar-layout": panelLayout, "data-agent-sidebar-position": effectivePosition, "data-agent-native-hosted-harness-ui": hostedHarnessUi ? "desktop" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", "data-agent-sidebar-per-app-chat": isPerAppChatSidebar ? "true" : undefined, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, "data-agent-sidebar-chat-handoff": chatViewTransitionHandoff ? "true" : undefined, style: chatViewTransition
2061
2061
  ? getAgentChatViewTransitionStyle(panelStyle)
2062
- : panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, availableAgents: effectiveAvailableAgents, availableModels: availableModels, modelListLoading: modelListLoading, selectedAgent: effectiveSelectedAgent, onAgentChange: effectiveOnAgentChange, hostedHarness: hostedHarnessEnabled, onConnectLocalRuntime: onConnectLocalRuntime, runtime: runtime, adapterReloadKey: adapterReloadKey, threadFooterSlot: threadFooterSlot, apiUrl: apiUrl, agentChatSurface: agentChatSurface, showTabBar: effectiveShowTabBar, suppressInlineOpenApp: suppressInlineOpenApp, composerPlaceholder: composerPlaceholder, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: effectivePosition, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
2062
+ : panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, availableAgents: effectiveAvailableAgents, availableModels: availableModels, modelListLoading: modelListLoading, selectedAgent: effectiveSelectedAgent, onAgentChange: effectiveOnAgentChange, hostedHarness: hostedHarnessEnabled, onConnectLocalRuntime: onConnectLocalRuntime, runtime: runtime, adapterReloadKey: adapterReloadKey, threadFooterSlot: threadFooterSlot, apiUrl: apiUrl, agentChatSurface: agentChatSurface, desktopIdentityUnauthenticated: desktopIdentityUnauthenticated, desktopIdentityAuthenticated: desktopIdentityAuthenticated, showTabBar: effectiveShowTabBar, suppressInlineOpenApp: suppressInlineOpenApp, composerPlaceholder: composerPlaceholder, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: effectivePosition, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
2063
2063
  const drawerPlaceholder = wideDrawerEnabled && !presentationMode && panelOpen ? (_jsx("div", { "aria-hidden": "true", className: "agent-sidebar-drawer-placeholder shrink-0", "data-agent-sidebar-placeholder": "true", style: { width: drawerPlaceholderWidth + 1 } })) : null;
2064
2064
  return (_jsx(AgentSidebarOnboardingContext.Provider, { value: true, children: _jsxs(RealtimeVoiceModeProvider, { browserTabId: browserTabId, children: [showFirstRunOnboarding && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsxs("div", { className: "agent-sidebar-shell flex min-w-0 flex-1 h-screen overflow-hidden", "data-agent-sidebar-position": effectivePosition, "data-agent-native-hosted-harness-ui": hostedHarnessUi ? "desktop" : undefined, "data-agent-native-hosted-chat": isPerAppChatHosted ? "true" : undefined, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: [isMobile &&
2065
2065
  !isPerAppChatHosted &&
@@ -14,7 +14,7 @@ import { type ContentPart } from "./sse-event-processor.js";
14
14
  import type { ChatThreadScope, ChatThreadSnapshot } from "./use-chat-threads.js";
15
15
  export { AssistantMessageListErrorBoundary, AssistantUiStaleIndexErrorBoundary, assistantUiRecoverableRenderErrorKind, isAssistantUiRecoverableRenderError, isAssistantUiStaleIndexError, } from "./assistant-ui-recovery.js";
16
16
  export { displayableUserMessageText } from "./chat/message-components.js";
17
- export declare function shouldSuppressUnauthenticatedDesktopThreadRestore(surface: AgentChatSurfaceKind, status: number): boolean;
17
+ export declare function shouldSuppressUnauthenticatedDesktopThreadRestore(surface: AgentChatSurfaceKind, status: number, desktopIdentityUnauthenticated?: boolean): boolean;
18
18
  type AssistantUiMessageResourceShape = {
19
19
  id: string;
20
20
  content: readonly unknown[];
@@ -278,6 +278,10 @@ export interface AssistantChatProps {
278
278
  * dev filesystem/bash code-editing tools out of in-product sidebars.
279
279
  */
280
280
  agentChatSurface?: AgentChatSurfaceKind;
281
+ /** Whether the desktop host is currently showing its unauthenticated identity gate. */
282
+ desktopIdentityUnauthenticated?: boolean;
283
+ /** Whether the desktop host has just established its authenticated identity session. */
284
+ desktopIdentityAuthenticated?: boolean;
281
285
  /** Route completed first-party open_app calls through the host app pane. */
282
286
  suppressInlineOpenApp?: boolean;
283
287
  /** Placeholder text for empty state */
@@ -44,10 +44,14 @@ import { useRunStuckDetection } from "./use-run-stuck-detection.js";
44
44
  import { cn } from "./utils.js";
45
45
  export { AssistantMessageListErrorBoundary, AssistantUiStaleIndexErrorBoundary, assistantUiRecoverableRenderErrorKind, isAssistantUiRecoverableRenderError, isAssistantUiStaleIndexError, } from "./assistant-ui-recovery.js";
46
46
  export { displayableUserMessageText } from "./chat/message-components.js";
47
- // Desktop chat mounts beside the parent identity gate, so an unauthenticated
48
- // relay is an expected empty state until that gate establishes a session.
49
- export function shouldSuppressUnauthenticatedDesktopThreadRestore(surface, status) {
50
- return surface === "desktop" && (status === 401 || status === 403);
47
+ // Desktop chat mounts beside the parent identity gate. The server masks an
48
+ // unauthenticated thread lookup as 404, so a stale local pointer must not turn
49
+ // the sign-in screen into a dead-thread error.
50
+ export function shouldSuppressUnauthenticatedDesktopThreadRestore(surface, status, desktopIdentityUnauthenticated = false) {
51
+ return (surface === "desktop" &&
52
+ (status === 401 ||
53
+ status === 403 ||
54
+ (status === 404 && desktopIdentityUnauthenticated)));
51
55
  }
52
56
  const useBrowserLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
53
57
  export function assistantUiMessageListStructureKey(messages) {
@@ -1382,7 +1386,7 @@ function approvalResolutionIdentity(approvalKey, toolCallId,
1382
1386
  askId) {
1383
1387
  return `${toolCallId ?? ""}\u0000${approvalKey}\u0000${askId ?? ""}`;
1384
1388
  }
1385
- const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, contextNamespace, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, showModelSelector = true, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, hostedHarness, onAgentChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", suppressInlineOpenApp = false, }, ref) {
1389
+ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, contextNamespace, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, showModelSelector = true, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, availableAgents, selectedAgent, hostedHarness, onAgentChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", desktopIdentityUnauthenticated = false, desktopIdentityAuthenticated = false, suppressInlineOpenApp = false, }, ref) {
1386
1390
  const t = useT();
1387
1391
  const thread = useThread();
1388
1392
  const threadRuntime = useThreadRuntime();
@@ -1843,6 +1847,35 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
1843
1847
  setIsRestoring(true);
1844
1848
  setRestoreAttempt((attempt) => attempt + 1);
1845
1849
  }, [isNewThread, threadId]);
1850
+ // The desktop identity gate and chat restore run in sibling surfaces. If the
1851
+ // gate wins the race after a masked 404 has already rendered, clear the
1852
+ // transient not-found card and leave the user at a fresh composer.
1853
+ useEffect(() => {
1854
+ if (!desktopIdentityUnauthenticated)
1855
+ return;
1856
+ setThreadRestoreError((current) => current === "not-found" ? null : current);
1857
+ }, [desktopIdentityUnauthenticated]);
1858
+ const desktopIdentityAuthenticatedRef = useRef(desktopIdentityAuthenticated);
1859
+ useEffect(() => {
1860
+ const becameAuthenticated = desktopIdentityAuthenticated && !desktopIdentityAuthenticatedRef.current;
1861
+ desktopIdentityAuthenticatedRef.current = desktopIdentityAuthenticated;
1862
+ if (!becameAuthenticated ||
1863
+ agentChatSurface !== "desktop" ||
1864
+ !threadId ||
1865
+ isNewThread) {
1866
+ return;
1867
+ }
1868
+ // A saved-thread request can race the identity handoff and be masked as a
1869
+ // 404/401/403. Retry once the host confirms the authenticated session so
1870
+ // the thread is restored without requiring a remount or manual retry.
1871
+ retryThreadRestore();
1872
+ }, [
1873
+ agentChatSurface,
1874
+ desktopIdentityAuthenticated,
1875
+ isNewThread,
1876
+ retryThreadRestore,
1877
+ threadId,
1878
+ ]);
1846
1879
  const onSaveThreadRef = useRef(onSaveThread);
1847
1880
  onSaveThreadRef.current = onSaveThread;
1848
1881
  const onGenerateTitleRef = useRef(onGenerateTitle);
@@ -2668,7 +2701,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
2668
2701
  const res = await fetch(`${apiUrl}/threads/${encodeURIComponent(threadId)}`);
2669
2702
  if (!res.ok) {
2670
2703
  if (!cancelled) {
2671
- setThreadRestoreError(shouldSuppressUnauthenticatedDesktopThreadRestore(agentChatSurface, res.status)
2704
+ setThreadRestoreError(shouldSuppressUnauthenticatedDesktopThreadRestore(agentChatSurface, res.status, desktopIdentityUnauthenticated)
2672
2705
  ? null
2673
2706
  : res.status === 404
2674
2707
  ? "not-found"
@@ -2776,6 +2809,7 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
2776
2809
  loadHistoryRepository,
2777
2810
  isNewThread,
2778
2811
  isThreadStateLoading,
2812
+ desktopIdentityUnauthenticated,
2779
2813
  restoreAttempt,
2780
2814
  ]);
2781
2815
  useEffect(() => {
@@ -1,20 +1,14 @@
1
1
  import type { AgentNativeDeploymentEnvironment, AgentNativeConfig } from "../config.js";
2
- export declare const BETA_OPT_OUT_QUERY_PARAM = "agentNativeBetaOptOut";
3
2
  export declare const BETA_OPT_OUT_STORAGE_KEY = "agent-native:beta-opt-out-until";
4
- export declare const BETA_OPT_OUT_DURATION_MS: number;
5
- export interface EnvironmentBadgeTargets {
6
- betaHost: string;
7
- productionHost: string;
8
- }
3
+ export { BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, type EnvironmentBadgeTargets, } from "../shared/environment-lanes.js";
9
4
  export declare function isBuilderIoEmployee(email: string | null | undefined): boolean;
10
- export declare function resolveEnvironmentTargets(hostname: string | undefined): EnvironmentBadgeTargets | null;
11
5
  export declare function resolveEnvironmentChannel(config: AgentNativeConfig, hostname: string | undefined): Extract<AgentNativeDeploymentEnvironment, "beta" | "production"> | null;
12
- export declare function buildEnvironmentUrl(sourceHref: string, targetHost: string): string | null;
13
6
  export declare function isBetaOptOutActive(value: string | number | null | undefined, now?: number): boolean;
14
- export declare function buildEnvironmentOptOutUrl(sourceHref: string, targetHost: string, now?: number): string | null;
15
7
  /**
16
- * Small internal-only lane switcher for first-party hosted Agent-Native apps.
17
- * It is mounted inside the authenticated AppProviders shell so public pages,
18
- * embeds, and signed-out visitors never receive environment navigation.
8
+ * First-party hosted lane switcher. Beta is intentionally visible before
9
+ * authentication so a visitor can always leave beta from the sign-in page.
10
+ * Production remains an internal auto-redirect lane for authenticated staff.
19
11
  */
20
- export declare function EnvironmentBadge(): import("react").JSX.Element | null;
12
+ export declare function EnvironmentBadge({ showProduction, }?: {
13
+ showProduction?: boolean;
14
+ }): import("react").JSX.Element | null;
@@ -2,47 +2,15 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "@agent-native/toolkit/ui/button";
3
3
  import { Popover, PopoverContent, PopoverTrigger, } from "@agent-native/toolkit/ui/popover";
4
4
  import { useEffect, useMemo, useRef } from "react";
5
+ import { BETA_OPT_OUT_QUERY_PARAM, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, } from "../shared/environment-lanes.js";
5
6
  import { trackEvent } from "./analytics.js";
6
7
  import { injectedAgentNativeConfig } from "./app-config.js";
7
8
  import { useSession } from "./use-session.js";
8
- export const BETA_OPT_OUT_QUERY_PARAM = "agentNativeBetaOptOut";
9
9
  export const BETA_OPT_OUT_STORAGE_KEY = "agent-native:beta-opt-out-until";
10
- export const BETA_OPT_OUT_DURATION_MS = 24 * 60 * 60 * 1000;
11
- const ENVIRONMENT_BETA_HOSTS = {
12
- "agent-workspace.builder.io": "beta.agent-workspace.builder.io",
13
- "analytics.agent-native.com": "beta.analytics.agent-native.com",
14
- "assets.agent-native.com": "beta.assets.agent-native.com",
15
- "brain.agent-native.com": "beta.brain.agent-native.com",
16
- "calendar.agent-native.com": "beta.calendar.agent-native.com",
17
- "chat.agent-native.com": "beta.chat.agent-native.com",
18
- "clips.agent-native.com": "beta.clips.agent-native.com",
19
- "content.agent-native.com": "beta.content.agent-native.com",
20
- "crm.agent-native.com": "beta.crm.agent-native.com",
21
- "design.agent-native.com": "beta.design.agent-native.com",
22
- "dispatch.agent-native.com": "beta.dispatch.agent-native.com",
23
- "factory.agent-native.com": "beta.factory.agent-native.com",
24
- "forms.agent-native.com": "beta.forms.agent-native.com",
25
- "macros.agent-native.com": "beta.macros.agent-native.com",
26
- "mail.agent-native.com": "beta.mail.agent-native.com",
27
- "plan.agent-native.com": "beta.plan.agent-native.com",
28
- "slides.agent-native.com": "beta.slides.agent-native.com",
29
- };
10
+ export { BETA_OPT_OUT_DURATION_MS, BETA_OPT_OUT_QUERY_PARAM, buildEnvironmentOptOutUrl, buildEnvironmentUrl, resolveEnvironmentTargets, } from "../shared/environment-lanes.js";
30
11
  export function isBuilderIoEmployee(email) {
31
12
  return email?.trim().toLowerCase().endsWith("@builder.io") ?? false;
32
13
  }
33
- export function resolveEnvironmentTargets(hostname) {
34
- const normalized = hostname?.trim().toLowerCase().replace(/\.$/, "");
35
- if (!normalized)
36
- return null;
37
- const productionHost = normalized.replace(/^beta\./, "");
38
- const betaHost = ENVIRONMENT_BETA_HOSTS[productionHost];
39
- if (!betaHost)
40
- return null;
41
- return {
42
- betaHost,
43
- productionHost,
44
- };
45
- }
46
14
  export function resolveEnvironmentChannel(config, hostname) {
47
15
  const configured = config.deployment?.environment;
48
16
  if (configured === "beta" || configured === "production") {
@@ -55,37 +23,10 @@ export function resolveEnvironmentChannel(config, hostname) {
55
23
  ? "beta"
56
24
  : "production";
57
25
  }
58
- export function buildEnvironmentUrl(sourceHref, targetHost) {
59
- try {
60
- const target = new URL(sourceHref);
61
- target.protocol = "https:";
62
- target.hostname = targetHost;
63
- target.port = "";
64
- return target.toString();
65
- }
66
- catch {
67
- // coercion-ok: Invalid navigation input is an explicit absent target.
68
- return null;
69
- }
70
- }
71
26
  export function isBetaOptOutActive(value, now = Date.now()) {
72
27
  const expiry = typeof value === "number" ? value : Number(value);
73
28
  return Number.isFinite(expiry) && expiry > now;
74
29
  }
75
- export function buildEnvironmentOptOutUrl(sourceHref, targetHost, now = Date.now()) {
76
- const targetHref = buildEnvironmentUrl(sourceHref, targetHost);
77
- if (!targetHref)
78
- return null;
79
- try {
80
- const target = new URL(targetHref);
81
- target.searchParams.set(BETA_OPT_OUT_QUERY_PARAM, String(now + BETA_OPT_OUT_DURATION_MS));
82
- return target.toString();
83
- }
84
- catch {
85
- // coercion-ok: buildEnvironmentUrl already validated the URL.
86
- return null;
87
- }
88
- }
89
30
  function readBetaOptOutUntil(now = Date.now()) {
90
31
  if (typeof window === "undefined")
91
32
  return null;
@@ -133,29 +74,29 @@ function consumeBetaOptOutQueryParam(sourceHref, now = Date.now()) {
133
74
  function EnvironmentLink({ label, href }) {
134
75
  return (_jsx(Button, { asChild: true, className: "w-full justify-center", size: "sm", variant: "outline", children: _jsx("a", { href: href, children: label }) }));
135
76
  }
136
- /**
137
- * Small internal-only lane switcher for first-party hosted Agent-Native apps.
138
- * It is mounted inside the authenticated AppProviders shell so public pages,
139
- * embeds, and signed-out visitors never receive environment navigation.
140
- */
141
- export function EnvironmentBadge() {
77
+ function EnvironmentBadgeContent({ environment, targets, }) {
78
+ if (typeof window === "undefined")
79
+ return null;
80
+ const currentHref = window.location.href;
81
+ const betaHref = buildEnvironmentUrl(currentHref, targets.betaHost);
82
+ const productionHref = buildEnvironmentOptOutUrl(currentHref, targets.productionHost);
83
+ if (environment === "beta" ? !productionHref : !betaHref)
84
+ return null;
85
+ const label = environment === "beta" ? "beta" : "prod";
86
+ const title = environment === "beta"
87
+ ? "You're on Agent Native Beta"
88
+ : "You're on Agent Native Production";
89
+ return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { "aria-label": `Open ${title.toLowerCase()} switcher`, className: "fixed bottom-3 right-3 z-[100] h-6 min-w-0 rounded-xl border-border/80 bg-background/95 px-2 text-[11px] font-semibold uppercase tracking-[0.5px] shadow-sm backdrop-blur-sm", size: "sm", variant: environment === "beta" ? "default" : "outline", children: label }) }), _jsxs(PopoverContent, { align: "center", className: "w-[280px] p-5", side: "top", sideOffset: 8, children: [_jsx("div", { className: "mb-1 text-sm font-semibold leading-5", children: title }), _jsx("div", { className: "mb-4 text-sm text-muted-foreground", children: "Choose where you want to continue." }), _jsx("div", { className: "grid gap-2", children: environment === "beta" ? (_jsx(EnvironmentLink, { href: productionHref, label: "Switch to production" })) : (_jsx(EnvironmentLink, { href: betaHref, label: "Go to beta" })) })] })] }));
90
+ }
91
+ function ProductionEnvironmentBadge({ targets, }) {
142
92
  const { session, status } = useSession();
143
- const config = useMemo(injectedAgentNativeConfig, []);
144
- const didAutoRedirect = useRef(false);
145
- const hostname = typeof window === "undefined" ? undefined : window.location.hostname;
146
- const environment = resolveEnvironmentChannel(config, hostname);
147
- const targets = resolveEnvironmentTargets(hostname);
148
93
  const isEligible = typeof window !== "undefined" &&
149
94
  window.parent === window &&
150
95
  status === "authenticated" &&
151
- isBuilderIoEmployee(session?.email) &&
152
- !!environment &&
153
- !!targets;
96
+ isBuilderIoEmployee(session?.email);
97
+ const didAutoRedirect = useRef(false);
154
98
  useEffect(() => {
155
- if (!isEligible ||
156
- environment !== "production" ||
157
- !targets ||
158
- didAutoRedirect.current) {
99
+ if (!isEligible || didAutoRedirect.current) {
159
100
  return;
160
101
  }
161
102
  if (readBetaOptOutUntil() !== null)
@@ -172,21 +113,31 @@ export function EnvironmentBadge() {
172
113
  trigger: "automatic_redirect",
173
114
  });
174
115
  window.location.replace(betaHref);
175
- }, [environment, isEligible, session?.email, status, targets?.betaHost]);
176
- if (!isEligible ||
116
+ }, [isEligible, session?.email, status, targets.betaHost]);
117
+ if (!isEligible)
118
+ return null;
119
+ return _jsx(EnvironmentBadgeContent, { environment: "production", targets: targets });
120
+ }
121
+ /**
122
+ * First-party hosted lane switcher. Beta is intentionally visible before
123
+ * authentication so a visitor can always leave beta from the sign-in page.
124
+ * Production remains an internal auto-redirect lane for authenticated staff.
125
+ */
126
+ export function EnvironmentBadge({ showProduction = true, } = {}) {
127
+ const config = useMemo(injectedAgentNativeConfig, []);
128
+ const hostname = typeof window === "undefined" ? undefined : window.location.hostname;
129
+ const environment = resolveEnvironmentChannel(config, hostname);
130
+ const targets = resolveEnvironmentTargets(hostname);
131
+ if (typeof window === "undefined" ||
132
+ window.parent !== window ||
177
133
  !environment ||
178
- !targets ||
179
- typeof window === "undefined") {
134
+ !targets) {
180
135
  return null;
181
136
  }
182
- const currentHref = window.location.href;
183
- const betaHref = buildEnvironmentUrl(currentHref, targets.betaHost);
184
- const productionHref = buildEnvironmentOptOutUrl(currentHref, targets.productionHost);
185
- if (!betaHref || !productionHref)
137
+ if (environment === "beta") {
138
+ return _jsx(EnvironmentBadgeContent, { environment: "beta", targets: targets });
139
+ }
140
+ if (!showProduction)
186
141
  return null;
187
- const label = environment === "beta" ? "beta" : "prod";
188
- const title = environment === "beta"
189
- ? "You're on Agent Native Beta"
190
- : "You're on Agent Native Production";
191
- return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { "aria-label": `Open ${title.toLowerCase()} switcher`, className: "fixed bottom-3 right-3 z-[100] h-6 min-w-0 rounded-xl border-border/80 bg-background/95 px-2 text-[11px] font-semibold uppercase tracking-[0.5px] shadow-sm backdrop-blur-sm", size: "sm", variant: environment === "beta" ? "default" : "outline", children: label }) }), _jsxs(PopoverContent, { align: "center", className: "w-[280px] p-5", side: "top", sideOffset: 8, children: [_jsx("div", { className: "mb-1 text-sm font-semibold leading-5", children: title }), _jsx("div", { className: "mb-4 text-sm text-muted-foreground", children: "Choose where you want to continue." }), _jsx("div", { className: "grid gap-2", children: environment === "beta" ? (_jsx(EnvironmentLink, { href: productionHref, label: "Switch to production" })) : (_jsx(EnvironmentLink, { href: betaHref, label: "Go to beta" })) })] })] }));
142
+ return _jsx(ProductionEnvironmentBadge, { targets: targets });
192
143
  }
@@ -3,6 +3,7 @@ export { AgentAskPopover, type AgentAskPopoverProps, } from "../AgentAskPopover.
3
3
  export { addContextToAgentChat, appendAgentChatContextToMessage, clearAgentChatContext, formatAgentChatContextItemsForPrompt, insertAgentComposerReference, listAgentChatContext, normalizeAgentComposerReference, refreshAgentChatContext, removeAgentChatContextItem, requestAgentChatThreadOpen, requestAgentTaskOpen, sendToAgentChat, sendToAgentChatAndConfirm, reportAgentChatSubmitResult, AGENT_CHAT_SUBMIT_RESULT_EVENT, parseSubmitChatMessage, setAgentChatContextItem, setContextToAgentChat, generateTabId, type ParsedSubmitChat, type AgentChatOpenTaskRequest, type AgentChatOpenThreadRequest, type AgentChatContextItem, type AgentChatContextMessage, type AgentChatContextMutationOptions, type AgentChatContextRemoveOptions, type AgentChatContextSetOptions, type AgentChatContextState, type AgentChatMessage, type AgentChatSubmitResult, type SendToAgentChatAndConfirmResult, type AgentComposerReference, type AgentComposerReferenceInsertOptions, type AgentComposerReferenceInsertPayload, } from "../agent-chat.js";
4
4
  export { saveAgentEngineApiKey, saveAgentEngineProviderSettings, type AgentEngineProvider, type SaveAgentEngineApiKeyOptions, type SaveAgentEngineProviderSettingsOptions, } from "../agent-engine-key.js";
5
5
  export { useAgentChatGenerating } from "../use-agent-chat.js";
6
+ export { useActiveAgentChatRunId } from "../use-active-agent-chat-run.js";
6
7
  export { useAgentChatContext, type UseAgentChatContextResult, } from "../use-agent-chat-context.js";
7
8
  export { useCodeMode, useDevMode } from "../use-dev-mode.js";
8
9
  export { codeAgentTranscriptEventsToContent, codeAgentTranscriptHasPendingApproval, createCodeAgentChatAdapter, type CodeAgentChatController, type CodeAgentChatControlResult, type CodeAgentChatFollowUpMode, type CodeAgentChatTranscriptEvent, type CreateCodeAgentChatAdapterOptions, } from "../code-agent-chat-adapter.js";
@@ -3,6 +3,7 @@ export { AgentAskPopover, } from "../AgentAskPopover.js";
3
3
  export { addContextToAgentChat, appendAgentChatContextToMessage, clearAgentChatContext, formatAgentChatContextItemsForPrompt, insertAgentComposerReference, listAgentChatContext, normalizeAgentComposerReference, refreshAgentChatContext, removeAgentChatContextItem, requestAgentChatThreadOpen, requestAgentTaskOpen, sendToAgentChat, sendToAgentChatAndConfirm, reportAgentChatSubmitResult, AGENT_CHAT_SUBMIT_RESULT_EVENT, parseSubmitChatMessage, setAgentChatContextItem, setContextToAgentChat, generateTabId, } from "../agent-chat.js";
4
4
  export { saveAgentEngineApiKey, saveAgentEngineProviderSettings, } from "../agent-engine-key.js";
5
5
  export { useAgentChatGenerating } from "../use-agent-chat.js";
6
+ export { useActiveAgentChatRunId } from "../use-active-agent-chat-run.js";
6
7
  export { useAgentChatContext, } from "../use-agent-chat-context.js";
7
8
  export { useCodeMode, useDevMode } from "../use-dev-mode.js";
8
9
  export { codeAgentTranscriptEventsToContent, codeAgentTranscriptHasPendingApproval, createCodeAgentChatAdapter, } from "../code-agent-chat-adapter.js";