@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
@@ -155,7 +155,21 @@ async function responseHasReadableMediaBytes(
155
155
  }
156
156
  }
157
157
 
158
- async function verifyServedMediaUrl(videoUrl: string): Promise<void> {
158
+ function servedMediaSizeBytes(response: Response): number | null {
159
+ const contentRange = response.headers.get("content-range") ?? "";
160
+ const total = Number(contentRange.match(/\/(\d+)$/)?.[1]);
161
+ if (Number.isFinite(total) && total > 0) return total;
162
+ if (response.status === 200) {
163
+ const length = Number(response.headers.get("content-length"));
164
+ if (Number.isFinite(length) && length > 0) return length;
165
+ }
166
+ return null;
167
+ }
168
+
169
+ async function verifyServedMediaUrl(
170
+ videoUrl: string,
171
+ expectedBytes: number,
172
+ ): Promise<void> {
159
173
  if (!shouldVerifyServedMediaUrl(videoUrl)) return;
160
174
 
161
175
  let lastFailure = "media URL did not serve readable bytes";
@@ -176,11 +190,21 @@ async function verifyServedMediaUrl(videoUrl: string): Promise<void> {
176
190
  signal: controller.signal,
177
191
  });
178
192
  const statusOk = response.status === 200 || response.status === 206;
179
- if (statusOk && (await responseHasReadableMediaBytes(response))) {
180
- return;
193
+ if (statusOk) {
194
+ const servedBytes = servedMediaSizeBytes(response);
195
+ if (servedBytes === null) {
196
+ lastFailure = "Stored media byte count could not be verified";
197
+ } else if (servedBytes !== expectedBytes) {
198
+ lastFailure = `Stored media byte count mismatch (${servedBytes} of ${expectedBytes} bytes)`;
199
+ } else if (await responseHasReadableMediaBytes(response)) {
200
+ return;
201
+ } else {
202
+ lastFailure = "media URL did not serve readable bytes";
203
+ }
204
+ } else {
205
+ lastFailure = `media URL returned HTTP ${response.status}`;
206
+ if (response.status < 500) break;
181
207
  }
182
- lastFailure = `media URL returned HTTP ${response.status}`;
183
- if (response.status < 500) break;
184
208
  } catch (err) {
185
209
  lastFailure = err instanceof Error ? err.message : String(err);
186
210
  } finally {
@@ -258,6 +282,7 @@ async function markRecordingReady(params: {
258
282
  ownerEmail: string;
259
283
  videoUrl: string;
260
284
  videoSizeBytes: number;
285
+ sourceSizeBytes: number;
261
286
  videoFormat: "webm" | "mp4";
262
287
  finalDurationMs: number;
263
288
  finalWidth: number;
@@ -275,6 +300,7 @@ async function markRecordingReady(params: {
275
300
  ownerEmail,
276
301
  videoUrl,
277
302
  videoSizeBytes,
303
+ sourceSizeBytes,
278
304
  videoFormat,
279
305
  finalDurationMs,
280
306
  finalWidth,
@@ -349,6 +375,7 @@ async function markRecordingReady(params: {
349
375
  status: "failed" as const,
350
376
  videoUrl,
351
377
  videoSizeBytes,
378
+ sourceSizeBytes,
352
379
  durationMs: finalDurationMs,
353
380
  };
354
381
  }
@@ -372,6 +399,9 @@ async function markRecordingReady(params: {
372
399
  status: "ready",
373
400
  progress: 100,
374
401
  videoUrl,
402
+ videoSizeBytes,
403
+ sourceSizeBytes,
404
+ durationMs: finalDurationMs,
375
405
  finishedAt: now,
376
406
  });
377
407
  await writeAppState("refresh-signal", { ts: Date.now() });
@@ -436,6 +466,7 @@ async function markRecordingReady(params: {
436
466
  status: "ready" as const,
437
467
  videoUrl,
438
468
  videoSizeBytes,
469
+ sourceSizeBytes,
439
470
  durationMs: finalDurationMs,
440
471
  };
441
472
  }
@@ -521,6 +552,7 @@ export default defineAction({
521
552
  status: "ready" as const,
522
553
  videoUrl: existing.videoUrl,
523
554
  videoSizeBytes: existing.videoSizeBytes ?? 0,
555
+ sourceSizeBytes: existing.videoSizeBytes ?? 0,
524
556
  durationMs: existing.durationMs ?? 0,
525
557
  };
526
558
  }
@@ -641,7 +673,10 @@ export default defineAction({
641
673
  );
642
674
  debugLog("[finalize] resumable upload completed", { id, videoUrl });
643
675
  try {
644
- await verifyServedMediaUrl(videoUrl);
676
+ await verifyServedMediaUrl(
677
+ videoUrl,
678
+ resumableSession.bytesUploaded,
679
+ );
645
680
  } catch (err) {
646
681
  const failureReason =
647
682
  err instanceof Error ? err.message : String(err);
@@ -656,6 +691,7 @@ export default defineAction({
656
691
  ...readyParams,
657
692
  videoUrl,
658
693
  videoSizeBytes: resumableSession.bytesUploaded,
694
+ sourceSizeBytes: resumableSession.bytesUploaded,
659
695
  // Streaming path forwards raw MediaRecorder bytes straight to the
660
696
  // provider — no faststart/Cues rewrite happened. Repair in the
661
697
  // background.
@@ -1162,7 +1198,7 @@ export default defineAction({
1162
1198
  bytes: uploadData.byteLength,
1163
1199
  });
1164
1200
  try {
1165
- await verifyServedMediaUrl(upload.url);
1201
+ await verifyServedMediaUrl(upload.url, uploadData.byteLength);
1166
1202
  } catch (err) {
1167
1203
  if (!requiresConfiguredVideoStorage()) {
1168
1204
  // Local dev can keep scratch chunks so the user can retry after fixing
@@ -1185,6 +1221,7 @@ export default defineAction({
1185
1221
  finalHasAudio: correctedHasAudio,
1186
1222
  videoUrl: upload.url,
1187
1223
  videoSizeBytes: uploadData.byteLength,
1224
+ sourceSizeBytes: assembled.byteLength,
1188
1225
  seekableApplied,
1189
1226
  });
1190
1227
  if (result.status === "ready") {
@@ -11,6 +11,7 @@ import { getDb, schema } from "../server/db/index.js";
11
11
  import { queueBuilderMediaCompression } from "../server/lib/builder-media-compression.js";
12
12
  import {
13
13
  getCurrentOwnerEmail,
14
+ getOrganizationDefaultVisibility,
14
15
  nanoid,
15
16
  ownerEmailMatches,
16
17
  parseSpaceIds,
@@ -178,6 +179,8 @@ export default defineAction({
178
179
  const { organizationId } = await requireOrganizationAccess(
179
180
  existingRecording?.organizationId ?? args.organizationId,
180
181
  );
182
+ const defaultVisibility =
183
+ await getOrganizationDefaultVisibility(organizationId);
181
184
 
182
185
  const now = new Date().toISOString();
183
186
  const id = existingRecording?.id ?? nanoid();
@@ -199,7 +202,7 @@ export default defineAction({
199
202
  const height = boundedDimension(oembed.height ?? oembed.thumbnail_height);
200
203
  const folderId = args.folderId ?? existingRecording?.folderId ?? null;
201
204
  const visibility =
202
- args.visibility ?? existingRecording?.visibility ?? "public";
205
+ args.visibility ?? existingRecording?.visibility ?? defaultVisibility;
203
206
  const titleSource = args.title
204
207
  ? "manual"
205
208
  : (existingRecording?.titleSource ?? "upload");
@@ -62,9 +62,9 @@ export const createRecordingSchema = z.object({
62
62
  .describe("Height of the recording in pixels (may be 0 until finalized)"),
63
63
  visibility: z
64
64
  .enum(["private", "org", "public"])
65
- .default("public")
65
+ .optional()
66
66
  .describe(
67
- "Initial share visibility for the recording (defaults to public)",
67
+ "Initial share visibility for the recording. When omitted, uses the organization default and falls back to public.",
68
68
  ),
69
69
  mimeType: z
70
70
  .string()
@@ -32,7 +32,10 @@ import {
32
32
  import { z } from "zod";
33
33
 
34
34
  import { getDb, schema } from "../server/db/index.js";
35
- import { isSoloCalendarEvent } from "../server/lib/calendar-event-classification.js";
35
+ import {
36
+ isDeclinedCalendarEvent,
37
+ isSoloCalendarEvent,
38
+ } from "../server/lib/calendar-event-classification.js";
36
39
  import {
37
40
  calendarEventToMeetingView,
38
41
  eventEndIso,
@@ -89,6 +92,11 @@ export default defineAction({
89
92
  .describe(
90
93
  "Exclude calendar events with no active attendee besides the current user. Used by desktop meeting reminders.",
91
94
  ),
95
+ excludeDeclinedEvents: booleanParam
96
+ .default(false)
97
+ .describe(
98
+ "Exclude calendar events where the current user has declined. Used by desktop meeting reminders.",
99
+ ),
92
100
  }),
93
101
  http: { method: "GET" },
94
102
  run: async (args) => {
@@ -190,10 +198,10 @@ export default defineAction({
190
198
  // event was emitted here — not merely because some other account returned
191
199
  // data or errored.
192
200
  const emittedLiveEventKeys = new Set<string>();
193
- // Calendar events excluded from desktop reminders because they have no
194
- // active attendee besides the current user. Keep the correlated
195
- // persisted meeting ids here too, so materialized solo events cannot
196
- // re-enter the reminder list through the fallback persisted-row merge.
201
+ // Calendar events excluded from desktop reminders because they are solo or
202
+ // declined by the current user. Keep the correlated persisted meeting ids
203
+ // here too, so materialized events cannot re-enter the reminder list
204
+ // through the fallback persisted-row merge.
197
205
  const excludedLiveEventKeys = new Set<string>();
198
206
  // Map a persisted meeting's `calendarEventId` (calendar_events.id) to the
199
207
  // Google event externalId so we can match it against the emitted set.
@@ -277,6 +285,16 @@ export default defineAction({
277
285
  if (!event.id || event.status === "cancelled") continue;
278
286
  if (!isTimedCalendarEvent(event)) continue;
279
287
  const cached = cachedByExternalId.get(event.id);
288
+ if (
289
+ args.excludeDeclinedEvents &&
290
+ isDeclinedCalendarEvent({ account, event, currentUserEmail })
291
+ ) {
292
+ excludedLiveEventKeys.add(event.id);
293
+ if (cached?.meetingId) {
294
+ excludedLiveEventKeys.add(cached.meetingId);
295
+ }
296
+ continue;
297
+ }
280
298
  if (
281
299
  args.excludePersonalSoloEvents &&
282
300
  isSoloCalendarEvent({ account, event, currentUserEmail })
@@ -143,7 +143,7 @@ export default defineAction({
143
143
  name: org.name,
144
144
  brandColor: settings?.brandColor ?? "#18181B",
145
145
  brandLogoUrl: settings?.brandLogoUrl ?? null,
146
- defaultVisibility: settings?.defaultVisibility ?? "private",
146
+ defaultVisibility: settings?.defaultVisibility ?? "public",
147
147
  createdAt: Number(org.createdAt),
148
148
  },
149
149
  members,
@@ -56,9 +56,18 @@ export default defineAction({
56
56
  `by analyzing the transcript segments (gaps between segment.endMs and the next segment.startMs). ` +
57
57
  `For each gap > ${args.thresholdMs}ms, add a trim range covering the silence minus a 200ms ` +
58
58
  `buffer on each side so speech isn't clipped. Then call ` +
59
- `\`trim-recording --recordingId=${args.recordingId} --startMs=<start> --endMs=<end>\` once for each silence.`,
59
+ `\`trim-recording --recordingId=${args.recordingId} --startMs=<start> --endMs=<end>\` once for each silence. ` +
60
+ `First call \`update-ai-request-status --recordingId=${args.recordingId} --kind=remove-silences --status=working\`. ` +
61
+ `After all trim calls finish, call the same action with --status=completed and a short result message. ` +
62
+ `If the work cannot finish, call it with --status=failed and explain why.`,
60
63
  };
61
64
 
65
+ await writeAppState(`clips-ai-request-status-${args.recordingId}`, {
66
+ kind: "remove-silences",
67
+ status: "queued",
68
+ message: null,
69
+ updatedAt: new Date().toISOString(),
70
+ });
62
71
  await writeAppState(`clips-ai-request-${args.recordingId}`, request as any);
63
72
  await writeAppState("refresh-signal", { ts: Date.now() });
64
73
 
@@ -454,6 +454,18 @@ function fullTextSegmentJson(
454
454
  return JSON.stringify(buildCaptionSegmentsFromText(text, durationMs));
455
455
  }
456
456
 
457
+ export function isSafeTranscriptCleanupReplacement(
458
+ sourceText: string,
459
+ cleanedText: string,
460
+ ): boolean {
461
+ const sourceLength = sourceText.trim().length;
462
+ const cleanedLength = cleanedText.trim().length;
463
+ if (!sourceLength || !cleanedLength) return false;
464
+ if (sourceLength < 200) return true;
465
+ const retention = cleanedLength / sourceLength;
466
+ return retention >= 0.6 && retention <= 1.25;
467
+ }
468
+
457
469
  async function failEmptyProviderTranscript({
458
470
  db,
459
471
  recordingId,
@@ -719,19 +731,49 @@ async function cleanupNativeTranscript({
719
731
  });
720
732
  return { cleaned: false, provider: result.provider };
721
733
  }
734
+ if (!isSafeTranscriptCleanupReplacement(sourceText, cleanedText)) {
735
+ await writeTranscriptCleanupState(recordingId, {
736
+ status: "failed",
737
+ provider: result.provider,
738
+ failureReason:
739
+ "Cleanup output was incomplete; the original transcript was kept.",
740
+ sourceChars: sourceText.length,
741
+ cleanedChars: cleanedText.length,
742
+ });
743
+ return { cleaned: false, provider: result.provider };
744
+ }
722
745
 
723
746
  const now = new Date().toISOString();
724
747
  const language = await resolveStoredLanguage(db, recordingId);
725
- await upsertTranscriptRow(db, {
726
- recordingId,
727
- ownerEmail,
728
- status: "ready",
729
- failureReason: null,
730
- language,
731
- segmentsJson: fullTextSegmentJson(cleanedText, durationMs),
732
- fullText: cleanedText,
733
- now,
734
- });
748
+ const updated = await db
749
+ .update(schema.recordingTranscripts)
750
+ .set({
751
+ ownerEmail,
752
+ status: "ready",
753
+ failureReason: null,
754
+ language,
755
+ segmentsJson: fullTextSegmentJson(cleanedText, durationMs),
756
+ fullText: cleanedText,
757
+ retryCount: 0,
758
+ updatedAt: now,
759
+ })
760
+ .where(
761
+ and(
762
+ eq(schema.recordingTranscripts.recordingId, recordingId),
763
+ eq(schema.recordingTranscripts.status, "ready"),
764
+ eq(schema.recordingTranscripts.fullText, sourceText),
765
+ ),
766
+ )
767
+ .returning({ recordingId: schema.recordingTranscripts.recordingId });
768
+ if (!updated.length) {
769
+ await writeTranscriptCleanupState(recordingId, {
770
+ status: "failed",
771
+ provider: result.provider,
772
+ failureReason:
773
+ "Transcript changed during cleanup; the newer transcript was kept.",
774
+ });
775
+ return { cleaned: false, provider: result.provider };
776
+ }
735
777
  await writeTranscriptCleanupState(recordingId, {
736
778
  status: "ready",
737
779
  provider: result.provider,
@@ -1060,7 +1102,7 @@ const requestTranscriptAction = defineAction({
1060
1102
 
1061
1103
  const db = getDb();
1062
1104
 
1063
- if (context?.caller === "tool") {
1105
+ if (context?.caller === "tool" || context?.caller === "frontend") {
1064
1106
  const [existingTranscript] = await db
1065
1107
  .select({
1066
1108
  status: schema.recordingTranscripts.status,
@@ -0,0 +1,7 @@
1
+ function escapeLike(value: string): string {
2
+ return value.replace(/([\\%_])/g, "\\$1");
3
+ }
4
+
5
+ export function buildCaseInsensitiveSearchPattern(query: string): string {
6
+ return `%${escapeLike(query.toLowerCase())}%`;
7
+ }
@@ -5,6 +5,7 @@ import { and, eq, sql } from "drizzle-orm";
5
5
  import { z } from "zod";
6
6
 
7
7
  import { getDb, schema } from "../server/db/index.js";
8
+ import { buildCaseInsensitiveSearchPattern } from "./search-recordings-utils.js";
8
9
 
9
10
  const SNIPPET_RADIUS = 80;
10
11
 
@@ -42,10 +43,6 @@ function recordingDeepLink(
42
43
  });
43
44
  }
44
45
 
45
- function escapeLike(s: string): string {
46
- return s.replace(/([\\%_])/g, "\\$1");
47
- }
48
-
49
46
  function buildSnippet(fullText: string, query: string): string | null {
50
47
  if (!fullText || !query) return null;
51
48
  const lower = fullText.toLowerCase();
@@ -113,7 +110,7 @@ export default defineAction({
113
110
  http: { method: "GET" },
114
111
  run: async (args) => {
115
112
  const db = getDb();
116
- const pattern = `%${escapeLike(args.query)}%`;
113
+ const pattern = buildCaseInsensitiveSearchPattern(args.query);
117
114
 
118
115
  // Title/description matches on the recordings table
119
116
  const recMatches = await db
@@ -132,7 +129,7 @@ export default defineAction({
132
129
  .where(
133
130
  and(
134
131
  accessFilter(schema.recordings, schema.recordingShares),
135
- sql`(${schema.recordings.title} LIKE ${pattern} ESCAPE '\\' OR ${schema.recordings.description} LIKE ${pattern} ESCAPE '\\')`,
132
+ sql`(lower(${schema.recordings.title}) LIKE ${pattern} ESCAPE '\\' OR lower(${schema.recordings.description}) LIKE ${pattern} ESCAPE '\\')`,
136
133
  ),
137
134
  )
138
135
  .limit(args.limit);
@@ -162,7 +159,7 @@ export default defineAction({
162
159
  .where(
163
160
  and(
164
161
  accessFilter(schema.recordings, schema.recordingShares),
165
- sql`${schema.recordingTranscripts.fullText} LIKE ${pattern} ESCAPE '\\'`,
162
+ sql`lower(${schema.recordingTranscripts.fullText}) LIKE ${pattern} ESCAPE '\\'`,
166
163
  ),
167
164
  )
168
165
  .limit(args.limit);
@@ -190,7 +187,7 @@ export default defineAction({
190
187
  .where(
191
188
  and(
192
189
  accessFilter(schema.recordings, schema.recordingShares),
193
- sql`${schema.recordingComments.content} LIKE ${pattern} ESCAPE '\\'`,
190
+ sql`lower(${schema.recordingComments.content}) LIKE ${pattern} ESCAPE '\\'`,
194
191
  ),
195
192
  )
196
193
  .limit(args.limit);
@@ -62,7 +62,7 @@ export default defineAction({
62
62
  .values({
63
63
  organizationId,
64
64
  brandColor: "#18181B",
65
- defaultVisibility: "private",
65
+ defaultVisibility: "public",
66
66
  createdAt: nowIso,
67
67
  updatedAt: nowIso,
68
68
  })
@@ -120,7 +120,7 @@ export default defineAction({
120
120
  name: updatedName,
121
121
  brandColor: row?.brandColor ?? "#18181B",
122
122
  brandLogoUrl: row?.brandLogoUrl ?? null,
123
- defaultVisibility: row?.defaultVisibility ?? "private",
123
+ defaultVisibility: row?.defaultVisibility ?? "public",
124
124
  updatedAt: row?.updatedAt ?? nowIso,
125
125
  };
126
126
  },
@@ -36,6 +36,7 @@ import { parseEdits, serializeEdits } from "../app/lib/timestamp-mapping.js";
36
36
  import { getDb, schema } from "../server/db/index.js";
37
37
  import {
38
38
  getCurrentOwnerEmail,
39
+ getOrganizationDefaultVisibility,
39
40
  nanoid,
40
41
  ownerEmailMatches,
41
42
  } from "../server/lib/recordings.js";
@@ -52,7 +53,9 @@ export default defineAction({
52
53
  visibility: z
53
54
  .enum(["private", "org", "public"])
54
55
  .optional()
55
- .describe("Visibility for the new recording (defaults to 'private')"),
56
+ .describe(
57
+ "Visibility for the new recording. When omitted, uses the organization default and falls back to public.",
58
+ ),
56
59
  videoUrl: z
57
60
  .string()
58
61
  .optional()
@@ -92,10 +95,10 @@ export default defineAction({
92
95
  throw new Error("stitch-recordings needs at least 2 sourceRecordingIds");
93
96
  }
94
97
 
95
- // Stitch creates a brand-new recording owned by the caller that defaults
96
- // to public visibility, so every source must be OWNED by the caller (not
98
+ // Stitch creates a brand-new recording owned by the caller, so every
99
+ // source must be OWNED by the caller (not
97
100
  // just editor-shared) — otherwise a user with editor access to a
98
- // private/org clip could reshare it as a new public recording they own.
101
+ // private/org clip could reshare it as a new recording they own.
99
102
  const sources = await db
100
103
  .select()
101
104
  .from(schema.recordings)
@@ -117,6 +120,8 @@ export default defineAction({
117
120
  assertNativeRecordingMedia(source);
118
121
  }
119
122
  const organizationId = ordered[0].organizationId;
123
+ const defaultVisibility =
124
+ await getOrganizationDefaultVisibility(organizationId);
120
125
 
121
126
  const totalDuration =
122
127
  args.durationMs ??
@@ -152,7 +157,7 @@ export default defineAction({
152
157
  hasCamera: ordered.some((r) => Boolean(r.hasCamera)),
153
158
  editsJson: serializeEdits(edits),
154
159
  ownerEmail,
155
- visibility: args.visibility ?? "public",
160
+ visibility: args.visibility ?? defaultVisibility,
156
161
  createdAt: now,
157
162
  updatedAt: now,
158
163
  // Reuse the first source's thumbnail so the new row has something to show immediately.
@@ -0,0 +1,38 @@
1
+ import { defineAction } from "@agent-native/core";
2
+ import { writeAppState } from "@agent-native/core/application-state";
3
+ import { assertAccess } from "@agent-native/core/sharing";
4
+ import { z } from "zod";
5
+
6
+ const STATUS_KEY_PREFIX = "clips-ai-request-status-";
7
+
8
+ export default defineAction({
9
+ description:
10
+ "Report progress or completion for queued Clips AI work so the recording page can show its current status.",
11
+ schema: z.object({
12
+ recordingId: z.string().describe("Recording ID"),
13
+ kind: z.enum(["remove-silences"]).describe("Queued request kind"),
14
+ status: z
15
+ .enum(["working", "completed", "failed"])
16
+ .describe("Current request status"),
17
+ message: z
18
+ .string()
19
+ .trim()
20
+ .max(500)
21
+ .optional()
22
+ .describe("Optional short status detail"),
23
+ }),
24
+ run: async (args) => {
25
+ await assertAccess("recording", args.recordingId, "editor");
26
+ await writeAppState(`${STATUS_KEY_PREFIX}${args.recordingId}`, {
27
+ kind: args.kind,
28
+ status: args.status,
29
+ message: args.message || null,
30
+ updatedAt: new Date().toISOString(),
31
+ });
32
+ return {
33
+ recordingId: args.recordingId,
34
+ kind: args.kind,
35
+ status: args.status,
36
+ };
37
+ },
38
+ });
@@ -70,6 +70,7 @@ import { cn } from "@/lib/utils";
70
70
  import { computePeaks, type WaveformPeaks } from "@/lib/waveform-peaks";
71
71
 
72
72
  import { ChaptersEditor } from "./chapters-editor";
73
+ import { defaultSelectionRange } from "./editor-selection";
73
74
  import { EditorToolbar } from "./editor-toolbar";
74
75
  import { StitchManager } from "./stitch-manager";
75
76
  import { ThumbnailPicker } from "./thumbnail-picker";
@@ -604,10 +605,8 @@ export function EditorLayout({ recordingId, className }: EditorLayoutProps) {
604
605
  }, [playheadMs, recordingId, selectionRange, split, trim, undo]);
605
606
 
606
607
  // Default selection window so the TrimHandles have something to render.
607
- const effectiveSelection = selectionRange ?? {
608
- startMs: 0,
609
- endMs: durationMs || 1_000,
610
- };
608
+ const effectiveSelection =
609
+ selectionRange ?? defaultSelectionRange(playheadMs, durationMs);
611
610
 
612
611
  if (playerDataQuery.isLoading) {
613
612
  return (
@@ -0,0 +1,19 @@
1
+ const DEFAULT_SELECTION_WINDOW_MS = 1_000;
2
+
3
+ export function defaultSelectionRange(
4
+ playheadMs: number,
5
+ durationMs: number,
6
+ ): { startMs: number; endMs: number } {
7
+ const clipDuration =
8
+ Number.isFinite(durationMs) && durationMs > 0
9
+ ? durationMs
10
+ : DEFAULT_SELECTION_WINDOW_MS;
11
+ const playhead = Number.isFinite(playheadMs)
12
+ ? Math.max(0, Math.min(clipDuration, playheadMs))
13
+ : 0;
14
+
15
+ return {
16
+ startMs: Math.max(0, playhead - DEFAULT_SELECTION_WINDOW_MS),
17
+ endMs: Math.min(clipDuration, playhead + DEFAULT_SELECTION_WINDOW_MS),
18
+ };
19
+ }
@@ -169,20 +169,20 @@ export function StitchManager({
169
169
 
170
170
  return (
171
171
  <Dialog open={open} onOpenChange={onOpenChange}>
172
- <DialogContent className="max-w-3xl">
173
- <DialogHeader>
172
+ <DialogContent className="flex max-h-[min(760px,calc(100vh-32px))] max-w-3xl flex-col gap-0">
173
+ <DialogHeader className="shrink-0">
174
174
  <DialogTitle className="flex items-center gap-2">
175
175
  <IconPuzzle className="w-4 h-4 text-primary" />
176
176
  {t("stitchManager.title")}
177
177
  </DialogTitle>
178
178
  </DialogHeader>
179
179
 
180
- <div className="grid grid-cols-2 gap-3 min-h-[320px]">
181
- <div className="flex flex-col border rounded-md">
180
+ <div className="grid min-h-[320px] flex-1 grid-cols-2 gap-3">
181
+ <div className="flex min-h-0 min-w-0 flex-col rounded-md border">
182
182
  <div className="px-3 py-2 text-xs font-medium border-b">
183
183
  {t("navigation.library")}
184
184
  </div>
185
- <ScrollArea className="flex-1">
185
+ <ScrollArea className="min-h-0 flex-1">
186
186
  {available.length === 0 ? (
187
187
  <div className="p-3 text-xs text-muted-foreground">
188
188
  {t("stitchManager.noOtherRecordings")}
@@ -214,7 +214,7 @@ export function StitchManager({
214
214
  </ScrollArea>
215
215
  </div>
216
216
 
217
- <div className="flex flex-col border rounded-md">
217
+ <div className="flex min-h-0 min-w-0 flex-col rounded-md border">
218
218
  <div className="px-3 py-2 text-xs font-medium border-b flex items-center justify-between">
219
219
  <span>{t("stitchManager.combineOrder")}</span>
220
220
  <span className="text-muted-foreground">
@@ -222,7 +222,7 @@ export function StitchManager({
222
222
  {formatMs(queue.reduce((s, r) => s + r.durationMs, 0))}
223
223
  </span>
224
224
  </div>
225
- <ScrollArea className="flex-1">
225
+ <ScrollArea className="min-h-0 flex-1">
226
226
  {queue.length === 0 ? (
227
227
  <div className="p-3 text-xs text-muted-foreground">
228
228
  {t("stitchManager.emptyQueue")}
@@ -263,7 +263,7 @@ export function StitchManager({
263
263
  </div>
264
264
  </div>
265
265
 
266
- <div className="flex items-center gap-2">
266
+ <div className="flex shrink-0 items-center gap-2 pt-4">
267
267
  <label className="text-xs text-muted-foreground">
268
268
  {t("stitchManager.titleLabel")}
269
269
  </label>
@@ -275,7 +275,7 @@ export function StitchManager({
275
275
  </div>
276
276
 
277
277
  {busy && (
278
- <div className="text-xs text-muted-foreground flex items-center gap-2">
278
+ <div className="flex shrink-0 items-center gap-2 pt-3 text-xs text-muted-foreground">
279
279
  <IconLoader2 className="w-4 h-4 animate-spin" />
280
280
  {t("stitchManager.combining", {
281
281
  progress: Math.round(progress * 100),
@@ -283,7 +283,7 @@ export function StitchManager({
283
283
  </div>
284
284
  )}
285
285
 
286
- <DialogFooter>
286
+ <DialogFooter className="shrink-0 pt-4">
287
287
  <Button variant="ghost" onClick={() => onOpenChange(false)}>
288
288
  {t("common.cancel")}
289
289
  </Button>
@@ -45,8 +45,7 @@ export function BulkActionToolbar({
45
45
  return (
46
46
  <div
47
47
  className={cn(
48
- "sticky bottom-4 mx-auto z-30 flex items-center gap-1 rounded-xl border border-border bg-popover px-3 py-2 shadow-lg",
49
- "w-fit",
48
+ "flex w-fit max-w-full items-center gap-1 rounded-xl border border-border bg-popover px-3 py-2 shadow-lg",
50
49
  )}
51
50
  >
52
51
  <span className="pe-2 text-xs font-medium text-foreground">