@agent-native/core 0.151.2 → 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 (250) 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/turn-into-app/SKILL.md +24 -0
  131. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +6 -0
  132. package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
  133. package/corpus/templates/slides/app/root.tsx +0 -1
  134. package/corpus/templates/slides/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  135. package/corpus/templates/slides/changelog/2026-08-11-share-dialog-uses-commenter-terminology.md +6 -0
  136. package/corpus/templates/slides/public/manifest.json +0 -1
  137. package/corpus/templates/tasks/.agents/skills/sharing/SKILL.md +1 -1
  138. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +24 -0
  139. package/corpus/templates/tasks/app/root.tsx +0 -1
  140. package/corpus/templates/tasks/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  141. package/corpus/templates/tasks/public/manifest.json +0 -1
  142. package/dist/agent/production-agent.js +1 -22
  143. package/dist/agent/run-manager.d.ts +7 -0
  144. package/dist/agent/run-manager.js +46 -3
  145. package/dist/agent/tool-approval-migrations.d.ts +40 -0
  146. package/dist/agent/tool-approval-migrations.js +51 -0
  147. package/dist/agent/tool-approval-store.js +5 -20
  148. package/dist/cli/templates-meta.js +2 -2
  149. package/dist/client/AgentPanel.js +10 -1
  150. package/dist/client/AssistantChat.d.ts +3 -0
  151. package/dist/client/AssistantChat.js +148 -140
  152. package/dist/client/agent-page/AgentTabsPage.js +2 -2
  153. package/dist/client/chat/attachment-adapters.js +8 -2
  154. package/dist/client/chat/tool-call-display.d.ts +1 -0
  155. package/dist/client/chat/tool-call-display.js +3 -1
  156. package/dist/client/chat-first.js +11 -5
  157. package/dist/client/hooks/index.d.ts +1 -1
  158. package/dist/client/hooks/index.js +1 -1
  159. package/dist/client/org/OrgSwitcher.d.ts +3 -1
  160. package/dist/client/org/OrgSwitcher.js +22 -16
  161. package/dist/client/org/WorkspaceNotice.js +3 -1
  162. package/dist/client/resources/index.d.ts +1 -1
  163. package/dist/client/resources/index.js +1 -1
  164. package/dist/client/resources/use-mcp-servers.d.ts +1 -0
  165. package/dist/client/resources/use-mcp-servers.js +14 -0
  166. package/dist/client/settings/AccountSettingsCard.js +8 -4
  167. package/dist/client/settings/SettingsPanel.js +46 -13
  168. package/dist/client/settings/SettingsTabsPage.js +8 -3
  169. package/dist/client/sharing/ShareButton.d.ts +7 -1
  170. package/dist/client/sharing/ShareButton.js +14 -7
  171. package/dist/client/sharing/ShareDialog.js +5 -1
  172. package/dist/client/sharing/useShareButtonController.d.ts +4 -0
  173. package/dist/client/sharing/useShareButtonController.js +15 -0
  174. package/dist/client/sharing/useShareDialogController.d.ts +7 -0
  175. package/dist/client/sharing/useShareDialogController.js +14 -0
  176. package/dist/client/sse-event-processor.js +37 -0
  177. package/dist/client/use-session.d.ts +2 -0
  178. package/dist/client/use-session.js +69 -5
  179. package/dist/collab/struct-routes.d.ts +1 -1
  180. package/dist/deploy/build.js +1 -1
  181. package/dist/file-upload/pre-upload-attachments.d.ts +3 -4
  182. package/dist/file-upload/pre-upload-attachments.js +65 -17
  183. package/dist/ingestion/index.d.ts +1 -0
  184. package/dist/ingestion/index.js +1 -0
  185. package/dist/ingestion/office.d.ts +3 -3
  186. package/dist/ingestion/office.js +24 -2
  187. package/dist/ingestion/spreadsheet.d.ts +41 -0
  188. package/dist/ingestion/spreadsheet.js +172 -0
  189. package/dist/integrations/adapters/slack.js +7 -3
  190. package/dist/localization/default-messages.d.ts +3 -0
  191. package/dist/localization/default-messages.js +3 -0
  192. package/dist/mcp/embed-app.js +20 -9
  193. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  194. package/dist/notifications/routes.d.ts +6 -6
  195. package/dist/oauth-tokens/migrations.d.ts +8 -0
  196. package/dist/oauth-tokens/migrations.js +36 -0
  197. package/dist/org/workspace-url.d.ts +8 -0
  198. package/dist/org/workspace-url.js +26 -2
  199. package/dist/secrets/routes.d.ts +3 -3
  200. package/dist/server/agent-chat-plugin.js +16 -8
  201. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  202. package/dist/server/auth.d.ts +0 -11
  203. package/dist/server/auth.js +37 -20
  204. package/dist/server/better-auth-migrations.js +23 -0
  205. package/dist/server/email-template.d.ts +5 -0
  206. package/dist/server/email-template.js +9 -0
  207. package/dist/server/embed-route.js +17 -5
  208. package/dist/server/identity-sso-store.d.ts +40 -66
  209. package/dist/server/identity-sso-store.js +187 -150
  210. package/dist/server/identity-sso.d.ts +17 -73
  211. package/dist/server/identity-sso.js +294 -297
  212. package/dist/server/onboarding-html.d.ts +0 -12
  213. package/dist/server/onboarding-html.js +46 -269
  214. package/dist/server/release-migrations.js +8 -0
  215. package/dist/shared/index.d.ts +1 -1
  216. package/dist/shared/index.js +1 -1
  217. package/dist/shared/workspace-app-id.d.ts +2 -0
  218. package/dist/shared/workspace-app-id.js +10 -0
  219. package/dist/sharing/actions/share-resource.d.ts +1 -0
  220. package/dist/sharing/actions/share-resource.js +20 -5
  221. package/dist/templates/chat/.agents/skills/sharing/SKILL.md +1 -1
  222. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +24 -0
  223. package/dist/templates/chat/app/root.tsx +0 -1
  224. package/dist/templates/chat/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  225. package/dist/templates/chat/public/manifest.json +0 -1
  226. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +24 -0
  227. package/dist/templates/default/app/root.tsx +0 -1
  228. package/dist/templates/default/public/manifest.json +0 -1
  229. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +24 -0
  230. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +22 -11
  231. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +1 -1
  232. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +24 -0
  233. package/docs/content/cross-app-sso.mdx +85 -27
  234. package/docs/content/template-mail.mdx +0 -6
  235. package/package.json +4 -3
  236. package/src/templates/chat/.agents/skills/sharing/SKILL.md +1 -1
  237. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +24 -0
  238. package/src/templates/chat/app/root.tsx +0 -1
  239. package/src/templates/chat/changelog/2026-08-11-browser-no-longer-offers-desktop-install.md +6 -0
  240. package/src/templates/chat/public/manifest.json +0 -1
  241. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +24 -0
  242. package/src/templates/default/app/root.tsx +0 -1
  243. package/src/templates/default/public/manifest.json +0 -1
  244. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +24 -0
  245. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +22 -11
  246. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +1 -1
  247. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +24 -0
  248. package/corpus/templates/calendar/changelog/2026-06-23-added-a-heads-up-explaining-google-s-app-not-verified-screen.md +0 -6
  249. package/corpus/templates/clips/app/components/meetings/google-oauth-identity-notice.tsx +0 -51
  250. package/corpus/templates/clips/changelog/2026-07-30-google-calendar-warning.md +0 -6
