@agent-native/core 0.128.4 → 0.129.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 (343) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +84 -0
  3. package/corpus/core/docs/content/template-design-collaboration-and-full-apps.mdx +3 -1
  4. package/corpus/core/package.json +6 -3
  5. package/corpus/core/src/a2a/client.ts +18 -4
  6. package/corpus/core/src/a2a/server.ts +19 -3
  7. package/corpus/core/src/a2a/types.ts +7 -0
  8. package/corpus/core/src/action.ts +43 -16
  9. package/corpus/core/src/agent/engine/ai-sdk-engine.ts +14 -10
  10. package/corpus/core/src/agent/production-agent.ts +41 -3
  11. package/corpus/core/src/agent/thread-data-builder.ts +5 -0
  12. package/corpus/core/src/chat-threads/migrations.ts +53 -0
  13. package/corpus/core/src/cli/create.ts +4 -0
  14. package/corpus/core/src/cli/skills-content/design-visual-edit-skill.ts +36 -16
  15. package/corpus/core/src/cli/skills.ts +16 -0
  16. package/corpus/core/src/client/AgentPanel.tsx +9 -5
  17. package/corpus/core/src/client/AssistantChat.tsx +138 -46
  18. package/corpus/core/src/client/MultiTabAssistantChat.tsx +16 -10
  19. package/corpus/core/src/client/agent-chat-adapter.ts +21 -3
  20. package/corpus/core/src/client/analytics.ts +159 -102
  21. package/corpus/core/src/client/chat/message-components.tsx +12 -5
  22. package/corpus/core/src/client/chat/runtime.ts +2 -1
  23. package/corpus/core/src/client/chat/tool-call-display.tsx +25 -2
  24. package/corpus/core/src/client/chat-model-groups.ts +3 -0
  25. package/corpus/core/src/client/client-status-requests.ts +161 -0
  26. package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
  27. package/corpus/core/src/client/sse-event-processor.ts +15 -3
  28. package/corpus/core/src/client/use-agent-engine-configured.ts +54 -50
  29. package/corpus/core/src/client/use-chat-models.ts +16 -11
  30. package/corpus/core/src/client/use-chat-threads.ts +32 -9
  31. package/corpus/core/src/client/use-session.ts +4 -5
  32. package/corpus/core/src/db/client.ts +83 -8
  33. package/corpus/core/src/db/ensure-additive-columns.ts +31 -20
  34. package/corpus/core/src/db/migrations.ts +22 -2
  35. package/corpus/core/src/mcp/approval-store.ts +99 -0
  36. package/corpus/core/src/mcp/build-server.ts +579 -303
  37. package/corpus/core/src/mcp/embed-app.ts +1 -1
  38. package/corpus/core/src/mcp/oauth-client-metadata.ts +380 -0
  39. package/corpus/core/src/mcp/oauth-route.ts +57 -52
  40. package/corpus/core/src/mcp/screen-memory-stdio.ts +400 -378
  41. package/corpus/core/src/mcp/server.ts +29 -145
  42. package/corpus/core/src/mcp/stdio.ts +72 -80
  43. package/corpus/core/src/mcp-client/manager.ts +6 -10
  44. package/corpus/core/src/mcp-client/oauth-client.ts +127 -36
  45. package/corpus/core/src/mcp-client/oauth-routes.ts +16 -6
  46. package/corpus/core/src/mcp-client/routes.ts +6 -5
  47. package/corpus/core/src/server/agent-capabilities.ts +20 -0
  48. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +27 -0
  49. package/corpus/core/src/server/agent-chat-plugin.ts +18 -0
  50. package/corpus/core/src/server/transcribe-voice.ts +14 -5
  51. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +13 -2
  52. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  53. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  54. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
  55. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +13 -2
  56. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -10
  57. package/corpus/templates/analytics/app/global.css +0 -31
  58. package/corpus/templates/analytics/app/lib/sql-query.ts +46 -20
  59. package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboard-loading-states-now-use-a-simpler-standar.md +6 -0
  60. package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboards-now-load-first-party-charts-reliably-in.md +6 -0
  61. package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +42 -16
  62. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +4 -2
  63. package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
  64. package/corpus/templates/assets/.agents/skills/security/SKILL.md +13 -2
  65. package/corpus/templates/brain/.agents/skills/security/SKILL.md +13 -2
  66. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +13 -2
  67. package/corpus/templates/chat/.agents/skills/security/SKILL.md +13 -2
  68. package/corpus/templates/chat/README.md +0 -2
  69. package/corpus/templates/clips/.agents/skills/security/SKILL.md +13 -2
  70. package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -6
  71. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +6 -2
  72. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -1
  73. package/corpus/templates/clips/changelog/2026-07-28-copied-share-links-no-longer-leave-an-unnecessary-confirmati.md +6 -0
  74. package/corpus/templates/clips/changelog/2026-07-28-playback-skip-controls-no-longer-show-overlapping-numbers.md +6 -0
  75. package/corpus/templates/clips/changelog/2026-07-28-public-clips-share-buttons-now-use-a-clean-text-only-label.md +6 -0
  76. package/corpus/templates/clips/desktop/src/app.tsx +14 -17
  77. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +3 -1
  78. package/corpus/templates/clips/desktop/src/styles.css +13 -10
  79. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +2 -2
  80. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +36 -0
  81. package/corpus/templates/content/.agents/skills/security/SKILL.md +13 -2
  82. package/corpus/templates/content/actions/_builder-cms-read-client.ts +155 -34
  83. package/corpus/templates/content/actions/_builder-docs-client.ts +151 -30
  84. package/corpus/templates/content/actions/stage-builder-source-bulk-update.ts +5 -2
  85. package/corpus/templates/content/app/root.tsx +35 -14
  86. package/corpus/templates/content/changelog/2026-07-28-builder-backed-files-media-fields-now-accept-direct-file-url.md +6 -0
  87. package/corpus/templates/content/changelog/2026-07-28-builder-content-reads-now-negotiate-the-newest-mcp-protocol-.md +6 -0
  88. package/corpus/templates/content/changelog/2026-07-28-public-content-pages-load-faster-before-the-optional-ask-sid.md +6 -0
  89. package/corpus/templates/design/.agents/skills/security/SKILL.md +13 -2
  90. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +36 -16
  91. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +42 -3
  92. package/corpus/templates/design/actions/open-visual-edit.ts +2 -1
  93. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
  94. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +14 -15
  95. package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +314 -0
  96. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +88 -3
  97. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
  98. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +7 -6
  99. package/corpus/templates/design/app/i18n-data.ts +56 -11
  100. package/corpus/templates/design/app/i18n-responsive-interact.ts +183 -0
  101. package/corpus/templates/design/app/lib/agent-chat.ts +60 -0
  102. package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +89 -0
  103. package/corpus/templates/design/changelog/2026-07-28-design-edits-can-be-applied-through-the-host-coding-agent-fr.md +6 -0
  104. package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +6 -0
  105. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +6 -0
  106. package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +2 -2
  107. package/corpus/templates/design/changelog/2026-07-28-visual-edit-now-always-shows-the-live-running-app-in-the-can.md +6 -0
  108. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +13 -2
  109. package/corpus/templates/forms/.agents/skills/security/SKILL.md +13 -2
  110. package/corpus/templates/macros/.agents/skills/security/SKILL.md +13 -2
  111. package/corpus/templates/mail/.agents/skills/security/SKILL.md +13 -2
  112. package/corpus/templates/plan/.agents/skills/security/SKILL.md +13 -2
  113. package/corpus/templates/slides/.agents/skills/security/SKILL.md +13 -2
  114. package/corpus/templates/tasks/.agents/skills/security/SKILL.md +13 -2
  115. package/corpus/toolkit/CHANGELOG.md +13 -0
  116. package/corpus/toolkit/package.json +1 -1
  117. package/corpus/toolkit/src/chat-history.css +1 -2
  118. package/corpus/toolkit/src/composer/TiptapComposer.tsx +45 -0
  119. package/dist/a2a/client.d.ts +7 -0
  120. package/dist/a2a/client.d.ts.map +1 -1
  121. package/dist/a2a/client.js +8 -3
  122. package/dist/a2a/client.js.map +1 -1
  123. package/dist/a2a/server.d.ts.map +1 -1
  124. package/dist/a2a/server.js +18 -3
  125. package/dist/a2a/server.js.map +1 -1
  126. package/dist/a2a/types.d.ts +7 -0
  127. package/dist/a2a/types.d.ts.map +1 -1
  128. package/dist/a2a/types.js.map +1 -1
  129. package/dist/action.d.ts +15 -1
  130. package/dist/action.d.ts.map +1 -1
  131. package/dist/action.js +39 -16
  132. package/dist/action.js.map +1 -1
  133. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  134. package/dist/agent/engine/ai-sdk-engine.js +14 -10
  135. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  136. package/dist/agent/production-agent.d.ts.map +1 -1
  137. package/dist/agent/production-agent.js +35 -7
  138. package/dist/agent/production-agent.js.map +1 -1
  139. package/dist/agent/thread-data-builder.d.ts +2 -0
  140. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  141. package/dist/agent/thread-data-builder.js +3 -0
  142. package/dist/agent/thread-data-builder.js.map +1 -1
  143. package/dist/chat-threads/migrations.d.ts +21 -0
  144. package/dist/chat-threads/migrations.d.ts.map +1 -0
  145. package/dist/chat-threads/migrations.js +45 -0
  146. package/dist/chat-threads/migrations.js.map +1 -0
  147. package/dist/cli/create.d.ts.map +1 -1
  148. package/dist/cli/create.js +4 -0
  149. package/dist/cli/create.js.map +1 -1
  150. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  151. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  152. package/dist/cli/skills-content/design-visual-edit-skill.js +36 -16
  153. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  154. package/dist/cli/skills.d.ts.map +1 -1
  155. package/dist/cli/skills.js +15 -0
  156. package/dist/cli/skills.js.map +1 -1
  157. package/dist/client/AgentPanel.d.ts.map +1 -1
  158. package/dist/client/AgentPanel.js +6 -5
  159. package/dist/client/AgentPanel.js.map +1 -1
  160. package/dist/client/AssistantChat.d.ts +37 -0
  161. package/dist/client/AssistantChat.d.ts.map +1 -1
  162. package/dist/client/AssistantChat.js +41 -8
  163. package/dist/client/AssistantChat.js.map +1 -1
  164. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  165. package/dist/client/MultiTabAssistantChat.js +11 -10
  166. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  167. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  168. package/dist/client/agent-chat-adapter.js +19 -3
  169. package/dist/client/agent-chat-adapter.js.map +1 -1
  170. package/dist/client/analytics.d.ts.map +1 -1
  171. package/dist/client/analytics.js +150 -101
  172. package/dist/client/analytics.js.map +1 -1
  173. package/dist/client/chat/message-components.d.ts +2 -1
  174. package/dist/client/chat/message-components.d.ts.map +1 -1
  175. package/dist/client/chat/message-components.js +11 -4
  176. package/dist/client/chat/message-components.js.map +1 -1
  177. package/dist/client/chat/runtime.d.ts.map +1 -1
  178. package/dist/client/chat/runtime.js +2 -1
  179. package/dist/client/chat/runtime.js.map +1 -1
  180. package/dist/client/chat/tool-call-display.d.ts +4 -1
  181. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  182. package/dist/client/chat/tool-call-display.js +14 -8
  183. package/dist/client/chat/tool-call-display.js.map +1 -1
  184. package/dist/client/chat-model-groups.d.ts.map +1 -1
  185. package/dist/client/chat-model-groups.js +3 -0
  186. package/dist/client/chat-model-groups.js.map +1 -1
  187. package/dist/client/client-status-requests.d.ts +14 -0
  188. package/dist/client/client-status-requests.d.ts.map +1 -0
  189. package/dist/client/client-status-requests.js +126 -0
  190. package/dist/client/client-status-requests.js.map +1 -0
  191. package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
  192. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  193. package/dist/client/sse-event-processor.d.ts +7 -0
  194. package/dist/client/sse-event-processor.d.ts.map +1 -1
  195. package/dist/client/sse-event-processor.js +8 -3
  196. package/dist/client/sse-event-processor.js.map +1 -1
  197. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  198. package/dist/client/use-agent-engine-configured.js +29 -43
  199. package/dist/client/use-agent-engine-configured.js.map +1 -1
  200. package/dist/client/use-chat-models.d.ts.map +1 -1
  201. package/dist/client/use-chat-models.js +11 -11
  202. package/dist/client/use-chat-models.js.map +1 -1
  203. package/dist/client/use-chat-threads.d.ts.map +1 -1
  204. package/dist/client/use-chat-threads.js +23 -7
  205. package/dist/client/use-chat-threads.js.map +1 -1
  206. package/dist/client/use-session.d.ts.map +1 -1
  207. package/dist/client/use-session.js +4 -4
  208. package/dist/client/use-session.js.map +1 -1
  209. package/dist/collab/awareness.d.ts +2 -2
  210. package/dist/collab/awareness.d.ts.map +1 -1
  211. package/dist/collab/struct-routes.d.ts +1 -1
  212. package/dist/db/client.d.ts.map +1 -1
  213. package/dist/db/client.js +48 -4
  214. package/dist/db/client.js.map +1 -1
  215. package/dist/db/ensure-additive-columns.d.ts.map +1 -1
  216. package/dist/db/ensure-additive-columns.js +32 -21
  217. package/dist/db/ensure-additive-columns.js.map +1 -1
  218. package/dist/db/migrations.d.ts +9 -0
  219. package/dist/db/migrations.d.ts.map +1 -1
  220. package/dist/db/migrations.js +14 -3
  221. package/dist/db/migrations.js.map +1 -1
  222. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  223. package/dist/mcp/approval-store.d.ts +16 -0
  224. package/dist/mcp/approval-store.d.ts.map +1 -0
  225. package/dist/mcp/approval-store.js +85 -0
  226. package/dist/mcp/approval-store.js.map +1 -0
  227. package/dist/mcp/build-server.d.ts +1 -34
  228. package/dist/mcp/build-server.d.ts.map +1 -1
  229. package/dist/mcp/build-server.js +220 -23
  230. package/dist/mcp/build-server.js.map +1 -1
  231. package/dist/mcp/embed-app.js +1 -1
  232. package/dist/mcp/embed-app.js.map +1 -1
  233. package/dist/mcp/oauth-client-metadata.d.ts +15 -0
  234. package/dist/mcp/oauth-client-metadata.d.ts.map +1 -0
  235. package/dist/mcp/oauth-client-metadata.js +297 -0
  236. package/dist/mcp/oauth-client-metadata.js.map +1 -0
  237. package/dist/mcp/oauth-route.d.ts.map +1 -1
  238. package/dist/mcp/oauth-route.js +39 -53
  239. package/dist/mcp/oauth-route.js.map +1 -1
  240. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
  241. package/dist/mcp/screen-memory-stdio.js +304 -296
  242. package/dist/mcp/screen-memory-stdio.js.map +1 -1
  243. package/dist/mcp/server.d.ts +12 -25
  244. package/dist/mcp/server.d.ts.map +1 -1
  245. package/dist/mcp/server.js +24 -133
  246. package/dist/mcp/server.js.map +1 -1
  247. package/dist/mcp/stdio.d.ts.map +1 -1
  248. package/dist/mcp/stdio.js +36 -35
  249. package/dist/mcp/stdio.js.map +1 -1
  250. package/dist/mcp-client/manager.d.ts.map +1 -1
  251. package/dist/mcp-client/manager.js +6 -6
  252. package/dist/mcp-client/manager.js.map +1 -1
  253. package/dist/mcp-client/oauth-client.d.ts +13 -17
  254. package/dist/mcp-client/oauth-client.d.ts.map +1 -1
  255. package/dist/mcp-client/oauth-client.js +74 -16
  256. package/dist/mcp-client/oauth-client.js.map +1 -1
  257. package/dist/mcp-client/oauth-routes.d.ts +2 -2
  258. package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
  259. package/dist/mcp-client/oauth-routes.js +16 -6
  260. package/dist/mcp-client/oauth-routes.js.map +1 -1
  261. package/dist/mcp-client/routes.js +5 -5
  262. package/dist/mcp-client/routes.js.map +1 -1
  263. package/dist/notifications/routes.d.ts +1 -1
  264. package/dist/observability/routes.d.ts +3 -3
  265. package/dist/progress/routes.d.ts +1 -1
  266. package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
  267. package/dist/provider-api/actions/provider-api.d.ts +8 -8
  268. package/dist/resources/handlers.d.ts +1 -1
  269. package/dist/secrets/routes.d.ts +9 -9
  270. package/dist/server/agent-capabilities.d.ts.map +1 -1
  271. package/dist/server/agent-capabilities.js +21 -0
  272. package/dist/server/agent-capabilities.js.map +1 -1
  273. package/dist/server/agent-chat/action-filters-a2a.d.ts +14 -0
  274. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  275. package/dist/server/agent-chat/action-filters-a2a.js +16 -0
  276. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  277. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  278. package/dist/server/agent-chat-plugin.js +11 -1
  279. package/dist/server/agent-chat-plugin.js.map +1 -1
  280. package/dist/server/realtime-token.d.ts +1 -1
  281. package/dist/server/transcribe-voice.d.ts +1 -1
  282. package/dist/server/transcribe-voice.js +12 -6
  283. package/dist/server/transcribe-voice.js.map +1 -1
  284. package/dist/templates/chat/.agents/skills/security/SKILL.md +13 -2
  285. package/dist/templates/chat/README.md +0 -2
  286. package/dist/templates/default/.agents/skills/security/SKILL.md +13 -2
  287. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  288. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  289. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
  290. package/docs/content/template-design-collaboration-and-full-apps.mdx +3 -1
  291. package/package.json +7 -4
  292. package/src/a2a/client.ts +18 -4
  293. package/src/a2a/server.ts +19 -3
  294. package/src/a2a/types.ts +7 -0
  295. package/src/action.ts +43 -16
  296. package/src/agent/engine/ai-sdk-engine.ts +14 -10
  297. package/src/agent/production-agent.ts +41 -3
  298. package/src/agent/thread-data-builder.ts +5 -0
  299. package/src/chat-threads/migrations.ts +53 -0
  300. package/src/cli/create.ts +4 -0
  301. package/src/cli/skills-content/design-visual-edit-skill.ts +36 -16
  302. package/src/cli/skills.ts +16 -0
  303. package/src/client/AgentPanel.tsx +9 -5
  304. package/src/client/AssistantChat.tsx +138 -46
  305. package/src/client/MultiTabAssistantChat.tsx +16 -10
  306. package/src/client/agent-chat-adapter.ts +21 -3
  307. package/src/client/analytics.ts +159 -102
  308. package/src/client/chat/message-components.tsx +12 -5
  309. package/src/client/chat/runtime.ts +2 -1
  310. package/src/client/chat/tool-call-display.tsx +25 -2
  311. package/src/client/chat-model-groups.ts +3 -0
  312. package/src/client/client-status-requests.ts +161 -0
  313. package/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
  314. package/src/client/sse-event-processor.ts +15 -3
  315. package/src/client/use-agent-engine-configured.ts +54 -50
  316. package/src/client/use-chat-models.ts +16 -11
  317. package/src/client/use-chat-threads.ts +32 -9
  318. package/src/client/use-session.ts +4 -5
  319. package/src/db/client.ts +83 -8
  320. package/src/db/ensure-additive-columns.ts +31 -20
  321. package/src/db/migrations.ts +22 -2
  322. package/src/mcp/approval-store.ts +99 -0
  323. package/src/mcp/build-server.ts +579 -303
  324. package/src/mcp/embed-app.ts +1 -1
  325. package/src/mcp/oauth-client-metadata.ts +380 -0
  326. package/src/mcp/oauth-route.ts +57 -52
  327. package/src/mcp/screen-memory-stdio.ts +400 -378
  328. package/src/mcp/server.ts +29 -145
  329. package/src/mcp/stdio.ts +72 -80
  330. package/src/mcp-client/manager.ts +6 -10
  331. package/src/mcp-client/oauth-client.ts +127 -36
  332. package/src/mcp-client/oauth-routes.ts +16 -6
  333. package/src/mcp-client/routes.ts +6 -5
  334. package/src/server/agent-capabilities.ts +20 -0
  335. package/src/server/agent-chat/action-filters-a2a.ts +27 -0
  336. package/src/server/agent-chat-plugin.ts +18 -0
  337. package/src/server/transcribe-voice.ts +14 -5
  338. package/src/templates/chat/.agents/skills/security/SKILL.md +13 -2
  339. package/src/templates/chat/README.md +0 -2
  340. package/src/templates/default/.agents/skills/security/SKILL.md +13 -2
  341. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  342. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  343. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
