@agent-native/core 0.169.1 → 0.170.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (459) hide show
  1. package/agent-native.eject.json +4 -1
  2. package/bin/agent-native.js +23 -5
  3. package/corpus/README.md +1 -1
  4. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +11 -4
  5. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
  6. package/corpus/templates/analytics/app/i18n-data.ts +28 -0
  7. package/corpus/templates/analytics/app/pages/Agents.tsx +25 -1
  8. package/corpus/templates/analytics/app/routes/$.tsx +10 -0
  9. package/corpus/templates/analytics/app/routes.ts +3 -1
  10. package/corpus/templates/analytics/changelog/2026-08-22-fixed-the-agent-native-templates-first-party-dashboard-panel.md +6 -0
  11. package/corpus/templates/analytics/changelog/2026-08-22-org-admin-panels-no-longer-report-a-database-error-as-a-per.md +9 -0
  12. package/corpus/templates/analytics/changelog/2026-08-22-slack-requests-report-invalid-inputs.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-08-22-unknown-analytics-links-now-return-a-real-not-found-status.md +6 -0
  14. package/corpus/templates/analytics/docs/schemas/first-party-analytics.md +2 -1
  15. package/corpus/templates/analytics/docs/schemas/tracked-events.md +2 -0
  16. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +29 -7
  17. package/corpus/templates/analytics/server/handlers/slack.ts +59 -5
  18. package/corpus/templates/analytics/server/lib/db-admin-connections.ts +11 -6
  19. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +132 -2
  20. package/corpus/templates/analytics/server/lib/slack.ts +4 -2
  21. package/corpus/templates/analytics/vitest.config.ts +6 -1
  22. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +11 -4
  23. package/corpus/templates/assets/app/routes/library.tsx +5 -3
  24. package/corpus/templates/assets/app/routes.ts +3 -1
  25. package/corpus/templates/assets/changelog/2026-08-22-library-page-loads-again-instead-of-crashing-on-open.md +6 -0
  26. package/corpus/templates/assets/vitest.config.ts +6 -1
  27. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +11 -4
  28. package/corpus/templates/brain/app/components/ui/pointer-lock.ts +1 -0
  29. package/corpus/templates/brain/app/routes/sources.tsx +8 -3
  30. package/corpus/templates/brain/changelog/2026-08-22-tuning-or-adding-a-source-no-longer-leaves-the-sources-page.md +6 -0
  31. package/corpus/templates/brain/vitest.config.ts +1 -0
  32. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +11 -4
  33. package/corpus/templates/calendar/actions/list-booking-links.ts +83 -4
  34. package/corpus/templates/calendar/actions/update-booking-link.ts +4 -3
  35. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +11 -3
  36. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +1 -1
  37. package/corpus/templates/calendar/app/components/calendar/GoogleConnectBanner.tsx +103 -44
  38. package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +28 -24
  39. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +9 -2
  40. package/corpus/templates/calendar/app/components/layout/Sidebar.tsx +47 -58
  41. package/corpus/templates/calendar/app/hooks/use-booking-links.ts +5 -1
  42. package/corpus/templates/calendar/app/lib/event-layout.ts +52 -26
  43. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +126 -98
  44. package/corpus/templates/calendar/app/pages/CalendarView.tsx +1 -0
  45. package/corpus/templates/calendar/app/pages/Settings.tsx +88 -81
  46. package/corpus/templates/calendar/app/routes.ts +3 -1
  47. package/corpus/templates/calendar/changelog/2026-08-22-booking-link-visibility-respects-shared-access.md +6 -0
  48. package/corpus/templates/calendar/changelog/2026-08-22-clicking-an-out-of-office-event-s-marker-no-longer-creates-a.md +6 -0
  49. package/corpus/templates/calendar/changelog/2026-08-22-event-detail-views-now-show-your-calendar-timezone.md +6 -0
  50. package/corpus/templates/calendar/changelog/2026-08-22-google-calendar-can-now-connect-with-the-shared-google-oauth.md +6 -0
  51. package/corpus/templates/calendar/changelog/2026-08-22-overlapping-events-now-show-each-others-boundaries.md +6 -0
  52. package/corpus/templates/calendar/changelog/2026-08-22-public-booking-pages-now-offer-time-slots-from-the-host-s-we.md +6 -0
  53. package/corpus/templates/calendar/server/handlers/bookings.ts +5 -7
  54. package/corpus/templates/calendar/server/handlers/google-auth.ts +10 -2
  55. package/corpus/templates/calendar/server/lib/google-calendar.ts +139 -14
  56. package/corpus/templates/calendar/server/onboarding.ts +85 -0
  57. package/corpus/templates/calendar/server/plugins/agent-chat.ts +2 -0
  58. package/corpus/templates/calendar/shared/api.ts +9 -1
  59. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  60. package/corpus/templates/chat/app/routes.ts +3 -1
  61. package/corpus/templates/chat/vitest.config.ts +8 -0
  62. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +11 -4
  63. package/corpus/templates/clips/actions/get-meeting.ts +9 -4
  64. package/corpus/templates/clips/actions/list-recordings.ts +16 -3
  65. package/corpus/templates/clips/actions/search-meetings.ts +1 -0
  66. package/corpus/templates/clips/actions/view-screen.ts +8 -1
  67. package/corpus/templates/clips/app/components/meetings/meeting-history-row.tsx +32 -1
  68. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +1 -1
  69. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +29 -1
  70. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  71. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +33 -4
  72. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +1 -0
  73. package/corpus/templates/clips/app/routes/access-request.approve.tsx +16 -9
  74. package/corpus/templates/clips/app/routes/embed.$shareId.tsx +17 -7
  75. package/corpus/templates/clips/app/routes/share.$shareId.tsx +17 -7
  76. package/corpus/templates/clips/changelog/2026-08-21-camera-bubble-black-circle.md +6 -0
  77. package/corpus/templates/clips/changelog/2026-08-22-screen-recordings-respect-the-microphone-toggle.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-08-22-the-recordings-library-no-longer-fails-right-after-server-start.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-08-23-the-agent-can-see-your-library-right-after-server-start.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/background.ts +1 -2
  81. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +39 -7
  82. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +21 -25
  83. package/corpus/templates/clips/desktop/src/app.tsx +53 -24
  84. package/corpus/templates/clips/desktop/src/lib/bubble-playback.ts +68 -0
  85. package/corpus/templates/clips/desktop/src/lib/recorder.ts +3 -0
  86. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +72 -14
  87. package/corpus/templates/clips/desktop/src/lib/updater.ts +8 -3
  88. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +162 -20
  89. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +43 -6
  90. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +150 -13
  91. package/corpus/templates/clips/desktop/src-tauri/src/tray.rs +12 -0
  92. package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +28 -3
  93. package/corpus/templates/clips/server/lib/emails.ts +17 -33
  94. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +11 -4
  95. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +140 -15
  96. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +12 -14
  97. package/corpus/templates/content/app/components/ui/pointer-lock.ts +1 -0
  98. package/corpus/templates/content/app/hooks/use-content-database.ts +18 -2
  99. package/corpus/templates/content/app/hooks/use-local-storage.ts +38 -22
  100. package/corpus/templates/content/app/i18n-data.ts +25 -0
  101. package/corpus/templates/content/app/routes.ts +3 -1
  102. package/corpus/templates/content/changelog/2026-08-22-code-blocks-inserted-from-the-slash-menu-no-longer-get-stuck.md +6 -0
  103. package/corpus/templates/content/changelog/2026-08-22-the-sidebar-page-tree-no-longer-flashes-empty-after-creating-a-page.md +6 -0
  104. package/corpus/templates/content/docs/solutions/2026-08-21-content-mermaid-rendering-shape.md +233 -0
  105. package/corpus/templates/content/server/plugins/agent-chat.ts +9 -2
  106. package/corpus/templates/content/vitest.config.ts +7 -1
  107. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +11 -4
  108. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +11 -4
  109. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +1383 -88
  110. package/corpus/templates/design/actions/generate-design.ts +98 -47
  111. package/corpus/templates/design/actions/get-design-system.ts +6 -1
  112. package/corpus/templates/design/actions/refresh-design-system-with-builder.ts +146 -0
  113. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +70 -26
  114. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +284 -136
  115. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +2057 -141
  116. package/corpus/templates/design/app/components/design/editor/DesignBottomToolbar.tsx +6 -2
  117. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +4 -4
  118. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +10 -1
  119. package/corpus/templates/design/app/components/design/multi-screen/alt-hover-measurement.ts +19 -2
  120. package/corpus/templates/design/app/components/design/multi-screen/types.ts +9 -2
  121. package/corpus/templates/design/app/components/layout/Header.tsx +15 -0
  122. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -2
  123. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -4
  124. package/corpus/templates/design/app/i18n-data.ts +1 -0
  125. package/corpus/templates/design/app/i18n-keyboard-shortcuts.ts +12 -0
  126. package/corpus/templates/design/app/lib/design-system-data.ts +68 -0
  127. package/corpus/templates/design/app/pages/DesignEditor.tsx +77 -35
  128. package/corpus/templates/design/app/pages/DesignSystems.tsx +136 -42
  129. package/corpus/templates/design/app/pages/Index.tsx +2 -0
  130. package/corpus/templates/design/app/pages/Templates.tsx +0 -10
  131. package/corpus/templates/design/app/pages/design-editor/code-layer-state.ts +10 -0
  132. package/corpus/templates/design/app/pages/design-editor/collab-sync.ts +50 -0
  133. package/corpus/templates/design/app/pages/design-editor/commands/apply-design-editor-command.ts +1 -1
  134. package/corpus/templates/design/app/pages/design-editor/commands/apply-file-content-update.ts +10 -8
  135. package/corpus/templates/design/app/pages/design-editor/commands/apply-local-content-update.ts +6 -6
  136. package/corpus/templates/design/app/pages/design-editor/commands/apply-pending-visual-styles-with-agent.ts +1 -1
  137. package/corpus/templates/design/app/pages/design-editor/commands/commit-visual-styles.ts +18 -7
  138. package/corpus/templates/design/app/pages/design-editor/commands/escape-hotkey.ts +4 -90
  139. package/corpus/templates/design/app/pages/design-editor/commands/layer-marquee-selection-change.ts +2 -1
  140. package/corpus/templates/design/app/pages/design-editor/commands/layer-selection-change.ts +4 -3
  141. package/corpus/templates/design/app/pages/design-editor/commands/screen-element-select.ts +12 -2
  142. package/corpus/templates/design/app/pages/design-editor/commands/screen-visual-style-change.ts +9 -2
  143. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-move-semantic-handoff.ts +1 -1
  144. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-semantic-handoff.ts +1 -1
  145. package/corpus/templates/design/app/pages/design-editor/commands/send-runtime-layer-state-semantic-handoff.ts +1 -1
  146. package/corpus/templates/design/app/pages/design-editor/commands/start-sidebar-resize.ts +1 -1
  147. package/corpus/templates/design/app/pages/design-editor/editor-state.ts +11 -1
  148. package/corpus/templates/design/app/pages/design-editor/effects/adopt-db-file-content.ts +11 -19
  149. package/corpus/templates/design/app/pages/design-editor/effects/observe-collab-text.ts +6 -6
  150. package/corpus/templates/design/app/pages/design-editor/effects/publish-agent-selection-context.ts +1 -1
  151. package/corpus/templates/design/app/pages/design-editor/effects/seed-collab-content.ts +12 -15
  152. package/corpus/templates/design/app/pages/design-editor/selection-state.ts +5 -59
  153. package/corpus/templates/design/app/pages/design-editor/tool-state.ts +8 -0
  154. package/corpus/templates/design/app/pages/design-editor/types.ts +3 -3
  155. package/corpus/templates/design/app/routes.ts +3 -1
  156. package/corpus/templates/design/changelog/2026-08-20-canvas-edits-patch-the-frame-instead-of-rebuilding-it.md +6 -0
  157. package/corpus/templates/design/changelog/2026-08-21-builder-design-system-imports-reconcile-after-indexing.md +6 -0
  158. package/corpus/templates/design/changelog/2026-08-21-draw-mode-needs-shift-y.md +6 -0
  159. package/corpus/templates/design/changelog/2026-08-21-eyedropper-shortcut.md +6 -0
  160. package/corpus/templates/design/changelog/2026-08-21-figma-style-alignment-guides-and-snapping.md +6 -0
  161. package/corpus/templates/design/changelog/2026-08-21-group-transforms-keep-the-selection.md +6 -0
  162. package/corpus/templates/design/changelog/2026-08-21-inspector-fields-keep-focus-on-enter.md +6 -0
  163. package/corpus/templates/design/changelog/2026-08-21-pen-alt-keeps-the-incoming-handle.md +6 -0
  164. package/corpus/templates/design/changelog/2026-08-21-pen-on-the-board-creates-one-vector.md +6 -0
  165. package/corpus/templates/design/changelog/2026-08-21-scale-a-multi-selection-from-the-group-handles.md +6 -0
  166. package/corpus/templates/design/changelog/2026-08-21-scale-resizes-text-with-the-object.md +6 -0
  167. package/corpus/templates/design/changelog/2026-08-21-selecting-another-object-keeps-the-scale-tool-armed.md +6 -0
  168. package/corpus/templates/design/changelog/2026-08-21-the-shape-tool-remembers-the-shape-you-picked.md +6 -0
  169. package/corpus/templates/design/changelog/2026-08-21-vectors-drawn-in-a-frame-land-where-you-drew-them.md +6 -0
  170. package/corpus/templates/design/changelog/2026-08-22-multi-screen-generation-no-longer-loses-a-saved-screens-layo.md +6 -0
  171. package/corpus/templates/design/changelog/2026-08-22-rename-and-search-fields-are-labeled-for-screen-readers.md +6 -0
  172. package/corpus/templates/design/package.json +2 -0
  173. package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +311 -0
  174. package/corpus/templates/design/shared/canvas-math.ts +612 -206
  175. package/corpus/templates/design/shared/pen-path.ts +37 -0
  176. package/corpus/templates/design/vitest.config.ts +7 -1
  177. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +11 -4
  178. package/corpus/templates/dispatch/actions/list-workspace-connections.ts +34 -3
  179. package/corpus/templates/dispatch/app/routes/integrations.tsx +55 -21
  180. package/corpus/templates/dispatch/app/routes.ts +3 -1
  181. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +11 -4
  182. package/corpus/templates/factory/.env.example +2 -7
  183. package/corpus/templates/factory/AGENTS.md +3 -0
  184. package/corpus/templates/factory/README.md +5 -3
  185. package/corpus/templates/factory/actions/create-factory.ts +16 -3
  186. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +2 -0
  187. package/corpus/templates/factory/actions/get-triage-item.ts +2 -0
  188. package/corpus/templates/factory/actions/list-factory-audit.ts +116 -36
  189. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  190. package/corpus/templates/factory/actions/list-triage-items.ts +22 -19
  191. package/corpus/templates/factory/actions/run-factory-automation.ts +7 -3
  192. package/corpus/templates/factory/actions/save-factory-automation.ts +5 -2
  193. package/corpus/templates/factory/actions/save-triage-config.ts +2 -8
  194. package/corpus/templates/factory/actions/start-builder-for-item.ts +21 -0
  195. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +229 -297
  196. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +397 -247
  197. package/corpus/templates/factory/app/components/factory/FactorySourceSettingsGroup.tsx +33 -0
  198. package/corpus/templates/factory/app/components/factory/NewFactoryForm.tsx +202 -162
  199. package/corpus/templates/factory/app/i18n/en-US.ts +32 -4
  200. package/corpus/templates/factory/app/routes/factory.tsx +84 -11
  201. package/corpus/templates/factory/app/routes.ts +3 -1
  202. package/corpus/templates/factory/changelog/2026-08-21-activity-runs-use-automation-display-names.md +6 -0
  203. package/corpus/templates/factory/changelog/2026-08-21-create-and-settings-source-cards.md +6 -0
  204. package/corpus/templates/factory/changelog/2026-08-21-keep-automations-visible-while-running.md +6 -0
  205. package/corpus/templates/factory/changelog/2026-08-21-nested-factory-automations-can-poll.md +6 -0
  206. package/corpus/templates/factory/changelog/2026-08-21-settings-sticky-unsaved-bar.md +6 -0
  207. package/corpus/templates/factory/server/connectors/credentials.ts +10 -5
  208. package/corpus/templates/factory/server/lib/factory-audit-report.ts +412 -0
  209. package/corpus/templates/factory/server/lib/factory-config-reconcile.ts +321 -0
  210. package/corpus/templates/factory/server/lib/factory-scope.ts +25 -2
  211. package/corpus/templates/factory/server/lib/require-factory-automation.ts +13 -4
  212. package/corpus/templates/factory/server/plugins/factory-migrations.ts +148 -4
  213. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +4 -6
  214. package/corpus/templates/factory/vitest.config.ts +17 -2
  215. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +11 -4
  216. package/corpus/templates/forms/app/routes/_app.settings.tsx +4 -1
  217. package/corpus/templates/forms/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  218. package/corpus/templates/forms/server/lib/public-form-ssr.ts +11 -1
  219. package/corpus/templates/forms/vitest.config.ts +1 -0
  220. package/corpus/templates/macros/.agents/skills/secrets/SKILL.md +11 -4
  221. package/corpus/templates/macros/app/routes.ts +3 -1
  222. package/corpus/templates/macros/vitest.config.ts +6 -1
  223. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +11 -4
  224. package/corpus/templates/mail/actions/manage-gmail-filters.ts +10 -2
  225. package/corpus/templates/mail/app/components/GoogleConnectBanner.tsx +100 -37
  226. package/corpus/templates/mail/app/components/email/IntegrationsSidebar.tsx +14 -2
  227. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +66 -36
  228. package/corpus/templates/mail/app/hooks/use-google-auth.ts +2 -0
  229. package/corpus/templates/mail/app/lib/google-oauth-setup.ts +17 -0
  230. package/corpus/templates/mail/app/pages/InboxPage.tsx +69 -9
  231. package/corpus/templates/mail/app/routes/$.tsx +9 -0
  232. package/corpus/templates/mail/app/routes/$view.$threadId.tsx +23 -1
  233. package/corpus/templates/mail/app/routes/$view.tsx +47 -1
  234. package/corpus/templates/mail/app/routes.ts +3 -1
  235. package/corpus/templates/mail/changelog/2026-08-22-gmail-can-now-connect-with-the-shared-google-oauth.md +6 -0
  236. package/corpus/templates/mail/changelog/2026-08-22-gmail-filters-now-shows-the-real-error.md +6 -0
  237. package/corpus/templates/mail/changelog/2026-08-22-unknown-mail-urls-now-show-the-404-page.md +6 -0
  238. package/corpus/templates/mail/server/handlers/google-auth.ts +11 -2
  239. package/corpus/templates/mail/server/lib/google-auth.ts +92 -12
  240. package/corpus/templates/mail/server/onboarding.ts +66 -18
  241. package/corpus/templates/mail/vitest.config.ts +6 -1
  242. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +11 -4
  243. package/corpus/templates/plan/app/routes/settings.tsx +4 -1
  244. package/corpus/templates/plan/app/routes.ts +3 -1
  245. package/corpus/templates/plan/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  246. package/corpus/templates/plan/netlify.toml +1 -1
  247. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +11 -4
  248. package/corpus/templates/slides/actions/patch-deck.ts +79 -10
  249. package/corpus/templates/slides/actions/update-slide.ts +11 -1
  250. package/corpus/templates/slides/app/components/deck/SlideRenderer.tsx +14 -4
  251. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +10 -52
  252. package/corpus/templates/slides/app/components/editor/GoogleDocImportHint.tsx +8 -53
  253. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +9 -75
  254. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +8 -60
  255. package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +10 -2
  256. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +19 -7
  257. package/corpus/templates/slides/app/lib/sanitize-slide-html.ts +49 -36
  258. package/corpus/templates/slides/app/routes/access-request.approve.tsx +16 -9
  259. package/corpus/templates/slides/app/routes.ts +3 -1
  260. package/corpus/templates/slides/changelog/2026-08-22-already-uploaded-chat-images-are-no-longer-dropped.md +6 -0
  261. package/corpus/templates/slides/changelog/2026-08-22-google-drive-and-slides-can-now-connect-with-the-shared-google-oauth.md +6 -0
  262. package/corpus/templates/slides/changelog/2026-08-22-multi-slide-repairs-now-report-slides-that-still-overflow.md +6 -0
  263. package/corpus/templates/slides/changelog/2026-08-22-update-slide-now-reports-which-batched-edit-was-skipped.md +6 -0
  264. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +52 -1
  265. package/corpus/templates/slides/server/lib/chat-attachments.ts +29 -3
  266. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +66 -16
  267. package/corpus/templates/slides/server/lib/slide-content-patch.ts +13 -2
  268. package/corpus/templates/slides/server/plugins/agent-chat.ts +5 -2
  269. package/corpus/templates/slides/tsconfig.json +5 -0
  270. package/corpus/templates/slides/vitest.config.ts +6 -1
  271. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +11 -4
  272. package/corpus/templates/tasks/app/routes/settings.tsx +4 -1
  273. package/corpus/templates/tasks/app/routes.ts +3 -1
  274. package/corpus/templates/tasks/changelog/2026-08-22-the-extensions-link-now-opens-the-extensions-tab-instead-o.md +6 -0
  275. package/corpus/templates/tasks/vitest.config.ts +7 -1
  276. package/dist/action.d.ts +91 -0
  277. package/dist/action.js +50 -0
  278. package/dist/agent/abort-reasons.d.ts +38 -0
  279. package/dist/agent/abort-reasons.js +49 -0
  280. package/dist/agent/engine/ai-sdk-engine.js +8 -5
  281. package/dist/agent/engine/anthropic-engine.js +7 -5
  282. package/dist/agent/engine/first-event-timeout.d.ts +42 -17
  283. package/dist/agent/engine/first-event-timeout.js +67 -25
  284. package/dist/agent/production-agent.d.ts +23 -0
  285. package/dist/agent/production-agent.js +107 -102
  286. package/dist/agent/run-loop-with-resume.d.ts +2 -28
  287. package/dist/agent/run-loop-with-resume.js +25 -40
  288. package/dist/agent/run-manager.js +5 -4
  289. package/dist/agent/run-store.d.ts +55 -0
  290. package/dist/agent/run-store.js +124 -1
  291. package/dist/agent/tool-search.js +2 -1
  292. package/dist/agent/types.d.ts +9 -4
  293. package/dist/app-config/configuration-error.d.ts +11 -0
  294. package/dist/app-config/configuration-error.js +14 -0
  295. package/dist/app-config/index.d.ts +1 -0
  296. package/dist/app-config/index.js +1 -0
  297. package/dist/app-config/integrations.d.ts +1 -0
  298. package/dist/app-config/integrations.js +10 -0
  299. package/dist/app-config/plugins.d.ts +34 -0
  300. package/dist/app-config/plugins.js +39 -0
  301. package/dist/app-config/run-lifecycle-invariants.d.ts +18 -9
  302. package/dist/app-config/run-lifecycle-invariants.js +18 -25
  303. package/dist/app-config/schema.d.ts +16 -0
  304. package/dist/app-config/schema.js +2 -0
  305. package/dist/chat-threads/schema-migrations.js +20 -0
  306. package/dist/chat-threads/store.js +21 -4
  307. package/dist/cli/native-dependencies.d.ts +4 -0
  308. package/dist/cli/native-dependencies.js +15 -0
  309. package/dist/client/EnvironmentBadge.d.ts +1 -1
  310. package/dist/client/EnvironmentBadge.js +40 -5
  311. package/dist/client/MultiTabAssistantChat.d.ts +1 -1
  312. package/dist/client/MultiTabAssistantChat.js +35 -14
  313. package/dist/client/agent-chat/index.d.ts +1 -1
  314. package/dist/client/agent-chat/index.js +1 -1
  315. package/dist/client/agent-page/use-jobs.d.ts +2 -1
  316. package/dist/client/agent-page/use-jobs.js +3 -5
  317. package/dist/client/agent-sidebar-state.js +3 -1
  318. package/dist/client/blocks/library/code-tabs.js +5 -0
  319. package/dist/client/blocks/library/code.js +1 -0
  320. package/dist/client/chat-first/apps-rail.js +2 -2
  321. package/dist/client/chat-model-groups.d.ts +12 -0
  322. package/dist/client/chat-model-groups.js +3 -2
  323. package/dist/client/integrations/GoogleProductLogo.d.ts +5 -0
  324. package/dist/client/integrations/GoogleProductLogo.js +45 -0
  325. package/dist/client/integrations/index.d.ts +2 -0
  326. package/dist/client/integrations/index.js +2 -0
  327. package/dist/client/integrations/workspace-provider-oauth.d.ts +8 -0
  328. package/dist/client/integrations/workspace-provider-oauth.js +13 -0
  329. package/dist/client/resources/mcp-integration-catalog.js +0 -29
  330. package/dist/client/settings/SettingsTabsPage.js +10 -6
  331. package/dist/client/sharing/ShareButton.js +11 -2
  332. package/dist/client/use-chat-models.d.ts +6 -0
  333. package/dist/client/use-chat-models.js +10 -0
  334. package/dist/client/use-db-sync.js +27 -9
  335. package/dist/connections/catalog.d.ts +111 -9
  336. package/dist/connections/catalog.js +86 -30
  337. package/dist/db/create-get-db.js +18 -0
  338. package/dist/db/ddl-guard.d.ts +0 -4
  339. package/dist/db/ddl-guard.js +46 -0
  340. package/dist/deploy/build.d.ts +19 -0
  341. package/dist/deploy/build.js +190 -16
  342. package/dist/deploy/function-bundle.d.ts +45 -0
  343. package/dist/deploy/function-bundle.js +337 -0
  344. package/dist/deploy/workspace-deploy.js +19 -1
  345. package/dist/eject/workspace-connections.js +4 -0
  346. package/dist/email-catalog/registry.d.ts +4 -0
  347. package/dist/email-catalog/registry.js +79 -14
  348. package/dist/extensions/content-patch.js +14 -2
  349. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  350. package/dist/integrations/plugin.d.ts +10 -0
  351. package/dist/integrations/plugin.js +40 -6
  352. package/dist/jobs/actions/run-automation-now.d.ts +2 -1
  353. package/dist/jobs/actions/run-automation-now.js +11 -5
  354. package/dist/jobs/frontmatter.js +53 -2
  355. package/dist/jobs/run-now.d.ts +11 -1
  356. package/dist/jobs/run-now.js +42 -7
  357. package/dist/jobs/scheduler.d.ts +1 -0
  358. package/dist/jobs/scheduler.js +2 -1
  359. package/dist/localization/core-messages/ar-SA.js +3 -0
  360. package/dist/localization/core-messages/de-DE.js +3 -0
  361. package/dist/localization/core-messages/en-US.d.ts +3 -0
  362. package/dist/localization/core-messages/en-US.js +3 -0
  363. package/dist/localization/core-messages/es-ES.js +3 -0
  364. package/dist/localization/core-messages/fr-FR.js +3 -0
  365. package/dist/localization/core-messages/hi-IN.js +3 -0
  366. package/dist/localization/core-messages/ja-JP.js +3 -0
  367. package/dist/localization/core-messages/ko-KR.js +3 -0
  368. package/dist/localization/core-messages/pt-BR.js +3 -0
  369. package/dist/localization/core-messages/zh-CN.js +3 -0
  370. package/dist/localization/core-messages/zh-TW.js +3 -0
  371. package/dist/localization/core-messages.d.ts +3 -0
  372. package/dist/localization/default-messages.d.ts +2 -5
  373. package/dist/localization/default-messages.js +2 -5
  374. package/dist/mcp/build-server.d.ts +9 -0
  375. package/dist/mcp/build-server.js +37 -8
  376. package/dist/mcp-client/oauth-client.d.ts +7 -0
  377. package/dist/mcp-client/oauth-client.js +12 -1
  378. package/dist/oauth-tokens/index.d.ts +1 -1
  379. package/dist/oauth-tokens/index.js +1 -1
  380. package/dist/oauth-tokens/lifecycle.d.ts +11 -0
  381. package/dist/oauth-tokens/lifecycle.js +17 -0
  382. package/dist/oauth-tokens/store.js +7 -0
  383. package/dist/observability/posthog-ai.d.ts +15 -1
  384. package/dist/observability/posthog-ai.js +24 -12
  385. package/dist/observability/routes.d.ts +3 -3
  386. package/dist/observability/traces.js +158 -28
  387. package/dist/onboarding/app-profile.js +2 -2
  388. package/dist/onboarding/plugin.js +10 -2
  389. package/dist/onboarding/types.d.ts +2 -0
  390. package/dist/provider-api/actions/custom-provider-registration.d.ts +1 -1
  391. package/dist/provider-api/actions/provider-api.d.ts +2 -2
  392. package/dist/provider-api/index.js +2 -0
  393. package/dist/resources/store.js +13 -4
  394. package/dist/scripts/agent-engines/list-agent-engines.js +29 -3
  395. package/dist/secrets/register-framework-secrets.js +1 -1
  396. package/dist/server/action-discovery.js +5 -0
  397. package/dist/server/agent-chat/action-filters-a2a.d.ts +27 -3
  398. package/dist/server/agent-chat/action-filters-a2a.js +48 -9
  399. package/dist/server/agent-chat-plugin.js +36 -9
  400. package/dist/server/agent-discovery.js +43 -20
  401. package/dist/server/auth.js +18 -16
  402. package/dist/server/beta-opt-out-html.js +45 -4
  403. package/dist/server/better-auth-instance.d.ts +2 -1
  404. package/dist/server/better-auth-instance.js +23 -7
  405. package/dist/server/builder-design-systems.d.ts +4 -1
  406. package/dist/server/builder-design-systems.js +87 -6
  407. package/dist/server/builder-oauth.d.ts +1 -7
  408. package/dist/server/builder-oauth.js +80 -163
  409. package/dist/server/core-routes-plugin.d.ts +29 -0
  410. package/dist/server/core-routes-plugin.js +100 -20
  411. package/dist/server/default-plugins.d.ts +18 -0
  412. package/dist/server/default-plugins.js +22 -0
  413. package/dist/server/edge.d.ts +1 -0
  414. package/dist/server/edge.js +1 -0
  415. package/dist/server/framework-request-handler.js +31 -3
  416. package/dist/server/google-oauth.d.ts +3 -0
  417. package/dist/server/google-oauth.js +3 -0
  418. package/dist/server/index.d.ts +4 -4
  419. package/dist/server/index.js +3 -3
  420. package/dist/server/onboarding-html.js +37 -3
  421. package/dist/server/realtime-token.d.ts +1 -1
  422. package/dist/server/transcribe-voice.d.ts +1 -1
  423. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  424. package/dist/server/workspace-provider-oauth.js +72 -20
  425. package/dist/shared/agent-sidebar-url.d.ts +1 -0
  426. package/dist/shared/agent-sidebar-url.js +1 -0
  427. package/dist/shared/environment-lanes.d.ts +2 -0
  428. package/dist/shared/environment-lanes.js +3 -1
  429. package/dist/shared/index.d.ts +3 -1
  430. package/dist/shared/index.js +3 -1
  431. package/dist/shared/surface-visibility.d.ts +31 -0
  432. package/dist/shared/surface-visibility.js +57 -0
  433. package/dist/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  434. package/dist/templates/chat/app/routes.ts +3 -1
  435. package/dist/templates/chat/vitest.config.ts +8 -0
  436. package/dist/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  437. package/dist/templates/default/app/routes.ts +3 -1
  438. package/dist/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  439. package/dist/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
  440. package/dist/tracking/registry.d.ts +11 -0
  441. package/dist/tracking/registry.js +5 -2
  442. package/dist/triggers/actions.js +10 -3
  443. package/dist/usage/store.js +23 -3
  444. package/dist/user-profile/actions/get-auth-methods.js +18 -5
  445. package/dist/vite/client.js +24 -5
  446. package/docs/content/actions-access-control.mdx +43 -4
  447. package/docs/content/actions-defining.mdx +16 -0
  448. package/docs/content/template-clips-capture-everywhere.mdx +29 -30
  449. package/docs/content/template-clips-developers.mdx +4 -4
  450. package/docs/content/template-clips.mdx +3 -1
  451. package/package.json +2 -2
  452. package/src/eject/workspace-connections.ts +4 -0
  453. package/src/templates/chat/.agents/skills/secrets/SKILL.md +11 -4
  454. package/src/templates/chat/app/routes.ts +3 -1
  455. package/src/templates/chat/vitest.config.ts +8 -0
  456. package/src/templates/default/.agents/skills/secrets/SKILL.md +11 -4
  457. package/src/templates/default/app/routes.ts +3 -1
  458. package/src/templates/headless/.agents/skills/secrets/SKILL.md +11 -4
  459. package/src/templates/workspace-core/.agents/skills/secrets/SKILL.md +11 -4
