@agent-native/core 0.98.17 → 0.99.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 (545) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +15 -0
  3. package/corpus/core/docs/content/actions.mdx +1 -1
  4. package/corpus/core/docs/content/authentication.mdx +1 -1
  5. package/corpus/core/docs/content/dispatch.mdx +3 -3
  6. package/corpus/core/docs/content/external-agents.mdx +30 -19
  7. package/corpus/core/docs/content/locales/ar-SA/actions.mdx +1 -1
  8. package/corpus/core/docs/content/locales/ar-SA/authentication.mdx +1 -1
  9. package/corpus/core/docs/content/locales/ar-SA/dispatch.mdx +3 -3
  10. package/corpus/core/docs/content/locales/ar-SA/external-agents.mdx +23 -19
  11. package/corpus/core/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
  12. package/corpus/core/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
  13. package/corpus/core/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
  14. package/corpus/core/docs/content/locales/ar-SA/server.mdx +2 -2
  15. package/corpus/core/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
  16. package/corpus/core/docs/content/locales/ar-SA/template-assets.mdx +1 -1
  17. package/corpus/core/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
  18. package/corpus/core/docs/content/locales/ar-SA/template-plan.mdx +3 -3
  19. package/corpus/core/docs/content/locales/de-DE/actions.mdx +1 -1
  20. package/corpus/core/docs/content/locales/de-DE/authentication.mdx +1 -1
  21. package/corpus/core/docs/content/locales/de-DE/dispatch.mdx +3 -3
  22. package/corpus/core/docs/content/locales/de-DE/external-agents.mdx +23 -19
  23. package/corpus/core/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
  24. package/corpus/core/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
  25. package/corpus/core/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
  26. package/corpus/core/docs/content/locales/de-DE/server.mdx +2 -2
  27. package/corpus/core/docs/content/locales/de-DE/skills-guide.mdx +1 -1
  28. package/corpus/core/docs/content/locales/de-DE/template-assets.mdx +1 -1
  29. package/corpus/core/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
  30. package/corpus/core/docs/content/locales/de-DE/template-plan.mdx +3 -3
  31. package/corpus/core/docs/content/locales/es-ES/actions.mdx +1 -1
  32. package/corpus/core/docs/content/locales/es-ES/authentication.mdx +1 -1
  33. package/corpus/core/docs/content/locales/es-ES/dispatch.mdx +3 -3
  34. package/corpus/core/docs/content/locales/es-ES/external-agents.mdx +32 -19
  35. package/corpus/core/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
  36. package/corpus/core/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
  37. package/corpus/core/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
  38. package/corpus/core/docs/content/locales/es-ES/server.mdx +2 -2
  39. package/corpus/core/docs/content/locales/es-ES/skills-guide.mdx +1 -1
  40. package/corpus/core/docs/content/locales/es-ES/template-assets.mdx +1 -1
  41. package/corpus/core/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
  42. package/corpus/core/docs/content/locales/es-ES/template-plan.mdx +3 -3
  43. package/corpus/core/docs/content/locales/fr-FR/actions.mdx +1 -1
  44. package/corpus/core/docs/content/locales/fr-FR/authentication.mdx +1 -1
  45. package/corpus/core/docs/content/locales/fr-FR/dispatch.mdx +3 -3
  46. package/corpus/core/docs/content/locales/fr-FR/external-agents.mdx +23 -19
  47. package/corpus/core/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
  48. package/corpus/core/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
  49. package/corpus/core/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
  50. package/corpus/core/docs/content/locales/fr-FR/server.mdx +2 -2
  51. package/corpus/core/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
  52. package/corpus/core/docs/content/locales/fr-FR/template-assets.mdx +1 -1
  53. package/corpus/core/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
  54. package/corpus/core/docs/content/locales/fr-FR/template-plan.mdx +3 -3
  55. package/corpus/core/docs/content/locales/hi-IN/actions.mdx +1 -1
  56. package/corpus/core/docs/content/locales/hi-IN/authentication.mdx +1 -1
  57. package/corpus/core/docs/content/locales/hi-IN/dispatch.mdx +3 -3
  58. package/corpus/core/docs/content/locales/hi-IN/external-agents.mdx +31 -19
  59. package/corpus/core/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
  60. package/corpus/core/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
  61. package/corpus/core/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
  62. package/corpus/core/docs/content/locales/hi-IN/server.mdx +2 -2
  63. package/corpus/core/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
  64. package/corpus/core/docs/content/locales/hi-IN/template-assets.mdx +1 -1
  65. package/corpus/core/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
  66. package/corpus/core/docs/content/locales/hi-IN/template-plan.mdx +3 -3
  67. package/corpus/core/docs/content/locales/ja-JP/actions.mdx +1 -1
  68. package/corpus/core/docs/content/locales/ja-JP/authentication.mdx +1 -1
  69. package/corpus/core/docs/content/locales/ja-JP/dispatch.mdx +3 -3
  70. package/corpus/core/docs/content/locales/ja-JP/external-agents.mdx +23 -19
  71. package/corpus/core/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
  72. package/corpus/core/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
  73. package/corpus/core/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
  74. package/corpus/core/docs/content/locales/ja-JP/server.mdx +2 -2
  75. package/corpus/core/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
  76. package/corpus/core/docs/content/locales/ja-JP/template-assets.mdx +1 -1
  77. package/corpus/core/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
  78. package/corpus/core/docs/content/locales/ja-JP/template-plan.mdx +3 -3
  79. package/corpus/core/docs/content/locales/ko-KR/actions.mdx +1 -1
  80. package/corpus/core/docs/content/locales/ko-KR/authentication.mdx +1 -1
  81. package/corpus/core/docs/content/locales/ko-KR/dispatch.mdx +3 -3
  82. package/corpus/core/docs/content/locales/ko-KR/external-agents.mdx +30 -19
  83. package/corpus/core/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
  84. package/corpus/core/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
  85. package/corpus/core/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
  86. package/corpus/core/docs/content/locales/ko-KR/server.mdx +2 -2
  87. package/corpus/core/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
  88. package/corpus/core/docs/content/locales/ko-KR/template-assets.mdx +1 -1
  89. package/corpus/core/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
  90. package/corpus/core/docs/content/locales/ko-KR/template-plan.mdx +3 -3
  91. package/corpus/core/docs/content/locales/pt-BR/actions.mdx +1 -1
  92. package/corpus/core/docs/content/locales/pt-BR/authentication.mdx +1 -1
  93. package/corpus/core/docs/content/locales/pt-BR/dispatch.mdx +3 -3
  94. package/corpus/core/docs/content/locales/pt-BR/external-agents.mdx +32 -19
  95. package/corpus/core/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
  96. package/corpus/core/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
  97. package/corpus/core/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
  98. package/corpus/core/docs/content/locales/pt-BR/server.mdx +2 -2
  99. package/corpus/core/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
  100. package/corpus/core/docs/content/locales/pt-BR/template-assets.mdx +1 -1
  101. package/corpus/core/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
  102. package/corpus/core/docs/content/locales/pt-BR/template-plan.mdx +3 -3
  103. package/corpus/core/docs/content/locales/zh-CN/actions.mdx +1 -1
  104. package/corpus/core/docs/content/locales/zh-CN/authentication.mdx +1 -1
  105. package/corpus/core/docs/content/locales/zh-CN/dispatch.mdx +3 -3
  106. package/corpus/core/docs/content/locales/zh-CN/external-agents.mdx +23 -19
  107. package/corpus/core/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
  108. package/corpus/core/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
  109. package/corpus/core/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
  110. package/corpus/core/docs/content/locales/zh-CN/server.mdx +2 -2
  111. package/corpus/core/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
  112. package/corpus/core/docs/content/locales/zh-CN/template-assets.mdx +1 -1
  113. package/corpus/core/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
  114. package/corpus/core/docs/content/locales/zh-CN/template-plan.mdx +3 -3
  115. package/corpus/core/docs/content/locales/zh-TW/actions.mdx +1 -1
  116. package/corpus/core/docs/content/locales/zh-TW/authentication.mdx +1 -1
  117. package/corpus/core/docs/content/locales/zh-TW/dispatch.mdx +3 -3
  118. package/corpus/core/docs/content/locales/zh-TW/external-agents.mdx +23 -19
  119. package/corpus/core/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
  120. package/corpus/core/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
  121. package/corpus/core/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
  122. package/corpus/core/docs/content/locales/zh-TW/server.mdx +2 -2
  123. package/corpus/core/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
  124. package/corpus/core/docs/content/locales/zh-TW/template-assets.mdx +1 -1
  125. package/corpus/core/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
  126. package/corpus/core/docs/content/locales/zh-TW/template-plan.mdx +3 -3
  127. package/corpus/core/docs/content/mcp-clients.mdx +31 -4
  128. package/corpus/core/docs/content/mcp-protocol.mdx +35 -15
  129. package/corpus/core/docs/content/plan-plugin.mdx +3 -3
  130. package/corpus/core/docs/content/server.mdx +2 -2
  131. package/corpus/core/docs/content/skills-guide.mdx +1 -1
  132. package/corpus/core/docs/content/template-assets.mdx +1 -1
  133. package/corpus/core/docs/content/template-dispatch.mdx +2 -2
  134. package/corpus/core/docs/content/template-plan.mdx +3 -3
  135. package/corpus/core/package.json +1 -1
  136. package/corpus/core/src/a2a/client.ts +3 -0
  137. package/corpus/core/src/a2a/handlers.ts +95 -7
  138. package/corpus/core/src/cli/connect.ts +50 -24
  139. package/corpus/core/src/cli/mcp-config-writers.ts +10 -0
  140. package/corpus/core/src/cli/mcp.ts +5 -5
  141. package/corpus/core/src/cli/skills-content/assets-skill.ts +1 -1
  142. package/corpus/core/src/cli/skills-content/design-exploration-skill.ts +1 -1
  143. package/corpus/core/src/cli/skills-content/help.ts +1 -1
  144. package/corpus/core/src/cli/skills-content/plan-setup-auth.ts +1 -1
  145. package/corpus/core/src/cli/skills-content/visual-plan-skill.ts +1 -1
  146. package/corpus/core/src/cli/skills-content/visual-recap-skill.ts +2 -2
  147. package/corpus/core/src/cli/skills.ts +23 -12
  148. package/corpus/core/src/client/resources/McpIntegrationDialog.tsx +5 -0
  149. package/corpus/core/src/client/resources/mcp-integration-catalog.ts +17 -0
  150. package/corpus/core/src/embedding/agent.ts +8 -6
  151. package/corpus/core/src/localization/default-messages.ts +7 -0
  152. package/corpus/core/src/mcp/ask-app-inline-tasks.ts +125 -0
  153. package/corpus/core/src/mcp/build-server.ts +65 -3
  154. package/corpus/core/src/mcp/builtin-tools.ts +186 -22
  155. package/corpus/core/src/mcp/connect-route.ts +17 -14
  156. package/corpus/core/src/mcp/oauth-route.ts +38 -13
  157. package/corpus/core/src/mcp/route-paths.ts +34 -0
  158. package/corpus/core/src/mcp/server.ts +21 -10
  159. package/corpus/core/src/mcp/stdio.ts +34 -16
  160. package/corpus/core/src/mcp/workspace-resolve.ts +2 -1
  161. package/corpus/core/src/mcp-client/manager.ts +5 -3
  162. package/corpus/core/src/mcp-client/remote-store.ts +10 -10
  163. package/corpus/core/src/server/agent-chat-plugin.ts +42 -9
  164. package/corpus/core/src/server/auth.ts +22 -6
  165. package/corpus/core/src/server/core-routes-plugin.ts +30 -24
  166. package/corpus/core/src/server/csrf.ts +17 -0
  167. package/corpus/core/src/server/framework-request-handler.ts +8 -2
  168. package/corpus/core/src/server/google-oauth.ts +6 -0
  169. package/corpus/core/src/server/http-response-telemetry.ts +6 -1
  170. package/corpus/core/src/server/recap-image-route.ts +3 -3
  171. package/corpus/core/src/server/security-headers.ts +7 -1
  172. package/corpus/core/src/server/ssr-handler.ts +2 -0
  173. package/corpus/core/src/shared/cache-control.ts +6 -4
  174. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +10 -0
  175. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  176. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  177. package/corpus/core/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  178. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
  179. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +10 -0
  180. package/corpus/templates/analytics/app/global.css +63 -4
  181. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +8 -5
  182. package/corpus/templates/analytics/changelog/2026-07-13-daily-dashboard-emails-recover-more-reliably-from-serverless.md +6 -0
  183. package/corpus/templates/analytics/changelog/2026-07-13-session-replays-keep-a-visible-mac-style-cursor-over-the-vis.md +6 -0
  184. package/corpus/templates/analytics/server/jobs/dashboard-report.ts +21 -2
  185. package/corpus/templates/analytics/server/lib/dashboard-report-subscriptions.ts +57 -1
  186. package/corpus/templates/analytics/server/lib/dashboard-report.ts +266 -28
  187. package/corpus/templates/analytics/server/routes/[...page].get.ts +0 -2
  188. package/corpus/templates/assets/.agents/skills/security/SKILL.md +10 -0
  189. package/corpus/templates/assets/agent-native.app-skill.json +1 -1
  190. package/corpus/templates/brain/.agents/skills/security/SKILL.md +10 -0
  191. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +10 -0
  192. package/corpus/templates/calendar/AGENTS.md +2 -1
  193. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +0 -19
  194. package/corpus/templates/calendar/app/lib/attendee-local-time.ts +14 -5
  195. package/corpus/templates/calendar/changelog/2026-07-13-your-local-time-now-follows-your-browser-timezone-and-event-.md +6 -0
  196. package/corpus/templates/chat/.agents/skills/security/SKILL.md +10 -0
  197. package/corpus/templates/clips/.agents/skills/recording/SKILL.md +7 -2
  198. package/corpus/templates/clips/.agents/skills/security/SKILL.md +10 -0
  199. package/corpus/templates/clips/AGENTS.md +7 -0
  200. package/corpus/templates/clips/actions/list-meetings.ts +19 -4
  201. package/corpus/templates/clips/actions/start-meeting-recording.ts +7 -1
  202. package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +75 -78
  203. package/corpus/templates/clips/app/components/recorder/confetti-canvas.tsx +18 -1
  204. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +6 -12
  205. package/corpus/templates/clips/app/components/recorder/recording-toolbar.tsx +19 -2
  206. package/corpus/templates/clips/app/lib/camera-composite.ts +70 -10
  207. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +1 -1
  208. package/corpus/templates/clips/app/routes/record.tsx +5 -25
  209. package/corpus/templates/clips/changelog/2026-07-13-clips-desktop-now-requires-macos-13-for-native-capture.md +6 -0
  210. package/corpus/templates/clips/changelog/2026-07-13-clips-hide-solo-meeting-reminders.md +6 -0
  211. package/corpus/templates/clips/changelog/2026-07-13-clips-now-removes-duplicate-mic-and-system-transcript-turns-.md +6 -0
  212. package/corpus/templates/clips/changelog/2026-07-13-desktop-recordings-run-cooler-and-quieter-live-transcription.md +6 -0
  213. package/corpus/templates/clips/changelog/2026-07-13-meeting-recordings-now-stop-after-a-calendar-meeting-ends-an.md +6 -0
  214. package/corpus/templates/clips/changelog/2026-07-13-meeting-transcripts-now-use-a-clean-agent-chat-style-reading.md +6 -0
  215. package/corpus/templates/clips/changelog/2026-07-13-screen-recordings-use-less-processing-power-during-longer-ca.md +6 -0
  216. package/corpus/templates/clips/chrome-extension/src/background.ts +5 -3
  217. package/corpus/templates/clips/chrome-extension/src/offscreen.ts +17 -14
  218. package/corpus/templates/clips/chrome-extension/src/overlay.ts +8 -2
  219. package/corpus/templates/clips/desktop/README.md +3 -0
  220. package/corpus/templates/clips/desktop/src/hooks/useMeetingTranscription.ts +9 -0
  221. package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -2
  222. package/corpus/templates/clips/desktop/src/lib/silence-events.ts +1 -0
  223. package/corpus/templates/clips/desktop/src/lib/transcription-capture.ts +5 -0
  224. package/corpus/templates/clips/desktop/src/lib/transcription-engine.ts +134 -5
  225. package/corpus/templates/clips/desktop/src/lib/upload-video-stream.ts +28 -0
  226. package/corpus/templates/clips/desktop/src/overlays/flow-bar.tsx +10 -3
  227. package/corpus/templates/clips/desktop/src/overlays/meeting-notification.tsx +42 -9
  228. package/corpus/templates/clips/desktop/src/overlays/recording-pill.tsx +10 -2
  229. package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +6 -1
  230. package/corpus/templates/clips/desktop/src-tauri/src/notifications.rs +77 -1
  231. package/corpus/templates/clips/desktop/src-tauri/src/silence_detector.rs +104 -25
  232. package/corpus/templates/clips/desktop/src-tauri/src/system_audio.rs +4 -0
  233. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +287 -32
  234. package/corpus/templates/clips/desktop/src-tauri/tauri.conf.json +1 -1
  235. package/corpus/templates/clips/server/lib/calendar-event-classification.ts +28 -0
  236. package/corpus/templates/clips/server/routes/[...page].get.ts +1 -59
  237. package/corpus/templates/clips/shared/recording-capture.ts +37 -0
  238. package/corpus/templates/content/.agents/skills/security/SKILL.md +10 -0
  239. package/corpus/templates/content/agent-native.app-skill.json +1 -1
  240. package/corpus/templates/content/server/routes/[...page].get.ts +1 -15
  241. package/corpus/templates/design/.agents/skills/security/SKILL.md +10 -0
  242. package/corpus/templates/design/actions/connect-assets-mcp.ts +1 -1
  243. package/corpus/templates/design/agent-native.app-skill.json +1 -1
  244. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +88 -12
  245. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +1 -0
  246. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +4 -1
  247. package/corpus/templates/design/changelog/2026-07-13-adding-shapes-preserves-canvas-background.md +6 -0
  248. package/corpus/templates/design/changelog/2026-07-13-clicking-quickly-between-overlapping-elements-no-longer-bounc.md +6 -0
  249. package/corpus/templates/design/server/plugins/assets-mcp.ts +1 -1
  250. package/corpus/templates/design/server/routes/[...page].get.ts +0 -2
  251. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +10 -0
  252. package/corpus/templates/forms/.agents/skills/security/SKILL.md +10 -0
  253. package/corpus/templates/macros/.agents/skills/security/SKILL.md +10 -0
  254. package/corpus/templates/mail/.agents/skills/security/SKILL.md +10 -0
  255. package/corpus/templates/plan/.agents/skills/security/SKILL.md +10 -0
  256. package/corpus/templates/plan/.agents/skills/visual-plan/SKILL.md +1 -1
  257. package/corpus/templates/plan/.agents/skills/visual-recap/SKILL.md +2 -2
  258. package/corpus/templates/plan/agent-native.app-skill.json +1 -1
  259. package/corpus/templates/plan/app/lib/plan-local-bridge.ts +6 -1
  260. package/corpus/templates/plan/app/pages/PlansPage.tsx +15 -6
  261. package/corpus/templates/plan/changelog/2026-07-13-fixed-local-plan-previews-continuously-flickering-while-revi.md +6 -0
  262. package/corpus/templates/plan/server/routes/[...page].get.ts +0 -2
  263. package/corpus/templates/slides/.agents/skills/security/SKILL.md +10 -0
  264. package/dist/a2a/client.d.ts +2 -0
  265. package/dist/a2a/client.d.ts.map +1 -1
  266. package/dist/a2a/client.js +2 -0
  267. package/dist/a2a/client.js.map +1 -1
  268. package/dist/a2a/handlers.d.ts.map +1 -1
  269. package/dist/a2a/handlers.js +84 -7
  270. package/dist/a2a/handlers.js.map +1 -1
  271. package/dist/cli/connect.d.ts +2 -2
  272. package/dist/cli/connect.d.ts.map +1 -1
  273. package/dist/cli/connect.js +45 -23
  274. package/dist/cli/connect.js.map +1 -1
  275. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  276. package/dist/cli/mcp-config-writers.js +7 -0
  277. package/dist/cli/mcp-config-writers.js.map +1 -1
  278. package/dist/cli/mcp.js +5 -3
  279. package/dist/cli/mcp.js.map +1 -1
  280. package/dist/cli/skills-content/assets-skill.d.ts +1 -1
  281. package/dist/cli/skills-content/assets-skill.d.ts.map +1 -1
  282. package/dist/cli/skills-content/assets-skill.js +1 -1
  283. package/dist/cli/skills-content/assets-skill.js.map +1 -1
  284. package/dist/cli/skills-content/design-exploration-skill.d.ts +1 -1
  285. package/dist/cli/skills-content/design-exploration-skill.d.ts.map +1 -1
  286. package/dist/cli/skills-content/design-exploration-skill.js +1 -1
  287. package/dist/cli/skills-content/design-exploration-skill.js.map +1 -1
  288. package/dist/cli/skills-content/help.d.ts +1 -1
  289. package/dist/cli/skills-content/help.d.ts.map +1 -1
  290. package/dist/cli/skills-content/help.js +1 -1
  291. package/dist/cli/skills-content/help.js.map +1 -1
  292. package/dist/cli/skills-content/plan-setup-auth.d.ts +1 -1
  293. package/dist/cli/skills-content/plan-setup-auth.d.ts.map +1 -1
  294. package/dist/cli/skills-content/plan-setup-auth.js +1 -1
  295. package/dist/cli/skills-content/plan-setup-auth.js.map +1 -1
  296. package/dist/cli/skills-content/visual-plan-skill.d.ts +1 -1
  297. package/dist/cli/skills-content/visual-plan-skill.d.ts.map +1 -1
  298. package/dist/cli/skills-content/visual-plan-skill.js +1 -1
  299. package/dist/cli/skills-content/visual-plan-skill.js.map +1 -1
  300. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  301. package/dist/cli/skills-content/visual-recap-skill.d.ts.map +1 -1
  302. package/dist/cli/skills-content/visual-recap-skill.js +2 -2
  303. package/dist/cli/skills-content/visual-recap-skill.js.map +1 -1
  304. package/dist/cli/skills.d.ts.map +1 -1
  305. package/dist/cli/skills.js +16 -12
  306. package/dist/cli/skills.js.map +1 -1
  307. package/dist/client/resources/McpIntegrationDialog.d.ts.map +1 -1
  308. package/dist/client/resources/McpIntegrationDialog.js +1 -1
  309. package/dist/client/resources/McpIntegrationDialog.js.map +1 -1
  310. package/dist/client/resources/mcp-integration-catalog.d.ts +1 -0
  311. package/dist/client/resources/mcp-integration-catalog.d.ts.map +1 -1
  312. package/dist/client/resources/mcp-integration-catalog.js +14 -0
  313. package/dist/client/resources/mcp-integration-catalog.js.map +1 -1
  314. package/dist/collab/routes.d.ts +2 -2
  315. package/dist/collab/struct-routes.d.ts +1 -1
  316. package/dist/embedding/agent.d.ts.map +1 -1
  317. package/dist/embedding/agent.js +6 -7
  318. package/dist/embedding/agent.js.map +1 -1
  319. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  320. package/dist/localization/default-messages.d.ts +5 -0
  321. package/dist/localization/default-messages.d.ts.map +1 -1
  322. package/dist/localization/default-messages.js +5 -0
  323. package/dist/localization/default-messages.js.map +1 -1
  324. package/dist/mcp/ask-app-inline-tasks.d.ts +47 -0
  325. package/dist/mcp/ask-app-inline-tasks.d.ts.map +1 -0
  326. package/dist/mcp/ask-app-inline-tasks.js +87 -0
  327. package/dist/mcp/ask-app-inline-tasks.js.map +1 -0
  328. package/dist/mcp/build-server.d.ts.map +1 -1
  329. package/dist/mcp/build-server.js +56 -3
  330. package/dist/mcp/build-server.js.map +1 -1
  331. package/dist/mcp/builtin-tools.d.ts.map +1 -1
  332. package/dist/mcp/builtin-tools.js +141 -21
  333. package/dist/mcp/builtin-tools.js.map +1 -1
  334. package/dist/mcp/connect-route.d.ts +12 -10
  335. package/dist/mcp/connect-route.d.ts.map +1 -1
  336. package/dist/mcp/connect-route.js +17 -14
  337. package/dist/mcp/connect-route.js.map +1 -1
  338. package/dist/mcp/oauth-route.d.ts +1 -1
  339. package/dist/mcp/oauth-route.d.ts.map +1 -1
  340. package/dist/mcp/oauth-route.js +30 -13
  341. package/dist/mcp/oauth-route.js.map +1 -1
  342. package/dist/mcp/route-paths.d.ts +13 -0
  343. package/dist/mcp/route-paths.d.ts.map +1 -0
  344. package/dist/mcp/route-paths.js +27 -0
  345. package/dist/mcp/route-paths.js.map +1 -0
  346. package/dist/mcp/server.d.ts +2 -1
  347. package/dist/mcp/server.d.ts.map +1 -1
  348. package/dist/mcp/server.js +14 -6
  349. package/dist/mcp/server.js.map +1 -1
  350. package/dist/mcp/stdio.d.ts +7 -6
  351. package/dist/mcp/stdio.d.ts.map +1 -1
  352. package/dist/mcp/stdio.js +27 -15
  353. package/dist/mcp/stdio.js.map +1 -1
  354. package/dist/mcp/workspace-resolve.d.ts +2 -1
  355. package/dist/mcp/workspace-resolve.d.ts.map +1 -1
  356. package/dist/mcp/workspace-resolve.js +2 -1
  357. package/dist/mcp/workspace-resolve.js.map +1 -1
  358. package/dist/mcp-client/manager.js +6 -3
  359. package/dist/mcp-client/manager.js.map +1 -1
  360. package/dist/mcp-client/remote-store.js +5 -7
  361. package/dist/mcp-client/remote-store.js.map +1 -1
  362. package/dist/notifications/routes.d.ts +3 -3
  363. package/dist/observability/routes.d.ts +5 -5
  364. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  365. package/dist/resources/handlers.d.ts +2 -2
  366. package/dist/secrets/routes.d.ts +9 -9
  367. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  368. package/dist/server/agent-chat-plugin.js +43 -11
  369. package/dist/server/agent-chat-plugin.js.map +1 -1
  370. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  371. package/dist/server/auth.d.ts.map +1 -1
  372. package/dist/server/auth.js +16 -6
  373. package/dist/server/auth.js.map +1 -1
  374. package/dist/server/core-routes-plugin.d.ts +4 -3
  375. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  376. package/dist/server/core-routes-plugin.js +20 -15
  377. package/dist/server/core-routes-plugin.js.map +1 -1
  378. package/dist/server/csrf.d.ts.map +1 -1
  379. package/dist/server/csrf.js +11 -0
  380. package/dist/server/csrf.js.map +1 -1
  381. package/dist/server/framework-request-handler.d.ts.map +1 -1
  382. package/dist/server/framework-request-handler.js +8 -2
  383. package/dist/server/framework-request-handler.js.map +1 -1
  384. package/dist/server/google-oauth.d.ts +2 -0
  385. package/dist/server/google-oauth.d.ts.map +1 -1
  386. package/dist/server/google-oauth.js +5 -0
  387. package/dist/server/google-oauth.js.map +1 -1
  388. package/dist/server/http-response-telemetry.d.ts.map +1 -1
  389. package/dist/server/http-response-telemetry.js +4 -1
  390. package/dist/server/http-response-telemetry.js.map +1 -1
  391. package/dist/server/recap-image-route.js +3 -3
  392. package/dist/server/recap-image-route.js.map +1 -1
  393. package/dist/server/security-headers.d.ts.map +1 -1
  394. package/dist/server/security-headers.js +4 -1
  395. package/dist/server/security-headers.js.map +1 -1
  396. package/dist/server/ssr-handler.d.ts.map +1 -1
  397. package/dist/server/ssr-handler.js +3 -1
  398. package/dist/server/ssr-handler.js.map +1 -1
  399. package/dist/shared/cache-control.d.ts +7 -6
  400. package/dist/shared/cache-control.d.ts.map +1 -1
  401. package/dist/shared/cache-control.js +4 -3
  402. package/dist/shared/cache-control.js.map +1 -1
  403. package/dist/templates/default/.agents/skills/security/SKILL.md +10 -0
  404. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  405. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  406. package/dist/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  407. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
  408. package/docs/content/actions.mdx +1 -1
  409. package/docs/content/authentication.mdx +1 -1
  410. package/docs/content/dispatch.mdx +3 -3
  411. package/docs/content/external-agents.mdx +30 -19
  412. package/docs/content/locales/ar-SA/actions.mdx +1 -1
  413. package/docs/content/locales/ar-SA/authentication.mdx +1 -1
  414. package/docs/content/locales/ar-SA/dispatch.mdx +3 -3
  415. package/docs/content/locales/ar-SA/external-agents.mdx +23 -19
  416. package/docs/content/locales/ar-SA/mcp-clients.mdx +31 -3
  417. package/docs/content/locales/ar-SA/mcp-protocol.mdx +29 -15
  418. package/docs/content/locales/ar-SA/plan-plugin.mdx +3 -3
  419. package/docs/content/locales/ar-SA/server.mdx +2 -2
  420. package/docs/content/locales/ar-SA/skills-guide.mdx +1 -1
  421. package/docs/content/locales/ar-SA/template-assets.mdx +1 -1
  422. package/docs/content/locales/ar-SA/template-dispatch.mdx +2 -2
  423. package/docs/content/locales/ar-SA/template-plan.mdx +3 -3
  424. package/docs/content/locales/de-DE/actions.mdx +1 -1
  425. package/docs/content/locales/de-DE/authentication.mdx +1 -1
  426. package/docs/content/locales/de-DE/dispatch.mdx +3 -3
  427. package/docs/content/locales/de-DE/external-agents.mdx +23 -19
  428. package/docs/content/locales/de-DE/mcp-clients.mdx +37 -3
  429. package/docs/content/locales/de-DE/mcp-protocol.mdx +29 -15
  430. package/docs/content/locales/de-DE/plan-plugin.mdx +3 -3
  431. package/docs/content/locales/de-DE/server.mdx +2 -2
  432. package/docs/content/locales/de-DE/skills-guide.mdx +1 -1
  433. package/docs/content/locales/de-DE/template-assets.mdx +1 -1
  434. package/docs/content/locales/de-DE/template-dispatch.mdx +2 -2
  435. package/docs/content/locales/de-DE/template-plan.mdx +3 -3
  436. package/docs/content/locales/es-ES/actions.mdx +1 -1
  437. package/docs/content/locales/es-ES/authentication.mdx +1 -1
  438. package/docs/content/locales/es-ES/dispatch.mdx +3 -3
  439. package/docs/content/locales/es-ES/external-agents.mdx +32 -19
  440. package/docs/content/locales/es-ES/mcp-clients.mdx +17 -3
  441. package/docs/content/locales/es-ES/mcp-protocol.mdx +38 -15
  442. package/docs/content/locales/es-ES/plan-plugin.mdx +3 -3
  443. package/docs/content/locales/es-ES/server.mdx +2 -2
  444. package/docs/content/locales/es-ES/skills-guide.mdx +1 -1
  445. package/docs/content/locales/es-ES/template-assets.mdx +1 -1
  446. package/docs/content/locales/es-ES/template-dispatch.mdx +2 -2
  447. package/docs/content/locales/es-ES/template-plan.mdx +3 -3
  448. package/docs/content/locales/fr-FR/actions.mdx +1 -1
  449. package/docs/content/locales/fr-FR/authentication.mdx +1 -1
  450. package/docs/content/locales/fr-FR/dispatch.mdx +3 -3
  451. package/docs/content/locales/fr-FR/external-agents.mdx +23 -19
  452. package/docs/content/locales/fr-FR/mcp-clients.mdx +17 -3
  453. package/docs/content/locales/fr-FR/mcp-protocol.mdx +29 -15
  454. package/docs/content/locales/fr-FR/plan-plugin.mdx +3 -3
  455. package/docs/content/locales/fr-FR/server.mdx +2 -2
  456. package/docs/content/locales/fr-FR/skills-guide.mdx +1 -1
  457. package/docs/content/locales/fr-FR/template-assets.mdx +1 -1
  458. package/docs/content/locales/fr-FR/template-dispatch.mdx +2 -2
  459. package/docs/content/locales/fr-FR/template-plan.mdx +3 -3
  460. package/docs/content/locales/hi-IN/actions.mdx +1 -1
  461. package/docs/content/locales/hi-IN/authentication.mdx +1 -1
  462. package/docs/content/locales/hi-IN/dispatch.mdx +3 -3
  463. package/docs/content/locales/hi-IN/external-agents.mdx +31 -19
  464. package/docs/content/locales/hi-IN/mcp-clients.mdx +17 -3
  465. package/docs/content/locales/hi-IN/mcp-protocol.mdx +36 -15
  466. package/docs/content/locales/hi-IN/plan-plugin.mdx +3 -3
  467. package/docs/content/locales/hi-IN/server.mdx +2 -2
  468. package/docs/content/locales/hi-IN/skills-guide.mdx +1 -1
  469. package/docs/content/locales/hi-IN/template-assets.mdx +1 -1
  470. package/docs/content/locales/hi-IN/template-dispatch.mdx +2 -2
  471. package/docs/content/locales/hi-IN/template-plan.mdx +3 -3
  472. package/docs/content/locales/ja-JP/actions.mdx +1 -1
  473. package/docs/content/locales/ja-JP/authentication.mdx +1 -1
  474. package/docs/content/locales/ja-JP/dispatch.mdx +3 -3
  475. package/docs/content/locales/ja-JP/external-agents.mdx +23 -19
  476. package/docs/content/locales/ja-JP/mcp-clients.mdx +34 -3
  477. package/docs/content/locales/ja-JP/mcp-protocol.mdx +29 -15
  478. package/docs/content/locales/ja-JP/plan-plugin.mdx +3 -3
  479. package/docs/content/locales/ja-JP/server.mdx +2 -2
  480. package/docs/content/locales/ja-JP/skills-guide.mdx +1 -1
  481. package/docs/content/locales/ja-JP/template-assets.mdx +1 -1
  482. package/docs/content/locales/ja-JP/template-dispatch.mdx +2 -2
  483. package/docs/content/locales/ja-JP/template-plan.mdx +3 -3
  484. package/docs/content/locales/ko-KR/actions.mdx +1 -1
  485. package/docs/content/locales/ko-KR/authentication.mdx +1 -1
  486. package/docs/content/locales/ko-KR/dispatch.mdx +3 -3
  487. package/docs/content/locales/ko-KR/external-agents.mdx +30 -19
  488. package/docs/content/locales/ko-KR/mcp-clients.mdx +33 -3
  489. package/docs/content/locales/ko-KR/mcp-protocol.mdx +36 -15
  490. package/docs/content/locales/ko-KR/plan-plugin.mdx +3 -3
  491. package/docs/content/locales/ko-KR/server.mdx +2 -2
  492. package/docs/content/locales/ko-KR/skills-guide.mdx +1 -1
  493. package/docs/content/locales/ko-KR/template-assets.mdx +1 -1
  494. package/docs/content/locales/ko-KR/template-dispatch.mdx +2 -2
  495. package/docs/content/locales/ko-KR/template-plan.mdx +3 -3
  496. package/docs/content/locales/pt-BR/actions.mdx +1 -1
  497. package/docs/content/locales/pt-BR/authentication.mdx +1 -1
  498. package/docs/content/locales/pt-BR/dispatch.mdx +3 -3
  499. package/docs/content/locales/pt-BR/external-agents.mdx +32 -19
  500. package/docs/content/locales/pt-BR/mcp-clients.mdx +34 -3
  501. package/docs/content/locales/pt-BR/mcp-protocol.mdx +32 -15
  502. package/docs/content/locales/pt-BR/plan-plugin.mdx +3 -3
  503. package/docs/content/locales/pt-BR/server.mdx +2 -2
  504. package/docs/content/locales/pt-BR/skills-guide.mdx +1 -1
  505. package/docs/content/locales/pt-BR/template-assets.mdx +1 -1
  506. package/docs/content/locales/pt-BR/template-dispatch.mdx +2 -2
  507. package/docs/content/locales/pt-BR/template-plan.mdx +3 -3
  508. package/docs/content/locales/zh-CN/actions.mdx +1 -1
  509. package/docs/content/locales/zh-CN/authentication.mdx +1 -1
  510. package/docs/content/locales/zh-CN/dispatch.mdx +3 -3
  511. package/docs/content/locales/zh-CN/external-agents.mdx +23 -19
  512. package/docs/content/locales/zh-CN/mcp-clients.mdx +28 -3
  513. package/docs/content/locales/zh-CN/mcp-protocol.mdx +29 -15
  514. package/docs/content/locales/zh-CN/plan-plugin.mdx +3 -3
  515. package/docs/content/locales/zh-CN/server.mdx +2 -2
  516. package/docs/content/locales/zh-CN/skills-guide.mdx +1 -1
  517. package/docs/content/locales/zh-CN/template-assets.mdx +1 -1
  518. package/docs/content/locales/zh-CN/template-dispatch.mdx +2 -2
  519. package/docs/content/locales/zh-CN/template-plan.mdx +3 -3
  520. package/docs/content/locales/zh-TW/actions.mdx +1 -1
  521. package/docs/content/locales/zh-TW/authentication.mdx +1 -1
  522. package/docs/content/locales/zh-TW/dispatch.mdx +3 -3
  523. package/docs/content/locales/zh-TW/external-agents.mdx +23 -19
  524. package/docs/content/locales/zh-TW/mcp-clients.mdx +28 -3
  525. package/docs/content/locales/zh-TW/mcp-protocol.mdx +30 -15
  526. package/docs/content/locales/zh-TW/plan-plugin.mdx +3 -3
  527. package/docs/content/locales/zh-TW/server.mdx +2 -2
  528. package/docs/content/locales/zh-TW/skills-guide.mdx +1 -1
  529. package/docs/content/locales/zh-TW/template-assets.mdx +1 -1
  530. package/docs/content/locales/zh-TW/template-dispatch.mdx +2 -2
  531. package/docs/content/locales/zh-TW/template-plan.mdx +3 -3
  532. package/docs/content/mcp-clients.mdx +31 -4
  533. package/docs/content/mcp-protocol.mdx +35 -15
  534. package/docs/content/plan-plugin.mdx +3 -3
  535. package/docs/content/server.mdx +2 -2
  536. package/docs/content/skills-guide.mdx +1 -1
  537. package/docs/content/template-assets.mdx +1 -1
  538. package/docs/content/template-dispatch.mdx +2 -2
  539. package/docs/content/template-plan.mdx +3 -3
  540. package/package.json +1 -1
  541. package/src/templates/default/.agents/skills/security/SKILL.md +10 -0
  542. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +15 -6
  543. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +16 -10
  544. package/src/templates/workspace-core/.agents/skills/performance/SKILL.md +20 -1
  545. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +10 -0
