@agent-native/core 0.103.1 → 0.104.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 (565) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +30 -0
  3. package/corpus/core/package.json +9 -2
  4. package/corpus/core/src/agent/engine/credential-errors.ts +2 -2
  5. package/corpus/core/src/agent/production-agent.ts +30 -0
  6. package/corpus/core/src/agent/run-store.ts +12 -2
  7. package/corpus/core/src/cli/create.ts +1 -0
  8. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +30 -11
  9. package/corpus/core/src/cli/templates-meta.ts +4 -3
  10. package/corpus/core/src/client/AgentAskPopover.tsx +89 -0
  11. package/corpus/core/src/client/AgentChatHome.tsx +4 -0
  12. package/corpus/core/src/client/AgentPanel.tsx +321 -223
  13. package/corpus/core/src/client/AssistantChat.tsx +6 -10
  14. package/corpus/core/src/client/MultiTabAssistantChat.tsx +53 -372
  15. package/corpus/core/src/client/agent-chat-adapter.ts +13 -1
  16. package/corpus/core/src/client/agent-page/AgentContextTab.tsx +133 -149
  17. package/corpus/core/src/client/agent-page/AgentEmptyState.tsx +44 -0
  18. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +153 -82
  19. package/corpus/core/src/client/agent-page/AgentTabFrame.tsx +39 -0
  20. package/corpus/core/src/client/agent-page/AgentTabsPage.tsx +368 -356
  21. package/corpus/core/src/client/agent-page/types.ts +1 -1
  22. package/corpus/core/src/client/analytics.ts +51 -5
  23. package/corpus/core/src/client/chat/run-recovery.tsx +12 -4
  24. package/corpus/core/src/client/composer/PromptComposer.tsx +5 -15
  25. package/corpus/core/src/client/composer/TiptapComposer.tsx +32 -3
  26. package/corpus/core/src/client/dynamic-suggestions.ts +3 -3
  27. package/corpus/core/src/client/index.ts +16 -1
  28. package/corpus/core/src/client/resources/ResourceTree.tsx +249 -38
  29. package/corpus/core/src/client/resources/ResourcesPanel.tsx +307 -140
  30. package/corpus/core/src/client/session-replay.ts +158 -5
  31. package/corpus/core/src/client/settings/AutomationsSection.tsx +30 -10
  32. package/corpus/core/src/client/settings/SettingsPanel.tsx +3 -2
  33. package/corpus/core/src/client/settings/SettingsTabsPage.tsx +2 -0
  34. package/corpus/core/src/client/settings/agent-settings-search.ts +2 -2
  35. package/corpus/core/src/client/use-chat-threads.ts +2 -0
  36. package/corpus/core/src/connections/catalog.ts +49 -7
  37. package/corpus/core/src/db/index.ts +6 -1
  38. package/corpus/core/src/extensions/actions.ts +106 -16
  39. package/corpus/core/src/extensions/content-patch.ts +22 -0
  40. package/corpus/core/src/extensions/routes.ts +18 -0
  41. package/corpus/core/src/extensions/store.ts +8 -0
  42. package/corpus/core/src/index.ts +3 -0
  43. package/corpus/core/src/ingestion/docx.ts +158 -0
  44. package/corpus/core/src/ingestion/figma-node-to-html.ts +1860 -0
  45. package/corpus/core/src/ingestion/figma.ts +548 -0
  46. package/corpus/core/src/ingestion/index.ts +107 -0
  47. package/corpus/core/src/ingestion/media.ts +264 -0
  48. package/corpus/core/src/ingestion/notion.ts +121 -0
  49. package/corpus/core/src/ingestion/office.ts +214 -0
  50. package/corpus/core/src/ingestion/orchestration.ts +160 -0
  51. package/corpus/core/src/ingestion/pptx.ts +333 -0
  52. package/corpus/core/src/ingestion/selection.ts +81 -0
  53. package/corpus/core/src/ingestion/website.ts +151 -0
  54. package/corpus/core/src/integrations/plugin.ts +45 -37
  55. package/corpus/core/src/localization/default-messages.ts +35 -12
  56. package/corpus/core/src/observability/hosted-model-experiment.ts +118 -0
  57. package/corpus/core/src/observability/traces.ts +5 -3
  58. package/corpus/core/src/provider-api/index.ts +452 -8
  59. package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +18 -1
  60. package/corpus/core/src/search-utils/index.ts +112 -0
  61. package/corpus/core/src/secrets/register-framework-secrets.ts +61 -0
  62. package/corpus/core/src/server/action-discovery.ts +33 -8
  63. package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
  64. package/corpus/core/src/server/agent-chat/prompt-resources.ts +144 -0
  65. package/corpus/core/src/server/agent-chat-plugin.ts +6 -0
  66. package/corpus/core/src/server/core-routes-plugin.ts +12 -0
  67. package/corpus/core/src/server/index.ts +30 -0
  68. package/corpus/core/src/server/workspace-provider-oauth.ts +583 -0
  69. package/corpus/core/src/styles/agent-native.css +9 -0
  70. package/corpus/core/src/templates/default/app/i18n/en-US.ts +3 -3
  71. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  72. package/corpus/core/src/templates/workspace-root/.env.example +12 -0
  73. package/corpus/core/src/workspace-connections/index.ts +6 -0
  74. package/corpus/core/src/workspace-connections/lifecycle.ts +43 -0
  75. package/corpus/core/src/workspace-connections/store.ts +16 -0
  76. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +46 -3
  77. package/corpus/templates/analytics/AGENTS.md +9 -0
  78. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +120 -6
  79. package/corpus/templates/analytics/actions/mutate-dashboard.ts +92 -30
  80. package/corpus/templates/analytics/actions/update-dashboard.ts +5 -5
  81. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +313 -220
  82. package/corpus/templates/analytics/app/components/layout/CommandPalette.tsx +2 -2
  83. package/corpus/templates/analytics/app/components/layout/Layout.tsx +9 -6
  84. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +90 -64
  85. package/corpus/templates/analytics/app/i18n-data.ts +3 -3
  86. package/corpus/templates/analytics/app/lib/dashboard-list-loading.ts +25 -0
  87. package/corpus/templates/analytics/app/lib/item-popularity.ts +13 -4
  88. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +1 -1
  89. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/pivot.ts +8 -3
  90. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +1 -0
  91. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +15 -3
  92. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-filter-defaults-can-now-be-changed-reliably-withou.md +6 -0
  93. package/corpus/templates/analytics/changelog/2026-07-16-dashboard-lists-load-in-one-stable-order-without-popping-bet.md +6 -0
  94. package/corpus/templates/analytics/changelog/2026-07-16-fixed-dashboard-filter-dropdown-text-alignment.md +6 -0
  95. package/corpus/templates/analytics/changelog/2026-07-16-recurring-signed-in-users-can-now-be-viewed-as-weekly-bars-b.md +6 -0
  96. package/corpus/templates/analytics/changelog/2026-07-16-the-analytics-agent-can-now-duplicate-a-chart-and-place-the-.md +6 -0
  97. package/corpus/templates/analytics/seeds/dashboards/agent-native-templates-first-party.json +41 -1
  98. package/corpus/templates/analytics/server/lib/dashboard-catalog.ts +1 -1
  99. package/corpus/templates/analytics/server/lib/first-party-metric-catalog.ts +47 -1
  100. package/corpus/templates/analytics/server/lib/session-replay.ts +68 -0
  101. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -0
  102. package/corpus/templates/analytics/server/routes/sessions/lookup.get.ts +47 -0
  103. package/corpus/templates/assets/.agents/skills/asset-generation/SKILL.md +16 -9
  104. package/corpus/templates/assets/.agents/skills/creative-context/SKILL.md +86 -0
  105. package/corpus/templates/assets/AGENTS.md +10 -0
  106. package/corpus/templates/assets/actions/create-generation-session.ts +59 -1
  107. package/corpus/templates/assets/actions/edit-image.ts +2 -0
  108. package/corpus/templates/assets/actions/generate-asset.ts +52 -0
  109. package/corpus/templates/assets/actions/generate-image-batch.ts +55 -0
  110. package/corpus/templates/assets/actions/generate-image.ts +219 -1
  111. package/corpus/templates/assets/actions/open-asset-picker.ts +14 -0
  112. package/corpus/templates/assets/actions/refine-image.ts +3 -0
  113. package/corpus/templates/assets/actions/restyle-image.ts +2 -0
  114. package/corpus/templates/assets/agent-native.app-skill.json +4 -0
  115. package/corpus/templates/assets/app/components/layout/Layout.tsx +2 -0
  116. package/corpus/templates/assets/app/i18n/zh-TW.ts +3 -0
  117. package/corpus/templates/assets/app/i18n-data.ts +29 -13
  118. package/corpus/templates/assets/app/routes/agent.tsx +7 -1
  119. package/corpus/templates/assets/app/routes/library.tsx +9 -0
  120. package/corpus/templates/assets/app/routes/settings.tsx +3 -0
  121. package/corpus/templates/assets/changelog/2026-07-16-creative-context-library.md +6 -0
  122. package/corpus/templates/assets/package.json +1 -0
  123. package/corpus/templates/assets/server/lib/image-processing.ts +1 -22
  124. package/corpus/templates/assets/server/plugins/creative-context.ts +205 -0
  125. package/corpus/templates/brain/app/i18n-data.ts +3 -3
  126. package/corpus/templates/brain/app/lib/brain.ts +1 -1
  127. package/corpus/templates/brain/server/lib/search.ts +17 -67
  128. package/corpus/templates/calendar/app/i18n-data.ts +3 -3
  129. package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +19 -18
  130. package/corpus/templates/chat/app/i18n/en-US.ts +3 -3
  131. package/corpus/templates/chat/app/lib/agent-page.tsx +10 -1
  132. package/corpus/templates/clips/.agents/skills/meetings/SKILL.md +1 -1
  133. package/corpus/templates/clips/AGENTS.md +4 -0
  134. package/corpus/templates/clips/actions/cleanup-transcript.ts +35 -4
  135. package/corpus/templates/clips/actions/create-meeting.ts +6 -2
  136. package/corpus/templates/clips/actions/create-organization.ts +3 -2
  137. package/corpus/templates/clips/actions/create-recording.ts +4 -1
  138. package/corpus/templates/clips/actions/finalize-recording.ts +44 -7
  139. package/corpus/templates/clips/actions/import-loom-recording.ts +4 -1
  140. package/corpus/templates/clips/actions/lib/create-recording-schema.ts +2 -2
  141. package/corpus/templates/clips/actions/list-meetings.ts +23 -5
  142. package/corpus/templates/clips/actions/list-organization-state.ts +1 -1
  143. package/corpus/templates/clips/actions/remove-silences.ts +10 -1
  144. package/corpus/templates/clips/actions/request-transcript.ts +53 -11
  145. package/corpus/templates/clips/actions/search-recordings-utils.ts +7 -0
  146. package/corpus/templates/clips/actions/search-recordings.ts +5 -8
  147. package/corpus/templates/clips/actions/set-organization-branding.ts +2 -2
  148. package/corpus/templates/clips/actions/stitch-recordings.ts +10 -5
  149. package/corpus/templates/clips/actions/update-ai-request-status.ts +38 -0
  150. package/corpus/templates/clips/app/components/editor/editor-layout.tsx +3 -4
  151. package/corpus/templates/clips/app/components/editor/editor-selection.ts +19 -0
  152. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +10 -10
  153. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +1 -2
  154. package/corpus/templates/clips/app/components/library/library-grid.tsx +101 -93
  155. package/corpus/templates/clips/app/components/player/video-player.tsx +11 -0
  156. package/corpus/templates/clips/app/components/workspace/branding-editor.tsx +53 -1
  157. package/corpus/templates/clips/app/i18n/ar-SA.ts +7 -1
  158. package/corpus/templates/clips/app/i18n/de-DE.ts +7 -1
  159. package/corpus/templates/clips/app/i18n/en-US.ts +10 -4
  160. package/corpus/templates/clips/app/i18n/es-ES.ts +7 -1
  161. package/corpus/templates/clips/app/i18n/fr-FR.ts +7 -1
  162. package/corpus/templates/clips/app/i18n/hi-IN.ts +7 -1
  163. package/corpus/templates/clips/app/i18n/ja-JP.ts +7 -1
  164. package/corpus/templates/clips/app/i18n/ko-KR.ts +7 -1
  165. package/corpus/templates/clips/app/i18n/pt-BR.ts +7 -1
  166. package/corpus/templates/clips/app/i18n/zh-CN.ts +6 -1
  167. package/corpus/templates/clips/app/i18n/zh-TW.ts +6 -1
  168. package/corpus/templates/clips/app/routes/_app.settings._index.tsx +5 -9
  169. package/corpus/templates/clips/app/routes/_app.settings.organization.tsx +6 -2
  170. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +129 -27
  171. package/corpus/templates/clips/app/routes/record.tsx +23 -2
  172. package/corpus/templates/clips/app/routes/share.$shareId.tsx +6 -2
  173. package/corpus/templates/clips/changelog/2026-07-16-authorized-viewers-can-open-shared-private-clips-without-a-m.md +6 -0
  174. package/corpus/templates/clips/changelog/2026-07-16-camera-bubble-hover-controls-appear-above-the-face.md +6 -0
  175. package/corpus/templates/clips/changelog/2026-07-16-chrome-extension-recovers-stale-recorder-state.md +6 -0
  176. package/corpus/templates/clips/changelog/2026-07-16-clips-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  177. package/corpus/templates/clips/changelog/2026-07-16-clips-search-now-matches-recording-content-without-requiring.md +6 -0
  178. package/corpus/templates/clips/changelog/2026-07-16-declined-meetings-no-longer-show-desktop-reminders.md +6 -0
  179. package/corpus/templates/clips/changelog/2026-07-16-failed-desktop-saves-now-show-their-local-recovery-copy.md +6 -0
  180. package/corpus/templates/clips/changelog/2026-07-16-long-desktop-clips-now-preserve-complete-playback-synced-aud.md +6 -0
  181. package/corpus/templates/clips/changelog/2026-07-16-long-recording-lists-keep-stitch-and-library-actions-visible.md +6 -0
  182. package/corpus/templates/clips/changelog/2026-07-16-organization-admins-can-choose-new-recording-visibility.md +6 -0
  183. package/corpus/templates/clips/changelog/2026-07-16-remove-silences-now-shows-queued-active-completed-and-failed.md +6 -0
  184. package/corpus/templates/clips/changelog/2026-07-16-settings-no-longer-repeats-the-builder-connection-status-in-.md +6 -0
  185. package/corpus/templates/clips/changelog/2026-07-16-transcripts-now-appear-from-native-browser-speech-sooner-wit.md +6 -0
  186. package/corpus/templates/clips/chrome-extension/public/manifest.json +1 -1
  187. package/corpus/templates/clips/chrome-extension/src/background.ts +73 -1
  188. package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +32 -0
  189. package/corpus/templates/clips/chrome-extension/src/native-transcription.ts +248 -0
  190. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +106 -0
  191. package/corpus/templates/clips/desktop/src/app.tsx +66 -28
  192. package/corpus/templates/clips/desktop/src/lib/recorder.ts +335 -285
  193. package/corpus/templates/clips/desktop/src/lib/single-flight.ts +7 -0
  194. package/corpus/templates/clips/desktop/src/lib/upload-verification.ts +51 -0
  195. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +2 -2
  196. package/corpus/templates/clips/desktop/src/overlays/finalizing.tsx +10 -2
  197. package/corpus/templates/clips/desktop/src/styles.css +13 -11
  198. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +8 -9
  199. package/corpus/templates/clips/desktop/src-tauri/src/meetings_watcher.rs +1 -0
  200. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +88 -13
  201. package/corpus/templates/clips/desktop/src-tauri/src/native_screen/live_upload.rs +13 -2
  202. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +241 -6
  203. package/corpus/templates/clips/server/db/schema.ts +2 -2
  204. package/corpus/templates/clips/server/lib/builder-media-compression.ts +64 -67
  205. package/corpus/templates/clips/server/lib/calendar-event-classification.ts +19 -0
  206. package/corpus/templates/clips/server/lib/google-calendar-client.ts +1 -0
  207. package/corpus/templates/clips/server/lib/recordings.ts +40 -1
  208. package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
  209. package/corpus/templates/clips/server/plugins/db.ts +2 -2
  210. package/corpus/templates/clips/server/routes/api/auth/google-calendar.get.ts +1 -1
  211. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +14 -5
  212. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +51 -1
  213. package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +1 -64
  214. package/corpus/templates/clips/shared/media-worker-contract.ts +32 -15
  215. package/corpus/templates/content/.agents/skills/content/SKILL.md +16 -0
  216. package/corpus/templates/content/.agents/skills/creative-context/SKILL.md +85 -0
  217. package/corpus/templates/content/.agents/skills/notion-integration/SKILL.md +8 -0
  218. package/corpus/templates/content/AGENTS.md +9 -0
  219. package/corpus/templates/content/actions/create-document.ts +94 -0
  220. package/corpus/templates/content/actions/edit-document.ts +144 -4
  221. package/corpus/templates/content/actions/update-document.ts +138 -0
  222. package/corpus/templates/content/agent-native.app-skill.json +4 -0
  223. package/corpus/templates/content/app/components/layout/Layout.tsx +2 -0
  224. package/corpus/templates/content/app/i18n/zh-TW.ts +3 -0
  225. package/corpus/templates/content/app/i18n-data.ts +13 -4
  226. package/corpus/templates/content/app/routes/_app.agent.tsx +2 -1
  227. package/corpus/templates/content/app/routes/_app.settings.tsx +3 -0
  228. package/corpus/templates/content/changelog/2026-07-16-creative-context-library.md +6 -0
  229. package/corpus/templates/content/package.json +1 -0
  230. package/corpus/templates/content/server/plugins/creative-context.ts +31 -0
  231. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +116 -0
  232. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +16 -0
  233. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  234. package/corpus/templates/design/AGENTS.md +6 -0
  235. package/corpus/templates/design/actions/clone-creative-context-design.ts +176 -0
  236. package/corpus/templates/design/actions/edit-design.ts +128 -0
  237. package/corpus/templates/design/actions/generate-design.ts +278 -14
  238. package/corpus/templates/design/actions/generate-screens.ts +42 -1
  239. package/corpus/templates/design/agent-native.app-skill.json +4 -0
  240. package/corpus/templates/design/app/components/layout/Layout.tsx +7 -3
  241. package/corpus/templates/design/app/i18n/zh-TW.ts +3 -0
  242. package/corpus/templates/design/app/i18n-data.ts +10 -4
  243. package/corpus/templates/design/app/routes/agent.tsx +2 -1
  244. package/corpus/templates/design/app/routes/settings.tsx +3 -0
  245. package/corpus/templates/design/changelog/2026-07-16-creative-context-library.md +6 -0
  246. package/corpus/templates/design/changelog/2026-07-16-design-agent-chat-no-longer-shows-a-separate-workspace-header.md +6 -0
  247. package/corpus/templates/design/package.json +1 -0
  248. package/corpus/templates/design/server/lib/figma-design-context.ts +5 -335
  249. package/corpus/templates/design/server/lib/figma-node-to-html.ts +1 -1859
  250. package/corpus/templates/design/server/lib/import-design-files.ts +6 -8
  251. package/corpus/templates/design/server/plugins/creative-context.ts +31 -0
  252. package/corpus/templates/design/shared/generation-session.ts +7 -0
  253. package/corpus/templates/dispatch/app/i18n-data.ts +3 -3
  254. package/corpus/templates/forms/app/i18n/en-US.ts +3 -3
  255. package/corpus/templates/macros/app/i18n/en-US.ts +3 -3
  256. package/corpus/templates/mail/app/components/email/EmailThread.tsx +35 -5
  257. package/corpus/templates/mail/app/i18n/en-US.ts +3 -3
  258. package/corpus/templates/mail/changelog/2026-07-16-mail-previews-now-expand-to-show-the-full-message-without-an.md +6 -0
  259. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +30 -11
  260. package/corpus/templates/plan/AGENTS.md +21 -1
  261. package/corpus/templates/plan/actions/get-visual-plan.ts +1 -1
  262. package/corpus/templates/plan/actions/patch-visual-plan-source.ts +161 -0
  263. package/corpus/templates/plan/actions/read-visual-plan-source.ts +1 -1
  264. package/corpus/templates/plan/actions/update-visual-plan.ts +126 -10
  265. package/corpus/templates/plan/app/hooks/use-plans.ts +2 -0
  266. package/corpus/templates/plan/app/i18n/en-US.ts +3 -3
  267. package/corpus/templates/plan/app/pages/PlansPage.tsx +65 -62
  268. package/corpus/templates/plan/changelog/2026-07-16-local-plan-previews-now-load-annotations-containing-html-lik.md +6 -0
  269. package/corpus/templates/plan/changelog/2026-07-16-plan-agents-now-prevent-stale-edits-from-overwriting-newer-p.md +6 -0
  270. package/corpus/templates/plan/server/plan-mdx.ts +75 -2
  271. package/corpus/templates/slides/.agents/skills/create-deck/SKILL.md +21 -4
  272. package/corpus/templates/slides/.agents/skills/creative-context/SKILL.md +122 -0
  273. package/corpus/templates/slides/.agents/skills/design-systems/SKILL.md +11 -0
  274. package/corpus/templates/slides/.agents/skills/slide-editing/SKILL.md +12 -3
  275. package/corpus/templates/slides/AGENTS.md +6 -0
  276. package/corpus/templates/slides/actions/add-slide.ts +230 -14
  277. package/corpus/templates/slides/actions/clone-context-slide.ts +302 -0
  278. package/corpus/templates/slides/actions/create-deck.ts +130 -0
  279. package/corpus/templates/slides/actions/extract-pdf.ts +6 -2
  280. package/corpus/templates/slides/actions/import-file.ts +5 -4
  281. package/corpus/templates/slides/actions/patch-deck.ts +200 -10
  282. package/corpus/templates/slides/actions/update-slide.ts +208 -15
  283. package/corpus/templates/slides/app/components/layout/Layout.tsx +2 -0
  284. package/corpus/templates/slides/app/components/visual-editor/CanvasCommentPins.tsx +16 -1
  285. package/corpus/templates/slides/app/i18n/ar-SA.ts +3 -0
  286. package/corpus/templates/slides/app/i18n/de-DE.ts +3 -0
  287. package/corpus/templates/slides/app/i18n/en-US.ts +6 -3
  288. package/corpus/templates/slides/app/i18n/es-ES.ts +3 -0
  289. package/corpus/templates/slides/app/i18n/fr-FR.ts +3 -0
  290. package/corpus/templates/slides/app/i18n/hi-IN.ts +3 -0
  291. package/corpus/templates/slides/app/i18n/ja-JP.ts +3 -0
  292. package/corpus/templates/slides/app/i18n/ko-KR.ts +3 -0
  293. package/corpus/templates/slides/app/i18n/pt-BR.ts +3 -0
  294. package/corpus/templates/slides/app/i18n/zh-CN.ts +3 -0
  295. package/corpus/templates/slides/app/i18n/zh-TW.ts +3 -0
  296. package/corpus/templates/slides/app/lib/validate-native-slide-html.ts +176 -0
  297. package/corpus/templates/slides/app/routes/agent.tsx +7 -1
  298. package/corpus/templates/slides/app/routes/settings.tsx +3 -0
  299. package/corpus/templates/slides/changelog/2026-07-16-creative-context-library.md +6 -0
  300. package/corpus/templates/slides/changelog/2026-07-16-google-slides-native-cloning.md +6 -0
  301. package/corpus/templates/slides/package.json +1 -0
  302. package/corpus/templates/slides/server/handlers/import/docx-parser.ts +4 -85
  303. package/corpus/templates/slides/server/handlers/import/pptx-parser.ts +7 -421
  304. package/corpus/templates/slides/server/plugins/creative-context.ts +166 -0
  305. package/dist/agent/engine/credential-errors.d.ts +1 -1
  306. package/dist/agent/engine/credential-errors.d.ts.map +1 -1
  307. package/dist/agent/engine/credential-errors.js +2 -2
  308. package/dist/agent/engine/credential-errors.js.map +1 -1
  309. package/dist/agent/production-agent.d.ts.map +1 -1
  310. package/dist/agent/production-agent.js +25 -0
  311. package/dist/agent/production-agent.js.map +1 -1
  312. package/dist/agent/run-store.d.ts.map +1 -1
  313. package/dist/agent/run-store.js +12 -2
  314. package/dist/agent/run-store.js.map +1 -1
  315. package/dist/cli/create.d.ts.map +1 -1
  316. package/dist/cli/create.js +1 -0
  317. package/dist/cli/create.js.map +1 -1
  318. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  319. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  320. package/dist/cli/skills-content/visual-plan-skill.js +30 -11
  321. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  322. package/dist/cli/templates-meta.d.ts.map +1 -1
  323. package/dist/cli/templates-meta.js +4 -3
  324. package/dist/cli/templates-meta.js.map +1 -1
  325. package/dist/client/AgentAskPopover.d.ts +11 -0
  326. package/dist/client/AgentAskPopover.d.ts.map +1 -0
  327. package/dist/client/AgentAskPopover.js +30 -0
  328. package/dist/client/AgentAskPopover.js.map +1 -0
  329. package/dist/client/AgentChatHome.d.ts +1 -1
  330. package/dist/client/AgentChatHome.d.ts.map +1 -1
  331. package/dist/client/AgentChatHome.js +2 -2
  332. package/dist/client/AgentChatHome.js.map +1 -1
  333. package/dist/client/AgentPanel.d.ts +9 -19
  334. package/dist/client/AgentPanel.d.ts.map +1 -1
  335. package/dist/client/AgentPanel.js +119 -80
  336. package/dist/client/AgentPanel.js.map +1 -1
  337. package/dist/client/AssistantChat.d.ts.map +1 -1
  338. package/dist/client/AssistantChat.js +4 -4
  339. package/dist/client/AssistantChat.js.map +1 -1
  340. package/dist/client/MultiTabAssistantChat.d.ts +3 -9
  341. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  342. package/dist/client/MultiTabAssistantChat.js +49 -189
  343. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  344. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  345. package/dist/client/agent-chat-adapter.js +12 -1
  346. package/dist/client/agent-chat-adapter.js.map +1 -1
  347. package/dist/client/agent-page/AgentContextTab.d.ts.map +1 -1
  348. package/dist/client/agent-page/AgentContextTab.js +26 -28
  349. package/dist/client/agent-page/AgentContextTab.js.map +1 -1
  350. package/dist/client/agent-page/AgentEmptyState.d.ts +13 -0
  351. package/dist/client/agent-page/AgentEmptyState.d.ts.map +1 -0
  352. package/dist/client/agent-page/AgentEmptyState.js +6 -0
  353. package/dist/client/agent-page/AgentEmptyState.js.map +1 -0
  354. package/dist/client/agent-page/AgentJobsTab.d.ts +1 -1
  355. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  356. package/dist/client/agent-page/AgentJobsTab.js +90 -58
  357. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  358. package/dist/client/agent-page/AgentTabFrame.d.ts +12 -0
  359. package/dist/client/agent-page/AgentTabFrame.d.ts.map +1 -0
  360. package/dist/client/agent-page/AgentTabFrame.js +7 -0
  361. package/dist/client/agent-page/AgentTabFrame.js.map +1 -0
  362. package/dist/client/agent-page/AgentTabsPage.d.ts +9 -1
  363. package/dist/client/agent-page/AgentTabsPage.d.ts.map +1 -1
  364. package/dist/client/agent-page/AgentTabsPage.js +135 -99
  365. package/dist/client/agent-page/AgentTabsPage.js.map +1 -1
  366. package/dist/client/agent-page/types.d.ts +1 -1
  367. package/dist/client/agent-page/types.d.ts.map +1 -1
  368. package/dist/client/agent-page/types.js.map +1 -1
  369. package/dist/client/analytics.d.ts +10 -3
  370. package/dist/client/analytics.d.ts.map +1 -1
  371. package/dist/client/analytics.js +37 -2
  372. package/dist/client/analytics.js.map +1 -1
  373. package/dist/client/chat/run-recovery.d.ts.map +1 -1
  374. package/dist/client/chat/run-recovery.js +10 -3
  375. package/dist/client/chat/run-recovery.js.map +1 -1
  376. package/dist/client/composer/PromptComposer.d.ts.map +1 -1
  377. package/dist/client/composer/PromptComposer.js +2 -2
  378. package/dist/client/composer/PromptComposer.js.map +1 -1
  379. package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
  380. package/dist/client/composer/TiptapComposer.js +15 -3
  381. package/dist/client/composer/TiptapComposer.js.map +1 -1
  382. package/dist/client/dynamic-suggestions.js +3 -3
  383. package/dist/client/dynamic-suggestions.js.map +1 -1
  384. package/dist/client/index.d.ts +4 -3
  385. package/dist/client/index.d.ts.map +1 -1
  386. package/dist/client/index.js +3 -2
  387. package/dist/client/index.js.map +1 -1
  388. package/dist/client/resources/ResourceTree.d.ts +5 -1
  389. package/dist/client/resources/ResourceTree.d.ts.map +1 -1
  390. package/dist/client/resources/ResourceTree.js +74 -5
  391. package/dist/client/resources/ResourceTree.js.map +1 -1
  392. package/dist/client/resources/ResourcesPanel.d.ts +11 -2
  393. package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
  394. package/dist/client/resources/ResourcesPanel.js +105 -31
  395. package/dist/client/resources/ResourcesPanel.js.map +1 -1
  396. package/dist/client/session-replay.d.ts +28 -0
  397. package/dist/client/session-replay.d.ts.map +1 -1
  398. package/dist/client/session-replay.js +122 -8
  399. package/dist/client/session-replay.js.map +1 -1
  400. package/dist/client/settings/AutomationsSection.d.ts +3 -1
  401. package/dist/client/settings/AutomationsSection.d.ts.map +1 -1
  402. package/dist/client/settings/AutomationsSection.js +16 -6
  403. package/dist/client/settings/AutomationsSection.js.map +1 -1
  404. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  405. package/dist/client/settings/SettingsPanel.js +3 -3
  406. package/dist/client/settings/SettingsPanel.js.map +1 -1
  407. package/dist/client/settings/SettingsTabsPage.d.ts +2 -0
  408. package/dist/client/settings/SettingsTabsPage.d.ts.map +1 -1
  409. package/dist/client/settings/SettingsTabsPage.js.map +1 -1
  410. package/dist/client/settings/agent-settings-search.js +2 -2
  411. package/dist/client/settings/agent-settings-search.js.map +1 -1
  412. package/dist/client/use-chat-threads.d.ts +2 -0
  413. package/dist/client/use-chat-threads.d.ts.map +1 -1
  414. package/dist/client/use-chat-threads.js.map +1 -1
  415. package/dist/collab/routes.d.ts +1 -1
  416. package/dist/connections/catalog.d.ts +41 -7
  417. package/dist/connections/catalog.d.ts.map +1 -1
  418. package/dist/connections/catalog.js +40 -7
  419. package/dist/connections/catalog.js.map +1 -1
  420. package/dist/db/index.d.ts +2 -2
  421. package/dist/db/index.d.ts.map +1 -1
  422. package/dist/db/index.js +2 -2
  423. package/dist/db/index.js.map +1 -1
  424. package/dist/extensions/actions.d.ts.map +1 -1
  425. package/dist/extensions/actions.js +85 -15
  426. package/dist/extensions/actions.js.map +1 -1
  427. package/dist/extensions/content-patch.d.ts +4 -0
  428. package/dist/extensions/content-patch.d.ts.map +1 -1
  429. package/dist/extensions/content-patch.js +18 -0
  430. package/dist/extensions/content-patch.js.map +1 -1
  431. package/dist/extensions/routes.d.ts.map +1 -1
  432. package/dist/extensions/routes.js +14 -0
  433. package/dist/extensions/routes.js.map +1 -1
  434. package/dist/extensions/store.d.ts +1 -0
  435. package/dist/extensions/store.d.ts.map +1 -1
  436. package/dist/extensions/store.js +4 -1
  437. package/dist/extensions/store.js.map +1 -1
  438. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  439. package/dist/index.d.ts +1 -1
  440. package/dist/index.d.ts.map +1 -1
  441. package/dist/index.js +1 -1
  442. package/dist/index.js.map +1 -1
  443. package/dist/ingestion/docx.d.ts +16 -0
  444. package/dist/ingestion/docx.d.ts.map +1 -0
  445. package/dist/ingestion/docx.js +129 -0
  446. package/dist/ingestion/docx.js.map +1 -0
  447. package/dist/ingestion/figma-node-to-html.d.ts +304 -0
  448. package/dist/ingestion/figma-node-to-html.d.ts.map +1 -0
  449. package/dist/ingestion/figma-node-to-html.js +1292 -0
  450. package/dist/ingestion/figma-node-to-html.js.map +1 -0
  451. package/dist/ingestion/figma.d.ts +115 -0
  452. package/dist/ingestion/figma.d.ts.map +1 -0
  453. package/dist/ingestion/figma.js +399 -0
  454. package/dist/ingestion/figma.js.map +1 -0
  455. package/dist/ingestion/index.d.ts +11 -0
  456. package/dist/ingestion/index.d.ts.map +1 -0
  457. package/dist/ingestion/index.js +11 -0
  458. package/dist/ingestion/index.js.map +1 -0
  459. package/dist/ingestion/media.d.ts +36 -0
  460. package/dist/ingestion/media.d.ts.map +1 -0
  461. package/dist/ingestion/media.js +178 -0
  462. package/dist/ingestion/media.js.map +1 -0
  463. package/dist/ingestion/notion.d.ts +12 -0
  464. package/dist/ingestion/notion.d.ts.map +1 -0
  465. package/dist/ingestion/notion.js +104 -0
  466. package/dist/ingestion/notion.js.map +1 -0
  467. package/dist/ingestion/office.d.ts +45 -0
  468. package/dist/ingestion/office.d.ts.map +1 -0
  469. package/dist/ingestion/office.js +141 -0
  470. package/dist/ingestion/office.js.map +1 -0
  471. package/dist/ingestion/orchestration.d.ts +52 -0
  472. package/dist/ingestion/orchestration.d.ts.map +1 -0
  473. package/dist/ingestion/orchestration.js +89 -0
  474. package/dist/ingestion/orchestration.js.map +1 -0
  475. package/dist/ingestion/pptx.d.ts +28 -0
  476. package/dist/ingestion/pptx.d.ts.map +1 -0
  477. package/dist/ingestion/pptx.js +255 -0
  478. package/dist/ingestion/pptx.js.map +1 -0
  479. package/dist/ingestion/selection.d.ts +20 -0
  480. package/dist/ingestion/selection.d.ts.map +1 -0
  481. package/dist/ingestion/selection.js +52 -0
  482. package/dist/ingestion/selection.js.map +1 -0
  483. package/dist/ingestion/website.d.ts +27 -0
  484. package/dist/ingestion/website.d.ts.map +1 -0
  485. package/dist/ingestion/website.js +100 -0
  486. package/dist/ingestion/website.js.map +1 -0
  487. package/dist/integrations/plugin.d.ts.map +1 -1
  488. package/dist/integrations/plugin.js +32 -27
  489. package/dist/integrations/plugin.js.map +1 -1
  490. package/dist/localization/default-messages.d.ts +22 -0
  491. package/dist/localization/default-messages.d.ts.map +1 -1
  492. package/dist/localization/default-messages.js +31 -9
  493. package/dist/localization/default-messages.js.map +1 -1
  494. package/dist/notifications/routes.d.ts +1 -1
  495. package/dist/observability/hosted-model-experiment.d.ts +39 -0
  496. package/dist/observability/hosted-model-experiment.d.ts.map +1 -0
  497. package/dist/observability/hosted-model-experiment.js +90 -0
  498. package/dist/observability/hosted-model-experiment.js.map +1 -0
  499. package/dist/observability/traces.d.ts.map +1 -1
  500. package/dist/observability/traces.js +5 -3
  501. package/dist/observability/traces.js.map +1 -1
  502. package/dist/progress/routes.d.ts +1 -1
  503. package/dist/provider-api/index.d.ts +35 -4
  504. package/dist/provider-api/index.d.ts.map +1 -1
  505. package/dist/provider-api/index.js +339 -8
  506. package/dist/provider-api/index.js.map +1 -1
  507. package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
  508. package/dist/scripts/agent-engines/list-agent-engines.js +18 -1
  509. package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
  510. package/dist/search-utils/index.d.ts +12 -0
  511. package/dist/search-utils/index.d.ts.map +1 -0
  512. package/dist/search-utils/index.js +95 -0
  513. package/dist/search-utils/index.js.map +1 -0
  514. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  515. package/dist/secrets/register-framework-secrets.js +57 -0
  516. package/dist/secrets/register-framework-secrets.js.map +1 -1
  517. package/dist/server/action-discovery.d.ts +8 -0
  518. package/dist/server/action-discovery.d.ts.map +1 -1
  519. package/dist/server/action-discovery.js +26 -9
  520. package/dist/server/action-discovery.js.map +1 -1
  521. package/dist/server/agent-chat/framework-prompts.js +2 -2
  522. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  523. package/dist/server/agent-chat/prompt-resources.d.ts +19 -0
  524. package/dist/server/agent-chat/prompt-resources.d.ts.map +1 -1
  525. package/dist/server/agent-chat/prompt-resources.js +95 -0
  526. package/dist/server/agent-chat/prompt-resources.js.map +1 -1
  527. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  528. package/dist/server/agent-chat-plugin.js +7 -0
  529. package/dist/server/agent-chat-plugin.js.map +1 -1
  530. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  531. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  532. package/dist/server/core-routes-plugin.js +5 -0
  533. package/dist/server/core-routes-plugin.js.map +1 -1
  534. package/dist/server/index.d.ts +5 -1
  535. package/dist/server/index.d.ts.map +1 -1
  536. package/dist/server/index.js +5 -1
  537. package/dist/server/index.js.map +1 -1
  538. package/dist/server/workspace-provider-oauth.d.ts +48 -0
  539. package/dist/server/workspace-provider-oauth.d.ts.map +1 -0
  540. package/dist/server/workspace-provider-oauth.js +415 -0
  541. package/dist/server/workspace-provider-oauth.js.map +1 -0
  542. package/dist/styles/agent-native.css +9 -0
  543. package/dist/templates/chat/app/i18n/en-US.ts +3 -3
  544. package/dist/templates/chat/app/lib/agent-page.tsx +10 -1
  545. package/dist/templates/default/app/i18n/en-US.ts +3 -3
  546. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  547. package/dist/templates/workspace-root/.env.example +12 -0
  548. package/dist/workspace-connections/index.d.ts +1 -0
  549. package/dist/workspace-connections/index.d.ts.map +1 -1
  550. package/dist/workspace-connections/index.js +1 -0
  551. package/dist/workspace-connections/index.js.map +1 -1
  552. package/dist/workspace-connections/lifecycle.d.ts +16 -0
  553. package/dist/workspace-connections/lifecycle.d.ts.map +1 -0
  554. package/dist/workspace-connections/lifecycle.js +14 -0
  555. package/dist/workspace-connections/lifecycle.js.map +1 -0
  556. package/dist/workspace-connections/store.d.ts.map +1 -1
  557. package/dist/workspace-connections/store.js +16 -0
  558. package/dist/workspace-connections/store.js.map +1 -1
  559. package/package.json +10 -3
  560. package/src/templates/chat/app/i18n/en-US.ts +3 -3
  561. package/src/templates/chat/app/lib/agent-page.spec.tsx +10 -1
  562. package/src/templates/chat/app/lib/agent-page.tsx +10 -1
  563. package/src/templates/default/app/i18n/en-US.ts +3 -3
  564. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +14 -5
  565. package/src/templates/workspace-root/.env.example +12 -0
