@agent-native/core 0.14.8 → 0.15.1

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 (544) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  3. package/dist/agent/engine/builder-engine.js +30 -9
  4. package/dist/agent/engine/builder-engine.js.map +1 -1
  5. package/dist/agent/engine/registry.d.ts.map +1 -1
  6. package/dist/agent/engine/registry.js +14 -4
  7. package/dist/agent/engine/registry.js.map +1 -1
  8. package/dist/agent/production-agent.d.ts.map +1 -1
  9. package/dist/agent/production-agent.js +71 -4
  10. package/dist/agent/production-agent.js.map +1 -1
  11. package/dist/agent/types.d.ts +9 -0
  12. package/dist/agent/types.d.ts.map +1 -1
  13. package/dist/agent/types.js.map +1 -1
  14. package/dist/appearance/actions/change-appearance.d.ts +3 -0
  15. package/dist/appearance/actions/change-appearance.d.ts.map +1 -0
  16. package/dist/appearance/actions/change-appearance.js +29 -0
  17. package/dist/appearance/actions/change-appearance.js.map +1 -0
  18. package/dist/chat-threads/store.d.ts +53 -2
  19. package/dist/chat-threads/store.d.ts.map +1 -1
  20. package/dist/chat-threads/store.js +172 -12
  21. package/dist/chat-threads/store.js.map +1 -1
  22. package/dist/cli/create.d.ts.map +1 -1
  23. package/dist/cli/create.js +114 -37
  24. package/dist/cli/create.js.map +1 -1
  25. package/dist/cli/index.js +30 -4
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/cli/workspace-dev.d.ts +25 -1
  28. package/dist/cli/workspace-dev.d.ts.map +1 -1
  29. package/dist/cli/workspace-dev.js +275 -49
  30. package/dist/cli/workspace-dev.js.map +1 -1
  31. package/dist/client/AgentPanel.d.ts +23 -4
  32. package/dist/client/AgentPanel.d.ts.map +1 -1
  33. package/dist/client/AgentPanel.js +276 -53
  34. package/dist/client/AgentPanel.js.map +1 -1
  35. package/dist/client/AppearancePicker.d.ts +11 -0
  36. package/dist/client/AppearancePicker.d.ts.map +1 -0
  37. package/dist/client/AppearancePicker.js +16 -0
  38. package/dist/client/AppearancePicker.js.map +1 -0
  39. package/dist/client/AssistantChat.d.ts +35 -0
  40. package/dist/client/AssistantChat.d.ts.map +1 -1
  41. package/dist/client/AssistantChat.js +315 -32
  42. package/dist/client/AssistantChat.js.map +1 -1
  43. package/dist/client/ConnectBuilderCard.d.ts.map +1 -1
  44. package/dist/client/ConnectBuilderCard.js +5 -2
  45. package/dist/client/ConnectBuilderCard.js.map +1 -1
  46. package/dist/client/ErrorBoundary.d.ts.map +1 -1
  47. package/dist/client/ErrorBoundary.js +8 -10
  48. package/dist/client/ErrorBoundary.js.map +1 -1
  49. package/dist/client/FeedbackButton.d.ts.map +1 -1
  50. package/dist/client/FeedbackButton.js +1 -1
  51. package/dist/client/FeedbackButton.js.map +1 -1
  52. package/dist/client/MultiTabAssistantChat.d.ts +13 -1
  53. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  54. package/dist/client/MultiTabAssistantChat.js +217 -38
  55. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  56. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  57. package/dist/client/NewWorkspaceAppFlow.js +37 -14
  58. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  59. package/dist/client/agent-chat-adapter.d.ts +5 -0
  60. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  61. package/dist/client/agent-chat-adapter.js +4 -0
  62. package/dist/client/agent-chat-adapter.js.map +1 -1
  63. package/dist/client/agent-sidebar-state.d.ts +12 -0
  64. package/dist/client/agent-sidebar-state.d.ts.map +1 -1
  65. package/dist/client/agent-sidebar-state.js +8 -0
  66. package/dist/client/agent-sidebar-state.js.map +1 -1
  67. package/dist/client/analytics.d.ts.map +1 -1
  68. package/dist/client/analytics.js +175 -3
  69. package/dist/client/analytics.js.map +1 -1
  70. package/dist/client/appearance.d.ts +40 -0
  71. package/dist/client/appearance.d.ts.map +1 -0
  72. package/dist/client/appearance.js +114 -0
  73. package/dist/client/appearance.js.map +1 -0
  74. package/dist/client/builder-frame.d.ts +1 -0
  75. package/dist/client/builder-frame.d.ts.map +1 -1
  76. package/dist/client/builder-frame.js +19 -9
  77. package/dist/client/builder-frame.js.map +1 -1
  78. package/dist/client/components/CodeRequiredDialog.d.ts.map +1 -1
  79. package/dist/client/components/CodeRequiredDialog.js +10 -2
  80. package/dist/client/components/CodeRequiredDialog.js.map +1 -1
  81. package/dist/client/components/ui/dropdown-menu.js +2 -2
  82. package/dist/client/components/ui/dropdown-menu.js.map +1 -1
  83. package/dist/client/components/ui/hover-card.js +1 -1
  84. package/dist/client/components/ui/hover-card.js.map +1 -1
  85. package/dist/client/components/ui/popover.js +1 -1
  86. package/dist/client/components/ui/popover.js.map +1 -1
  87. package/dist/client/composer/PromptComposer.d.ts +7 -0
  88. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  89. package/dist/client/composer/PromptComposer.js +63 -32
  90. package/dist/client/composer/PromptComposer.js.map +1 -1
  91. package/dist/client/composer/TiptapComposer.d.ts +5 -0
  92. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  93. package/dist/client/composer/TiptapComposer.js +36 -6
  94. package/dist/client/composer/TiptapComposer.js.map +1 -1
  95. package/dist/client/composer/useVoiceDictation.d.ts.map +1 -1
  96. package/dist/client/composer/useVoiceDictation.js +13 -1
  97. package/dist/client/composer/useVoiceDictation.js.map +1 -1
  98. package/dist/client/dev-mode.d.ts +14 -0
  99. package/dist/client/dev-mode.d.ts.map +1 -0
  100. package/dist/client/dev-mode.js +14 -0
  101. package/dist/client/dev-mode.js.map +1 -0
  102. package/dist/client/error-format.d.ts +3 -2
  103. package/dist/client/error-format.d.ts.map +1 -1
  104. package/dist/client/error-format.js +9 -2
  105. package/dist/client/error-format.js.map +1 -1
  106. package/dist/client/extensions/EmbeddedTool.d.ts +20 -0
  107. package/dist/client/extensions/EmbeddedTool.d.ts.map +1 -0
  108. package/dist/client/extensions/EmbeddedTool.js +199 -0
  109. package/dist/client/extensions/EmbeddedTool.js.map +1 -0
  110. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  111. package/dist/client/extensions/ExtensionViewer.js +24 -2
  112. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  113. package/dist/client/extensions/ToolEditor.d.ts +5 -0
  114. package/dist/client/extensions/ToolEditor.d.ts.map +1 -0
  115. package/dist/client/extensions/ToolEditor.js +129 -0
  116. package/dist/client/extensions/ToolEditor.js.map +1 -0
  117. package/dist/client/extensions/ToolViewer.d.ts +5 -0
  118. package/dist/client/extensions/ToolViewer.d.ts.map +1 -0
  119. package/dist/client/extensions/ToolViewer.js +400 -0
  120. package/dist/client/extensions/ToolViewer.js.map +1 -0
  121. package/dist/client/extensions/ToolViewerPage.d.ts +2 -0
  122. package/dist/client/extensions/ToolViewerPage.d.ts.map +1 -0
  123. package/dist/client/extensions/ToolViewerPage.js +24 -0
  124. package/dist/client/extensions/ToolViewerPage.js.map +1 -0
  125. package/dist/client/extensions/ToolsListPage.d.ts +2 -0
  126. package/dist/client/extensions/ToolsListPage.d.ts.map +1 -0
  127. package/dist/client/extensions/ToolsListPage.js +67 -0
  128. package/dist/client/extensions/ToolsListPage.js.map +1 -0
  129. package/dist/client/extensions/ToolsSidebarSection.d.ts +2 -0
  130. package/dist/client/extensions/ToolsSidebarSection.d.ts.map +1 -0
  131. package/dist/client/extensions/ToolsSidebarSection.js +236 -0
  132. package/dist/client/extensions/ToolsSidebarSection.js.map +1 -0
  133. package/dist/client/extensions/tool-order.d.ts +7 -0
  134. package/dist/client/extensions/tool-order.d.ts.map +1 -0
  135. package/dist/client/extensions/tool-order.js +47 -0
  136. package/dist/client/extensions/tool-order.js.map +1 -0
  137. package/dist/client/index.d.ts +8 -1
  138. package/dist/client/index.d.ts.map +1 -1
  139. package/dist/client/index.js +7 -0
  140. package/dist/client/index.js.map +1 -1
  141. package/dist/client/onboarding/OnboardingPanel.js +1 -0
  142. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  143. package/dist/client/org/InvitationBanner.d.ts.map +1 -1
  144. package/dist/client/org/InvitationBanner.js +23 -2
  145. package/dist/client/org/InvitationBanner.js.map +1 -1
  146. package/dist/client/org/OrgSwitcher.d.ts +5 -4
  147. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  148. package/dist/client/org/OrgSwitcher.js +57 -9
  149. package/dist/client/org/OrgSwitcher.js.map +1 -1
  150. package/dist/client/org/hooks.d.ts.map +1 -1
  151. package/dist/client/org/hooks.js +10 -6
  152. package/dist/client/org/hooks.js.map +1 -1
  153. package/dist/client/org/workspace-app-links.d.ts +31 -0
  154. package/dist/client/org/workspace-app-links.d.ts.map +1 -0
  155. package/dist/client/org/workspace-app-links.js +268 -0
  156. package/dist/client/org/workspace-app-links.js.map +1 -0
  157. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  158. package/dist/client/resources/ResourcesPanel.js +18 -5
  159. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  160. package/dist/client/resources/use-resources.d.ts +18 -13
  161. package/dist/client/resources/use-resources.d.ts.map +1 -1
  162. package/dist/client/resources/use-resources.js +24 -6
  163. package/dist/client/resources/use-resources.js.map +1 -1
  164. package/dist/client/settings/BackgroundAgentSection.d.ts.map +1 -1
  165. package/dist/client/settings/BackgroundAgentSection.js +9 -1
  166. package/dist/client/settings/BackgroundAgentSection.js.map +1 -1
  167. package/dist/client/settings/BrowserSection.d.ts.map +1 -1
  168. package/dist/client/settings/BrowserSection.js +16 -1
  169. package/dist/client/settings/BrowserSection.js.map +1 -1
  170. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  171. package/dist/client/settings/SettingsPanel.js +4 -1
  172. package/dist/client/settings/SettingsPanel.js.map +1 -1
  173. package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
  174. package/dist/client/settings/VoiceTranscriptionSection.js +5 -5
  175. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  176. package/dist/client/settings/useBuilderStatus.d.ts +8 -0
  177. package/dist/client/settings/useBuilderStatus.d.ts.map +1 -1
  178. package/dist/client/settings/useBuilderStatus.js +50 -13
  179. package/dist/client/settings/useBuilderStatus.js.map +1 -1
  180. package/dist/client/settings/useBuilderStatus.spec.d.ts +2 -0
  181. package/dist/client/settings/useBuilderStatus.spec.d.ts.map +1 -0
  182. package/dist/client/settings/useBuilderStatus.spec.js +64 -0
  183. package/dist/client/settings/useBuilderStatus.spec.js.map +1 -0
  184. package/dist/client/sharing/ShareButton.d.ts +5 -0
  185. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  186. package/dist/client/sharing/ShareButton.js +60 -6
  187. package/dist/client/sharing/ShareButton.js.map +1 -1
  188. package/dist/client/theme.js +1 -1
  189. package/dist/client/theme.js.map +1 -1
  190. package/dist/client/tools/EmbeddedTool.d.ts +20 -0
  191. package/dist/client/tools/EmbeddedTool.d.ts.map +1 -0
  192. package/dist/client/tools/EmbeddedTool.js +199 -0
  193. package/dist/client/tools/EmbeddedTool.js.map +1 -0
  194. package/dist/client/tools/ExtensionSlot.d.ts +27 -0
  195. package/dist/client/tools/ExtensionSlot.d.ts.map +1 -0
  196. package/dist/client/tools/ExtensionSlot.js +96 -0
  197. package/dist/client/tools/ExtensionSlot.js.map +1 -0
  198. package/dist/client/tools/ToolEditor.d.ts +5 -0
  199. package/dist/client/tools/ToolEditor.d.ts.map +1 -0
  200. package/dist/client/tools/ToolEditor.js +129 -0
  201. package/dist/client/tools/ToolEditor.js.map +1 -0
  202. package/dist/client/tools/ToolViewer.d.ts +5 -0
  203. package/dist/client/tools/ToolViewer.d.ts.map +1 -0
  204. package/dist/client/tools/ToolViewer.js +400 -0
  205. package/dist/client/tools/ToolViewer.js.map +1 -0
  206. package/dist/client/tools/ToolViewerPage.d.ts +2 -0
  207. package/dist/client/tools/ToolViewerPage.d.ts.map +1 -0
  208. package/dist/client/tools/ToolViewerPage.js +24 -0
  209. package/dist/client/tools/ToolViewerPage.js.map +1 -0
  210. package/dist/client/tools/ToolsListPage.d.ts +2 -0
  211. package/dist/client/tools/ToolsListPage.d.ts.map +1 -0
  212. package/dist/client/tools/ToolsListPage.js +67 -0
  213. package/dist/client/tools/ToolsListPage.js.map +1 -0
  214. package/dist/client/tools/ToolsSidebarSection.d.ts +2 -0
  215. package/dist/client/tools/ToolsSidebarSection.d.ts.map +1 -0
  216. package/dist/client/tools/ToolsSidebarSection.js +236 -0
  217. package/dist/client/tools/ToolsSidebarSection.js.map +1 -0
  218. package/dist/client/tools/iframe-bridge.d.ts +38 -0
  219. package/dist/client/tools/iframe-bridge.d.ts.map +1 -0
  220. package/dist/client/tools/iframe-bridge.js +207 -0
  221. package/dist/client/tools/iframe-bridge.js.map +1 -0
  222. package/dist/client/tools/index.d.ts +8 -0
  223. package/dist/client/tools/index.d.ts.map +1 -0
  224. package/dist/client/tools/index.js +8 -0
  225. package/dist/client/tools/index.js.map +1 -0
  226. package/dist/client/tools/tool-order.d.ts +7 -0
  227. package/dist/client/tools/tool-order.d.ts.map +1 -0
  228. package/dist/client/tools/tool-order.js +47 -0
  229. package/dist/client/tools/tool-order.js.map +1 -0
  230. package/dist/client/transcription/BuilderTranscriptionCta.d.ts.map +1 -1
  231. package/dist/client/transcription/BuilderTranscriptionCta.js +2 -3
  232. package/dist/client/transcription/BuilderTranscriptionCta.js.map +1 -1
  233. package/dist/client/use-change-version.d.ts +46 -0
  234. package/dist/client/use-change-version.d.ts.map +1 -0
  235. package/dist/client/use-change-version.js +135 -0
  236. package/dist/client/use-change-version.js.map +1 -0
  237. package/dist/client/use-chat-threads.d.ts +16 -2
  238. package/dist/client/use-chat-threads.d.ts.map +1 -1
  239. package/dist/client/use-chat-threads.js +87 -12
  240. package/dist/client/use-chat-threads.js.map +1 -1
  241. package/dist/client/use-chat-threads.spec.d.ts +2 -0
  242. package/dist/client/use-chat-threads.spec.d.ts.map +1 -0
  243. package/dist/client/use-chat-threads.spec.js +85 -0
  244. package/dist/client/use-chat-threads.spec.js.map +1 -0
  245. package/dist/client/use-db-sync.d.ts +5 -2
  246. package/dist/client/use-db-sync.d.ts.map +1 -1
  247. package/dist/client/use-db-sync.js +41 -16
  248. package/dist/client/use-db-sync.js.map +1 -1
  249. package/dist/client/use-pinch-zoom.d.ts +35 -0
  250. package/dist/client/use-pinch-zoom.d.ts.map +1 -0
  251. package/dist/client/use-pinch-zoom.js +105 -0
  252. package/dist/client/use-pinch-zoom.js.map +1 -0
  253. package/dist/deploy/workspace-deploy.d.ts.map +1 -1
  254. package/dist/deploy/workspace-deploy.js +99 -5
  255. package/dist/deploy/workspace-deploy.js.map +1 -1
  256. package/dist/extensions/actions.d.ts.map +1 -1
  257. package/dist/extensions/actions.js +3 -0
  258. package/dist/extensions/actions.js.map +1 -1
  259. package/dist/extensions/store.d.ts +5 -0
  260. package/dist/extensions/store.d.ts.map +1 -1
  261. package/dist/extensions/store.js +16 -1
  262. package/dist/extensions/store.js.map +1 -1
  263. package/dist/file-upload/actions/upload-image.d.ts +3 -0
  264. package/dist/file-upload/actions/upload-image.d.ts.map +1 -0
  265. package/dist/file-upload/actions/upload-image.js +145 -0
  266. package/dist/file-upload/actions/upload-image.js.map +1 -0
  267. package/dist/file-upload/builder.d.ts.map +1 -1
  268. package/dist/file-upload/builder.js +31 -11
  269. package/dist/file-upload/builder.js.map +1 -1
  270. package/dist/file-upload/index.d.ts +1 -0
  271. package/dist/file-upload/index.d.ts.map +1 -1
  272. package/dist/file-upload/index.js +1 -0
  273. package/dist/file-upload/index.js.map +1 -1
  274. package/dist/file-upload/pre-upload-attachments.d.ts +39 -0
  275. package/dist/file-upload/pre-upload-attachments.d.ts.map +1 -0
  276. package/dist/file-upload/pre-upload-attachments.js +110 -0
  277. package/dist/file-upload/pre-upload-attachments.js.map +1 -0
  278. package/dist/file-upload/registry.d.ts.map +1 -1
  279. package/dist/file-upload/registry.js +8 -7
  280. package/dist/file-upload/registry.js.map +1 -1
  281. package/dist/onboarding/default-steps.js +1 -1
  282. package/dist/onboarding/default-steps.js.map +1 -1
  283. package/dist/org/context.d.ts +15 -1
  284. package/dist/org/context.d.ts.map +1 -1
  285. package/dist/org/context.js +25 -0
  286. package/dist/org/context.js.map +1 -1
  287. package/dist/org/handlers.d.ts +2 -2
  288. package/dist/org/handlers.d.ts.map +1 -1
  289. package/dist/org/handlers.js +3 -17
  290. package/dist/org/handlers.js.map +1 -1
  291. package/dist/org/index.d.ts +1 -1
  292. package/dist/org/index.d.ts.map +1 -1
  293. package/dist/org/index.js +1 -1
  294. package/dist/org/index.js.map +1 -1
  295. package/dist/resources/handlers.d.ts +6 -0
  296. package/dist/resources/handlers.d.ts.map +1 -1
  297. package/dist/resources/handlers.js +30 -6
  298. package/dist/resources/handlers.js.map +1 -1
  299. package/dist/resources/script-helpers.d.ts +11 -2
  300. package/dist/resources/script-helpers.d.ts.map +1 -1
  301. package/dist/resources/script-helpers.js +20 -3
  302. package/dist/resources/script-helpers.js.map +1 -1
  303. package/dist/resources/store.d.ts +28 -3
  304. package/dist/resources/store.d.ts.map +1 -1
  305. package/dist/resources/store.js +170 -20
  306. package/dist/resources/store.js.map +1 -1
  307. package/dist/scripts/resources/list.d.ts +1 -1
  308. package/dist/scripts/resources/list.d.ts.map +1 -1
  309. package/dist/scripts/resources/list.js +16 -4
  310. package/dist/scripts/resources/list.js.map +1 -1
  311. package/dist/scripts/resources/write.d.ts +1 -1
  312. package/dist/scripts/resources/write.d.ts.map +1 -1
  313. package/dist/scripts/resources/write.js +47 -3
  314. package/dist/scripts/resources/write.js.map +1 -1
  315. package/dist/server/action-discovery.d.ts.map +1 -1
  316. package/dist/server/action-discovery.js +8 -3
  317. package/dist/server/action-discovery.js.map +1 -1
  318. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  319. package/dist/server/agent-chat-plugin.js +214 -25
  320. package/dist/server/agent-chat-plugin.js.map +1 -1
  321. package/dist/server/agent-discovery.d.ts +35 -0
  322. package/dist/server/agent-discovery.d.ts.map +1 -1
  323. package/dist/server/agent-discovery.js +139 -8
  324. package/dist/server/agent-discovery.js.map +1 -1
  325. package/dist/server/app-url.d.ts +12 -6
  326. package/dist/server/app-url.d.ts.map +1 -1
  327. package/dist/server/app-url.js +58 -11
  328. package/dist/server/app-url.js.map +1 -1
  329. package/dist/server/auth.d.ts +22 -0
  330. package/dist/server/auth.d.ts.map +1 -1
  331. package/dist/server/auth.js +316 -65
  332. package/dist/server/auth.js.map +1 -1
  333. package/dist/server/better-auth-instance.d.ts +0 -4
  334. package/dist/server/better-auth-instance.d.ts.map +1 -1
  335. package/dist/server/better-auth-instance.js +0 -3
  336. package/dist/server/better-auth-instance.js.map +1 -1
  337. package/dist/server/builder-browser.d.ts.map +1 -1
  338. package/dist/server/builder-browser.js +23 -0
  339. package/dist/server/builder-browser.js.map +1 -1
  340. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  341. package/dist/server/core-routes-plugin.js +29 -14
  342. package/dist/server/core-routes-plugin.js.map +1 -1
  343. package/dist/server/credential-provider.d.ts +14 -0
  344. package/dist/server/credential-provider.d.ts.map +1 -1
  345. package/dist/server/credential-provider.js +88 -11
  346. package/dist/server/credential-provider.js.map +1 -1
  347. package/dist/server/google-auth-plugin.d.ts.map +1 -1
  348. package/dist/server/google-auth-plugin.js +65 -17
  349. package/dist/server/google-auth-plugin.js.map +1 -1
  350. package/dist/server/google-oauth.d.ts.map +1 -1
  351. package/dist/server/google-oauth.js +47 -17
  352. package/dist/server/google-oauth.js.map +1 -1
  353. package/dist/server/index.d.ts +1 -1
  354. package/dist/server/index.d.ts.map +1 -1
  355. package/dist/server/index.js +1 -1
  356. package/dist/server/index.js.map +1 -1
  357. package/dist/server/local-migration.d.ts +41 -0
  358. package/dist/server/local-migration.d.ts.map +1 -0
  359. package/dist/server/local-migration.js +235 -0
  360. package/dist/server/local-migration.js.map +1 -0
  361. package/dist/server/oauth-public-origin.d.ts.map +1 -1
  362. package/dist/server/oauth-public-origin.js +19 -1
  363. package/dist/server/oauth-public-origin.js.map +1 -1
  364. package/dist/server/onboarding-html.d.ts.map +1 -1
  365. package/dist/server/onboarding-html.js +74 -19
  366. package/dist/server/onboarding-html.js.map +1 -1
  367. package/dist/server/poll.d.ts.map +1 -1
  368. package/dist/server/poll.js +20 -5
  369. package/dist/server/poll.js.map +1 -1
  370. package/dist/server/request-context.d.ts +8 -0
  371. package/dist/server/request-context.d.ts.map +1 -1
  372. package/dist/server/request-context.js.map +1 -1
  373. package/dist/shared/index.d.ts +2 -0
  374. package/dist/shared/index.d.ts.map +1 -1
  375. package/dist/shared/index.js +2 -0
  376. package/dist/shared/index.js.map +1 -1
  377. package/dist/shared/llm-connection.d.ts +10 -0
  378. package/dist/shared/llm-connection.d.ts.map +1 -0
  379. package/dist/shared/llm-connection.js +29 -0
  380. package/dist/shared/llm-connection.js.map +1 -0
  381. package/dist/shared/workspace-app-audience.d.ts +25 -0
  382. package/dist/shared/workspace-app-audience.d.ts.map +1 -0
  383. package/dist/shared/workspace-app-audience.js +126 -0
  384. package/dist/shared/workspace-app-audience.js.map +1 -0
  385. package/dist/shared/workspace-app-id.d.ts +1 -1
  386. package/dist/shared/workspace-app-id.d.ts.map +1 -1
  387. package/dist/shared/workspace-app-id.js +1 -0
  388. package/dist/shared/workspace-app-id.js.map +1 -1
  389. package/dist/sharing/access.d.ts.map +1 -1
  390. package/dist/sharing/access.js +46 -5
  391. package/dist/sharing/access.js.map +1 -1
  392. package/dist/sharing/actions/list-resource-shares.d.ts.map +1 -1
  393. package/dist/sharing/actions/list-resource-shares.js +8 -1
  394. package/dist/sharing/actions/list-resource-shares.js.map +1 -1
  395. package/dist/sharing/actions/set-resource-visibility.d.ts.map +1 -1
  396. package/dist/sharing/actions/set-resource-visibility.js +12 -3
  397. package/dist/sharing/actions/set-resource-visibility.js.map +1 -1
  398. package/dist/sharing/actions/share-resource.d.ts.map +1 -1
  399. package/dist/sharing/actions/share-resource.js +50 -1
  400. package/dist/sharing/actions/share-resource.js.map +1 -1
  401. package/dist/sharing/registry.d.ts +26 -0
  402. package/dist/sharing/registry.d.ts.map +1 -1
  403. package/dist/sharing/registry.js.map +1 -1
  404. package/dist/styles/agent-native.css +91 -0
  405. package/dist/templates/default/.agents/skills/adding-a-feature/SKILL.md +72 -0
  406. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +60 -37
  407. package/dist/templates/default/.agents/skills/real-time-sync/SKILL.md +28 -17
  408. package/dist/templates/default/.agents/skills/shadcn-ui/SKILL.md +79 -0
  409. package/dist/templates/default/AGENTS.md +22 -19
  410. package/dist/templates/default/actions/navigate.ts +3 -0
  411. package/dist/templates/default/app/hooks/use-navigation-state.ts +29 -5
  412. package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +251 -0
  413. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +264 -0
  414. package/dist/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +130 -0
  415. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +112 -0
  416. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +88 -0
  417. package/dist/templates/workspace-core/.agents/skills/automations/SKILL.md +191 -0
  418. package/dist/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +74 -0
  419. package/dist/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +75 -0
  420. package/dist/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +190 -0
  421. package/dist/templates/workspace-core/.agents/skills/create-skill/SKILL.md +168 -0
  422. package/dist/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +163 -0
  423. package/dist/templates/workspace-core/.agents/skills/extension-points/SKILL.md +205 -0
  424. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +720 -0
  425. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +92 -0
  426. package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +285 -0
  427. package/dist/templates/workspace-core/.agents/skills/observability/SKILL.md +192 -0
  428. package/dist/templates/workspace-core/.agents/skills/onboarding/SKILL.md +43 -0
  429. package/dist/templates/workspace-core/.agents/skills/portability/SKILL.md +84 -0
  430. package/dist/templates/workspace-core/.agents/skills/qa/SKILL.md +313 -0
  431. package/dist/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +112 -0
  432. package/dist/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +165 -0
  433. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +41 -0
  434. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +239 -0
  435. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +191 -0
  436. package/dist/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +79 -0
  437. package/dist/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +73 -0
  438. package/dist/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +79 -0
  439. package/dist/templates/workspace-core/.agents/skills/sharing/SKILL.md +217 -0
  440. package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +132 -0
  441. package/dist/templates/workspace-core/.agents/skills/tracking/SKILL.md +150 -0
  442. package/dist/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +124 -0
  443. package/dist/templates/workspace-core/AGENTS.md +16 -1
  444. package/dist/templates/workspace-root/AGENTS.md +35 -0
  445. package/dist/templates/workspace-root/README.md +7 -0
  446. package/dist/tools/actions.d.ts +3 -0
  447. package/dist/tools/actions.d.ts.map +1 -0
  448. package/dist/tools/actions.js +272 -0
  449. package/dist/tools/actions.js.map +1 -0
  450. package/dist/tools/fetch-tool.d.ts +23 -0
  451. package/dist/tools/fetch-tool.d.ts.map +1 -0
  452. package/dist/tools/fetch-tool.js +178 -0
  453. package/dist/tools/fetch-tool.js.map +1 -0
  454. package/dist/tools/html-shell.d.ts +45 -0
  455. package/dist/tools/html-shell.d.ts.map +1 -0
  456. package/dist/tools/html-shell.js +514 -0
  457. package/dist/tools/html-shell.js.map +1 -0
  458. package/dist/tools/proxy-security.d.ts +12 -0
  459. package/dist/tools/proxy-security.d.ts.map +1 -0
  460. package/dist/tools/proxy-security.js +158 -0
  461. package/dist/tools/proxy-security.js.map +1 -0
  462. package/dist/tools/routes.d.ts +2 -0
  463. package/dist/tools/routes.d.ts.map +1 -0
  464. package/dist/tools/routes.js +627 -0
  465. package/dist/tools/routes.js.map +1 -0
  466. package/dist/tools/schema.d.ts +664 -0
  467. package/dist/tools/schema.d.ts.map +1 -0
  468. package/dist/tools/schema.js +146 -0
  469. package/dist/tools/schema.js.map +1 -0
  470. package/dist/tools/slots/routes.d.ts +15 -0
  471. package/dist/tools/slots/routes.d.ts.map +1 -0
  472. package/dist/tools/slots/routes.js +94 -0
  473. package/dist/tools/slots/routes.js.map +1 -0
  474. package/dist/tools/slots/schema.d.ts +303 -0
  475. package/dist/tools/slots/schema.d.ts.map +1 -0
  476. package/dist/tools/slots/schema.js +76 -0
  477. package/dist/tools/slots/schema.js.map +1 -0
  478. package/dist/tools/slots/store.d.ts +66 -0
  479. package/dist/tools/slots/store.d.ts.map +1 -0
  480. package/dist/tools/slots/store.js +227 -0
  481. package/dist/tools/slots/store.js.map +1 -0
  482. package/dist/tools/store.d.ts +40 -0
  483. package/dist/tools/store.d.ts.map +1 -0
  484. package/dist/tools/store.js +193 -0
  485. package/dist/tools/store.js.map +1 -0
  486. package/dist/tools/theme.d.ts +2 -0
  487. package/dist/tools/theme.d.ts.map +1 -0
  488. package/dist/tools/theme.js +67 -0
  489. package/dist/tools/theme.js.map +1 -0
  490. package/dist/tools/url-safety.d.ts +24 -0
  491. package/dist/tools/url-safety.d.ts.map +1 -0
  492. package/dist/tools/url-safety.js +224 -0
  493. package/dist/tools/url-safety.js.map +1 -0
  494. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  495. package/dist/vite/action-types-plugin.js +4 -0
  496. package/dist/vite/action-types-plugin.js.map +1 -1
  497. package/docs/content/authentication.md +36 -0
  498. package/docs/content/creating-templates.md +15 -0
  499. package/docs/content/dispatch.md +3 -3
  500. package/docs/content/multi-app-workspace.md +5 -0
  501. package/docs/content/tracking.md +12 -0
  502. package/docs/content/workspace-management.md +39 -4
  503. package/package.json +15 -12
  504. package/src/templates/default/.agents/skills/adding-a-feature/SKILL.md +72 -0
  505. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +60 -37
  506. package/src/templates/default/.agents/skills/real-time-sync/SKILL.md +28 -17
  507. package/src/templates/default/.agents/skills/shadcn-ui/SKILL.md +79 -0
  508. package/src/templates/default/AGENTS.md +22 -19
  509. package/src/templates/default/actions/navigate.ts +3 -0
  510. package/src/templates/default/app/hooks/use-navigation-state.ts +29 -5
  511. package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +251 -0
  512. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +264 -0
  513. package/src/templates/workspace-core/.agents/skills/adding-a-feature/SKILL.md +130 -0
  514. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +112 -0
  515. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +88 -0
  516. package/src/templates/workspace-core/.agents/skills/automations/SKILL.md +191 -0
  517. package/src/templates/workspace-core/.agents/skills/capture-learnings/SKILL.md +74 -0
  518. package/src/templates/workspace-core/.agents/skills/client-side-routing/SKILL.md +75 -0
  519. package/src/templates/workspace-core/.agents/skills/context-awareness/SKILL.md +190 -0
  520. package/src/templates/workspace-core/.agents/skills/create-skill/SKILL.md +168 -0
  521. package/src/templates/workspace-core/.agents/skills/delegate-to-agent/SKILL.md +163 -0
  522. package/src/templates/workspace-core/.agents/skills/extension-points/SKILL.md +205 -0
  523. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +720 -0
  524. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +92 -0
  525. package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +285 -0
  526. package/src/templates/workspace-core/.agents/skills/observability/SKILL.md +192 -0
  527. package/src/templates/workspace-core/.agents/skills/onboarding/SKILL.md +43 -0
  528. package/src/templates/workspace-core/.agents/skills/portability/SKILL.md +84 -0
  529. package/src/templates/workspace-core/.agents/skills/qa/SKILL.md +313 -0
  530. package/src/templates/workspace-core/.agents/skills/real-time-collab/SKILL.md +112 -0
  531. package/src/templates/workspace-core/.agents/skills/real-time-sync/SKILL.md +165 -0
  532. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +41 -0
  533. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +239 -0
  534. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +191 -0
  535. package/src/templates/workspace-core/.agents/skills/self-modifying-code/SKILL.md +79 -0
  536. package/src/templates/workspace-core/.agents/skills/server-plugins/SKILL.md +73 -0
  537. package/src/templates/workspace-core/.agents/skills/shadcn-ui/SKILL.md +79 -0
  538. package/src/templates/workspace-core/.agents/skills/sharing/SKILL.md +217 -0
  539. package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +132 -0
  540. package/src/templates/workspace-core/.agents/skills/tracking/SKILL.md +150 -0
  541. package/src/templates/workspace-core/.agents/skills/voice-transcription/SKILL.md +124 -0
  542. package/src/templates/workspace-core/AGENTS.md +16 -1
  543. package/src/templates/workspace-root/AGENTS.md +35 -0
  544. package/src/templates/workspace-root/README.md +7 -0
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Migrate data owned by `local@localhost` to a real account.
3
+ *
4
+ * When a user starts an app in local mode and later signs in to create a real
5
+ * account, this function moves all of their existing data over to the new
6
+ * account so they don't lose anything.
7
+ *
8
+ * Scope of the migration:
9
+ * - `application_state`: rows with `session_id = 'local'`
10
+ * - `settings`: keys prefixed with `u:local@localhost:`
11
+ * - `oauth_tokens`: rows with `owner = 'local@localhost'`
12
+ * - Any template table that has an `owner_email` column: rows with
13
+ * `owner_email = 'local@localhost'`
14
+ *
15
+ * The operation is a no-op if the target email is itself `local@localhost`,
16
+ * empty, or if there is nothing to migrate.
17
+ */
18
+ export interface LocalMigrationResult {
19
+ /** Whether anything was actually migrated. */
20
+ migrated: boolean;
21
+ /** Per-table row counts that were updated. Omits tables with zero updates. */
22
+ tables: Record<string, number>;
23
+ /** Target email the data now belongs to. */
24
+ targetEmail: string;
25
+ /**
26
+ * Non-fatal per-step errors encountered during migration. One bad table
27
+ * no longer fails the whole upgrade — we migrate everything we can and
28
+ * report any steps that threw here so the UI can surface them.
29
+ */
30
+ errors?: Array<{
31
+ step: string;
32
+ message: string;
33
+ }>;
34
+ }
35
+ /**
36
+ * Migrate every piece of local-mode data to the given real account email.
37
+ * Safe to call multiple times — it only touches rows that are still attached
38
+ * to `local@localhost`.
39
+ */
40
+ export declare function migrateLocalUserData(targetEmail: string): Promise<LocalMigrationResult>;
41
+ //# sourceMappingURL=local-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-migration.d.ts","sourceRoot":"","sources":["../../src/server/local-migration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAQH,MAAM,WAAW,oBAAoB;IACnC,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAoLD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,CAAC,CAyD/B"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Migrate data owned by `local@localhost` to a real account.
3
+ *
4
+ * When a user starts an app in local mode and later signs in to create a real
5
+ * account, this function moves all of their existing data over to the new
6
+ * account so they don't lose anything.
7
+ *
8
+ * Scope of the migration:
9
+ * - `application_state`: rows with `session_id = 'local'`
10
+ * - `settings`: keys prefixed with `u:local@localhost:`
11
+ * - `oauth_tokens`: rows with `owner = 'local@localhost'`
12
+ * - Any template table that has an `owner_email` column: rows with
13
+ * `owner_email = 'local@localhost'`
14
+ *
15
+ * The operation is a no-op if the target email is itself `local@localhost`,
16
+ * empty, or if there is nothing to migrate.
17
+ */
18
+ import { getDbExec, isPostgres } from "../db/client.js";
19
+ const LOCAL_EMAIL = "local@localhost";
20
+ const LOCAL_SESSION_ID = "local";
21
+ const OWNER_COLUMN = "owner_email";
22
+ /**
23
+ * Error messages that indicate a missing/inaccessible table or column — the
24
+ * migration treats these as "feature not enabled" and skips silently.
25
+ */
26
+ const SCHEMA_SKIP_ERR = /no such table|no such column|does not exist|undefined table|undefined column|relation .* does not exist|column .* does not exist|permission denied|is not a table|cannot update view|cannot change column in a view/i;
27
+ function shouldSkipSchemaError(err) {
28
+ const message = err instanceof Error ? err.message : String(err);
29
+ return SCHEMA_SKIP_ERR.test(message);
30
+ }
31
+ /**
32
+ * Discover every table (not view) in `public` that has an `owner_email`
33
+ * column. Views and materialized views are excluded — they can't be updated
34
+ * directly and would 500 the migration.
35
+ */
36
+ async function discoverOwnerEmailTables() {
37
+ const client = getDbExec();
38
+ if (isPostgres()) {
39
+ // Join against information_schema.tables to filter out views and
40
+ // materialized views (anything that isn't a plain BASE TABLE).
41
+ const { rows } = await client.execute({
42
+ sql: `SELECT c.table_name
43
+ FROM information_schema.columns c
44
+ JOIN information_schema.tables t
45
+ ON t.table_schema = c.table_schema
46
+ AND t.table_name = c.table_name
47
+ WHERE c.table_schema = 'public'
48
+ AND c.column_name = $1
49
+ AND t.table_type = 'BASE TABLE'`,
50
+ args: [OWNER_COLUMN],
51
+ });
52
+ return rows.map((r) => r.table_name ?? r[0]).filter(Boolean);
53
+ }
54
+ // SQLite path: iterate tables (type='table', not 'view') and inspect columns via PRAGMA
55
+ const tablesRes = await client.execute(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`);
56
+ const tables = tablesRes.rows
57
+ .map((r) => (r.name ?? r[0]))
58
+ .filter(Boolean);
59
+ const withOwner = [];
60
+ for (const table of tables) {
61
+ const escaped = table.replace(/"/g, '""');
62
+ const colsRes = await client.execute(`PRAGMA table_info("${escaped}")`);
63
+ const hasOwner = colsRes.rows.some((row) => (row.name ?? row[1]) === OWNER_COLUMN);
64
+ if (hasOwner)
65
+ withOwner.push(table);
66
+ }
67
+ return withOwner;
68
+ }
69
+ /** Replace `?` placeholders with `$1`, `$2`, … for Postgres. */
70
+ function sqlWithParams(sql) {
71
+ if (!isPostgres())
72
+ return sql;
73
+ let i = 0;
74
+ return sql.replace(/\?/g, () => `$${++i}`);
75
+ }
76
+ /**
77
+ * Rename `settings` keys so a user's config carries over. Keys are prefixed
78
+ * with `u:<email>:` — moving from one email to another is a prefix swap.
79
+ *
80
+ * If a destination key already exists (unlikely but possible if the user had
81
+ * previously signed in with the same email) we leave the destination alone
82
+ * and drop the local row, so we never clobber real-account state.
83
+ */
84
+ async function migrateSettings(targetEmail) {
85
+ const client = getDbExec();
86
+ const oldPrefix = `u:${LOCAL_EMAIL}:`;
87
+ const newPrefix = `u:${targetEmail}:`;
88
+ const { rows } = await client.execute({
89
+ sql: sqlWithParams(`SELECT key FROM settings WHERE key LIKE ? ESCAPE '\\'`),
90
+ args: [oldPrefix.replace(/([\\%_])/g, "\\$1") + "%"],
91
+ });
92
+ let updated = 0;
93
+ for (const row of rows) {
94
+ const oldKey = (row.key ?? row[0]);
95
+ if (!oldKey.startsWith(oldPrefix))
96
+ continue;
97
+ const newKey = newPrefix + oldKey.slice(oldPrefix.length);
98
+ // Skip if the destination already exists — don't overwrite real data.
99
+ const existsRes = await client.execute({
100
+ sql: sqlWithParams(`SELECT 1 FROM settings WHERE key = ?`),
101
+ args: [newKey],
102
+ });
103
+ if (existsRes.rows.length > 0) {
104
+ await client.execute({
105
+ sql: sqlWithParams(`DELETE FROM settings WHERE key = ?`),
106
+ args: [oldKey],
107
+ });
108
+ continue;
109
+ }
110
+ await client.execute({
111
+ sql: sqlWithParams(`UPDATE settings SET key = ? WHERE key = ?`),
112
+ args: [newKey, oldKey],
113
+ });
114
+ updated++;
115
+ }
116
+ return updated;
117
+ }
118
+ /**
119
+ * Move application_state rows from `session_id='local'` to the target email.
120
+ * Rows that already exist for the destination session are left alone.
121
+ */
122
+ async function migrateApplicationState(targetEmail) {
123
+ const client = getDbExec();
124
+ // Only migrate keys that don't already exist under the destination session.
125
+ const { rows } = await client.execute({
126
+ sql: sqlWithParams(`SELECT key FROM application_state WHERE session_id = ?`),
127
+ args: [LOCAL_SESSION_ID],
128
+ });
129
+ let updated = 0;
130
+ for (const row of rows) {
131
+ const key = (row.key ?? row[0]);
132
+ const existsRes = await client.execute({
133
+ sql: sqlWithParams(`SELECT 1 FROM application_state WHERE session_id = ? AND key = ?`),
134
+ args: [targetEmail, key],
135
+ });
136
+ if (existsRes.rows.length > 0) {
137
+ await client.execute({
138
+ sql: sqlWithParams(`DELETE FROM application_state WHERE session_id = ? AND key = ?`),
139
+ args: [LOCAL_SESSION_ID, key],
140
+ });
141
+ continue;
142
+ }
143
+ await client.execute({
144
+ sql: sqlWithParams(`UPDATE application_state SET session_id = ? WHERE session_id = ? AND key = ?`),
145
+ args: [targetEmail, LOCAL_SESSION_ID, key],
146
+ });
147
+ updated++;
148
+ }
149
+ return updated;
150
+ }
151
+ /** Move oauth_tokens rows. `owner` is the user's email in core tables. */
152
+ async function migrateOauthTokens(targetEmail) {
153
+ const client = getDbExec();
154
+ const res = await client.execute({
155
+ sql: sqlWithParams(`UPDATE oauth_tokens SET owner = ? WHERE owner = ?`),
156
+ args: [targetEmail, LOCAL_EMAIL],
157
+ });
158
+ return res.rowsAffected ?? 0;
159
+ }
160
+ /** Move rows in a template table that uses the `owner_email` convention. */
161
+ async function migrateOwnerEmailTable(table, targetEmail) {
162
+ const client = getDbExec();
163
+ const escaped = table.replace(/"/g, '""');
164
+ const res = await client.execute({
165
+ sql: sqlWithParams(`UPDATE "${escaped}" SET owner_email = ? WHERE owner_email = ?`),
166
+ args: [targetEmail, LOCAL_EMAIL],
167
+ });
168
+ return res.rowsAffected ?? 0;
169
+ }
170
+ /**
171
+ * Migrate every piece of local-mode data to the given real account email.
172
+ * Safe to call multiple times — it only touches rows that are still attached
173
+ * to `local@localhost`.
174
+ */
175
+ export async function migrateLocalUserData(targetEmail) {
176
+ const email = targetEmail?.trim().toLowerCase();
177
+ if (!email || email === LOCAL_EMAIL) {
178
+ return { migrated: false, tables: {}, targetEmail: email || "" };
179
+ }
180
+ const tables = {};
181
+ // Core tables — best-effort. A missing table just means the feature isn't
182
+ // enabled in this app (e.g. an app that doesn't use oauth_tokens).
183
+ const coreSteps = [
184
+ ["settings", () => migrateSettings(email)],
185
+ ["application_state", () => migrateApplicationState(email)],
186
+ ["oauth_tokens", () => migrateOauthTokens(email)],
187
+ ];
188
+ const errors = [];
189
+ for (const [name, fn] of coreSteps) {
190
+ try {
191
+ const count = await fn();
192
+ if (count > 0)
193
+ tables[name] = count;
194
+ }
195
+ catch (err) {
196
+ // Missing table or column — skip silently. Other errors are logged
197
+ // per-step so one bad table doesn't 500 the entire migration.
198
+ if (!shouldSkipSchemaError(err)) {
199
+ const message = err?.message ?? String(err);
200
+ errors.push({ step: name, message });
201
+ console.error(`[local-migration] ${name} failed:`, err);
202
+ }
203
+ }
204
+ }
205
+ // Template tables — discovered dynamically. If discovery itself fails,
206
+ // fall back to an empty list so the migration doesn't 500.
207
+ let templateTables = [];
208
+ try {
209
+ templateTables = await discoverOwnerEmailTables();
210
+ }
211
+ catch (err) {
212
+ console.error("[local-migration] owner_email table discovery failed:", err);
213
+ templateTables = [];
214
+ }
215
+ for (const table of templateTables) {
216
+ try {
217
+ const count = await migrateOwnerEmailTable(table, email);
218
+ if (count > 0)
219
+ tables[table] = count;
220
+ }
221
+ catch (err) {
222
+ if (!shouldSkipSchemaError(err)) {
223
+ const message = err?.message ?? String(err);
224
+ errors.push({ step: table, message });
225
+ console.error(`[local-migration] ${table} failed:`, err);
226
+ }
227
+ }
228
+ }
229
+ const migrated = Object.values(tables).some((n) => n > 0);
230
+ const result = { migrated, tables, targetEmail: email };
231
+ if (errors.length > 0)
232
+ result.errors = errors;
233
+ return result;
234
+ }
235
+ //# sourceMappingURL=local-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-migration.js","sourceRoot":"","sources":["../../src/server/local-migration.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Migrate data owned by `local@localhost` to a real account.\n *\n * When a user starts an app in local mode and later signs in to create a real\n * account, this function moves all of their existing data over to the new\n * account so they don't lose anything.\n *\n * Scope of the migration:\n * - `application_state`: rows with `session_id = 'local'`\n * - `settings`: keys prefixed with `u:local@localhost:`\n * - `oauth_tokens`: rows with `owner = 'local@localhost'`\n * - Any template table that has an `owner_email` column: rows with\n * `owner_email = 'local@localhost'`\n *\n * The operation is a no-op if the target email is itself `local@localhost`,\n * empty, or if there is nothing to migrate.\n */\n\nimport { getDbExec, isPostgres } from \"../db/client.js\";\n\nconst LOCAL_EMAIL = \"local@localhost\";\nconst LOCAL_SESSION_ID = \"local\";\nconst OWNER_COLUMN = \"owner_email\";\n\nexport interface LocalMigrationResult {\n /** Whether anything was actually migrated. */\n migrated: boolean;\n /** Per-table row counts that were updated. Omits tables with zero updates. */\n tables: Record<string, number>;\n /** Target email the data now belongs to. */\n targetEmail: string;\n /**\n * Non-fatal per-step errors encountered during migration. One bad table\n * no longer fails the whole upgrade — we migrate everything we can and\n * report any steps that threw here so the UI can surface them.\n */\n errors?: Array<{ step: string; message: string }>;\n}\n\n/**\n * Error messages that indicate a missing/inaccessible table or column — the\n * migration treats these as \"feature not enabled\" and skips silently.\n */\nconst SCHEMA_SKIP_ERR =\n /no such table|no such column|does not exist|undefined table|undefined column|relation .* does not exist|column .* does not exist|permission denied|is not a table|cannot update view|cannot change column in a view/i;\n\nfunction shouldSkipSchemaError(err: unknown): boolean {\n const message = err instanceof Error ? err.message : String(err);\n return SCHEMA_SKIP_ERR.test(message);\n}\n\n/**\n * Discover every table (not view) in `public` that has an `owner_email`\n * column. Views and materialized views are excluded — they can't be updated\n * directly and would 500 the migration.\n */\nasync function discoverOwnerEmailTables(): Promise<string[]> {\n const client = getDbExec();\n if (isPostgres()) {\n // Join against information_schema.tables to filter out views and\n // materialized views (anything that isn't a plain BASE TABLE).\n const { rows } = await client.execute({\n sql: `SELECT c.table_name\n FROM information_schema.columns c\n JOIN information_schema.tables t\n ON t.table_schema = c.table_schema\n AND t.table_name = c.table_name\n WHERE c.table_schema = 'public'\n AND c.column_name = $1\n AND t.table_type = 'BASE TABLE'`,\n args: [OWNER_COLUMN],\n });\n return rows.map((r: any) => r.table_name ?? r[0]).filter(Boolean);\n }\n\n // SQLite path: iterate tables (type='table', not 'view') and inspect columns via PRAGMA\n const tablesRes = await client.execute(\n `SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`,\n );\n const tables = tablesRes.rows\n .map((r: any) => (r.name ?? r[0]) as string)\n .filter(Boolean);\n\n const withOwner: string[] = [];\n for (const table of tables) {\n const escaped = table.replace(/\"/g, '\"\"');\n const colsRes = await client.execute(`PRAGMA table_info(\"${escaped}\")`);\n const hasOwner = colsRes.rows.some(\n (row: any) => (row.name ?? row[1]) === OWNER_COLUMN,\n );\n if (hasOwner) withOwner.push(table);\n }\n return withOwner;\n}\n\n/** Replace `?` placeholders with `$1`, `$2`, … for Postgres. */\nfunction sqlWithParams(sql: string): string {\n if (!isPostgres()) return sql;\n let i = 0;\n return sql.replace(/\\?/g, () => `$${++i}`);\n}\n\n/**\n * Rename `settings` keys so a user's config carries over. Keys are prefixed\n * with `u:<email>:` — moving from one email to another is a prefix swap.\n *\n * If a destination key already exists (unlikely but possible if the user had\n * previously signed in with the same email) we leave the destination alone\n * and drop the local row, so we never clobber real-account state.\n */\nasync function migrateSettings(targetEmail: string): Promise<number> {\n const client = getDbExec();\n const oldPrefix = `u:${LOCAL_EMAIL}:`;\n const newPrefix = `u:${targetEmail}:`;\n\n const { rows } = await client.execute({\n sql: sqlWithParams(`SELECT key FROM settings WHERE key LIKE ? ESCAPE '\\\\'`),\n args: [oldPrefix.replace(/([\\\\%_])/g, \"\\\\$1\") + \"%\"],\n });\n\n let updated = 0;\n for (const row of rows) {\n const oldKey = (row.key ?? (row as any)[0]) as string;\n if (!oldKey.startsWith(oldPrefix)) continue;\n const newKey = newPrefix + oldKey.slice(oldPrefix.length);\n\n // Skip if the destination already exists — don't overwrite real data.\n const existsRes = await client.execute({\n sql: sqlWithParams(`SELECT 1 FROM settings WHERE key = ?`),\n args: [newKey],\n });\n if (existsRes.rows.length > 0) {\n await client.execute({\n sql: sqlWithParams(`DELETE FROM settings WHERE key = ?`),\n args: [oldKey],\n });\n continue;\n }\n\n await client.execute({\n sql: sqlWithParams(`UPDATE settings SET key = ? WHERE key = ?`),\n args: [newKey, oldKey],\n });\n updated++;\n }\n return updated;\n}\n\n/**\n * Move application_state rows from `session_id='local'` to the target email.\n * Rows that already exist for the destination session are left alone.\n */\nasync function migrateApplicationState(targetEmail: string): Promise<number> {\n const client = getDbExec();\n // Only migrate keys that don't already exist under the destination session.\n const { rows } = await client.execute({\n sql: sqlWithParams(\n `SELECT key FROM application_state WHERE session_id = ?`,\n ),\n args: [LOCAL_SESSION_ID],\n });\n\n let updated = 0;\n for (const row of rows) {\n const key = (row.key ?? (row as any)[0]) as string;\n const existsRes = await client.execute({\n sql: sqlWithParams(\n `SELECT 1 FROM application_state WHERE session_id = ? AND key = ?`,\n ),\n args: [targetEmail, key],\n });\n if (existsRes.rows.length > 0) {\n await client.execute({\n sql: sqlWithParams(\n `DELETE FROM application_state WHERE session_id = ? AND key = ?`,\n ),\n args: [LOCAL_SESSION_ID, key],\n });\n continue;\n }\n await client.execute({\n sql: sqlWithParams(\n `UPDATE application_state SET session_id = ? WHERE session_id = ? AND key = ?`,\n ),\n args: [targetEmail, LOCAL_SESSION_ID, key],\n });\n updated++;\n }\n return updated;\n}\n\n/** Move oauth_tokens rows. `owner` is the user's email in core tables. */\nasync function migrateOauthTokens(targetEmail: string): Promise<number> {\n const client = getDbExec();\n const res = await client.execute({\n sql: sqlWithParams(`UPDATE oauth_tokens SET owner = ? WHERE owner = ?`),\n args: [targetEmail, LOCAL_EMAIL],\n });\n return res.rowsAffected ?? 0;\n}\n\n/** Move rows in a template table that uses the `owner_email` convention. */\nasync function migrateOwnerEmailTable(\n table: string,\n targetEmail: string,\n): Promise<number> {\n const client = getDbExec();\n const escaped = table.replace(/\"/g, '\"\"');\n const res = await client.execute({\n sql: sqlWithParams(\n `UPDATE \"${escaped}\" SET owner_email = ? WHERE owner_email = ?`,\n ),\n args: [targetEmail, LOCAL_EMAIL],\n });\n return res.rowsAffected ?? 0;\n}\n\n/**\n * Migrate every piece of local-mode data to the given real account email.\n * Safe to call multiple times — it only touches rows that are still attached\n * to `local@localhost`.\n */\nexport async function migrateLocalUserData(\n targetEmail: string,\n): Promise<LocalMigrationResult> {\n const email = targetEmail?.trim().toLowerCase();\n if (!email || email === LOCAL_EMAIL) {\n return { migrated: false, tables: {}, targetEmail: email || \"\" };\n }\n\n const tables: Record<string, number> = {};\n\n // Core tables — best-effort. A missing table just means the feature isn't\n // enabled in this app (e.g. an app that doesn't use oauth_tokens).\n const coreSteps: Array<[string, () => Promise<number>]> = [\n [\"settings\", () => migrateSettings(email)],\n [\"application_state\", () => migrateApplicationState(email)],\n [\"oauth_tokens\", () => migrateOauthTokens(email)],\n ];\n const errors: Array<{ step: string; message: string }> = [];\n for (const [name, fn] of coreSteps) {\n try {\n const count = await fn();\n if (count > 0) tables[name] = count;\n } catch (err: any) {\n // Missing table or column — skip silently. Other errors are logged\n // per-step so one bad table doesn't 500 the entire migration.\n if (!shouldSkipSchemaError(err)) {\n const message = err?.message ?? String(err);\n errors.push({ step: name, message });\n console.error(`[local-migration] ${name} failed:`, err);\n }\n }\n }\n\n // Template tables — discovered dynamically. If discovery itself fails,\n // fall back to an empty list so the migration doesn't 500.\n let templateTables: string[] = [];\n try {\n templateTables = await discoverOwnerEmailTables();\n } catch (err) {\n console.error(\"[local-migration] owner_email table discovery failed:\", err);\n templateTables = [];\n }\n for (const table of templateTables) {\n try {\n const count = await migrateOwnerEmailTable(table, email);\n if (count > 0) tables[table] = count;\n } catch (err: any) {\n if (!shouldSkipSchemaError(err)) {\n const message = err?.message ?? String(err);\n errors.push({ step: table, message });\n console.error(`[local-migration] ${table} failed:`, err);\n }\n }\n }\n\n const migrated = Object.values(tables).some((n) => n > 0);\n const result: LocalMigrationResult = { migrated, tables, targetEmail: email };\n if (errors.length > 0) result.errors = errors;\n return result;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-public-origin.d.ts","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AASA,wBAAgB,oBAAoB,IAAI,MAAM,CAe7C"}
1
+ {"version":3,"file":"oauth-public-origin.d.ts","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AAuBA,wBAAgB,oBAAoB,IAAI,MAAM,CAoB7C"}
@@ -8,6 +8,18 @@ function normalizeOrigin(raw) {
8
8
  return "";
9
9
  }
10
10
  }
11
+ function isLoopbackOrigin(origin) {
12
+ try {
13
+ const hostname = new URL(origin).hostname;
14
+ return (hostname === "localhost" ||
15
+ hostname === "127.0.0.1" ||
16
+ hostname === "::1" ||
17
+ hostname === "[::1]");
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
11
23
  export function getPublicOAuthOrigin() {
12
24
  for (const raw of [
13
25
  process.env.WORKSPACE_OAUTH_ORIGIN,
@@ -16,11 +28,17 @@ export function getPublicOAuthOrigin() {
16
28
  process.env.VITE_APP_URL,
17
29
  process.env.BETTER_AUTH_URL,
18
30
  process.env.VITE_BETTER_AUTH_URL,
31
+ ]) {
32
+ const origin = normalizeOrigin(raw);
33
+ if (origin && !isLoopbackOrigin(origin))
34
+ return origin;
35
+ }
36
+ for (const raw of [
19
37
  process.env.WORKSPACE_GATEWAY_URL,
20
38
  process.env.VITE_WORKSPACE_GATEWAY_URL,
21
39
  ]) {
22
40
  const origin = normalizeOrigin(raw);
23
- if (origin)
41
+ if (origin && !isLoopbackOrigin(origin))
24
42
  return origin;
25
43
  }
26
44
  return "";
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-public-origin.js","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AAAA,SAAS,eAAe,CAAC,GAAuB;IAC9C,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,KAAK,MAAM,GAAG,IAAI;QAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAClC,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,OAAO,CAAC,GAAG,CAAC,OAAO;QACnB,OAAO,CAAC,GAAG,CAAC,YAAY;QACxB,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAChC,OAAO,CAAC,GAAG,CAAC,qBAAqB;QACjC,OAAO,CAAC,GAAG,CAAC,0BAA0B;KACvC,EAAE,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["function normalizeOrigin(raw: string | undefined): string {\n if (!raw) return \"\";\n try {\n return new URL(raw).origin;\n } catch {\n return \"\";\n }\n}\n\nexport function getPublicOAuthOrigin(): string {\n for (const raw of [\n process.env.WORKSPACE_OAUTH_ORIGIN,\n process.env.VITE_WORKSPACE_OAUTH_ORIGIN,\n process.env.APP_URL,\n process.env.VITE_APP_URL,\n process.env.BETTER_AUTH_URL,\n process.env.VITE_BETTER_AUTH_URL,\n process.env.WORKSPACE_GATEWAY_URL,\n process.env.VITE_WORKSPACE_GATEWAY_URL,\n ]) {\n const origin = normalizeOrigin(raw);\n if (origin) return origin;\n }\n return \"\";\n}\n"]}
1
+ {"version":3,"file":"oauth-public-origin.js","sourceRoot":"","sources":["../../src/server/oauth-public-origin.ts"],"names":[],"mappings":"AAAA,SAAS,eAAe,CAAC,GAAuB;IAC9C,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,MAAc;IACtC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC;QAC1C,OAAO,CACL,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,KAAK;YAClB,QAAQ,KAAK,OAAO,CACrB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,KAAK,MAAM,GAAG,IAAI;QAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB;QAClC,OAAO,CAAC,GAAG,CAAC,2BAA2B;QACvC,OAAO,CAAC,GAAG,CAAC,OAAO;QACnB,OAAO,CAAC,GAAG,CAAC,YAAY;QACxB,OAAO,CAAC,GAAG,CAAC,eAAe;QAC3B,OAAO,CAAC,GAAG,CAAC,oBAAoB;KACjC,EAAE,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;IACzD,CAAC;IACD,KAAK,MAAM,GAAG,IAAI;QAChB,OAAO,CAAC,GAAG,CAAC,qBAAqB;QACjC,OAAO,CAAC,GAAG,CAAC,0BAA0B;KACvC,EAAE,CAAC;QACF,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;IACzD,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC","sourcesContent":["function normalizeOrigin(raw: string | undefined): string {\n if (!raw) return \"\";\n try {\n return new URL(raw).origin;\n } catch {\n return \"\";\n }\n}\n\nfunction isLoopbackOrigin(origin: string): boolean {\n try {\n const hostname = new URL(origin).hostname;\n return (\n hostname === \"localhost\" ||\n hostname === \"127.0.0.1\" ||\n hostname === \"::1\" ||\n hostname === \"[::1]\"\n );\n } catch {\n return false;\n }\n}\n\nexport function getPublicOAuthOrigin(): string {\n for (const raw of [\n process.env.WORKSPACE_OAUTH_ORIGIN,\n process.env.VITE_WORKSPACE_OAUTH_ORIGIN,\n process.env.APP_URL,\n process.env.VITE_APP_URL,\n process.env.BETTER_AUTH_URL,\n process.env.VITE_BETTER_AUTH_URL,\n ]) {\n const origin = normalizeOrigin(raw);\n if (origin && !isLoopbackOrigin(origin)) return origin;\n }\n for (const raw of [\n process.env.WORKSPACE_GATEWAY_URL,\n process.env.VITE_WORKSPACE_GATEWAY_URL,\n ]) {\n const origin = normalizeOrigin(raw);\n if (origin && !isLoopbackOrigin(origin)) return origin;\n }\n return \"\";\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"onboarding-html.d.ts","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAmC/B,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,CA2kD1E;AAED,kDAAkD;AAClD,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAwG7C"}
1
+ {"version":3,"file":"onboarding-html.d.ts","sourceRoot":"","sources":["../../src/server/onboarding-html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAmC/B,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF;;;;OAIG;IACH,kBAAkB,CAAC,EAAE;QACnB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACxB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF;;;;OAIG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,qBAA0B,GAAG,MAAM,CAgoD1E;AAED,kDAAkD;AAClD,eAAO,MAAM,eAAe,QAAsB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CA0G7C"}
@@ -419,6 +419,8 @@ ${runLocalCommand
419
419
  <meta charset="UTF-8">
420
420
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
421
421
  <title>${hasMarketing ? esc(marketing.appName) + " — Sign in" : "Welcome"}</title>
422
+ <link rel="icon" type="image/svg+xml" href="${withAppBasePath("/favicon.svg")}">
423
+ <link rel="apple-touch-icon" href="${withAppBasePath("/icon-180.svg")}">
422
424
  ${hasMarketing
423
425
  ? `<meta name="description" content="${esc(marketing.tagline)}">
424
426
  <meta property="og:title" content="${esc(marketing.appName)}">
@@ -855,18 +857,27 @@ ${googleOnly
855
857
  return origin ? origin + path : __anPath(path);
856
858
  }
857
859
  function __anBuilderPreviewReturnOrigin() {
860
+ var candidates = [window.location.href, document.referrer || ''];
858
861
  try {
859
- var url = new URL(window.location.href);
860
- var host = url.hostname.toLowerCase();
861
- var isPreviewHost =
862
- host === 'builderio.xyz' || host.slice(-14) === '.builderio.xyz' ||
863
- host === 'builderio.dev' || host.slice(-14) === '.builderio.dev' ||
864
- host === 'builder.codes' || host.slice(-14) === '.builder.codes' ||
865
- host === 'builder.my' || host.slice(-11) === '.builder.my';
866
- return url.protocol === 'https:' && isPreviewHost ? url.origin : '';
867
- } catch(e) {
868
- return '';
862
+ if (window.location.ancestorOrigins) {
863
+ for (var j = 0; j < window.location.ancestorOrigins.length; j++) {
864
+ candidates.push(window.location.ancestorOrigins[j]);
865
+ }
866
+ }
867
+ } catch(e) {}
868
+ for (var i = 0; i < candidates.length; i++) {
869
+ try {
870
+ var url = new URL(candidates[i]);
871
+ var host = url.hostname.toLowerCase();
872
+ var isPreviewHost =
873
+ host === 'builderio.xyz' || host.slice(-14) === '.builderio.xyz' ||
874
+ host === 'builderio.dev' || host.slice(-14) === '.builderio.dev' ||
875
+ host === 'builder.codes' || host.slice(-14) === '.builder.codes' ||
876
+ host === 'builder.my' || host.slice(-11) === '.builder.my';
877
+ if (url.protocol === 'https:' && isPreviewHost) return url.origin;
878
+ } catch(e) {}
869
879
  }
880
+ return '';
870
881
  }
871
882
  function __anWorkspaceGatewayReturnOrigin() {
872
883
  var previewOrigin = __anBuilderPreviewReturnOrigin();
@@ -906,6 +917,15 @@ ${googleOnly
906
917
  var origin = __anWorkspaceGatewayReturnOrigin();
907
918
  return origin ? origin + path : path;
908
919
  }
920
+ function __anFinishOAuthExchange(ret, flowId) {
921
+ if (__anIsBuilderPreview()) {
922
+ __anSetOAuthDebug('OAuth exchange redeemed; reloading the embedded app', flowId);
923
+ window.location.reload();
924
+ return;
925
+ }
926
+ __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);
927
+ window.location.href = ret || '/';
928
+ }
909
929
  function __anGetReturnPath() {
910
930
  try {
911
931
  var inner = new URLSearchParams(window.location.search).get('return');
@@ -933,6 +953,13 @@ ${googleOnly
933
953
  return false;
934
954
  }
935
955
  }
956
+ function __anIsAgentNativeDesktop() {
957
+ try {
958
+ return (navigator.userAgent || '').indexOf('AgentNativeDesktop') !== -1;
959
+ } catch(e) {
960
+ return false;
961
+ }
962
+ }
936
963
  function __anIsElectron() {
937
964
  try {
938
965
  return (navigator.userAgent || '').indexOf('Electron') !== -1;
@@ -947,9 +974,9 @@ ${googleOnly
947
974
  var qp = new URLSearchParams(window.location.search).get('authMode');
948
975
  if (qp === 'popup' || qp === 'redirect') return qp;
949
976
  } catch(e) {}
950
- // Builder.io browser iframe must use popup — Google sets
951
- // X-Frame-Options: DENY so a redirect inside the iframe fails.
952
- if (__anIsBuilderPreview() && !__anIsBuilderDesktop()) return 'popup';
977
+ // Builder.io preview surfaces must use popup — Google sets
978
+ // X-Frame-Options: DENY so a redirect inside the webview/iframe fails.
979
+ if (__anIsBuilderPreview()) return 'popup';
953
980
  var mode = __AN_GOOGLE_AUTH_MODE || 'auto';
954
981
  if (mode === 'popup') return 'popup';
955
982
  if (mode === 'redirect') return 'redirect';
@@ -971,12 +998,22 @@ ${googleOnly
971
998
  function __anSetOAuthDebug(message, flowId) {
972
999
  var text = message + (flowId ? ' (flow ' + __anFlowDebugId(flowId) + ')' : '');
973
1000
  try {
974
- console.info('[agent-native][google-oauth]', { message: message, flow: __anFlowDebugId(flowId) || undefined });
1001
+ console.info('[agent-native][google-oauth] ' + text);
1002
+ } catch(e) {}
1003
+ // Only surface the debug overlay when explicitly opted in via #oauth-debug
1004
+ // hash or ?oauth_debug=1 query — otherwise it leaks raw flow IDs and
1005
+ // diagnostic strings into the user-facing sign-in screen.
1006
+ var showDebugOverlay = false;
1007
+ try {
1008
+ var loc = window.location || {};
1009
+ showDebugOverlay =
1010
+ (typeof loc.hash === 'string' && loc.hash.indexOf('oauth-debug') !== -1) ||
1011
+ (typeof loc.search === 'string' && loc.search.indexOf('oauth_debug=1') !== -1);
975
1012
  } catch(e) {}
976
1013
  var debug = document.getElementById('google-debug');
977
1014
  if (debug) {
978
1015
  debug.textContent = text;
979
- debug.classList.add('show');
1016
+ if (showDebugOverlay) debug.classList.add('show');
980
1017
  }
981
1018
  }
982
1019
  function __anShowOAuthError(err, btn, message) {
@@ -1000,8 +1037,7 @@ ${googleOnly
1000
1037
  if (data && (data.email || data.token)) {
1001
1038
  if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);
1002
1039
  __anOAuthPollTimer = null;
1003
- __anSetOAuthDebug('OAuth exchange redeemed; returning to the app', flowId);
1004
- window.location.href = ret || '/';
1040
+ __anFinishOAuthExchange(ret, flowId);
1005
1041
  return;
1006
1042
  }
1007
1043
  if (data && data.error) {
@@ -1018,7 +1054,7 @@ ${googleOnly
1018
1054
  }
1019
1055
  }
1020
1056
  if (Date.now() - started > timeoutMs) {
1021
- __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never redeemed; check server logs for [agent-native][google-oauth].');
1057
+ __anShowOAuthError(err, btn, 'Google sign-in did not finish. Flow ' + __anFlowDebugId(flowId) + ' never reached this app. Check the Google OAuth redirect URI and server logs for [agent-native][google-oauth].');
1022
1058
  }
1023
1059
  }
1024
1060
  if (__anOAuthPollTimer) clearInterval(__anOAuthPollTimer);
@@ -1027,8 +1063,9 @@ ${googleOnly
1027
1063
  }
1028
1064
  function __anStartPopupOAuth(ret, btn, err) {
1029
1065
  var flowId = __anNewOAuthFlowId();
1066
+ var oauthReturn = __anIsBuilderPreview() ? __anOAuthReturnTarget(ret) : ret;
1030
1067
  var params = new URLSearchParams();
1031
- if (ret) params.set('return', ret);
1068
+ if (oauthReturn) params.set('return', oauthReturn);
1032
1069
  params.set('desktop', '1');
1033
1070
  params.set('flow_id', flowId);
1034
1071
  params.set('redirect', '1');
@@ -1056,6 +1093,18 @@ ${googleOnly
1056
1093
  }
1057
1094
  __anWaitForOAuthExchange(flowId, ret, btn, err);
1058
1095
  }
1096
+ function __anStartNativeDesktopOAuth(ret, btn, err) {
1097
+ var flowId = __anNewOAuthFlowId();
1098
+ var params = new URLSearchParams();
1099
+ if (ret) params.set('return', ret);
1100
+ params.set('desktop', '1');
1101
+ params.set('flow_id', flowId);
1102
+ params.set('redirect', '1');
1103
+ var url = __anPath('/_agent-native/google/auth-url') + '?' + params.toString();
1104
+ __anSetOAuthDebug('Opening Google sign-in in system browser', flowId);
1105
+ __anOpenOAuthUrl(url);
1106
+ __anWaitForOAuthExchange(flowId, ret, btn, err);
1107
+ }
1059
1108
  function __anOpenOAuthUrl(url) {
1060
1109
  try { sessionStorage.setItem('__an_signin', '1'); } catch(e) {}
1061
1110
  window.location.href = url;
@@ -1535,6 +1584,10 @@ ${showGoogle
1535
1584
  __anStartPopupOAuth(ret, btn, err);
1536
1585
  return;
1537
1586
  }
1587
+ if (__anIsAgentNativeDesktop()) {
1588
+ __anStartNativeDesktopOAuth(ret, btn, err);
1589
+ return;
1590
+ }
1538
1591
  if (__anIsBuilderPreview()) {
1539
1592
  var params = new URLSearchParams();
1540
1593
  if (ret) params.set('return', __anOAuthReturnTarget(ret));
@@ -1636,6 +1689,8 @@ export function getResetPasswordHtml() {
1636
1689
  <meta charset="UTF-8">
1637
1690
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
1638
1691
  <title>Reset password</title>
1692
+ <link rel="icon" type="image/svg+xml" href="${withAppBasePath("/favicon.svg")}">
1693
+ <link rel="apple-touch-icon" href="${withAppBasePath("/icon-180.svg")}">
1639
1694
  <style>
1640
1695
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
1641
1696
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #0a0a0a; color: #e5e5e5; display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 1rem; }