@agent-native/core 0.151.1 → 0.152.0

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 (256) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/sharing/SKILL.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +24 -0
  4. package/corpus/templates/analytics/actions/bigquery-query.ts +21 -0
  5. package/corpus/templates/analytics/app/components/ConnectionTestStatus.tsx +65 -0
  6. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +3 -3
  7. package/corpus/templates/analytics/app/pages/DataSources.tsx +15 -37
  8. package/corpus/templates/analytics/app/root.tsx +0 -1
  9. package/corpus/templates/analytics/changelog/2026-08-11-analytics-custom-blocks-keep-loading-with-legacy-bigquery-action.md +6 -0
  10. package/corpus/templates/analytics/changelog/2026-08-11-analytics-routes-company-knowledge-and-slack-context-questio.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  12. package/corpus/templates/analytics/public/manifest.json +0 -1
  13. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +5 -0
  14. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  15. package/corpus/templates/assets/.agents/skills/sharing/SKILL.md +1 -1
  16. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +24 -0
  17. package/corpus/templates/assets/app/root.tsx +0 -1
  18. package/corpus/templates/assets/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  19. package/corpus/templates/assets/public/manifest.json +0 -1
  20. package/corpus/templates/brain/.agents/skills/sharing/SKILL.md +1 -1
  21. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +24 -0
  22. package/corpus/templates/brain/app/root.tsx +0 -1
  23. package/corpus/templates/brain/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  24. package/corpus/templates/brain/public/manifest.json +0 -1
  25. package/corpus/templates/calendar/.agents/skills/sharing/SKILL.md +1 -1
  26. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +24 -0
  27. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +0 -53
  28. package/corpus/templates/calendar/app/i18n-data.ts +0 -80
  29. package/corpus/templates/calendar/app/root.tsx +0 -1
  30. package/corpus/templates/calendar/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  31. package/corpus/templates/calendar/changelog/2026-08-11-google-calendar-connection-buttons-now-open-the-sign-in-flow.md +6 -0
  32. package/corpus/templates/calendar/public/manifest.json +0 -1
  33. package/corpus/templates/calendar/server/plugins/auth.ts +0 -10
  34. package/corpus/templates/chat/.agents/skills/sharing/SKILL.md +1 -1
  35. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +24 -0
  36. package/corpus/templates/chat/app/root.tsx +0 -1
  37. package/corpus/templates/chat/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  38. package/corpus/templates/chat/public/manifest.json +0 -1
  39. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +24 -0
  40. package/corpus/templates/clips/app/components/player/playback-comment-overlay.tsx +1 -1
  41. package/corpus/templates/clips/app/components/player/share-dialog.tsx +6 -0
  42. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +20 -3
  43. package/corpus/templates/clips/app/i18n/en-US.ts +4 -4
  44. package/corpus/templates/clips/app/root.tsx +0 -1
  45. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -3
  46. package/corpus/templates/clips/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  47. package/corpus/templates/clips/changelog/2026-08-11-clips-desktop-settings-are-now-easier-to-scan-with-a-wider-t.md +6 -0
  48. package/corpus/templates/clips/changelog/2026-08-11-google-calendar-connections-from-meetings-now-open-directly.md +6 -0
  49. package/corpus/templates/clips/changelog/2026-08-11-recording-viewers-can-comment-and-react.md +6 -0
  50. package/corpus/templates/clips/changelog/2026-08-11-system-audio-recording-now-lives-inside-the-microphone-menu-.md +6 -0
  51. package/corpus/templates/clips/changelog/2026-08-11-timestamped-comments-stay-on-the-video-for-three-seconds-wh.md +6 -0
  52. package/corpus/templates/clips/desktop/src/app.tsx +773 -1001
  53. package/corpus/templates/clips/desktop/src/components/MediaDeviceRow.tsx +15 -27
  54. package/corpus/templates/clips/desktop/src/styles.css +364 -5
  55. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +1 -1
  56. package/corpus/templates/clips/public/manifest.json +0 -1
  57. package/corpus/templates/content/.agents/skills/sharing/SKILL.md +1 -1
  58. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +24 -0
  59. package/corpus/templates/content/AGENTS.md +3 -0
  60. package/corpus/templates/content/actions/resolve-content-landing.ts +120 -0
  61. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +9 -0
  62. package/corpus/templates/content/app/i18n-data.ts +58 -0
  63. package/corpus/templates/content/app/lib/content-landing.ts +22 -0
  64. package/corpus/templates/content/app/root.tsx +0 -1
  65. package/corpus/templates/content/app/routes/_app._index.tsx +36 -26
  66. package/corpus/templates/content/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  67. package/corpus/templates/content/changelog/2026-08-11-content-opens-your-last-page-on-return-and-gives-new-users-a.md +6 -0
  68. package/corpus/templates/content/docs/product/capabilities/content.workspace.session-restore.md +7 -1
  69. package/corpus/templates/content/parity/matrix.md +1 -0
  70. package/corpus/templates/content/parity/matrix.ts +22 -0
  71. package/corpus/templates/content/public/manifest.json +0 -1
  72. package/corpus/templates/content/shared/content-landing.ts +17 -0
  73. package/corpus/templates/crm/.agents/skills/sharing/SKILL.md +1 -1
  74. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +24 -0
  75. package/corpus/templates/crm/app/root.tsx +0 -1
  76. package/corpus/templates/crm/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  77. package/corpus/templates/crm/public/manifest.json +0 -1
  78. package/corpus/templates/design/.agents/skills/sharing/SKILL.md +1 -1
  79. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +24 -0
  80. package/corpus/templates/design/app/i18n/en-US.ts +5 -0
  81. package/corpus/templates/design/app/root.tsx +0 -1
  82. package/corpus/templates/design/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  83. package/corpus/templates/design/changelog/2026-08-11-design-sharing-now-identifies-viewers-who-can-add-review-com.md +6 -0
  84. package/corpus/templates/design/public/manifest.json +0 -1
  85. package/corpus/templates/dispatch/.agents/skills/sharing/SKILL.md +1 -1
  86. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +24 -0
  87. package/corpus/templates/dispatch/AGENTS.md +9 -0
  88. package/corpus/templates/dispatch/actions/list-dispatch-usage-metrics.ts +5 -19
  89. package/corpus/templates/dispatch/actions/view-screen.ts +10 -3
  90. package/corpus/templates/dispatch/app/root.tsx +0 -1
  91. package/corpus/templates/dispatch/app/routes/settings.tsx +13 -1
  92. package/corpus/templates/dispatch/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  93. package/corpus/templates/dispatch/changelog/2026-08-11-clicking-the-dispatch-logo-returns-to-the-overview-page.md +6 -0
  94. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-no-longer-links-to-itself-from-the-app-switcher.md +6 -0
  95. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-settings-now-link-directly-to-admin.md +6 -0
  96. package/corpus/templates/dispatch/changelog/2026-08-11-dispatch-shows-usage-trends-recent-prompts-and-an-agent-revi.md +6 -0
  97. package/corpus/templates/dispatch/changelog/2026-08-11-human-friendly-app-names.md +6 -0
  98. package/corpus/templates/dispatch/public/manifest.json +0 -1
  99. package/corpus/templates/dispatch/server/lib/identity-sso.ts +432 -158
  100. package/corpus/templates/dispatch/server/plugins/identity-sso.ts +204 -123
  101. package/corpus/templates/dispatch/server/plugins/setup-dispatch.ts +1 -0
  102. package/corpus/templates/factory/.agents/skills/sharing/SKILL.md +1 -1
  103. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +24 -0
  104. package/corpus/templates/factory/app/root.tsx +0 -1
  105. package/corpus/templates/factory/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  106. package/corpus/templates/factory/public/manifest.json +0 -1
  107. package/corpus/templates/forms/.agents/skills/sharing/SKILL.md +1 -1
  108. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +24 -0
  109. package/corpus/templates/forms/app/root.tsx +0 -1
  110. package/corpus/templates/forms/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  111. package/corpus/templates/forms/public/manifest.json +0 -1
  112. package/corpus/templates/macros/.agents/skills/sharing/SKILL.md +1 -1
  113. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +24 -0
  114. package/corpus/templates/mail/.agents/skills/sharing/SKILL.md +1 -1
  115. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +24 -0
  116. package/corpus/templates/mail/app/root.tsx +0 -1
  117. package/corpus/templates/mail/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  118. package/corpus/templates/mail/changelog/2026-08-11-google-sign-in-now-opens-the-gmail-connection-flow-directly.md +6 -0
  119. package/corpus/templates/mail/public/manifest.json +0 -1
  120. package/corpus/templates/mail/server/plugins/auth.ts +0 -10
  121. package/corpus/templates/plan/.agents/skills/sharing/SKILL.md +1 -1
  122. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +24 -0
  123. package/corpus/templates/plan/app/i18n/en-US.ts +2 -0
  124. package/corpus/templates/plan/app/pages/PlansPage.tsx +6 -0
  125. package/corpus/templates/plan/app/root.tsx +0 -1
  126. package/corpus/templates/plan/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  127. package/corpus/templates/plan/changelog/2026-08-11-plan-sharing-now-identifies-viewers-who-can-add-comments.md +6 -0
  128. package/corpus/templates/plan/public/manifest.json +0 -1
  129. package/corpus/templates/slides/.agents/skills/sharing/SKILL.md +1 -1
  130. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +13 -0
  131. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +24 -0
  132. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +6 -0
  133. package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
  134. package/corpus/templates/slides/app/root.tsx +0 -1
  135. package/corpus/templates/slides/changelog/2026-08-10-asking-the-agent-for-several-slide-animations-at-once-now-ke.md +6 -0
  136. package/corpus/templates/slides/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  137. package/corpus/templates/slides/changelog/2026-08-11-share-dialog-uses-commenter-terminology.md +6 -0
  138. package/corpus/templates/slides/public/manifest.json +0 -1
  139. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +1 -1
  140. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +24 -0
  141. package/corpus/templates/tasks/app/root.tsx +0 -1
  142. package/corpus/templates/tasks/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  143. package/corpus/templates/tasks/public/manifest.json +0 -1
  144. package/dist/agent/production-agent.js +1 -22
  145. package/dist/agent/run-manager.d.ts +7 -0
  146. package/dist/agent/run-manager.js +46 -3
  147. package/dist/agent/tool-approval-migrations.d.ts +40 -0
  148. package/dist/agent/tool-approval-migrations.js +51 -0
  149. package/dist/agent/tool-approval-store.js +5 -20
  150. package/dist/cli/templates-meta.js +2 -2
  151. package/dist/client/AgentPanel.js +10 -1
  152. package/dist/client/AssistantChat.d.ts +3 -0
  153. package/dist/client/AssistantChat.js +148 -140
  154. package/dist/client/agent-page/AgentTabsPage.js +2 -2
  155. package/dist/client/chat/attachment-adapters.js +8 -2
  156. package/dist/client/chat/tool-call-display.d.ts +1 -0
  157. package/dist/client/chat/tool-call-display.js +3 -1
  158. package/dist/client/chat-first.js +11 -5
  159. package/dist/client/hooks/index.d.ts +1 -1
  160. package/dist/client/hooks/index.js +1 -1
  161. package/dist/client/org/OrgSwitcher.d.ts +3 -1
  162. package/dist/client/org/OrgSwitcher.js +22 -16
  163. package/dist/client/org/WorkspaceNotice.js +3 -1
  164. package/dist/client/resources/index.d.ts +1 -1
  165. package/dist/client/resources/index.js +1 -1
  166. package/dist/client/resources/use-mcp-servers.d.ts +1 -0
  167. package/dist/client/resources/use-mcp-servers.js +14 -0
  168. package/dist/client/settings/AccountSettingsCard.js +8 -4
  169. package/dist/client/settings/SettingsPanel.js +46 -13
  170. package/dist/client/settings/SettingsTabsPage.js +8 -3
  171. package/dist/client/sharing/ShareButton.d.ts +7 -1
  172. package/dist/client/sharing/ShareButton.js +14 -7
  173. package/dist/client/sharing/ShareDialog.js +5 -1
  174. package/dist/client/sharing/useShareButtonController.d.ts +4 -0
  175. package/dist/client/sharing/useShareButtonController.js +15 -0
  176. package/dist/client/sharing/useShareDialogController.d.ts +7 -0
  177. package/dist/client/sharing/useShareDialogController.js +14 -0
  178. package/dist/client/sse-event-processor.js +37 -0
  179. package/dist/client/use-session.d.ts +2 -0
  180. package/dist/client/use-session.js +69 -5
  181. package/dist/collab/struct-routes.d.ts +1 -1
  182. package/dist/deploy/build.js +1 -1
  183. package/dist/file-upload/pre-upload-attachments.d.ts +3 -4
  184. package/dist/file-upload/pre-upload-attachments.js +65 -17
  185. package/dist/ingestion/index.d.ts +1 -0
  186. package/dist/ingestion/index.js +1 -0
  187. package/dist/ingestion/office.d.ts +3 -3
  188. package/dist/ingestion/office.js +24 -2
  189. package/dist/ingestion/spreadsheet.d.ts +41 -0
  190. package/dist/ingestion/spreadsheet.js +172 -0
  191. package/dist/integrations/adapters/slack.js +7 -3
  192. package/dist/localization/default-messages.d.ts +3 -0
  193. package/dist/localization/default-messages.js +3 -0
  194. package/dist/mcp/embed-app.js +20 -9
  195. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  196. package/dist/notifications/routes.d.ts +6 -6
  197. package/dist/oauth-tokens/migrations.d.ts +8 -0
  198. package/dist/oauth-tokens/migrations.js +36 -0
  199. package/dist/observability/routes.d.ts +5 -5
  200. package/dist/org/workspace-url.d.ts +8 -0
  201. package/dist/org/workspace-url.js +26 -2
  202. package/dist/progress/routes.d.ts +1 -1
  203. package/dist/secrets/routes.d.ts +3 -3
  204. package/dist/server/agent-chat-plugin.js +16 -8
  205. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  206. package/dist/server/auth.d.ts +0 -11
  207. package/dist/server/auth.js +37 -20
  208. package/dist/server/better-auth-migrations.js +23 -0
  209. package/dist/server/email-template.d.ts +5 -0
  210. package/dist/server/email-template.js +9 -0
  211. package/dist/server/embed-route.js +17 -5
  212. package/dist/server/identity-sso-store.d.ts +40 -66
  213. package/dist/server/identity-sso-store.js +187 -150
  214. package/dist/server/identity-sso.d.ts +17 -73
  215. package/dist/server/identity-sso.js +294 -297
  216. package/dist/server/onboarding-html.d.ts +0 -12
  217. package/dist/server/onboarding-html.js +46 -269
  218. package/dist/server/realtime-token.d.ts +1 -1
  219. package/dist/server/release-migrations.js +8 -0
  220. package/dist/server/transcribe-voice.d.ts +1 -1
  221. package/dist/shared/index.d.ts +1 -1
  222. package/dist/shared/index.js +1 -1
  223. package/dist/shared/workspace-app-id.d.ts +2 -0
  224. package/dist/shared/workspace-app-id.js +10 -0
  225. package/dist/sharing/actions/share-resource.d.ts +1 -0
  226. package/dist/sharing/actions/share-resource.js +20 -5
  227. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +1 -1
  228. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +24 -0
  229. package/dist/templates/chat/app/root.tsx +0 -1
  230. package/dist/templates/chat/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  231. package/dist/templates/chat/public/manifest.json +0 -1
  232. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +24 -0
  233. package/dist/templates/default/app/root.tsx +0 -1
  234. package/dist/templates/default/public/manifest.json +0 -1
  235. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +24 -0
  236. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +22 -11
  237. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +1 -1
  238. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +24 -0
  239. package/docs/content/cross-app-sso.mdx +85 -27
  240. package/docs/content/template-mail.mdx +0 -6
  241. package/package.json +4 -3
  242. package/src/templates/chat/.agents/skills/sharing/SKILL.md +1 -1
  243. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +24 -0
  244. package/src/templates/chat/app/root.tsx +0 -1
  245. package/src/templates/chat/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  246. package/src/templates/chat/public/manifest.json +0 -1
  247. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +24 -0
  248. package/src/templates/default/app/root.tsx +0 -1
  249. package/src/templates/default/public/manifest.json +0 -1
  250. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +24 -0
  251. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +22 -11
  252. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +1 -1
  253. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +24 -0
  254. package/corpus/templates/calendar/changelog/2026-06-23-added-a-heads-up-explaining-google-s-app-not-verified-screen.md +0 -6
  255. package/corpus/templates/clips/app/components/meetings/google-oauth-identity-notice.tsx +0 -51
  256. package/corpus/templates/clips/changelog/2026-07-30-google-calendar-warning.md +0 -6