@@ -787,6 +787,7 @@ import { postShaderFillPreviewClearToPreviewIframes } from "./design-editor/text
787
787
  import {
788
788
  getDesignBottomToolbarMode,
789
789
  getSingleScreenCreationTool,
790
+ resolveToolAfterSelection,
790
791
  shouldAutoEnableDrawOverlay,
791
792
  } from "./design-editor/tool-state";
792
793
  import {
@@ -956,6 +957,9 @@ function DesignEditor() {
956
957
  // Editor state
957
958
  const [mode, setMode] = useState<EditorMode>("edit");
958
959
  const [activeTool, setActiveTool] = useState<DesignTool>("move");
960
+ // Drawing drops activeTool back to move (Figma parity), so the shape group
961
+ // button cannot read its own identity off it.
962
+ const [shapeTool, setShapeTool] = useState<ShapeTool>("rect");
959
963
  // The frame tool draws a top-level SCREEN or a plain FRAME container. Made
960
964
  // explicit because deciding it from where the drag started is unguessable.
961
965
  const [frameToolDraws, setFrameToolDraws] = useState<"screen" | "frame">(
@@ -1360,7 +1364,7 @@ function DesignEditor() {
1360
1364
  } | null>(null);
1361
1365
  const reviewFocusNonceRef = useRef(0);
1362
1366
  const [activeLeftPanel, setActiveLeftPanel] =
1363
- useState<DesignLeftPanel>("file");
1367
+ useState<DesignLeftPanel | null>("file");
1364
1368
  const [activeCodeFile, setActiveCodeFile] =
1365
1369
  useState<CodeWorkbenchActiveFile | null>(null);
1366
1370
  const initialSearchCommandAppliedForIdRef = useRef<string | null>(null);
@@ -6092,9 +6096,9 @@ function DesignEditor() {
6092
6096
  latestActiveContentRef.current = activeContent;
6093
6097
  }, [activeContent]);
6094
6098
  useEffect(() => {
6095
- if (!initialGenerationChromeLimited || activeLeftPanel === "agent") return;
6099
+ if (!initialGenerationChromeLimited) return;
6096
6100
  setActiveLeftPanel("agent");
6097
- }, [activeLeftPanel, initialGenerationChromeLimited]);
6101
+ }, [initialGenerationChromeLimited]);
6098
6102
  const fileContentById = useMemo(() => {
6099
6103
  const map = new Map<string, string>();
6100
6104
  for (const file of files) {
@@ -8110,13 +8114,18 @@ function DesignEditor() {
8110
8114
  * engine handles persistence identically to in-screen elements.
8111
8115
  */
8112
8116
  const handleBoardDrawPrimitive = useCallback(
8113
- (primitive: CanvasPrimitiveInsert) => {
8117
+ (
8118
+ primitive: CanvasPrimitiveInsert,
8119
+ options?: { nextTool?: "move" | "pen" },
8120
+ ) => {
8114
8121
  if (!boardFileId || !canEditDesign) return false;
8115
8122
  const result = handleCreatePrimitive(boardFileId, primitive);
8116
8123
  if (!result) return false;
8117
8124
  const nodeId = typeof result === "string" ? result : primitive.nodeId;
8118
8125
  if (nodeId) {
8119
- handlePrimitiveCreated(boardFileId, nodeId);
8126
+ // Without the caller's tool intent a board pen commit lands on Move,
8127
+ // which disarms the Pen mid-path — a screen insert keeps it.
8128
+ handlePrimitiveCreated(boardFileId, nodeId, options);
8120
8129
  }
8121
8130
 
8122
8131
  return result;
@@ -8369,6 +8378,7 @@ function DesignEditor() {
8369
8378
  blurActiveDesignEditableTarget();
8370
8379
  flushSync(() => {
8371
8380
  setActiveTool(tool);
8381
+ setShapeTool(tool);
8372
8382
  if (viewModeRef.current === "single" && activeFile) {
8373
8383
  setMode("edit");
8374
8384
  setDrawMode(false);
@@ -9010,7 +9020,7 @@ function DesignEditor() {
9010
9020
  handleBreakpointBarSelect(undefined);
9011
9021
  }
9012
9022
  }
9013
- setActiveTool("move");
9023
+ setActiveTool(resolveToolAfterSelection);
9014
9024
  setMode("edit");
9015
9025
  },
9016
9026
  [clearPendingOverviewLayerSelectionTimer, handleBreakpointBarSelect],
@@ -9391,6 +9401,7 @@ function DesignEditor() {
9391
9401
  elementInfo?: ElementInfo;
9392
9402
  /** Pre-gesture values, for the pending-edit revert stack. */
9393
9403
  originalStyles?: Record<string, string>;
9404
+ preserveSelection?: boolean;
9394
9405
  } = {},
9395
9406
  ) =>
9396
9407
  runCommitVisualStyles(
@@ -9889,7 +9900,10 @@ function DesignEditor() {
9889
9900
  selector: string,
9890
9901
  styles: Record<string, string>,
9891
9902
  elementInfo?: ElementInfo,
9892
- metadata?: { originalStyles?: Record<string, string> },
9903
+ metadata?: {
9904
+ originalStyles?: Record<string, string>;
9905
+ preserveSelection?: boolean;
9906
+ },
9893
9907
  ) => {
9894
9908
  if (!activeFile?.id) return;
9895
9909
  // The gesture already moved the live DOM, so this never needs the
@@ -9901,6 +9915,7 @@ function DesignEditor() {
9901
9915
  runtimeApplied: true,
9902
9916
  elementInfo,
9903
9917
  originalStyles: metadata?.originalStyles,
9918
+ preserveSelection: metadata?.preserveSelection,
9904
9919
  });
9905
9920
  },
9906
9921
  [activeFile?.id, commitVisualStyles],
@@ -10048,7 +10063,10 @@ function DesignEditor() {
10048
10063
  selector: string,
10049
10064
  styles: Record<string, string>,
10050
10065
  elementInfo?: ElementInfo,
10051
- metadata?: { originalStyles?: Record<string, string> },
10066
+ metadata?: {
10067
+ originalStyles?: Record<string, string>;
10068
+ preserveSelection?: boolean;
10069
+ },
10052
10070
  ) =>
10053
10071
  runScreenVisualStyleChange(
10054
10072
  {
@@ -13179,7 +13197,6 @@ function DesignEditor() {
13179
13197
  activeBreakpointWidthStateRef,
13180
13198
  activeTool,
13181
13199
  cancelActiveEditorDrag,
13182
- codeLayerOwnerByNodeIdRef,
13183
13200
  drawMode,
13184
13201
  enterOverviewFromZoom,
13185
13202
  focusedAnnotationSending,
@@ -13192,11 +13209,8 @@ function DesignEditor() {
13192
13209
  overviewAnnotationSending,
13193
13210
  pinMode,
13194
13211
  selectedElement,
13195
- selectedLayerIdsState,
13196
- setActiveFileId,
13197
13212
  setActiveTool,
13198
13213
  setDrawMode,
13199
- setExpandedLayerIds,
13200
13214
  setHoveredElement,
13201
13215
  setMode,
13202
13216
  setOverviewClearSelectionRequest,
@@ -13221,7 +13235,6 @@ function DesignEditor() {
13221
13235
  overviewAnnotationSending,
13222
13236
  pinMode,
13223
13237
  selectedElement,
13224
- selectedLayerIdsState,
13225
13238
  viewMode,
13226
13239
  ],
13227
13240
  );
@@ -13478,12 +13491,8 @@ function DesignEditor() {
13478
13491
  owner.node.parentId,
13479
13492
  );
13480
13493
  if (!parentOwner || parentOwner.fileId !== owner.fileId) return;
13481
- // BUG-ESCAPE-SHELL (same mechanism as handleEscapeHotkey's pop walk): the
13482
- // flat ownership map still resolves a top-level layer's parentId to the
13483
- // collapsed <html>/<body> shell node, which the layers panel never shows
13484
- // as selectable. Without this guard, Shift+Enter/"\\" on a top-level
13485
- // layer would select <body> instead of no-op'ing like the comment above
13486
- // already documents.
13494
+ // The flat ownership map still resolves a top-level layer's parentId to
13495
+ // the collapsed <html>/<body> shell node the layers panel never shows.
13487
13496
  if (!hasSelectableCodeLayerParent({ parentNode: parentOwner.node })) {
13488
13497
  return;
13489
13498
  }
@@ -15624,6 +15633,20 @@ function DesignEditor() {
15624
15633
  selectedLayerTargetsRef.current = selectedLayerTargets;
15625
15634
  }, [selectedLayerTargets]);
15626
15635
 
15636
+ /** The overview canvas keeps a layer's owning screen in `selectedScreenIds`
15637
+ * (z-order and "topmost screen" read it), so without this the screen's own
15638
+ * full-bleed SelectionBox stays mounted over the element and its drag
15639
+ * surface swallows the gesture — the frame moves instead of the layer. */
15640
+ const selectedElementScreenId = useMemo(() => {
15641
+ const first = selectedLayerTargets[0];
15642
+ if (!first) return null;
15643
+ return selectedLayerTargets.every(
15644
+ (target) => target.fileId === first.fileId,
15645
+ )
15646
+ ? first.fileId
15647
+ : null;
15648
+ }, [selectedLayerTargets]);
15649
+
15627
15650
  const selectedLayerSelectorGroupsByScreen = useMemo(() => {
15628
15651
  const groupsByScreen: Record<string, string[][]> = {};
15629
15652
  selectedLayerTargets.forEach((target) => {
@@ -17869,7 +17892,7 @@ function DesignEditor() {
17869
17892
  }),
17870
17893
  );
17871
17894
  setActiveFileId(pickedId);
17872
- setActiveTool("move");
17895
+ setActiveTool(resolveToolAfterSelection);
17873
17896
  setMode("edit");
17874
17897
  if (activeBreakpointWidthStateRef.current !== undefined) {
17875
17898
  handleBreakpointBarSelect(undefined);
@@ -19007,10 +19030,13 @@ function DesignEditor() {
19007
19030
  onRequestTweaks: handleRequestTweaks,
19008
19031
  onStyleChange: handleStyleChange,
19009
19032
  onStylesChange: handleStylesChange,
19010
- motionKeyframeState,
19011
- onToggleMotionKeyframe: canEditDesign
19012
- ? handleToggleMotionKeyframe
19033
+ motionKeyframeState: SHOW_DESIGN_SECONDARY_LEFT_PANELS
19034
+ ? motionKeyframeState
19013
19035
  : undefined,
19036
+ onToggleMotionKeyframe:
19037
+ SHOW_DESIGN_SECONDARY_LEFT_PANELS && canEditDesign
19038
+ ? handleToggleMotionKeyframe
19039
+ : undefined,
19014
19040
  breakpointContext,
19015
19041
  onExport: handleInspectorExport,
19016
19042
  onRenderExportPreview: handleRenderExportPreview,
@@ -19083,15 +19109,23 @@ function DesignEditor() {
19083
19109
  : undefined
19084
19110
  }
19085
19111
  motionOpen={motionDockOpen}
19086
- motionDisabled={!activeFile}
19112
+ motionDisabled={!activeFile || initialGenerationChromeLimited}
19087
19113
  projectMenu={hostEmbeddedEditor ? null : projectMenu}
19088
19114
  onMotionToggle={() => setMotionDockOpenAnimated(!motionDockOpen)}
19089
- onPanelChange={setActiveLeftPanel}
19115
+ onPanelChange={(panel) => {
19116
+ if (panel === null && initialGenerationChromeLimited) return;
19117
+ setActiveLeftPanel(panel);
19118
+ }}
19090
19119
  />
19091
19120
  <div
19092
19121
  ref={leftSidebarContentRef}
19093
- className="flex min-h-0 max-w-[calc(100dvw-57px)] shrink-0 flex-col border-r border-[var(--design-editor-panel-divider-color)] bg-[var(--design-editor-panel-bg)] transition-[width] duration-150 ease-out md:max-w-none"
19094
- style={{ width: leftContentWidth }}
19122
+ aria-hidden={activeLeftPanel === null}
19123
+ className={cn(
19124
+ "flex min-h-0 max-w-[calc(100dvw-57px)] shrink-0 flex-col overflow-hidden border-r border-[var(--design-editor-panel-divider-color)] bg-[var(--design-editor-panel-bg)] transition-[width] duration-150 ease-out md:max-w-none",
19125
+ activeLeftPanel === null &&
19126
+ "pointer-events-none invisible border-r-0",
19127
+ )}
19128
+ style={{ width: activeLeftPanel ? leftContentWidth : 0 }}
19095
19129
  >
19096
19130
  <div
19097
19131
  className={cn(
@@ -19325,13 +19359,15 @@ function DesignEditor() {
19325
19359
  </>
19326
19360
  ) : null}
19327
19361
  </div>
19328
- <div
19329
- role="separator"
19330
- aria-orientation="vertical"
19331
- aria-label={t("layersPanel.title")}
19332
- className="absolute right-[-2px] top-0 z-[80] h-full w-1 cursor-col-resize bg-transparent transition-colors hover:bg-[var(--design-editor-selection-color)]"
19333
- onPointerDown={(event) => startSidebarResize("left", event)}
19334
- />
19362
+ {activeLeftPanel ? (
19363
+ <div
19364
+ role="separator"
19365
+ aria-orientation="vertical"
19366
+ aria-label={t("layersPanel.title")}
19367
+ className="absolute right-[-2px] top-0 z-[80] h-full w-1 cursor-col-resize bg-transparent transition-colors hover:bg-[var(--design-editor-selection-color)]"
19368
+ onPointerDown={(event) => startSidebarResize("left", event)}
19369
+ />
19370
+ ) : null}
19335
19371
  </div>
19336
19372
  ) : null}
19337
19373
 
@@ -19350,6 +19386,7 @@ function DesignEditor() {
19350
19386
  pinMode={pinMode}
19351
19387
  drawMode={drawMode}
19352
19388
  activeTool={activeTool}
19389
+ shapeTool={shapeTool}
19353
19390
  isOverview={viewMode === "overview"}
19354
19391
  hasActiveFile={Boolean(activeFile)}
19355
19392
  onMove={handleMoveTool}
@@ -19813,6 +19850,7 @@ function DesignEditor() {
19813
19850
  cameraCommand={cameraCommand}
19814
19851
  activeId={activeFileId}
19815
19852
  selectedScreenIds={overviewSelectedScreenIds}
19853
+ selectedElementScreenId={selectedElementScreenId}
19816
19854
  hiddenScreenIds={hiddenLayerIds}
19817
19855
  lockedScreenIds={lockedLayerIds}
19818
19856
  fullViewScreenIds={fullViewScreenIds}
@@ -20467,7 +20505,11 @@ function DesignEditor() {
20467
20505
  closing. Canvas remains visible above.
20468
20506
  Preview-only scrubbing fires a motion-preview postMessage to the
20469
20507
  canvas iframe; track/duration edits autosave through apply-motion-edit. */}
20470
- {!hostOwnsChrome && activeFile && motionDockMounted ? (
20508
+ {!hostOwnsChrome &&
20509
+ SHOW_DESIGN_SECONDARY_LEFT_PANELS &&
20510
+ !initialGenerationChromeLimited &&
20511
+ activeFile &&
20512
+ motionDockMounted ? (
20471
20513
  <MotionDock
20472
20514
  tracks={motionTracks}
20473
20515
  durationMs={motionDurationMs}
@@ -26,6 +26,7 @@ import {
26
26
  useCallback,
27
27
  useEffect,
28
28
  useMemo,
29
+ useRef,
29
30
  useState,
30
31
  type ReactNode,
31
32
  } from "react";
@@ -72,6 +73,12 @@ import {
72
73
  } from "@/lib/design-system-preview";
73
74
 
74
75
  import { QueryErrorState } from "../components/QueryErrorState";
76
+ import {
77
+ builderRefreshKey,
78
+ parseDesignSystemData,
79
+ shouldRefreshBuilderDesignSystem,
80
+ type DesignSystemData,
81
+ } from "../lib/design-system-data";
75
82
 
76
83
  interface DesignSystem {
77
84
  id: string;
@@ -88,29 +95,21 @@ interface DesignSystem {
88
95
  updatedAt?: string;
89
96
  }
90
97
 
91
- interface DesignSystemData {
92
- colors?: {
93
- primary?: unknown;
94
- secondary?: unknown;
95
- accent?: unknown;
96
- background?: unknown;
97
- surface?: unknown;
98
- text?: unknown;
99
- textMuted?: unknown;
100
- };
101
- typography?: {
102
- headingFont?: unknown;
103
- bodyFont?: unknown;
104
- headingWeight?: unknown;
105
- bodyWeight?: unknown;
106
- };
107
- spacing?: Record<string, unknown>;
108
- borders?: Record<string, unknown>;
109
- logos?: Array<{ url?: string; name?: string; variant?: string }>;
110
- defaults?: Record<string, unknown>;
111
- notes?: unknown;
112
- /** The source system's own named vocabulary; absent on kits predating it. */
113
- tokens?: unknown;
98
+ type BuilderRefreshResult = {
99
+ synced: boolean;
100
+ status?: string;
101
+ rejectedTokenCount?: number;
102
+ };
103
+
104
+ function isTerminalBuilderStatus(status?: string): boolean {
105
+ return (
106
+ status === "ready" ||
107
+ status === "complete" ||
108
+ status === "completed" ||
109
+ status === "error" ||
110
+ status === "failed" ||
111
+ status === "cancelled"
112
+ );
114
113
  }
115
114
 
116
115
  export default function DesignSystems() {
@@ -132,6 +131,19 @@ export default function DesignSystems() {
132
131
  const setDefaultMutation = useActionMutation("set-default-design-system");
133
132
  const deleteMutation = useActionMutation("delete-design-system");
134
133
  const updateMutation = useActionMutation("update-design-system");
134
+ const refreshBuilderSystemMutation = useActionMutation<
135
+ BuilderRefreshResult,
136
+ { id: string }
137
+ >("refresh-design-system-with-builder", {
138
+ skipActionQueryInvalidation: true,
139
+ });
140
+ const refreshBuilderSystemRef = useRef(
141
+ refreshBuilderSystemMutation.mutateAsync,
142
+ );
143
+ refreshBuilderSystemRef.current = refreshBuilderSystemMutation.mutateAsync;
144
+ const settledBuilderRefreshesRef = useRef(new Set<string>());
145
+ const stoppedBuilderRefreshesRef = useRef(new Set<string>());
146
+ const activeBuilderRefreshesRef = useRef(new Set<string>());
135
147
 
136
148
  const designSystems = data?.designSystems ?? [];
137
149
  const selectedDesignSystemId = searchParams.get("designSystemId");
@@ -362,13 +374,107 @@ export default function DesignSystems() {
362
374
  });
363
375
  }, [selectedSystemIds, queryClient, exitSelectionMode, deleteMutation, t]);
364
376
 
365
- const parseData = (dataStr: string): DesignSystemData | null => {
366
- try {
367
- return JSON.parse(dataStr);
368
- } catch {
369
- return null;
377
+ useEffect(() => {
378
+ const builderSystemEntries = designSystems
379
+ .filter(shouldRefreshBuilderDesignSystem)
380
+ .map((system) => ({
381
+ id: system.id,
382
+ key: builderRefreshKey(system),
383
+ }))
384
+ .filter(
385
+ ({ key }) =>
386
+ !settledBuilderRefreshesRef.current.has(key) &&
387
+ !stoppedBuilderRefreshesRef.current.has(key) &&
388
+ !activeBuilderRefreshesRef.current.has(key),
389
+ );
390
+ if (builderSystemEntries.length === 0) return;
391
+
392
+ let disposed = false;
393
+ const timers: Array<ReturnType<typeof setTimeout>> = [];
394
+ const maxAttempts = 5;
395
+ const maxPolls = 3;
396
+ const retryDelayMs = 5_000;
397
+ const retryPollDelayMs = 30_000;
398
+
399
+ const scheduleRetry = (
400
+ entry: { id: string; key: string },
401
+ delayMs: number,
402
+ attempt: number,
403
+ pollCount: number,
404
+ ): void => {
405
+ if (disposed) return;
406
+ timers.push(
407
+ setTimeout(() => {
408
+ void refresh(entry, attempt, pollCount);
409
+ }, delayMs),
410
+ );
411
+ };
412
+
413
+ const refresh = async (
414
+ entry: { id: string; key: string },
415
+ attempt: number,
416
+ pollCount: number,
417
+ ): Promise<void> => {
418
+ try {
419
+ const result = await refreshBuilderSystemRef.current({ id: entry.id });
420
+ if (disposed) return;
421
+ if (result.synced) {
422
+ activeBuilderRefreshesRef.current.delete(entry.key);
423
+ settledBuilderRefreshesRef.current.add(entry.key);
424
+ await queryClient.invalidateQueries({
425
+ queryKey: ["action", "list-design-systems"],
426
+ });
427
+ return;
428
+ }
429
+ if (result.status === "conflict") {
430
+ activeBuilderRefreshesRef.current.delete(entry.key);
431
+ stoppedBuilderRefreshesRef.current.add(entry.key);
432
+ await queryClient.invalidateQueries({
433
+ queryKey: ["action", "list-design-systems"],
434
+ });
435
+ return;
436
+ }
437
+ if (result.status === "incomplete" || result.rejectedTokenCount) {
438
+ activeBuilderRefreshesRef.current.delete(entry.key);
439
+ stoppedBuilderRefreshesRef.current.add(entry.key);
440
+ return;
441
+ }
442
+ if (isTerminalBuilderStatus(result.status)) {
443
+ activeBuilderRefreshesRef.current.delete(entry.key);
444
+ settledBuilderRefreshesRef.current.add(entry.key);
445
+ return;
446
+ }
447
+ } catch {
448
+ if (disposed) return;
449
+ }
450
+ if (disposed) return;
451
+ const exhausted = attempt >= maxAttempts;
452
+ if (exhausted && pollCount >= maxPolls) {
453
+ activeBuilderRefreshesRef.current.delete(entry.key);
454
+ stoppedBuilderRefreshesRef.current.add(entry.key);
455
+ return;
456
+ }
457
+ scheduleRetry(
458
+ entry,
459
+ exhausted ? retryPollDelayMs : retryDelayMs,
460
+ exhausted ? 0 : attempt + 1,
461
+ exhausted ? pollCount + 1 : pollCount,
462
+ );
463
+ };
464
+
465
+ for (const entry of builderSystemEntries) {
466
+ activeBuilderRefreshesRef.current.add(entry.key);
467
+ void refresh(entry, 0, 0);
370
468
  }
371
- };
469
+
470
+ return () => {
471
+ disposed = true;
472
+ for (const timer of timers) clearTimeout(timer);
473
+ for (const entry of builderSystemEntries) {
474
+ activeBuilderRefreshesRef.current.delete(entry.key);
475
+ }
476
+ };
477
+ }, [designSystems, queryClient]);
372
478
 
373
479
  useSetPageTitle(t("navigation.designSystems"));
374
480
 
@@ -486,7 +592,7 @@ export default function DesignSystems() {
486
592
 
487
593
  {/* Design system cards */}
488
594
  {designSystems.map((ds) => {
489
- const parsed = parseData(ds.data);
595
+ const parsed = parseDesignSystemData(ds.data);
490
596
  const colors = parsed?.colors;
491
597
  const primaryColor = getCssColorToken(colors?.primary);
492
598
  const secondaryColor = getCssColorToken(colors?.secondary);
@@ -997,18 +1103,6 @@ function EmptyPreviewLine({
997
1103
  );
998
1104
  }
999
1105
 
1000
- function parseDesignSystemData(dataStr: string): DesignSystemData | null {
1001
- try {
1002
- const parsed = JSON.parse(dataStr);
1003
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
1004
- return null;
1005
- }
1006
- return parsed as DesignSystemData;
1007
- } catch {
1008
- return null;
1009
- }
1010
- }
1011
-
1012
1106
  function parseDesignSystemAssets(
1013
1107
  assetsStr?: string | null,
1014
1108
  ): Array<{ name?: string; url?: string; variant?: string }> {
@@ -864,6 +864,7 @@ export default function Index() {
864
864
  value={search}
865
865
  onChange={(e) => handleSearchChange(e.target.value)}
866
866
  placeholder={t("home.searchPlaceholder")}
867
+ aria-label={t("home.searchPlaceholder")}
867
868
  className="ps-8 h-8 w-48 bg-accent/50 border-border text-sm text-foreground/90 placeholder:text-muted-foreground/70"
868
869
  />
869
870
  </div>
@@ -1262,6 +1263,7 @@ export default function Index() {
1262
1263
  }
1263
1264
  }}
1264
1265
  placeholder={t("home.designName")}
1266
+ aria-label={t("home.designName")}
1265
1267
  className="h-9 text-sm"
1266
1268
  />
1267
1269
  <AlertDialogFooter>
@@ -302,16 +302,6 @@ export default function Templates() {
302
302
  </p>
303
303
  </div>
304
304
 
305
- <div className="relative mb-6 md:hidden">
306
- <IconSearch className="absolute start-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground/70" />
307
- <Input
308
- value={search}
309
- onChange={(event) => setSearch(event.target.value)}
310
- placeholder={t("templatesPage.searchPlaceholder")}
311
- className="h-9 w-full bg-accent/50 ps-8 text-sm"
312
- />
313
- </div>
314
-
315
305
  {isLoading ? (
316
306
  <TemplateGridSkeleton />
317
307
  ) : isError ? (
@@ -1134,6 +1134,16 @@ export function removeEmptyGeneratedGroupWrappers(
1134
1134
  candidateParentAttrIds: ReadonlySet<string>,
1135
1135
  ): string {
1136
1136
  if (candidateParentAttrIds.size === 0) return content;
1137
+ // Both are necessary conditions for isGeneratedGroupWrapperNode to ever
1138
+ // match. Checking them on the raw string first keeps a document with no
1139
+ // generated groups — the common case — from paying for a full projection of
1140
+ // post-edit content on every structural edit.
1141
+ if (
1142
+ !content.includes("data-agent-native-layer-name") ||
1143
+ !content.includes("Group")
1144
+ ) {
1145
+ return content;
1146
+ }
1137
1147
  let next = content;
1138
1148
  // Loop: removing one empty wrapper can itself empty out ITS parent (e.g.
1139
1149
  // ungrouping down a chain of nested generated groups), so keep sweeping
@@ -1,4 +1,8 @@
1
1
  import { shouldUseLiveFileContent } from "@shared/html-content";
2
+ import DiffMatchPatch from "diff-match-patch";
3
+ import type * as Y from "yjs";
4
+
5
+ const { DIFF_DELETE, DIFF_EQUAL } = DiffMatchPatch;
2
6
 
3
7
  export function shouldRebaseCollabDocFromStoredContent({
4
8
  liveContent,
@@ -56,3 +60,49 @@ export function shouldApplyRemotePreviewContent({
56
60
  }): boolean {
57
61
  return !isLocalEdit && nextContent !== previousContent;
58
62
  }
63
+
64
+ const diffMatchPatch = new DiffMatchPatch();
65
+
66
+ /**
67
+ * Replace the collab document's text with `next` as the smallest set of
68
+ * disjoint splices, and report whether anything changed.
69
+ *
70
+ * Never `delete(0, length) + insert(0, next)`. That shape ships the whole
71
+ * document on every edit, the UndoManager pins every replaced copy so the doc
72
+ * grows without bound within a session, and it is wrong under concurrency:
73
+ * two peers each rewriting the whole text merge into a duplicated document
74
+ * instead of both edits.
75
+ *
76
+ * Disjoint rather than one prefix/suffix splice, because a single splice spans
77
+ * everything between the first and last changed character. An agent rewrite
78
+ * touching two ends of a screen would delete the untouched middle and take a
79
+ * concurrent edit inside it with it. This mirrors the server's own
80
+ * `applyTextToYDoc`, which has always diffed this way.
81
+ */
82
+ export function writeCollabText(
83
+ ydoc: Y.Doc,
84
+ ytext: Y.Text,
85
+ next: string,
86
+ origin: unknown,
87
+ ): boolean {
88
+ const current = ytext.toString();
89
+ if (current === next) return false;
90
+ // No cleanup pass: diff_cleanupEfficiency merges edits across equal runs
91
+ // shorter than Diff_EditCost (4), which deletes up to three untouched
92
+ // characters and takes any concurrent edit anchored in them along with it.
93
+ const diffs = diffMatchPatch.diff_main(current, next);
94
+ ydoc.transact(() => {
95
+ let cursor = 0;
96
+ for (const [operation, text] of diffs) {
97
+ if (operation === DIFF_EQUAL) {
98
+ cursor += text.length;
99
+ } else if (operation === DIFF_DELETE) {
100
+ ytext.delete(cursor, text.length);
101
+ } else {
102
+ ytext.insert(cursor, text);
103
+ cursor += text.length;
104
+ }
105
+ }
106
+ }, origin);
107
+ return true;
108
+ }
@@ -37,7 +37,7 @@ export interface ApplyDesignEditorCommandArgs {
37
37
  overviewScreens: OverviewScreen[];
38
38
  setActiveFileId: Dispatch<SetStateAction<string | null>>;
39
39
  setActiveInspectorTab: Dispatch<SetStateAction<InspectorTab>>;
40
- setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel>>;
40
+ setActiveLeftPanel: Dispatch<SetStateAction<DesignLeftPanel | null>>;
41
41
  setActiveTool: Dispatch<SetStateAction<DesignTool>>;
42
42
  setDrawMode: Dispatch<SetStateAction<boolean>>;
43
43
  setInteractDeviceName: Dispatch<SetStateAction<string>>;
@@ -10,7 +10,10 @@ import {
10
10
  waitForShaderWriteToSettle,
11
11
  } from "@/components/design/inspector/GlslShaderPanel";
12
12
  import type { ClipboardContentMutationPublication } from "@/lib/clipboard-content-lineage";
13
- import { resolveScreenCollabSyncTarget } from "@/pages/design-editor/collab-sync";
13
+ import {
14
+ resolveScreenCollabSyncTarget,
15
+ writeCollabText,
16
+ } from "@/pages/design-editor/collab-sync";
14
17
  import { TAB_ID } from "@/pages/design-editor/editor-session";
15
18
  import type { FileContentSaveRequest } from "@/pages/design-editor/editor-state";
16
19
  import type { ContentHistoryEntry } from "@/pages/design-editor/history";
@@ -218,13 +221,12 @@ export function runApplyFileContentUpdate(
218
221
  overviewDocConnected: !!(overviewYdoc && overviewIsSynced),
219
222
  });
220
223
  if (writeLiveDoc && overviewYdoc) {
221
- const ytext = overviewYdoc.getText("content");
222
- if (ytext.toString() !== nextContent) {
223
- overviewYdoc.transact(() => {
224
- ytext.delete(0, ytext.length);
225
- ytext.insert(0, nextContent);
226
- }, TAB_ID);
227
- }
224
+ writeCollabText(
225
+ overviewYdoc,
226
+ overviewYdoc.getText("content"),
227
+ nextContent,
228
+ TAB_ID,
229
+ );
228
230
  }
229
231
  if (options.persist === false) {
230
232
  cancelQueuedFileContentSave(fileId);