@@ -812,10 +812,14 @@ body[data-clips-route="recording-pill"] #root {
812
812
  vector-effect: non-scaling-stroke;
813
813
  }
814
814
 
815
+ /* One variable owns the meter's height and the bars scale off it — every rule
816
+ that resizes the meter sets `--meter-height`, not `height`. Two rules setting
817
+ `height` independently is how the box and the bars drifted apart before. */
815
818
  .live-audio-bars {
819
+ --meter-height: 26px;
816
820
  display: inline-flex;
817
821
  width: 48px;
818
- height: 26px;
822
+ height: var(--meter-height);
819
823
  align-items: center;
820
824
  justify-content: center;
821
825
  gap: 4px;
@@ -823,15 +827,14 @@ body[data-clips-route="recording-pill"] #root {
823
827
  }
824
828
 
825
829
  .live-audio-bars-compact {
826
- width: 24px;
827
- height: 24px;
828
- gap: 3.5px;
830
+ --meter-height: 22px;
831
+ width: 21px;
832
+ gap: 3px;
829
833
  }
830
834
 
831
835
  .live-audio-bar {
832
836
  display: block;
833
- width: 3.5px;
834
- min-height: 3.5px;
837
+ width: 3px;
835
838
  border-radius: 999px;
836
839
  background: rgba(132, 204, 22, 0.98);
837
840
  box-shadow: 0 0 5px rgba(132, 204, 22, 0.35);
@@ -5577,7 +5580,7 @@ body[data-clips-route="recording-pill"] #root {
5577
5580
  gap: 6px;
5578
5581
  height: auto;
5579
5582
  width: auto;
5580
- padding: 12px 10px;
5583
+ padding: 10px 8px;
5581
5584
  cursor: pointer;
5582
5585
  }
