@agent-native/core 0.149.1 → 0.149.3

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 (422) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +54 -488
  3. package/corpus/templates/analytics/.agents/skills/actions/references/action-fields.md +136 -0
  4. package/corpus/templates/analytics/.agents/skills/actions/references/examples.md +94 -0
  5. package/corpus/templates/analytics/.agents/skills/actions/references/provider-apis.md +95 -0
  6. package/corpus/templates/analytics/.agents/skills/create-skill/SKILL.md +9 -35
  7. package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +4 -2
  8. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +2 -0
  9. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +4 -5
  10. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +18 -31
  11. package/corpus/templates/analytics/AGENTS.md +25 -32
  12. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +150 -46
  13. package/corpus/templates/analytics/app/global.css +1 -1
  14. package/corpus/templates/analytics/app/i18n-data.ts +37 -0
  15. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +1 -1
  16. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +32 -0
  17. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +2 -0
  18. package/corpus/templates/analytics/changelog/2026-08-10-dashboard-tables-can-be-copied-and-sorted-by-multiple-column.md +6 -0
  19. package/corpus/templates/analytics/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  20. package/corpus/templates/analytics/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  21. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +54 -488
  22. package/corpus/templates/assets/.agents/skills/actions/references/action-fields.md +136 -0
  23. package/corpus/templates/assets/.agents/skills/actions/references/examples.md +94 -0
  24. package/corpus/templates/assets/.agents/skills/actions/references/provider-apis.md +95 -0
  25. package/corpus/templates/assets/.agents/skills/create-skill/SKILL.md +9 -35
  26. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +4 -2
  27. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +4 -5
  28. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +18 -31
  29. package/corpus/templates/assets/AGENTS.md +6 -9
  30. package/corpus/templates/assets/app/global.css +1 -1
  31. package/corpus/templates/assets/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  32. package/corpus/templates/assets/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  33. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +54 -488
  34. package/corpus/templates/brain/.agents/skills/actions/references/action-fields.md +136 -0
  35. package/corpus/templates/brain/.agents/skills/actions/references/examples.md +94 -0
  36. package/corpus/templates/brain/.agents/skills/actions/references/provider-apis.md +95 -0
  37. package/corpus/templates/brain/.agents/skills/create-skill/SKILL.md +9 -35
  38. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +4 -5
  39. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +18 -31
  40. package/corpus/templates/brain/AGENTS.md +5 -12
  41. package/corpus/templates/brain/app/global.css +1 -1
  42. package/corpus/templates/brain/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  43. package/corpus/templates/brain/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  44. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +54 -488
  45. package/corpus/templates/calendar/.agents/skills/actions/references/action-fields.md +136 -0
  46. package/corpus/templates/calendar/.agents/skills/actions/references/examples.md +94 -0
  47. package/corpus/templates/calendar/.agents/skills/actions/references/provider-apis.md +95 -0
  48. package/corpus/templates/calendar/.agents/skills/create-skill/SKILL.md +9 -35
  49. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +4 -5
  50. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +18 -31
  51. package/corpus/templates/calendar/AGENTS.md +8 -9
  52. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  53. package/corpus/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  54. package/corpus/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  55. package/corpus/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  56. package/corpus/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  57. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  58. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  59. package/corpus/templates/chat/AGENTS.md +32 -80
  60. package/corpus/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  61. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +54 -488
  62. package/corpus/templates/clips/.agents/skills/actions/references/action-fields.md +136 -0
  63. package/corpus/templates/clips/.agents/skills/actions/references/examples.md +94 -0
  64. package/corpus/templates/clips/.agents/skills/actions/references/provider-apis.md +95 -0
  65. package/corpus/templates/clips/.agents/skills/create-skill/SKILL.md +9 -35
  66. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +4 -5
  67. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +18 -31
  68. package/corpus/templates/clips/AGENTS.md +25 -31
  69. package/corpus/templates/clips/changelog/2026-08-10-clips-desktop-sign-in-now-starts-with-magic-links-and-google.md +6 -0
  70. package/corpus/templates/clips/chrome-extension/src/overlay.css +1 -0
  71. package/corpus/templates/clips/desktop/src/app.tsx +274 -137
  72. package/corpus/templates/clips/desktop/src/styles.css +35 -0
  73. package/corpus/templates/content/.agents/skills/actions/SKILL.md +54 -488
  74. package/corpus/templates/content/.agents/skills/actions/references/action-fields.md +136 -0
  75. package/corpus/templates/content/.agents/skills/actions/references/examples.md +94 -0
  76. package/corpus/templates/content/.agents/skills/actions/references/provider-apis.md +95 -0
  77. package/corpus/templates/content/.agents/skills/create-skill/SKILL.md +9 -35
  78. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +4 -2
  79. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +4 -5
  80. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +18 -31
  81. package/corpus/templates/content/AGENTS.md +5 -9
  82. package/corpus/templates/content/app/global.css +1 -0
  83. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +18 -31
  84. package/corpus/templates/crm/AGENTS.md +7 -11
  85. package/corpus/templates/crm/app/global.css +1 -1
  86. package/corpus/templates/crm/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  87. package/corpus/templates/crm/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  88. package/corpus/templates/design/.agents/skills/actions/SKILL.md +54 -488
  89. package/corpus/templates/design/.agents/skills/actions/references/action-fields.md +136 -0
  90. package/corpus/templates/design/.agents/skills/actions/references/examples.md +94 -0
  91. package/corpus/templates/design/.agents/skills/actions/references/provider-apis.md +95 -0
  92. package/corpus/templates/design/.agents/skills/create-skill/SKILL.md +9 -35
  93. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +4 -2
  94. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +4 -5
  95. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +18 -31
  96. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +70 -3
  97. package/corpus/templates/design/AGENTS.md +13 -21
  98. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +12 -0
  99. package/corpus/templates/design/app/components/design/LayersPanel.tsx +19 -2
  100. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +115 -7
  101. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +82 -7
  102. package/corpus/templates/design/app/components/design/design-trace.ts +120 -0
  103. package/corpus/templates/design/app/components/design/dnd-debug.ts +2 -1
  104. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +40 -26
  105. package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +4 -1
  106. package/corpus/templates/design/app/components/design/multi-screen/frame-geometry.ts +12 -3
  107. package/corpus/templates/design/app/components/design/multi-screen/screen-content-cache.ts +4 -0
  108. package/corpus/templates/design/app/components/design/multi-screen/types.ts +7 -0
  109. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +3 -2
  110. package/corpus/templates/design/app/components/layout/Sidebar.tsx +2 -2
  111. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +3 -0
  112. package/corpus/templates/design/app/i18n-data.ts +1 -0
  113. package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +5 -5
  114. package/corpus/templates/design/app/pages/DesignSystems.tsx +3 -2
  115. package/corpus/templates/design/app/pages/design-editor/canvas-primitive-insert.ts +100 -13
  116. package/corpus/templates/design/app/pages/design-editor/cross-screen-text-color.ts +1 -1
  117. package/corpus/templates/design/app/pages/design-editor/data-operations.ts +14 -0
  118. package/corpus/templates/design/changelog/2026-08-10-marquee-selecting-layers-far-down-a-tall-screen-now-selects-.md +6 -0
  119. package/corpus/templates/design/changelog/2026-08-10-the-frame-tool-draws-a-plain-frame-by-default-with-screen-av.md +6 -0
  120. package/corpus/templates/design/e2e/global-setup.ts +27 -32
  121. package/corpus/templates/design/playwright.config.ts +3 -5
  122. package/corpus/templates/design/shared/breakpoint-media.ts +9 -2
  123. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +54 -488
  124. package/corpus/templates/dispatch/.agents/skills/actions/references/action-fields.md +136 -0
  125. package/corpus/templates/dispatch/.agents/skills/actions/references/examples.md +94 -0
  126. package/corpus/templates/dispatch/.agents/skills/actions/references/provider-apis.md +95 -0
  127. package/corpus/templates/dispatch/.agents/skills/create-skill/SKILL.md +9 -35
  128. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +4 -5
  129. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +18 -31
  130. package/corpus/templates/dispatch/AGENTS.md +9 -16
  131. package/corpus/templates/dispatch/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  132. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +54 -488
  133. package/corpus/templates/factory/.agents/skills/actions/references/action-fields.md +136 -0
  134. package/corpus/templates/factory/.agents/skills/actions/references/examples.md +94 -0
  135. package/corpus/templates/factory/.agents/skills/actions/references/provider-apis.md +95 -0
  136. package/corpus/templates/factory/.agents/skills/create-skill/SKILL.md +9 -35
  137. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +4 -5
  138. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +18 -31
  139. package/corpus/templates/factory/AGENTS.md +10 -24
  140. package/corpus/templates/factory/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  141. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +54 -488
  142. package/corpus/templates/forms/.agents/skills/actions/references/action-fields.md +136 -0
  143. package/corpus/templates/forms/.agents/skills/actions/references/examples.md +94 -0
  144. package/corpus/templates/forms/.agents/skills/actions/references/provider-apis.md +95 -0
  145. package/corpus/templates/forms/.agents/skills/create-skill/SKILL.md +9 -35
  146. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +4 -5
  147. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +18 -31
  148. package/corpus/templates/forms/AGENTS.md +11 -17
  149. package/corpus/templates/forms/app/global.css +1 -0
  150. package/corpus/templates/forms/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  151. package/corpus/templates/forms/changelog/2026-08-11-full-page-chat-composers-stay-at-a-focused-750px-width.md +6 -0
  152. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +4 -5
  153. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +18 -31
  154. package/corpus/templates/macros/AGENTS.md +8 -8
  155. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +54 -488
  156. package/corpus/templates/mail/.agents/skills/actions/references/action-fields.md +136 -0
  157. package/corpus/templates/mail/.agents/skills/actions/references/examples.md +94 -0
  158. package/corpus/templates/mail/.agents/skills/actions/references/provider-apis.md +95 -0
  159. package/corpus/templates/mail/.agents/skills/create-skill/SKILL.md +9 -35
  160. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +4 -5
  161. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +18 -31
  162. package/corpus/templates/mail/AGENTS.md +5 -6
  163. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +54 -488
  164. package/corpus/templates/plan/.agents/skills/actions/references/action-fields.md +136 -0
  165. package/corpus/templates/plan/.agents/skills/actions/references/examples.md +94 -0
  166. package/corpus/templates/plan/.agents/skills/actions/references/provider-apis.md +95 -0
  167. package/corpus/templates/plan/.agents/skills/create-skill/SKILL.md +9 -35
  168. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +4 -5
  169. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +18 -31
  170. package/corpus/templates/plan/AGENTS.md +5 -14
  171. package/corpus/templates/plan/app/global.css +1 -0
  172. package/corpus/templates/plan/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  173. package/corpus/templates/plan/changelog/2026-08-11-plan-no-longer-reloads-when-runtime-state-changes.md +6 -0
  174. package/corpus/templates/plan/server/ui-plan-html.ts +4 -1
  175. package/corpus/templates/plan/vite.config.ts +5 -0
  176. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +54 -488
  177. package/corpus/templates/slides/.agents/skills/actions/references/action-fields.md +136 -0
  178. package/corpus/templates/slides/.agents/skills/actions/references/examples.md +94 -0
  179. package/corpus/templates/slides/.agents/skills/actions/references/provider-apis.md +95 -0
  180. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +2 -2
  181. package/corpus/templates/slides/.agents/skills/create-skill/SKILL.md +9 -35
  182. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +6 -3
  183. package/corpus/templates/slides/.agents/skills/deck-management/SKILL.md +6 -1
  184. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +4 -5
  185. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +3 -2
  186. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +3 -0
  187. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +3 -3
  188. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +18 -31
  189. package/corpus/templates/slides/AGENTS.md +33 -35
  190. package/corpus/templates/slides/actions/add-deck.ts +2 -0
  191. package/corpus/templates/slides/actions/add-slide.ts +15 -1
  192. package/corpus/templates/slides/actions/create-deck.ts +18 -6
  193. package/corpus/templates/slides/actions/get-deck-reference-context.ts +2 -2
  194. package/corpus/templates/slides/actions/get-deck.ts +83 -7
  195. package/corpus/templates/slides/actions/import-file.ts +2 -1
  196. package/corpus/templates/slides/actions/patch-deck.ts +165 -9
  197. package/corpus/templates/slides/actions/save-deck.ts +24 -1
  198. package/corpus/templates/slides/actions/update-slide.ts +1 -1
  199. package/corpus/templates/slides/app/components/comments/SlideCommentsPanel.tsx +2 -2
  200. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +1 -23
  201. package/corpus/templates/slides/app/components/design-system/DesignSystemCard.tsx +2 -2
  202. package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +6 -6
  203. package/corpus/templates/slides/app/components/editor/AnimationsPanel.tsx +3 -3
  204. package/corpus/templates/slides/app/components/editor/DeckEditorSkeleton.tsx +4 -4
  205. package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +1 -1
  206. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +432 -668
  207. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +296 -259
  208. package/corpus/templates/slides/app/components/editor/GeneratingSlidePreview.tsx +1 -1
  209. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +13 -1
  210. package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +56 -174
  211. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +241 -116
  212. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
  213. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +42 -14
  214. package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +6 -12
  215. package/corpus/templates/slides/app/components/editor/editor-command-model.ts +35 -0
  216. package/corpus/templates/slides/app/components/layout/AgentWorkIndicator.tsx +1 -1
  217. package/corpus/templates/slides/app/components/layout/Layout.tsx +34 -35
  218. package/corpus/templates/slides/app/components/layout/Sidebar.tsx +8 -10
  219. package/corpus/templates/slides/app/components/layout/layout-route-policy.ts +2 -5
  220. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +45 -40
  221. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +63 -16
  222. package/corpus/templates/slides/app/context/DeckContext.tsx +2 -1
  223. package/corpus/templates/slides/app/global.css +76 -1
  224. package/corpus/templates/slides/app/hooks/use-generating-slide-preview.ts +25 -3
  225. package/corpus/templates/slides/app/i18n/en-US.ts +2 -0
  226. package/corpus/templates/slides/app/lib/create-deck-generation.ts +52 -23
  227. package/corpus/templates/slides/app/lib/recent-references.ts +23 -1
  228. package/corpus/templates/slides/app/lib/slide-animation-elements.ts +104 -3
  229. package/corpus/templates/slides/app/pages/DeckEditor.tsx +17 -33
  230. package/corpus/templates/slides/app/pages/DesignSystems.tsx +2 -2
  231. package/corpus/templates/slides/app/pages/Index.tsx +315 -151
  232. package/corpus/templates/slides/app/root.tsx +43 -0
  233. package/corpus/templates/slides/changelog/2026-08-10-ai-editing-avatar-badge.md +6 -0
  234. package/corpus/templates/slides/changelog/2026-08-10-generated-decks-keep-a-clear-human-readable-title.md +6 -0
  235. package/corpus/templates/slides/changelog/2026-08-10-new-deck-creation-now-shows-progress-opens-the-editor-direct.md +6 -0
  236. package/corpus/templates/slides/changelog/2026-08-10-presentation-reveals-now-follow-valid-targets.md +6 -0
  237. package/corpus/templates/slides/changelog/2026-08-10-slides-editing-controls-are-consolidated-into-one-focused-me.md +6 -0
  238. package/corpus/templates/slides/changelog/2026-08-10-slides-now-verify-and-restyle-every-imported-slide-in-one-pa.md +6 -0
  239. package/corpus/templates/slides/changelog/2026-08-10-slides-only-suggests-a-google-connection-for-relevant-reques.md +6 -0
  240. package/corpus/templates/slides/changelog/2026-08-10-the-google-slides-import-option-is-now-labeled-slides.md +6 -0
  241. package/corpus/templates/slides/changelog/2026-08-11-faster-slides-chat-deck-reads.md +6 -0
  242. package/corpus/templates/slides/changelog/2026-08-11-slides-chat-can-read-one-slide-without-loading-the-full-deck.md +6 -0
  243. package/corpus/templates/slides/changelog/2026-08-11-slides-clearly-indicate-when-an-ai-agent-is-editing-alongsid.md +6 -0
  244. package/corpus/templates/slides/package.json +1 -0
  245. package/corpus/templates/slides/server/lib/chat-attachments.ts +1 -1
  246. package/corpus/templates/slides/server/lib/validate-slide-animations.ts +163 -0
  247. package/corpus/templates/slides/server/plugins/agent-chat.ts +8 -5
  248. package/corpus/templates/slides/shared/api.ts +47 -15
  249. package/corpus/templates/slides/shared/deck-title.ts +135 -0
  250. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +54 -488
  251. package/corpus/templates/tasks/.agents/skills/actions/references/action-fields.md +136 -0
  252. package/corpus/templates/tasks/.agents/skills/actions/references/examples.md +94 -0
  253. package/corpus/templates/tasks/.agents/skills/actions/references/provider-apis.md +95 -0
  254. package/corpus/templates/tasks/.agents/skills/agent-watchdog/SKILL.md +1 -0
  255. package/corpus/templates/tasks/.agents/skills/create-skill/SKILL.md +9 -35
  256. package/corpus/templates/tasks/.agents/skills/efficient-fable/SKILL.md +1 -0
  257. package/corpus/templates/tasks/.agents/skills/efficient-frontier/SKILL.md +1 -0
  258. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +4 -5
  259. package/corpus/templates/tasks/.agents/skills/plan-arbiter/SKILL.md +1 -0
  260. package/corpus/templates/tasks/.agents/skills/plow-ahead/SKILL.md +1 -0
  261. package/corpus/templates/tasks/.agents/skills/quick-recap/SKILL.md +1 -0
  262. package/corpus/templates/tasks/.agents/skills/read-the-damn-docs/SKILL.md +1 -0
  263. package/corpus/templates/tasks/.agents/skills/stay-within-limits/SKILL.md +1 -0
  264. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +18 -31
  265. package/corpus/templates/tasks/AGENTS.md +5 -20
  266. package/corpus/templates/tasks/app/components/tasks/TaskListRow.tsx +4 -1
  267. package/dist/agent/engine/ai-sdk-engine.js +1 -1
  268. package/dist/agent/production-agent.d.ts +21 -1
  269. package/dist/agent/production-agent.js +505 -355
  270. package/dist/agent/run-manager.js +156 -14
  271. package/dist/agent/run-store.d.ts +11 -10
  272. package/dist/agent/run-store.js +17 -13
  273. package/dist/agent/tool-approval-store.d.ts +18 -0
  274. package/dist/agent/tool-approval-store.js +122 -0
  275. package/dist/agent/types.d.ts +1 -1
  276. package/dist/cli/code-agent-executor.js +11 -2
  277. package/dist/client/AgentPanel.js +31 -6
  278. package/dist/client/AssistantChat.d.ts +9 -4
  279. package/dist/client/AssistantChat.js +221 -149
  280. package/dist/client/active-run-state.d.ts +9 -1
  281. package/dist/client/active-run-state.js +34 -3
  282. package/dist/client/agent-chat/index.d.ts +1 -1
  283. package/dist/client/agent-chat-adapter.d.ts +8 -0
  284. package/dist/client/agent-chat-adapter.js +125 -28
  285. package/dist/client/agent-chat.d.ts +1 -1
  286. package/dist/client/chat/markdown-renderer.js +14 -2
  287. package/dist/client/chat/message-components.d.ts +13 -3
  288. package/dist/client/chat/message-components.js +57 -52
  289. package/dist/client/chat/run-recovery.d.ts +1 -0
  290. package/dist/client/chat/run-recovery.js +8 -0
  291. package/dist/client/chat/tool-call-display.d.ts +5 -5
  292. package/dist/client/chat/tool-call-display.js +9 -212
  293. package/dist/client/chat-first/apps-rail.js +3 -3
  294. package/dist/client/chat-first/browser-pane.js +4 -1
  295. package/dist/client/chat-first/chat-history.d.ts +3 -1
  296. package/dist/client/chat-first/chat-history.js +7 -4
  297. package/dist/client/chat-first/surface-tabs.d.ts +1 -1
  298. package/dist/client/chat-first/surface-tabs.js +52 -41
  299. package/dist/client/chat-first/types.d.ts +3 -0
  300. package/dist/client/chat-first.d.ts +10 -0
  301. package/dist/client/chat-first.js +37 -2
  302. package/dist/client/components/ui/message-scroller.js +4 -1
  303. package/dist/client/i18n.js +3 -1
  304. package/dist/client/resources/McpConnectionSuggestion.js +9 -1
  305. package/dist/client/sse-event-processor.d.ts +4 -2
  306. package/dist/client/sse-event-processor.js +46 -6
  307. package/dist/client/use-chat-models.js +156 -80
  308. package/dist/client/use-run-stuck-detection.d.ts +2 -0
  309. package/dist/client/use-run-stuck-detection.js +85 -9
  310. package/dist/collab/awareness.d.ts +2 -2
  311. package/dist/collab/routes.d.ts +1 -1
  312. package/dist/collab/struct-routes.d.ts +1 -1
  313. package/dist/integrations/adapters/slack.d.ts +0 -4
  314. package/dist/integrations/adapters/slack.js +6 -30
  315. package/dist/integrations/catalog.js +1 -1
  316. package/dist/integrations/pending-tasks-store.d.ts +0 -8
  317. package/dist/integrations/pending-tasks-store.js +0 -21
  318. package/dist/integrations/slack-manifest.d.ts +2 -2
  319. package/dist/integrations/slack-manifest.js +0 -3
  320. package/dist/integrations/webhook-handler.js +1 -1
  321. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  322. package/dist/observability/routes.d.ts +3 -3
  323. package/dist/provider-api/actions/custom-provider-registration.d.ts +4 -4
  324. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  325. package/dist/scripts/docs/source-search.js +2 -2
  326. package/dist/server/agent-chat/framework-prompts.js +7 -2
  327. package/dist/server/agent-chat/prompt-resources.js +2 -2
  328. package/dist/server/agent-chat/skill-frontmatter.d.ts +31 -2
  329. package/dist/server/agent-chat/skill-frontmatter.js +41 -15
  330. package/dist/server/agent-chat-plugin.js +3 -3
  331. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  332. package/dist/server/agents-bundle.d.ts +16 -19
  333. package/dist/server/agents-bundle.js +19 -35
  334. package/dist/server/auth.js +262 -31
  335. package/dist/server/better-auth-instance.d.ts +1 -0
  336. package/dist/server/better-auth-instance.js +17 -2
  337. package/dist/server/onboarding-html.js +56 -9
  338. package/dist/server/prompts/framework-core-compact.d.ts +6 -1
  339. package/dist/server/prompts/framework-core-compact.js +12 -9
  340. package/dist/server/prompts/framework-core.d.ts +6 -1
  341. package/dist/server/prompts/framework-core.js +11 -9
  342. package/dist/server/prompts/index.d.ts +1 -1
  343. package/dist/server/prompts/index.js +1 -1
  344. package/dist/server/prompts/shared-rules.d.ts +15 -11
  345. package/dist/server/prompts/shared-rules.js +17 -13
  346. package/dist/server/realtime-token.d.ts +1 -1
  347. package/dist/server/transcribe-voice.d.ts +1 -1
  348. package/dist/shared/reasoning-effort.d.ts +8 -8
  349. package/dist/shared/reasoning-effort.js +10 -10
  350. package/dist/shared/streaming-text-smoothing.js +41 -11
  351. package/dist/styles/agent-native.css +19 -32
  352. package/dist/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  353. package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  354. package/dist/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  355. package/dist/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  356. package/dist/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  357. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  358. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  359. package/dist/templates/chat/AGENTS.md +32 -80
  360. package/dist/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  361. package/dist/templates/default/.agents/skills/actions/SKILL.md +54 -488
  362. package/dist/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
  363. package/dist/templates/default/.agents/skills/actions/references/examples.md +94 -0
  364. package/dist/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
  365. package/dist/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
  366. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
  367. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
  368. package/dist/templates/headless/.agents/skills/actions/SKILL.md +54 -488
  369. package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
  370. package/dist/templates/headless/.agents/skills/actions/references/examples.md +94 -0
  371. package/dist/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
  372. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
  373. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
  374. package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
  375. package/dist/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
  376. package/dist/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
  377. package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
  378. package/dist/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
  379. package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
  380. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
  381. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
  382. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
  383. package/dist/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
  384. package/dist/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
  385. package/dist/templates/workspace-core/AGENTS.md +7 -16
  386. package/docs/content/messaging.mdx +6 -7
  387. package/docs/content/template-chat.mdx +1 -1
  388. package/package.json +2 -2
  389. package/src/templates/chat/.agents/skills/actions/SKILL.md +54 -488
  390. package/src/templates/chat/.agents/skills/actions/references/action-fields.md +136 -0
  391. package/src/templates/chat/.agents/skills/actions/references/examples.md +94 -0
  392. package/src/templates/chat/.agents/skills/actions/references/provider-apis.md +95 -0
  393. package/src/templates/chat/.agents/skills/create-skill/SKILL.md +9 -35
  394. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +4 -5
  395. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +18 -31
  396. package/src/templates/chat/AGENTS.md +32 -80
  397. package/src/templates/chat/changelog/2026-08-10-full-page-chat-now-uses-the-available-width-up-to-1000px-for.md +6 -0
  398. package/src/templates/default/.agents/skills/actions/SKILL.md +54 -488
  399. package/src/templates/default/.agents/skills/actions/references/action-fields.md +136 -0
  400. package/src/templates/default/.agents/skills/actions/references/examples.md +94 -0
  401. package/src/templates/default/.agents/skills/actions/references/provider-apis.md +95 -0
  402. package/src/templates/default/.agents/skills/create-skill/SKILL.md +9 -35
  403. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +4 -5
  404. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +18 -31
  405. package/src/templates/headless/.agents/skills/actions/SKILL.md +54 -488
  406. package/src/templates/headless/.agents/skills/actions/references/action-fields.md +136 -0
  407. package/src/templates/headless/.agents/skills/actions/references/examples.md +94 -0
  408. package/src/templates/headless/.agents/skills/actions/references/provider-apis.md +95 -0
  409. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +18 -31
  410. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +54 -488
  411. package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +136 -0
  412. package/src/templates/workspace-core/.agents/skills/actions/references/examples.md +94 -0
  413. package/src/templates/workspace-core/.agents/skills/actions/references/provider-apis.md +95 -0
  414. package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +1 -0
  415. package/src/templates/workspace-core/.agents/skills/agent-page/SKILL.md +1 -0
  416. package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +9 -35
  417. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +4 -5
  418. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +21 -29
  419. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +18 -31
  420. package/src/templates/workspace-core/.agents/skills/workspace-conventions/SKILL.md +7 -17
  421. package/src/templates/workspace-core/.agents/skills/writing-agent-instructions/SKILL.md +3 -3
  422. package/src/templates/workspace-core/AGENTS.md +7 -16
