@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
@@ -1429,6 +1429,16 @@ function isMissingCredentialMessage(message) {
1429
1429
  msg.includes("no llm provider") ||
1430
1430
  msg.includes("llm provider is connected"));
1431
1431
  }
1432
+ function isMissingProviderErrorMessage(message, errorCode) {
1433
+ const text = message.toLowerCase();
1434
+ const code = (errorCode ?? "").toLowerCase();
1435
+ return (text.includes("no llm provider") ||
1436
+ text.includes("missing credentials") ||
1437
+ text.includes("missing api key") ||
1438
+ text.includes("missing_api_key") ||
1439
+ ((code === "missing_credentials" || code === "missing_api_key") &&
1440
+ text.includes("llm provider")));
1441
+ }
1432
1442
  function missingCredentialFailure(message) {
1433
1443
  try {
1434
1444
  const parsed = JSON.parse(message);
@@ -1439,9 +1449,10 @@ function missingCredentialFailure(message) {
1439
1449
  : message;
1440
1450
  const errorCode = typeof parsed.errorCode === "string"
1441
1451
  ? parsed.errorCode
1442
- : "missing_credentials";
1452
+ : isMissingCredentialMessage(raw)
1453
+ ? "missing_credentials"
1454
+ : "authentication_error";
1443
1455
  return {
1444
- text: formatChatErrorText(raw, typeof parsed.upgradeUrl === "string" ? parsed.upgradeUrl : undefined, errorCode),
1445
1456
  runError: {
1446
1457
  message: normalizeChatError(raw).message,
1447
1458
  errorCode,
@@ -1450,10 +1461,11 @@ function missingCredentialFailure(message) {
1450
1461
  }
1451
1462
  catch {
1452
1463
  return {
1453
- text: formatChatErrorText(message, undefined, "missing_credentials"),
1454
1464
  runError: {
1455
1465
  message: normalizeChatError(message).message,
1456
- errorCode: "missing_credentials",
1466
+ errorCode: isMissingCredentialMessage(message)
1467
+ ? "missing_credentials"
1468
+ : "authentication_error",
1457
1469
  },
1458
1470
  };
1459
1471
  }
@@ -1707,6 +1719,16 @@ export function createAgentChatAdapter(options) {
1707
1719
  activeRun.threadId === threadId &&
1708
1720
  activeRun.runId === runId));
1709
1721
  };
1722
+ const clearOwnedActiveRun = () => {
1723
+ if (!ownsActiveRunState())
1724
+ return;
1725
+ if (threadId && runId) {
1726
+ clearActiveRunIfMatches(threadId, runId);
1727
+ }
1728
+ else {
1729
+ clearActiveRun();
1730
+ }
1731
+ };
1710
1732
  // The adapter's own stream outranks AssistantChat's reconnect fallback:
1711
1733
  // when it attaches to a run, any reconnect reader folding the same run
1712
1734
  // must stop writing UI state or both folds render at once.
@@ -1716,6 +1738,18 @@ export function createAgentChatAdapter(options) {
1716
1738
  preemptRunStream(threadId, runId, streamOwnershipToken);
1717
1739
  }
1718
1740
  };
1741
+ let terminalChatUiStopped = false;
1742
+ const publishTerminalChatUiStopped = () => {
1743
+ if (terminalChatUiStopped)
1744
+ return;
1745
+ terminalChatUiStopped = true;
1746
+ if (typeof window === "undefined")
1747
+ return;
1748
+ dispatchTerminalChatUiCleanup(tabId);
1749
+ window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
1750
+ detail: { isRunning: false, tabId },
1751
+ }));
1752
+ };
1719
1753
  const settleTerminalChatRun = () => {
1720
1754
  if (threadId && runId) {
1721
1755
  releaseRunStream(threadId, runId, streamOwnershipToken);
@@ -1728,12 +1762,7 @@ export function createAgentChatAdapter(options) {
1728
1762
  else {
1729
1763
  clearActiveRun();
1730
1764
  }
1731
- if (typeof window === "undefined")
1732
- return;
1733
- dispatchTerminalChatUiCleanup(tabId);
1734
- window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
1735
- detail: { isRunning: false, tabId },
1736
- }));
1765
+ publishTerminalChatUiStopped();
1737
1766
  };
1738
1767
  const seenRunSeqs = new Map();
1739
1768
  const preparingActionStatesByRun = new Map();
