@agent-native/core 0.141.7 → 0.144.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 (371) hide show
  1. package/agent-native.eject.json +9 -0
  2. package/corpus/README.md +1 -1
  3. package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +19 -0
  4. package/corpus/templates/analytics/.agents/skills/turn-into-app/SKILL.md +296 -0
  5. package/corpus/templates/analytics/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  6. package/corpus/templates/analytics/.agents/skills/turn-into-skill/SKILL.md +112 -0
  7. package/corpus/templates/analytics/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  8. package/corpus/templates/analytics/AGENTS.md +35 -38
  9. package/corpus/templates/analytics/actions/ensure-native-v2-dashboards.ts +1 -1
  10. package/corpus/templates/analytics/actions/list-dashboard-usage-stats.ts +17 -22
  11. package/corpus/templates/analytics/actions/migrate-first-party-analytics-to-bigquery.ts +1 -1
  12. package/corpus/templates/analytics/actions/navigate.ts +4 -5
  13. package/corpus/templates/analytics/actions/provider-api-register.ts +50 -0
  14. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +44 -11
  15. package/corpus/templates/analytics/actions/test-custom-api-connection.ts +106 -0
  16. package/corpus/templates/analytics/app/components/CustomApiCard.tsx +430 -0
  17. package/corpus/templates/analytics/app/i18n-data.ts +680 -0
  18. package/corpus/templates/analytics/app/lib/native-mcp-exclusions.ts +6 -0
  19. package/corpus/templates/analytics/app/lib/sql-query.ts +33 -6
  20. package/corpus/templates/analytics/app/pages/DataSources.tsx +4 -0
  21. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-load-reliably-during-background-data-sw.md +6 -0
  22. package/corpus/templates/analytics/changelog/2026-08-06-analytics-dashboards-remain-responsive-while-historical-data.md +6 -0
  23. package/corpus/templates/analytics/changelog/2026-08-06-analytics-query-results-now-render-as-a-table-with-csv-downl.md +6 -0
  24. package/corpus/templates/analytics/changelog/2026-08-06-connect-public-https-custom-apis-and-hand-tested-endpoints-t.md +6 -0
  25. package/corpus/templates/analytics/changelog/2026-08-06-durable-agent-worker-memory.md +6 -0
  26. package/corpus/templates/analytics/changelog/2026-08-06-live-dashboard-panels-use-the-shared-query-timeout.md +6 -0
  27. package/corpus/templates/analytics/changelog/2026-08-06-on-demand-billing-is-available-as-a-native-dashboard-with-ta.md +6 -0
  28. package/corpus/templates/analytics/changelog/2026-08-06-visible-dashboard-names-are-unique.md +6 -0
  29. package/corpus/templates/analytics/netlify.toml +7 -0
  30. package/corpus/templates/analytics/scripts/emit-netlify-dashboard-report-cron.ts +4 -0
  31. package/corpus/templates/analytics/server/db/index.ts +27 -0
  32. package/corpus/templates/analytics/server/db/schema.ts +10 -0
  33. package/corpus/templates/analytics/server/lib/dashboards-store.ts +227 -60
  34. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +156 -45
  35. package/corpus/templates/analytics/server/lib/native-v2-dashboards.ts +227 -1
  36. package/corpus/templates/analytics/server/plugins/agent-chat.ts +5 -0
  37. package/corpus/templates/analytics/server/plugins/analytics-rollup-backfill-jobs.ts +1 -0
  38. package/corpus/templates/analytics/server/plugins/db.ts +52 -18
  39. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +28 -2
  40. package/corpus/templates/assets/.agents/skills/image-generation/SKILL.md +16 -1
  41. package/corpus/templates/assets/.agents/skills/turn-into-app/SKILL.md +296 -0
  42. package/corpus/templates/assets/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  43. package/corpus/templates/assets/.agents/skills/turn-into-skill/SKILL.md +112 -0
  44. package/corpus/templates/assets/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  45. package/corpus/templates/brain/.agents/skills/turn-into-app/SKILL.md +296 -0
  46. package/corpus/templates/brain/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  47. package/corpus/templates/brain/.agents/skills/turn-into-skill/SKILL.md +112 -0
  48. package/corpus/templates/brain/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  49. package/corpus/templates/brain/actions/list-connection-providers.ts +24 -3
  50. package/corpus/templates/brain/app/lib/dispatch-links.ts +44 -0
  51. package/corpus/templates/brain/app/routes/sources.tsx +15 -7
  52. package/corpus/templates/brain/changelog/2026-08-06-brain-provider-setup-links-open-dispatch-correctly-in-standa.md +6 -0
  53. package/corpus/templates/brain/server/plugins/agent-chat.ts +1 -0
  54. package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +26 -0
  55. package/corpus/templates/calendar/.agents/skills/turn-into-app/SKILL.md +296 -0
  56. package/corpus/templates/calendar/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  57. package/corpus/templates/calendar/.agents/skills/turn-into-skill/SKILL.md +112 -0
  58. package/corpus/templates/calendar/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  59. package/corpus/templates/calendar/AGENTS.md +11 -32
  60. package/corpus/templates/calendar/actions/update-event.ts +107 -1
  61. package/corpus/templates/calendar/app/components/calendar/EventCalendarSelect.tsx +83 -0
  62. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +57 -0
  63. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +59 -73
  64. package/corpus/templates/calendar/app/hooks/use-events.ts +4 -1
  65. package/corpus/templates/calendar/app/i18n-data.ts +20 -0
  66. package/corpus/templates/calendar/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  67. package/corpus/templates/calendar/changelog/2026-08-06-existing-events-can-move-between-connected-google-account-ca.md +6 -0
  68. package/corpus/templates/calendar/server/lib/google-calendar.ts +101 -0
  69. package/corpus/templates/calendar/server/plugins/agent-chat.ts +7 -1
  70. package/corpus/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  71. package/corpus/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  72. package/corpus/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  73. package/corpus/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  74. package/corpus/templates/clips/.agents/skills/turn-into-app/SKILL.md +296 -0
  75. package/corpus/templates/clips/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  76. package/corpus/templates/clips/.agents/skills/turn-into-skill/SKILL.md +112 -0
  77. package/corpus/templates/clips/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  78. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +9 -24
  79. package/corpus/templates/clips/app/components/editor/timeline-geometry.ts +15 -0
  80. package/corpus/templates/clips/app/components/editor/waveform.tsx +4 -17
  81. package/corpus/templates/clips/app/components/player/delete-recording-menu.tsx +14 -3
  82. package/corpus/templates/clips/app/components/player/player-controls.tsx +0 -3
  83. package/corpus/templates/clips/app/components/player/scrubber.tsx +2 -33
  84. package/corpus/templates/clips/app/components/player/video-player.tsx +58 -11
  85. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +28 -38
  86. package/corpus/templates/clips/app/routes/share.$shareId.tsx +21 -27
  87. package/corpus/templates/clips/changelog/2026-08-06-clips-recovers-from-stalled-recording-setup-without-requirin.md +6 -0
  88. package/corpus/templates/clips/changelog/2026-08-06-clips-starts-faster-after-a-deploy-or-idle-period-startup-no.md +6 -0
  89. package/corpus/templates/clips/changelog/2026-08-06-deleting-a-recording-returns-cleanly-to-the-library-and-fit-.md +6 -0
  90. package/corpus/templates/clips/changelog/2026-08-06-hide-clip-insights-from-viewers-without-analytics-access.md +6 -0
  91. package/corpus/templates/clips/changelog/2026-08-06-trimmed-clips-play-on-a-clean-timeline-without-cut-markers.md +6 -0
  92. package/corpus/templates/clips/desktop/src/app.tsx +48 -20
  93. package/corpus/templates/clips/desktop/src/lib/recorder.ts +275 -74
  94. package/corpus/templates/clips/desktop/src/lib/recording-start-guard.ts +84 -0
  95. package/corpus/templates/clips/desktop/src/overlays/toolbar.tsx +14 -4
  96. package/corpus/templates/clips/server/plugins/db.ts +214 -26
  97. package/corpus/templates/content/.agents/skills/turn-into-app/SKILL.md +296 -0
  98. package/corpus/templates/content/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  99. package/corpus/templates/content/.agents/skills/turn-into-skill/SKILL.md +112 -0
  100. package/corpus/templates/content/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  101. package/corpus/templates/crm/.agents/skills/turn-into-app/SKILL.md +296 -0
  102. package/corpus/templates/crm/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  103. package/corpus/templates/crm/.agents/skills/turn-into-skill/SKILL.md +112 -0
  104. package/corpus/templates/crm/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  105. package/corpus/templates/crm/changelog/2026-08-06-crm-starts-faster-after-a-deploy-or-idle-period-one-time-dat.md +6 -0
  106. package/corpus/templates/crm/server/plugins/db.ts +11 -8
  107. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +36 -1
  108. package/corpus/templates/design/.agents/skills/turn-into-app/SKILL.md +296 -0
  109. package/corpus/templates/design/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  110. package/corpus/templates/design/.agents/skills/turn-into-skill/SKILL.md +112 -0
  111. package/corpus/templates/design/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  112. package/corpus/templates/design/actions/import-from-url.ts +1 -1
  113. package/corpus/templates/design/app/components/design/LayersPanel.tsx +27 -18
  114. package/corpus/templates/design/app/pages/Index.tsx +6 -2
  115. package/corpus/templates/design/changelog/2026-08-05-deleting-a-design-from-the-home-page-no-longer-leaves-the-ap.md +6 -0
  116. package/corpus/templates/design/changelog/2026-08-05-renaming-a-layer-now-focuses-its-name-field-automatically.md +6 -0
  117. package/corpus/templates/design/server/plugins/agent-chat.ts +2 -0
  118. package/corpus/templates/dispatch/.agents/skills/turn-into-app/SKILL.md +296 -0
  119. package/corpus/templates/dispatch/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  120. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/SKILL.md +112 -0
  121. package/corpus/templates/dispatch/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  122. package/corpus/templates/dispatch/AGENTS.md +8 -1
  123. package/corpus/templates/dispatch/app/dispatch-extensions.tsx +1 -0
  124. package/corpus/templates/dispatch/app/hooks/use-navigation-state.ts +30 -15
  125. package/corpus/templates/dispatch/app/i18n-data.ts +131 -0
  126. package/corpus/templates/dispatch/app/routes/admin._index.tsx +4 -0
  127. package/corpus/templates/dispatch/app/routes/admin.agents.tsx +1 -0
  128. package/corpus/templates/dispatch/app/routes/admin.approvals.tsx +1 -0
  129. package/corpus/templates/dispatch/app/routes/admin.apps.$appId.tsx +1 -0
  130. package/corpus/templates/dispatch/app/routes/admin.apps.tsx +1 -0
  131. package/corpus/templates/dispatch/app/routes/admin.audit.tsx +1 -0
  132. package/corpus/templates/dispatch/app/routes/admin.automations.tsx +1 -0
  133. package/corpus/templates/dispatch/app/routes/admin.destinations.tsx +4 -0
  134. package/corpus/templates/dispatch/app/routes/admin.dreams.tsx +1 -0
  135. package/corpus/templates/dispatch/app/routes/admin.identities.tsx +1 -0
  136. package/corpus/templates/dispatch/app/routes/admin.integrations.tsx +4 -0
  137. package/corpus/templates/dispatch/app/routes/admin.messaging.tsx +1 -0
  138. package/corpus/templates/dispatch/app/routes/admin.metrics.tsx +1 -0
  139. package/corpus/templates/dispatch/app/routes/admin.new-app.tsx +1 -0
  140. package/corpus/templates/dispatch/app/routes/admin.operations.tsx +1 -0
  141. package/corpus/templates/dispatch/app/routes/admin.thread-debug.tsx +4 -0
  142. package/corpus/templates/dispatch/app/routes/admin.transactional-email.$appId.$id.tsx +4 -0
  143. package/corpus/templates/dispatch/app/routes/admin.transactional-email.tsx +4 -0
  144. package/corpus/templates/dispatch/app/routes/admin.tsx +1 -0
  145. package/corpus/templates/dispatch/app/routes/admin.vault.tsx +1 -0
  146. package/corpus/templates/dispatch/app/routes/admin.workspace.tsx +1 -0
  147. package/corpus/templates/dispatch/changelog/2026-08-06-dispatch-keeps-everyday-navigation-focused-while-management-.md +6 -0
  148. package/corpus/templates/dispatch/changelog/2026-08-06-ready-workspace-apps-stay-one-click-away-in-a-compact-dispat.md +6 -0
  149. package/corpus/templates/dispatch/changelog/2026-08-06-shared-vault-values-and-management-are-now-restricted-to-wor.md +6 -0
  150. package/corpus/templates/factory/.agents/skills/turn-into-app/SKILL.md +296 -0
  151. package/corpus/templates/factory/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  152. package/corpus/templates/factory/.agents/skills/turn-into-skill/SKILL.md +112 -0
  153. package/corpus/templates/factory/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  154. package/corpus/templates/forms/.agents/skills/turn-into-app/SKILL.md +296 -0
  155. package/corpus/templates/forms/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  156. package/corpus/templates/forms/.agents/skills/turn-into-skill/SKILL.md +112 -0
  157. package/corpus/templates/forms/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  158. package/corpus/templates/forms/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  159. package/corpus/templates/forms/server/plugins/agent-chat.ts +4 -0
  160. package/corpus/templates/macros/.agents/skills/turn-into-app/SKILL.md +296 -0
  161. package/corpus/templates/macros/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  162. package/corpus/templates/macros/.agents/skills/turn-into-skill/SKILL.md +112 -0
  163. package/corpus/templates/macros/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  164. package/corpus/templates/mail/.agents/skills/turn-into-app/SKILL.md +296 -0
  165. package/corpus/templates/mail/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  166. package/corpus/templates/mail/.agents/skills/turn-into-skill/SKILL.md +112 -0
  167. package/corpus/templates/mail/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  168. package/corpus/templates/mail/changelog/2026-08-06-delegated-requests-continue-in-the-background.md +6 -0
  169. package/corpus/templates/mail/server/plugins/agent-chat.ts +6 -0
  170. package/corpus/templates/plan/.agents/skills/turn-into-app/SKILL.md +296 -0
  171. package/corpus/templates/plan/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  172. package/corpus/templates/plan/.agents/skills/turn-into-skill/SKILL.md +112 -0
  173. package/corpus/templates/plan/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  174. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +48 -5
  175. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +37 -1
  176. package/corpus/templates/slides/.agents/skills/image-generation-via-a2a/SKILL.md +6 -0
  177. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +15 -2
  178. package/corpus/templates/slides/.agents/skills/slide-images/SKILL.md +29 -24
  179. package/corpus/templates/slides/.agents/skills/turn-into-app/SKILL.md +296 -0
  180. package/corpus/templates/slides/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  181. package/corpus/templates/slides/.agents/skills/turn-into-skill/SKILL.md +112 -0
  182. package/corpus/templates/slides/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  183. package/corpus/templates/slides/AGENTS.md +17 -21
  184. package/corpus/templates/slides/_gitignore +1 -0
  185. package/corpus/templates/slides/actions/export-pptx.ts +470 -36
  186. package/corpus/templates/slides/actions/get-deck.ts +12 -0
  187. package/corpus/templates/slides/actions/import-file.ts +175 -139
  188. package/corpus/templates/slides/actions/import-google-slides-reference.ts +271 -12
  189. package/corpus/templates/slides/actions/import-pptx.ts +193 -68
  190. package/corpus/templates/slides/actions/patch-deck.ts +51 -0
  191. package/corpus/templates/slides/actions/update-slide.ts +29 -3
  192. package/corpus/templates/slides/app/components/deck/DeckCard.tsx +10 -13
  193. package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +5 -1
  194. package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +25 -12
  195. package/corpus/templates/slides/app/components/editor/ExportMenu.tsx +112 -57
  196. package/corpus/templates/slides/app/components/editor/GoogleDriveConnectionCta.tsx +202 -0
  197. package/corpus/templates/slides/app/components/editor/GoogleSlidesReferenceImport.tsx +26 -14
  198. package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +173 -0
  199. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +182 -141
  200. package/corpus/templates/slides/app/components/editor/canvas-interactions/index.ts +1 -0
  201. package/corpus/templates/slides/app/components/editor/canvas-interactions/slides-canvas-adapter.ts +18 -0
  202. package/corpus/templates/slides/app/components/editor/slide-text-targets.ts +85 -0
  203. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -0
  204. package/corpus/templates/slides/app/components/onboarding/FirstDeckOnboardingFlow.tsx +15 -0
  205. package/corpus/templates/slides/app/components/presentation/PresentationView.tsx +27 -1
  206. package/corpus/templates/slides/app/i18n/en-US.ts +1 -0
  207. package/corpus/templates/slides/app/lib/create-deck-generation.ts +72 -11
  208. package/corpus/templates/slides/app/lib/deck-preview-frame.ts +15 -0
  209. package/corpus/templates/slides/app/lib/deck-share-links.ts +9 -0
  210. package/corpus/templates/slides/app/lib/export-pptx-client.ts +89 -0
  211. package/corpus/templates/slides/app/lib/import-uploaded-deck.ts +89 -0
  212. package/corpus/templates/slides/app/lib/slide-animation-elements.ts +3 -0
  213. package/corpus/templates/slides/app/pages/Index.tsx +172 -15
  214. package/corpus/templates/slides/changelog/2026-08-06-clicking-the-gray-canvas-around-a-slide-clears-its-selection.md +6 -0
  215. package/corpus/templates/slides/changelog/2026-08-06-deck-thumbnails-keep-a-consistent-listing-frame-across-aspec.md +6 -0
  216. package/corpus/templates/slides/changelog/2026-08-06-deep-linked-decks-open-directly-instead-of-being-interrupted.md +6 -0
  217. package/corpus/templates/slides/changelog/2026-08-06-google-slides-exports-now-show-clear-import-steps-when-direc.md +6 -0
  218. package/corpus/templates/slides/changelog/2026-08-06-import-pdf-google-slides-and-powerpoint-decks-directly-from-.md +6 -0
  219. package/corpus/templates/slides/changelog/2026-08-06-imported-powerpoint-exports-keep-text-and-images-editable-an.md +6 -0
  220. package/corpus/templates/slides/changelog/2026-08-06-presentation-prompts-continue-adding-rendered-slides-until-t.md +6 -0
  221. package/corpus/templates/slides/changelog/2026-08-06-public-decks-now-share-read-only-presentation-links-by-defau.md +6 -0
  222. package/corpus/templates/slides/changelog/2026-08-06-slides-offers-a-direct-connect-google-button-when-a-drive-co.md +6 -0
  223. package/corpus/templates/slides/changelog/2026-08-06-slides-preserve-uploaded-pdf-layouts-accept-larger-reference.md +6 -0
  224. package/corpus/templates/slides/changelog/2026-08-06-styled-words-stay-part-of-their-text-box-instead-of-becoming.md +6 -0
  225. package/corpus/templates/slides/changelog/2026-08-06-uploaded-decks-keep-their-slides-and-visuals-when-you-improv.md +6 -0
  226. package/corpus/templates/slides/server/handlers/google-docs-auth.ts +7 -20
  227. package/corpus/templates/slides/server/handlers/import/html-converter.ts +247 -13
  228. package/corpus/templates/slides/server/handlers/import/pptx-assets.ts +67 -0
  229. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +2 -0
  230. package/corpus/templates/slides/server/handlers/uploads.ts +7 -3
  231. package/corpus/templates/slides/server/lib/chat-attachments.ts +7 -4
  232. package/corpus/templates/slides/server/lib/emails.ts +7 -2
  233. package/corpus/templates/slides/server/lib/google-docs-error.ts +50 -0
  234. package/corpus/templates/slides/server/lib/google-docs-oauth.ts +1 -0
  235. package/corpus/templates/slides/server/lib/import-asset-storage.ts +127 -0
  236. package/corpus/templates/slides/server/lib/source-import.ts +167 -0
  237. package/corpus/templates/slides/server/plugins/agent-chat.ts +12 -3
  238. package/corpus/templates/slides/server/routes/api/import-assets/[token].get.ts +70 -0
  239. package/corpus/templates/slides/shared/upload-types.ts +3 -0
  240. package/corpus/templates/tasks/.agents/skills/turn-into-app/SKILL.md +296 -0
  241. package/corpus/templates/tasks/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  242. package/corpus/templates/tasks/.agents/skills/turn-into-skill/SKILL.md +112 -0
  243. package/corpus/templates/tasks/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  244. package/dist/agent/production-agent.d.ts +17 -0
  245. package/dist/agent/production-agent.js +72 -1
  246. package/dist/cli/agent-plugin.d.ts +112 -0
  247. package/dist/cli/agent-plugin.js +1081 -0
  248. package/dist/cli/app-skill.js +39 -1
  249. package/dist/cli/code-agent-executor.d.ts +3 -0
  250. package/dist/cli/code-agent-executor.js +51 -13
  251. package/dist/cli/index.js +13 -0
  252. package/dist/cli/templates-meta.js +1 -1
  253. package/dist/client/AgentPanel.d.ts +3 -1
  254. package/dist/client/AgentPanel.js +9 -2
  255. package/dist/client/AssistantChat.d.ts +8 -0
  256. package/dist/client/AssistantChat.js +23 -8
  257. package/dist/client/NewWorkspaceAppFlow.js +1 -0
  258. package/dist/client/agent-chat-adapter.js +123 -4
  259. package/dist/client/assistant-ui-recovery.d.ts +2 -1
  260. package/dist/client/assistant-ui-recovery.js +7 -3
  261. package/dist/client/onboarding/FirstRunOnboarding.js +11 -4
  262. package/dist/client/org/TeamPage.js +1 -1
  263. package/dist/client/require-session.js +1 -1
  264. package/dist/client/resources/McpConnectionSuggestion.d.ts +1 -0
  265. package/dist/client/resources/McpConnectionSuggestion.js +27 -10
  266. package/dist/client/resources/McpIntegrationDialog.js +77 -45
  267. package/dist/client/resources/mcp-integration-catalog.d.ts +13 -1
  268. package/dist/client/resources/mcp-integration-catalog.js +255 -2
  269. package/dist/client/resources/mcp-integration-logos.js +18 -2
  270. package/dist/client/settings/AccountSettingsCard.js +2 -1
  271. package/dist/collab/struct-routes.d.ts +1 -1
  272. package/dist/db/client.d.ts +9 -0
  273. package/dist/db/client.js +51 -16
  274. package/dist/db/create-get-db.js +2 -2
  275. package/dist/db/ddl-guard.d.ts +11 -10
  276. package/dist/db/ddl-guard.js +40 -12
  277. package/dist/deploy/build.d.ts +2 -0
  278. package/dist/deploy/build.js +97 -4
  279. package/dist/deploy/workspace-deploy.js +0 -2
  280. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  281. package/dist/guards/no-env-credentials.js +9 -0
  282. package/dist/ingestion/index.d.ts +1 -1
  283. package/dist/ingestion/pptx.d.ts +68 -0
  284. package/dist/ingestion/pptx.js +660 -213
  285. package/dist/integrations/plugin.js +9 -6
  286. package/dist/jobs/scheduler.js +79 -23
  287. package/dist/localization/default-messages.d.ts +54 -0
  288. package/dist/localization/default-messages.js +57 -2
  289. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  290. package/dist/mcp-client/oauth-routes.d.ts +2 -0
  291. package/dist/mcp-client/oauth-routes.js +73 -6
  292. package/dist/observability/routes.d.ts +5 -5
  293. package/dist/onboarding/app-profile.js +11 -0
  294. package/dist/progress/routes.d.ts +1 -1
  295. package/dist/resources/handlers.d.ts +1 -1
  296. package/dist/resources/store.js +15 -1
  297. package/dist/scripts/call-agent.js +34 -4
  298. package/dist/secrets/routes.d.ts +3 -3
  299. package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -1
  300. package/dist/server/agent-chat/action-filters-a2a.js +36 -1
  301. package/dist/server/agent-chat-plugin.js +29 -8
  302. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  303. package/dist/server/auth.js +47 -11
  304. package/dist/server/better-auth-instance.js +5 -3
  305. package/dist/server/core-routes-plugin.d.ts +8 -1
  306. package/dist/server/core-routes-plugin.js +28 -3
  307. package/dist/server/credential-provider.d.ts +3 -3
  308. package/dist/server/credential-provider.js +90 -4
  309. package/dist/server/onboarding-html.d.ts +2 -0
  310. package/dist/server/onboarding-html.js +115 -29
  311. package/dist/server/realtime-token.d.ts +1 -1
  312. package/dist/server/self-dispatch.d.ts +5 -4
  313. package/dist/server/self-dispatch.js +25 -14
  314. package/dist/server/ssr-handler.d.ts +1 -1
  315. package/dist/server/ssr-handler.js +1 -1
  316. package/dist/server/transcribe-voice.d.ts +1 -1
  317. package/dist/shared/cache-control.d.ts +26 -2
  318. package/dist/shared/cache-control.js +43 -2
  319. package/dist/shared/password-policy.d.ts +3 -0
  320. package/dist/shared/password-policy.js +3 -0
  321. package/dist/sharing/actions/set-resource-visibility.js +16 -4
  322. package/dist/sharing/registry.d.ts +14 -0
  323. package/dist/styles/agent-native.css +6 -0
  324. package/dist/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  325. package/dist/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  326. package/dist/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  327. package/dist/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  328. package/dist/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  329. package/dist/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  330. package/dist/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  331. package/dist/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  332. package/dist/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  333. package/dist/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  334. package/dist/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  335. package/dist/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  336. package/dist/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  337. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  338. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  339. package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  340. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  341. package/dist/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  342. package/dist/templates/workspace-root/AGENTS.md +7 -0
  343. package/dist/user-profile/actions/change-password.js +8 -3
  344. package/dist/user-profile/actions/set-password.js +5 -1
  345. package/dist/vite/action-types-plugin.js +59 -0
  346. package/docs/content/creating-templates.mdx +1 -1
  347. package/docs/content/getting-started-actions.mdx +38 -189
  348. package/docs/content/getting-started-database.mdx +80 -164
  349. package/docs/content/getting-started-pages.mdx +44 -155
  350. package/docs/content/getting-started.mdx +26 -106
  351. package/docs/content/skills-guide.mdx +13 -0
  352. package/package.json +6 -2
  353. package/src/templates/chat/.agents/skills/turn-into-app/SKILL.md +296 -0
  354. package/src/templates/chat/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  355. package/src/templates/chat/.agents/skills/turn-into-skill/SKILL.md +112 -0
  356. package/src/templates/chat/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  357. package/src/templates/default/.agents/skills/turn-into-app/SKILL.md +296 -0
  358. package/src/templates/default/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  359. package/src/templates/default/.agents/skills/turn-into-skill/SKILL.md +112 -0
  360. package/src/templates/default/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  361. package/src/templates/headless/.agents/skills/turn-into-app/SKILL.md +296 -0
  362. package/src/templates/headless/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  363. package/src/templates/headless/.agents/skills/turn-into-skill/SKILL.md +112 -0
  364. package/src/templates/headless/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  365. package/src/templates/workspace-core/.agents/skills/adding-workspace-apps/SKILL.md +6 -0
  366. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +51 -0
  367. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +296 -0
  368. package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +4 -0
  369. package/src/templates/workspace-core/.agents/skills/turn-into-skill/SKILL.md +112 -0
  370. package/src/templates/workspace-core/.agents/skills/turn-into-skill/agents/openai.yaml +4 -0
  371. package/src/templates/workspace-root/AGENTS.md +7 -0
