@agent-native/core 0.114.15 → 0.115.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 (467) hide show
  1. package/agent-native.eject.json +2 -0
  2. package/bin/agent-native.js +35 -14
  3. package/bin/launcher.js +34 -0
  4. package/corpus/README.md +3 -3
  5. package/corpus/core/CHANGELOG.md +35 -0
  6. package/corpus/core/agent-native.eject.json +2 -0
  7. package/corpus/core/bin/agent-native.js +35 -14
  8. package/corpus/core/bin/launcher.js +34 -0
  9. package/corpus/core/docs/content/agent-native-toolkit.mdx +16 -0
  10. package/corpus/core/docs/content/recurring-jobs.mdx +35 -6
  11. package/corpus/core/export-snapshot.json +4 -0
  12. package/corpus/core/package.json +5 -1
  13. package/corpus/core/src/action.ts +22 -1
  14. package/corpus/core/src/agent/production-agent.ts +105 -3
  15. package/corpus/core/src/cli/templates-meta.ts +12 -0
  16. package/corpus/core/src/client/AssistantChat.tsx +53 -26
  17. package/corpus/core/src/client/agent-page/AgentJobsTab.tsx +19 -0
  18. package/corpus/core/src/client/agent-page/use-jobs.ts +1 -0
  19. package/corpus/core/src/client/chat/message-components.tsx +35 -1
  20. package/corpus/core/src/client/chat/tool-call-display.tsx +38 -3
  21. package/corpus/core/src/connections/catalog.ts +20 -1
  22. package/corpus/core/src/connections/reader.ts +65 -0
  23. package/corpus/core/src/dashboard-storage/index.ts +27 -0
  24. package/corpus/core/src/dashboard-storage/panel-source.ts +168 -0
  25. package/corpus/core/src/dashboard-storage/schema.ts +62 -0
  26. package/corpus/core/src/dashboard-storage/store.ts +333 -0
  27. package/corpus/core/src/deploy/build.ts +95 -16
  28. package/corpus/core/src/eject/provider-api-definitions.ts +1 -0
  29. package/corpus/core/src/eject/workspace-connections.ts +1 -0
  30. package/corpus/core/src/extensions/actions.ts +199 -73
  31. package/corpus/core/src/jobs/actions/list-recurring-jobs.ts +2 -0
  32. package/corpus/core/src/jobs/scheduler.ts +71 -4
  33. package/corpus/core/src/jobs/tools.ts +31 -1
  34. package/corpus/core/src/localization/default-messages.ts +1 -0
  35. package/corpus/core/src/mcp-client/index.ts +6 -0
  36. package/corpus/core/src/provider-api/actions/provider-api.ts +1 -1
  37. package/corpus/core/src/provider-api/index.ts +190 -5
  38. package/corpus/core/src/secrets/register-framework-secrets.ts +8 -0
  39. package/corpus/core/src/server/agent-chat/context-tools.ts +9 -0
  40. package/corpus/core/src/server/agent-chat/framework-prompts.ts +2 -2
  41. package/corpus/core/src/server/agent-chat-plugin.ts +22 -2
  42. package/corpus/core/src/server/core-routes-plugin.ts +1 -0
  43. package/corpus/core/src/server/credential-provider.ts +9 -3
  44. package/corpus/core/src/server/workspace-provider-oauth.ts +181 -4
  45. package/corpus/core/src/styles/agent-native.css +45 -2
  46. package/corpus/core/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  47. package/corpus/core/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  48. package/corpus/core/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  49. package/corpus/core/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  50. package/corpus/core/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  51. package/corpus/core/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  52. package/corpus/core/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  53. package/corpus/core/src/triggers/actions.ts +11 -2
  54. package/corpus/core/src/triggers/dispatcher.ts +20 -1
  55. package/corpus/core/src/triggers/types.ts +5 -0
  56. package/corpus/core/src/vite/action-types-plugin.ts +9 -1
  57. package/corpus/templates/analytics/.agents/skills/agent-native-docs/SKILL.md +115 -0
  58. package/corpus/templates/analytics/AGENTS.md +11 -11
  59. package/corpus/templates/analytics/_gitignore +39 -0
  60. package/corpus/templates/analytics/actions/query-dashboard-panel.ts +30 -0
  61. package/corpus/templates/analytics/actions/update-dashboard.ts +2 -1
  62. package/corpus/templates/analytics/app/lib/sql-query.ts +11 -25
  63. package/corpus/templates/analytics/changelog/2026-07-21-fixed-extension-updates-failing-before-changes-could-be-appl.md +6 -0
  64. package/corpus/templates/analytics/server/lib/dashboard-panel-query.ts +1 -0
  65. package/corpus/templates/analytics/server/lib/dashboard-panel-source-resolver.ts +51 -0
  66. package/corpus/templates/analytics/server/lib/prometheus.ts +1 -1
  67. package/corpus/templates/analytics/server/plugins/agent-chat.ts +1 -1
  68. package/corpus/templates/assets/.agents/skills/agent-native-docs/SKILL.md +115 -0
  69. package/corpus/templates/brain/.agents/skills/agent-native-docs/SKILL.md +115 -0
  70. package/corpus/templates/calendar/.agents/skills/agent-native-docs/SKILL.md +115 -0
  71. package/corpus/templates/calendar/_gitignore +39 -0
  72. package/corpus/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  73. package/corpus/templates/chat/AGENTS.md +1 -1
  74. package/corpus/templates/clips/.agents/skills/agent-native-docs/SKILL.md +115 -0
  75. package/corpus/templates/clips/AGENTS.md +7 -0
  76. package/corpus/templates/clips/actions/prepare-crm-call-evidence.ts +58 -0
  77. package/corpus/templates/clips/app/components/library/bulk-action-toolbar.tsx +25 -8
  78. package/corpus/templates/clips/app/components/library/library-grid.tsx +118 -9
  79. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  80. package/corpus/templates/clips/app/components/library/recording-card.tsx +10 -8
  81. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +88 -11
  82. package/corpus/templates/clips/app/i18n/en-US.ts +6 -0
  83. package/corpus/templates/clips/app/routes/_app.trash.tsx +16 -1
  84. package/corpus/templates/clips/changelog/2026-07-21-crm-call-evidence-handoff.md +6 -0
  85. package/corpus/templates/clips/changelog/2026-07-21-recording-retries-and-restarts-keep-their-upload-session-so-.md +6 -0
  86. package/corpus/templates/clips/chrome-extension/src/background.ts +20 -5
  87. package/corpus/templates/clips/chrome-extension/src/native-recording-state.ts +19 -0
  88. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -0
  89. package/corpus/templates/clips/desktop/src/app.tsx +24 -3
  90. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +9 -0
  91. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +54 -28
  92. package/corpus/templates/clips/server/plugins/agent-chat.ts +1 -0
  93. package/corpus/templates/content/.agents/skills/agent-native-docs/SKILL.md +115 -0
  94. package/corpus/templates/content/_gitignore +39 -0
  95. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +20 -38
  96. package/corpus/templates/content/app/components/editor/previewDocumentSaveController.ts +40 -1
  97. package/corpus/templates/content/learnings.defaults.md +5 -0
  98. package/corpus/templates/crm/.agents/skills/agent-native-docs/SKILL.md +115 -0
  99. package/corpus/templates/crm/.agents/skills/agent-native-toolkit/SKILL.md +133 -0
  100. package/corpus/templates/crm/.agents/skills/crm/SKILL.md +128 -0
  101. package/corpus/templates/crm/.agents/skills/customizing-agent-native/SKILL.md +145 -0
  102. package/corpus/templates/crm/.agents/skills/feature-flags/SKILL.md +169 -0
  103. package/corpus/templates/crm/.agents/skills/upgrade-agent-native/SKILL.md +100 -0
  104. package/corpus/templates/crm/.env.example +5 -0
  105. package/corpus/templates/crm/AGENTS.md +120 -0
  106. package/corpus/templates/crm/CHANGELOG.md +1 -0
  107. package/corpus/templates/crm/DEVELOPING.md +66 -0
  108. package/corpus/templates/crm/README.md +106 -0
  109. package/corpus/templates/crm/_gitignore +12 -0
  110. package/corpus/templates/crm/actions/_crm-action-utils.ts +87 -0
  111. package/corpus/templates/crm/actions/_crm-dashboard.ts +69 -0
  112. package/corpus/templates/crm/actions/_crm-signal-utils.ts +79 -0
  113. package/corpus/templates/crm/actions/apply-crm-proposals.ts +203 -0
  114. package/corpus/templates/crm/actions/attach-call-evidence.ts +170 -0
  115. package/corpus/templates/crm/actions/configure-crm-connection.ts +126 -0
  116. package/corpus/templates/crm/actions/configure-native-crm.ts +44 -0
  117. package/corpus/templates/crm/actions/create-crm-record.ts +148 -0
  118. package/corpus/templates/crm/actions/create-crm-signal-tracker.ts +58 -0
  119. package/corpus/templates/crm/actions/delete-staged-dataset.ts +14 -0
  120. package/corpus/templates/crm/actions/get-crm-automation-recipe.ts +36 -0
  121. package/corpus/templates/crm/actions/get-crm-dashboard-panel.ts +33 -0
  122. package/corpus/templates/crm/actions/get-crm-dashboard.ts +14 -0
  123. package/corpus/templates/crm/actions/get-crm-overview.ts +13 -0
  124. package/corpus/templates/crm/actions/get-crm-pipeline-data.ts +61 -0
  125. package/corpus/templates/crm/actions/get-crm-record.ts +75 -0
  126. package/corpus/templates/crm/actions/install-crm-pipeline-dashboard.ts +81 -0
  127. package/corpus/templates/crm/actions/list-crm-dashboard-revisions.ts +15 -0
  128. package/corpus/templates/crm/actions/list-crm-dashboards.ts +15 -0
  129. package/corpus/templates/crm/actions/list-crm-proposals.ts +31 -0
  130. package/corpus/templates/crm/actions/list-crm-records.ts +79 -0
  131. package/corpus/templates/crm/actions/list-crm-saved-views.ts +15 -0
  132. package/corpus/templates/crm/actions/list-crm-signal-hits.ts +43 -0
  133. package/corpus/templates/crm/actions/list-crm-signal-trackers.ts +32 -0
  134. package/corpus/templates/crm/actions/list-crm-tasks.ts +22 -0
  135. package/corpus/templates/crm/actions/list-staged-datasets.ts +14 -0
  136. package/corpus/templates/crm/actions/list-workspace-connections.ts +47 -0
  137. package/corpus/templates/crm/actions/manage-crm-signal-tracker.ts +87 -0
  138. package/corpus/templates/crm/actions/manage-crm-task.ts +132 -0
  139. package/corpus/templates/crm/actions/navigate.ts +63 -0
  140. package/corpus/templates/crm/actions/provider-api-catalog.ts +22 -0
  141. package/corpus/templates/crm/actions/provider-api-docs.ts +54 -0
  142. package/corpus/templates/crm/actions/provider-api-request.ts +92 -0
  143. package/corpus/templates/crm/actions/query-staged-dataset.ts +44 -0
  144. package/corpus/templates/crm/actions/record-crm-call-insight.ts +160 -0
  145. package/corpus/templates/crm/actions/record-crm-smart-signal.ts +150 -0
  146. package/corpus/templates/crm/actions/restore-crm-dashboard-revision.ts +23 -0
  147. package/corpus/templates/crm/actions/review-crm-signal.ts +31 -0
  148. package/corpus/templates/crm/actions/run-crm-saved-view-program.ts +103 -0
  149. package/corpus/templates/crm/actions/run-crm-signal-trackers.ts +275 -0
  150. package/corpus/templates/crm/actions/run.ts +11 -0
  151. package/corpus/templates/crm/actions/save-crm-dashboard.ts +51 -0
  152. package/corpus/templates/crm/actions/save-crm-saved-view.ts +119 -0
  153. package/corpus/templates/crm/actions/sync-crm.ts +146 -0
  154. package/corpus/templates/crm/actions/update-crm-record.ts +508 -0
  155. package/corpus/templates/crm/actions/view-screen.ts +218 -0
  156. package/corpus/templates/crm/agent-native.app-skill.json +58 -0
  157. package/corpus/templates/crm/app/components/crm/CreateCrmRecordDialog.tsx +158 -0
  158. package/corpus/templates/crm/app/components/crm/CrmDashboardPanel.tsx +83 -0
  159. package/corpus/templates/crm/app/components/crm/CrmSignalsPanel.tsx +225 -0
  160. package/corpus/templates/crm/app/components/crm/IntelligenceSettings.tsx +413 -0
  161. package/corpus/templates/crm/app/components/crm/RecordActions.tsx +510 -0
  162. package/corpus/templates/crm/app/components/crm/RecordGrid.tsx +134 -0
  163. package/corpus/templates/crm/app/components/crm/RecordWorkspace.tsx +367 -0
  164. package/corpus/templates/crm/app/components/crm/SavedViewDataProgram.tsx +92 -0
  165. package/corpus/templates/crm/app/components/crm/Surface.tsx +96 -0
  166. package/corpus/templates/crm/app/components/crm/WorkOverview.tsx +180 -0
  167. package/corpus/templates/crm/app/components/layout/CrmLayout.tsx +106 -0
  168. package/corpus/templates/crm/app/components/layout/CrmSidebar.tsx +84 -0
  169. package/corpus/templates/crm/app/entry.client.tsx +16 -0
  170. package/corpus/templates/crm/app/entry.server.tsx +10 -0
  171. package/corpus/templates/crm/app/global.css +167 -0
  172. package/corpus/templates/crm/app/hooks/use-navigation-state.ts +60 -0
  173. package/corpus/templates/crm/app/i18n/en-US.ts +89 -0
  174. package/corpus/templates/crm/app/i18n/index.ts +34 -0
  175. package/corpus/templates/crm/app/lib/dashboard.ts +13 -0
  176. package/corpus/templates/crm/app/lib/navigation.ts +54 -0
  177. package/corpus/templates/crm/app/lib/tab-id.ts +1 -0
  178. package/corpus/templates/crm/app/lib/types.ts +172 -0
  179. package/corpus/templates/crm/app/lib/utils.ts +1 -0
  180. package/corpus/templates/crm/app/root.tsx +88 -0
  181. package/corpus/templates/crm/app/routes/_index.tsx +26 -0
  182. package/corpus/templates/crm/app/routes/accounts.tsx +41 -0
  183. package/corpus/templates/crm/app/routes/agent.tsx +5 -0
  184. package/corpus/templates/crm/app/routes/ask.tsx +53 -0
  185. package/corpus/templates/crm/app/routes/dashboard.tsx +118 -0
  186. package/corpus/templates/crm/app/routes/opportunities.tsx +41 -0
  187. package/corpus/templates/crm/app/routes/people.tsx +41 -0
  188. package/corpus/templates/crm/app/routes/proposals.tsx +266 -0
  189. package/corpus/templates/crm/app/routes/records.$recordId.tsx +35 -0
  190. package/corpus/templates/crm/app/routes/settings.tsx +63 -0
  191. package/corpus/templates/crm/app/routes/setup.tsx +308 -0
  192. package/corpus/templates/crm/app/routes/tasks.tsx +252 -0
  193. package/corpus/templates/crm/app/routes/views.tsx +333 -0
  194. package/corpus/templates/crm/app/routes.ts +17 -0
  195. package/corpus/templates/crm/app/vite-env.d.ts +6 -0
  196. package/corpus/templates/crm/changelog/2026-07-21-agent-native-crm.md +6 -0
  197. package/corpus/templates/crm/changelog/2026-07-21-clips-call-evidence-review-recipe.md +6 -0
  198. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-find-and-review-evidence-grounded-call-signals-w.md +6 -0
  199. package/corpus/templates/crm/changelog/2026-07-21-crm-can-now-manage-keyword-and-smart-call-signal-trackers-fr.md +6 -0
  200. package/corpus/templates/crm/changelog/2026-07-21-delegated-local-crm-automation.md +6 -0
  201. package/corpus/templates/crm/changelog/2026-07-21-native-sql.md +6 -0
  202. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboard.md +6 -0
  203. package/corpus/templates/crm/changelog/2026-07-21-pipeline-dashboards-now-install-correctly-from-the-crm-actio.md +6 -0
  204. package/corpus/templates/crm/changelog/2026-07-21-salesforce-connection.md +6 -0
  205. package/corpus/templates/crm/components.json +20 -0
  206. package/corpus/templates/crm/docs/architecture/crm-contract.md +180 -0
  207. package/corpus/templates/crm/learnings.defaults.md +5 -0
  208. package/corpus/templates/crm/package.json +59 -0
  209. package/corpus/templates/crm/public/favicon.svg +1 -0
  210. package/corpus/templates/crm/public/icon-180.svg +1 -0
  211. package/corpus/templates/crm/public/manifest.json +11 -0
  212. package/corpus/templates/crm/react-router.config.ts +7 -0
  213. package/corpus/templates/crm/server/crm/adapter.ts +32 -0
  214. package/corpus/templates/crm/server/crm/crm-field-firewall.ts +64 -0
  215. package/corpus/templates/crm/server/crm/crm-mirror.ts +711 -0
  216. package/corpus/templates/crm/server/crm/hubspot-adapter.ts +1143 -0
  217. package/corpus/templates/crm/server/crm/native-adapter.ts +1715 -0
  218. package/corpus/templates/crm/server/crm/read-through.ts +207 -0
  219. package/corpus/templates/crm/server/crm/salesforce-adapter.ts +1255 -0
  220. package/corpus/templates/crm/server/db/crm-store.ts +1170 -0
  221. package/corpus/templates/crm/server/db/index.ts +169 -0
  222. package/corpus/templates/crm/server/db/schema.ts +441 -0
  223. package/corpus/templates/crm/server/lib/intelligence/default-detectors.ts +65 -0
  224. package/corpus/templates/crm/server/lib/intelligence/evidence.ts +105 -0
  225. package/corpus/templates/crm/server/lib/intelligence/keyword-detector.ts +100 -0
  226. package/corpus/templates/crm/server/lib/intelligence/smart-detector.ts +144 -0
  227. package/corpus/templates/crm/server/lib/intelligence/summary.ts +141 -0
  228. package/corpus/templates/crm/server/lib/provider-api.ts +64 -0
  229. package/corpus/templates/crm/server/middleware/auth.ts +4 -0
  230. package/corpus/templates/crm/server/plugins/agent-chat.ts +68 -0
  231. package/corpus/templates/crm/server/plugins/auth.ts +14 -0
  232. package/corpus/templates/crm/server/plugins/core-routes.ts +17 -0
  233. package/corpus/templates/crm/server/plugins/db.ts +454 -0
  234. package/corpus/templates/crm/server/routes/[...page].get.ts +5 -0
  235. package/corpus/templates/crm/shared/crm-automation-recipes.ts +132 -0
  236. package/corpus/templates/crm/shared/crm-contract.ts +254 -0
  237. package/corpus/templates/crm/shared/crm-sales-config.ts +63 -0
  238. package/corpus/templates/crm/ssr-entry.ts +11 -0
  239. package/corpus/templates/crm/tsconfig.json +24 -0
  240. package/corpus/templates/crm/vite.config.ts +15 -0
  241. package/corpus/templates/crm/vitest.config.ts +5 -0
  242. package/corpus/templates/design/.agents/skills/agent-native-docs/SKILL.md +115 -0
  243. package/corpus/templates/dispatch/.agents/skills/agent-native-docs/SKILL.md +115 -0
  244. package/corpus/templates/forms/.agents/skills/agent-native-docs/SKILL.md +115 -0
  245. package/corpus/templates/forms/_gitignore +39 -0
  246. package/corpus/templates/forms/learnings.defaults.md +5 -0
  247. package/corpus/templates/macros/.agents/skills/agent-native-docs/SKILL.md +115 -0
  248. package/corpus/templates/macros/_gitignore +39 -0
  249. package/corpus/templates/macros/learnings.defaults.md +5 -0
  250. package/corpus/templates/mail/.agents/skills/agent-native-docs/SKILL.md +115 -0
  251. package/corpus/templates/mail/_gitignore +39 -0
  252. package/corpus/templates/plan/.agents/skills/agent-native-docs/SKILL.md +115 -0
  253. package/corpus/templates/slides/.agents/skills/agent-native-docs/SKILL.md +115 -0
  254. package/corpus/templates/slides/_gitignore +39 -0
  255. package/corpus/templates/tasks/.agents/skills/agent-native-docs/SKILL.md +27 -0
  256. package/corpus/templates/tasks/_gitignore +39 -0
  257. package/corpus/toolkit/CHANGELOG.md +12 -0
  258. package/corpus/toolkit/README.md +30 -0
  259. package/corpus/toolkit/agent-native.eject.json +33 -0
  260. package/corpus/toolkit/package.json +15 -1
  261. package/corpus/toolkit/src/dashboard/DataTable.tsx +273 -0
  262. package/corpus/toolkit/src/dashboard/DateRangePicker.tsx +57 -0
  263. package/corpus/toolkit/src/dashboard/GenericChartPanel.tsx +461 -0
  264. package/corpus/toolkit/src/dashboard/MetricCard.tsx +54 -0
  265. package/corpus/toolkit/src/dashboard/StatsCard.tsx +49 -0
  266. package/corpus/toolkit/src/dashboard/dashboard-layout.ts +329 -0
  267. package/corpus/toolkit/src/dashboard/index.ts +6 -0
  268. package/corpus/toolkit/src/index.ts +1 -0
  269. package/corpus/toolkit/src/ui/calendar.tsx +8 -8
  270. package/corpus/toolkit/src/ui/date-picker.tsx +4 -1
  271. package/dist/action.d.ts +14 -1
  272. package/dist/action.d.ts.map +1 -1
  273. package/dist/action.js.map +1 -1
  274. package/dist/agent/production-agent.d.ts +3 -1
  275. package/dist/agent/production-agent.d.ts.map +1 -1
  276. package/dist/agent/production-agent.js +83 -3
  277. package/dist/agent/production-agent.js.map +1 -1
  278. package/dist/cli/templates-meta.d.ts.map +1 -1
  279. package/dist/cli/templates-meta.js +12 -0
  280. package/dist/cli/templates-meta.js.map +1 -1
  281. package/dist/client/AssistantChat.d.ts +4 -0
  282. package/dist/client/AssistantChat.d.ts.map +1 -1
  283. package/dist/client/AssistantChat.js +30 -17
  284. package/dist/client/AssistantChat.js.map +1 -1
  285. package/dist/client/agent-page/AgentJobsTab.d.ts.map +1 -1
  286. package/dist/client/agent-page/AgentJobsTab.js +3 -1
  287. package/dist/client/agent-page/AgentJobsTab.js.map +1 -1
  288. package/dist/client/agent-page/use-jobs.d.ts +1 -0
  289. package/dist/client/agent-page/use-jobs.d.ts.map +1 -1
  290. package/dist/client/agent-page/use-jobs.js.map +1 -1
  291. package/dist/client/chat/message-components.d.ts +5 -0
  292. package/dist/client/chat/message-components.d.ts.map +1 -1
  293. package/dist/client/chat/message-components.js +17 -1
  294. package/dist/client/chat/message-components.js.map +1 -1
  295. package/dist/client/chat/tool-call-display.d.ts +3 -1
  296. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  297. package/dist/client/chat/tool-call-display.js +17 -7
  298. package/dist/client/chat/tool-call-display.js.map +1 -1
  299. package/dist/collab/awareness.d.ts +2 -2
  300. package/dist/collab/awareness.d.ts.map +1 -1
  301. package/dist/collab/routes.d.ts +1 -1
  302. package/dist/collab/struct-routes.d.ts +1 -1
  303. package/dist/connections/catalog.d.ts +17 -3
  304. package/dist/connections/catalog.d.ts.map +1 -1
  305. package/dist/connections/catalog.js +16 -1
  306. package/dist/connections/catalog.js.map +1 -1
  307. package/dist/connections/reader.d.ts +18 -0
  308. package/dist/connections/reader.d.ts.map +1 -1
  309. package/dist/connections/reader.js +41 -0
  310. package/dist/connections/reader.js.map +1 -1
  311. package/dist/dashboard-storage/index.d.ts +4 -0
  312. package/dist/dashboard-storage/index.d.ts.map +1 -0
  313. package/dist/dashboard-storage/index.js +4 -0
  314. package/dist/dashboard-storage/index.js.map +1 -0
  315. package/dist/dashboard-storage/panel-source.d.ts +68 -0
  316. package/dist/dashboard-storage/panel-source.d.ts.map +1 -0
  317. package/dist/dashboard-storage/panel-source.js +76 -0
  318. package/dist/dashboard-storage/panel-source.js.map +1 -0
  319. package/dist/dashboard-storage/schema.d.ts +562 -0
  320. package/dist/dashboard-storage/schema.d.ts.map +1 -0
  321. package/dist/dashboard-storage/schema.js +32 -0
  322. package/dist/dashboard-storage/schema.js.map +1 -0
  323. package/dist/dashboard-storage/store.d.ts +62 -0
  324. package/dist/dashboard-storage/store.d.ts.map +1 -0
  325. package/dist/dashboard-storage/store.js +227 -0
  326. package/dist/dashboard-storage/store.js.map +1 -0
  327. package/dist/deploy/build.d.ts +7 -0
  328. package/dist/deploy/build.d.ts.map +1 -1
  329. package/dist/deploy/build.js +78 -14
  330. package/dist/deploy/build.js.map +1 -1
  331. package/dist/eject/provider-api-definitions.d.ts +2 -1
  332. package/dist/eject/provider-api-definitions.d.ts.map +1 -1
  333. package/dist/eject/provider-api-definitions.js +1 -0
  334. package/dist/eject/provider-api-definitions.js.map +1 -1
  335. package/dist/eject/workspace-connections.d.ts.map +1 -1
  336. package/dist/eject/workspace-connections.js +1 -0
  337. package/dist/eject/workspace-connections.js.map +1 -1
  338. package/dist/extensions/actions.d.ts.map +1 -1
  339. package/dist/extensions/actions.js +165 -67
  340. package/dist/extensions/actions.js.map +1 -1
  341. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  342. package/dist/jobs/actions/list-recurring-jobs.d.ts +1 -0
  343. package/dist/jobs/actions/list-recurring-jobs.d.ts.map +1 -1
  344. package/dist/jobs/actions/list-recurring-jobs.js +1 -0
  345. package/dist/jobs/actions/list-recurring-jobs.js.map +1 -1
  346. package/dist/jobs/scheduler.d.ts +17 -2
  347. package/dist/jobs/scheduler.d.ts.map +1 -1
  348. package/dist/jobs/scheduler.js +51 -2
  349. package/dist/jobs/scheduler.js.map +1 -1
  350. package/dist/jobs/tools.d.ts.map +1 -1
  351. package/dist/jobs/tools.js +32 -2
  352. package/dist/jobs/tools.js.map +1 -1
  353. package/dist/localization/default-messages.d.ts +1 -0
  354. package/dist/localization/default-messages.d.ts.map +1 -1
  355. package/dist/localization/default-messages.js +1 -0
  356. package/dist/localization/default-messages.js.map +1 -1
  357. package/dist/mcp-client/index.d.ts +2 -0
  358. package/dist/mcp-client/index.d.ts.map +1 -1
  359. package/dist/mcp-client/index.js +5 -0
  360. package/dist/mcp-client/index.js.map +1 -1
  361. package/dist/observability/routes.d.ts +1 -1
  362. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  363. package/dist/provider-api/actions/provider-api.d.ts +8 -6
  364. package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
  365. package/dist/provider-api/actions/provider-api.js +1 -1
  366. package/dist/provider-api/actions/provider-api.js.map +1 -1
  367. package/dist/provider-api/index.d.ts +11 -7
  368. package/dist/provider-api/index.d.ts.map +1 -1
  369. package/dist/provider-api/index.js +143 -5
  370. package/dist/provider-api/index.js.map +1 -1
  371. package/dist/resources/handlers.d.ts +1 -1
  372. package/dist/secrets/register-framework-secrets.d.ts.map +1 -1
  373. package/dist/secrets/register-framework-secrets.js +7 -0
  374. package/dist/secrets/register-framework-secrets.js.map +1 -1
  375. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  376. package/dist/server/agent-chat/context-tools.js +9 -0
  377. package/dist/server/agent-chat/context-tools.js.map +1 -1
  378. package/dist/server/agent-chat/framework-prompts.js +2 -2
  379. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  380. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  381. package/dist/server/agent-chat-plugin.js +18 -2
  382. package/dist/server/agent-chat-plugin.js.map +1 -1
  383. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  384. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  385. package/dist/server/core-routes-plugin.js +1 -0
  386. package/dist/server/core-routes-plugin.js.map +1 -1
  387. package/dist/server/credential-provider.d.ts +4 -3
  388. package/dist/server/credential-provider.d.ts.map +1 -1
  389. package/dist/server/credential-provider.js +9 -3
  390. package/dist/server/credential-provider.js.map +1 -1
  391. package/dist/server/workspace-provider-oauth.d.ts +6 -1
  392. package/dist/server/workspace-provider-oauth.d.ts.map +1 -1
  393. package/dist/server/workspace-provider-oauth.js +141 -4
  394. package/dist/server/workspace-provider-oauth.js.map +1 -1
  395. package/dist/styles/agent-native.css +45 -2
  396. package/dist/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  397. package/dist/templates/chat/AGENTS.md +1 -1
  398. package/dist/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  399. package/dist/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  400. package/dist/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  401. package/dist/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  402. package/dist/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  403. package/dist/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  404. package/dist/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  405. package/dist/triggers/actions.d.ts.map +1 -1
  406. package/dist/triggers/actions.js +10 -2
  407. package/dist/triggers/actions.js.map +1 -1
  408. package/dist/triggers/dispatcher.d.ts.map +1 -1
  409. package/dist/triggers/dispatcher.js +15 -0
  410. package/dist/triggers/dispatcher.js.map +1 -1
  411. package/dist/triggers/types.d.ts +5 -0
  412. package/dist/triggers/types.d.ts.map +1 -1
  413. package/dist/triggers/types.js.map +1 -1
  414. package/dist/vite/action-types-plugin.d.ts.map +1 -1
  415. package/dist/vite/action-types-plugin.js +4 -1
  416. package/dist/vite/action-types-plugin.js.map +1 -1
  417. package/docs/content/agent-native-toolkit.mdx +16 -0
  418. package/docs/content/recurring-jobs.mdx +35 -6
  419. package/package.json +6 -2
  420. package/src/action.ts +22 -1
  421. package/src/agent/production-agent.ts +105 -3
  422. package/src/cli/templates-meta.ts +12 -0
  423. package/src/client/AssistantChat.tsx +53 -26
  424. package/src/client/agent-page/AgentJobsTab.tsx +19 -0
  425. package/src/client/agent-page/use-jobs.ts +1 -0
  426. package/src/client/chat/message-components.tsx +35 -1
  427. package/src/client/chat/tool-call-display.tsx +38 -3
  428. package/src/connections/catalog.ts +20 -1
  429. package/src/connections/reader.ts +65 -0
  430. package/src/dashboard-storage/index.ts +27 -0
  431. package/src/dashboard-storage/panel-source.ts +168 -0
  432. package/src/dashboard-storage/schema.ts +62 -0
  433. package/src/dashboard-storage/store.ts +333 -0
  434. package/src/deploy/build.ts +95 -16
  435. package/src/eject/provider-api-definitions.ts +1 -0
  436. package/src/eject/workspace-connections.ts +1 -0
  437. package/src/extensions/actions.ts +199 -73
  438. package/src/jobs/actions/list-recurring-jobs.ts +2 -0
  439. package/src/jobs/scheduler.ts +71 -4
  440. package/src/jobs/tools.ts +31 -1
  441. package/src/localization/default-messages.ts +1 -0
  442. package/src/mcp-client/index.ts +6 -0
  443. package/src/provider-api/actions/provider-api.ts +1 -1
  444. package/src/provider-api/index.ts +190 -5
  445. package/src/secrets/register-framework-secrets.ts +8 -0
  446. package/src/server/agent-chat/context-tools.ts +9 -0
  447. package/src/server/agent-chat/framework-prompts.ts +2 -2
  448. package/src/server/agent-chat-plugin.ts +22 -2
  449. package/src/server/core-routes-plugin.ts +1 -0
  450. package/src/server/credential-provider.ts +9 -3
  451. package/src/server/workspace-provider-oauth.ts +181 -4
  452. package/src/styles/agent-native.css +45 -2
  453. package/src/templates/chat/.agents/skills/agent-native-docs/SKILL.md +27 -0
  454. package/src/templates/chat/AGENTS.md +1 -1
  455. package/src/templates/default/.agents/skills/agent-native-docs/SKILL.md +27 -0
  456. package/src/templates/default/.agents/skills/app-branding/SKILL.md +159 -0
  457. package/src/templates/default/.agents/skills/app-permissions/SKILL.md +155 -0
  458. package/src/templates/headless/.agents/skills/agent-native-docs/SKILL.md +27 -0
  459. package/src/templates/workspace-core/.agents/skills/agent-native-docs/SKILL.md +27 -0
  460. package/src/templates/workspace-core/.agents/skills/extensions/SKILL.md +31 -18
  461. package/src/templates/workspace-core/.agents/skills/recurring-jobs/SKILL.md +15 -0
  462. package/src/triggers/actions.ts +11 -2
  463. package/src/triggers/dispatcher.ts +20 -1
  464. package/src/triggers/types.ts +5 -0
  465. package/src/vite/action-types-plugin.ts +9 -1
  466. package/corpus/templates/analytics/server/handlers/sql-query.ts +0 -36
  467. package/corpus/templates/analytics/server/routes/api/sql-query.post.ts +0 -1