@@ -2062,7 +2091,7 @@ export function createAgentChatAdapter(options) {
2062
2091
  const reconnectRes = await fetch(`${apiUrl}/runs/${encodeURIComponent(runId)}/events?after=${lastSeq + 1}`, { signal: abortSignal });
2063
2092
  if (!reconnectRes.ok || !reconnectRes.body) {
2064
2093
  if (reconnectRes.status === 404) {
2065
- clearActiveRun();
2094
+ clearOwnedActiveRun();
2066
2095
  return false;
2067
2096
  }
2068
2097
  lastReconnectError = new Error(`Reconnect failed: ${reconnectRes.status}`);
@@ -2091,14 +2120,14 @@ export function createAgentChatAdapter(options) {
2091
2120
  yield nextResult;
2092
2121
  }
2093
2122
  if (ownsActiveRunState()) {
2094
- clearActiveRun();
2123
+ clearOwnedActiveRun();
2095
2124
  }
2096
2125
  return true;
2097
2126
  }
2098
2127
  catch (reconnectErr) {
2099
2128
  if (reconnectErr instanceof Error &&
2100
2129
  reconnectErr.name === "AbortError") {
2101
- clearActiveRun();
2130
+ clearOwnedActiveRun();
2102
2131
  return true;
2103
2132
  }
2104
2133
  if (reconnectErr instanceof AgentAutoContinueSignal) {
@@ -2162,7 +2191,7 @@ export function createAgentChatAdapter(options) {
2162
2191
  catch (activeErr) {
2163
2192
  if (activeErr instanceof Error &&
2164
2193
  activeErr.name === "AbortError") {
2165
- clearActiveRun();
2194
+ clearOwnedActiveRun();
2166
2195
  return true;
2167
2196
  }
2168
2197
  lastActiveRunError = activeErr;
@@ -2235,7 +2264,7 @@ export function createAgentChatAdapter(options) {
2235
2264
  catch (activeErr) {
2236
2265
  if (activeErr instanceof Error &&
2237
2266
  activeErr.name === "AbortError") {
2238
- clearActiveRun();
2267
+ clearOwnedActiveRun();
2239
2268
  return true;
2240
2269
  }
2241
2270
  lastActiveRunError = activeErr;
@@ -2273,17 +2302,19 @@ export function createAgentChatAdapter(options) {
2273
2302
  settleInterruptedToolCalls(content, undefined, {
2274
2303
  includeActivity: true,
2275
2304
  });
2276
- content.push({
2277
- type: "text",
2278
- text: formatChatErrorText(args.message, undefined, args.errorCode),
2279
- });
2305
+ if (!isMissingProviderErrorMessage(args.message, args.errorCode)) {
2306
+ content.push({
2307
+ type: "text",
2308
+ text: formatChatErrorText(args.message, undefined, args.errorCode),
2309
+ });
2310
+ }
2280
2311
  settleTerminalChatRun();
2281
2312
  yield {
2282
2313
  content: [...content],
2283
2314
  status: { type: "incomplete", reason: "error" },
2284
2315
  metadata: { custom: { ...(runId ? { runId } : {}), runError } },
2285
2316
  };
2286
- clearActiveRun();
2317
+ clearOwnedActiveRun();
2287
2318
  };
2288
2319
  // Final outcome for a background turn the follow loop can no longer
2289
2320
  // follow: either the run went terminal server-side (surface its
@@ -2313,7 +2344,7 @@ export function createAgentChatAdapter(options) {
2313
2344
  },
2314
2345
  },
2315
2346
  };
2316
- clearActiveRun();
2347
+ clearOwnedActiveRun();
2317
2348
  return;
2318
2349
  }
2319
2350
  // terminal_reason is either a bare reason ("dispatch_payload_missing")
@@ -2385,7 +2416,7 @@ export function createAgentChatAdapter(options) {
2385
2416
  },
2386
2417
  },
2387
2418
  };
2388
- clearActiveRun();
2419
+ clearOwnedActiveRun();
2389
2420
  return;
2390
2421
  }
2391
2422
  if (lastRecoverableRunError) {
@@ -2466,17 +2497,17 @@ export function createAgentChatAdapter(options) {
2466
2497
  }
2467
2498
  settleTerminalChatRun();
2468
2499
  yield missingFinalResponseResult;
2469
- clearActiveRun();
2500
+ clearOwnedActiveRun();
2470
2501
  return "completed";
2471
2502
  }
2472
2503
  // readSSEStream returned normally: a terminal done/error was
2473
2504
  // consumed and rendered — the turn is over.
2474
- clearActiveRun();
2505
+ clearOwnedActiveRun();
2475
2506
  return "completed";
2476
2507
  }