@@ -40,7 +40,11 @@ import {
40
40
  uploadRecordingThumbnail,
41
41
  } from "@/lib/thumbnail-capture";
42
42
  import {
43
+ editedToOriginal,
44
+ effectiveDuration,
43
45
  getExcludedRanges,
46
+ isExcluded,
47
+ originalToEdited,
44
48
  parseEdits,
45
49
  type TrimRange,
46
50
  } from "@/lib/timestamp-mapping";
@@ -418,6 +422,49 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
418
422
  const [shouldRefreshAutoThumbnail, setShouldRefreshAutoThumbnail] =
419
423
  useState(false);
420
424
  const excludedRanges = useMemo(() => getExcludedRanges(edits), [edits]);
425
+ const scrubberTimeline = useMemo(() => {
426
+ const mapMarker = (originalMs: number): number | null => {
427
+ if (!Number.isFinite(originalMs) || isExcluded(originalMs, edits)) {
428
+ return null;
429
+ }
430
+ return originalToEdited(originalMs, edits);
431
+ };
432
+
433
+ return {
434
+ durationMs: effectiveDuration(resolvedDurationMs, edits),
435
+ currentMs: originalToEdited(currentMs, edits),
436
+ comments: (comments ?? []).flatMap((comment) => {
437
+ const editedMs = mapMarker(comment.videoTimestampMs);
438
+ return editedMs === null
439
+ ? []
440
+ : [
441
+ {
442
+ id: comment.id,
443
+ content: comment.content,
444
+ videoTimestampMs: editedMs,
445
+ },
446
+ ];
447
+ }),
448
+ chapters: (chapters ?? []).flatMap((chapter) => {
449
+ const editedMs = mapMarker(chapter.startMs);
450
+ return editedMs === null
451
+ ? []
452
+ : [{ startMs: editedMs, title: chapter.title }];
453
+ }),
454
+ reactions: (reactions ?? []).flatMap((reaction) => {
455
+ const editedMs = mapMarker(reaction.videoTimestampMs);
456
+ return editedMs === null
457
+ ? []
458
+ : [
459
+ {
460
+ id: reaction.id,
461
+ emoji: reaction.emoji,
462
+ videoTimestampMs: editedMs,
463
+ },
464
+ ];
465
+ }),
466
+ };
467
+ }, [chapters, comments, currentMs, edits, reactions, resolvedDurationMs]);
421
468
  const activeVideoSourceIdentity = useMemo(
422
469
  () => videoSourceIdentity(activeVideoSrc),
423
470
  [activeVideoSrc],
@@ -954,16 +1001,17 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
954
1001
  const seekByMs = useCallback(
955
1002
  (deltaMs: number) => {
956
1003
  const v = videoRef.current;
957
- const liveMs =
1004
+ const liveOriginalMs =
958
1005
  v &&
959
1006
  Number.isFinite(v.currentTime) &&
960
1007
  v.currentTime >= 0 &&
961
1008
  v.currentTime < 1e7
962
1009
  ? Math.floor(v.currentTime * 1000)
963
1010
  : currentMs;
964
- seekToVisibleMs(liveMs + deltaMs);
1011
+ const liveEditedMs = originalToEdited(liveOriginalMs, edits);
1012
+ seekToVisibleMs(editedToOriginal(liveEditedMs + deltaMs, edits));
965
1013
  },
966
- [currentMs, seekToVisibleMs],
1014
+ [currentMs, edits, seekToVisibleMs],
967
1015
  );
968
1016
 
969
1017
  // Imperative handle for parent
@@ -1780,8 +1828,8 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
1780
1828
  >
1781
1829
  <PlayerControls
1782
1830
  isPlaying={isPlaying}
1783
- durationMs={resolvedDurationMs}
1784
- currentMs={currentMs}
1831
+ durationMs={scrubberTimeline.durationMs}
1832
+ currentMs={scrubberTimeline.currentMs}
1785
1833
  volume={volume}
1786
1834
  muted={muted}
1787
1835
  speed={speed}
@@ -1789,16 +1837,15 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
1789
1837
  isFullscreen={isFullscreen}
1790
1838
  isPip={isPip}
1791
1839
  theaterMode={!!theaterMode}
1792
- comments={comments}
1793
- chapters={chapters}
1794
- reactions={reactions}
1795
- excludedRanges={excludedRanges}
1840
+ comments={scrubberTimeline.comments}
1841
+ chapters={scrubberTimeline.chapters}
1842
+ reactions={scrubberTimeline.reactions}
1796
1843
  hasCaptions={!!transcriptSegments?.length}
1797
1844
  onPlayPause={() => {
1798
1845
  togglePlayback();
1799
1846
  }}
1800
- onSeek={(ms) => {
1801
- seekToVisibleMs(ms);
1847
+ onSeek={(editedMs) => {
1848
+ seekToVisibleMs(editedToOriginal(editedMs, edits));
1802
1849
  }}
1803
1850
  onSeekRelative={seekByMs}
1804
1851
  onVolumeChange={(vol) => {
@@ -183,21 +183,6 @@ function nativeSaveFailureMessage(reason: string | null | undefined): string {
183
183
  return "The desktop recorder finished and saved a local copy, but Clips could not upload it. You can retry from the Clips menu without recording again.";
184
184
  }
185
185
 
186
- function InsightsUnavailableState() {
187
- const t = useT();
188
-
189
- return (
190
- <div className="flex h-full flex-col items-center justify-center px-8 py-12 text-center">
191
- <p className="text-sm font-medium text-foreground">
192
- {t("sharePage.ownerInsights")}
193
- </p>
194
- <p className="mt-2 max-w-[240px] text-sm leading-5 text-muted-foreground">
195
- {t("sharePage.ownerInsightsDescription")}
196
- </p>
197
- </div>
198
- );
199
- }
200
-
201
186
  function parseTimeParam(raw: string | null): number {
202
187
  if (!raw) return 0;
203
188
  const value = raw.trim();
@@ -299,18 +284,6 @@ export default function RecordingPage() {
299
284
  const readyMediaPollRef = useRef<{ key: string; until: number } | null>(null);
300
285
  const [metadataRefreshUntil, setMetadataRefreshUntil] = useState(0);
301
286
 
302
- useEffect(() => {
303
- if (
304
- panelParam === "agent" ||
305
- panelParam === "comments" ||
306
- panelParam === "transcript" ||
307
- panelParam === "insights" ||
308
- panelParam === "settings"
309
- ) {
310
- setPanel(panelParam);
311
- }
312
- }, [panelParam]);
313
-
314
287
  const playerDataQ = useActionQuery<any>(
315
288
  "get-recording-player-data",
316
289
  {
@@ -414,6 +387,25 @@ export default function RecordingPage() {
414
387
  const transcriptCleanup = playerDataQ.data?.transcript?.cleanup ?? null;
415
388
  const ctas = playerDataQ.data?.ctas ?? [];
416
389
  const canEdit = role === "owner" || role === "admin" || role === "editor";
390
+ useEffect(() => {
391
+ if (!canEdit && (panel === "insights" || panel === "settings")) {
392
+ setPanel("comments");
393
+ }
394
+ }, [canEdit, panel]);
395
+
396
+ useEffect(() => {
397
+ if (
398
+ (panelParam === "agent" ||
399
+ panelParam === "comments" ||
400
+ panelParam === "transcript" ||
401
+ panelParam === "insights" ||
402
+ panelParam === "settings") &&
403
+ ((panelParam !== "insights" && panelParam !== "settings") || canEdit)
404
+ ) {
405
+ setPanel(panelParam);
406
+ }
407
+ }, [canEdit, panelParam]);
408
+
417
409
  const builderCredits =
418
410
  (playerDataQ.data?.builderCredits as BuilderCreditsStatus | null) ?? null;
419
411
  const titleGenerationPaused = Boolean(
@@ -1149,7 +1141,7 @@ export default function RecordingPage() {
1149
1141
  trigger("comments", t("recordingPage.activity")),
1150
1142
  trigger("transcript", t("recordingPage.transcript")),
1151
1143
  trigger("agent", t("recordingPage.agent")),
1152
- trigger("insights", t("recordingPage.insights")),
1144
+ canEdit ? trigger("insights", t("recordingPage.insights")) : null,
1153
1145
  canEdit ? trigger("settings", t("recordingPage.settings")) : null,
1154
1146
  ];
1155
1147
 
@@ -1162,7 +1154,7 @@ export default function RecordingPage() {
1162
1154
  <TabsList
1163
1155
  className={cn(
1164
1156
  "mx-3 mt-3 grid w-auto",
1165
- canEdit ? "grid-cols-5" : "grid-cols-4",
1157
+ canEdit ? "grid-cols-5" : "grid-cols-3",
1166
1158
  )}
1167
1159
  >
1168
1160
  {triggers}
@@ -1259,19 +1251,17 @@ export default function RecordingPage() {
1259
1251
  presentation={compact ? "share" : "default"}
1260
1252
  />
1261
1253
  </TabsContent>
1262
- <TabsContent
1263
- value="insights"
1264
- className="flex-1 min-h-0 mt-3 overflow-y-auto data-[state=inactive]:hidden"
1265
- >
1266
- {canEdit ? (
1254
+ {canEdit ? (
1255
+ <TabsContent
1256
+ value="insights"
1257
+ className="flex-1 min-h-0 mt-3 overflow-y-auto data-[state=inactive]:hidden"
1258
+ >
1267
1259
  <InsightsPanel
1268
1260
  recordingId={recording.id}
1269
1261
  durationMs={recording.durationMs}
1270
1262
  />
1271
- ) : (
1272
- <InsightsUnavailableState />
1273
- )}
1274
- </TabsContent>
1263
+ </TabsContent>
1264
+ ) : null}
1275
1265
  {canEdit ? (
1276
1266
  <TabsContent
1277
1267
  value="settings"
@@ -529,6 +529,12 @@ export default function ShareRoute() {
529
529
  const viewerCanOpenDashboard = Boolean(
530
530
  dataQ.data?.data?.viewer?.canOpenDashboard,
531
531
  );
532
+ useEffect(() => {
533
+ if (!viewerCanEdit && panel === "insights") {
534
+ setPanel("comments");
535
+ }
536
+ }, [panel, viewerCanEdit]);
537
+
532
538
  const viewCount = Number(dataQ.data?.data?.viewCount ?? 0);
533
539
  const agentViewCount = Number(dataQ.data?.data?.agentViewCount ?? 0);
534
540
  const showTitleSkeleton = recording
@@ -1102,7 +1108,9 @@ export default function ShareRoute() {
1102
1108
  onValueChange={setPanel}
1103
1109
  className="flex h-full flex-col"
1104
1110
  >
1105
- <TabsList className="mx-3 mt-3 grid w-auto grid-cols-4">
1111
+ <TabsList
1112
+ className={`mx-3 mt-3 grid w-auto ${viewerCanEdit ? "grid-cols-4" : "grid-cols-3"}`}
1113
+ >
1106
1114
  <TabsTrigger value="comments" className="text-xs gap-1">
1107
1115
  {t("recordingPage.activity")}
1108
1116
  {comments.length > 0 ? (
@@ -1117,9 +1125,11 @@ export default function ShareRoute() {
1117
1125
  <TabsTrigger value="agent" className="text-xs">
1118
1126
  {t("sharePage.agent")}
1119
1127
  </TabsTrigger>
1120
- <TabsTrigger value="insights" className="text-xs">
1121
- {t("sharePage.insights")}
1122
- </TabsTrigger>
1128
+ {viewerCanEdit ? (
1129
+ <TabsTrigger value="insights" className="text-xs">
1130
+ {t("sharePage.insights")}
1131
+ </TabsTrigger>
1132
+ ) : null}
1123
1133
  </TabsList>
1124
1134
  <TabsContent
1125
1135
  value="agent"
@@ -1187,19 +1197,17 @@ export default function ShareRoute() {
1187
1197
  presentation="share"
1188
1198
  />
1189
1199
  </TabsContent>
1190
- <TabsContent
1191
- value="insights"
1192
- className="mt-3 min-h-0 flex-1 data-[state=inactive]:hidden"
1193
- >
1194
- {viewerCanEdit ? (
1200
+ {viewerCanEdit ? (
1201
+ <TabsContent
1202
+ value="insights"
1203
+ className="mt-3 min-h-0 flex-1 data-[state=inactive]:hidden"
1204
+ >
1195
1205
  <InsightsPanel
1196
1206
  recordingId={recording.id}
1197
1207
  durationMs={recording.durationMs}
1198
1208
  />
1199
- ) : (
1200
- <PublicInsightsState />
1201
- )}
1202
- </TabsContent>
1209
+ </TabsContent>
1210
+ ) : null}
1203
1211
  </Tabs>
1204
1212
  </aside>
1205
1213
 
@@ -1316,20 +1324,6 @@ function PublicAgentEmptyState({
1316
1324
  );
1317
1325
  }
1318
1326
 
1319
- function PublicInsightsState() {
1320
- const t = useT();
1321
- return (
1322
- <div className="flex h-full flex-col items-center justify-center px-8 py-12 text-center">
1323
- <p className="text-sm font-medium text-foreground">
1324
- {t("sharePage.ownerInsights")}
1325
- </p>
1326
- <p className="mt-2 max-w-[240px] text-sm leading-5 text-muted-foreground">
1327
- {t("sharePage.ownerInsightsDescription")}
1328
- </p>
1329
- </div>
1330
- );
1331
- }
1332
-
1333
1327
  function EndState({
1334
1328
  title,
1335
1329
  message,
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-06
4
+ ---
5
+
6
+ Clips recovers from stalled recording setup without requiring a restart
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-08-06
4
+ ---
5
+
6
+ Clips starts faster after a deploy or idle period — startup no longer re-scans recordings or re-probes columns one at a time on every cold start.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-06
4
+ ---
5
+
6
+ Deleting a recording returns cleanly to the library, and Fit to width fits the whole timeline.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-08-06
4
+ ---
5
+
6
+ Hide clip insights from viewers without analytics access
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-08-06
4
+ ---
5
+
6
+ Trimmed clips play on a clean timeline without cut markers
@@ -980,6 +980,7 @@ export function App() {
980
980
  );
981
981
  const [rewindHomeOpen, setRewindHomeOpen] = useState(false);
982
982
  const [recorder, setRecorder] = useState<RecorderHandle | null>(null);
983
+ const recordingStartAbortRef = useRef<AbortController | null>(null);
983
984
  const [recError, setRecError] = useState<string | null>(null);
984
985
  const [cameraError, setCameraError] = useState<string | null>(null);
985
986
  const [shortcutRegistrationError, setShortcutRegistrationError] = useState<
@@ -2267,14 +2268,14 @@ export function App() {
2267
2268
  try {
2268
2269
  await invoke("show_toolbar");
2269
2270
  if (cancelled) return;
2270
- // Seed disabled — previous recordings may have latched it on in
2271
- // the toolbar's React state (the window is destroyed on
2272
- // `hide_overlays`, so this is mostly defensive, but free).
2273
- emit("clips:toolbar-enabled", false).catch(() => {});
2274
2271
  } catch (err) {
2275
2272
  console.error("[clips-popover] show_toolbar failed:", err);
2276
2273
  }
2277
2274
  })();
2275
+ // Seed disabled before the asynchronous window creation. A late seed can
2276
+ // otherwise arrive after the recorder's enabled event and strand the
2277
+ // toolbar at 0:00.
2278
+ emit("clips:toolbar-enabled", false).catch(() => {});
2278
2279
  return () => {
2279
2280
  cancelled = true;
2280
2281
  // In screen-only mode the bubble effect never runs, so its
@@ -2889,6 +2890,9 @@ export function App() {
2889
2890
 
2890
2891
  let handle: RecorderHandle | null = null;
2891
2892
  let startError: unknown = null;
2893
+ const startController = new AbortController();
2894
+ recordingStartAbortRef.current = startController;
2895
+ let parkPopoverTimer: number | null = null;
2892
2896
  try {
2893
2897
  // Per Steve: "when we hit Start Recording the popover should disappear
2894
2898
  // BEFORE the screen picker shows up — otherwise you might accidentally
@@ -2940,11 +2944,11 @@ export function App() {
2940
2944
  preAcquiredCameraStream,
2941
2945
  preAcquiredDisplayStream: options?.resumeCapture?.displayStream ?? null,
2942
2946
  preAcquiredAudioStream: options?.resumeCapture?.audioStream ?? null,
2947
+ signal: startController.signal,
2943
2948
  });
2944
- // macOS: park the popover to its 2×2 pinhole IMMEDIATELY so it
2945
- // doesn't appear in the screen picker window list. The native
2946
- // Rust recorder used for full-screen doesn't need getDisplayMedia
2947
- // at all, so parking is always safe on macOS.
2949
+ // macOS: give WebKit a short window to dispatch getDisplayMedia before
2950
+ // parking the popover. Parking synchronously can leave the picker
2951
+ // request pending in a long-lived tray webview.
2948
2952
  //
2949
2953
  // Windows: do NOT park before getDisplayMedia resolves. On Windows,
2950
2954
  // the WebView2 screen picker UI renders within the popover webview —
@@ -2953,24 +2957,25 @@ export function App() {
2953
2957
  // popover itself (line ~2165) AFTER the streams are acquired, which
2954
2958
  // is the correct time on Windows.
2955
2959
  if (isMacPlatform()) {
2956
- invoke("park_popover_offscreen").catch(() => {});
2957
- emit("clips:popover-visible", false).catch(() => {});
2960
+ parkPopoverTimer = window.setTimeout(() => {
2961
+ if (!startController.signal.aborted && recordingFlowGateRef.current) {
2962
+ invoke("park_popover_offscreen").catch(() => {});
2963
+ emit("clips:popover-visible", false).catch(() => {});
2964
+ }
2965
+ }, 250);
2958
2966
  }
2959
-
2960
- // No watchdog — the macOS screen picker can stay open indefinitely
2961
- // (a user deciding which window to capture may take 20, 60, 180
2962
- // seconds). A false-positive timeout here fires recovery mid-setup,
2963
- // which flips `recordingFlowActive` back to false → the bubble
2964
- // session effect's cleanup runs and stops the popover-owned camera
2965
- // stream → the recorder ends up with a dead track when the screen
2966
- // picker finally resolves. If the user actually wants to abort,
2967
- // canceling the picker throws NotAllowedError and we recover through
2968
- // the normal error path.
2969
2967
  handle = await recordingPromise;
2970
2968
  console.log("[clips-popover] recorder handle received");
2971
2969
  } catch (err) {
2972
2970
  startError = err;
2973
2971
  } finally {
2972
+ if (parkPopoverTimer !== null) {
2973
+ window.clearTimeout(parkPopoverTimer);
2974
+ parkPopoverTimer = null;
2975
+ }
2976
+ if (recordingStartAbortRef.current === startController) {
2977
+ recordingStartAbortRef.current = null;
2978
+ }
2974
2979
  // If the recorder handle was NEVER set, ALWAYS run recovery here —
2975
2980
  // even if downstream code throws before reaching the failure
2976
2981
  // branch. This makes the tray-dead symptom impossible: regardless
@@ -3064,6 +3069,29 @@ export function App() {
3064
3069
  // include a function that is recreated every render.
3065
3070
  handleStartRecordingRef.current = handleStartRecording;
3066
3071
 
3072
+ // The toolbar exists before a recorder handle does. Keep its Cancel action
3073
+ // useful during capture setup, when the normal recorder event listener has
3074
+ // not been installed yet.
3075
+ useEffect(() => {
3076
+ let cancelled = false;
3077
+ let unlisten: (() => void) | null = null;
3078
+ listen("clips:recorder-cancel", () => {
3079
+ recordingStartAbortRef.current?.abort();
3080
+ })
3081
+ .then((nextUnlisten) => {
3082
+ if (cancelled) {
3083
+ nextUnlisten();
3084
+ return;
3085
+ }
3086
+ unlisten = nextUnlisten;
3087
+ })
3088
+ .catch(() => {});
3089
+ return () => {
3090
+ cancelled = true;
3091
+ unlisten?.();
3092
+ };
3093
+ }, []);
3094
+
3067
3095
  // Gates every start-recording gesture (button, global shortcut, permission
3068
3096
  // retry) on the mic toggle. When the mic is off we hold the actual
3069
3097
  // getDisplayMedia/getUserMedia call until the user confirms in