@@ -0,0 +1,7 @@
1
+ export function singleFlight<T>(operation: () => Promise<T>): () => Promise<T> {
2
+ let inFlight: Promise<T> | null = null;
3
+ return () => {
4
+ inFlight ??= operation();
5
+ return inFlight;
6
+ };
7
+ }
@@ -0,0 +1,51 @@
1
+ export interface FinalizeReceipt {
2
+ ok?: unknown;
3
+ finalized?: unknown;
4
+ status?: unknown;
5
+ sourceSizeBytes?: unknown;
6
+ durationMs?: unknown;
7
+ }
8
+
9
+ export interface LocalRecordingProof {
10
+ bytes: number;
11
+ durationMs: number;
12
+ }
13
+
14
+ export function verifyFinalizeReceipt(
15
+ receipt: FinalizeReceipt | null,
16
+ local: LocalRecordingProof,
17
+ ): void {
18
+ if (
19
+ !receipt ||
20
+ receipt.ok !== true ||
21
+ receipt.finalized !== true ||
22
+ receipt.status !== "ready"
23
+ ) {
24
+ throw new Error(
25
+ "Clip may be incomplete. Finalization was not confirmed; the local backup was kept.",
26
+ );
27
+ }
28
+
29
+ const sourceSizeBytes = Number(receipt.sourceSizeBytes);
30
+ if (
31
+ !Number.isFinite(sourceSizeBytes) ||
32
+ sourceSizeBytes <= 0 ||
33
+ sourceSizeBytes !== local.bytes
34
+ ) {
35
+ throw new Error(
36
+ `Clip may be incomplete. The server confirmed ${Number.isFinite(sourceSizeBytes) ? sourceSizeBytes : "an unknown number of"} of ${local.bytes} source bytes; the local backup was kept.`,
37
+ );
38
+ }
39
+
40
+ const durationMs = Number(receipt.durationMs);
41
+ const toleranceMs = Math.max(5_000, local.durationMs * 0.02);
42
+ if (
43
+ !Number.isFinite(durationMs) ||
44
+ durationMs <= 0 ||
45
+ Math.abs(durationMs - local.durationMs) > toleranceMs
46
+ ) {
47
+ throw new Error(
48
+ "Clip may be incomplete. The uploaded duration did not match the local recording; the local backup was kept.",
49
+ );
50
+ }
51
+ }
@@ -48,7 +48,7 @@ type BubbleSize = "small" | "medium";
48
48
  *