5583
5586
 
@@ -5592,8 +5595,8 @@ body[data-clips-route="recording-pill"] #root {
5592
5595
  }
5593
5596
 
5594
5597
  .pill-vertical .pill-wave-meter {
5595
- height: 24px;
5596
- width: 24px;
5598
+ --meter-height: 22px;
5599
+ width: 21px;
5597
5600
  }
5598
5601
 
5599
5602
  /* Wrapper around logo + waveform. */
@@ -5617,7 +5620,7 @@ body[data-clips-route="recording-pill"] #root {
5617
5620
  /* Layout only. `display` must stay flex here — a `block` override collapses
5618
5621
  the meter's bars into a single stacked column instead of a waveform. */
5619
5622
  .pill-wave-meter {
5620
- height: 26px;
5623
+ --meter-height: 26px;
5621
5624
  width: 48px;
5622
5625
  flex-shrink: 0;
5623
5626
  }
@@ -66,7 +66,7 @@ static PILL_HOVER_TRACKING: AtomicBool = AtomicBool::new(false);
66
66
  /// Collapsed dimensions (logical px). The collapsed pill is a vertical capsule
67
67
  /// — clips logo on top, waveform below — so it is taller than it is wide. The
68
68
  /// expanded form stretches horizontally to fit the live-transcript area.