@@ -1524,25 +1524,32 @@ export class RecorderEngine {
1524
1524
  return this.compressAndReupload(meta);
1525
1525
  }
1526
1526
 
1527
- await this.resetUploadedChunks(null, signal);
1527
+ const uploadMode = await this.resetUploadedChunks(null, signal);
1528
1528
  this.transition("uploading", { progress: 0 });
1529
1529
  const assembled = new Blob(this.localChunks, { type: this.mimeType });
1530
- return this.uploadBlobInSlices(assembled, this.mimeType, meta, signal);
1530
+ return uploadMode === "streaming"
1531
+ ? this.uploadBlobInStreamingChunks(assembled, this.mimeType, meta, signal)
1532
+ : this.uploadBlobInSlices(assembled, this.mimeType, meta, signal);
1531
1533
  }
1532
1534
 
1533
1535
  private async resetUploadedChunks(
1534
1536
  compression: CompressionUploadMeta | null,
1535
1537
  signal?: AbortSignal,
1536
- ): Promise<void> {
1538
+ ): Promise<UploadMode> {
1537
1539
  const resetUrl = `${appBasePath()}/api/uploads/${
1538
1540
  this.opts.recordingId
1539
1541
  }/reset-chunks`;
1542
+ const uploadMimeType = compression?.outputMimeType || this.mimeType;
1540
1543
  let resetRes: Response;
1541
1544
  try {
1542
1545
  resetRes = await fetch(resetUrl, {
1543
1546
  method: "POST",
1544
1547
  headers: { "Content-Type": "application/json" },
1545
- body: JSON.stringify({ compression }),
1548
+ body: JSON.stringify({
1549
+ compression,
1550
+ requestStreaming: this.uploadMode === "streaming",
1551
+ mimeType: uploadMimeType,
1552
+ }),
1546
1553
  signal,
1547
1554
  });
1548
1555
  } catch (err) {
@@ -1566,6 +1573,17 @@ export class RecorderEngine {
1566
1573
  }). ${text || resetRes.statusText}`,
1567
1574
  );
1568
1575
  }
1576
+ const reset = (await resetRes.json().catch(() => null)) as {
1577
+ uploadMode?: unknown;
1578
+ } | null;
1579
+ if (reset?.uploadMode !== "streaming" && reset?.uploadMode !== "buffered") {
1580
+ throw new Error(
1581
+ "Couldn't prepare the recording for re-upload (reset-chunks returned no upload mode).",
1582
+ );
1583
+ }
1584
+ const uploadMode = reset.uploadMode;
1585
+ this.uploadMode = uploadMode;
1586
+ return uploadMode;
1569
1587
  }
1570
1588
 
1571
1589
  // -------------------------------------------------------------------------
@@ -1653,7 +1671,10 @@ export class RecorderEngine {
1653
1671
  outputMimeType: compression.outputMimeType,
1654
1672
  }
1655
1673
  : null;
1656
- await this.resetUploadedChunks(compressionPayload, abort.signal);
1674
+ const uploadMode = await this.resetUploadedChunks(
1675
+ compressionPayload,
1676
+ abort.signal,
1677
+ );
1657
1678
 
1658
1679
  if (compressionError) {
1659
1680
  // Compression itself failed — we still hold the original assembled
@@ -1680,12 +1701,19 @@ export class RecorderEngine {
1680
1701
  }
1681
1702
 
1682
1703
  this.transition("uploading", { progress: 0 });
1683
- return this.uploadBlobInSlices(
1684
- finalBlob,
1685
- compression.outputMimeType,
1686
- meta,
1687
- abort.signal,
1688
- );
1704
+ return uploadMode === "streaming"
1705
+ ? this.uploadBlobInStreamingChunks(
1706
+ finalBlob,
1707
+ compression.outputMimeType,
1708
+ meta,
1709
+ abort.signal,
1710
+ )
1711
+ : this.uploadBlobInSlices(
1712
+ finalBlob,
1713
+ compression.outputMimeType,
1714
+ meta,
1715
+ abort.signal,
1716
+ );
1689
1717
  } finally {
1690
1718
  // Always release the controller reference even on throw — otherwise
1691
1719
  // a subsequent cancel() would abort a freshly-started compression.
@@ -2025,6 +2053,55 @@ export class RecorderEngine {
2025
2053
  return results[finalSlice.index];
2026
2054
  }
2027
2055
 
2056
+ private async uploadBlobInStreamingChunks(
2057
+ blob: Blob,
2058
+ mimeType: string,
2059
+ meta: {
2060
+ durationMs: number;
2061
+ dimensions: { width: number; height: number };
2062
+ hasAudio: boolean;
2063
+ hasCamera: boolean;
2064
+ },
2065
+ signal?: AbortSignal,
2066
+ ): Promise<Record<string, unknown> | undefined> {
2067
+ if (blob.size === 0) {
2068
+ throw new Error("Cannot retry an empty recording upload.");
2069
+ }
2070
+
2071
+ this.chunkIndex = 0;
2072
+ const totalChunks = Math.ceil(blob.size / STREAM_CHUNK_BYTES);
2073
+ let result: Record<string, unknown> | undefined;
2074
+
2075
+ for (let index = 0; index < totalChunks; index++) {
2076
+ const start = index * STREAM_CHUNK_BYTES;
2077
+ const end = Math.min(start + STREAM_CHUNK_BYTES, blob.size);
2078
+ const isFinal = index === totalChunks - 1;
2079
+ const chunk = blob.slice(start, end, mimeType);
2080
+ result = await this.uploadChunk(chunk, this.chunkIndex++, {
2081
+ isFinal,
2082
+ total: totalChunks,
2083
+ mimeType,
2084
+ ...(isFinal
2085
+ ? {
2086
+ durationMs: meta.durationMs,
2087
+ width: meta.dimensions.width,
2088
+ height: meta.dimensions.height,
2089
+ hasAudio: meta.hasAudio,
2090
+ hasCamera: meta.hasCamera,
2091
+ }
2092
+ : {}),
2093
+ signal,
2094
+ });
2095
+ this.opts.onChunk?.({
2096
+ index,
2097
+ bytes: chunk.size,
2098
+ total: totalChunks,
2099
+ });
2100
+ }
2101
+
2102
+ return result;
2103
+ }
2104
+
2028
2105
  private async uploadChunk(
2029
2106
  blob: Blob,
2030
2107
  index: number,
@@ -833,6 +833,10 @@ All notable user-facing changes to Clips are documented here. Open it any time f
833
833
  loadFailedBody:
834
834
  "Something went wrong while loading this list. Your recordings are safe — try again.",
835
835
  retry: "Retry",
836
+ paginationRange: "{{start}}–{{end}} of {{total}}",
837
+ paginationPrevious: "Previous",
838
+ paginationNext: "Next",
839
+ paginationPage: "Page {{page}} of {{totalPages}}",
836
840
  },
837
841
  notificationsRoute: {
838
842
  pageTitle: "Notifications · Clips",
@@ -1370,6 +1374,8 @@ All notable user-facing changes to Clips are documented here. Open it any time f
1370
1374
  clipsFinalRaw: {
1371
1375
  splitAtPlayhead: "Split at playhead (S)",
1372
1376
  selectedCount: "{{count}} selected",
1377
+ selectAll: "Select all",
1378
+ deselectAll: "Deselect all",
1373
1379
  move: "Move",
1374
1380
  moveSelected: "Move {{count}} selected",
1375
1381
  current: "Current",
@@ -46,6 +46,7 @@ export default function TrashRoute() {
46
46
  const t = useT();
47
47
  const [sort, setSort] = useState<SortKey>("recent");
48
48
  const [selected, setSelected] = useState<Set<string>>(new Set());
49
+ const [lastSelectedId, setLastSelectedId] = useState<string | null>(null);
49
50
  const [confirmPurge, setConfirmPurge] = useState(false);
50
51
  const [singlePurgeId, setSinglePurgeId] = useState<string | null>(null);
51
52
  const [isBulkPending, setIsBulkPending] = useState(false);
@@ -60,13 +61,26 @@ export default function TrashRoute() {
60
61
  "delete-recording-permanent",
61
62
  );
62
63
 
63
- const toggleSelect = (id: string) => {
64
+ const toggleSelect = (id: string, shiftKey = false) => {
64
65
  setSelected((prev) => {
66
+ if (shiftKey && lastSelectedId && lastSelectedId !== id) {
67
+ const ids = recordings.map((r) => r.id);
68
+ const fromIndex = ids.indexOf(lastSelectedId);
69
+ const toIndex = ids.indexOf(id);
70
+ if (fromIndex !== -1 && toIndex !== -1) {
71
+ const [start, end] =
72
+ fromIndex < toIndex ? [fromIndex, toIndex] : [toIndex, fromIndex];
73
+ const next = new Set(prev);
74
+ for (let i = start; i <= end; i++) next.add(ids[i]);
75
+ return next;
76
+ }
77
+ }
65
78
  const next = new Set(prev);
66
79
  if (next.has(id)) next.delete(id);
67
80
  else next.add(id);
68
81
  return next;
69
82
  });
83
+ setLastSelectedId(id);
70
84
  };
71
85
 
72
86
  const restoreAll = async (ids: string[]) => {
@@ -170,6 +184,7 @@ export default function TrashRoute() {
170
184
  ? new Set()
171
185
  : new Set(recordings.map((r) => r.id)),
172
186
  );
187
+ setLastSelectedId(null);
173
188
  };
174
189
 
175
190
  return (
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: added
3
+ date: 2026-07-21
4
+ ---
5
+
6
+ Clips can now prepare an access-checked recording link for bounded CRM call evidence without exposing media or transcripts.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-07-21
4
+ ---
5
+
6
+ Recording retries and restarts keep their upload session so they can finish saving.
@@ -1,4 +1,6 @@
1
1
  import {
2
+ restartUploadModeFromResponse,
3
+ restartUploadResetBody,
2
4
  shouldReconcilePersistedRecording,
3
5
  type OffscreenRecordingState,
4
6
  } from "./native-recording-state";
@@ -166,6 +168,7 @@ type NativeRecording = {
166
168
  // fallback so it is never lost; these describe that saved file.
167
169
  savedToDisk?: boolean;
168
170
  savedFilename?: string;
171
+ mimeType?: string;
169
172
  };
170
173
 
171
174
  type OffscreenStatusMessage = {
@@ -179,6 +182,7 @@ type OffscreenStatusMessage = {
179
182
  savedToDisk?: boolean;
180
183
  savedFilename?: string;
181
184
  recordingStep?: string;
185
+ mimeType?: string;
182
186
  };
183
187
 
184
188
  type ExtensionErrorMessage = {
@@ -1512,8 +1516,8 @@ async function handleOverlayRestart() {
1512
1516
  // so we must not leave the overlay stuck mid-recording/paused with no
1513
1517
  // recorder behind it — tear the overlay back down and release those streams,
1514
1518
  // matching the re-arm failure handling just below.
1515
- const chunksReset = await resetRecordingChunks(recording);
1516
- if (!chunksReset) {
1519
+ const uploadMode = await resetRecordingChunks(recording);
1520
+ if (!uploadMode) {
1517
1521
  recording.status = "error";
1518
1522
  recording.error =
1519
1523
  "Could not clear the previous take before restarting. Stop and start a new recording.";
@@ -1530,6 +1534,7 @@ async function handleOverlayRestart() {
1530
1534
  error: recording.error,
1531
1535
  };
1532
1536
  }
1537
+ recording.uploadMode = uploadMode;
1533
1538
  overlayPhase = "countdown";
1534
1539
  overlayBaseElapsedMs = 0;
1535
1540
  overlayBaseEpochMs = nowMs();
@@ -1579,18 +1584,25 @@ async function handleOverlayRestart() {
1579
1584
 
1580
1585
  async function resetRecordingChunks(
1581
1586
  recording: NativeRecording,
1582
- ): Promise<boolean> {
1587
+ ): Promise<UploadMode | null> {
1583
1588
  const url = `${recording.clipsBaseUrl}/api/uploads/${encodeURIComponent(
1584
1589
  recording.recordingId,
1585
1590
  )}/reset-chunks`;
1586
- const headers = await authHeaders(settingsFromRecording(recording));
1591
+ const headers = {
1592
+ ...(await authHeaders(settingsFromRecording(recording))),
1593
+ "Content-Type": "application/json",
1594
+ };
1587
1595
  const response = await fetch(url, {
1588
1596
  method: "POST",
1589
1597
  headers,
1590
1598
  credentials: "include",
1591
1599
  cache: "no-store",
1600
+ body: JSON.stringify(
1601
+ restartUploadResetBody(recording.mimeType ?? "video/webm"),
1602
+ ),
1592
1603
  }).catch(() => undefined);
1593
- return Boolean(response?.ok);
1604
+ if (!response?.ok) return null;
1605
+ return restartUploadModeFromResponse(await response.json().catch(() => null));
1594
1606
  }
1595
1607
 
1596
1608
  // Finalize a successful save: open the clip and tear down the "Saving…" overlay.
@@ -2399,6 +2411,9 @@ async function dispatchRuntimeMessage(message: unknown): Promise<unknown> {
2399
2411
  activeNativeRecording,
2400
2412
  );
2401
2413
  }
2414
+ if (typeof status.mimeType === "string") {
2415
+ activeNativeRecording.mimeType = status.mimeType;
2416
+ }
2402
2417
  if (status.status === "error") {
2403
2418
  activeNativeRecording.savedToDisk = status.savedToDisk === true;
2404
2419
  activeNativeRecording.savedFilename =
@@ -6,6 +6,8 @@ export type NativeRecordingStateStatus =
6
6
  | "complete"
7
7
  | "error";
8
8
 
9
+ export type RestartUploadMode = "streaming" | "buffered";
10
+
9
11
  export type OffscreenRecordingState = {
10
12
  activeSessionId?: string;
11
13
  preparedSessionId?: string;
@@ -30,3 +32,20 @@ export function shouldReconcilePersistedRecording(
30
32
  if (status === "error" || status === "complete") return false;
31
33
  return !hasLiveOffscreenSession(sessionId, state);
32
34
  }
35
+
36
+ export function restartUploadResetBody(mimeType: string): {
37
+ requestStreaming: true;
38
+ mimeType: string;
39
+ } {
40
+ return { requestStreaming: true, mimeType };
41
+ }
42
+
43
+ export function restartUploadModeFromResponse(
44
+ value: unknown,
45
+ ): RestartUploadMode | null {
46
+ if (!value || typeof value !== "object") return null;
47
+ const uploadMode = (value as { uploadMode?: unknown }).uploadMode;
48
+ return uploadMode === "streaming" || uploadMode === "buffered"
49
+ ? uploadMode
50
+ : null;
51
+ }
@@ -56,6 +56,8 @@ const STORAGE_SETUP_REQUIRED_MESSAGE =
56
56
  const STORAGE_SETUP_FAILURE_RE =
57
57
  /video storage is not connected|no video storage configured|file upload provider|storage provider|connect builder|s3-compatible/i;
58
58
  const CHUNK_UPLOAD_MAX_ATTEMPTS = 3;
59
+ const CHUNK_UPLOAD_TIMEOUT_MS = 60_000;
60
+ const FINAL_CHUNK_UPLOAD_TIMEOUT_MS = 180_000;
59
61
  const RETRYABLE_CHUNK_UPLOAD_STATUSES = new Set([
60
62
  408, 425, 429, 500, 502, 503, 504,
61
63
  ]);
@@ -860,6 +862,11 @@ async function uploadChunk(
860
862
  headers,
861
863
  credentials: "include",
862
864
  body,
865
+ signal: AbortSignal.timeout(
866
+ extra.isFinal
867
+ ? FINAL_CHUNK_UPLOAD_TIMEOUT_MS
868
+ : CHUNK_UPLOAD_TIMEOUT_MS,
869
+ ),
863
870
  });
864
871
  } catch (err) {
865
872
  if (attempt >= CHUNK_UPLOAD_MAX_ATTEMPTS) throw err;
@@ -1387,6 +1394,7 @@ function startRecorderNow(recording: ActiveRecording): void {
1387
1394
  height: recording.dimensions.height,
1388
1395
  hasAudio: recording.hasAudio,
1389
1396
  hasCamera: recording.hasCamera,
1397
+ mimeType: recording.mimeType,
1390
1398
  });
1391
1399
  } catch (err) {
1392
1400
  captureExtensionError(err, {
@@ -572,6 +572,21 @@ function openPrivacySettings(pane: MacosPrivacyPane): void {
572
572
  }
573
573
  }
574
574
 
575
+ // Same explicit-drag pattern the toolbar/bubble overlays use —
576
+ // `data-tauri-drag-region` has been unreliable, so we call `startDragging()`
577
+ // directly on mousedown. Clicks on buttons/inputs still reach their handlers
578
+ // since we only start a drag when the mousedown target isn't inside one.
579
+ function handlePopoverHeaderMouseDown(event: React.MouseEvent) {
580
+ if (event.button !== 0) return;
581
+ const target = event.target as HTMLElement;
582
+ if (target.closest("button, a, input, select, textarea")) return;
583
+ getCurrentWindow()
584
+ .startDragging()
585
+ .catch((err) => {
586
+ console.warn("[clips-popover] startDragging failed:", err);
587
+ });
588
+ }
589
+
575
590
  function nativeVoiceProvider(): VoiceProvider {
576
591
  return isMacPlatform() ? "macos-native" : "browser";
577
592
  }
@@ -4248,7 +4263,10 @@ function Header({
4248
4263
  // close button lives top-right as an absolute-positioned sibling, so the
4249
4264
  // tabs aren't offset by the close button's width.
4250
4265
  return (
4251
- <div className="header header-centered">
4266
+ <div
4267
+ className="header header-centered"
4268
+ onMouseDown={handlePopoverHeaderMouseDown}
4269
+ >
4252
4270
  <FeedbackButton submitterEmail={submitterEmail} />
4253
4271
  <div
4254
4272
  className="mode-toggle"
@@ -4444,7 +4462,10 @@ function PopoverSubViewHeader({
4444
4462
  action?: ReactNode;
4445
4463
  }) {
4446
4464
  return (
4447
- <div className="setup-header popover-view-header">
4465
+ <div
4466
+ className="setup-header popover-view-header"
4467
+ onMouseDown={handlePopoverHeaderMouseDown}
4468
+ >
4448
4469
  <button
4449
4470
  type="button"
4450
4471
  className="setup-back"
@@ -6376,7 +6397,7 @@ function Setup({
6376
6397
 
6377
6398
  return (
6378
6399
  <div className="setup">
6379
- <div className="setup-header">
6400
+ <div className="setup-header" onMouseDown={handlePopoverHeaderMouseDown}>
6380
6401
  {onCancel ? (
6381
6402
  <button
6382
6403
  type="button"
@@ -344,6 +344,14 @@ export function RecordingPill() {
344
344
  void toggleExpanded();
345
345
  };
346
346
 
347
+ const handlePillMouseUp = (e: React.MouseEvent) => {
348
+ const start = dragStartScreenPointRef.current;
349
+ if (isDirectPillClick(start, { x: e.screenX, y: e.screenY })) return;
350
+ void invoke("recording_pill_save_position").catch((err) => {
351
+ console.warn("[clips-pill] save position failed", err);
352
+ });
353
+ };
354
+
347
355
  const mm = String(Math.floor(elapsed / 60)).padStart(2, "0");
348
356
  const ss = String(elapsed % 60).padStart(2, "0");
349
357
  const stopLabel =
@@ -356,6 +364,7 @@ export function RecordingPill() {
356
364
  hovered ? " pill-hovered" : ""
357
365
  }`}