@@ -2269,15 +2269,19 @@ export function createAgentChatPlugin(options) {
2269
2269
  catch { }
2270
2270
  // Lean mode: only template actions + essential framework tools. Drop
2271
2271
  // web-request, browser tools, teams, jobs, automations, notifications,
2272
- // progress, call-agent, and MCP entries to keep the tool list tight and
2273
- // prevent the LLM from reaching for web-request instead of the
2274
- // template's native actions (e.g. log-meal).
2272
+ // progress, and MCP entries to keep the tool list tight and prevent the
2273
+ // LLM from reaching for web-request instead of the template's native
2274
+ // actions (e.g. log-meal). Cross-app delegation is the exception: when
2275
+ // it is enabled, keep its two discovery/delegation tools available even
2276
+ // in lean mode because the framework prompt and default starter surface
2277
+ // still promise sibling-app routing.
2275
2278
  const leanActionEntries = {
2276
2279
  ...templateScripts,
2277
2280
  ...resourceScripts,
2278
2281
  ...refreshScreenTool,
2279
2282
  ...urlTools,
2280
2283
  ...chatScripts,
2284
+ ...(a2aAgentDelegationEnabled ? callAgentScript : {}),
2281
2285
  ...toolActions,
2282
2286
  };
2283
2287
  const anonymousReadOnlyActions = attachToolSearch(filterReadOnlyActions(templateScripts));
@@ -2387,7 +2391,11 @@ export function createAgentChatPlugin(options) {
2387
2391
  // Lean mode: use only the template's systemPrompt + actions list.
2388
2392
  // Skip resource loading and schema block — those add DB round-trips
2389
2393
  // and tokens that minimal/voice apps don't need.
2390
- const leanBasePrompt = (options?.systemPrompt ?? "") + prodActionsPrompt;
2394
+ const leanActionsPrompt = prodActionsPrompt +
2395
+ (a2aAgentDelegationEnabled
2396
+ ? generateActionsPrompt(callAgentScript, "tool")
2397
+ : "");
2398
+ const leanBasePrompt = (options?.systemPrompt ?? "") + leanActionsPrompt;
2391
2399
  const anonymousReadOnlyPrompt = (options?.systemPrompt ?? PROD_FRAMEWORK_PROMPT_COMPACT) +
2392
2400
  generateActionsPrompt(filterReadOnlyActions(templateScripts), "tool", lazyContext ? effectiveInitialToolNames : undefined) +
2393
2401
  "\n\nYou are answering from a public shared page. Treat the visible resource as read-only: do not create, edit, delete, comment on, share, or otherwise mutate app data. If the user asks for a change, describe what you would change or suggest signing in to edit.";
@@ -2584,8 +2592,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2584
2592
  if (leanPrompt) {
2585
2593
  const leanRunPolicyPrompt = buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, prodCodeExecPromptNote);
2586
2594
  await emitContextXraySystemSections(event, {
2587
- frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - prodActionsPrompt.length)),
2588
- actionsPrompt: prodActionsPrompt,
2595
+ frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - leanActionsPrompt.length)),
2596
+ actionsPrompt: leanActionsPrompt,
2589
2597
  additionalFramework: leanRunPolicyPrompt,