69
- const PILL_W_LOGICAL: u32 = 44;
69
+ const PILL_W_LOGICAL: u32 = 38;
70
70
  const PILL_W_EXPANDED_LOGICAL: u32 = 480;
71
71
  /// Meeting mode uses the same focused transcript width as other recordings;
72
72
  /// live notes are intentionally kept out of this compact overlay.
@@ -74,7 +74,7 @@ const PILL_W_EXPANDED_MEETING_LOGICAL: u32 = 480;
74
74
  /// Keep this close to the rendered capsule's height. The window frame is what
75
75
  /// hover is polled against, so slack here makes the pill light up while the
76
76
  /// cursor is still nowhere near it.
77
- const PILL_H_LOGICAL: u32 = 64;
77
+ const PILL_H_LOGICAL: u32 = 60;
78
78
  const PILL_H_EXPANDED_LOGICAL: u32 = 340;
79
79
  /// Bottom margin from the screen edge, logical px. Granola uses ~24.
80
80
  const PILL_BOTTOM_MARGIN_LOGICAL: u32 = 24;
@@ -157,6 +157,38 @@ mod macos {
157
157
 
158
158
  const MEETING_AUDIO_OWNER: &str = "meeting-whisper";
159
159
 
160
+ /// Emit every Nth shared-bus buffer as a meter level. Buffers land every
161
+ /// ~10-20 ms; the overlay only needs ~20 Hz to look live.
162
+ const SHARED_LEVEL_EVERY: u32 = 3;
163
+
164
+ /// Meter levels for the shared-producer path. Each physical capture path
165
+ /// emits `voice:audio-level` from its own tap, but a meeting that subscribes
166
+ /// to the Rewind audio bus opens none of those taps — the samples arrive
167
+ /// already mixed. Without this the recording pill's waveform reports silence
168
+ /// for the entire call while transcription runs perfectly.
169
+ fn shared_level_tap(
170
+ app: AppHandle,
171
+ source: &'static str,
172
+ ) -> impl Fn(&[f32]) + Send + Sync + 'static {
173
+ let tick = Arc::new(AtomicU32::new(0));
174
+ move |samples: &[f32]| {
175
+ if tick.fetch_add(1, Ordering::Relaxed) % SHARED_LEVEL_EVERY != 0 {
176
+ return;
177
+ }
178
+ // Sparse peak — a meter does not need every frame.
179
+ let step = (samples.len() / 64).max(1);
180
+ let level = samples
181
+ .iter()
182
+ .step_by(step)
183
+ .fold(0.0f32, |peak, sample| peak.max(sample.abs()))
184
+ .min(1.0);
185
+ let _ = app.emit(
186
+ "voice:audio-level",
187
+ serde_json::json!({ "level": level, "source": source }),
188
+ );
189
+ }
190
+ }
191
+
160
192
  /// One transcript segment with real timestamps from whisper, already