2477
2508
  catch (attachErr) {
2478
2509
  if (attachErr instanceof Error && attachErr.name === "AbortError") {
2479
- clearActiveRun();
2510
+ clearOwnedActiveRun();
2480
2511
  return "aborted";
2481
2512
  }
2482
2513
  if (attachErr instanceof AgentAutoContinueSignal) {
@@ -2624,7 +2655,7 @@ export function createAgentChatAdapter(options) {
2624
2655
  const replayedTerminalRunIds = new Set();
2625
2656
  while (true) {
2626
2657
  if (abortSignal.aborted) {
2627
- clearActiveRun();
2658
+ clearOwnedActiveRun();
2628
2659
  return "completed";
2629
2660
  }
2630
2661
  if (Date.now() - followStartedAt >=
@@ -2663,7 +2694,7 @@ export function createAgentChatAdapter(options) {
2663
2694
  }
2664
2695
  catch (pollErr) {
2665
2696
  if (pollErr instanceof Error && pollErr.name === "AbortError") {
2666
- clearActiveRun();
2697
+ clearOwnedActiveRun();
2667
2698
  return "completed";
2668
2699
  }
2669
2700
  activeUnreadable = true;
@@ -2672,7 +2703,7 @@ export function createAgentChatAdapter(options) {
2672
2703
  // Unreadable: learn nothing, decide nothing, wait and re-ask.
2673
2704
  await delay(BACKGROUND_FOLLOW_POLL_INTERVAL_MS, abortSignal);
2674
2705
  if (abortSignal.aborted) {
2675
- clearActiveRun();
2706
+ clearOwnedActiveRun();
2676
2707
  return "completed";
2677
2708
  }
2678
2709
  continue;
@@ -2747,7 +2778,7 @@ export function createAgentChatAdapter(options) {
2747
2778
  if (isBackgroundTerminalErrorOutcome(active)) {
2748
2779
  const graceOutcome = await awaitBackgroundErrorRecoverySuccessor(activeRunId);
2749
2780
  if (graceOutcome === "aborted") {
2750
- clearActiveRun();
2781
+ clearOwnedActiveRun();
2751
2782
  return "completed";
2752
2783
  }
2753
2784
  if (graceOutcome === "successor") {
@@ -2866,7 +2897,7 @@ export function createAgentChatAdapter(options) {
2866
2897
  catch (refetchErr) {
2867
2898
  if (refetchErr instanceof Error &&
2868
2899
  refetchErr.name === "AbortError") {
2869
- clearActiveRun();
2900
+ clearOwnedActiveRun();
2870
2901
  return "completed";
2871
2902
  }
2872
2903
  secondOpinionUnreadable = true;
@@ -2966,7 +2997,7 @@ export function createAgentChatAdapter(options) {
2966
2997
  const nextPollDelayMs = Math.min(backedOffPollDelayMs, idleRemainingMs);
2967
2998
  await delay(nextPollDelayMs, abortSignal);
2968
2999
  if (abortSignal.aborted) {
2969
- clearActiveRun();
3000
+ clearOwnedActiveRun();
2970
3001
  return "completed";
2971
3002
  }
2972
3003
  }
@@ -3098,7 +3129,7 @@ export function createAgentChatAdapter(options) {
3098
3129
  includeReferences = Boolean(runConfig?.custom?.references);
3099
3130
  internalContinuationRequest = true;
3100
3131
  startupRecoveryAttempts = 0;
3101
- clearActiveRun();
3132
+ clearOwnedActiveRun();
3102
3133
  if (!isTransient) {
3103
3134
  return {
3104
3135
  ok: true,
@@ -3334,7 +3365,6 @@ export function createAgentChatAdapter(options) {
3334
3365
  detail: { ...failure.runError, tabId },
3335
3366
  }));
3336
3367
  }
3337
- content.push({ type: "text", text: failure.text });
3338
3368
  settleTerminalChatRun();
3339
3369
  yield {
3340
3370
  content: [...content],
@@ -3417,17 +3447,17 @@ export function createAgentChatAdapter(options) {
3417
3447
  }
3418
3448
  settleTerminalChatRun();
3419
3449
  yield missingFinalResponseResult;
3420
- clearActiveRun();
3450
+ clearOwnedActiveRun();
3421
3451
  return;
3422
3452
  }
3423
3453
  // Run completed normally — clear active run state
3424
- clearActiveRun();
3454
+ clearOwnedActiveRun();
3425
3455
  return;
3426
3456
  }
3427
3457
  catch (err) {
3428
3458
  if (err instanceof Error && err.name === "AbortError") {
3429
3459
  // User-initiated abort (Stop button) — clear active run
3430
- clearActiveRun();
3460
+ clearOwnedActiveRun();
3431
3461
  return;
3432
3462
  }
3433
3463
  if (err instanceof AgentAutoContinueSignal) {
@@ -3487,7 +3517,7 @@ export function createAgentChatAdapter(options) {
3487
3517
  },
3488
3518
  },
3489
3519
  };
3490
- clearActiveRun();
3520
+ clearOwnedActiveRun();
3491
3521
  return;
3492
3522
  }
3493
3523
  const preservedError = err.errorInfo ?? lastRecoverableRunError ?? null;
@@ -3541,7 +3571,7 @@ export function createAgentChatAdapter(options) {
3541
3571
  custom: { ...(runId ? { runId } : {}), runError },
3542
3572
  },
3543
3573
  };
3544
- clearActiveRun();
3574
+ clearOwnedActiveRun();
3545
3575
  return;
3546
3576
  }
3547
3577
  if (continuation.resetVisibleContent) {
@@ -3612,7 +3642,7 @@ export function createAgentChatAdapter(options) {
3612
3642
  custom: { ...(runId ? { runId } : {}), runError },
3613
3643
  },
3614
3644
  };
3615
- clearActiveRun();
3645
+ clearOwnedActiveRun();
3616
3646
  return;
3617
3647
  }
3618
3648
  const errMsg = err instanceof Error ? err.message : "Something went wrong.";
@@ -3636,7 +3666,7 @@ export function createAgentChatAdapter(options) {
3636
3666
  reason: "error",
3637
3667
  },
3638
3668
  };
3639
- clearActiveRun();
3669
+ clearOwnedActiveRun();
3640
3670
  return;
3641
3671
  }
3642
3672
  if (isMissingCredentialMessage(errMsg)) {
@@ -3647,7 +3677,6 @@ export function createAgentChatAdapter(options) {
3647
3677
  detail: { ...failure.runError, tabId },
3648
3678
  }));
3649
3679
  }
3650
- content.push({ type: "text", text: failure.text });
3651
3680
  settleTerminalChatRun();
3652
3681
  yield {
3653
3682
  content: [...content],
@@ -3657,7 +3686,7 @@ export function createAgentChatAdapter(options) {
3657
3686
  },
3658
3687
  metadata: { custom: { runError: failure.runError } },
3659
3688
  };
3660
- clearActiveRun();
3689
+ clearOwnedActiveRun();
3661
3690
  return;
3662
3691
  }
3663
3692
  // Connection lost — try to reconnect to the run
@@ -3716,7 +3745,7 @@ export function createAgentChatAdapter(options) {
3716
3745
  },
3717
3746
  metadata: { custom: { ...(runId ? { runId } : {}), runError } },
3718
3747
  };
3719
- clearActiveRun();
3748
+ clearOwnedActiveRun();
3720
3749
  return;
3721
3750
  }