2590
2598
  extra,
2591
2599
  modelOverlay,
@@ -2823,8 +2831,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2823
2831
  // for the same pattern.
2824
2832
  if (leanPrompt) {
2825
2833
  await emitContextXraySystemSections(event, {
2826
- frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - prodActionsPrompt.length)),
2827
- actionsPrompt: prodActionsPrompt,
2834
+ frameworkPrompt: leanBasePrompt.slice(0, Math.max(0, leanBasePrompt.length - leanActionsPrompt.length)),
2835
+ actionsPrompt: leanActionsPrompt,
2828
2836
  extra,
2829
2837
  modelOverlay,
2830
2838
  runtimeContext,
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
- error?: undefined;
31
30
  ok: boolean;
32
31
  key: string;
33
32
  baseUrlKey?: string;
34
33
  scope: AgentEngineApiKeyScope;
34
+ error?: undefined;
35
35
  }>>;
36
36
  export {};
@@ -112,17 +112,6 @@ export interface AuthOptions {
112
112
  features?: string[];
113
113
  runLocalCommand?: string;
114
114
  };
115
- /**
116
- * Optional host-scoped notice shown before the built-in Google sign-in
117
- * redirects to Google.
118
- */
119
- googleSignInNotice?: {
120
- host?: string;
121
- title: string;
122
- body: string | string[];
123
- continueLabel?: string;
124
- cancelLabel?: string;
125
- };
126
115
  /**
127
116
  * Optional email signup legal copy for the built-in login page.
128
117
  * Leave unset to use Agent Native links only on `*.agent-native.com` hosts,
@@ -999,7 +999,6 @@ function getOnboardingHtmlOptions(options, event, rawPath, authMode) {
999
999
  authMode,
1000
1000
  googleOnly: options.googleOnly,
1001
1001
  marketing: options.marketing,
1002
- googleSignInNotice: options.googleSignInNotice,
1003
1002
  signupLegalNotice: options.signupLegalNotice,
1004
1003
  googleAuthMode: options.googleAuthMode,
1005
1004
  requestHost: event ? getRequestHost(event) : undefined,
@@ -1922,6 +1921,13 @@ async function hasAutoDevAccountUser(db) {
1922
1921
  });
1923
1922
  return rows.length > 0;
1924
1923
  }
1924
+ async function hasRealUser(db) {
1925
+ const { rows } = await db.execute({
1926
+ sql: 'SELECT 1 FROM "user" WHERE email NOT IN (?, ?) LIMIT 1',
1927
+ args: [AUTO_DEV_ACCOUNT_EMAIL, LEGACY_AUTO_DEV_ACCOUNT_EMAIL],
1928
+ });
1929
+ return rows.length > 0;
1930
+ }
1925
1931
  const autoDevAccountCreationPromises = new Map();
1926
1932
  function getAutoDevAccountCreationKey() {
1927
1933
  return `${process.cwd()}:${process.env.APP_BASE_PATH ?? ""}`;
@@ -2012,11 +2018,7 @@ async function createOrReuseAutoDevSession(auth, config) {
2012
2018
  if (session)
2013
2019
  return { email: session.email, token: session.token };
2014
2020
  const db = getDbExec();
2015
- const { rows: realUsers } = await db.execute({
2016
- sql: 'SELECT 1 FROM "user" WHERE email NOT IN (?, ?) LIMIT 1',
2017
- args: [AUTO_DEV_ACCOUNT_EMAIL, LEGACY_AUTO_DEV_ACCOUNT_EMAIL],
2018
- });
2019
- if (realUsers.length > 0)
2021
+ if (await hasRealUser(db))
2020
2022
  return null;
2021
2023
  const devPassword = await createAutoDevAccountForSession(auth, db);
2022
2024
  if (!devPassword && !(await hasAutoDevAccountUser(db)))
@@ -2027,8 +2029,30 @@ async function createOrReuseAutoDevSession(auth, config) {
2027
2029
  }
2028
2030
  return session ? { email: session.email, token: session.token } : null;
2029
2031
  }
2032
+ async function getLocalDevAuthAvailability(event, config) {
2033
+ if (!isLocalDevAuthAllowed(event)) {
2034
+ return { available: false, reason: "not-allowed" };
2035
+ }
2036
+ try {
2037
+ const db = getDbExec();
2038
+ await getBetterAuth(config);
2039
+ if (await hasAutoDevAccountUser(db))
2040
+ return { available: true };
2041
+ if (await hasRealUser(db)) {
2042
+ return { available: false, reason: "existing-user" };
2043
+ }
2044
+ return { available: true };
2045
+ }
2046
+ catch {
2047
+ return { available: false, reason: "unreadable" };
2048
+ }
2049
+ }
2030
2050
  function createLocalDevAuthHandler(config) {
2031
2051
  return defineEventHandler(async (event) => {
2052
+ if (getMethod(event) === "GET") {
2053
+ setResponseHeader(event, "Cache-Control", "no-store");
2054
+ return getLocalDevAuthAvailability(event, config);
2055
+ }
2032
2056
  if (getMethod(event) !== "POST") {
2033
2057
  setResponseStatus(event, 405);
2034
2058
  return { error: "Method not allowed" };
@@ -2105,11 +2129,7 @@ async function maybeAutoCreateDevSession(event, redirectTo) {
2105
2129
  // pre-fix local DB that still holds a `dev@local` row isn't treated
2106
2130
  // as having a "real user" (which would permanently disable
2107
2131
  // auto-create on that DB).
2108
- const { rows: realUsers } = await db.execute({
2109
- sql: 'SELECT 1 FROM "user" WHERE email NOT IN (?, ?) LIMIT 1',
2110
- args: [AUTO_DEV_ACCOUNT_EMAIL, LEGACY_AUTO_DEV_ACCOUNT_EMAIL],
2111
- });
2112
- if (realUsers.length > 0)
2132
+ if (await hasRealUser(db))
2113
2133
  return null;
2114
2134
  // If the dev account already exists, this is not a freshly-scaffolded
2115
2135
  // app — the user has been through the auto-create flow at least
@@ -3086,7 +3106,7 @@ async function mountBetterAuthRoutes(app, options) {
3086
3106
  for (const key of callbackKeys) {
3087
3107
  if (typeof body[key] !== "string")
3088
3108
  continue;
3089
- const callbackURL = betterAuthCallbackURL(body[key], false, event);
3109
+ const callbackURL = betterAuthCallbackURL(body[key], true, event);
3090
3110
  if (callbackURL !== body[key]) {
3091
3111
  sanitizedBody[key] = callbackURL;
3092
3112
  changed = true;
@@ -3312,13 +3332,13 @@ async function mountBetterAuthRoutes(app, options) {
3312
3332
  desktopFlow = await issueDesktopMagicLinkFlow();
3313
3333
  callbackPath = withDesktopMagicLinkFlow(callbackPath, desktopFlow);
3314
3334
  }
3315
- const callbackURL = betterAuthCallbackURL(callbackPath, false, event);
3335
+ const callbackURL = betterAuthCallbackURL(callbackPath, true, event);
3316
3336
  const newUserCallbackPath = `${getAppBasePath()}/_agent-native/auth/magic-link/new-user?return=${encodeURIComponent(callbackPath)}`;
3317
3337
  await auth.api.signInMagicLink({
3318
3338
  body: {
3319
3339
  email,
3320
3340
  callbackURL,
3321
- newUserCallbackURL: betterAuthCallbackURL(newUserCallbackPath, callbackURL !== callbackPath, event),
3341
+ newUserCallbackURL: betterAuthCallbackURL(newUserCallbackPath, true, event),
3322
3342
  },
3323
3343
  headers: event.headers,
3324
3344
  });
@@ -3347,8 +3367,8 @@ async function mountBetterAuthRoutes(app, options) {
3347
3367
  const email = normalizeAuthEmail(rawEmail);
3348
3368
  const password = body?.password;
3349
3369
  const callbackURL = typeof body?.callbackURL === "string"
3350
- ? betterAuthCallbackURL(body.callbackURL, false, event)
3351
- : "/";
3370
+ ? betterAuthCallbackURL(body.callbackURL, true, event)
3371
+ : betterAuthCallbackURL("/", true, event);
3352
3372
  if (!email) {
3353
3373
  setResponseStatus(event, 400);
3354
3374
  return { error: VALID_AUTH_EMAIL_MESSAGE };
@@ -3715,10 +3735,7 @@ export async function autoMountAuth(app, options = {}) {
3715
3735
  customGetSession = options.getSession;
3716
3736
  }
3717
3737
  if (_authGuardConfig) {
3718
- if (options.googleOnly ||
3719
- options.loginHtml ||
3720
- options.marketing ||
3721
- options.googleSignInNotice) {
3738
+ if (options.googleOnly || options.loginHtml || options.marketing) {
3722
3739
  const loginHtmlConfig = getOnboardingLoginHtmlConfig(options, _authGuardConfig.authMode);
3723
3740
  _authGuardConfig.loginHtml = loginHtmlConfig.loginHtml;
3724
3741
  _authGuardConfig.getLoginHtml = loginHtmlConfig.getLoginHtml;
@@ -224,6 +224,29 @@ export const BETTER_AUTH_MIGRATIONS = [
224
224
  },
225
225
  run: assertBetterAuthUserIdentityColumns,
226
226
  },
227
+ {
228
+ version: 3,
229
+ name: "legacy-auth-sessions-table",
230
+ sql: {
231
+ // `addSession()` is still used by the mobile/deep-link OAuth flow and
232
+ // the workspace callback. Provision its legacy table in the release
233
+ // runtime so those request paths only perform normal row writes.
234
+ postgres: `
235
+ CREATE TABLE IF NOT EXISTS sessions (
236
+ token TEXT PRIMARY KEY,
237
+ email TEXT,
238
+ created_at BIGINT NOT NULL
239
+ )
240
+ `,
241
+ sqlite: `
242
+ CREATE TABLE IF NOT EXISTS sessions (
243
+ token TEXT PRIMARY KEY,
244
+ email TEXT,
245
+ created_at INTEGER NOT NULL
246
+ )
247
+ `,
248
+ },
249
+ },
227
250
  ];
228
251
  export async function runBetterAuthMigrations(nitroApp) {
229
252
  await runMigrations(BETTER_AUTH_MIGRATIONS, {
@@ -74,6 +74,11 @@ export declare function renderEmail(args: RenderEmailArgs): RenderedEmail;
74
74
  * paragraph strings passed to `renderEmail`. Escapes the content.
75
75
  */