@@ -24,6 +24,7 @@ pub async fn whisper_transcription_start(
24
24
  mic_device_label: Option<String>,
25
25
  capture_system: bool,
26
26
  voice_processing: bool,
27
+ emit_partials: bool,
27
28
  owner: Option<String>,
28
29
  ) -> Result<(), String> {
29
30
  if !crate::config::feature_config(&app).whisper_model_enabled {
@@ -38,6 +39,7 @@ pub async fn whisper_transcription_start(
38
39
  mic_device_label,
39
40
  capture_system,
40
41
  voice_processing,
42
+ emit_partials,
41
43
  macos::SessionOwner::from_param(owner),
42
44
  )
43
45
  .await
@@ -51,6 +53,7 @@ pub async fn whisper_transcription_start(
51
53
  mic_device_label,
52
54
  capture_system,
53
55
  voice_processing,
56
+ emit_partials,
54
57
  owner,
55
58
  );
56
59
  Err("Whisper transcription is only supported on macOS.".into())
@@ -161,7 +164,14 @@ mod macos {
161
164
  let path_str = path
162
165
  .to_str()
163
166
  .ok_or_else(|| "model path is not valid UTF-8".to_string())?;
164
- let ctx = WhisperContext::new_with_params(path_str, WhisperContextParameters::default())
167
+ let mut params = WhisperContextParameters::default();
168
+ // The `metal` Cargo feature defaults `use_gpu` to true for every mac
169
+ // (Intel included) via whisper-rs's `_gpu` cfg. Metal offload only
170
+ // pays off on Apple Silicon's unified-memory GPU, so pin this
171
+ // explicitly instead of trusting that default — Intel Macs keep
172
+ // today's CPU decode path.
173
+ params.use_gpu(cfg!(target_arch = "aarch64"));
174
+ let ctx = WhisperContext::new_with_params(path_str, params)
165
175
  .map_err(|e| format!("whisper model load failed: {e}"))?;
166
176
  let ctx = Arc::new(ctx);
167
177
  *guard = Some(ctx.clone());
@@ -177,8 +187,25 @@ mod macos {
177
187
 
178
188
  // ---- resampling -------------------------------------------------------
179
189
 
190
+ /// One linearly-interpolated 16 kHz output sample at output index `i`,
191
+ /// given `ratio = 16000 / src_rate`. Shared by `resample_to_16k` (one-shot,
192
+ /// full buffer) and `IncrementalResample` (append-only, growing buffer) so
193
+ /// both produce byte-identical values for the same input.
194
+ fn resample_linear_at(input: &[f32], ratio: f64, i: usize) -> f32 {
195
+ let src_pos = i as f64 / ratio;
196
+ let idx = src_pos as usize;
197
+ let frac = (src_pos - idx as f64) as f32;
198
+ let a = input.get(idx).copied().unwrap_or(0.0);
199
+ let b = input.get(idx + 1).copied().unwrap_or(a);
200
+ a + (b - a) * frac
201
+ }
202
+
180
203
  /// Linear-resample mono f32 to 16 kHz (Whisper's required rate). Per-buffer
181
- /// resampling introduces negligible boundary error for speech.
204
+ /// resampling introduces negligible boundary error for speech. One-shot —
205
+ /// used only for the final flush on stop. The hot per-utterance path (an
206
+ /// utterance can be resampled repeatedly as it grows toward the 25 s cap)
207
+ /// uses `IncrementalResample` instead so it doesn't redo the whole buffer
208
+ /// every time.
182
209
  fn resample_to_16k(input: &[f32], src_rate: f64) -> Vec<f32> {
183
210
  if input.is_empty() {
184
211
  return Vec::new();
@@ -190,16 +217,95 @@ mod macos {
190
217
  let out_len = ((input.len() as f64) * ratio).floor() as usize;
191
218
  let mut out = Vec::with_capacity(out_len);
192
219
  for i in 0..out_len {
193
- let src_pos = i as f64 / ratio;
194
- let idx = src_pos as usize;
195
- let frac = (src_pos - idx as f64) as f32;
196
- let a = input.get(idx).copied().unwrap_or(0.0);
197
- let b = input.get(idx + 1).copied().unwrap_or(a);
198
- out.push(a + (b - a) * frac);
220
+ out.push(resample_linear_at(input, ratio, i));
199
221
  }
200
222
  out
201
223
  }
202
224
 
225
+ /// Incrementally maintains a 16 kHz resample of a growing raw-sample
226
+ /// buffer so repeated inference calls (partials, then the final) within
227
+ /// one utterance only resample the audio that arrived since the last
228
+ /// call, not the whole utterance from scratch. Lives entirely on the
229
+ /// worker thread — not shared, no locking needed.
230
+ struct IncrementalResample {
231
+ src_rate: f32,
232
+ /// 16 kHz samples resampled so far. A prefix of what
233
+ /// `resample_to_16k(raw, src_rate)` would produce for the current
234
+ /// `raw`; `sync` extends it in place.
235
+ out: Vec<f32>,
236
+ /// Length of `out` that's permanent: every sample up to this point
237
+ /// used two real interpolation neighbors (never the same-sample
238
+ /// fallback `resample_to_16k` falls back to at the true tail), so it
239
+ /// can never change as more raw samples arrive. `sync` recomputes
240
+ /// anything past this on every call.
241
+ committed_len: usize,
242
+ }
243
+
244
+ impl IncrementalResample {
245
+ fn new() -> Self {
246
+ Self {
247
+ src_rate: -1.0,
248
+ out: Vec::new(),
249
+ committed_len: 0,
250
+ }
251
+ }
252
+
253
+ /// Discard all cached state. Call this everywhere the raw buffer it
254
+ /// tracks is cleared or front-drained (finalize, timeline reset) —
255
+ /// after either, raw sample indices no longer line up with what's
256
+ /// cached here, so the cheapest correct move is a clean rebuild on
257
+ /// the next `sync` (bounded by however little raw audio is left).
258
+ fn drop_all(&mut self) {
259
+ self.out.clear();
260
+ self.committed_len = 0;
261
+ }
262
+
263
+ /// Extend the cached resample to cover all of `raw`, byte-identical to
264
+ /// calling `resample_to_16k(raw, src_rate)` fresh. Only the samples
265
+ /// that arrived since the last call are actually resampled.
266
+ fn sync(&mut self, raw: &[f32], src_rate: f32) {
267
+ if (src_rate - self.src_rate).abs() > 0.5 {
268
+ self.src_rate = src_rate;
269
+ self.drop_all();
270
+ }
271
+ // Drop the small uncommitted tail from the previous call (its
272
+ // fallback neighbor may since have become a real sample) before
273
+ // recomputing it with the now-current buffer.
274
+ self.out.truncate(self.committed_len);
275
+
276
+ if raw.is_empty() {
277
+ return;
278
+ }
279
+ if (src_rate as f64 - 16000.0).abs() < 1.0 {
280
+ if raw.len() > self.out.len() {
281
+ self.out.extend_from_slice(&raw[self.out.len()..]);
282
+ }
283
+ self.committed_len = self.out.len();
284
+ return;
285
+ }
286
+
287
+ let ratio = 16000.0 / src_rate as f64;
288
+ let full_len = ((raw.len() as f64) * ratio).floor() as usize;
289
+ while self.out.len() < full_len {
290
+ let i = self.out.len();
291
+ self.out.push(resample_linear_at(raw, ratio, i));
292
+ }
293
+ // Reserve the last couple of raw samples as lookahead: an output
294
+ // sample this close to the end may have used the same-sample
295
+ // fallback above because its true second neighbor hasn't arrived
296
+ // yet. Only commit up to where both neighbors are guaranteed
297
+ // real, so that sample gets redone (cheaply) once more audio
298
+ // confirms it instead of freezing the fallback value forever.
299
+ let safe_raw_len = raw.len().saturating_sub(2);
300
+ let safe_len = ((safe_raw_len as f64) * ratio).floor() as usize;
301
+ self.committed_len = safe_len.min(self.out.len());
302
+ }
303
+
304
+ fn samples(&self) -> &[f32] {
305
+ &self.out
306
+ }
307
+ }
308
+
203
309
  // ---- per-stream worker ------------------------------------------------
204
310
 
205
311
  /// One transcription stream (mic or system). Buffers raw capture samples
@@ -228,6 +334,10 @@ mod macos {
228
334
  /// local counters that must be reset after the realtime callback clears
229
335
  /// the shared sample buffer.
230
336
  reset_generation: AtomicU32,
337
+ /// Whether this consumer renders live partial transcript updates.
338
+ /// Recording capture only persists finals and disables this expensive
339
+ /// repeated inference; meeting capture keeps it enabled.
340
+ emit_partials: bool,
231
341
  }
232
342
 
233
343
  impl WhisperStream {
@@ -238,6 +348,7 @@ mod macos {
238
348
  language: Option<String>,
239
349
  ctx: Arc<WhisperContext>,
240
350
  stream_start: Instant,
351
+ emit_partials: bool,
241
352
  ) -> Arc<Self> {
242
353
  let done = Arc::new(AtomicBool::new(false));
243
354
  let stream = Arc::new(WhisperStream {
@@ -253,6 +364,7 @@ mod macos {
253
364
  buffer_start: stream_start,
254
365
  }),
255
366
  reset_generation: AtomicU32::new(0),
367
+ emit_partials,
256
368
  });
257
369
  let worker_stream = stream.clone();
258
370
  std::thread::spawn(move || {
@@ -372,6 +484,7 @@ mod macos {
372
484
  params.set_language(language);
373
485
  params.set_translate(false);
374
486
  params.set_no_context(true);
487
+ params.set_suppress_nst(true);
375
488
  params.set_print_special(false);
376
489
  params.set_print_progress(false);
377
490
  params.set_print_realtime(false);
@@ -382,7 +495,7 @@ mod macos {
382
495
  let mut out = Vec::new();
383
496
  for segment in state.as_iter() {
384
497
  let text = segment.to_string();
385
- if is_speech(&text) {
498
+ if is_speech(&text) && segment.no_speech_probability() < MAX_NO_SPEECH_PROBABILITY {
386
499
  // whisper timestamps are in centiseconds → ms.
387
500
  out.push((
388
501
  segment.start_timestamp() * 10,
@@ -415,6 +528,24 @@ mod macos {
415
528
  const SAMPLE_RATE_16K: f32 = 16000.0;
416
529
  /// RMS above this counts as speech for the silence/end-of-utterance timer.
417
530
  const VOICE_RMS_THRESHOLD: f32 = 0.006;
531
+ /// A second, model-level gate for ambient/no-speech Whisper segments.
532
+ const MAX_NO_SPEECH_PROBABILITY: f32 = 0.72;
533
+
534
+ fn partial_inference_due(
535
+ emit_partials: bool,
536
+ had_voice: bool,
537
+ have_secs: f32,
538
+ since_last_infer: Duration,
539
+ ) -> bool {
540
+ emit_partials
541
+ && had_voice
542
+ && have_secs > 0.5
543
+ && since_last_infer > Duration::from_millis(1200)
544
+ }
545
+
546
+ fn utterance_finalize_due(have_secs: f32, silence: Duration) -> bool {
547
+ (have_secs > 0.4 && silence > Duration::from_millis(800)) || have_secs > 25.0
548
+ }
418
549
 
419
550
  fn worker(stream: Arc<WhisperStream>, ctx: Arc<WhisperContext>) {
420
551
  let mut state = match ctx.create_state() {
@@ -429,7 +560,7 @@ mod macos {
429
560
  }
430
561
  };
431
562
  let lang = stream.language.as_deref();
432
- let mut last_len = 0usize;
563
+ let mut last_raw_len = 0usize;
433
564
  let mut last_infer = Instant::now() - Duration::from_secs(10);
434
565
  let mut last_voice = Instant::now();
435
566
  // Whether the CURRENT utterance buffer ever crossed the voice
@@ -437,6 +568,8 @@ mod macos {
437
568
  // silent audio, so we NEVER run inference on a buffer with no voice.
438
569
  let mut had_voice = false;
439
570
  let mut seen_reset_generation = stream.reset_generation.load(Ordering::SeqCst);
571
+ // Growing-utterance resample cache — see `IncrementalResample`.
572
+ let mut resample_state = IncrementalResample::new();
440
573
 
441
574
  while stream.running.load(Ordering::SeqCst) {
442
575
  std::thread::sleep(Duration::from_millis(250));
@@ -444,59 +577,83 @@ mod macos {
444
577
  let reset_generation = stream.reset_generation.load(Ordering::SeqCst);
445
578
  if reset_generation != seen_reset_generation {
446
579
  seen_reset_generation = reset_generation;
447
- last_len = 0;
580
+ last_raw_len = 0;
448
581
  last_voice = Instant::now();
449
582
  last_infer = Instant::now() - Duration::from_secs(10);
450
583
  had_voice = false;
584
+ resample_state.drop_all();
451
585
  continue;
452
586
  }
453
587
 
454
- // Clone the raw buffer (cheap relative to inference), then resample
455
- // to 16 kHz here on the worker rather than on the audio thread.
456
- let raw = match stream.buf.lock() {
457
- Ok(b) => b.clone(),
588
+ // Voice activity only needs the samples that arrived since the last
589
+ // poll. Inspect that tail in place instead of cloning + resampling
590
+ // the entire growing utterance four times per second. Full snapshots
591
+ // are reserved for an inference that is actually due.
592
+ let (raw_len, new_rms) = match stream.buf.lock() {
593
+ Ok(b) => {
594
+ let raw_len = b.len();
595
+ let new_rms = if raw_len > last_raw_len {
596
+ let new = &b[last_raw_len..];
597
+ Some((new.iter().map(|x| x * x).sum::<f32>() / new.len() as f32).sqrt())
598
+ } else {
599
+ None
600
+ };
601
+ (raw_len, new_rms)
602
+ }
458
603
  Err(_) => continue,
459
604
  };
460
- let src_rate = stream.src_rate.load(Ordering::SeqCst) as f64;
461
- let samples = resample_to_16k(&raw, src_rate);
462
605
  if stream.reset_generation.load(Ordering::SeqCst) != seen_reset_generation {
463
606
  continue;
464
607
  }
465
- let len = samples.len();
466
-
467
- // Track voice activity over the newly-arrived region.
468
- if len > last_len {
469
- let new = &samples[last_len..];
470
- let rms = (new.iter().map(|x| x * x).sum::<f32>() / new.len() as f32).sqrt();
608
+ if let Some(rms) = new_rms {
471
609
  if rms > VOICE_RMS_THRESHOLD {
472
610
  last_voice = Instant::now();
473
611
  had_voice = true;
474
612
  }
475
- last_len = len;
476
613
  }
614
+ last_raw_len = raw_len;
477
615
 
478
- let have_secs = len as f32 / SAMPLE_RATE_16K;
616
+ let src_rate = (stream.src_rate.load(Ordering::SeqCst) as f32).max(1.0);
617
+ let have_secs = raw_len as f32 / src_rate;
479
618
  let silence = last_voice.elapsed();
480
619
 
481
620
  // Finalize on a real pause (>0.8 s silence with >0.4 s speech) or
482
621
  // when the buffer grows too long to keep as one utterance.
483
- if (have_secs > 0.4 && silence > Duration::from_millis(800)) || have_secs > 25.0 {
622
+ if utterance_finalize_due(have_secs, silence) {
484
623
  // Only transcribe if the utterance actually contained voice —
485
624
  // otherwise we'd feed whisper silence and get a hallucinated
486
625
  // "you" / "Thank you.".
626
+ let mut n_processed = raw_len;
487
627
  if had_voice && have_secs > 0.4 {
488
- let segs = infer(&mut state, &samples, lang);
628
+ match stream.buf.lock() {
629
+ Ok(b) => {
630
+ // Hold the lock only long enough to extend the
631
+ // resample cache with the new tail (cheap) — NOT
632
+ // through inference, so the realtime capture
633
+ // callback (`push`) never blocks on whisper.
634
+ resample_state.sync(&b, src_rate);
635
+ n_processed = b.len();
636
+ }
637
+ Err(_) => continue,
638
+ }
639
+ if stream.reset_generation.load(Ordering::SeqCst) != seen_reset_generation {
640
+ continue;
641
+ }
642
+ let segs = infer(&mut state, resample_state.samples(), lang);
489
643
  stream.emit_transcript("voice:final-transcript", &segs, stream.offset_ms());
490
644
  }
491
- let n_processed = raw.len();
492
645
  if let Ok(mut b) = stream.buf.lock() {
493
646
  let to_drain = n_processed.min(b.len());
494
647
  b.drain(..to_drain);
495
648
  }
649
+ // Raw indices shift after the drain above (front-truncated),
650
+ // so the resample cache is invalid regardless of whether this
651
+ // utterance ran inference — rebuild fresh from whatever's left.
652
+ resample_state.drop_all();
496
653
  // New buffer begins now — advance the timeline offset so the
497
654
  // next utterance's whisper timestamps map correctly.
498
655
  stream.reset_buffer_start();
499
- last_len = 0;
656
+ last_raw_len = 0;
500
657
  had_voice = false;
501
658
  last_infer = Instant::now();
502
659
  continue;
@@ -504,8 +661,20 @@ mod macos {
504
661
 
505
662
  // Partial while speech is still accruing (only once real voice has
506
663
  // been heard in this utterance).
507
- if had_voice && have_secs > 0.5 && last_infer.elapsed() > Duration::from_millis(1200) {
508
- let segs = infer(&mut state, &samples, lang);
664
+ if partial_inference_due(
665
+ stream.emit_partials,
666
+ had_voice,
667
+ have_secs,
668
+ last_infer.elapsed(),
669
+ ) {
670
+ match stream.buf.lock() {
671
+ Ok(b) => resample_state.sync(&b, src_rate),
672
+ Err(_) => continue,
673
+ }
674
+ if stream.reset_generation.load(Ordering::SeqCst) != seen_reset_generation {
675
+ continue;
676
+ }
677
+ let segs = infer(&mut state, resample_state.samples(), lang);
509
678
  stream.emit_transcript("voice:partial-transcript", &segs, stream.offset_ms());
510
679
  last_infer = Instant::now();
511
680
  }
@@ -644,6 +813,7 @@ mod macos {
644
813
  mic_device_label: Option<String>,
645
814
  capture_system: bool,
646
815
  voice_processing: bool,
816
+ emit_partials: bool,
647
817
  owner: SessionOwner,
648
818
  ) -> Result<(), String> {
649
819
  // Priority rule (D10): a meeting-owned session must never be
@@ -701,6 +871,7 @@ mod macos {
701
871
  lang.clone(),
702
872
  ctx.clone(),
703
873
  session_start,
874
+ emit_partials,
704
875
  );
705
876
  let sys_stream = capture_system.then(|| {
706
877
  WhisperStream::new(
@@ -710,6 +881,7 @@ mod macos {
710
881
  lang.clone(),
711
882
  ctx.clone(),
712
883
  session_start,
884
+ emit_partials,
713
885
  )
714
886
  });
715
887
  let mic_for_cb = mic_stream.clone();
@@ -863,9 +1035,92 @@ mod macos {
863
1035
 
864
1036
  #[cfg(test)]
865
1037
  mod tests {
866
- use super::{should_use_combined_sck_capture, split_mic_capture_options, SessionOwner};
1038
+ use std::time::Duration;
1039
+
1040
+ use super::{
1041
+ partial_inference_due, resample_to_16k, should_use_combined_sck_capture,
1042
+ split_mic_capture_options, utterance_finalize_due, IncrementalResample, SessionOwner,
1043
+ };
867
1044
  use crate::native_speech::macos::MicVoiceProcessingMode;
868
1045
 
1046
+ #[test]
1047
+ fn incremental_resample_matches_one_shot_resample_as_buffer_grows() {
1048
+ let mut state = IncrementalResample::new();
1049
+ let src_rate = 48000.0_f32;
1050
+ let mut raw: Vec<f32> = Vec::new();
1051
+ // Simulate audio arriving in small chunks and syncing after each —
1052
+ // mirrors the worker polling `stream.buf` every 250 ms. A non-integer
1053
+ // chunk size (137) deliberately avoids landing on a 48k/16k=3 boundary.
1054
+ for chunk in 0..40u32 {
1055
+ for i in 0..137u32 {
1056
+ raw.push(((chunk * 137 + i) as f32 * 0.013).sin());
1057
+ }
1058
+ state.sync(&raw, src_rate);
1059
+ let expected = resample_to_16k(&raw, src_rate as f64);
1060
+ assert_eq!(
1061
+ state.samples(),
1062
+ expected.as_slice(),
1063
+ "diverged after {} raw samples",
1064
+ raw.len()
1065
+ );
1066
+ }
1067
+ }
1068
+
1069
+ #[test]
1070
+ fn incremental_resample_rebuilds_cleanly_after_drop_all() {
1071
+ let mut state = IncrementalResample::new();
1072
+ let src_rate = 44100.0_f32;
1073
+ let mut raw: Vec<f32> = (0..2_000).map(|i| (i as f32 * 0.02).sin()).collect();
1074
+ state.sync(&raw, src_rate);
1075
+ assert_eq!(
1076
+ state.samples(),
1077
+ resample_to_16k(&raw, src_rate as f64).as_slice()
1078
+ );
1079
+
1080
+ // Utterance finalize: raw buffer is front-drained (indices shift),
1081
+ // so the cache must be dropped, not incrementally patched.
1082
+ raw.drain(..1_500);
1083
+ state.drop_all();
1084
+ state.sync(&raw, src_rate);
1085
+ assert_eq!(
1086
+ state.samples(),
1087
+ resample_to_16k(&raw, src_rate as f64).as_slice()
1088
+ );
1089
+ }
1090
+
1091
+ #[test]
1092
+ fn recording_mode_never_runs_live_partial_inference() {
1093
+ assert!(!partial_inference_due(
1094
+ false,
1095
+ true,
1096
+ 10.0,
1097
+ Duration::from_secs(10)
1098
+ ));
1099
+ }
1100
+
1101
+ #[test]
1102
+ fn meeting_mode_keeps_existing_partial_inference_cadence() {
1103
+ assert!(partial_inference_due(
1104
+ true,
1105
+ true,
1106
+ 1.0,
1107
+ Duration::from_millis(1201)
1108
+ ));
1109
+ assert!(!partial_inference_due(
1110
+ true,
1111
+ true,
1112
+ 1.0,
1113
+ Duration::from_millis(1200)
1114
+ ));
1115
+ }
1116
+
1117
+ #[test]
1118
+ fn recording_mode_keeps_silence_and_long_utterance_finalization() {
1119
+ assert!(utterance_finalize_due(1.0, Duration::from_millis(801)));
1120
+ assert!(utterance_finalize_due(25.1, Duration::ZERO));
1121
+ assert!(!utterance_finalize_due(25.0, Duration::from_millis(100)));
1122
+ }
1123
+
869
1124
  #[test]
870
1125
  fn combined_sck_capture_is_only_selected_for_supported_meetings() {
871
1126
  assert!(should_use_combined_sck_capture(SessionOwner::Meeting, true));
@@ -22,7 +22,7 @@
22
22
  "targets": ["dmg", "app", "msi"],
23
23
  "icon": ["icons/icon.png", "icons/icon.ico", "icons/icon.icns"],
24
24
  "macOS": {
25
- "minimumSystemVersion": "11.0",
25
+ "minimumSystemVersion": "13.0",
26
26
  "entitlements": "./Entitlements.plist",
27
27
  "files": {
28
28
  "Resources/Assets.car": "Assets.car"
@@ -77,3 +77,31 @@ export function isPersonalSoloCalendarEvent(args: {
77
77
  return Boolean(email && selfEmails.has(email));
78
78
  });
79
79
  }
80
+
81
+ /**
82
+ * True when a calendar event has no active attendee besides the current user.
83
+ * This is intentionally broader than the title-based personal-event helper:
84
+ * desktop meeting reminders should not surface for any self-only event.
85
+ */
86
+ export function isSoloCalendarEvent(args: {
87
+ account: CalendarAccountForEventClassification;
88
+ event: CalendarEvent;
89
+ currentUserEmail?: string | null;
90
+ }): boolean {
91
+ const selfEmails = new Set(
92
+ [args.currentUserEmail, args.account.email, args.account.ownerEmail]
93
+ .map(normalizeEmail)
94
+ .filter((email): email is string => Boolean(email)),
95
+ );
96
+
97
+ const organizerEmail = normalizeEmail(args.event.organizer?.email);
98
+ if (organizerEmail && !selfEmails.has(organizerEmail)) return false;
99
+
100
+ const activeAttendees = (args.event.attendees ?? []).filter(
101
+ (attendee) => attendee.responseStatus !== "declined",
102
+ );
103
+ return activeAttendees.every((attendee) => {
104
+ const email = normalizeEmail(attendee.email);
105
+ return Boolean(email && selfEmails.has(email));
106
+ });
107
+ }
@@ -1,13 +1,5 @@
1
- import { getOrgContext } from "@agent-native/core/org";
2
- import { getSession, runWithRequestContext } from "@agent-native/core/server";
3
1
  import { createH3SSRHandler } from "@agent-native/core/server/ssr-handler";
4
- import { resolveAccess } from "@agent-native/core/sharing";
5
- import {
6
- defineEventHandler,
7
- getRequestURL,
8
- setResponseHeader,
9
- type H3Event,
10
- } from "h3";
2
+ import { defineEventHandler, setResponseHeader } from "h3";
11
3
 
12
4
  import {
13
5
  MEDIA_CAPTURE_PERMISSIONS_POLICY,
@@ -18,57 +10,7 @@ const ssrHandler = createH3SSRHandler(
18
10
  () => import("virtual:react-router/server-build"),
19
11
  );
20
12
 
21
- function recordingIdFromAuthenticatedPath(pathname: string): string | null {
22
- const match = pathname.match(/^\/r\/([^/]+)\/?$/);
23
- if (!match?.[1]) return null;
24
- try {
25
- return decodeURIComponent(match[1]);
26
- } catch {
27
- return match[1];
28
- }
29
- }
30
-
31
- function shareRedirect(recordingId: string, search: string): Response {
32
- return new Response(null, {
33
- status: 302,
34
- headers: {
35
- location: `/share/${encodeURIComponent(recordingId)}${search}`,
36
- "Permissions-Policy": MEDIA_CAPTURE_PERMISSIONS_POLICY,
37
- },
38
- });
39
- }
40
-
41
- async function redirectNonOwnerRecordingPath(
42
- event: H3Event,
43
- ): Promise<Response | null> {
44
- const url = getRequestURL(event);
45
- const recordingId = recordingIdFromAuthenticatedPath(url.pathname);
46
- if (!recordingId) return null;
47
-
48
- const session = await getSession(event).catch(() => null);
49
- if (!session?.email) return shareRedirect(recordingId, url.search);
50
-
51
- const orgCtx = await getOrgContext(event).catch(() => null);
52
- const orgId = orgCtx?.orgId ?? session.orgId ?? undefined;
53
-
54
- try {
55
- const access = await runWithRequestContext(
56
- { userEmail: session.email, orgId },
57
- () => resolveAccess("recording", recordingId),
58
- );
59
- if (access?.role === "owner") return null;
60
- } catch {
61
- // Treat missing/inaccessible recordings the same as no access here;
62
- // the share route can render the canonical public/not-found state.
63
- }
64
-
65
- return shareRedirect(recordingId, url.search);
66
- }
67
-
68
13
  export default defineEventHandler(async (event) => {
69
- const redirect = await redirectNonOwnerRecordingPath(event);
70
- if (redirect) return redirect;
71
-
72
14
  const response = (await ssrHandler(event)) as Response;
73
15
  setResponseHeader(
74
16
  event,
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared screen-capture quality policy for browser-based Clips recorders.
3
+ *
4
+ * Display capture constraints are applied after the user chooses a surface. We
5
+ * use `max` envelopes (never `min`/`exact`) so Retina and 4K sources are
6
+ * downscaled before MediaRecorder has to encode them.
7
+ */
8
+
9
+ export const SCREEN_CAPTURE_FRAME_RATE = 24;
10
+ export const SCREEN_CAPTURE_MAX_WIDTH = 1920;
11
+ export const SCREEN_CAPTURE_MAX_HEIGHT = 1080;
12
+
13
+ export type ScreenCaptureSurface = "browser" | "window" | "monitor";
14
+
15
+ export type ScreenCaptureVideoConstraints = MediaTrackConstraints & {
16
+ displaySurface: ScreenCaptureSurface;
17
+ };
18
+
19
+ export function screenCaptureVideoConstraints(
20
+ displaySurface: ScreenCaptureSurface,
21
+ ): ScreenCaptureVideoConstraints {
22
+ return {
23
+ frameRate: {
24
+ ideal: SCREEN_CAPTURE_FRAME_RATE,
25
+ max: SCREEN_CAPTURE_FRAME_RATE,
26
+ },
27
+ width: {
28
+ ideal: SCREEN_CAPTURE_MAX_WIDTH,
29
+ max: SCREEN_CAPTURE_MAX_WIDTH,
30
+ },
31
+ height: {
32
+ ideal: SCREEN_CAPTURE_MAX_HEIGHT,
33
+ max: SCREEN_CAPTURE_MAX_HEIGHT,
34
+ },
35
+ displaySurface,
36
+ };
37
+ }
@@ -147,6 +147,16 @@ export default defineEventHandler(async (event) => {
147
147
 
148
148
  - Never create unprotected routes that modify data.
149
149
 
150
+ **Exception — the SSR HTML/`.data` catch-all is deliberately session-blind.**
151
+ The rule above is for routes that read or mutate user data. The SSR page
152
+ render and React Router `.data` route are different: they serve one
153
+ impersonal, public-cacheable shell to every visitor by design, and loaders on
154
+ that path render no user data. Do not "fix" this by adding `getSession`,
155
+ `private`, or `no-store` to it — that regresses the CDN cache contract for the
156
+ whole site. Data scoping lives in actions and API routes; the client gates
157
+ private UI after the shell loads. See the `authentication` skill and
158
+ `guard:ssr-cache-shell` / `ssr-handler.spec.ts`.
159
+
150
160
  ## Human-in-the-Loop Approval for High-Consequence Actions
151
161
 
152
162
  For a small set of outward-facing, hard-to-undo operations — sending an email, charging a card, deleting an account, posting publicly — auth and access control are necessary but not sufficient: you also do not want the **agent** to perform them autonomously. Set `needsApproval` on the `defineAction` so the agent cannot run the action without a human approving the specific call.
@@ -5,7 +5,7 @@
5
5
  "description": "Create and manage docs plus Notion-style databases, boards, structured intake forms, and request records through Content, including repo-backed Markdown/MDX.",
6
6
  "hosted": {
7
7
  "url": "https://content.agent-native.com",
8
- "mcpUrl": "https://content.agent-native.com/_agent-native/mcp"
8
+ "mcpUrl": "https://content.agent-native.com/mcp"
9
9
  },
10
10
  "mcp": {
11
11
  "serverName": "agent-native-content"