@@ -1,37 +1,22 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { getDbExec, intType, isPostgres, retryOnDdlRace, } from "../db/client.js";
2
+ import { getDbExec, isPostgres, retryOnDdlRace } from "../db/client.js";
3
3
  import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
4
+ import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_TABLE_SQL, } from "./tool-approval-migrations.js";
4
5
  const APPROVAL_TTL_MS = 15 * 60_000;
5
6
  const APPROVAL_CLEANUP_AGE_MS = 24 * 60 * 60_000;
6
7
  let initPromise;
7
8
  async function ensureAgentToolApprovalTable() {
8
9
  if (!initPromise) {
9
10
  initPromise = (async () => {
10
- const createSql = `CREATE TABLE IF NOT EXISTS agent_tool_approvals (
11
- id TEXT PRIMARY KEY,
12
- owner_email TEXT NOT NULL,
13
- org_id TEXT,
14
- thread_id TEXT,
15
- turn_id TEXT,
16
- tool_name TEXT NOT NULL,
17
- call_id TEXT NOT NULL,
18
- approval_key_hash TEXT NOT NULL,
19
- status TEXT NOT NULL,
20
- expires_at ${intType()} NOT NULL,
21
- consumed_at ${intType()},
22
- created_at ${intType()} NOT NULL,
23
- updated_at ${intType()} NOT NULL
24
- )`;
25
- const indexSql = `CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_binding
26
- ON agent_tool_approvals(owner_email, org_id, thread_id, tool_name, call_id, status)`;
11
+ const createSql = AGENT_TOOL_APPROVAL_TABLE_SQL[isPostgres() ? "postgres" : "sqlite"];
27
12
  if (isPostgres()) {
28
13
  await ensureTableExists("agent_tool_approvals", createSql);
29
- await ensureIndexExists("idx_agent_tool_approvals_binding", indexSql);
14
+ await ensureIndexExists("idx_agent_tool_approvals_binding", AGENT_TOOL_APPROVAL_INDEX_SQL);
30
15
  return;
31
16
  }
32
17
  const client = getDbExec();
33
18
  await retryOnDdlRace(() => client.execute(createSql));
34
- await retryOnDdlRace(() => client.execute(indexSql));
19
+ await retryOnDdlRace(() => client.execute(AGENT_TOOL_APPROVAL_INDEX_SQL));
35
20
  })().catch((error) => {
36
21
  initPromise = undefined;
37
22
  throw error;
@@ -46,8 +46,8 @@ export const TEMPLATES = [
46
46
  label: "Plan",
47
47
  hint: "Structured visual plans and PR recaps with diagrams, wireframes, prototypes, annotations, and sharing",
48
48
  icon: "FileText",
49
- color: "#52525B",
50
- colorRgb: "82 82 91",
49
+ color: "#2F6FED",
50
+ colorRgb: "47 111 237",
51
51
  devPort: 8105,
52
52
  prodUrl: "https://plan.agent-native.com",
53
53
  defaultMode: "prod",
@@ -690,7 +690,16 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
690
690
  return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, resourceTitle: activeTab.label || "Chat", shareUrl: getChatThreadShareUrl(activeTab.id), trigger: "icon", triggerClassName: "h-7 w-7" }));
691
691
  })(), feedbackEnabled ? (_jsx(FeedbackButton, { variant: "icon", side: "bottom", align: "end", chatSessionId: activeChatSessionId, chatStorageKey: storageKey, open: feedbackOpen, onOpenChange: setFeedbackOpen, trigger: _jsx("button", { type: "button", tabIndex: -1, "aria-hidden": "true", className: "pointer-events-none absolute end-0 top-full h-px w-px opacity-0" }) })) : null, mode === "chat" && (_jsx(IconTooltip, { content: t("agentPanel.newChat"), children: _jsx("button", { onClick: addTab, "aria-label": t("agentPanel.newChat"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), !onCollapse && mode === "cli" && canUseCodeTools && (_jsx(IconTooltip, { content: t("agentPanel.newTerminal"), children: _jsx("button", { onClick: addCliTab, "aria-label": t("agentPanel.newTerminal"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), _jsxs(DropdownMenu, { open: headerMenuOpen, onOpenChange: setHeaderMenuOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { className: cn("flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", (headerMenuOpen || mode === "settings") &&
692
692
  "bg-accent text-foreground"), "aria-label": t("agentPanel.panelOptions"), children: _jsx(IconDotsVertical, { size: 14 }) }) }), _jsxs(DropdownMenuContent, { align: "end", sideOffset: 6, className: "w-48", children: [onCollapse && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: onCollapse, children: [_jsx(IconLayoutSidebarRightCollapse, { size: 14, className: "shrink-0" }), t("agentPanel.collapseSidebar"), _jsx(DropdownMenuShortcut, { children: toggleSidebarHint })] }), _jsx(DropdownMenuSeparator, {})] })), onCollapse && mode === "chat" && wideDrawerAction ? (_jsxs(DropdownMenuItem, { onSelect: wideDrawerAction, children: [_jsx(IconArrowsHorizontal, { size: 14, className: "shrink-0" }), wideDrawerLabel, _jsx(DropdownMenuShortcut, { children: widenChatHint })] })) : null, showFullViewAction && agentPageHref ? (_jsx(DropdownMenuItem, { asChild: true, children: _jsxs(Link, { to: agentPageHref, "aria-label": t("agentPanel.openFullView"), children: [_jsx(IconArrowsMaximize, { size: 14, className: "shrink-0" }), t("agentPanel.openFullView")] }) })) : null, (onCollapse && mode === "chat" && wideDrawerAction) ||
693
- showFullViewAction ? (_jsx(DropdownMenuSeparator, {})) : null, onCollapse && mode === "chat" && (_jsxs(DropdownMenuItem, { onSelect: addTab, children: [_jsx(IconPlus, { size: 14, className: "shrink-0" }), t("agentPanel.newChat")] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: () => {
693
+ showFullViewAction ? (_jsx(DropdownMenuSeparator, {})) : null, onCollapse && mode === "chat" && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuItem, { onSelect: addTab, children: [_jsx(IconPlus, { size: 14, className: "shrink-0" }), t("agentPanel.newChat")] }), (() => {
694
+ const activeTab = activeChatSessionId
695
+ ? tabs.find((tab) => tab.id === activeChatSessionId)
696
+ : undefined;
697
+ if (!activeTab ||
698
+ (activeTabMessageCount <= 0 && activeTab.status === "idle")) {
699
+ return null;
700
+ }
701
+ return (_jsx("div", { className: "p-1", children: _jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, resourceTitle: activeTab.label || "Chat", shareUrl: getChatThreadShareUrl(activeTab.id), trigger: "label-icon", triggerClassName: "w-full justify-start" }) }));
702
+ })()] })), mode === "chat" && toggleHistory && (_jsxs(DropdownMenuItem, { onSelect: () => {
694
703
  // Let the menu finish restoring focus before mounting the
695
704
  // history popover; otherwise Radix dismisses the new overlay.
696
705
  setTimeout(() => toggleHistory(), 0);
@@ -117,6 +117,7 @@ export declare function resolveAssistantChatRunningStatusLabel({ runningActivity
117
117
  isReconnecting: boolean;
118
118
  hasReconnectContent: boolean;
119
119
  }): string;
120
+ export declare function resolveAssistantChatComposerPlaceholder(composerPlaceholder: string | null | undefined): string;
120
121
  export declare function shouldShowGlobalRunningStatus({ showRunningInUI, runningActivityLabel, runningActivityTool, latestMessage, reconnectContent, }: {
121
122
  showRunningInUI: boolean;
122
123
  runningActivityLabel: string | null | undefined;
@@ -236,6 +237,8 @@ export interface AssistantChatProps {
236
237
  * dev filesystem/bash code-editing tools out of in-product sidebars.
237
238
  */
238
239
  agentChatSurface?: AgentChatSurfaceKind;
240
+ /** Route completed first-party open_app calls through the host app pane. */
241
+ suppressInlineOpenApp?: boolean;
239
242
  /** Placeholder text for empty state */
240
243
  emptyStateText?: string;
241
244
  /** Suggestion prompts shown when no messages */
@@ -23,7 +23,7 @@ import { CheckpointContext, MessageActionsContext, assistantMessageRunId, UserMe
23
23
  import { repoHasAssistantMessage, getRepoMessages, getRepoMessage, shouldImportServerThreadData, dedupeRepoMessagesById, dropEmptyAssistantMessages, withLastAssistantRunDuration, } from "./chat/repo-helpers.js";
24
24
  import { BuilderSetupCard, BuilderSetupContent, LoopLimitContinueCard, RunErrorRecoveryCard, PlanModeCallout, getLoopLimitMetadata, getRunErrorMetadata, getRequestModeMetadata, runErrorKey, } from "./chat/run-recovery.js";
25
25
  import { createAgentChatRuntimeAdapter, } from "./chat/runtime.js";
26
- import { ChatRunningContext, ChatRunningRunIdContext, ChatRunningTurnIdContext, ChatRunDurationContext, ApprovalContext, ReconnectStreamMessage, } from "./chat/tool-call-display.js";
26
+ import { ChatRunningContext, ChatRunningRunIdContext, ChatRunningTurnIdContext, ChatRunDurationContext, SuppressInlineOpenAppContext, ApprovalContext, ReconnectStreamMessage, } from "./chat/tool-call-display.js";
27
27
  import { useAgentChatLifecycleTracking } from "./chat/use-agent-chat-lifecycle-tracking.js";
28
28
  import { useReconnectReaderOwner } from "./chat/use-reconnect-reader-owner.js";
29
29
  import { MessageScroller, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, } from "./components/ui/message-scroller.js";
@@ -123,6 +123,7 @@ const RECONNECT_EMPTY_RETRY_MESSAGE = "The previous attempt disconnected before
123
123
  // through transient labels ("Contacting model", "Preparing X action"); past it
124
124
  // the live label appears so a genuinely slow step reads as working, not hung.
125
125
  const ACTIVITY_LABEL_REVEAL_DELAY_MS = 6_000;
126
+ const DEFAULT_ASSISTANT_CHAT_COMPOSER_PLACEHOLDER = "Write a message...";
126
127
  function isReplayableTerminalRun(runInfo) {
127
128
  const dispatchMode = typeof runInfo.dispatchMode === "string" ? runInfo.dispatchMode : "";
128
129
  return (runInfo.status !== "running" &&
@@ -1021,6 +1022,9 @@ export function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, i
1021
1022
  return "Still working";
1022
1023
  return "Thinking";
1023
1024
  }
1025
+ export function resolveAssistantChatComposerPlaceholder(composerPlaceholder) {
1026
+ return composerPlaceholder ?? DEFAULT_ASSISTANT_CHAT_COMPOSER_PLACEHOLDER;
1027
+ }
1024
1028
  function contentHasVisibleTailReasoning(content) {
1025
1029
  if (!Array.isArray(content))
1026
1030
  return false;
@@ -1037,7 +1041,7 @@ function contentHasVisibleTailReasoning(content) {
1037
1041
  }
1038
1042
  return false;
1039
1043
  }
1040
- function contentHasToolCall(content, toolName) {
1044
+ function contentHasActiveToolCall(content, toolName) {
1041
1045
  if (!Array.isArray(content))
1042
1046
  return false;
1043
1047
  return content.some((part) => {
@@ -1045,6 +1049,7 @@ function contentHasToolCall(content, toolName) {
1045
1049
  return false;
1046
1050
  const candidate = part;
1047
1051
  return (candidate.type === "tool-call" &&
1052
+ candidate.result === undefined &&
1048
1053
  (!toolName || candidate.toolName === toolName));
1049
1054
  });
1050
1055
  }
@@ -1056,36 +1061,37 @@ export function shouldShowGlobalRunningStatus({ showRunningInUI, runningActivity
1056
1061
  : null;
1057
1062
  const latestMessageHasTailReasoning = message?.role === "assistant" &&
1058
1063
  contentHasVisibleTailReasoning(message.content);
1059
- const latestMessageHasTool = message?.role === "assistant" && contentHasToolCall(message.content);
1060
- const reconnectHasTool = contentHasToolCall(reconnectContent);
1064
+ const latestMessageHasActiveTool = message?.role === "assistant" && contentHasActiveToolCall(message.content);
1065
+ const reconnectHasActiveTool = contentHasActiveToolCall(reconnectContent);
1061
1066
  const reconnectHasTailReasoning = contentHasVisibleTailReasoning(reconnectContent);
1062
1067
  const matchingActivityToolIsVisible = Boolean(runningActivityTool &&
1063
1068
  ((message?.role === "assistant" &&
1064
- contentHasToolCall(message.content, runningActivityTool)) ||
1065
- contentHasToolCall(reconnectContent, runningActivityTool)));
1069
+ contentHasActiveToolCall(message.content, runningActivityTool)) ||
1070
+ contentHasActiveToolCall(reconnectContent, runningActivityTool)));
1066
1071
  // A pending card for the same tool is already the running indicator.
1067
1072
  // Rendering its global activity label as well shows the logical call twice
1068
1073
  // (for example, `generate design` plus `Writing generate design...`).
1069
1074
  if (runningActivityLabel && matchingActivityToolIsVisible) {
1070
1075
  return false;
1071
1076
  }
1072
- if (!runningActivityLabel && (latestMessageHasTool || reconnectHasTool)) {
1077
+ if (!runningActivityLabel &&
1078
+ (latestMessageHasActiveTool || reconnectHasActiveTool)) {
1073
1079
  return false;
1074
1080
  }
1075
1081
  // The reasoning cell already owns the generic Thinking state. Activity
1076
1082
  // events can briefly reassert that same label between reasoning deltas;
1077
1083
  // rendering both makes a second Thinking row flash beneath the thought.
1078
1084
  if (runningActivityLabel === "Thinking" &&
1079
- (latestMessageHasTool ||
1080
- reconnectHasTool ||
1085
+ (latestMessageHasActiveTool ||
1086
+ reconnectHasActiveTool ||
1081
1087
  latestMessageHasTailReasoning ||
1082
1088
  reconnectHasTailReasoning)) {
1083
1089
  return false;
1084
1090
  }
1085
1091
  if (runningActivityLabel)
1086
1092
  return true;
1087
- return (!latestMessageHasTool &&
1088
- !reconnectHasTool &&
1093
+ return (!latestMessageHasActiveTool &&
1094
+ !reconnectHasActiveTool &&
1089
1095
  !latestMessageHasTailReasoning &&
1090
1096
  !reconnectHasTailReasoning);
1091
1097
  }
@@ -1359,7 +1365,7 @@ export function useAutoResumeStatus(tabId, forceStopped) {
1359
1365
  function approvalResolutionIdentity(approvalKey, toolCallId) {
1360
1366
  return `${toolCallId ?? ""}\u0000${approvalKey}`;
1361
1367
  }
1362
- const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", }, ref) {
1368
+ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateText, suggestions, dynamicSuggestions, threadFooterSlot, emptyStateAddon, showHeader = true, onSwitchToCli, className, apiUrl, tabId, browserTabId, threadId, contextScope, isActiveComposer = true, onMessageCountChange, onSaveThread, onGenerateTitle, composerSlot, onComposerTextChange, composerAreaClassName, composerPlaceholder, missingApiKeySetupLayout = "default", composerLayoutVariant = "default", centerComposerWhenEmpty = false, emptyStateDisplay = "default", composerToolbarSlot, composerExtraActionButton, composerDisabled = false, composerDisabledPlaceholder, isNewThread, isThreadStateLoading, onSlashCommand, execMode, onExecModeChange, approvalActions, planModeDisabled, planModeDisabledReason, selectedModel, defaultModel, selectedEngine, selectedEffort, availableModels, modelListLoading, onModelChange, onEffortChange, imageModelMenu, onForkChat, onConnectProvider, onConnectLocalRuntime, plusMenuMode = "full", providerStatusChecksEnabled = true, loadHistoryRepository, historyReloadKey, externalStreaming = false, agentChatSurface = "app", suppressInlineOpenApp = false, }, ref) {
1363
1369
  const thread = useThread();
1364
1370
  const threadRuntime = useThreadRuntime();
1365
1371
  const composerRuntime = useComposerRuntime();
@@ -4133,141 +4139,143 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
4133
4139
  approvalActions,
4134
4140
  recordApprovalResolution,
4135
4141
  ]);
4136
- return (_jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(MessageActionsContext.Provider, { value: messageActionsCtx, children: _jsx(ApprovalContext.Provider, { value: approvalCtx, children: _jsx(ChatRunDurationContext.Provider, { value: lastChatRunDurationMs, children: _jsx(ServerRunActiveContext.Provider, { value: serverRunActive, children: _jsx(ChatRunningRunIdContext.Provider, { value: activeChatRunId, children: _jsx(ChatRunningTurnIdContext.Provider, { value: activeChatTurnId, children: _jsx(ChatRunningContext.Provider
4137
- // Keep the current message in a non-complete state while
4138
- // the terminal error card is visible, even if the server
4139
- // still reports the prior run for a short time while its
4140
- // claim is released. Historical messages use turn
4141
- // ownership below.
4142
- , {
4142
+ return (_jsx(SuppressInlineOpenAppContext.Provider, { value: suppressInlineOpenApp, children: _jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(MessageActionsContext.Provider, { value: messageActionsCtx, children: _jsx(ApprovalContext.Provider, { value: approvalCtx, children: _jsx(ChatRunDurationContext.Provider, { value: lastChatRunDurationMs, children: _jsx(ServerRunActiveContext.Provider, { value: serverRunActive, children: _jsx(ChatRunningRunIdContext.Provider, { value: activeChatRunId, children: _jsx(ChatRunningTurnIdContext.Provider, { value: activeChatTurnId, children: _jsx(ChatRunningContext.Provider
4143
4143
  // Keep the current message in a non-complete state while
4144
4144
  // the terminal error card is visible, even if the server
4145
4145
  // still reports the prior run for a short time while its
4146
4146
  // claim is released. Historical messages use turn
4147
4147
  // ownership below.
4148
- value: showRunningInUI || runErrorInfo !== null, children: _jsx(TextStreamingContext.Provider, { value: textStreaming, children: _jsxs("div", { "data-agent-empty-state": centeredEmptyState
4149
- ? "centered"
4150
- : compactMissingKeyEmptyState
4151
- ? "compact-setup"
4152
- : undefined, className: cn("relative flex flex-1 flex-col h-full min-h-0 text-foreground", className), onDragEnter: handleChatDragEnter, onDragOver: handleChatDragOver, onDragLeave: handleChatDragLeave, onDropCapture: handleChatDropCapture, onDrop: handleChatDrop, children: [dropActive && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-50 flex items-center justify-center rounded-md border-2 border-dashed border-primary/70 bg-primary/5 backdrop-blur-[1px]", children: _jsx("span", { className: "rounded-md bg-background/90 px-3 py-1.5 text-xs font-medium text-foreground shadow-sm", children: "Drop to attach" }) })), showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { onClick: onSwitchToCli, "aria-label": "Switch to CLI", className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] }) }), _jsx(TooltipContent, { children: "Switch to CLI" })] }) })) })] })), _jsx(MessageScrollerProvider, { autoScroll: false, children: _jsxs(MessageScroller, { className: "agent-chat-scroll", children: [_jsx(MessageScrollerViewport, { ref: scrollRef, children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: authSessionAvailable ? (_jsx(IconRefresh, { className: "h-5 w-5 text-muted-foreground" })) : (_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" })) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authSessionAvailable
4153
- ? "Chat session needs refresh"
4154
- : authError.sessionExpired
4155
- ? "Session expired"
4156
- : "Authentication required" }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authSessionAvailable
4157
- ? "You're signed in, but this chat connection needs to reconnect."
4158
- : authError.sessionExpired
4159
- ? "Your session may have expired. Log out and log back in to reconnect."
4160
- : "You need to log in to use the agent." })] }), _jsxs("div", { className: "flex gap-2", children: [!authError.sessionExpired &&
4161
- !authSessionAvailable && (_jsx("button", { onClick: () => {
4162
- window.location.href =
4163
- buildSignInReturnHref();
4164
- }, className: "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md", children: "Log in" })), authError.sessionExpired &&
4165
- !authSessionAvailable && (_jsx("button", { onClick: async () => {
4166
- try {
4167
- await fetch(agentNativePath("/_agent-native/auth/logout"), {
4168
- method: "POST",
4169
- });
4148
+ , {
4149
+ // Keep the current message in a non-complete state while
4150
+ // the terminal error card is visible, even if the server
4151
+ // still reports the prior run for a short time while its
4152
+ // claim is released. Historical messages use turn
4153
+ // ownership below.
4154
+ value: showRunningInUI || runErrorInfo !== null, children: _jsx(TextStreamingContext.Provider, { value: textStreaming, children: _jsxs("div", { "data-agent-empty-state": centeredEmptyState
4155
+ ? "centered"
4156
+ : compactMissingKeyEmptyState
4157
+ ? "compact-setup"
4158
+ : undefined, className: cn("relative flex flex-1 flex-col h-full min-h-0 text-foreground", className), onDragEnter: handleChatDragEnter, onDragOver: handleChatDragOver, onDragLeave: handleChatDragLeave, onDropCapture: handleChatDropCapture, onDrop: handleChatDrop, children: [dropActive && (_jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0 z-50 flex items-center justify-center rounded-md border-2 border-dashed border-primary/70 bg-primary/5 backdrop-blur-[1px]", children: _jsx("span", { className: "rounded-md bg-background/90 px-3 py-1.5 text-xs font-medium text-foreground shadow-sm", children: "Drop to attach" }) })), showHeader && (_jsxs("div", { className: "flex h-11 shrink-0 items-center justify-between border-b border-border px-4", children: [_jsx("span", { className: "text-[13px] font-medium text-muted-foreground", children: "Agent" }), _jsx("div", { className: "flex items-center gap-1", children: onSwitchToCli && (_jsx(TooltipProvider, { delayDuration: 200, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("button", { onClick: onSwitchToCli, "aria-label": "Switch to CLI", className: "flex items-center gap-1 text-[12px] text-muted-foreground hover:text-foreground px-2 py-1 rounded-md hover:bg-accent", children: [_jsx(IconTerminal, { className: "h-3.5 w-3.5" }), "CLI"] }) }), _jsx(TooltipContent, { children: "Switch to CLI" })] }) })) })] })), _jsx(MessageScrollerProvider, { autoScroll: false, children: _jsxs(MessageScroller, { className: "agent-chat-scroll", children: [_jsx(MessageScrollerViewport, { ref: scrollRef, children: authError ? (_jsxs("div", { className: "flex flex-col items-center justify-center h-full px-4 gap-3", children: [_jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-full bg-muted", children: authSessionAvailable ? (_jsx(IconRefresh, { className: "h-5 w-5 text-muted-foreground" })) : (_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground" })) }), _jsxs("div", { className: "text-center max-w-[280px]", children: [_jsx("p", { className: "text-sm font-medium text-foreground mb-1", children: authSessionAvailable
4159
+ ? "Chat session needs refresh"
4160
+ : authError.sessionExpired
4161
+ ? "Session expired"
4162
+ : "Authentication required" }), _jsx("p", { className: "text-xs text-muted-foreground leading-relaxed", children: authSessionAvailable
4163
+ ? "You're signed in, but this chat connection needs to reconnect."
4164
+ : authError.sessionExpired
4165
+ ? "Your session may have expired. Log out and log back in to reconnect."
4166
+ : "You need to log in to use the agent." })] }), _jsxs("div", { className: "flex gap-2", children: [!authError.sessionExpired &&
4167
+ !authSessionAvailable && (_jsx("button", { onClick: () => {
4168
+ window.location.href =
4169
+ buildSignInReturnHref();
4170
+ }, className: "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md", children: "Log in" })), authError.sessionExpired &&
4171
+ !authSessionAvailable && (_jsx("button", { onClick: async () => {
4172
+ try {
4173
+ await fetch(agentNativePath("/_agent-native/auth/logout"), {
4174
+ method: "POST",
4175
+ });
4176
+ }
4177
+ catch (error) {
4178
+ console.error("Failed to log out before reloading the chat", error);
4179
+ }
4180
+ window.location.reload();
4181
+ }, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "Log out" })), _jsx("button", { onClick: () => {
4182
+ setAuthError(null);
4183
+ window.location.reload();
4184
+ }, className: authSessionAvailable
4185
+ ? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
4186
+ : "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Refresh chat" })] })] })) : isRestoring && centeredRestoringState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
4187
+ ? "sr-only"
4188
+ : "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), "aria-busy": "true", children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ?? "Loading chat..." })] })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : showEmptyState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
4189
+ ? "sr-only"
4190
+ : "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ?? "How can I help you?" }), emptyStateAddon, resolvedSuggestions &&
4191
+ resolvedSuggestions.length > 0 ? (_jsx("div", { className: "flex w-full max-w-[280px] flex-col gap-1", children: resolvedSuggestions.map((suggestion) => (_jsx("button", { onClick: () => {
4192
+ if (engineSetupRequired) {
4193
+ requestMissingKeySetup();
4194
+ return;
4170
4195
  }
4171
- catch (error) {
4172
- console.error("Failed to log out before reloading the chat", error);
4196
+ void addToQueue(suggestion);
4197
+ }, className: "w-full px-2 py-1 text-center text-[13px] text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: suggestion }, suggestion))) })) : null, showInlineEmptyThreadFooterSlot ? (_jsx("div", { className: "agent-thread-footer-slot agent-thread-footer-slot--empty", children: resolvedThreadFooterSlot })) : null] })) : (_jsxs(MessageScrollerContent, { className: "agent-thread-content gap-4 px-4 py-4", children: [_jsx(AssistantMessageListErrorBoundary, { resetKey: messageListResetKey, children: _jsx(UserStoppedRunContext.Provider, { value: wasRecentlyStoppedRun, children: _jsx(ThreadPrimitive.Messages
4198
+ // assistant-ui indexes message parts through tap resources.
4199
+ // Keep this key tied to that shape so clear/add transitions remount stale
4200
+ // lookups without remounting on every streamed text update.
4201
+ , { components: {
4202
+ UserMessage: AssistantChatUserMessageItem,
4203
+ AssistantMessage: AssistantChatAssistantMessageItem,
4204
+ } }, messageListResetKey) }) }), visibleLoopLimit && !showRunningInUI && (_jsx(MessageScrollerItem, { children: _jsx(LoopLimitContinueCard, { info: visibleLoopLimit, onContinue: () => {
4205
+ setShowContinue(false);
4206
+ setLoopLimitInfo(null);
4207
+ addToQueue("Continue from where you left off.", undefined, undefined, undefined, undefined, "queued", "continue");
4208
+ } }) })), shouldShowRunError && visibleRunError && (_jsx(MessageScrollerItem, { children: _jsx(RunErrorRecoveryCard, { info: visibleRunError, onContinue: () => {
4209
+ setRunErrorInfo(null);
4210
+ addToQueue(RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE, undefined, undefined, undefined, undefined, "queued", "continue");
4211
+ }, onRetry: retryAfterRunError, onFork: onForkChat, onProviderConnected: handleBuilderConnected, onDismiss: () => {
4212
+ if (visibleRunErrorKey) {
4213
+ setDismissedRunErrorKey(visibleRunErrorKey);
4173
4214
  }
4174
- window.location.reload();
4175
- }, className: "text-xs text-destructive hover:text-destructive/80 px-3 py-1.5 rounded-md border border-destructive/30 hover:bg-destructive/10", children: "Log out" })), _jsx("button", { onClick: () => {
4176
- setAuthError(null);
4177
- window.location.reload();
4178
- }, className: authSessionAvailable
4179
- ? "text-xs text-background bg-foreground hover:opacity-90 px-3 py-1.5 rounded-md"
4180
- : "text-xs text-muted-foreground hover:text-foreground px-3 py-1.5 rounded-md border border-border hover:bg-accent", children: "Refresh chat" })] })] })) : isRestoring && centeredRestoringState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
4181
- ? "sr-only"
4182
- : "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), "aria-busy": "true", children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ?? "Loading chat..." })] })) : isRestoring ? (_jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "flex justify-end", children: _jsx("div", { className: "h-8 w-32 rounded-lg bg-muted animate-pulse" }) }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx("div", { className: "h-4 w-48 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-64 rounded bg-muted animate-pulse" }), _jsx("div", { className: "h-4 w-40 rounded bg-muted animate-pulse" })] })] })) : showEmptyState ? (_jsxs("div", { className: cn("agent-empty-state", emptyStateDisplay === "hidden"
4183
- ? "sr-only"
4184
- : "flex h-full flex-col items-center justify-center gap-3 px-4 py-16"), children: [_jsx(IconMessage, { className: "h-5 w-5 text-muted-foreground/60" }), _jsx("p", { className: "sr-only", children: emptyStateText ?? "How can I help you?" }), emptyStateAddon, resolvedSuggestions &&
4185
- resolvedSuggestions.length > 0 ? (_jsx("div", { className: "flex w-full max-w-[280px] flex-col gap-1", children: resolvedSuggestions.map((suggestion) => (_jsx("button", { onClick: () => {
4186
- if (engineSetupRequired) {
4187
- requestMissingKeySetup();
4188
- return;
4189
- }
4190
- void addToQueue(suggestion);
4191
- }, className: "w-full px-2 py-1 text-center text-[13px] text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: suggestion }, suggestion))) })) : null, showInlineEmptyThreadFooterSlot ? (_jsx("div", { className: "agent-thread-footer-slot agent-thread-footer-slot--empty", children: resolvedThreadFooterSlot })) : null] })) : (_jsxs(MessageScrollerContent, { className: "agent-thread-content gap-4 px-4 py-4", children: [_jsx(AssistantMessageListErrorBoundary, { resetKey: messageListResetKey, children: _jsx(UserStoppedRunContext.Provider, { value: wasRecentlyStoppedRun, children: _jsx(ThreadPrimitive.Messages
4192
- // assistant-ui indexes message parts through tap resources.
4193
- // Keep this key tied to that shape so clear/add transitions remount stale
4194
- // lookups without remounting on every streamed text update.
4195
- , { components: {
4196
- UserMessage: AssistantChatUserMessageItem,
4197
- AssistantMessage: AssistantChatAssistantMessageItem,
4198
- } }, messageListResetKey) }) }), visibleLoopLimit && !showRunningInUI && (_jsx(MessageScrollerItem, { children: _jsx(LoopLimitContinueCard, { info: visibleLoopLimit, onContinue: () => {
4199
- setShowContinue(false);
4200
- setLoopLimitInfo(null);
4201
- addToQueue("Continue from where you left off.", undefined, undefined, undefined, undefined, "queued", "continue");
4202
- } }) })), shouldShowRunError && visibleRunError && (_jsx(MessageScrollerItem, { children: _jsx(RunErrorRecoveryCard, { info: visibleRunError, onContinue: () => {
4203
- setRunErrorInfo(null);
4204
- addToQueue(RECONNECT_NO_PROGRESS_CONTINUE_MESSAGE, undefined, undefined, undefined, undefined, "queued", "continue");
4205
- }, onRetry: retryAfterRunError, onFork: onForkChat, onProviderConnected: handleBuilderConnected, onDismiss: () => {
4206
- if (visibleRunErrorKey) {
4207
- setDismissedRunErrorKey(visibleRunErrorKey);
4208
- }
4209
- setRunErrorInfo(null);
4210
- } }) })), (isReconnecting ||
4211
- reconnectFrozen ||
4212
- adapterHandoffPending) &&
4213
- visibleReconnectContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: visibleReconnectContent, allowActivitySpinner: !reconnectFrozen }) })), (isReconnecting ||
4214
- reconnectFrozen ||
4215
- adapterHandoffPending) &&
4216
- visibleReconnectContent.length === 0 &&
4217
- reconnectContent.length === 0 &&
4218
- reconnectActivityContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: reconnectActivityContent, allowActivitySpinner: !reconnectFrozen }) })), showGlobalRunningStatus && (_jsx(MessageScrollerItem, { children: _jsx(RunningActivityStatus, { label: runningStatusLabel }) })), visibleQueuedMessages.length > 0 && (_jsx(MessageScrollerItem, { children: _jsxs("div", { className: "flex items-center justify-end gap-1.5 pr-0.5 text-xs text-muted-foreground", children: [_jsx(IconClock, { className: "h-3 w-3" }), _jsxs("span", { children: [visibleQueuedMessages.length, " queued"] })] }) })), visibleQueuedMessages.map((msg) => {
4219
- const displayText = displayableUserMessageText(msg.text);
4220
- const imageSources = queuedMessageImageSources(msg);
4221
- return (_jsx(MessageScrollerItem, { messageId: msg.id, children: _jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [isRunning && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => sendQueuedMessageNow(msg.id), "aria-label": "Send now", className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconArrowUp, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Send now (stops the current response)" })] })), _jsx("button", { type: "button", onClick: () => applyLocalQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) }), _jsxs("div", { className: "max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words", children: [displayText, imageSources.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: imageSources.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] })] }) }, msg.id));
4222
- }), resolvedThreadFooterSlot ? (_jsx(MessageScrollerItem, { children: _jsx("div", { className: "agent-thread-footer-slot", children: resolvedThreadFooterSlot }) })) : null] })) }), !authError &&
4223
- !isRestoring &&
4224
- !showEmptyState &&
4225
- showScrollToBottom ? (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })) : null] }) }, chatScrollResetKey), showComposerSlot ? composerSlot : null, isActiveComposer && (_jsx(McpConnectionSuggestion, { text: composerText })), showCenteredEmptyThreadFooterSlot ? (_jsx("div", { className: "agent-thread-footer-slot agent-thread-footer-slot--centered-empty", children: resolvedThreadFooterSlot })) : null, guidedQuestions && guidedQuestions.length > 0 && (_jsx("div", { className: "shrink-0 px-3 pb-2", children: _jsx(GuidedQuestionFlow, { questions: guidedQuestions, onSubmit: handleGuidedQuestionsSubmit, onSkip: handleGuidedQuestionsSkip, ...(guidedQuestionsTitle
4226
- ? { title: guidedQuestionsTitle }
4227
- : {}), ...(guidedQuestionsDescription
4228
- ? { description: guidedQuestionsDescription }
4229
- : {}), ...(guidedQuestionsSkipLabel
4230
- ? { skipLabel: guidedQuestionsSkipLabel }
4231
- : {}), ...(guidedQuestionsSubmitLabel
4232
- ? { submitLabel: guidedQuestionsSubmitLabel }
4233
- : {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) })), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: () => setComposerError(null), className: "shrink-0 opacity-70 hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) })] })), _jsxs("div", { className: "agent-composer-stack", "data-agent-composer-adjacent-ui": hasComposerAccessoryAboveStack ? "true" : undefined, children: [_jsx(SelectionAttachedPill, {}), showPlanModeCallout && (_jsx(PlanModeCallout, { canImplementPlan: canImplementPlan, onImplementPlan: handleImplementPlan, onSwitchToAct: handleSwitchToAct })), showInlineMissingKeySetup ? (_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleBuilderConnected })) : null, _jsxs(Popover, { open: showMissingKeySetup &&
4234
- !showInlineMissingKeySetup &&
4235
- missingKeySetupOpen, onOpenChange: setMissingKeySetupOpen, children: [_jsx(AgentComposerFrame, { layoutVariant: composerLayoutVariant, className: cn(composerAreaClassName, isComposerDisabled &&
4236
- !showMissingKeySetup &&
4237
- "opacity-70"), rootClassName: cn(showMissingKeySetup &&
4238
- "agent-composer-root--missing-key"), children: showMissingKeySetup &&
4239
- !showInlineMissingKeySetup ? (_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "agent-composer-missing-key-trigger", "aria-label": "Connect AI to start chatting", children: _jsxs("span", { className: "agent-composer-missing-key-content", children: [_jsxs("span", { className: "agent-composer-missing-key-copy", children: [_jsx("span", { className: "agent-composer-missing-key-title", children: missingApiKeySetupLayout ===
4240
- "sidebar"
4241
- ? "Connect AI to chat"
4242
- : "Connect AI to start chatting" }), missingApiKeySetupLayout !==
4243
- "sidebar" ? (_jsx("span", { className: "agent-composer-missing-key-description", children: "Builder.io includes free credits, or use your own API key." })) : null] }), _jsx("span", { className: "agent-composer-missing-key-cta", children: "Connect AI" })] }) }) })) : (_jsxs(_Fragment, { children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, onTextChange: isActiveComposer
4244
- ? handleComposerTextChange
4245
- : undefined, disabled: isComposerDisabled ||
4246
- showInlineMissingKeySetup, placeholder: showInlineMissingKeySetup
4247
- ? "Connect AI above to start chatting..."
4248
- : engineSetupRequired
4249
- ? "Connect AI to start chatting..."
4250
- : composerDisabled
4251
- ? (composerDisabledPlaceholder ??
4252
- "Open Desktop to use this chat.")
4253
- : isRunning
4254
- ? queuedMessages.length > 0
4255
- ? `${queuedMessages.length} queued — send a follow-up...`
4256
- : "Send a follow-up..."
4257
- : composerPlaceholder, onSubmit: isRunning ||
4258
- composerContextItems.length > 0
4259
- ? (text, references, attachments, options) => void addToQueue(text, undefined, references.length > 0
4260
- ? references
4261
- : undefined, attachments, undefined, resolveAssistantChatSubmitIntent({
4262
- isRunning,
4263
- requestedIntent: options?.intent,
4264
- }), undefined, true)
4265
- : undefined, willQueue: engineSetupRequired || isRunning, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange: onModelChange, onEffortChange: onEffortChange, imageModelMenu: imageModelMenu, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, toolbarSlot: composerToolbarSlot, contextItems: composerContextItems, onRemoveContextItem: removeComposerContextItem, plusMenuMode: plusMenuMode, layoutVariant: composerLayoutVariant, providerConnectStatusEnabled: providerStatusChecksEnabled, voiceEnabled: true, draftScope: threadId || tabId, interceptBuildRequestsForBuilder: true, onAttachmentError: setComposerError, extraActionButton: composerExtraActionButton, stopButton: showRunningInUI ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => stopActiveRun({
4266
- preserveQueuedMessages: true,
4267
- }), "aria-label": "Stop response", "data-agent-composer-slot": "stop-button", className: "shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(IconPlayerStopFilled, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Stop response" })] })) : undefined })] })) }), showMissingKeySetup &&
4268
- !showInlineMissingKeySetup ? (_jsx(PopoverContent, { side: missingApiKeySetupLayout === "sidebar"
4269
- ? "top"
4270
- : "bottom", align: "center", sideOffset: 8, collisionPadding: 12, "data-agent-native-composer-popover": "true", className: "z-[260] box-border w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,26rem),26rem)] rounded-lg border-border p-3 shadow-lg", children: _jsx(BuilderSetupContent, { onConnected: handleBuilderConnected, layout: missingApiKeySetupLayout }) })) : null] })] })] }) }) }) }) }) }) }) }) }) }));
4215
+ setRunErrorInfo(null);
4216
+ } }) })), (isReconnecting ||
4217
+ reconnectFrozen ||
4218
+ adapterHandoffPending) &&
4219
+ visibleReconnectContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: visibleReconnectContent, allowActivitySpinner: !reconnectFrozen }) })), (isReconnecting ||
4220
+ reconnectFrozen ||
4221
+ adapterHandoffPending) &&
4222
+ visibleReconnectContent.length === 0 &&
4223
+ reconnectContent.length === 0 &&
4224
+ reconnectActivityContent.length > 0 && (_jsx(MessageScrollerItem, { children: _jsx(ReconnectStreamMessage, { content: reconnectActivityContent, allowActivitySpinner: !reconnectFrozen }) })), showGlobalRunningStatus && (_jsx(MessageScrollerItem, { children: _jsx(RunningActivityStatus, { label: runningStatusLabel }) })), visibleQueuedMessages.length > 0 && (_jsx(MessageScrollerItem, { children: _jsxs("div", { className: "flex items-center justify-end gap-1.5 pr-0.5 text-xs text-muted-foreground", children: [_jsx(IconClock, { className: "h-3 w-3" }), _jsxs("span", { children: [visibleQueuedMessages.length, " ", "queued"] })] }) })), visibleQueuedMessages.map((msg) => {
4225
+ const displayText = displayableUserMessageText(msg.text);
4226
+ const imageSources = queuedMessageImageSources(msg);
4227
+ return (_jsx(MessageScrollerItem, { messageId: msg.id, children: _jsxs("div", { className: "group flex items-start justify-end gap-1.5", children: [isRunning && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => sendQueuedMessageNow(msg.id), "aria-label": "Send now", className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconArrowUp, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Send now (stops the current response)" })] })), _jsx("button", { type: "button", onClick: () => applyLocalQueuedMessages((prev) => prev.filter((m) => m.id !== msg.id)), "aria-label": "Remove from queue", className: "mt-1.5 flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-border bg-background text-muted-foreground opacity-0 shadow-sm transition-opacity hover:bg-accent hover:text-foreground focus-visible:opacity-100 group-hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) }), _jsxs("div", { className: "max-w-[85%] rounded-lg bg-accent/50 px-3 py-2 text-sm leading-relaxed text-foreground/60 whitespace-pre-wrap break-words", children: [displayText, imageSources.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1.5 mt-1.5", children: imageSources.map((img, j) => (_jsx("img", { src: img, alt: "", className: "h-12 w-12 rounded object-cover border border-border/50" }, j))) }))] })] }) }, msg.id));
4228
+ }), resolvedThreadFooterSlot ? (_jsx(MessageScrollerItem, { children: _jsx("div", { className: "agent-thread-footer-slot", children: resolvedThreadFooterSlot }) })) : null] })) }), !authError &&
4229
+ !isRestoring &&
4230
+ !showEmptyState &&
4231
+ showScrollToBottom ? (_jsx("div", { className: "shrink-0 flex justify-center -mb-1", children: _jsx("button", { type: "button", onClick: scrollToBottom, className: "flex h-7 w-7 items-center justify-center rounded-full border border-border bg-background shadow-sm hover:bg-accent", "aria-label": "Scroll to bottom", children: _jsx(IconChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground" }) }) })) : null] }) }, chatScrollResetKey), showComposerSlot ? composerSlot : null, isActiveComposer && (_jsx(McpConnectionSuggestion, { text: composerText })), showCenteredEmptyThreadFooterSlot ? (_jsx("div", { className: "agent-thread-footer-slot agent-thread-footer-slot--centered-empty", children: resolvedThreadFooterSlot })) : null, guidedQuestions && guidedQuestions.length > 0 && (_jsx("div", { className: "shrink-0 px-3 pb-2", children: _jsx(GuidedQuestionFlow, { questions: guidedQuestions, onSubmit: handleGuidedQuestionsSubmit, onSkip: handleGuidedQuestionsSkip, ...(guidedQuestionsTitle
4232
+ ? { title: guidedQuestionsTitle }
4233
+ : {}), ...(guidedQuestionsDescription
4234
+ ? { description: guidedQuestionsDescription }
4235
+ : {}), ...(guidedQuestionsSkipLabel
4236
+ ? { skipLabel: guidedQuestionsSkipLabel }
4237
+ : {}), ...(guidedQuestionsSubmitLabel
4238
+ ? { submitLabel: guidedQuestionsSubmitLabel }
4239
+ : {}), className: "h-auto items-stretch justify-stretch bg-transparent" }) })), composerError && (_jsxs("div", { role: "alert", className: "shrink-0 mx-3 mb-1.5 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive", children: [_jsx(IconAlertTriangle, { className: "h-3.5 w-3.5 mt-0.5 shrink-0" }), _jsx("span", { className: "flex-1 leading-snug", children: composerError }), _jsx("button", { type: "button", "aria-label": "Dismiss error", onClick: () => setComposerError(null), className: "shrink-0 opacity-70 hover:opacity-100", children: _jsx(IconX, { className: "h-3 w-3" }) })] })), _jsxs("div", { className: "agent-composer-stack", "data-agent-composer-adjacent-ui": hasComposerAccessoryAboveStack
4240
+ ? "true"
4241
+ : undefined, children: [_jsx(SelectionAttachedPill, {}), showPlanModeCallout && (_jsx(PlanModeCallout, { canImplementPlan: canImplementPlan, onImplementPlan: handleImplementPlan, onSwitchToAct: handleSwitchToAct })), showInlineMissingKeySetup ? (_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleBuilderConnected })) : null, _jsxs(Popover, { open: showMissingKeySetup &&
4242
+ !showInlineMissingKeySetup &&
4243
+ missingKeySetupOpen, onOpenChange: setMissingKeySetupOpen, children: [_jsx(AgentComposerFrame, { layoutVariant: composerLayoutVariant, className: cn(composerAreaClassName, isComposerDisabled &&
4244
+ !showMissingKeySetup &&
4245
+ "opacity-70"), rootClassName: cn(showMissingKeySetup &&
4246
+ "agent-composer-root--missing-key"), children: showMissingKeySetup &&
4247
+ !showInlineMissingKeySetup ? (_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { type: "button", className: "agent-composer-missing-key-trigger", "aria-label": "Connect AI to start chatting", children: _jsxs("span", { className: "agent-composer-missing-key-content", children: [_jsxs("span", { className: "agent-composer-missing-key-copy", children: [_jsx("span", { className: "agent-composer-missing-key-title", children: missingApiKeySetupLayout ===
4248
+ "sidebar"
4249
+ ? "Connect AI to chat"
4250
+ : "Connect AI to start chatting" }), missingApiKeySetupLayout !==
4251
+ "sidebar" ? (_jsx("span", { className: "agent-composer-missing-key-description", children: "Builder.io includes free credits, or use your own API key." })) : null] }), _jsx("span", { className: "agent-composer-missing-key-cta", children: "Connect AI" })] }) }) })) : (_jsxs(_Fragment, { children: [_jsx(ComposerAttachmentPreviewStrip, {}), _jsx(TiptapComposer, { focusRef: tiptapRef, onTextChange: isActiveComposer
4252
+ ? handleComposerTextChange
4253
+ : undefined, disabled: isComposerDisabled ||
4254
+ showInlineMissingKeySetup, placeholder: showInlineMissingKeySetup
4255
+ ? "Connect AI above to start chatting..."
4256
+ : engineSetupRequired
4257
+ ? "Connect AI to start chatting..."
4258
+ : composerDisabled
4259
+ ? (composerDisabledPlaceholder ??
4260
+ "Open Desktop to use this chat.")
4261
+ : isRunning
4262
+ ? queuedMessages.length > 0
4263
+ ? `${queuedMessages.length} queued — send a follow-up...`
4264
+ : "Send a follow-up..."
4265
+ : resolveAssistantChatComposerPlaceholder(composerPlaceholder), onSubmit: isRunning ||
4266
+ composerContextItems.length > 0
4267
+ ? (text, references, attachments, options) => void addToQueue(text, undefined, references.length > 0
4268
+ ? references
4269
+ : undefined, attachments, undefined, resolveAssistantChatSubmitIntent({
4270
+ isRunning,
4271
+ requestedIntent: options?.intent,
4272
+ }), undefined, true)
4273
+ : undefined, willQueue: engineSetupRequired || isRunning, onSlashCommand: onSlashCommand, execMode: execMode, onExecModeChange: onExecModeChange, planModeDisabled: planModeDisabled, planModeDisabledReason: planModeDisabledReason, selectedModel: selectedModel ?? defaultModel, selectedEffort: selectedEffort, availableModels: availableModels, modelListLoading: modelListLoading, onModelChange: onModelChange, onEffortChange: onEffortChange, imageModelMenu: imageModelMenu, onConnectProvider: onConnectProvider, onConnectLocalRuntime: onConnectLocalRuntime, toolbarSlot: composerToolbarSlot, contextItems: composerContextItems, onRemoveContextItem: removeComposerContextItem, plusMenuMode: plusMenuMode, layoutVariant: composerLayoutVariant, providerConnectStatusEnabled: providerStatusChecksEnabled, voiceEnabled: true, draftScope: threadId || tabId, interceptBuildRequestsForBuilder: true, onAttachmentError: setComposerError, extraActionButton: composerExtraActionButton, stopButton: showRunningInUI ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("button", { type: "button", onClick: () => stopActiveRun({
4274
+ preserveQueuedMessages: true,
4275
+ }), "aria-label": "Stop response", "data-agent-composer-slot": "stop-button", className: "shrink-0 flex h-7 w-7 cursor-pointer items-center justify-center rounded-full bg-primary text-primary-foreground shadow-sm transition-opacity hover:opacity-90 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", children: _jsx(IconPlayerStopFilled, { className: "h-3 w-3" }) }) }), _jsx(TooltipContent, { children: "Stop response" })] })) : undefined })] })) }), showMissingKeySetup &&
4276
+ !showInlineMissingKeySetup ? (_jsx(PopoverContent, { side: missingApiKeySetupLayout === "sidebar"
4277
+ ? "top"
4278
+ : "bottom", align: "center", sideOffset: 8, collisionPadding: 12, "data-agent-native-composer-popover": "true", className: "z-[260] box-border w-[min(calc(100vw-2rem),var(--radix-popover-content-available-width,26rem),26rem)] rounded-lg border-border p-3 shadow-lg", children: _jsx(BuilderSetupContent, { onConnected: handleBuilderConnected, layout: missingApiKeySetupLayout }) })) : null] })] })] }) }) }) }) }) }) }) }) }) }) }));
4271
4279
  });