49
49
  * # Hover controls (Loom-style)
50
50
  *
51
- * On pointerenter, a small horizontal pill fades in under the bubble
51
+ * On pointerenter, a small horizontal pill fades in above the bubble
52
52
  * with two size-dot buttons (small / medium) and an X close button.
53
53
  * Clicking a dot calls `set_bubble_size` on the Rust side, which
54
54
  * resizes this window and persists the choice to disk. On
@@ -752,7 +752,7 @@ export function Bubble() {
752
752
  </svg>
753
753
  </button>
754
754
  </div>
755
- {/* Size control pill — fades in under the bubble on hover. Marked
755
+ {/* Size control pill — fades in above the bubble on hover. Marked
756
756
  `data-no-drag` so clicks land on the onClick handlers. */}
757
757
  <div
758
758
  className={`bubble-controls ${showControls ? "is-visible" : ""}`}
@@ -20,6 +20,7 @@ type ProcessingProgress = {
20
20
  stage?: string;
21
21
  progress?: number | null;
22
22
  viewUrl?: string;
23
+ savedLocally?: boolean;
23
24
  };
24
25
 
25
26
  type NativeUploadFinished = {
@@ -52,7 +53,10 @@ function takePersistedFinalizingResult(): NativeUploadFinished | null {
52
53
  viewUrl: payload.viewUrl,
53
54
  ok: payload.ok,
54
55
  error: typeof payload.error === "string" ? payload.error : null,
55
- localFilePath: null,
56
+ localFilePath:
57
+ typeof payload.localFilePath === "string"
58
+ ? payload.localFilePath
59
+ : null,
56
60
  };
57
61
  } catch {
58
62
  return null;
@@ -78,6 +82,7 @@ export function Finalizing() {
78
82
  let completionTimer: ReturnType<typeof window.setTimeout> | null = null;
79
83
  let openingWatchdog: ReturnType<typeof window.setTimeout> | null = null;
80
84
  const hardWatchdog = window.setTimeout(() => {
85
+ void invoke("show_popover").catch(() => {});
81
86
  void invoke("hide_finalizing").catch(() => {});
82
87
  }, 120_000);
83
88
  let finishedHandled = false;
@@ -164,6 +169,7 @@ export function Finalizing() {
164
169
  stage: "failed",
165
170
  progress: 1,
166
171
  viewUrl: payload.viewUrl,
172
+ savedLocally: Boolean(payload.localFilePath),
167
173
  });
168
174
  completionTimer = window.setTimeout(() => {
169
175
  void invoke("show_popover").catch(() => {});
@@ -212,7 +218,9 @@ export function Finalizing() {
212
218
  progress.stage === "uploaded"
213
219
  ? "Uploaded"
214
220
  : progress.stage === "failed"
215
- ? "Upload paused"
221
+ ? progress.savedLocally
222
+ ? "Upload paused — clip saved locally"
223
+ : "Upload paused — open Clips to recover"
216
224
  : progress.stage === "uploading" ||
217
225
  progress.stage === "processing" ||
218
226
  progress.stage === "opening"
@@ -3131,25 +3131,27 @@ body[data-clips-route="recording-pill"] #root {
3131
3131
 
3132
3132
  /*
3133
3133
  * The Tauri bubble window is sized (in Rust) to exactly the circle diameter
3134
- * PLUS a `--bubble-controls-budget` strip at the bottom, so the hover pill
3134
+ * PLUS a `--bubble-controls-budget` strip at the top, so the hover pill
3135
3135
  * has real window real-estate to render into. Everything outside window
3136
3136
  * bounds is invisible no matter the CSS `overflow` — you can't paint where
3137
3137
  * the OS hasn't given you pixels — so we build in the budget up front.
3138
3138
  *
3139
3139
  * ┌──────────────┐
3140
+ * │ · ● │ ← .bubble-controls pill (hover-faded)
3141
+ * └──────────────┘
3142
+ * ┌──────────────┐
3140
3143
  * │ .bubble-root │ ← circle (drag region, data-tauri-drag-region)
3141
3144
  * │ ◯ │ Canvas lives here with pointer-events: none so
3142
3145
  * │ │ drags reach the drag-region parent.
3143
3146
  * └──────────────┘
3144
- * ┌──────────────┐
3145
- * │ · ● │ ← .bubble-controls pill (hover-faded)
3146
- * └──────────────┘
3147
3147
  */
3148
3148
  .bubble-wrapper {
3149
3149
  position: fixed;
3150
3150
  inset: var(--overlay-shadow-gutter);
3151
3151
  display: flex;
3152
- flex-direction: column;
3152
+ /* Reverse the stack so the circle stays at the bottom of the window and
3153
+ the hover pill occupies the reserved space above it. */
3154
+ flex-direction: column-reverse;
3153
3155
  align-items: center;
3154
3156
  /* Transparent background — the Tauri window is `transparent: true`,
3155
3157
  so the circular camera surface below paints through. */
@@ -3159,9 +3161,9 @@ body[data-clips-route="recording-pill"] #root {
3159
3161
  }
3160
3162
 
3161
3163
  .bubble-root {
3162
- /* Circle fills the top of the wrapper. We use `flex: 0 0 auto` + a
3164
+ /* Circle fills the bottom of the wrapper. We use `flex: 0 0 auto` + a
3163
3165
  1:1 aspect-ratio so the circle is always square regardless of the
3164
- actual window height (which includes the controls budget). */
3166
+ actual window height (which includes the controls budget above it). */
3165
3167
  flex: 0 0 auto;
3166
3168
  aspect-ratio: 1 / 1;
3167
3169
  /* Width = 100% of wrapper → the wrapper is exactly bubble-diameter
@@ -3269,15 +3271,15 @@ body[data-clips-route="recording-pill"] #root {
3269
3271
  color: white;
3270
3272
  }
3271
3273
 
3272
- /* Size-control pill — lives in the bottom strip of the wrapper (beneath
3274
+ /* Size-control pill — lives in the top strip of the wrapper (above
3273
3275
  the circle). Centered horizontally, fades in on hover, matches Loom's
3274
3276
  visual weight. Because it's a sibling of `.bubble-root` (not a child),
3275
3277
  the border-radius clipping on the circle can't eat it. */
3276
3278
  .bubble-controls {
3277
- /* `flex: 0 0 auto` + margin-top creates the small gap between the
3278
- circle and the pill. */
3279
+ /* `flex: 0 0 auto` + margin-bottom creates the small gap between the
3280
+ pill and the circle. */
3279
3281
  flex: 0 0 auto;
3280
- margin-top: 8px;
3282
+ margin-bottom: 8px;
3281
3283
  display: inline-flex;
3282
3284
  align-items: center;
3283
3285
  gap: 8px;
@@ -87,7 +87,7 @@ enum TextInsertionStrategy {
87
87
  UnicodeType,
88
88
  }
89
89
 
90
- /// Extra vertical real-estate reserved beneath the circular bubble for the
90
+ /// Extra vertical real-estate reserved above the circular bubble for the
91
91
  /// hover-controls pill (small-dot + medium-dot). The Tauri window is
92
92
  /// `transparent: true`, so the budget paints through as empty space until the
93
93
  /// user hovers the bubble and the pill fades in. We'd otherwise have no pixels
@@ -95,7 +95,7 @@ enum TextInsertionStrategy {
95
95
  /// matter what CSS `overflow` says.
96
96
  ///
97
97
  /// 80 physical px ≈ 40 logical px on retina — enough for the ~28px pill plus
98
- /// an 8px gap from the circle, with a small cushion at the window bottom.
98
+ /// an 8px gap from the circle, with a small cushion at the window top.
99
99
  const BUBBLE_CONTROLS_BUDGET_PX: u32 = 80;
100
100
 
101
101
  fn overlay_scale_factor(app: &AppHandle) -> f64 {
@@ -128,7 +128,7 @@ fn bubble_size_for_name(name: &str) -> u32 {
128
128
  }
129
129
 
130
130
  /// Total window height for a bubble of the given diameter — includes the
131
- /// controls-budget strip beneath the circle.
131
+ /// controls-budget strip above the circle.
132
132
  fn bubble_window_height_for(size: u32) -> u32 {
133
133
  size + BUBBLE_CONTROLS_BUDGET_PX
134
134
  }
@@ -874,18 +874,17 @@ pub async fn show_bubble(app: AppHandle) -> Result<(), String> {
874
874
  let size_name = load_bubble_size_name(&app);
875
875
  let size: u32 = bubble_size_for_name(&size_name);
876
876
  // The actual window is TALLER than the circle — see
877
- // `BUBBLE_CONTROLS_BUDGET_PX` — to give the hover controls pill room.
877
+ // `BUBBLE_CONTROLS_BUDGET_PX` — to give the hover controls pill room
878
+ // above the face while keeping the face aligned to the bottom edge.
878
879
  let gutter = overlay_shadow_gutter_physical(&app);
879
- let content_h: u32 = bubble_window_height_for(size);
880
880
  let (win_w, win_h) = bubble_window_size_for(&app, size);
881
881
 
882
882
  let (mon_x, mon_y, mon_w, mon_h) = tray_monitor_physical_rect(&app);
883
883
 
884
- // Default Loom-style anchor: flush-left with a small margin, a hair
885
- // above the bottom edge of the target monitor. On Retina the 60
886
- // physical-px offset maps to ~30 logical px.
884
+ // Default Loom-style anchor: flush-left with the circle resting against
885
+ // the bottom edge of the target monitor (inside the shadow gutter).
887
886
  let default_x: i32 = mon_x + 48 - gutter as i32;
888
- let default_y: i32 = mon_y + mon_h as i32 - content_h as i32 - 60 - gutter as i32;
887
+ let default_y: i32 = mon_y + mon_h as i32 - win_h as i32;
889
888
  let (default_x, default_y) =
890
889
  clamp_bubble_window_position(&app, default_x, default_y, win_w, win_h);
891
890
  // Keep saved positions, but normalize them against the current display
@@ -298,6 +298,7 @@ async fn tick_once(app: &AppHandle, client: &reqwest::Client) -> Result<(), Stri
298
298
  // upcoming window to include recently-started events (see action).
299
299
  ("includeStartedWithinMin", "5"),
300
300
  ("excludePersonalSoloEvents", "true"),
301
+ ("excludeDeclinedEvents", "true"),
301
302
  ]);
302
303
  req = req.header("X-Request-Source", "clips-desktop");
303
304
  if let Some(c) = cookie.as_deref() {
@@ -1088,6 +1088,93 @@ impl MixerTimeline {
1088
1088
  (0.0, 0.0)
1089
1089
  }
1090
1090
  }
1091
+
1092
+ fn push_at(
1093
+ &mut self,
1094
+ frame_index: i64,
1095
+ interleaved: &[f32],
1096
+ min_base_frame: i64,
1097
+ max_gap: i64,
1098
+ ) {
1099
+ let frames = interleaved.len() / 2;
1100
+ if frames == 0 {
1101
+ return;
1102
+ }
1103
+ if !self.started {
1104
+ self.started = true;
1105
+ self.base_frame = frame_index.max(min_base_frame);
1106
+ }
1107
+
1108
+ let cur_end = self.end_frame();
1109
+ if frame_index > cur_end {
1110
+ let gap = (frame_index - cur_end).min(max_gap) as usize;
1111
+ self.samples
1112
+ .extend(std::iter::repeat(0.0_f32).take(gap * 2));
1113
+ }
1114
+
1115
+ let overlap_frames = (cur_end - frame_index).max(0) as usize;
1116
+ if overlap_frames < frames {
1117
+ self.samples
1118
+ .extend_from_slice(&interleaved[overlap_frames * 2..]);
1119
+ }
1120
+ }
1121
+ }
1122
+
1123
+ #[cfg(test)]
1124
+ mod mixer_timeline_tests {
1125
+ use super::MixerTimeline;
1126
+
1127
+ fn stereo_frames(values: &[f32]) -> Vec<f32> {
1128
+ values.iter().flat_map(|value| [*value, *value]).collect()
1129
+ }
1130
+
1131
+ #[test]
1132
+ fn trims_overlapping_frames_instead_of_extending_the_timeline() {
1133
+ let mut timeline = MixerTimeline::new();
1134
+ timeline.push_at(0, &stereo_frames(&[1.0, 2.0, 3.0, 4.0]), 0, 96_000);
1135
+ timeline.push_at(3, &stereo_frames(&[4.0, 5.0, 6.0, 7.0]), 0, 96_000);
1136
+
1137
+ assert_eq!(
1138
+ timeline.samples,
1139
+ stereo_frames(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0])
1140
+ );
1141
+ assert_eq!(timeline.end_frame(), 7);
1142
+ }
1143
+
1144
+ #[test]
1145
+ fn ignores_fully_duplicated_buffers() {
1146
+ let mut timeline = MixerTimeline::new();
1147
+ let frames = stereo_frames(&[1.0, 2.0, 3.0]);
1148
+ timeline.push_at(0, &frames, 0, 96_000);
1149
+ timeline.push_at(0, &frames, 0, 96_000);
1150
+
1151
+ assert_eq!(timeline.samples, frames);
1152
+ assert_eq!(timeline.end_frame(), 3);
1153
+ }
1154
+
1155
+ #[test]
1156
+ fn trims_input_that_starts_behind_already_emitted_output() {
1157
+ let mut timeline = MixerTimeline::new();
1158
+ timeline.started = true;
1159
+ timeline.base_frame = 10;
1160
+ timeline.push_at(8, &stereo_frames(&[1.0, 2.0, 3.0, 4.0]), 10, 96_000);
1161
+
1162
+ assert_eq!(timeline.samples, stereo_frames(&[3.0, 4.0]));
1163
+ assert_eq!(timeline.end_frame(), 12);
1164
+ }
1165
+
1166
+ #[test]
1167
+ fn preserves_forward_timestamp_gaps_as_silence() {
1168
+ let mut timeline = MixerTimeline::new();
1169
+ timeline.push_at(0, &stereo_frames(&[1.0, 2.0]), 0, 96_000);
1170
+ timeline.push_at(5, &stereo_frames(&[6.0]), 0, 96_000);
1171
+
1172
+ assert_eq!(
1173
+ timeline.samples,
1174
+ stereo_frames(&[1.0, 2.0, 0.0, 0.0, 0.0, 6.0])
1175
+ );
1176
+ assert_eq!(timeline.end_frame(), 6);
1177
+ }
1091
1178
  }
1092
1179
 
1093
1180
  enum SourceBound {
@@ -1198,19 +1285,7 @@ impl LiveAudioMixer {
1198
1285
  MixSource::System => &mut self.system,
1199
1286
  MixSource::Mic => &mut self.mic,
1200
1287
  };
1201
- if !timeline.started {
1202
- timeline.started = true;
1203
- // Never start behind already-emitted output.
1204
- timeline.base_frame = frame_index.max(out_pos);
1205
- }
1206
- let cur_end = timeline.end_frame();
1207
- if frame_index > cur_end {
1208
- let gap = (frame_index - cur_end).min(max_gap) as usize;
1209
- timeline
1210
- .samples
1211
- .extend(std::iter::repeat(0.0_f32).take(gap * 2));
1212
- }
1213
- timeline.samples.extend_from_slice(interleaved);
1288
+ timeline.push_at(frame_index, interleaved, out_pos, max_gap);
1214
1289
  timeline.last_push = Some(Instant::now());
1215
1290
  }
1216
1291
 
@@ -161,6 +161,7 @@ async fn send_live_upload_post_with_retry(
161
161
  total: usize,
162
162
  is_final: bool,
163
163
  duration_ms: Option<u128>,
164
+ expected_source_bytes: Option<u64>,
164
165
  bytes: &[u8],
165
166
  ) -> Result<(), String> {
166
167
  let rec = &params.recording_id;
@@ -192,6 +193,7 @@ async fn send_live_upload_post_with_retry(
192
193
  params.has_camera,
193
194
  NativeUploadMode::Buffered,
194
195
  false,
196
+ expected_source_bytes,
195
197
  bytes.to_vec(),
196
198
  )
197
199
  .await;
@@ -258,7 +260,7 @@ async fn live_upload_loop(
258
260
  bytes.len()
259
261
  );
260
262
  if let Err(e) = send_live_upload_post_with_retry(
261
- &client, &ctrl, &params, index, 0, false, None, &bytes,
263
+ &client, &ctrl, &params, index, 0, false, None, None, &bytes,
262
264
  )
263
265
  .await
264
266
  {
@@ -301,7 +303,15 @@ async fn live_upload_loop(
301
303
  "[live-upload] {rec}: sending tail chunk #{index} offset={offset} size={take} final={is_last}"
302
304
  );
303
305
  if let Err(e) = send_live_upload_post_with_retry(
304
- &client, &ctrl, &params, index, total, is_last, duration, &bytes,
306
+ &client,
307
+ &ctrl,
308
+ &params,
309
+ index,
310
+ total,
311
+ is_last,
312
+ duration,
313
+ is_last.then_some(final_len),
314
+ &bytes,
305
315
  )
306
316
  .await
307
317
  {
@@ -329,6 +339,7 @@ async fn live_upload_loop(
329
339
  index + 1,
330
340
  true,
331
341
  Some(duration_ms),
342
+ Some(final_len),
332
343
  &[],
333
344
  )
334
345
  .await