3722
3751
  // Reconnect failed or not possible — keep going from the partial
@@ -3745,7 +3774,7 @@ export function createAgentChatAdapter(options) {
3745
3774
  },
3746
3775
  },
3747
3776
  };
3748
- clearActiveRun();
3777
+ clearOwnedActiveRun();
3749
3778
  return;
3750
3779
  }
3751
3780
  const message = exhaustedRecoveryMessage("stream_ended");
@@ -3780,7 +3809,7 @@ export function createAgentChatAdapter(options) {
3780
3809
  custom: { ...(runId ? { runId } : {}), runError },
3781
3810
  },
3782
3811
  };
3783
- clearActiveRun();
3812
+ clearOwnedActiveRun();
3784
3813
  return;
3785
3814
  }
3786
3815
  if (continuation.resetVisibleContent) {
@@ -3843,11 +3872,8 @@ export function createAgentChatAdapter(options) {
3843
3872
  }
3844
3873
  }
3845
3874
  finally {
3846
- if (typeof window !== "undefined" && ownsActiveRunState()) {
3847
- dispatchTerminalChatUiCleanup(tabId);
3848
- window.dispatchEvent(new CustomEvent("agentNative.chatRunning", {
3849
- detail: { isRunning: false, tabId },
3850
- }));
3875
+ if (ownsActiveRunState()) {
3876
+ publishTerminalChatUiStopped();
3851
3877
  }
3852
3878
  }
3853
3879
  },
@@ -143,14 +143,14 @@ function DocumentTitleGuard({ fallbackTitle }) {
143
143
  }, [fallbackTitle]);
144
144
  return null;
145
145
  }
146
- function ProvidersInner({ queryClient, defaultTheme = "system", themeAttribute = "class", tooltipDelayDuration, toaster = DEFAULT_TOASTER, disableThemeTransitions = true, i18n, documentTitleFallback, children, }) {
146
+ function ProvidersInner({ queryClient, defaultTheme = "system", themeAttribute = "class", tooltipDelayDuration, toaster = DEFAULT_TOASTER, disableThemeTransitions = true, i18n, documentTitleFallback, showProductionEnvironmentBadge, children, }) {
147
147
  const localizedChildren = i18n === false ? (children) : (_jsx(AgentNativeI18nProvider, { ...(i18n ?? {}), children: children }));
148
- return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(ThemeProvider, { attribute: themeAttribute, defaultTheme: defaultTheme, enableSystem: true, disableTransitionOnChange: disableThemeTransitions, children: [_jsx(EmbeddedThemeSync, {}), _jsxs(TooltipProvider, { delayDuration: tooltipDelayDuration, children: [localizedChildren, _jsx(DocumentTitleGuard, { fallbackTitle: documentTitleFallback }), _jsx(RuntimeConfigNotice, {}), _jsx(RoutedAppEnhancements, {}), toaster] })] }) }));
148
+ return (_jsx(QueryClientProvider, { client: queryClient, children: _jsxs(ThemeProvider, { attribute: themeAttribute, defaultTheme: defaultTheme, enableSystem: true, disableTransitionOnChange: disableThemeTransitions, children: [_jsx(EmbeddedThemeSync, {}), _jsxs(TooltipProvider, { delayDuration: tooltipDelayDuration, children: [localizedChildren, _jsx(DocumentTitleGuard, { fallbackTitle: documentTitleFallback }), _jsx(RuntimeConfigNotice, {}), _jsx(RoutedAppEnhancements, {}), _jsx(EnvironmentBadge, { showProduction: showProductionEnvironmentBadge }), toaster] })] }) }));
149
149
  }