4272
4280
  export const AssistantChat = forwardRef(function AssistantChat({ apiUrl = agentNativePath("/_agent-native/agent-chat"), tabId, browserTabId, threadId, contextScope, isActiveComposer, ...props }, ref) {
4273
4281
  const modelRef = useRef(props.selectedModel);
@@ -10,7 +10,7 @@ import { McpIntegrationDialog,
10
10
  // host for the existing MCP management flow.
11
11
  } from "../resources/McpIntegrationDialog.js";
12
12
  import { McpServerDetail } from "../resources/McpServerDetail.js";
13
- import { useCreateMcpServer, useDeleteMcpServer, useMcpServers, } from "../resources/use-mcp-servers.js";
13
+ import { useCreateMcpServer, useDeleteMcpServer, useMcpServers, formatMcpServersLoadError, } from "../resources/use-mcp-servers.js";
14
14
  import { AGENT_SETTINGS_SECTIONS, buildSectionSearchEntries, } from "../settings/agent-settings-search.js";
15
15
  import { AgentSettingsContent } from "../settings/SettingsPanel.js";
16
16
  import { cn } from "../utils.js";
@@ -160,7 +160,7 @@ export function ConnectionsTab({ canManageOrg, } = {}) {
160
160
  return (_jsx(AgentTabFrame, { title: "Agent integrations", description: "Tools and services this agent can reach, grouped by where they are configured.", actions: _jsx("button", { type: "button", onClick: () => {
161
161
  setError(null);
162
162
  setDialogOpen(true);
163
- }, className: "cursor-pointer rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90", children: t("mcpIntegrations.connect") }), children: _jsxs("section", { className: "space-y-4", children: [error && (_jsx("p", { className: "rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: error })), serversQuery.isLoading ? (_jsx(TabLoading, {})) : serversQuery.isError ? (_jsx("p", { className: "rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: "Could not load agent integrations." })) : (_jsx("div", { className: "space-y-6", children: [
163
+ }, className: "cursor-pointer rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90", children: t("mcpIntegrations.connect") }), children: _jsxs("section", { className: "space-y-4", children: [error && (_jsx("p", { className: "rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: error })), serversQuery.isLoading ? (_jsx(TabLoading, {})) : serversQuery.isError ? (_jsxs("div", { role: "alert", className: "rounded-md border border-destructive/20 bg-destructive/5 px-3 py-2 text-xs text-destructive", children: [_jsx("p", { children: formatMcpServersLoadError(serversQuery.error) }), _jsx("button", { type: "button", onClick: () => void serversQuery.refetch(), disabled: serversQuery.isFetching, className: "mt-2 font-medium underline underline-offset-2 hover:text-foreground disabled:cursor-wait disabled:opacity-60", children: serversQuery.isFetching ? "Retrying…" : "Retry" })] })) : (_jsx("div", { className: "space-y-6", children: [
164
164
  { label: "Personal", servers: data?.user ?? [] },
165
165
  { label: "Organization", servers: data?.org ?? [] },
166
166
  ].map((section) => (_jsxs("section", { className: "space-y-2", children: [_jsx("h2", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground/70", children: section.label }), section.servers.length > 0 ? (_jsx("div", { className: "divide-y divide-border/60 border-y border-border/60", children: section.servers.map(renderServer) })) : (_jsx(AgentEmptyState, { icon: IconPlugConnected, title: `No ${section.label.toLowerCase()} agent integrations yet`, description: section.label === "Personal"