76
76
  export declare function emailStrong(text: string): string;
77
+ /**
78
+ * Build a quoted message block for user-authored text in notification emails.
79
+ * The message stays escaped while preserving intentional line breaks.
80
+ */
81
+ export declare function emailQuote(text: string): string;
77
82
  /**
78
83
  * Build a labelled inline link for paragraph strings passed to `renderEmail`.
79
84
  * Use this instead of rendering raw URLs in the visible email body.
@@ -216,6 +216,15 @@ function stripTags(s) {
216
216
  export function emailStrong(text) {
217
217
  return `<strong style="color:#fafafa; font-weight:600;">${escapeHtml(text)}</strong>`;
218
218
  }
219
+ /**
220
+ * Build a quoted message block for user-authored text in notification emails.
221
+ * The message stays escaped while preserving intentional line breaks.
222
+ */
223
+ export function emailQuote(text) {
224
+ const content = escapeHtml(text.trim()).replace(/\r?\n/g, "<br />");
225
+ // guard:allow-raw-color — quoted blocks intentionally use a fixed email-safe accent
226
+ return `<div style="margin:0 0 16px 0; padding:12px 16px; border-left:3px solid #52525b; background:#18181b; color:#e4e4e7; font-size:16px; line-height:1.6;">${content}</div>`;
227
+ }
219
228
  /**
220
229
  * Build a labelled inline link for paragraph strings passed to `renderEmail`.
221
230
  * Use this instead of rendering raw URLs in the visible email body.
@@ -91,19 +91,31 @@ function expiredEmbedSessionResponse(event) {
91
91
  main { max-width: 520px; text-align: center; }
92
92
  h1 { margin: 0 0 8px; font-size: 16px; line-height: 1.25; }
93
93
  p { margin: 0; color: color-mix(in srgb, CanvasText 64%, Canvas); font-size: 13px; line-height: 1.5; }
94
+ button { margin-top: 16px; border: 1px solid color-mix(in srgb, CanvasText 24%, Canvas); border-radius: 6px; padding: 7px 12px; background: Canvas; color: CanvasText; font: inherit; font-size: 12px; cursor: pointer; }
95
+ button:hover { background: color-mix(in srgb, CanvasText 8%, Canvas); }
94
96
  </style>
95
97
  </head>
96
98
  <body>
97
99
  <main>
98
100
  <h1>Embedded app session expired</h1>
99
- <p>This chat preview is refreshing. If it does not reload, ask the chat to open the app again.</p>
101
+ <p>This embedded app session expired. The app will try to reconnect automatically.</p>
102
+ <button type="button" id="retry">Retry</button>
100
103
  </main>
101
104
  <script>
102
- try {
103
- if (window.parent && window.parent !== window) {
104
- window.parent.postMessage({ type: "agentNative.embedSessionExpired" }, "*");
105
+ function notifyParent() {
106
+ try {
107
+ if (window.parent && window.parent !== window) {
108
+ window.parent.postMessage({
109
+ type: "agentNative.embedSessionExpired",
110
+ embedStartUrl: window.location.href
111
+ }, "*");
112
+ }
113
+ } catch (error) {
114
+ void error;
105
115
  }
106
- } catch {}
116
+ }
117
+ document.getElementById("retry")?.addEventListener("click", notifyParent);
118
+ notifyParent();
107
119
  </script>
108
120
  </body>
109
121
  </html>`, {
@@ -1,88 +1,62 @@
1
1
  /**
2
- * Framework-table store for the cross-app SSO ("Sign in with Agent-Native")
3
- * CLIENT side. Backs two pieces of the federated login round-trip:
2
+ * Framework-table store for the cross-app SSO client.
4
3
  *
5
- * - `identity_sso_state` — short-lived (10 min), single-use, crypto-random
6
- * CSRF `state` values. Minted at `/_agent-native/identity/login`,
7
- * consumed exactly once at `/_agent-native/identity/callback`. Carries an
8
- * optional same-origin `return` path so the user lands back where they
9
- * started after federated sign-in.
10
- * - `identity_sso_jti` — replayed-token guard. The hub-issued identity JWT
11
- * carries a random `jti`; the first callback that verifies a given `jti`
12
- * records it here, and any later callback that presents the same `jti`
13
- * is rejected. Best-effort: a DB blip never widens the trust boundary
14
- * (signature + exp + scope + single-use state are still enforced), it
15
- * only relaxes the extra replay gate.
4
+ * The current protocol uses a fresh flow-state table instead of extending the
5
+ * original `identity_sso_state` table. That keeps the migration additive for
6
+ * deployments that already have the merged PR's schema:
16
7
  *
17
- * Mirrors `mcp/connect-store.ts`: lazy `ensureTable()`, `getDbExec()`,
18
- * dialect-agnostic SQL via `intType()`, `isConnectionError()` swallow so a
19
- * transient Neon WS drop never 500s. `CREATE TABLE IF NOT EXISTS` only —
20
- * strictly additive, never DROP / ALTER (shared prod DB rule).
8
+ * - `identity_sso_flow_state` binds state to the exact app, client,
9
+ * authority, callback, and PKCE challenge. State is single-use.
10
+ * - `identity_sso_jti` remains a defence-in-depth replay guard for the
11
+ * server-to-server assertion. The assertion is never sent through the
12
+ * browser; the one-time authorization code is the only browser credential.
21
13
  *
22
- * Node-only (crypto), bundled alongside the other framework auth modules.
23
- */
24
- /**
25
- * Read + normalise `AGENT_NATIVE_IDENTITY_HUB_URL`. Returns `undefined`
26
- * (feature OFF) unless it is set to a syntactically valid http(s) URL. A
27
- * malformed value is treated as OFF rather than throwing, so a typo can
28
- * never brick an app's login — it just behaves as if SSO were unconfigured.
14
+ * Uses the same portable raw-SQL pattern as the other framework stores. DDL is
15
+ * additive and lazy, and PostgreSQL creation goes through the DDL guard.
29
16
  */