358
366
  onMouseDown={handlePillMouseDown}
367
+ onMouseUp={handlePillMouseUp}
359
368
  >
360
369
  <div
361
370
  className={`pill-header${
@@ -130,20 +130,32 @@ fn pill_detached_position_path(app: &AppHandle) -> Option<PathBuf> {
130
130
  Some(dir.join("pill-position-detached.json"))
131
131
  }
132
132
 
133
- fn load_meeting_position(app: &AppHandle) -> Option<(i32, i32)> {
133
+ #[derive(Deserialize)]
134
+ struct MeetingPillPosition {
135
+ x: i32,
136
+ y: i32,
137
+ #[serde(default)]
138
+ anchor: Option<String>,
139
+ #[serde(default)]
140
+ width: Option<u32>,
141
+ }
142
+
143
+ fn load_meeting_position(app: &AppHandle) -> Option<MeetingPillPosition> {
134
144
  let path = pill_meeting_position_path(app)?;
135
145
  let bytes = std::fs::read(&path).ok()?;
136
- let value: serde_json::Value = serde_json::from_slice(&bytes).ok()?;
137
- let x = value.get("x")?.as_i64()? as i32;
138
- let y = value.get("y")?.as_i64()? as i32;
139
- Some((x, y))
146
+ serde_json::from_slice(&bytes).ok()
140
147
  }
141
148
 
142
- fn save_meeting_position_to_disk(app: &AppHandle, x: i32, y: i32) {
149
+ fn save_meeting_position_to_disk(app: &AppHandle, x: i32, y: i32, width: u32) {
143
150
  let Some(path) = pill_meeting_position_path(app) else {
144
151
  return;
145
152
  };
146
- let body = match serde_json::to_vec(&serde_json::json!({ "x": x, "y": y })) {
153
+ let body = match serde_json::to_vec(&serde_json::json!({
154
+ "x": x + width as i32,
155
+ "y": y,
156
+ "anchor": "right",
157
+ "width": width,
158
+ })) {
147
159
  Ok(b) => b,
148
160
  Err(_) => return,
149
161
  };
@@ -313,7 +325,28 @@ fn anchored_rect(
313
325
  let (_, h_exp) = pill_size_physical(app, true);
314
326
  let max_y_exp = (my + mh as i32 - h_exp as i32).max(my);
315
327
  let (x, y) = match load_meeting_position(app) {
316
- Some((sx, sy)) => (sx.clamp(mx, max_x), sy.clamp(my, max_y_exp)),
328
+ Some(position) if position.anchor.as_deref() == Some("right") => {
329
+ let saved_width = position.width.unwrap_or(w);
330
+ (
331
+ (position.x - saved_width as i32).clamp(mx, max_x),
332
+ position.y.clamp(my, max_y_exp),
333
+ )
334
+ }
335
+ Some(position) => {
336
+ let (expanded_w, _) = pill_size_physical(app, true);
337
+ let right_margin = (PILL_RIGHT_MARGIN_LOGICAL as f64 * scale_factor(app)) as i32;
338
+ let legacy_right_edge = position.x + expanded_w as i32;
339
+ let monitor_right = mx + mw as i32;
340
+ if (legacy_right_edge - (monitor_right - right_margin)).abs() <= 4 {
341
+ save_meeting_position_to_disk(app, position.x, position.y, expanded_w);
342
+ (
343
+ (legacy_right_edge - w as i32).clamp(mx, max_x),
344
+ position.y.clamp(my, max_y_exp),
345
+ )
346
+ } else {
347
+ (position.x.clamp(mx, max_x), position.y.clamp(my, max_y_exp))
348
+ }
349
+ }
317
350
  None => default_center_right(app, w, h),
318
351
  };
319
352
  return (w, h, x, y);
@@ -492,35 +525,28 @@ pub async fn recording_pill_expand(app: AppHandle, expanded: bool) -> Result<(),
492
525
  pub async fn recording_pill_hide(app: AppHandle) -> Result<(), String> {
493
526
  stop_pill_hover_tracking();
494
527
  if let Some(w) = app.get_webview_window(PILL_LABEL) {
495
- // Snapshot current position before close so the next show re-opens
496
- // at the user's chosen spot.
497
- if let Ok(pos) = w.outer_position() {
498
- if PILL_DETACHED.load(Ordering::Relaxed) {
499
- save_detached_position_to_disk(&app, pos.x, pos.y);
500
- } else if PILL_RIGHT_SIDE.load(Ordering::Relaxed) {
501
- save_meeting_position_to_disk(&app, pos.x, pos.y);
502
- } else {
503
- save_pill_position_to_disk(&app, pos.x, pos.y);
504
- }
505
- }
506
528
  let _ = w.close();
507
529
  }
508
530
  Ok(())
509
531
  }
510
532
 
511
- /// Persist the pill's current position. Called by the React side after the
512
- /// user drag-moves it (mouseup) so the next `show` reopens at the chosen
513
- /// spot.
514
533
  #[tauri::command]
515
- pub async fn recording_pill_save_position(app: AppHandle, x: i32, y: i32) -> Result<(), String> {
516
- // Persist to the right slot — detached drags shouldn't overwrite the
517
- // user's preferred bottom-center position and vice versa.
534
+ pub async fn recording_pill_save_position(app: AppHandle) -> Result<(), String> {
535
+ let Some(window) = app.get_webview_window(PILL_LABEL) else {
536
+ return Ok(());
537
+ };
538
+ let Ok(position) = window.outer_position() else {
539
+ return Ok(());
540
+ };
541
+
518
542
  if PILL_DETACHED.load(Ordering::Relaxed) {
519
- save_detached_position_to_disk(&app, x, y);
543
+ save_detached_position_to_disk(&app, position.x, position.y);
520
544
  } else if PILL_RIGHT_SIDE.load(Ordering::Relaxed) {
521
- save_meeting_position_to_disk(&app, x, y);
545
+ if let Ok(size) = window.outer_size() {
546
+ save_meeting_position_to_disk(&app, position.x, position.y, size.width);
547
+ }
522
548
  } else {
523
- save_pill_position_to_disk(&app, x, y);
549
+ save_pill_position_to_disk(&app, position.x, position.y);
524
550
  }
525
551
  Ok(())
526
552
  }
@@ -18,6 +18,7 @@ const INITIAL_TOOL_NAMES = [
18
18
  "list-recordings",
19
19
  "search-recordings",
20
20
  "get-recording-player-data",
21
+ "prepare-crm-call-evidence",
21
22
  "request-transcript",
22
23
  "create-recording",
23
24
  "import-loom-recording",