@@ -20,7 +20,8 @@
20
20
  *
21
21
  * Result is cached in module scope so it's only computed once per cold start.
22
22
  */
23
- export const DEFAULT_SKILL_SCOPE = "both";
23
+ import { DEFAULT_SKILL_SCOPE, isRuntimeVisibleScope, normalizeSkillScope, } from "./agent-chat/skill-frontmatter.js";
24
+ export { DEFAULT_SKILL_SCOPE, isRuntimeVisibleScope, normalizeSkillScope, };
24
25
  const DEFAULT_AGENT_INSTRUCTIONS_PATH = "AGENTS.md";
25
26
  export function resolveAgentInstructionPaths(instructions) {
26
27
  return {
@@ -29,26 +30,6 @@ export function resolveAgentInstructionPaths(instructions) {
29
30
  };
30
31
  }
31
32
  let cached = null;
32
- /**
33
- * Coerce a raw frontmatter `scope` value into a known `SkillScope`. Unknown,
34
- * empty, or malformed values fall back to the default (`both`) so a typo never
35
- * silently hides a skill from the runtime agent. Optionally warns once per
36
- * distinct bad value to aid debugging without spamming logs.
37
- */
38
- const warnedBadScopes = new Set();
39
- export function normalizeSkillScope(raw) {
40
- if (!raw)
41
- return DEFAULT_SKILL_SCOPE;
42
- const value = raw.trim().toLowerCase();
43
- if (value === "runtime" || value === "dev" || value === "both") {
44
- return value;
45
- }
46
- if (value && !warnedBadScopes.has(value)) {
47
- warnedBadScopes.add(value);
48
- console.warn(`[agents-bundle] Unknown skill scope "${raw}" — treating as "${DEFAULT_SKILL_SCOPE}". Valid values: runtime, dev, both.`);
49
- }
50
- return DEFAULT_SKILL_SCOPE;
51
- }
52
33
  /**
53
34
  * Parse the YAML frontmatter at the top of a skill file.
54
35
  * Only pulls out `name`, `description`, and `scope` — deliberately simple, no
@@ -57,8 +38,11 @@ export function normalizeSkillScope(raw) {
57
38
  * - Inline: `description: Some text`
58
39
  * - Folded scalar: `description: >-\n multi\n line` → "multi line"
59
40
  * - Literal scalar: `description: |\n multi\n line` → "multi\nline"
41
+ *
42
+ * `sourceLabel` only names the file in the invalid-scope log; pass it wherever
43
+ * a path is known so a typo is traceable to the SKILL.md that carries it.
60
44
  */
61
- export function parseSkillFrontmatter(content) {
45
+ export function parseSkillFrontmatter(content, sourceLabel) {
62
46
  const match = content.match(/^---\r?\n([\s\S]+?)\r?\n---/);
63
47
  if (!match)
64
48
  return {};
@@ -106,7 +90,7 @@ export function parseSkillFrontmatter(content) {
106
90
  else if (key === "description" && value)
107
91
  result.description = value;
108
92
  else if (key === "scope" && value)
109
- result.scope = normalizeSkillScope(value);
93
+ result.scope = normalizeSkillScope(value, sourceLabel ?? result.name);
110
94
  }
111
95
  return result;
112
96
  }
@@ -170,7 +154,7 @@ function readSkillsDir(skillsDir, rootForRelative, out, skipExistingNames) {
170
154
  if (!fs.existsSync(realSkillFile))
171
155
  continue;
172
156
  const content = fs.readFileSync(realSkillFile, "utf-8");
173
- const meta = parseSkillFrontmatter(content);
157
+ const meta = parseSkillFrontmatter(content, path.relative(rootForRelative, skillFile).replace(/\\/g, "/"));
174
158
  const name = meta.name ?? entry.name;
175
159
  if (skipExistingNames && out[name])
176
160
  continue; // Template wins
@@ -375,17 +359,19 @@ export async function loadAgentsBundle() {
375
359
  */
376
360
  /**
377
361
  * Skills visible to the agent-native RUNTIME agent. Excludes `scope: dev`
378
- * skills (those are for the human's coding agent only). Skills with no scope,
379
- * `scope: runtime`, or `scope: both` are all included. Use this anywhere the
380
- * runtime agent's view of skills is built (prompt block + docs-search) so a
381
- * dev-scoped skill is invisible to the runtime agent everywhere.
362
+ * skills (those are for the human's coding agent only) and skills whose scope
363
+ * could not be read. Skills with no scope, `scope: runtime`, or `scope: both`
364
+ * are all included. Use this anywhere the runtime agent's view of skills is
365
+ * built (prompt block + docs-search) so a dev-scoped skill is invisible to the
366
+ * runtime agent everywhere.
382
367
  */
383
368
  export function getRuntimeSkills(bundle) {
384
- return Object.values(bundle.skills).filter((skill) => skill.meta.scope !== "dev");
369
+ return Object.values(bundle.skills).filter((skill) => isRuntimeVisibleScope(skill.meta.scope));
385
370
  }
386
371
  /**
387
372
  * Skills visible to development/coding agents. Excludes `scope: runtime`
388
- * skills that are intended only for the deployed in-app agent.
373
+ * skills that are intended only for the deployed in-app agent. An `invalid`
374
+ * scope stays visible here on purpose — this is the audience that can fix it.
389
375
  */
390
376
  export function getDevelopmentSkills(bundle) {
391
377
  return Object.values(bundle.skills).filter((skill) => skill.meta.scope !== "runtime");
@@ -437,14 +423,12 @@ function generateSkillsPromptBlockForEntries(entries, mode) {
437
423
  extras = ` (also contains: ${s.extraFiles.join(", ")})`;
438
424
  }
439
425
  }
440
- const runtimeHint = mode === "runtime"
441
- ? ` Read with \`docs-search --slug "${skillDocsSlug(s.meta.name)}"\` before starting a task it applies to.`
442
- : "";
426
+ const runtimeHint = mode === "runtime" ? ` [${skillDocsSlug(s.meta.name)}]` : "";
443
427
  return `- \`${s.meta.name}\` at \`${s.dir}/\` — ${s.meta.description || "(no description)"}${extras}${runtimeHint}`;
444
428
  });
445
429
  const readHint = mode === "runtime"
446
- ? `To read a skill in the in-app runtime agent:
447
- \`docs-search --slug "skill-<skill-name>"\`
430
+ ? `To read a skill in the in-app runtime agent, before starting a task it applies to:
431
+ \`docs-search --slug "<slug>"\` — each skill's slug is the [bracketed] token ending its line
448
432
  \`docs-search --query "<topic>"\` to discover matching docs/skills`
449
433
  : `To read a skill in dev mode (when you have bash access):
450
434
  \`bash(command="cat <skill-dir>/SKILL.md")\`
@@ -63,7 +63,7 @@ import { resolveAuthCookieNamespace } from "./cookie-namespace.js";
63
63
  import { getAllowedCorsOrigin, readCorsAllowedOrigins, } from "./cors-origins.js";
64
64
  import { readDesktopSso, writeDesktopSso, clearDesktopSso, } from "./desktop-sso.js";
65
65
  import { resolveGoogleSignInCredentials } from "./google-oauth-credentials.js";
66
- import { isElectron as isElectronRequest, getAppBasePath, getAppUrl, getOrigin, encodeOAuthState, decodeOAuthState, createOAuthSession, oauthCallbackResponse, oauthErrorPage, resolveOAuthRedirectUri, isAllowedOAuthRedirectUri, } from "./google-oauth.js";
66
+ import { isElectron as isElectronRequest, getAppBasePath, getAppUrl, getOrigin, encodeOAuthState, decodeOAuthState, createOAuthSession, oauthCallbackResponse, oauthDesktopExchangePage, oauthErrorPage, resolveOAuthRedirectUri, isAllowedOAuthRedirectUri, } from "./google-oauth.js";
67
67
  // Pure env-read feature switch from a leaf module (no dependency back on
68
68
  // auth.ts), so the guard and the SSO route handler share one validator and
69
69
  // can never disagree about whether federated SSO is enabled.
@@ -1025,6 +1025,8 @@ function areGenericGoogleOAuthRoutesEnabled(app) {
1025
1025
  }
1026
1026
  const _desktopExchanges = new Map();
1027
1027
  const DESKTOP_EXCHANGE_ERROR_PREFIX = "__error__::";
1028
+ const DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX = "__magic-link-challenge__::";
1029
+ const DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX = "__magic-link-exchange__::";
1028
1030
  const DESKTOP_AUTH_TOKEN_BODY_ORIGINS = new Set([
1029
1031
  "tauri://localhost",
1030
1032
  "http://tauri.localhost",
@@ -1033,6 +1035,90 @@ const DESKTOP_AUTH_TOKEN_BODY_ORIGINS = new Set([
1033
1035
  ]);
1034
1036
  // 5-minute TTL for exchange entries (short — single-use tokens).
1035
1037
  const DESKTOP_EXCHANGE_TTL_MS = 5 * 60 * 1000;
1038
+ function normalizeDesktopFlowId(value) {
1039
+ if (typeof value !== "string")
1040
+ return null;
1041
+ const flowId = value.trim();
1042
+ return /^[A-Za-z0-9_-]{1,128}$/.test(flowId) ? flowId : null;
1043
+ }
1044
+ function normalizeDesktopFlowVerifier(value) {
1045
+ if (typeof value !== "string")
1046
+ return null;
1047
+ const verifier = value.trim();
1048
+ return /^[A-Za-z0-9_-]{32,128}$/.test(verifier) ? verifier : null;
1049
+ }
1050
+ function desktopFlowVerifierHash(verifier) {
1051
+ return crypto.createHash("sha256").update(verifier).digest("base64url");
1052
+ }
1053
+ function matchesDesktopFlowVerifier(verifier, expectedHash) {
1054
+ const actual = Buffer.from(desktopFlowVerifierHash(verifier));
1055
+ const expected = Buffer.from(expectedHash);
1056
+ return (actual.length === expected.length &&
1057
+ crypto.timingSafeEqual(actual, expected));
1058
+ }
1059
+ function parseDesktopExchangeStoredEntry(packed) {
1060
+ if (packed.startsWith(DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX)) {
1061
+ const verifierHash = packed.slice(DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX.length);
1062
+ return verifierHash ? { challenge: true, verifierHash } : null;
1063
+ }
1064
+ if (packed.startsWith(DESKTOP_EXCHANGE_ERROR_PREFIX)) {
1065
+ const raw = packed.slice(DESKTOP_EXCHANGE_ERROR_PREFIX.length);
1066
+ return {
1067
+ error: JSON.parse(Buffer.from(raw, "base64url").toString()),
1068
+ };
1069
+ }
1070
+ const isMagicLinkExchange = packed.startsWith(DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX);
1071
+ const encoded = isMagicLinkExchange
1072
+ ? packed.slice(DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX.length)
1073
+ : packed;
1074
+ const verifierSeparator = isMagicLinkExchange ? encoded.indexOf("::") : -1;
1075
+ const verifierHash = verifierSeparator >= 0 ? encoded.slice(0, verifierSeparator) : undefined;
1076
+ const tokenAndEmail = verifierSeparator >= 0 ? encoded.slice(verifierSeparator + 2) : encoded;
1077
+ const sepIdx = tokenAndEmail.indexOf("::");
1078
+ if (sepIdx === -1)
1079
+ return null;
1080
+ return {
1081
+ token: tokenAndEmail.slice(0, sepIdx),
1082
+ email: tokenAndEmail.slice(sepIdx + 2),
1083
+ ...(verifierHash ? { verifierHash } : {}),
1084
+ };
1085
+ }
1086
+ function isDesktopMagicLinkCallbackPath(value) {
1087
+ try {
1088
+ return new URL(value, "http://agent-native.invalid").pathname.endsWith("/_agent-native/auth/magic-link/desktop-callback");
1089
+ }
1090
+ catch {
1091
+ // coercion-ok: malformed callback URLs are treated as non-desktop callbacks.
1092
+ return false;
1093
+ }
1094
+ }
1095
+ function withDesktopMagicLinkFlow(callbackURL, flow) {
1096
+ const url = new URL(callbackURL, "http://agent-native.invalid");
1097
+ url.searchParams.set("flow_id", flow.flowId);
1098
+ url.searchParams.set("verifier", flow.verifier);
1099
+ return `${url.pathname}${url.search}${url.hash}`;
1100
+ }
1101
+ async function persistDesktopMagicLinkChallenge(flowId, verifierHash) {
1102
+ await addSession(`dex:${flowId}`, `${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}${verifierHash}`);
1103
+ }
1104
+ async function issueDesktopMagicLinkFlow() {
1105
+ const flowId = crypto.randomBytes(32).toString("base64url");
1106
+ const verifier = crypto.randomBytes(32).toString("base64url");
1107
+ const verifierHash = desktopFlowVerifierHash(verifier);
1108
+ _desktopExchanges.set(flowId, {
1109
+ challenge: true,
1110
+ verifierHash,
1111
+ expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
1112
+ });
1113
+ try {
1114
+ await persistDesktopMagicLinkChallenge(flowId, verifierHash);
1115
+ }
1116
+ catch (error) {
1117
+ _desktopExchanges.delete(flowId);
1118
+ throw error;
1119
+ }
1120
+ return { flowId, verifier };
1121
+ }
1036
1122
  export function setDesktopExchange(flowId, token, email) {
1037
1123
  _desktopExchanges.set(flowId, {
1038
1124
  token,
@@ -1059,9 +1145,12 @@ export function setDesktopExchangeError(flowId, error) {
1059
1145
  * Non-fatal — if the DB isn't ready yet the in-memory Map still works for
1060
1146
  * same-instance requests.
1061
1147
  */
1062
- async function persistDesktopExchangeToDB(flowId, token, email) {
1148
+ async function persistDesktopExchangeToDB(flowId, token, email, verifierHash) {
1063
1149
  try {
1064
- await addSession(`dex:${flowId}`, `${token}::${email}`);
1150
+ const packed = verifierHash
1151
+ ? `${DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX}${verifierHash}::${token}::${email}`
1152
+ : `${token}::${email}`;
1153
+ await addSession(`dex:${flowId}`, packed);
1065
1154
  }
1066
1155
  catch {
1067
1156
  // non-fatal — in-memory Map is the primary path
@@ -1090,8 +1179,12 @@ async function consumeDesktopExchangeFromDB(flowId) {
1090
1179
  // redeemed with the session table's default 30-day TTL.
1091
1180
  const client = getDbExec();
1092
1181
  const { rows } = await client.execute({
1093
- sql: `DELETE FROM sessions WHERE token = ? AND created_at > ? RETURNING email`,
1094
- args: [`dex:${flowId}`, Date.now() - DESKTOP_EXCHANGE_TTL_MS],
1182
+ sql: `DELETE FROM sessions WHERE token = ? AND created_at > ? AND email NOT LIKE ? RETURNING email`,
1183
+ args: [
1184
+ `dex:${flowId}`,
1185
+ Date.now() - DESKTOP_EXCHANGE_TTL_MS,
1186
+ `${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}%`,
1187
+ ],
1095
1188
  });
1096
1189
  forgetCachedSessionEmail(`dex:${flowId}`);
1097
1190
  if (rows.length === 0)
@@ -1099,21 +1192,72 @@ async function consumeDesktopExchangeFromDB(flowId) {
1099
1192
  const packed = (rows[0].email ?? rows[0][0]);
1100
1193
  if (!packed)
1101
1194
  return null;
1102
- if (packed.startsWith(DESKTOP_EXCHANGE_ERROR_PREFIX)) {
1103
- const raw = packed.slice(DESKTOP_EXCHANGE_ERROR_PREFIX.length);
1104
- return {
1105
- error: JSON.parse(Buffer.from(raw, "base64url").toString()),
1106
- };
1107
- }
1108
- const sepIdx = packed.indexOf("::");
1109
- if (sepIdx === -1)
1195
+ return parseDesktopExchangeStoredEntry(packed);
1196
+ }
1197
+ catch {
1198
+ // coercion-ok: a DB fallback outage leaves the exchange pending so polling can retry without consuming a token.
1199
+ return null;
1200
+ }
1201
+ }
1202
+ async function readDesktopMagicLinkChallengeFromDB(flowId) {
1203
+ try {
1204
+ const client = getDbExec();
1205
+ const { rows } = await client.execute({
1206
+ sql: `SELECT email FROM sessions WHERE token = ? AND created_at > ? LIMIT 1`,
1207
+ args: [`dex:${flowId}`, Date.now() - DESKTOP_EXCHANGE_TTL_MS],
1208
+ });
1209
+ if (rows.length === 0)
1210
+ return null;
1211
+ const packed = (rows[0].email ?? rows[0][0]);
1212
+ if (!packed)
1110
1213
  return null;
1111
- return { token: packed.slice(0, sepIdx), email: packed.slice(sepIdx + 2) };
1214
+ const entry = parseDesktopExchangeStoredEntry(packed);
1215
+ return entry && "challenge" in entry
1216
+ ? { verifierHash: entry.verifierHash }
1217
+ : null;
1112
1218
  }
1113
1219
  catch {
1114
1220
  return null;
1115
1221
  }
1116
1222
  }
1223
+ async function claimDesktopMagicLinkFlow(flowId, verifier, token, email) {
1224
+ const verifierHash = desktopFlowVerifierHash(verifier);
1225
+ const entry = _desktopExchanges.get(flowId);
1226
+ if (entry) {
1227
+ if (!("challenge" in entry) ||
1228
+ entry.expiresAt < Date.now() ||
1229
+ !matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
1230
+ return false;
1231
+ }
1232
+ _desktopExchanges.set(flowId, {
1233
+ token,
1234
+ email,
1235
+ verifierHash,
1236
+ expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
1237
+ });
1238
+ await persistDesktopExchangeToDB(flowId, token, email, verifierHash);
1239
+ return true;
1240
+ }
1241
+ try {
1242
+ const client = getDbExec();
1243
+ const packed = `${DESKTOP_MAGIC_LINK_EXCHANGE_PREFIX}${verifierHash}::${token}::${email}`;
1244
+ const { rows } = await client.execute({
1245
+ sql: `UPDATE sessions SET email = ?, created_at = ? WHERE token = ? AND created_at > ? AND email = ? RETURNING email`,
1246
+ args: [
1247
+ packed,
1248
+ Date.now(),
1249
+ `dex:${flowId}`,
1250
+ Date.now() - DESKTOP_EXCHANGE_TTL_MS,
1251
+ `${DESKTOP_MAGIC_LINK_CHALLENGE_PREFIX}${verifierHash}`,
1252
+ ],
1253
+ });
1254
+ return rows.length > 0;
1255
+ }
1256
+ catch {
1257
+ // coercion-ok: a failed DB claim must not issue a native session token.
1258
+ return false;
1259
+ }
1260
+ }
1117
1261
  setInterval(() => {
1118
1262
  const now = Date.now();
1119
1263
  for (const [k, v] of _desktopExchanges) {
@@ -2640,15 +2784,7 @@ async function mountBetterAuthRoutes(app, options) {
2640
2784
  emailDomain: email.split("@")[1] || "",
2641
2785
  });
2642
2786
  if (flowId && sessionToken) {
2643
- _desktopExchanges.set(flowId, {
2644
- token: sessionToken,
2645
- email,
2646
- expiresAt: Date.now() + DESKTOP_EXCHANGE_TTL_MS,
2647
- });
2648
- // Also persist to DB for cross-instance durability (Cloudflare
2649
- // Workers, multi-region). Fire-and-forget — in-memory Map is
2650
- // still the primary fast path for same-instance requests.
2651
- void persistDesktopExchangeToDB(flowId, sessionToken, email);
2787
+ setDesktopExchange(flowId, sessionToken, email);
2652
2788
  logGoogleOAuthDebug(event, "callback-exchange-stored", {
2653
2789
  flowId,
2654
2790
  desktop,
@@ -2687,13 +2823,23 @@ async function mountBetterAuthRoutes(app, options) {
2687
2823
  return { error: "Method not allowed" };
2688
2824
  }
2689
2825
  const query = getQuery(event);
2690
- const flowId = query.flow_id;
2826
+ const flowId = normalizeDesktopFlowId(query.flow_id);
2691
2827
  if (!flowId) {
2692
2828
  setResponseStatus(event, 400);
2693
2829
  return { error: "Missing flow_id" };
2694
2830
  }
2831
+ const verifier = normalizeDesktopFlowVerifier(getQuery(event).verifier);
2695
2832
  let entry = _desktopExchanges.get(flowId);
2696
2833
  if (!entry || entry.expiresAt < Date.now()) {
2834
+ const challenge = await readDesktopMagicLinkChallengeFromDB(flowId);
2835
+ if (challenge) {
2836
+ if (!verifier ||
2837
+ !matchesDesktopFlowVerifier(verifier, challenge.verifierHash)) {
2838
+ setResponseStatus(event, 403);
2839
+ return { error: "Invalid desktop exchange verifier." };
2840
+ }
2841
+ return { pending: true, flow: oauthDebugFlowId(flowId) };
2842
+ }
2697
2843
  // In-memory miss — fall back to the DB-persisted entry. This handles
2698
2844
  // cross-instance routing (Cloudflare Workers, multi-region) where the
2699
2845
  // OAuth callback and the polling request may hit different isolates.
@@ -2709,11 +2855,35 @@ async function mountBetterAuthRoutes(app, options) {
2709
2855
  entry =
2710
2856
  "error" in fromDb
2711
2857
  ? { error: fromDb.error, expiresAt: Date.now() + 1 }
2712
- : {
2713
- token: fromDb.token,
2714
- email: fromDb.email,
2715
- expiresAt: Date.now() + 1,
2716
- };
2858
+ : "challenge" in fromDb
2859
+ ? {
2860
+ challenge: true,
2861
+ verifierHash: fromDb.verifierHash,
2862
+ expiresAt: Date.now() + 1,
2863
+ }
2864
+ : {
2865
+ token: fromDb.token,
2866
+ email: fromDb.email,
2867
+ ...(fromDb.verifierHash
2868
+ ? { verifierHash: fromDb.verifierHash }
2869
+ : {}),
2870
+ expiresAt: Date.now() + 1,
2871
+ };
2872
+ }
2873
+ if ("challenge" in entry) {
2874
+ if (!verifier ||
2875
+ !matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
2876
+ setResponseStatus(event, 403);
2877
+ return { error: "Invalid desktop exchange verifier." };
2878
+ }
2879
+ return { pending: true, flow: oauthDebugFlowId(flowId) };
2880
+ }
2881
+ if ("token" in entry && entry.verifierHash) {
2882
+ if (!verifier ||
2883
+ !matchesDesktopFlowVerifier(verifier, entry.verifierHash)) {
2884
+ setResponseStatus(event, 403);
2885
+ return { error: "Invalid desktop exchange verifier." };
2886
+ }
2717
2887
  }
2718
2888
  _desktopExchanges.delete(flowId);
2719
2889
  // Also wipe the DB-persisted entry so it cannot be replayed via the
@@ -2735,6 +2905,13 @@ async function mountBetterAuthRoutes(app, options) {
2735
2905
  // still make a follow-up /auth/session?_session=... request, but the
2736
2906
  // OAuth handoff should not depend on that second request succeeding.
2737
2907
  setFrameworkSessionCookie(event, entry.token);
2908
+ if (isElectronRequest(event)) {
2909
+ await writeDesktopSso({
2910
+ email: entry.email,
2911
+ token: entry.token,
2912
+ expiresAt: Date.now() + sessionMaxAge * 1000,
2913
+ });
2914
+ }
2738
2915
  setResponseHeader(event, "Referrer-Policy", "no-referrer");
2739
2916
  logGoogleOAuthDebug(event, "exchange-success", {
2740
2917
  flowId,
@@ -2742,6 +2919,52 @@ async function mountBetterAuthRoutes(app, options) {
2742
2919
  });
2743
2920
  return { token: entry.token, email: entry.email };
2744
2921
  }));
2922
+ // Magic-link verification happens in the system browser, so native shells
2923
+ // need the verified browser session copied into the same one-time exchange
2924
+ // used by Google OAuth before they can establish their own WebView session.
2925
+ app.use("/_agent-native/auth/magic-link/desktop-callback", defineEventHandler(async (event) => {
2926
+ if (!isReadMethod(event)) {
2927
+ setResponseStatus(event, 405);
2928
+ return { error: "Method not allowed" };
2929
+ }
2930
+ const flowId = normalizeDesktopFlowId(getQuery(event).flow_id);
2931
+ const verifier = normalizeDesktopFlowVerifier(getQuery(event).verifier);
2932
+ if (!flowId) {
2933
+ setResponseStatus(event, 400);
2934
+ return { error: "Missing flow_id" };
2935
+ }
2936
+ if (!verifier) {
2937
+ return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
2938
+ }
2939
+ const session = await getSession(event);
2940
+ if (!session?.email || !session.token) {
2941
+ setDesktopExchangeError(flowId, {
2942
+ message: AUTH_MAGIC_LINK_FALLBACK,
2943
+ code: "callback_error",
2944
+ });
2945
+ return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
2946
+ }
2947
+ try {
2948
+ // Better Auth owns the browser cookie, while native clients resolve
2949
+ // the exchanged token through the framework session table.
2950
+ await addSession(session.token, session.email);
2951
+ }
2952
+ catch (error) {
2953
+ captureAuthError(error, {
2954
+ route: "magic-link",
2955
+ email: session.email,
2956
+ });
2957
+ setDesktopExchangeError(flowId, {
2958
+ message: AUTH_MAGIC_LINK_FALLBACK,
2959
+ code: "callback_error",
2960
+ });
2961
+ return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
2962
+ }
2963
+ if (!(await claimDesktopMagicLinkFlow(flowId, verifier, session.token, session.email))) {
2964
+ return oauthErrorPage(AUTH_MAGIC_LINK_FALLBACK);
2965
+ }
2966
+ return oauthDesktopExchangePage("Sign-in complete. You can return to the app.");
2967
+ }));
2745
2968
  // Initialize Better Auth. Forward `googleScopes` into the BetterAuthConfig
2746
2969
  // so the social provider requests the broader product scopes (Gmail,
2747
2970
  // Calendar, etc.) up front during the primary sign-in — eliminating the
@@ -3050,9 +3273,10 @@ async function mountBetterAuthRoutes(app, options) {
3050
3273
  const body = await readBody(event);
3051
3274
  const rawEmail = typeof body?.email === "string" ? body.email : "";
3052
3275
  const email = normalizeAuthEmail(rawEmail);
3053
- const callbackURL = typeof body?.callbackURL === "string"
3276
+ let callbackURL = typeof body?.callbackURL === "string"
3054
3277
  ? safeReturnPath(body.callbackURL)
3055
3278
  : "/";
3279
+ let desktopFlow;
3056
3280
  if (!email) {
3057
3281
  setResponseStatus(event, 400);
3058
3282
  return { error: VALID_AUTH_EMAIL_MESSAGE };
@@ -3062,6 +3286,10 @@ async function mountBetterAuthRoutes(app, options) {
3062
3286
  return { error: GOOGLE_AUTH_REQUIRED_MESSAGE };
3063
3287
  }
3064
3288
  try {
3289
+ if (isDesktopMagicLinkCallbackPath(callbackURL)) {
3290
+ desktopFlow = await issueDesktopMagicLinkFlow();
3291
+ callbackURL = withDesktopMagicLinkFlow(callbackURL, desktopFlow);
3292
+ }
3065
3293
  await auth.api.signInMagicLink({
3066
3294
  body: {
3067
3295
  email,
@@ -3070,7 +3298,10 @@ async function mountBetterAuthRoutes(app, options) {
3070
3298
  },
3071
3299
  headers: event.headers,
3072
3300
  });
3073
- return { ok: true };
3301
+ return {
3302
+ ok: true,
3303
+ ...(desktopFlow ?? {}),
3304
+ };
3074
3305
  }
3075
3306
  catch (e) {
3076
3307
  if (!isExpectedAuthFailure(e)) {
@@ -253,3 +253,4 @@ export declare function resetBetterAuth(): Promise<void>;
253
253
  export declare function configureLocalSqlite(sqlite: {
254
254
  pragma(statement: string): unknown;
255
255
  }): void;
256
+ export declare function buildDatabaseConfig(dialect: string): Promise<BetterAuthOptions["database"]>;
@@ -16,7 +16,7 @@ import { pgTable, text as pgText, timestamp as pgTimestamp, boolean as pgBoolean
16
16
  import { sqliteTable, text as sqliteText, integer as sqliteInteger, } from "drizzle-orm/sqlite-core";
17
17
  import { TEMPLATES } from "../cli/templates-meta.js";
18
18
  import { getDbExec, isPostgres } from "../db/client.js";
19
- import { getDialect, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, guardNeonPool, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
19
+ import { getDialect, getCloudflareD1Binding, getDatabaseUrl, getDatabaseAuthToken, closePgliteClients, getPgliteClient, isPgliteUrl, loadPgliteDrizzle, pgPoolOptions, neonPoolOptions, guardNeonPool, sharedDbPool, onSharedDbPoolsClosed, onSharedDbPoolReplaced, } from "../db/client.js";
20
20
  import { CORE_RESET_PASSWORD_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, } from "../email-catalog/system-emails.js";
21
21
  import { saveOAuthTokens } from "../oauth-tokens/store.js";
22
22
  import { acceptPendingInvitationsForEmail } from "../org/accept-pending.js";
@@ -1126,7 +1126,7 @@ export function configureLocalSqlite(sqlite) {
1126
1126
  sqlite.pragma("busy_timeout = 10000");
1127
1127
  sqlite.pragma("journal_mode = WAL");
1128
1128
  }
1129
- async function buildDatabaseConfig(dialect) {
1129
+ export async function buildDatabaseConfig(dialect) {
1130
1130
  if (dialect === "postgres") {
1131
1131
  const url = getDatabaseUrl();
1132
1132
  const { buildResilientNeonPool, buildResilientPostgresJsClient, isNeonUrl, } = await import("../db/create-get-db.js");
@@ -1180,6 +1180,21 @@ async function buildDatabaseConfig(dialect) {
1180
1180
  schema: pgAuthSchema,
1181
1181
  });
1182
1182
  }
1183
+ if (dialect === "d1") {
1184
+ const d1 = getCloudflareD1Binding();
1185
+ if (!d1) {
1186
+ throw new Error("Cloudflare D1 database binding is unavailable; configure the DB binding before initializing Better Auth.");
1187
+ }
1188
+ const { drizzle } = await import("drizzle-orm/d1");
1189
+ const db = drizzle(d1, {
1190
+ schema: sqliteAuthSchema,
1191
+ });
1192
+ const { drizzleAdapter } = await import("better-auth/adapters/drizzle");
1193
+ return drizzleAdapter(db, {
1194
+ provider: "sqlite",
1195
+ schema: sqliteAuthSchema,
1196
+ });
1197
+ }
1183
1198
  // SQLite / libsql
1184
1199
  const url = getDatabaseUrl("file:./data/app.db");
1185
1200
  if (url.startsWith("file:") || !url.includes("://")) {