17
+ export declare const SSO_STATE_TTL_MS: number;
18
+ export declare const SSO_LOGIN_MAX = 60;
19
+ export declare const SSO_LOGIN_WINDOW_MS = 60000;
30
20
  export declare function getIdentityHubUrl(): string | undefined;
31
- /**
32
- * Whether the federated-SSO client is active. When false, NOTHING in the
33
- * SSO module has any effect: the route 404s, the guard bypass is inert, the
34
- * login button is not rendered. This is the single switch the
35
- * env-unset-no-op invariant is asserted against.
36
- */
37
21
  export declare function isIdentitySsoEnabled(): boolean;
38
22
  export declare function isDesktopSsoCanaryUserAgent(userAgent: string | undefined): boolean;
39
23
  export declare function isCanonicalAgentNativeAppOrigin(origin: string | undefined): boolean;
40
24
  export declare function isCanonicalAgentNativeAppRequest(host: string | undefined, forwardedProtocol: string | undefined): boolean;
41
25
  /**
42
- * The conditional "Sign in with Agent-Native" entry injected into the login
43
- * page — ONLY when the feature is enabled. Returns an empty string when
44
- * disabled so the login HTML is byte-for-byte identical to today's output
45
- * with the env unset (asserted by the env-unset-no-op regression test). Pure
46
- * string builder, no I/O — safe to call during HTML render. Lives in this
47
- * leaf module so `onboarding-html.ts` can import it without creating an
48
- * `auth.ts` ↔ `identity-sso.ts` import cycle.
26
+ * The conditional login entry is the only browser UI this feature adds. It
27
+ * stays byte-for-byte absent when the direct web federation env is unset.
49
28
  */