150
150
  export function AppProviders({ queryClient, isPublicPath = false, clientOnlyFallback, sessionBypass = false, defaultTheme, themeAttribute, tooltipDelayDuration, toaster, disableThemeTransitions, i18n, documentTitleFallback, children, }) {
151
151
  const fallback = clientOnlyFallback ?? _jsx(DefaultSpinner, {});
152
152
  if (isPublicPath) {
153
- return (_jsx(ProvidersInner, { queryClient: queryClient, defaultTheme: defaultTheme, themeAttribute: themeAttribute, tooltipDelayDuration: tooltipDelayDuration, toaster: toaster, disableThemeTransitions: disableThemeTransitions, i18n: i18n, documentTitleFallback: documentTitleFallback, children: children }));
153
+ return (_jsx(ProvidersInner, { queryClient: queryClient, defaultTheme: defaultTheme, themeAttribute: themeAttribute, tooltipDelayDuration: tooltipDelayDuration, toaster: toaster, disableThemeTransitions: disableThemeTransitions, i18n: i18n, documentTitleFallback: documentTitleFallback, showProductionEnvironmentBadge: false, children: children }));
154
154
  }
155
- return (_jsx(ClientOnly, { fallback: fallback, children: _jsx(ProvidersInner, { queryClient: queryClient, defaultTheme: defaultTheme, themeAttribute: themeAttribute, tooltipDelayDuration: tooltipDelayDuration, toaster: toaster, disableThemeTransitions: disableThemeTransitions, i18n: i18n, documentTitleFallback: documentTitleFallback, children: _jsx(RequireSession, { bypass: sessionBypass, fallback: fallback, children: sessionBypass ? (children) : (_jsxs(FirstRunOnboardingStartupGate, { children: [children, _jsx(EnvironmentBadge, {})] })) }) }) }));
155
+ return (_jsx(ClientOnly, { fallback: fallback, children: _jsx(ProvidersInner, { queryClient: queryClient, defaultTheme: defaultTheme, themeAttribute: themeAttribute, tooltipDelayDuration: tooltipDelayDuration, toaster: toaster, disableThemeTransitions: disableThemeTransitions, i18n: i18n, documentTitleFallback: documentTitleFallback, showProductionEnvironmentBadge: !sessionBypass, children: _jsx(RequireSession, { bypass: sessionBypass, fallback: fallback, children: sessionBypass ? (children) : (_jsx(FirstRunOnboardingStartupGate, { children: children })) }) }) }));
156
156
  }
@@ -71,6 +71,10 @@ export declare function MessageActionsMenu({ showRevert, onRevert, threadId, }?:
71
71
  export declare function UserMessage(): React.JSX.Element | null;
72
72
  export declare function messageTextFromContent(content: unknown): string;
73
73
  export declare function isMissingFinalResponseWarningText(text: string): boolean;
74
+ export declare function isMissingCredentialAssistantMessage(message: {
75
+ content?: unknown;
76
+ metadata?: unknown;
77
+ }): boolean;
74
78
  export declare function latestUserMessageText(messages: readonly unknown[]): string;
75
79
  export declare function userMessageTextBeforeAssistant(messages: readonly unknown[], assistantMessageId: string): string;
76
80
  export declare function assistantMessageHasUnresolvedTool(content: unknown): boolean;
@@ -539,6 +539,32 @@ function missingFinalResponseWarningText(content) {
539
539
  }
540
540
  return null;
541
541
  }
