@agent-native/core 0.121.1 → 0.122.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 (465) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +145 -0
  3. package/corpus/core/docs/content/actions.mdx +2 -2
  4. package/corpus/core/docs/content/agent-surfaces.mdx +1 -1
  5. package/corpus/core/docs/content/authentication.mdx +2 -0
  6. package/corpus/core/docs/content/deployment.mdx +36 -0
  7. package/corpus/core/docs/content/getting-started.mdx +477 -115
  8. package/corpus/core/docs/content/http-api.mdx +266 -0
  9. package/corpus/core/docs/content/syncing-template-changes.mdx +159 -0
  10. package/corpus/core/package.json +2 -1
  11. package/corpus/core/src/a2a/activity.ts +38 -27
  12. package/corpus/core/src/agent/engine/builder-engine.ts +35 -4
  13. package/corpus/core/src/agent/run-manager.ts +20 -1
  14. package/corpus/core/src/agent/run-store.ts +4 -1
  15. package/corpus/core/src/agent/types.ts +28 -8
  16. package/corpus/core/src/chat-threads/store.ts +45 -0
  17. package/corpus/core/src/checkpoints/index.ts +2 -0
  18. package/corpus/core/src/checkpoints/route-match.ts +13 -0
  19. package/corpus/core/src/cli/create.ts +105 -17
  20. package/corpus/core/src/cli/index.ts +20 -0
  21. package/corpus/core/src/cli/template-baseline.ts +410 -0
  22. package/corpus/core/src/cli/template-sync.ts +1004 -0
  23. package/corpus/core/src/cli/templates-meta.ts +1 -0
  24. package/corpus/core/src/client/AssistantChat.tsx +38 -12
  25. package/corpus/core/src/client/NewWorkspaceAppFlow.tsx +75 -10
  26. package/corpus/core/src/client/chat/message-components.tsx +127 -66
  27. package/corpus/core/src/client/chat/tool-call-display.tsx +29 -5
  28. package/corpus/core/src/client/error-format.ts +18 -0
  29. package/corpus/core/src/client/org/OrgSwitcher.tsx +30 -8
  30. package/corpus/core/src/client/org/TeamPage.tsx +7 -6
  31. package/corpus/core/src/client/sse-event-processor.ts +3 -0
  32. package/corpus/core/src/data-widgets/index.ts +41 -0
  33. package/corpus/core/src/deploy/build.ts +11 -9
  34. package/corpus/core/src/integrations/webhook-handler.ts +63 -9
  35. package/corpus/core/src/org/auto-join-domain.ts +4 -3
  36. package/corpus/core/src/org/context.ts +108 -39
  37. package/corpus/core/src/org/index.ts +5 -0
  38. package/corpus/core/src/org/service-identity.ts +60 -0
  39. package/corpus/core/src/provider-api/index.ts +22 -1
  40. package/corpus/core/src/scripts/docs/search.ts +12 -1
  41. package/corpus/core/src/server/agent-chat/context-tools.ts +9 -4
  42. package/corpus/core/src/server/agent-chat/framework-prompts.ts +38 -66
  43. package/corpus/core/src/server/agent-chat-plugin.ts +17 -10
  44. package/corpus/core/src/server/agents-bundle.ts +84 -5
  45. package/corpus/core/src/server/auth.ts +4 -3
  46. package/corpus/core/src/server/builder-browser.ts +47 -19
  47. package/corpus/core/src/server/core-routes-plugin.ts +2 -2
  48. package/corpus/core/src/server/credential-provider.ts +209 -68
  49. package/corpus/core/src/server/index.ts +3 -0
  50. package/corpus/core/src/server/prompts/framework-core-compact.ts +6 -13
  51. package/corpus/core/src/server/prompts/framework-core.ts +9 -21
  52. package/corpus/core/src/server/prompts/index.ts +0 -1
  53. package/corpus/core/src/server/prompts/shared-rules.ts +19 -11
  54. package/corpus/core/src/server/ssr-handler.ts +13 -2
  55. package/corpus/core/src/settings/user-settings.ts +13 -1
  56. package/corpus/core/src/shared/cache-control.ts +141 -0
  57. package/corpus/core/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  58. package/corpus/core/src/templates/chat/_gitignore +1 -0
  59. package/corpus/core/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  60. package/corpus/core/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  61. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  62. package/corpus/core/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  63. package/corpus/core/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  64. package/corpus/core/src/vite/agents-bundle-plugin.ts +7 -6
  65. package/corpus/core/src/vite/client.ts +5 -0
  66. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +4 -5
  67. package/corpus/templates/analytics/.agents/skills/admin-surfaces/SKILL.md +55 -0
  68. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +10 -0
  69. package/corpus/templates/analytics/.agents/skills/dashboard-management/references/template-catalog-and-demo.md +62 -0
  70. package/corpus/templates/analytics/.agents/skills/dashboard-ops/SKILL.md +85 -0
  71. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +27 -2
  72. package/corpus/templates/analytics/.agents/skills/data-querying/references/inline-chart-embeds.md +139 -0
  73. package/corpus/templates/analytics/.agents/skills/monitoring/SKILL.md +77 -0
  74. package/corpus/templates/analytics/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  75. package/corpus/templates/analytics/AGENTS.md +91 -563
  76. package/corpus/templates/analytics/_gitignore +1 -0
  77. package/corpus/templates/analytics/actions/bigquery.ts +12 -4
  78. package/corpus/templates/analytics/actions/generate-chart.ts +5 -5
  79. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +30 -1
  80. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/DashboardFilterBar.tsx +3 -0
  81. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/SqlChartCard.tsx +1 -1
  82. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +1 -0
  83. package/corpus/templates/analytics/changelog/2026-07-24-analytics-finds-saved-dashboards-and-queries-far-more-reliab.md +6 -0
  84. package/corpus/templates/analytics/changelog/2026-07-24-notion-access-errors-now-explain-that-a-page-needs-sharing-w.md +6 -0
  85. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +7 -0
  86. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +191 -30
  87. package/corpus/templates/analytics/server/lib/bigquery.ts +11 -1
  88. package/corpus/templates/analytics/server/lib/notion.ts +15 -4
  89. package/corpus/templates/analytics/server/plugins/agent-chat.ts +10 -0
  90. package/corpus/templates/assets/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  91. package/corpus/templates/brain/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  92. package/corpus/templates/brain/_gitignore +1 -0
  93. package/corpus/templates/calendar/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  94. package/corpus/templates/calendar/_gitignore +1 -0
  95. package/corpus/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  96. package/corpus/templates/chat/_gitignore +1 -0
  97. package/corpus/templates/clips/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  98. package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +34 -0
  99. package/corpus/templates/clips/AGENTS.md +5 -4
  100. package/corpus/templates/clips/_gitignore +1 -0
  101. package/corpus/templates/clips/actions/cleanup-transcript.ts +5 -0
  102. package/corpus/templates/clips/actions/get-recording-insights.ts +44 -8
  103. package/corpus/templates/clips/actions/get-recording-player-data.ts +39 -70
  104. package/corpus/templates/clips/actions/list-clip-views.ts +2 -4
  105. package/corpus/templates/clips/actions/list-recordings.ts +69 -19
  106. package/corpus/templates/clips/actions/list-viewers.ts +5 -2
  107. package/corpus/templates/clips/actions/regenerate-summary.ts +5 -1
  108. package/corpus/templates/clips/actions/request-transcript.ts +28 -1
  109. package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +21 -1
  110. package/corpus/templates/clips/app/components/meetings/quick-ask-sidebar.tsx +14 -1
  111. package/corpus/templates/clips/app/components/player/insights-panel.tsx +8 -20
  112. package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +335 -0
  113. package/corpus/templates/clips/app/components/player/video-player.tsx +13 -8
  114. package/corpus/templates/clips/app/components/sharing/share-ui.tsx +2 -1
  115. package/corpus/templates/clips/app/i18n/en-US.ts +13 -2
  116. package/corpus/templates/clips/app/lib/capture-permissions.ts +110 -0
  117. package/corpus/templates/clips/app/lib/recording-link.ts +32 -0
  118. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +27 -0
  119. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +46 -15
  120. package/corpus/templates/clips/app/routes/record.tsx +77 -31
  121. package/corpus/templates/clips/app/routes/share.$shareId.tsx +42 -31
  122. package/corpus/templates/clips/changelog/2026-07-24-clip-pages-now-show-a-view-count-with-viewer-avatars-next-to.md +6 -0
  123. package/corpus/templates/clips/changelog/2026-07-24-clip-summaries-read-like-a-description-you-d-write-yourself-.md +6 -0
  124. package/corpus/templates/clips/changelog/2026-07-24-clip-view-counts-now-separate-human-views-from-agent-views-s.md +6 -0
  125. package/corpus/templates/clips/changelog/2026-07-24-clips-actions-can-now-be-called-by-org-service-tokens-so-ext.md +6 -0
  126. package/corpus/templates/clips/changelog/2026-07-24-clips-no-longer-briefly-shows-a-dock-icon-while-launching.md +6 -0
  127. package/corpus/templates/clips/changelog/2026-07-24-fixed-owner-and-editor-share-links-redirecting-to-the-record.md +6 -0
  128. package/corpus/templates/clips/changelog/2026-07-24-meeting-and-note-recordings-now-start-as-a-compact-pill-on-t.md +6 -0
  129. package/corpus/templates/clips/changelog/2026-07-24-new-clips-now-copy-a-shareable-link-instead-of-the-owner-onl.md +6 -0
  130. package/corpus/templates/clips/changelog/2026-07-24-opening-a-share-link-as-the-clip-s-owner-now-goes-straight-t.md +6 -0
  131. package/corpus/templates/clips/changelog/2026-07-24-permissions-and-rewind-controls-now-use-compact-consistent-h.md +6 -0
  132. package/corpus/templates/clips/changelog/2026-07-24-quitting-the-desktop-app-no-longer-shows-a-false-macos-crash.md +6 -0
  133. package/corpus/templates/clips/changelog/2026-07-24-screen-recording-permission-errors-now-name-the-exact-app-to.md +6 -0
  134. package/corpus/templates/clips/changelog/2026-07-24-the-desktop-app-now-copies-a-new-clip-s-share-link-to-your-c.md +6 -0
  135. package/corpus/templates/clips/changelog/2026-07-24-the-recording-toolbar-now-stays-above-other-apps-including-o.md +6 -0
  136. package/corpus/templates/clips/changelog/2026-07-24-transcript-captions-now-use-real-speech-timings-instead-of-a.md +6 -0
  137. package/corpus/templates/clips/changelog/2026-07-24-video-playback-no-longer-stutters-and-replays-the-last-momen.md +6 -0
  138. package/corpus/templates/clips/chrome-extension/src/background.ts +17 -1
  139. package/corpus/templates/clips/desktop/package.json +2 -0
  140. package/corpus/templates/clips/desktop/src/app.tsx +89 -0
  141. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -3
  142. package/corpus/templates/clips/desktop/src/lib/audio-meter.ts +51 -0
  143. package/corpus/templates/clips/desktop/src/lib/native-notification.ts +44 -0
  144. package/corpus/templates/clips/desktop/src/lib/recording-link.ts +67 -0
  145. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +35 -35
  146. package/corpus/templates/clips/desktop/src/overlays/live-transcript.tsx +3 -2
  147. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +47 -46
  148. package/corpus/templates/clips/desktop/src/styles.css +127 -78
  149. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +7 -0
  150. package/corpus/templates/clips/desktop/src-tauri/Info.plist +6 -0
  151. package/corpus/templates/clips/desktop/src-tauri/capabilities/default.json +1 -0
  152. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +7 -3
  153. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +4 -1
  154. package/corpus/templates/clips/desktop/src-tauri/src/main.rs +8 -0
  155. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +21 -10
  156. package/corpus/templates/clips/desktop/src-tauri/src/util.rs +40 -0
  157. package/corpus/templates/clips/server/db/schema.ts +25 -0
  158. package/corpus/templates/clips/server/lib/agent-views.ts +145 -0
  159. package/corpus/templates/clips/server/lib/public-agent-context.ts +7 -0
  160. package/corpus/templates/clips/server/lib/recording-share-grant.ts +79 -0
  161. package/corpus/templates/clips/server/lib/recordings.ts +51 -3
  162. package/corpus/templates/clips/server/plugins/db.ts +23 -0
  163. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +49 -17
  164. package/corpus/templates/clips/shared/recording-link.ts +43 -0
  165. package/corpus/templates/clips/shared/share-attribution.ts +4 -0
  166. package/corpus/templates/clips/shared/share-dashboard-redirect.ts +42 -0
  167. package/corpus/templates/clips/shared/view-analytics.ts +26 -0
  168. package/corpus/templates/content/.agents/skills/content/SKILL.md +5 -0
  169. package/corpus/templates/content/.agents/skills/content/references/local-file-mode.md +135 -0
  170. package/corpus/templates/content/.agents/skills/document-editing/SKILL.md +12 -0
  171. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +238 -0
  172. package/corpus/templates/content/.agents/skills/document-editing/references/document-behavior.md +91 -0
  173. package/corpus/templates/content/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  174. package/corpus/templates/content/AGENTS.md +62 -583
  175. package/corpus/templates/content/_gitignore +1 -0
  176. package/corpus/templates/design/.agents/skills/creative-context/SKILL.md +11 -0
  177. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +50 -8
  178. package/corpus/templates/design/.agents/skills/design-generation/references/code-layers.md +81 -0
  179. package/corpus/templates/design/.agents/skills/design-generation/references/code-workspace.md +42 -0
  180. package/corpus/templates/design/.agents/skills/design-generation/references/editor-extensions.md +34 -0
  181. package/corpus/templates/design/.agents/skills/responsive-breakpoints/SKILL.md +4 -1
  182. package/corpus/templates/design/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  183. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +17 -0
  184. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +8196 -0
  185. package/corpus/templates/design/.generated/bridge/embedded-wheel.generated.ts +265 -0
  186. package/corpus/templates/design/.generated/bridge/hit-test.generated.ts +642 -0
  187. package/corpus/templates/design/.generated/bridge/motion-preview.generated.ts +571 -0
  188. package/corpus/templates/design/.generated/bridge/nav.generated.ts +91 -0
  189. package/corpus/templates/design/.generated/bridge/sample.generated.ts +23 -0
  190. package/corpus/templates/design/.generated/bridge/shader-fill-preview.generated.ts +263 -0
  191. package/corpus/templates/design/.generated/bridge/shader-runtime.generated.ts +518 -0
  192. package/corpus/templates/design/.generated/bridge/tweak.generated.ts +20 -0
  193. package/corpus/templates/design/.generated/bridge/zoom.generated.ts +32 -0
  194. package/corpus/templates/design/AGENTS.md +88 -503
  195. package/corpus/templates/design/_gitignore +1 -0
  196. package/corpus/templates/dispatch/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  197. package/corpus/templates/dispatch/_gitignore +1 -0
  198. package/corpus/templates/dispatch/changelog/2026-07-24-signing-in-now-puts-you-in-your-companys-workspace.md +6 -0
  199. package/corpus/templates/forms/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  200. package/corpus/templates/forms/_gitignore +1 -0
  201. package/corpus/templates/forms/server/lib/public-form-ssr.ts +2 -2
  202. package/corpus/templates/macros/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  203. package/corpus/templates/macros/_gitignore +1 -0
  204. package/corpus/templates/mail/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  205. package/corpus/templates/mail/_gitignore +1 -0
  206. package/corpus/templates/plan/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  207. package/corpus/templates/plan/_gitignore +1 -0
  208. package/corpus/templates/slides/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  209. package/corpus/templates/slides/_gitignore +1 -0
  210. package/corpus/templates/slides/server/plugins/db.ts +4 -0
  211. package/corpus/templates/tasks/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  212. package/corpus/templates/tasks/AGENTS.md +1 -1
  213. package/corpus/templates/tasks/_gitignore +1 -0
  214. package/dist/a2a/activity.d.ts +4 -1
  215. package/dist/a2a/activity.d.ts.map +1 -1
  216. package/dist/a2a/activity.js +27 -16
  217. package/dist/a2a/activity.js.map +1 -1
  218. package/dist/agent/engine/builder-engine.d.ts +1 -0
  219. package/dist/agent/engine/builder-engine.d.ts.map +1 -1
  220. package/dist/agent/engine/builder-engine.js +31 -4
  221. package/dist/agent/engine/builder-engine.js.map +1 -1
  222. package/dist/agent/run-manager.d.ts.map +1 -1
  223. package/dist/agent/run-manager.js +18 -1
  224. package/dist/agent/run-manager.js.map +1 -1
  225. package/dist/agent/run-store.d.ts +1 -0
  226. package/dist/agent/run-store.d.ts.map +1 -1
  227. package/dist/agent/run-store.js +2 -1
  228. package/dist/agent/run-store.js.map +1 -1
  229. package/dist/agent/types.d.ts +12 -1
  230. package/dist/agent/types.d.ts.map +1 -1
  231. package/dist/agent/types.js +21 -1
  232. package/dist/agent/types.js.map +1 -1
  233. package/dist/chat-threads/store.d.ts +10 -0
  234. package/dist/chat-threads/store.d.ts.map +1 -1
  235. package/dist/chat-threads/store.js +41 -0
  236. package/dist/chat-threads/store.js.map +1 -1
  237. package/dist/checkpoints/index.d.ts +1 -0
  238. package/dist/checkpoints/index.d.ts.map +1 -1
  239. package/dist/checkpoints/index.js +1 -0
  240. package/dist/checkpoints/index.js.map +1 -1
  241. package/dist/checkpoints/route-match.d.ts +8 -0
  242. package/dist/checkpoints/route-match.d.ts.map +1 -0
  243. package/dist/checkpoints/route-match.js +13 -0
  244. package/dist/checkpoints/route-match.js.map +1 -0
  245. package/dist/cli/create.d.ts +35 -4
  246. package/dist/cli/create.d.ts.map +1 -1
  247. package/dist/cli/create.js +69 -19
  248. package/dist/cli/create.js.map +1 -1
  249. package/dist/cli/index.js +19 -0
  250. package/dist/cli/index.js.map +1 -1
  251. package/dist/cli/template-baseline.d.ts +54 -0
  252. package/dist/cli/template-baseline.d.ts.map +1 -0
  253. package/dist/cli/template-baseline.js +334 -0
  254. package/dist/cli/template-baseline.js.map +1 -0
  255. package/dist/cli/template-sync.d.ts +57 -0
  256. package/dist/cli/template-sync.d.ts.map +1 -0
  257. package/dist/cli/template-sync.js +787 -0
  258. package/dist/cli/template-sync.js.map +1 -0
  259. package/dist/cli/templates-meta.d.ts.map +1 -1
  260. package/dist/cli/templates-meta.js +1 -0
  261. package/dist/cli/templates-meta.js.map +1 -1
  262. package/dist/client/AssistantChat.d.ts +2 -1
  263. package/dist/client/AssistantChat.d.ts.map +1 -1
  264. package/dist/client/AssistantChat.js +38 -10
  265. package/dist/client/AssistantChat.js.map +1 -1
  266. package/dist/client/NewWorkspaceAppFlow.d.ts.map +1 -1
  267. package/dist/client/NewWorkspaceAppFlow.js +32 -2
  268. package/dist/client/NewWorkspaceAppFlow.js.map +1 -1
  269. package/dist/client/chat/message-components.d.ts +20 -0
  270. package/dist/client/chat/message-components.d.ts.map +1 -1
  271. package/dist/client/chat/message-components.js +81 -46
  272. package/dist/client/chat/message-components.js.map +1 -1
  273. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  274. package/dist/client/chat/tool-call-display.js +14 -6
  275. package/dist/client/chat/tool-call-display.js.map +1 -1
  276. package/dist/client/error-format.d.ts.map +1 -1
  277. package/dist/client/error-format.js +13 -0
  278. package/dist/client/error-format.js.map +1 -1
  279. package/dist/client/org/OrgSwitcher.d.ts +8 -1
  280. package/dist/client/org/OrgSwitcher.d.ts.map +1 -1
  281. package/dist/client/org/OrgSwitcher.js +3 -2
  282. package/dist/client/org/OrgSwitcher.js.map +1 -1
  283. package/dist/client/org/TeamPage.d.ts.map +1 -1
  284. package/dist/client/org/TeamPage.js +1 -1
  285. package/dist/client/org/TeamPage.js.map +1 -1
  286. package/dist/client/sse-event-processor.d.ts.map +1 -1
  287. package/dist/client/sse-event-processor.js +3 -0
  288. package/dist/client/sse-event-processor.js.map +1 -1
  289. package/dist/collab/awareness.d.ts +2 -2
  290. package/dist/collab/awareness.d.ts.map +1 -1
  291. package/dist/data-widgets/index.d.ts +3 -0
  292. package/dist/data-widgets/index.d.ts.map +1 -1
  293. package/dist/data-widgets/index.js +33 -0
  294. package/dist/data-widgets/index.js.map +1 -1
  295. package/dist/deploy/build.d.ts.map +1 -1
  296. package/dist/deploy/build.js +11 -7
  297. package/dist/deploy/build.js.map +1 -1
  298. package/dist/eject/provider-api-definitions.d.ts +1 -0
  299. package/dist/eject/provider-api-definitions.d.ts.map +1 -1
  300. package/dist/integrations/webhook-handler.d.ts.map +1 -1
  301. package/dist/integrations/webhook-handler.js +46 -9
  302. package/dist/integrations/webhook-handler.js.map +1 -1
  303. package/dist/notifications/routes.d.ts +3 -3
  304. package/dist/observability/routes.d.ts +3 -3
  305. package/dist/org/auto-join-domain.d.ts +3 -2
  306. package/dist/org/auto-join-domain.d.ts.map +1 -1
  307. package/dist/org/auto-join-domain.js +1 -1
  308. package/dist/org/auto-join-domain.js.map +1 -1
  309. package/dist/org/context.d.ts.map +1 -1
  310. package/dist/org/context.js +84 -28
  311. package/dist/org/context.js.map +1 -1
  312. package/dist/org/index.d.ts +1 -0
  313. package/dist/org/index.d.ts.map +1 -1
  314. package/dist/org/index.js +1 -0
  315. package/dist/org/index.js.map +1 -1
  316. package/dist/org/service-identity.d.ts +43 -0
  317. package/dist/org/service-identity.d.ts.map +1 -0
  318. package/dist/org/service-identity.js +34 -0
  319. package/dist/org/service-identity.js.map +1 -0
  320. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  321. package/dist/provider-api/actions/provider-api.d.ts +13 -11
  322. package/dist/provider-api/actions/provider-api.d.ts.map +1 -1
  323. package/dist/provider-api/index.d.ts +4 -0
  324. package/dist/provider-api/index.d.ts.map +1 -1
  325. package/dist/provider-api/index.js +17 -1
  326. package/dist/provider-api/index.js.map +1 -1
  327. package/dist/resources/handlers.d.ts +1 -1
  328. package/dist/scripts/docs/search.d.ts.map +1 -1
  329. package/dist/scripts/docs/search.js +12 -1
  330. package/dist/scripts/docs/search.js.map +1 -1
  331. package/dist/server/agent-chat/context-tools.d.ts.map +1 -1
  332. package/dist/server/agent-chat/context-tools.js +3 -3
  333. package/dist/server/agent-chat/context-tools.js.map +1 -1
  334. package/dist/server/agent-chat/framework-prompts.d.ts +8 -3
  335. package/dist/server/agent-chat/framework-prompts.d.ts.map +1 -1
  336. package/dist/server/agent-chat/framework-prompts.js +33 -62
  337. package/dist/server/agent-chat/framework-prompts.js.map +1 -1
  338. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  339. package/dist/server/agent-chat-plugin.js +16 -10
  340. package/dist/server/agent-chat-plugin.js.map +1 -1
  341. package/dist/server/agents-bundle.d.ts +18 -0
  342. package/dist/server/agents-bundle.d.ts.map +1 -1
  343. package/dist/server/agents-bundle.js +70 -4
  344. package/dist/server/agents-bundle.js.map +1 -1
  345. package/dist/server/auth.d.ts.map +1 -1
  346. package/dist/server/auth.js +4 -3
  347. package/dist/server/auth.js.map +1 -1
  348. package/dist/server/builder-browser.d.ts.map +1 -1
  349. package/dist/server/builder-browser.js +43 -19
  350. package/dist/server/builder-browser.js.map +1 -1
  351. package/dist/server/core-routes-plugin.js +2 -2
  352. package/dist/server/core-routes-plugin.js.map +1 -1
  353. package/dist/server/credential-provider.d.ts +38 -2
  354. package/dist/server/credential-provider.d.ts.map +1 -1
  355. package/dist/server/credential-provider.js +142 -64
  356. package/dist/server/credential-provider.js.map +1 -1
  357. package/dist/server/index.d.ts +1 -1
  358. package/dist/server/index.d.ts.map +1 -1
  359. package/dist/server/index.js +1 -1
  360. package/dist/server/index.js.map +1 -1
  361. package/dist/server/prompts/framework-core-compact.d.ts +1 -1
  362. package/dist/server/prompts/framework-core-compact.d.ts.map +1 -1
  363. package/dist/server/prompts/framework-core-compact.js +7 -13
  364. package/dist/server/prompts/framework-core-compact.js.map +1 -1
  365. package/dist/server/prompts/framework-core.d.ts +1 -1
  366. package/dist/server/prompts/framework-core.d.ts.map +1 -1
  367. package/dist/server/prompts/framework-core.js +10 -21
  368. package/dist/server/prompts/framework-core.js.map +1 -1
  369. package/dist/server/prompts/index.d.ts +1 -1
  370. package/dist/server/prompts/index.d.ts.map +1 -1
  371. package/dist/server/prompts/index.js +1 -1
  372. package/dist/server/prompts/index.js.map +1 -1
  373. package/dist/server/prompts/shared-rules.d.ts +16 -10
  374. package/dist/server/prompts/shared-rules.d.ts.map +1 -1
  375. package/dist/server/prompts/shared-rules.js +19 -10
  376. package/dist/server/prompts/shared-rules.js.map +1 -1
  377. package/dist/server/ssr-handler.d.ts +1 -1
  378. package/dist/server/ssr-handler.d.ts.map +1 -1
  379. package/dist/server/ssr-handler.js +10 -3
  380. package/dist/server/ssr-handler.js.map +1 -1
  381. package/dist/server/transcribe-voice.d.ts +1 -1
  382. package/dist/settings/user-settings.d.ts.map +1 -1
  383. package/dist/settings/user-settings.js +13 -1
  384. package/dist/settings/user-settings.js.map +1 -1
  385. package/dist/shared/cache-control.d.ts +52 -0
  386. package/dist/shared/cache-control.d.ts.map +1 -1
  387. package/dist/shared/cache-control.js +107 -0
  388. package/dist/shared/cache-control.js.map +1 -1
  389. package/dist/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  390. package/dist/templates/chat/_gitignore +1 -0
  391. package/dist/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  392. package/dist/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  393. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  394. package/dist/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  395. package/dist/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  396. package/dist/vite/agents-bundle-plugin.d.ts.map +1 -1
  397. package/dist/vite/agents-bundle-plugin.js +8 -7
  398. package/dist/vite/agents-bundle-plugin.js.map +1 -1
  399. package/dist/vite/client.d.ts.map +1 -1
  400. package/dist/vite/client.js +2 -0
  401. package/dist/vite/client.js.map +1 -1
  402. package/docs/content/actions.mdx +2 -2
  403. package/docs/content/agent-surfaces.mdx +1 -1
  404. package/docs/content/authentication.mdx +2 -0
  405. package/docs/content/deployment.mdx +36 -0
  406. package/docs/content/getting-started.mdx +477 -115
  407. package/docs/content/http-api.mdx +266 -0
  408. package/docs/content/syncing-template-changes.mdx +159 -0
  409. package/package.json +4 -3
  410. package/src/a2a/activity.ts +38 -27
  411. package/src/agent/engine/builder-engine.ts +35 -4
  412. package/src/agent/run-manager.ts +20 -1
  413. package/src/agent/run-store.ts +4 -1
  414. package/src/agent/types.ts +28 -8
  415. package/src/chat-threads/store.ts +45 -0
  416. package/src/checkpoints/index.ts +2 -0
  417. package/src/checkpoints/route-match.ts +13 -0
  418. package/src/cli/create.ts +105 -17
  419. package/src/cli/index.ts +20 -0
  420. package/src/cli/template-baseline.ts +410 -0
  421. package/src/cli/template-sync.ts +1004 -0
  422. package/src/cli/templates-meta.ts +1 -0
  423. package/src/client/AssistantChat.tsx +38 -12
  424. package/src/client/NewWorkspaceAppFlow.tsx +75 -10
  425. package/src/client/chat/message-components.tsx +127 -66
  426. package/src/client/chat/tool-call-display.tsx +29 -5
  427. package/src/client/error-format.ts +18 -0
  428. package/src/client/org/OrgSwitcher.tsx +30 -8
  429. package/src/client/org/TeamPage.tsx +7 -6
  430. package/src/client/sse-event-processor.ts +3 -0
  431. package/src/data-widgets/index.ts +41 -0
  432. package/src/deploy/build.ts +11 -9
  433. package/src/integrations/webhook-handler.ts +63 -9
  434. package/src/org/auto-join-domain.ts +4 -3
  435. package/src/org/context.ts +108 -39
  436. package/src/org/index.ts +5 -0
  437. package/src/org/service-identity.ts +60 -0
  438. package/src/provider-api/index.ts +22 -1
  439. package/src/scripts/docs/search.ts +12 -1
  440. package/src/server/__snapshots__/agent-chat-plugin.surface.spec.ts.snap +25 -36
  441. package/src/server/agent-chat/context-tools.ts +9 -4
  442. package/src/server/agent-chat/framework-prompts.ts +38 -66
  443. package/src/server/agent-chat-plugin.ts +17 -10
  444. package/src/server/agents-bundle.ts +84 -5
  445. package/src/server/auth.ts +4 -3
  446. package/src/server/builder-browser.ts +47 -19
  447. package/src/server/core-routes-plugin.ts +2 -2
  448. package/src/server/credential-provider.ts +209 -68
  449. package/src/server/index.ts +3 -0
  450. package/src/server/prompts/framework-core-compact.ts +6 -13
  451. package/src/server/prompts/framework-core.ts +9 -21
  452. package/src/server/prompts/index.ts +0 -1
  453. package/src/server/prompts/shared-rules.ts +19 -11
  454. package/src/server/ssr-handler.ts +13 -2
  455. package/src/settings/user-settings.ts +13 -1
  456. package/src/shared/cache-control.ts +141 -0
  457. package/src/templates/chat/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  458. package/src/templates/chat/_gitignore +1 -0
  459. package/src/templates/default/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  460. package/src/templates/headless/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  461. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +19 -0
  462. package/src/templates/workspace-core/.agents/skills/upgrade-agent-native/SKILL.md +24 -2
  463. package/src/templates/workspace-core/.agents/skills/visual-answer/SKILL.md +1 -0
  464. package/src/vite/agents-bundle-plugin.ts +7 -6
  465. package/src/vite/client.ts +5 -0