50
29
  export declare function identitySsoLoginButtonHtml(): string;
51
- /** CSRF state values are valid for 10 minutes. */
52
- export declare const SSO_STATE_TTL_MS: number;
53
- /**
54
- * Rate limit for `identity/login`: at most this many state rows may be
55
- * created within `SSO_LOGIN_WINDOW_MS`. The endpoint is reachable without a
56
- * session (it's the entry point), so keep a coarse global cap to stop table
57
- * flooding without per-IP plumbing.
58
- */
59
- export declare const SSO_LOGIN_MAX = 60;
60
- export declare const SSO_LOGIN_WINDOW_MS = 60000;
61
- /**
62
- * Mint a fresh crypto-random `state` value, persist it with an optional
63
- * same-origin return path, and return it. Rate-limited at creation: at most
64
- * `SSO_LOGIN_MAX` rows within `SSO_LOGIN_WINDOW_MS`. Throws `RATE_LIMITED`
65
- * when the cap is exceeded so the route can map it to a 429.
66
- */
67
- export declare function createSsoState(returnPath: string | null): Promise<string>;
30
+ export interface CreateSsoStateInput {
31
+ returnPath: string | null;
32
+ appId: string;
33
+ clientId: string;
34
+ redirectUri: string;
35
+ authority: string;
36
+ codeChallenge: string;
37
+ }
38
+ export interface SsoStateBinding {
39
+ appId: string;
40
+ clientId: string;
41
+ redirectUri: string;
42
+ authority: string;
43
+ codeChallenge: string;
44
+ }
68
45
  export interface SsoStateConsumeResult {
69
46
  ok: boolean;
70
47
  returnPath: string | null;
71
48
  }