161
193
  /// offset onto the meeting timeline (ms since capture start).
162
194
  #[derive(Serialize, Clone)]
@@ -1056,15 +1088,19 @@ mod macos {
1056
1088
  // RawMicCapture, or raw system capture is opened.
1057
1089
  let shared_audio = if owner == SessionOwner::Meeting {
1058
1090
  let mic_for_shared = mic_stream.clone();
1091
+ let mic_level = shared_level_tap(app.clone(), "mic");
1059
1092
  let shared_mic = Arc::new(move |samples: &[f32], sample_rate: f64| {
1060
1093
  mic_for_shared.set_src_rate(sample_rate);
1061
1094
  mic_for_shared.push(samples);
1095
+ mic_level(samples);
1062
1096
  });
1063
1097
  let shared_system = sys_stream.as_ref().map(|stream| {
1064
1098
  let stream = stream.clone();
1099
+ let system_level = shared_level_tap(app.clone(), "system");
1065
1100
  Arc::new(move |samples: &[f32], sample_rate: f64| {
1066
1101
  stream.set_src_rate(sample_rate);
1067
1102
  stream.push(samples);
1103
+ system_level(samples);
1068
1104
  }) as crate::capture_audio_bus::AudioCallback
1069
1105
  });
1070
1106
  match try_subscribe(
@@ -163,7 +163,9 @@ private UI after the shell loads. See the `authentication` skill and
163
163
  proves *someone* is signed in. To restrict an operation to some teammates, set
164
164
  `authorize` on the `defineAction`. It wraps `run`, so it applies at every
165
165
  dispatch site (agent tool, HTTP, frontend, MCP, A2A, CLI) — unlike
166
- `needsApproval`, which is honoured only in the agent loop.
166
+ `needsApproval`, which is honored by the agent loop and MCP 2026 hosts that
167
+ support elicitation, but is not an authorization boundary for every dispatch
168
+ site.
167
169
 
168
170
  ```ts
169
171
  import { coachAccess } from "../lib/access.js"; // defineAppRoles(...)
@@ -203,7 +205,16 @@ export default defineAction({
203
205
  });
204
206
  ```
205
207
 
206
- When the gate is truthy and the call is not yet approved, the loop emits an `approval_required` event and **stops the turn — `run()` never executes**. The human approves via the chat UI's Approve affordance, which re-issues the turn with the call's stable `approvalKey`; only then does the action run. A predicate gates conditionally (e.g. only external recipients) and **fails closed** — a throw is treated as "approval required".
208
+ When the gate is truthy and the call is not yet approved, the agent loop emits
209
+ an `approval_required` event and **stops the turn — `run()` never executes**.
210
+ The human approves via the chat UI's Approve affordance, which re-issues the
211
+ turn with the call's stable `approvalKey`; only then does the action run. MCP
212
+ 2026 hosts receive an `input_required` approval request bound to the exact
213
+ caller, action, and arguments. The signed response state is backed by a durable,
214
+ single-use grant, so denial, expiry, replay, missing host support, or invalid
215
+ state fails closed before `run()`. A predicate gates conditionally (e.g. only
216
+ external recipients) and **fails closed** — a throw is treated as "approval
217
+ required".
207
218
 
208
219
  Rules:
209
220
 
@@ -439,19 +439,43 @@ async function postBuilderMcp(args: {
439
439
  endpoint: string;
440
440
  privateKey: string;
441
441
  payload: Record<string, unknown>;
442
- sessionId?: string | null;
442
+ connection?: BuilderMcpConnection;
443
+ modernClientName?: string;
443
444
  fetchImpl: FetchLike;
444
445
  }) {
446
+ const method =
447
+ typeof args.payload.method === "string" ? args.payload.method : "";
448
+ const modernClientName =
449
+ args.modernClientName ??
450
+ (args.connection?.protocolVersion === "2026-07-28"
451
+ ? "agent-native-content-template"
452
+ : undefined);
453
+ const payload = modernClientName
454
+ ? withModernBuilderMcpEnvelope(args.payload, modernClientName)
455
+ : args.payload;
445
456
  const headers: Record<string, string> = {
446
457
  accept: "application/json, text/event-stream",
447
458
  authorization: `Bearer ${args.privateKey}`,
448
459
  "content-type": "application/json",
449
460
  };
450
- if (args.sessionId) headers["mcp-session-id"] = args.sessionId;
461
+ if (args.connection?.sessionId) {
462
+ headers["mcp-session-id"] = args.connection.sessionId;
463
+ }
464
+ if (modernClientName) {
465
+ headers["mcp-protocol-version"] = "2026-07-28";
466
+ headers["mcp-method"] = method;
467
+ const params = args.payload.params as Record<string, unknown> | undefined;
468
+ if (typeof params?.name === "string") {
469
+ headers["mcp-name"] = params.name;
470
+ }
471
+ if (method === "resources/read" && typeof params?.uri === "string") {
472
+ headers["mcp-name"] = params.uri;
473
+ }
474
+ }
451
475
  const response = await args.fetchImpl(args.endpoint, {
452
476
  method: "POST",
453
477
  headers,
454
- body: JSON.stringify(args.payload),
478
+ body: JSON.stringify(payload),
455
479
  });
456
480
  const text = await response.text();
457
481
  if (!response.ok) {
@@ -463,6 +487,44 @@ async function postBuilderMcp(args: {
463
487
  };
464
488
  }
465
489
 
490
+ interface BuilderMcpConnection {
491
+ protocolVersion: "2026-07-28" | "2025-11-25" | "2024-11-05";
492
+ sessionId: string | null;
493
+ }
494
+
495
+ function withModernBuilderMcpEnvelope(
496
+ payload: Record<string, unknown>,
497
+ clientName: string,
498
+ ): Record<string, unknown> {
499
+ const params =
500
+ payload.params &&
501
+ typeof payload.params === "object" &&
502
+ !Array.isArray(payload.params)
503
+ ? (payload.params as Record<string, unknown>)
504
+ : {};
505
+ const meta =
506
+ params._meta &&
507
+ typeof params._meta === "object" &&
508
+ !Array.isArray(params._meta)
509
+ ? (params._meta as Record<string, unknown>)
510
+ : {};
511
+ return {
512
+ ...payload,
513
+ params: {
514
+ ...params,
515
+ _meta: {
516
+ ...meta,
517
+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
518
+ "io.modelcontextprotocol/clientInfo": {
519
+ name: clientName,
520
+ version: "0.1.0",
521
+ },
522
+ "io.modelcontextprotocol/clientCapabilities": {},
523
+ },
524
+ },
525
+ };
526
+ }
527
+
466
528
  function builderMcpEntriesFromToolResponse(
467
529
  response: unknown,
468
530
  model: string,
@@ -593,39 +655,98 @@ async function initializeBuilderMcp(args: {
593
655
  privateKey: string;
594
656
  fetchImpl: FetchLike;
595
657
  }) {
596
- const initialized = await postBuilderMcp({
597
- endpoint: args.endpoint,
598
- privateKey: args.privateKey,
599
- fetchImpl: args.fetchImpl,
600
- payload: {
601
- jsonrpc: "2.0",
602
- id: 1,
603
- method: "initialize",
604
- params: {
605
- protocolVersion: "2024-11-05",
606
- capabilities: {},
607
- clientInfo: {
608
- name: "agent-native-content-template",
609
- version: "0.1.0",
610
- },
611
- },
612
- },
613
- });
614
- const sessionId = initialized.sessionId;
615
- if (sessionId) {
616
- await postBuilderMcp({
658
+ try {
659
+ const discovered = await postBuilderMcp({
617
660
  endpoint: args.endpoint,
618
661
  privateKey: args.privateKey,
619
662
  fetchImpl: args.fetchImpl,
620
- sessionId,
621
663
  payload: {
622
664
  jsonrpc: "2.0",
623
- method: "notifications/initialized",
665
+ id: 1,
666
+ method: "server/discover",
624
667
  params: {},
625
668
  },
626
- }).catch(() => null);
669
+ });
670
+ const result = discovered.json.result;
671
+ if (
672
+ result &&
673
+ typeof result === "object" &&
674
+ Array.isArray((result as Record<string, unknown>).supportedVersions) &&
675
+ (
676
+ (result as Record<string, unknown>).supportedVersions as unknown[]
677
+ ).includes("2026-07-28")
678
+ ) {
679
+ return {
680
+ protocolVersion: "2026-07-28",
681
+ sessionId: null,
682
+ } satisfies BuilderMcpConnection;
683
+ }
684
+ } catch (error) {
685
+ // A legacy server may reject server/discover before initialize.
686
+ if (
687
+ !(error instanceof Error) ||
688
+ !/HTTP (?:400|404|405)\./.test(error.message)
689
+ ) {
690
+ throw error;
691
+ }
692
+ }
693
+
694
+ const initializeLegacyProtocol = async (
695
+ protocolVersion: "2025-11-25" | "2024-11-05",
696
+ ) => {
697
+ const initialized = await postBuilderMcp({
698
+ endpoint: args.endpoint,
699
+ privateKey: args.privateKey,
700
+ fetchImpl: args.fetchImpl,
701
+ payload: {
702
+ jsonrpc: "2.0",
703
+ id: 1,
704
+ method: "initialize",
705
+ params: {
706
+ protocolVersion,
707
+ capabilities: {},
708
+ clientInfo: {
709
+ name: "agent-native-content-template",
710
+ version: "0.1.0",
711
+ },
712
+ },
713
+ },
714
+ });
715
+ if (initialized.json.error) {
716
+ throw new Error(
717
+ `Builder MCP initialize rejected protocol ${protocolVersion}.`,
718
+ );
719
+ }
720
+ const sessionId = initialized.sessionId;
721
+ if (sessionId) {
722
+ await postBuilderMcp({
723
+ endpoint: args.endpoint,
724
+ privateKey: args.privateKey,
725
+ fetchImpl: args.fetchImpl,
726
+ connection: { protocolVersion, sessionId },
727
+ payload: {
728
+ jsonrpc: "2.0",
729
+ method: "notifications/initialized",
730
+ params: {},
731
+ },
732
+ }).catch(() => null);
733
+ }
734
+ return {
735
+ protocolVersion,
736
+ sessionId,
737
+ } satisfies BuilderMcpConnection;
738
+ };
739
+
740
+ try {
741
+ return await initializeLegacyProtocol("2025-11-25");
742
+ } catch (error) {
743
+ const isProtocolRejection =
744
+ error instanceof Error &&
745
+ (/HTTP (?:400|404|405|422)\./.test(error.message) ||
746
+ error.message.includes("initialize rejected protocol"));
747
+ if (!isProtocolRejection) throw error;
748
+ return await initializeLegacyProtocol("2024-11-05");
627
749
  }
628
- return sessionId;
629
750
  }
630
751
 
631
752
  async function readBuilderCmsContentEntriesViaMcp(args: {
@@ -640,7 +761,7 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
640
761
  }): Promise<BuilderCmsReadResult> {
641
762
  const fetchedAt = new Date().toISOString();
642
763
  const endpoint = builderMcpEndpoint();
643
- const sessionId = await initializeBuilderMcp({
764
+ const connection = await initializeBuilderMcp({
644
765
  endpoint,
645
766
  privateKey: args.privateKey,
646
767
  fetchImpl: args.fetchImpl,
@@ -668,7 +789,7 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
668
789
  endpoint,
669
790
  privateKey: args.privateKey,
670
791
  fetchImpl: args.fetchImpl,
671
- sessionId,
792
+ connection,
672
793
  payload: {
673
794
  jsonrpc: "2.0",
674
795
  id: `content-${offset}`,
@@ -747,7 +868,7 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
747
868
  endpoint,
748
869
  privateKey: args.privateKey,
749
870
  fetchImpl: args.fetchImpl,
750
- sessionId,
871
+ connection,
751
872
  payload: {
752
873
  jsonrpc: "2.0",
753
874
  id: 3,
@@ -775,7 +896,7 @@ async function readBuilderCmsContentEntriesViaMcp(args: {
775
896
  endpoint,
776
897
  privateKey: args.privateKey,
777
898
  fetchImpl: args.fetchImpl,
778
- sessionId,
899
+ connection,
779
900
  payload: {
780
901
  jsonrpc: "2.0",
781
902
  id: `entry-${entry.id}`,
@@ -1046,7 +1167,7 @@ export async function listBuilderCmsModels(
1046
1167
 
1047
1168
  try {
1048
1169
  const endpoint = builderMcpEndpoint();
1049
- const sessionId = await initializeBuilderMcp({
1170
+ const connection = await initializeBuilderMcp({
1050
1171
  endpoint,
1051
1172
  privateKey,
1052
1173
  fetchImpl,
@@ -1055,7 +1176,7 @@ export async function listBuilderCmsModels(
1055
1176
  endpoint,
1056
1177
  privateKey,
1057
1178
  fetchImpl,
1058
- sessionId,
1179
+ connection,
1059
1180
  payload: {
1060
1181
  jsonrpc: "2.0",
1061
1182
  id: 2,
@@ -194,19 +194,43 @@ async function postBuilderMcp(args: {
194
194
  endpoint: string;
195
195
  privateKey: string;
196
196
  payload: Record<string, unknown>;
197
- sessionId?: string | null;
197
+ connection?: BuilderMcpConnection;
198
+ modernClientName?: string;
198
199
  fetchImpl: FetchLike;
199
200
  }) {
201
+ const method =
202
+ typeof args.payload.method === "string" ? args.payload.method : "";
203
+ const modernClientName =
204
+ args.modernClientName ??
205
+ (args.connection?.protocolVersion === "2026-07-28"
206
+ ? "agent-native-content-builder-mdx"
207
+ : undefined);
208
+ const payload = modernClientName
209
+ ? withModernBuilderMcpEnvelope(args.payload, modernClientName)
210
+ : args.payload;
200
211
  const headers: Record<string, string> = {
201
212
  accept: "application/json, text/event-stream",
202
213
  authorization: `Bearer ${args.privateKey}`,
203
214
  "content-type": "application/json",
204
215
  };
205
- if (args.sessionId) headers["mcp-session-id"] = args.sessionId;
216
+ if (args.connection?.sessionId) {
217
+ headers["mcp-session-id"] = args.connection.sessionId;
218
+ }
219
+ if (modernClientName) {
220
+ headers["mcp-protocol-version"] = "2026-07-28";
221
+ headers["mcp-method"] = method;
222
+ const params = args.payload.params as Record<string, unknown> | undefined;
223
+ if (typeof params?.name === "string") {
224
+ headers["mcp-name"] = params.name;
225
+ }
226
+ if (method === "resources/read" && typeof params?.uri === "string") {
227
+ headers["mcp-name"] = params.uri;
228
+ }
229
+ }
206
230
  const response = await args.fetchImpl(args.endpoint, {
207
231
  method: "POST",
208
232
  headers,
209
- body: JSON.stringify(args.payload),
233
+ body: JSON.stringify(payload),
210
234
  });
211
235
  const text = await response.text();
212
236
  if (!response.ok) {
@@ -218,44 +242,141 @@ async function postBuilderMcp(args: {
218
242
  };
219
243
  }
220
244
 
245
+ interface BuilderMcpConnection {
246
+ protocolVersion: "2026-07-28" | "2025-11-25" | "2024-11-05";
247
+ sessionId: string | null;
248
+ }
249
+
250
+ function withModernBuilderMcpEnvelope(
251
+ payload: Record<string, unknown>,
252
+ clientName: string,
253
+ ): Record<string, unknown> {
254
+ const params =
255
+ payload.params &&
256
+ typeof payload.params === "object" &&
257
+ !Array.isArray(payload.params)
258
+ ? (payload.params as Record<string, unknown>)
259
+ : {};
260
+ const meta =
261
+ params._meta &&
262
+ typeof params._meta === "object" &&
263
+ !Array.isArray(params._meta)
264
+ ? (params._meta as Record<string, unknown>)
265
+ : {};
266
+ return {
267
+ ...payload,
268
+ params: {
269
+ ...params,
270
+ _meta: {
271
+ ...meta,
272
+ "io.modelcontextprotocol/protocolVersion": "2026-07-28",
273
+ "io.modelcontextprotocol/clientInfo": {
274
+ name: clientName,
275
+ version: "0.1.0",
276
+ },
277
+ "io.modelcontextprotocol/clientCapabilities": {},
278
+ },
279
+ },
280
+ };
281
+ }
282
+
221
283
  async function initializeBuilderMcp(args: {
222
284
  endpoint: string;
223
285
  privateKey: string;
224
286
  fetchImpl: FetchLike;
225
287
  }) {
226
- const initialized = await postBuilderMcp({
227
- endpoint: args.endpoint,
228
- privateKey: args.privateKey,
229
- fetchImpl: args.fetchImpl,
230
- payload: {
231
- jsonrpc: "2.0",
232
- id: 1,
233
- method: "initialize",
234
- params: {
235
- protocolVersion: "2024-11-05",
236
- capabilities: {},
237
- clientInfo: {
238
- name: "agent-native-content-builder-mdx",
239
- version: "0.1.0",
240
- },
241
- },
242
- },
243
- });
244
- const sessionId = initialized.sessionId;
245
- if (sessionId) {
246
- await postBuilderMcp({
288
+ try {
289
+ const discovered = await postBuilderMcp({
247
290
  endpoint: args.endpoint,
248
291
  privateKey: args.privateKey,
249
292
  fetchImpl: args.fetchImpl,
250
- sessionId,
251
293
  payload: {
252
294
  jsonrpc: "2.0",
253
- method: "notifications/initialized",
295
+ id: 1,
296
+ method: "server/discover",
254
297
  params: {},
255
298
  },
256
- }).catch(() => null);
299
+ });
300
+ const result = discovered.json.result;
301
+ if (
302
+ result &&
303
+ typeof result === "object" &&
304
+ Array.isArray((result as Record<string, unknown>).supportedVersions) &&
305
+ (
306
+ (result as Record<string, unknown>).supportedVersions as unknown[]
307
+ ).includes("2026-07-28")
308
+ ) {
309
+ return {
310
+ protocolVersion: "2026-07-28",
311
+ sessionId: null,
312
+ } satisfies BuilderMcpConnection;
313
+ }
314
+ } catch (error) {
315
+ // A legacy server may reject server/discover before initialize.
316
+ if (
317
+ !(error instanceof Error) ||
318
+ !/HTTP (?:400|404|405)\./.test(error.message)
319
+ ) {
320
+ throw error;
321
+ }
322
+ }
323
+
324
+ const initializeLegacyProtocol = async (
325
+ protocolVersion: "2025-11-25" | "2024-11-05",
326
+ ) => {
327
+ const initialized = await postBuilderMcp({
328
+ endpoint: args.endpoint,
329
+ privateKey: args.privateKey,
330
+ fetchImpl: args.fetchImpl,
331
+ payload: {
332
+ jsonrpc: "2.0",
333
+ id: 1,
334
+ method: "initialize",
335
+ params: {
336
+ protocolVersion,
337
+ capabilities: {},
338
+ clientInfo: {
339
+ name: "agent-native-content-builder-mdx",
340
+ version: "0.1.0",
341
+ },
342
+ },
343
+ },
344
+ });
345
+ if (initialized.json.error) {
346
+ throw new Error(
347
+ `Builder MCP initialize rejected protocol ${protocolVersion}.`,
348
+ );
349
+ }
350
+ const sessionId = initialized.sessionId;
351
+ if (sessionId) {
352
+ await postBuilderMcp({
353
+ endpoint: args.endpoint,
354
+ privateKey: args.privateKey,
355
+ fetchImpl: args.fetchImpl,
356
+ connection: { protocolVersion, sessionId },
357
+ payload: {
358
+ jsonrpc: "2.0",
359
+ method: "notifications/initialized",
360
+ params: {},
361
+ },
362
+ }).catch(() => null);
363
+ }
364
+ return {
365
+ protocolVersion,
366
+ sessionId,
367
+ } satisfies BuilderMcpConnection;
368
+ };
369
+
370
+ try {
371
+ return await initializeLegacyProtocol("2025-11-25");
372
+ } catch (error) {
373
+ const isProtocolRejection =
374
+ error instanceof Error &&
375
+ (/HTTP (?:400|404|405|422)\./.test(error.message) ||
376
+ error.message.includes("initialize rejected protocol"));
377
+ if (!isProtocolRejection) throw error;
378
+ return await initializeLegacyProtocol("2024-11-05");
257
379
  }
258
- return sessionId;
259
380
  }
260
381
 
261
382
  function fullEntryFromToolResponse(value: unknown, model: string) {
@@ -363,7 +484,7 @@ async function readFullBuilderDocsEntryViaMcp(args: {
363
484
  privateKey: string;
364
485
  }) {
365
486
  const endpoint = builderMcpEndpoint();
366
- const sessionId = await initializeBuilderMcp({
487
+ const connection = await initializeBuilderMcp({
367
488
  endpoint,
368
489
  privateKey: args.privateKey,
369
490
  fetchImpl: args.fetchImpl,
@@ -372,7 +493,7 @@ async function readFullBuilderDocsEntryViaMcp(args: {
372
493
  endpoint,
373
494
  privateKey: args.privateKey,
374
495
  fetchImpl: args.fetchImpl,
375
- sessionId,
496
+ connection,
376
497
  payload: {
377
498
  jsonrpc: "2.0",
378
499
  id: `builder-mdx-${args.model}-${args.entryId}`,
@@ -39,6 +39,7 @@ const supportedBulkPropertyTypes = new Set<DocumentPropertyType>([
39
39
  "url",
40
40
  "email",
41
41
  "phone",
42
+ "files_media",
42
43
  ]);
43
44
 
44
45
  function parseSourceValues(
@@ -577,7 +578,9 @@ const fieldSchema = z.object({
577
578
  .passthrough(),
578
579
  z.null(),
579
580
  ])
580
- .describe("Value to set on the mapped Builder-backed field."),
581
+ .describe(
582
+ "Value to set on the mapped Builder-backed field. Builder File fields accept one http(s) URL as a string or one-item array; no media-picker upload is required.",
583
+ ),
581
584
  });
582
585
 
583
586
  export const stageBuilderSourceBulkUpdateSchema = z
@@ -645,7 +648,7 @@ export { stageBuilderSourceBulkUpdateWithDeps };
645
648
 
646
649
  export default defineAction({
647
650
  description:
648
- "Preview or stage one bounded bulk update across selected source-backed Builder CMS rows. This only stages local reviewable diffs; Builder writeback still goes through the existing review and execution actions.",
651
+ "Preview or stage one bounded bulk update across selected source-backed Builder CMS rows, including Builder File fields backed by Content Files & media properties. This only stages local reviewable diffs; Builder writeback still goes through the existing review and execution actions.",
649
652
  schema: stageBuilderSourceBulkUpdateSchema,
650
653
  run: async (
651
654
  args: StageBuilderSourceBulkUpdateRequest,