542
+ export function isMissingCredentialAssistantMessage(message) {
543
+ const metadata = message.metadata;
544
+ const runError = metadata?.custom?.runError ?? metadata?.runError;
545
+ const errorCode = typeof runError?.errorCode === "string"
546
+ ? runError.errorCode.toLowerCase()
547
+ : "";
548
+ const errorMessage = typeof runError?.message === "string" ? runError.message : "";
549
+ if (/no llm provider(?: key)? (?:is connected|was found)|missing credentials|missing api key|missing_api_key/i.test(errorMessage) ||
550
+ ((errorCode === "missing_credentials" || errorCode === "missing_api_key") &&
551
+ !errorMessage &&
552
+ !message.content)) {
553
+ return true;
554
+ }
555
+ const text = Array.isArray(message.content)
556
+ ? message.content
557
+ .filter((part) => Boolean(part) &&
558
+ typeof part === "object" &&
559
+ part.type === "text" &&
560
+ typeof part.text === "string")
561
+ .map((part) => part.text)
562
+ .join("\n")
563
+ : typeof message.content === "string"
564
+ ? message.content
565
+ : "";
566
+ return /^Error:\s*(?:No LLM provider(?: key)? (?:is connected|was found))/i.test(text.trim());
567
+ }
542
568
  export function latestUserMessageText(messages) {
543
569
  for (let index = messages.length - 1; index >= 0; index -= 1) {
544
570
  const message = messages[index];
@@ -847,6 +873,7 @@ export function AssistantMessage() {
847
873
  const activeTurnId = React.useContext(ChatRunningTurnIdContext);
848
874
  const lastRunDurationMs = React.useContext(ChatRunDurationContext);
849
875
  const msg = messageRuntime.getState();
876
+ const isMissingCredential = isMissingCredentialAssistantMessage(msg);
850
877
  const persistedDurationMs = getAssistantRunDurationMs(msg);
851
878
  const timestamp = formatMessageTimestamp(msg.createdAt, locale, t("agentChat.history.yesterday"));
852
879
  const isLast = msg.isLast;
@@ -1052,7 +1079,7 @@ export function AssistantMessage() {
1052
1079
  chatRunning,
1053
1080
  isLast,
1054
1081
  });
1055
- if (!hasRenderableContent)
1082
+ if (!hasRenderableContent || isMissingCredential)
1056
1083
  return null;
1057
1084
  return (_jsxs("div", { className: "group relative", style: { contentVisibility: isComplete ? "auto" : "visible" }, children: [_jsxs("div", { className: "w-full max-w-[95%] text-sm leading-relaxed text-foreground", children: [isComplete && (_jsx(McpConnectionSuggestion, { text: responseConnectionText, contextText: responseConnectionContext, variant: "response" })), _jsx(ToolCallStackMotion, { children: _jsx(MessagePrimitive.GroupedParts, { groupBy: groupAssistantWorkParts, children: ({ part, children }) => {
1058
1085
  switch (part.type) {
@@ -112,6 +112,14 @@ function isConnectionRecoveryRunError(info) {
112
112
  message.includes("connection kept failing") ||
113
113
  message.includes("automatic recovery attempts"));
114
114
  }
115
+ function isMissingLlmProviderRunError(info) {
116
+ const code = (info.errorCode ?? "").toLowerCase();
117
+ const text = [info.message, info.details].filter(Boolean).join("\n");
118
+ const hasCredentialSetupText = /no llm provider(?: key)? (?:is connected|was found)|missing credentials|missing api key|missing_api_key|(?:api[_ -]?key|auth[_ -]?token)\s*(?:(?:is|was)\s+)?(?:not\s+(?:set|configured|available|present|provided|found)|missing|unavailable|empty|unset|unconfigured)/i.test(text);
119
+ return (hasCredentialSetupText ||
120
+ ((code === "missing_credentials" || code === "missing_api_key") &&
121
+ !text.trim()));
122
+ }
115
123
  // ─── BuilderConnectCta ────────────────────────────────────────────────────────
116
124
  // Renders a single row with left-aligned copy and a right-aligned action.
117
125
  // Click opens the Builder OAuth popup via the shared
@@ -194,11 +202,15 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
194
202
  const [copyState, setCopyState] = useState("idle");
195
203
  const [forking, setForking] = useState(false);
196
204
  const [forkError, setForkError] = useState(null);
205
+ const [providerConnected, setProviderConnected] = useState(false);
206
+ const retryRequestedRef = useRef(false);
207
+ const [retryRequested, setRetryRequested] = useState(false);
197
208
  const builderReconnect = useBuilderConnectFlow({
198
209
  trackingSource: "assistant_chat_reconnect_error",
199
210
  });
200
211
  const canRecover = info.recoverable === true;
201
212
  const shouldShowBuilderReconnect = isBuilderReconnectRunError(info);
213
+ const shouldShowMissingProviderSetup = isMissingLlmProviderRunError(info);
202
214
  const isProviderAuthError = isProviderAuthenticationError([info.message, info.details].filter(Boolean).join("\n"), info.errorCode);
203
215
  // Blocked on something the reader goes and fixes elsewhere, then comes back
204
216
  // to. Without a retry the card is a dead end and its own copy ("then retry")
@@ -241,6 +253,17 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
241
253
  onRetry();
242
254
  onDismiss();
243
255
  }, [onDismiss, onProviderConnected, onRetry]);
256
+ const handleMissingProviderConnected = useCallback(() => {
257
+ setProviderConnected(true);
258
+ onProviderConnected?.();
259
+ }, [onProviderConnected]);
260
+ const handleMissingProviderRetry = useCallback(() => {
261
+ if (retryRequestedRef.current)
262
+ return;
263
+ retryRequestedRef.current = true;
264
+ setRetryRequested(true);
265
+ onRetry();
266
+ }, [onRetry]);
244
267
  const handleFork = useCallback(async () => {
245
268
  if (!onFork || forking)
246
269
  return;
@@ -264,6 +287,9 @@ export function RunErrorRecoveryCard({ info, onContinue, onRetry, onFork, onDism
264
287
  onDismiss();
265
288
  }
266
289
  }, [builderReconnectResolved, onDismiss]);
290
+ if (shouldShowMissingProviderSetup) {
291
+ return (_jsxs("div", { className: "w-full", children: [_jsx(BuilderSetupCard, { fullWidth: true, layout: "sidebar", onConnected: handleMissingProviderConnected }), providerConnected ? (_jsx("div", { className: "flex justify-center px-3 pt-1", children: _jsxs("button", { type: "button", onClick: handleMissingProviderRetry, disabled: retryRequested, className: "inline-flex h-8 items-center gap-1.5 rounded-md bg-foreground px-3 text-xs font-medium text-background hover:opacity-90 disabled:cursor-wait disabled:opacity-60", children: [_jsx(IconRefresh, { size: 13 }), t("agentChat.common.retry")] }) })) : null] }));
292
+ }
267
293
  return (_jsxs("div", { className: "rounded-lg border border-amber-500/25 bg-amber-500/[0.06] p-3 text-sm", children: [_jsxs("div", { className: "flex items-start gap-2", children: [_jsx("span", { className: "mt-0.5 flex h-6 w-6 shrink-0 items-center justify-center rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300", children: _jsx(IconAlertTriangle, { size: 14 }) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "font-medium text-foreground", children: runErrorHeadline(info, {
268
294
  recoverable: t("agentChat.error.stopped"),
269
295
  terminal: t("agentChat.error.failed"),
@@ -1,2 +1,3 @@
1
1
  import type { ChatFirstAppRailProps } from "./types.js";
2
+ export declare const CHAT_FIRST_APP_RAIL_SHOW_ALL_STORAGE_KEY = "agent-native:chat-first-app-rail-show-all:v1";
2
3
  export declare const ChatFirstAppsRail: import("react").MemoExoticComponent<({ apps, defaultAppIds, activeAppId, loading, error, collapsed, layout: controlledLayout, onLayoutChange, onLayoutError, onRetry, onOpenApp, onRemoveApp, onOpenAllApps, onCreateApp, createAppTrigger, renderIcon, copy, }: ChatFirstAppRailProps) => import("react").JSX.Element>;
@@ -1,10 +1,33 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuSeparator, ContextMenuTrigger, Skeleton, Tooltip, TooltipContent, TooltipTrigger, } from "@agent-native/toolkit/ui";
3
3
  import { IconApps, IconChevronDown, IconChevronUp, IconPin, IconPlus, IconTrash, } from "@tabler/icons-react";
4
- import { memo, useMemo, useState } from "react";
4
+ import { memo, useEffect, useMemo, useState } from "react";
5
5
  import { CHAT_FIRST_DEFAULT_APP_IDS, orderChatFirstAppIds, readChatFirstAppLayout, writeChatFirstAppLayout, } from "../chat-first.js";
6
6
  import { cn } from "../utils.js";
7
7
  import { defaultChatFirstCopy } from "./copy.js";
8
+ export const CHAT_FIRST_APP_RAIL_SHOW_ALL_STORAGE_KEY = "agent-native:chat-first-app-rail-show-all:v1";
9
+ function readChatFirstAppRailShowAll() {
10
+ if (typeof window === "undefined")
11
+ return false;
12
+ try {
13
+ return (window.localStorage.getItem(CHAT_FIRST_APP_RAIL_SHOW_ALL_STORAGE_KEY) ===
14
+ "true");
15
+ }
16
+ catch {
17
+ // coercion-ok: localStorage is optional; false keeps the rail usable in-memory.
18
+ return false;
19
+ }
20
+ }
21
+ function writeChatFirstAppRailShowAll(showAllApps) {
22
+ if (typeof window === "undefined")
23
+ return;
24
+ try {
25
+ window.localStorage.setItem(CHAT_FIRST_APP_RAIL_SHOW_ALL_STORAGE_KEY, String(showAllApps));
26
+ }
27
+ catch {
28
+ // coercion-ok: localStorage is optional; the in-memory toggle remains usable.
29
+ }
30
+ }
8
31
  function ChatFirstRailAppIcon({ app, activeAppId, renderIcon, }) {
9
32
  const isActive = activeAppId !== undefined && activeAppId === app.id;
10
33
  const isInactive = activeAppId !== undefined && !isActive;
@@ -45,7 +68,10 @@ export const ChatFirstAppsRail = memo(function ChatFirstAppsRail({ apps, default
45
68
  const [localLayout, setLocalLayout] = useState(() => readChatFirstAppLayout());
46
69
  const layout = controlledLayout ?? localLayout;
47
70
  const [draggedAppId, setDraggedAppId] = useState(null);
48
- const [showAllApps, setShowAllApps] = useState(false);
71
+ const [showAllApps, setShowAllApps] = useState(() => readChatFirstAppRailShowAll());
72
+ useEffect(() => {
73
+ writeChatFirstAppRailShowAll(showAllApps);
74
+ }, [showAllApps]);
49
75
  const orderedApps = useMemo(() => {
50
76
  const orderedIds = orderChatFirstAppIds(apps.map((app) => app.id), layout, defaultAppIds);
51
77
  const appsById = new Map(apps.map((app) => [app.id, app]));
@@ -605,6 +605,12 @@ function isMissingCredentialText(message, errorCode) {
605
605
  msg.includes("no llm provider") ||
606
606
  msg.includes("llm provider is connected"));
607
607
  }
608
+ function isMissingProviderErrorText(message, errorCode) {
609
+ const code = String(errorCode ?? "").toLowerCase();
610
+ return (code === "missing_api_key" ||
611
+ code === "missing_credentials" ||
612
+ /no llm provider(?: key)? (?:is connected|was found)/i.test(message));
613
+ }
608
614
  function dispatchActivityClear(tabId) {
609
615
  if (typeof window === "undefined")
610
616
  return;
@@ -1389,10 +1395,6 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
1389
1395
  // the last preparation activity, so do not leave its label mounted.
1390
1396
  dispatchActivityClear(tabId);
1391
1397
  settleInterruptedToolCalls(content, undefined, { includeActivity: true });
1392
- content.push({
1393
- type: "text",
1394
- text: formatChatErrorText(errMsg, undefined, errorCode),
1395
- });
1396
1398
  return {
1397
1399
  action: "missing_api_key",
1398
1400
  result: {
@@ -1472,6 +1474,7 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
1472
1474
  };
1473
1475
  }
1474
1476
  const normalized = normalizeChatError(errMsg, ev.errorCode);
1477
+ const missingProviderError = isMissingProviderErrorText(errMsg, ev.errorCode);
1475
1478
  if (isMissingCredentialText(errMsg, ev.errorCode)) {
1476
1479
  dispatchMissingApiKey(tabId);
1477
1480
  }
@@ -1492,10 +1495,12 @@ export function processEvent(ev, content, toolCallCounter, tabId, state) {
1492
1495
  }));
1493
1496
  }
1494
1497
  settleInterruptedToolCalls(content, undefined, { includeActivity: true });
1495
- content.push({
1496
- type: "text",
1497
- text: formatChatErrorText(errMsg, ev.upgradeUrl, ev.errorCode),
1498
- });
1498
+ if (!missingProviderError) {
1499
+ content.push({
1500
+ type: "text",
1501
+ text: formatChatErrorText(errMsg, ev.upgradeUrl, ev.errorCode),
1502
+ });
1503
+ }
1499
1504
  return {
1500
1505
  action: "error",
1501
1506
  result: {
@@ -0,0 +1,2 @@
1
+ /** Return the focused run for a thread and keep it current as the stream moves. */
2
+ export declare function useActiveAgentChatRunId(threadId: string | null | undefined): string | null;
@@ -0,0 +1,22 @@
1
+ import { useEffect, useState } from "react";
2
+ import { ACTIVE_RUN_STATE_EVENT, getActiveRun, } from "./active-run-state.js";
3
+ /** Return the focused run for a thread and keep it current as the stream moves. */
4
+ export function useActiveAgentChatRunId(threadId) {
5
+ const [activeRun, setActiveRun] = useState(() => getActiveRun());
6
+ useEffect(() => {
7
+ const syncFromStorage = () => setActiveRun(getActiveRun());
8
+ const handleActiveRunChange = (event) => {
9
+ const state = event
10
+ .detail?.state;
11
+ setActiveRun(state ?? null);
12
+ };
13
+ syncFromStorage();
14
+ window.addEventListener(ACTIVE_RUN_STATE_EVENT, handleActiveRunChange);
15
+ window.addEventListener("storage", syncFromStorage);
16
+ return () => {
17
+ window.removeEventListener(ACTIVE_RUN_STATE_EVENT, handleActiveRunChange);
18
+ window.removeEventListener("storage", syncFromStorage);
19
+ };
20
+ }, []);
21
+ return activeRun && activeRun.threadId === threadId ? activeRun.runId : null;
22
+ }