49
+ /** Mint and persist a bound, crypto-random state value. */
50
+ export declare function createSsoState(input: CreateSsoStateInput): Promise<string>;
72
51
  /**
73
- * Atomically consume a `state` value. Returns `{ ok: true, returnPath }` only
74
- * when the state existed, had not expired, and had not been consumed before —
75
- * and this call is the one that transitioned it to consumed (single-use,
76
- * enforced via a conditional UPDATE so a double callback can't both pass).
77
- * Any other condition returns `{ ok: false }`.
52
+ * Atomically consume state only when every security binding still matches.
53
+ * A missing or mismatched binding is indistinguishable from an unknown state.
78
54
  */
79
- export declare function consumeSsoState(state: string): Promise<SsoStateConsumeResult>;
55
+ export declare function consumeSsoState(state: string, expected: SsoStateBinding): Promise<SsoStateConsumeResult>;
80
56
  /**
81
- * Returns true when the given identity-token `jti` has already been seen
82
- * (i.e. this is a replay). On the first sighting, records the `jti` and
83
- * returns false. Best-effort: a store/DB error returns `false` (not a
84
- * replay) so a transient Neon WS drop never blocks a legitimate first-time
85
- * sign-in — signature + exp + scope + single-use CSRF state remain the hard
86
- * gates; this only adds defence in depth against token replay.
57
+ * Strict replay defense for the server-to-server assertion. A database error
58
+ * fails closed here: code exchange already provides the primary single-use
59
+ * guarantee, and refusing a login is safer than accepting an unverifiable
60
+ * replay boundary.
87
61
  */
88
62
  export declare function isJtiReplayed(jti: string | undefined): Promise<boolean>;