@@ -101,7 +101,11 @@ export default defineAction({
101
101
  `Regenerate the description for recording ${args.recordingId}. ` +
102
102
  `Read the transcript in this request's context and call ` +
103
103
  `\`update-recording --id=${args.recordingId} --description="..."\` with a 2–4 ` +
104
- `sentence summary of what the recording covers. Title: "${rec.title}".`;
104
+ `sentence summary of what the recording covers. Title: "${rec.title}". ` +
105
+ `Write the description the way the person who made this recording would ` +
106
+ `describe it themselves: lead with the subject matter, and never use ` +
107
+ `outside-narrator framing like "the speaker", "the presenter", "the video", ` +
108
+ `"this recording", or "this clip".`;
105
109
 
106
110
  const request = {
107
111
  kind: "regenerate-summary" as const,
@@ -437,6 +437,26 @@ function fullTextSegmentJson(
437
437
  return JSON.stringify(buildCaptionSegmentsFromText(text, durationMs));
438
438
  }
439
439
 
440
+ /**
441
+ * Pick the segments to store after cleanup rewrites the transcript text.
442
+ *
443
+ * Measured timings from the capture engine always win.
444
+ * `buildCaptionSegmentsFromText` spaces cues in proportion to word count, so
445
+ * re-synthesizing over real timestamps spreads a short transcript evenly across
446
+ * the whole recording — which reads as minute-long gaps of dropped speech even
447
+ * when nothing was dropped there.
448
+ */
449
+ export function resolveCleanupSegmentsJson(
450
+ priorSegmentsJson: string | null | undefined,
451
+ cleanedText: string,
452
+ durationMs: number | null | undefined,
453
+ ): string {
454
+ if (parseTranscriptSegments(priorSegmentsJson).length > 1) {
455
+ return priorSegmentsJson as string;
456
+ }
457
+ return fullTextSegmentJson(cleanedText, durationMs);
458
+ }
459
+
440
460
  export function isSafeTranscriptCleanupReplacement(
441
461
  sourceText: string,
442
462
  cleanedText: string,
@@ -642,12 +662,14 @@ async function cleanupNativeTranscript({
642
662
  ownerEmail,
643
663
  fullText,
644
664
  durationMs,
665
+ segmentsJson,
645
666
  }: {
646
667
  db: ReturnType<typeof getDb>;
647
668
  recordingId: string;
648
669
  ownerEmail: string;
649
670
  fullText: string;
650
671
  durationMs: number | null | undefined;
672
+ segmentsJson?: string | null;
651
673
  }): Promise<{ cleaned: boolean; provider?: string }> {
652
674
  const sourceText = fullText.trim();
653
675
  if (!sourceText) return { cleaned: false };
@@ -704,7 +726,11 @@ async function cleanupNativeTranscript({
704
726
  status: "ready",
705
727
  failureReason: null,
706
728
  language,
707
- segmentsJson: fullTextSegmentJson(cleanedText, durationMs),
729
+ segmentsJson: resolveCleanupSegmentsJson(
730
+ segmentsJson,
731
+ cleanedText,
732
+ durationMs,
733
+ ),
708
734
  fullText: cleanedText,
709
735
  retryCount: 0,
710
736
  updatedAt: now,
@@ -855,6 +881,7 @@ async function completeReadyTranscript({
855
881
  ownerEmail,
856
882
  fullText,
857
883
  durationMs: recForTitle?.durationMs,
884
+ segmentsJson,
858
885
  }).catch((err) => {
859
886
  console.warn(
860
887
  `[clips] native transcript cleanup failed for ${recordingId}:`,
@@ -23,6 +23,7 @@ import {
23
23
  } from "@/components/ui/dialog";
24
24
  import { ScrollArea } from "@/components/ui/scroll-area";
25
25
  import { exportConcat } from "@/lib/ffmpeg-export";
26
+ import { copyRecordingShareLink } from "@/lib/recording-link";
26
27
  import { formatMs } from "@/lib/timestamp-mapping";
27
28
  import { uploadFileClient } from "@/lib/upload-file-client";
28
29
  import { cn } from "@/lib/utils";
@@ -142,7 +143,26 @@ export function StitchManager({
142
143
  videoUrl,
143
144
  durationMs: totalDuration,
144
145
  });
145
- toast.success(t("stitchManager.created"));
146
+ const newRecordingId = (result as { id?: string } | null)?.id;
147
+ if (newRecordingId) {
148
+ const copied = await copyRecordingShareLink(newRecordingId);
149
+ if (copied) {
150
+ toast.success(t("stitchManager.created"), {
151
+ description: t("recordRoute.linkCopied"),
152
+ });
153
+ } else {
154
+ toast.success(t("stitchManager.created"), {
155
+ action: {
156
+ label: t("recordRoute.copyLinkAction"),
157
+ onClick: () => {
158
+ void copyRecordingShareLink(newRecordingId);
159
+ },
160
+ },
161
+ });
162
+ }
163
+ } else {
164
+ toast.success(t("stitchManager.created"));
165
+ }
146
166
  onOpenChange(false);
147
167
  return result;
148
168
  } catch (err: any) {
@@ -78,6 +78,7 @@ export function QuickAskSidebar({
78
78
  const [open, setOpen] = useState(false);
79
79
  const [draft, setDraft] = useState("");
80
80
  const [history, setHistory] = useState<ChatTurn[]>([]);
81
+ const [pendingAsk, setPendingAsk] = useState<string | null>(null);
81
82
  const textareaRef = useRef<HTMLTextAreaElement>(null);
82
83
 
83
84
  // Single global keydown listener; toggles on Cmd/Ctrl+J. Esc is handled
@@ -94,11 +95,17 @@ export function QuickAskSidebar({
94
95
  return () => window.removeEventListener("keydown", onKeyDown);
95
96
  }, []);
96
97
 
98
+ // The desktop pill's "Ask anything" bar hands its question over as `?ask=`
99
+ // alongside `?chat=1`, so the question the user typed on the overlay lands
100
+ // in the agent chat here instead of being retyped.
97
101
  useEffect(() => {
98
102
  const params = new URLSearchParams(window.location.search);
99
- if (params.get("chat") !== "1") return;
103
+ const askParam = params.get("ask")?.trim();
104
+ if (params.get("chat") !== "1" && !askParam) return;
100
105
  setOpen(true);
106
+ if (askParam) setPendingAsk(askParam);
101
107
  params.delete("chat");
108
+ params.delete("ask");
102
109
  const nextQuery = params.toString();
103
110
  window.history.replaceState(
104
111
  window.history.state,
@@ -155,6 +162,12 @@ export function QuickAskSidebar({
155
162
  [meetingId, meetingTitle, segments, t],
156
163
  );
157
164
 
165
+ useEffect(() => {
166
+ if (!pendingAsk) return;
167
+ setPendingAsk(null);
168
+ send(pendingAsk);
169
+ }, [pendingAsk, send]);
170
+
158
171
  return (
159
172
  <Sheet open={open} onOpenChange={setOpen}>
160
173
  <SheetContent
@@ -16,8 +16,11 @@ import {
16
16
  CartesianGrid,
17
17
  } from "recharts";
18
18
 
19
+ import {
20
+ ViewerAvatar,
21
+ viewerLabel,
22
+ } from "@/components/player/recording-views-badge";
19
23
  import { ViewedByPopover } from "@/components/sharing/viewed-by-popover";
20
- import { Avatar, AvatarFallback } from "@/components/ui/avatar";
21
24
 
22
25
  export interface InsightsPanelProps {
23
26
  recordingId: string;
@@ -152,20 +155,13 @@ export function InsightsPanel({ recordingId, durationMs }: InsightsPanelProps) {
152
155
  {viewers.slice(0, 12).map((v, i) => (
153
156
  <div
154
157
  key={i}
155
- className="flex items-center gap-2 rounded-full border border-border bg-card pr-3 pl-0.5 py-0.5"
158
+ className="flex items-center gap-2 rounded-full border border-border bg-card pe-3 ps-0.5 py-0.5"
156
159
  title={v.viewerEmail ?? t("recordingInsights.anonymous")}
157
160
  >
158
- <Avatar className="h-6 w-6">
159
- <AvatarFallback className="text-[10px] bg-primary text-primary-foreground">
160
- {initials(v.viewerName || v.viewerEmail || "?")}
161
- </AvatarFallback>
162
- </Avatar>
161
+ <ViewerAvatar viewer={v} />
163
162
  <span className="text-xs">
164
- {v.viewerName ||
165
- (v.viewerEmail
166
- ? v.viewerEmail.split("@")[0]
167
- : t("recordingInsights.anon"))}
168
- <span className="text-muted-foreground ml-1">
163
+ {viewerLabel(v, t("recordingInsights.anonymous"))}
164
+ <span className="text-muted-foreground ms-1">
169
165
  {Math.round(v.completedPct)}%
170
166
  </span>
171
167
  </span>
@@ -207,14 +203,6 @@ function Stat({
207
203
  );
208
204
  }
209
205
 
210
- function initials(s: string): string {
211
- return s
212
- .split(/\s+|@/)
213
- .slice(0, 2)
214
- .map((p) => p[0]?.toUpperCase() ?? "")
215
- .join("");
216
- }
217
-
218
206
  function msCompact(ms: number): string {
219
207
  const s = Math.floor(ms / 1000);
220
208
  const m = Math.floor(s / 60);
@@ -0,0 +1,335 @@
1
+ import { useActionQuery } from "@agent-native/core/client/hooks";
2
+ import { useT } from "@agent-native/core/client/i18n";
3
+ import { IconTerminal2, IconUser } from "@tabler/icons-react";
4
+ import { useState } from "react";
5
+
6
+ import { Avatar, AvatarFallback } from "@/components/ui/avatar";
7
+ import { Button } from "@/components/ui/button";
8
+ import {
9
+ Popover,
10
+ PopoverContent,
11
+ PopoverTrigger,
12
+ } from "@/components/ui/popover";
13
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
14
+ import { cn } from "@/lib/utils";
15
+
16
+ interface ViewerRow {
17
+ id: string;
18
+ viewerEmail: string | null;
19
+ viewerName: string | null;
20
+ totalWatchMs: number;
21
+ completedPct: number;
22
+ countedView: boolean;
23
+ ctaClicked: boolean;
24
+ firstViewedAt: string | null;
25
+ lastViewedAt: string | null;
26
+ }
27
+
28
+ interface AgentViewerRow {
29
+ agentLabel: string;
30
+ views: number;
31
+ lastSeenAt: string;
32
+ }
33
+
34
+ interface Insights {
35
+ views: number;
36
+ agentViews: number;
37
+ agentViewers: AgentViewerRow[];
38
+ uniqueViewers: number;
39
+ completionRate: number;
40
+ ctaConversionRate: number;
41
+ dropOff: { bucket: number; watching: number }[];
42
+ topViewers: {
43
+ viewerEmail: string | null;
44
+ viewerName: string | null;
45
+ totalWatchMs: number;
46
+ completedPct: number;
47
+ }[];
48
+ durationMs: number;
49
+ }
50
+
51
+ export interface RecordingViewsBadgeProps {
52
+ recordingId: string;
53
+ /** Public counted-view total. Rendered as-is when details are unavailable. */
54
+ viewCount: number;
55
+ /** True only for owner/editor — gates avatars, the popover, and all viewer identities. */
56
+ canViewDetails: boolean;
57
+ /** Optional: called by the popover's "More insights" button. Omit to hide that button. */
58
+ onOpenInsights?: () => void;
59
+ className?: string;
60
+ }
61
+
62
+ /**
63
+ * Header-sized view counter. Viewer identities are owner/editor-only, so a
64
+ * visitor gets plain text and fires no viewer queries at all — `canViewDetails`
65
+ * is the client half of the server-side access check on `list-viewers`.
66
+ */
67
+ export function RecordingViewsBadge({
68
+ recordingId,
69
+ viewCount,
70
+ canViewDetails,
71
+ onOpenInsights,
72
+ className,
73
+ }: RecordingViewsBadgeProps): React.ReactElement | null {
74
+ const t = useT();
75
+ const [open, setOpen] = useState(false);
76
+
77
+ const viewersQuery = useActionQuery<{ viewers: ViewerRow[] }>(
78
+ "list-viewers",
79
+ { recordingId, limit: 12 },
80
+ { enabled: canViewDetails },
81
+ );
82
+ const insightsQuery = useActionQuery<Insights>(
83
+ "get-recording-insights",
84
+ { recordingId },
85
+ { enabled: canViewDetails && open },
86
+ );
87
+
88
+ const countLabel = t("recordingInsights.viewsCount", { count: viewCount });
89
+
90
+ if (viewCount <= 0 && !canViewDetails) return null;
91
+
92
+ if (!canViewDetails) {
93
+ return (
94
+ <span
95
+ className={cn("text-sm text-muted-foreground tabular-nums", className)}
96
+ >
97
+ {countLabel}
98
+ </span>
99
+ );
100
+ }
101
+
102
+ const viewers = viewersQuery.data?.viewers ?? [];
103
+ const insights = insightsQuery.data;
104
+ const agentViewers = insights?.agentViewers ?? [];
105
+ const summary = insights
106
+ ? t("recordingInsights.totalViewsSummary", {
107
+ total: insights.views,
108
+ unique: insights.uniqueViewers,
109
+ })
110
+ : countLabel;
111
+
112
+ return (
113
+ <Popover open={open} onOpenChange={setOpen}>
114
+ <PopoverTrigger asChild onClick={(e) => e.stopPropagation()}>
115
+ <button
116
+ type="button"
117
+ className={cn(
118
+ "inline-flex cursor-pointer items-center gap-2 rounded-full border border-border bg-card px-2 py-1 text-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground",
119
+ className,
120
+ )}
121
+ >
122
+ {viewers.length > 0 ? (
123
+ <span className="hidden -space-x-1.5 sm:flex">
124
+ {viewers.slice(0, 3).map((v) => (
125
+ <ViewerAvatar
126
+ key={v.id}
127
+ viewer={v}
128
+ className="h-6 w-6 ring-2 ring-card"
129
+ />
130
+ ))}
131
+ </span>
132
+ ) : null}
133
+ <span className="tabular-nums">{countLabel}</span>
134
+ </button>
135
+ </PopoverTrigger>
136
+ <PopoverContent
137
+ align="end"
138
+ className="w-80 p-0"
139
+ onClick={(e) => e.stopPropagation()}
140
+ >
141
+ <Tabs defaultValue="views">
142
+ <div className="p-2 pb-0">
143
+ <TabsList className="grid h-8 w-full grid-cols-2">
144
+ <TabsTrigger value="views" className="text-xs">
145
+ {t("recordingInsights.viewsTab")}
146
+ </TabsTrigger>
147
+ <TabsTrigger value="insights" className="text-xs">
148
+ {t("recordingInsights.insightsTab")}
149
+ </TabsTrigger>
150
+ </TabsList>
151
+ </div>
152
+
153
+ <TabsContent value="views" className="mt-2">
154
+ <div className="border-y border-border px-3 py-2 text-xs text-muted-foreground">
155
+ {summary}
156
+ </div>
157
+ <div className="max-h-80 overflow-y-auto p-1.5">
158
+ <p className="px-2 pt-1 pb-1.5 text-xs font-medium text-muted-foreground">
159
+ {t("recordingInsights.humanViews")}
160
+ </p>
161
+ {viewersQuery.isLoading ? (
162
+ <p className="px-2 py-3 text-sm text-muted-foreground">
163
+ {t("recordingInsights.loading")}
164
+ </p>
165
+ ) : viewers.length === 0 ? (
166
+ <p className="px-2 py-3 text-sm text-muted-foreground">
167
+ {t("recordingInsights.noViewsYet")}
168
+ </p>
169
+ ) : (
170
+ <ul className="space-y-0.5">
171
+ {viewers.map((v) => (
172
+ <li
173
+ key={v.id}
174
+ className="flex items-center gap-2 rounded-md px-2 py-1.5"
175
+ >
176
+ <ViewerAvatar viewer={v} />
177
+ <span className="min-w-0 flex-1 truncate text-sm text-foreground">
178
+ {viewerLabel(v, t("recordingInsights.anonymous"))}
179
+ </span>
180
+ <span className="shrink-0 text-xs text-muted-foreground tabular-nums">
181
+ {Math.round(v.completedPct)}%
182
+ </span>
183
+ </li>
184
+ ))}
185
+ </ul>
186
+ )}
187
+
188
+ <p className="mt-2 border-t border-border px-2 pt-2.5 pb-1.5 text-xs font-medium text-muted-foreground">
189
+ {t("recordingInsights.agentViews")}
190
+ </p>
191
+ {agentViewers.length === 0 ? (
192
+ <p className="px-2 py-1.5 text-sm text-muted-foreground">
193
+ {t("recordingInsights.noAgentViewsYet")}
194
+ </p>
195
+ ) : (
196
+ <ul className="space-y-0.5">
197
+ {agentViewers.map((a) => (
198
+ <li
199
+ key={a.agentLabel}
200
+ className="flex items-center gap-2 rounded-md px-2 py-1.5"
201
+ >
202
+ <span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
203
+ <IconTerminal2 className="h-3.5 w-3.5" />
204
+ </span>
205
+ <span className="min-w-0 flex-1 truncate text-sm text-foreground">
206
+ {a.agentLabel}
207
+ </span>
208
+ <span className="shrink-0 text-xs text-muted-foreground tabular-nums">
209
+ {t("recordingInsights.viewsCount", { count: a.views })}
210
+ </span>
211
+ </li>
212
+ ))}
213
+ </ul>
214
+ )}
215
+ </div>
216
+ </TabsContent>
217
+
218
+ <TabsContent value="insights" className="mt-2 space-y-3 p-3 pt-1">
219
+ {insightsQuery.isLoading ? (
220
+ <p className="py-3 text-sm text-muted-foreground">
221
+ {t("recordingInsights.loading")}
222
+ </p>
223
+ ) : (
224
+ <>
225
+ <div className="grid grid-cols-2 gap-2">
226
+ <StatCard
227
+ label={t("recordingInsights.humanViews")}
228
+ value={insights?.views ?? viewCount}
229
+ />
230
+ <StatCard
231
+ label={t("recordingInsights.agentViews")}
232
+ value={insights?.agentViews ?? 0}
233
+ />
234
+ </div>
235
+ <div className="grid grid-cols-3 gap-2 text-xs text-muted-foreground">
236
+ <MiniStat
237
+ label={t("recordingInsights.uniqueViewers")}
238
+ value={insights?.uniqueViewers ?? 0}
239
+ />
240
+ <MiniStat
241
+ label={t("recordingInsights.completion")}
242
+ value={`${Math.round(insights?.completionRate ?? 0)}%`}
243
+ />
244
+ <MiniStat
245
+ label={t("recordingInsights.ctaConversion")}
246
+ value={`${Math.round(insights?.ctaConversionRate ?? 0)}%`}
247
+ />
248
+ </div>
249
+ </>
250
+ )}
251
+ {onOpenInsights ? (
252
+ <Button
253
+ type="button"
254
+ variant="outline"
255
+ size="sm"
256
+ className="w-full cursor-pointer"
257
+ onClick={() => {
258
+ setOpen(false);
259
+ onOpenInsights();
260
+ }}
261
+ >
262
+ {t("recordingInsights.moreInsights")}
263
+ </Button>
264
+ ) : null}
265
+ </TabsContent>
266
+ </Tabs>
267
+ </PopoverContent>
268
+ </Popover>
269
+ );
270
+ }
271
+
272
+ /** Identity fields every viewer surface shares — `list-viewers` rows and the
273
+ * leaner `topViewers` rows from `get-recording-insights` alike. */
274
+ export interface ViewerIdentity {
275
+ viewerEmail: string | null;
276
+ viewerName: string | null;
277
+ }
278
+
279
+ export function ViewerAvatar({
280
+ viewer,
281
+ className,
282
+ }: {
283
+ viewer: ViewerIdentity;
284
+ className?: string;
285
+ }) {
286
+ const anonymous = !viewer.viewerName && !viewer.viewerEmail;
287
+ return (
288
+ <Avatar className={cn("h-6 w-6 shrink-0", className)}>
289
+ <AvatarFallback className="bg-primary text-[10px] text-primary-foreground">
290
+ {anonymous ? (
291
+ <IconUser className="h-3 w-3" />
292
+ ) : (
293
+ initials(viewer.viewerName || viewer.viewerEmail || "?")
294
+ )}
295
+ </AvatarFallback>
296
+ </Avatar>
297
+ );
298
+ }
299
+
300
+ function MiniStat({ label, value }: { label: string; value: string | number }) {
301
+ return (
302
+ <div className="min-w-0">
303
+ <div className="truncate">{label}</div>
304
+ <div className="mt-0.5 text-foreground tabular-nums">{value}</div>
305
+ </div>
306
+ );
307
+ }
308
+
309
+ function StatCard({ label, value }: { label: string; value: string | number }) {
310
+ return (
311
+ <div className="rounded-lg border border-border bg-card p-2.5">
312
+ <div className="text-xs text-muted-foreground">{label}</div>
313
+ <div className="mt-0.5 text-xl font-semibold text-foreground tabular-nums">
314
+ {value}
315
+ </div>
316
+ </div>
317
+ );
318
+ }
319
+
320
+ export function viewerLabel(
321
+ viewer: ViewerIdentity,
322
+ anonymousLabel: string,
323
+ ): string {
324
+ if (viewer.viewerName) return viewer.viewerName;
325
+ if (viewer.viewerEmail) return viewer.viewerEmail.split("@")[0];
326
+ return anonymousLabel;
327
+ }
328
+
329
+ function initials(s: string): string {
330
+ return s
331
+ .split(/\s+|@/)
332
+ .slice(0, 2)
333
+ .map((p) => p[0]?.toUpperCase() ?? "")
334
+ .join("");
335
+ }
@@ -1400,7 +1400,10 @@ export const VideoPlayer = forwardRef<VideoPlayerHandle, VideoPlayerProps>(
1400
1400
  v,
1401
1401
  resolvedDurationMs,
1402
1402
  );
1403
- if (visibleMs !== ms) {
1403
+ // Only ever correct forward (skipping a trimmed range). Seeking
1404
+ // backwards here flushes the decode pipeline and replays from the
1405
+ // previous keyframe, which reads as a stutter with a buffering flash.
1406
+ if (visibleMs > ms) {
1404
1407
  v.currentTime = visibleMs / 1000;
1405
1408
  setCurrentMs(visibleMs);
1406
1409
  if (visibleMs > 0) {
@@ -1815,21 +1818,23 @@ function CenterPlaybackOverlay({
1815
1818
  * trustworthy finite number we have — preferring the resolved duration from
1816
1819
  * the player, then falling back to `video.duration`, then the seekable range.
1817
1820
  */
1818
- function clampSeek(
1821
+ export function clampSeek(
1819
1822
  ms: number,
1820
1823
  v: HTMLVideoElement,
1821
1824
  resolvedDurationMs: number,
1822
1825
  ): number {
1823
- let maxSec = Number.POSITIVE_INFINITY;
1826
+ // Clamp in integer milliseconds. Routing through seconds and back loses 1ms
1827
+ // for ~1% of integer inputs (1001 -> 1000), which the timeupdate handler
1828
+ // would then "correct" by seeking the player backwards.
1829
+ let maxMs = Number.POSITIVE_INFINITY;
1824
1830
  if (resolvedDurationMs > 0) {
1825
- maxSec = resolvedDurationMs / 1000;
1831
+ maxMs = resolvedDurationMs;
1826
1832
  } else if (Number.isFinite(v.duration) && v.duration > 0) {
1827
- maxSec = v.duration;
1833
+ maxMs = v.duration * 1000;
1828
1834
  } else if (v.seekable && v.seekable.length > 0) {
1829
- maxSec = v.seekable.end(v.seekable.length - 1);
1835
+ maxMs = v.seekable.end(v.seekable.length - 1) * 1000;
1830
1836
  }
1831
- const sec = Math.max(0, Math.min(maxSec, ms / 1000));
1832
- return Math.floor(sec * 1000);
1837
+ return Math.floor(Math.max(0, Math.min(maxMs, ms)));
1833
1838
  }
1834
1839
 
1835
1840
  function skipExcludedRange(
@@ -1,3 +1,4 @@
1
+ import { writeClipboardText } from "@agent-native/core/client/clipboard";
1
2
  import {
2
3
  useActionMutation,
3
4
  useActionQuery,
@@ -70,7 +71,7 @@ export const ROLE_OPTIONS: Array<{ value: Role; label: string }> = [
70
71
  ];
71
72
 
72
73
  export function copyToClipboard(value: string): void {
73
- navigator.clipboard.writeText(value).catch(() => {});
74
+ void writeClipboardText(value);
74
75
  }
75
76
 
76
77
  // ---------------------------------------------------------------------------
@@ -288,7 +288,6 @@ const messages = {
288
288
  storageConnectedChecking: "Storage connected. Checking this clip...",
289
289
  signInToFinish: "Sign in to finish",
290
290
  signInIfYours: "Sign in if this is yours",
291
- openDashboard: "Open dashboard",
292
291
  checkAgain: "Check again",
293
292
  backToHome: "Back to home",
294
293
  generatingTitle: "Generating title",
@@ -807,11 +806,21 @@ All notable user-facing changes to Clips are documented here. Open it any time f
807
806
  recentViewers: "Recent viewers",
808
807
  noViewers: "No viewers yet.",
809
808
  anonymous: "Anonymous",
810
- anon: "Anon",
811
809
  moreViewers: "+{{count}} more",
812
810
  viewedBy: "Viewed by",
813
811
  someone: "Someone",
814
812
  noViewsYet: "No views yet.",
813
+ viewsCount_one: "{{count}} view",
814
+ viewsCount_other: "{{count}} views",
815
+ totalViewsSummary: "{{total}} total views, {{unique}} unique viewers",
816
+ viewsTab: "Views",
817
+ insightsTab: "Insights",
818
+ humanViews: "Human views",
819
+ agentViews: "Agent views",
820
+ noAgentViewsYet: "No agent views yet.",
821
+ totalVideoViews: "Total video views",
822
+ averageCompletionRate: "Average completion rate",
823
+ moreInsights: "More insights",
815
824
  },
816
825
  libraryGrid: {
817
826
  spaceRoot: "Space root",
@@ -1291,6 +1300,8 @@ All notable user-facing changes to Clips are documented here. Open it any time f
1291
1300
  couldNotImportLoom: "Could not import that Loom.",
1292
1301
  recordingReadyToUpload: "Recording is ready to upload",
1293
1302
  recordingSaved: "Recording saved",
1303
+ linkCopied: "Link copied",
1304
+ copyLinkAction: "Copy link",
1294
1305
  noLocalRecordingData: "No local recording data is available to download.",
1295
1306
  recordingDownloadStarted: "Recording download started",
1296
1307
  backToLibrary: "Back to library",