@agent-native/core 0.128.3 → 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 (350) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +91 -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/legacy-chart-shorthand.tsx +479 -0
  22. package/corpus/core/src/client/chat/markdown-renderer.tsx +23 -3
  23. package/corpus/core/src/client/chat/message-components.tsx +12 -5
  24. package/corpus/core/src/client/chat/runtime.ts +2 -1
  25. package/corpus/core/src/client/chat/tool-call-display.tsx +25 -2
  26. package/corpus/core/src/client/chat-model-groups.ts +3 -0
  27. package/corpus/core/src/client/client-status-requests.ts +161 -0
  28. package/corpus/core/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
  29. package/corpus/core/src/client/sse-event-processor.ts +15 -3
  30. package/corpus/core/src/client/use-agent-engine-configured.ts +54 -50
  31. package/corpus/core/src/client/use-chat-models.ts +16 -11
  32. package/corpus/core/src/client/use-chat-threads.ts +32 -9
  33. package/corpus/core/src/client/use-session.ts +4 -5
  34. package/corpus/core/src/db/client.ts +83 -8
  35. package/corpus/core/src/db/ensure-additive-columns.ts +31 -20
  36. package/corpus/core/src/db/migrations.ts +22 -2
  37. package/corpus/core/src/extensions/actions.ts +1 -1
  38. package/corpus/core/src/mcp/approval-store.ts +99 -0
  39. package/corpus/core/src/mcp/build-server.ts +579 -303
  40. package/corpus/core/src/mcp/embed-app.ts +1 -1
  41. package/corpus/core/src/mcp/oauth-client-metadata.ts +380 -0
  42. package/corpus/core/src/mcp/oauth-route.ts +57 -52
  43. package/corpus/core/src/mcp/screen-memory-stdio.ts +400 -378
  44. package/corpus/core/src/mcp/server.ts +29 -145
  45. package/corpus/core/src/mcp/stdio.ts +72 -80
  46. package/corpus/core/src/mcp-client/manager.ts +6 -10
  47. package/corpus/core/src/mcp-client/oauth-client.ts +127 -36
  48. package/corpus/core/src/mcp-client/oauth-routes.ts +16 -6
  49. package/corpus/core/src/mcp-client/routes.ts +6 -5
  50. package/corpus/core/src/server/agent-capabilities.ts +20 -0
  51. package/corpus/core/src/server/agent-chat/action-filters-a2a.ts +27 -0
  52. package/corpus/core/src/server/agent-chat-plugin.ts +18 -0
  53. package/corpus/core/src/server/transcribe-voice.ts +14 -5
  54. package/corpus/core/src/templates/default/.agents/skills/security/SKILL.md +13 -2
  55. package/corpus/core/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  56. package/corpus/core/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  57. package/corpus/core/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
  58. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +12 -0
  59. package/corpus/templates/analytics/.agents/skills/security/SKILL.md +13 -2
  60. package/corpus/templates/analytics/actions/generate-chart.ts +2 -2
  61. package/corpus/templates/analytics/app/components/dashboard/DashboardPanelSkeleton.tsx +1 -10
  62. package/corpus/templates/analytics/app/global.css +0 -31
  63. package/corpus/templates/analytics/app/lib/sql-query.ts +46 -20
  64. package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboard-loading-states-now-use-a-simpler-standar.md +6 -0
  65. package/corpus/templates/analytics/changelog/2026-07-28-analytics-dashboards-now-load-first-party-charts-reliably-in.md +6 -0
  66. package/corpus/templates/analytics/server/lib/first-party-analytics-cache.ts +42 -16
  67. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +4 -2
  68. package/corpus/templates/analytics/shared/sql-query-limits.ts +1 -0
  69. package/corpus/templates/assets/.agents/skills/security/SKILL.md +13 -2
  70. package/corpus/templates/brain/.agents/skills/security/SKILL.md +13 -2
  71. package/corpus/templates/calendar/.agents/skills/security/SKILL.md +13 -2
  72. package/corpus/templates/chat/.agents/skills/security/SKILL.md +13 -2
  73. package/corpus/templates/clips/.agents/skills/security/SKILL.md +13 -2
  74. package/corpus/templates/clips/app/components/player/player-controls.tsx +3 -6
  75. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +6 -2
  76. package/corpus/templates/clips/app/routes/share.$shareId.tsx +3 -1
  77. package/corpus/templates/clips/changelog/2026-07-28-copied-share-links-no-longer-leave-an-unnecessary-confirmati.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-07-28-playback-skip-controls-no-longer-show-overlapping-numbers.md +6 -0
  79. package/corpus/templates/clips/changelog/2026-07-28-public-clips-share-buttons-now-use-a-clean-text-only-label.md +6 -0
  80. package/corpus/templates/clips/desktop/src/app.tsx +14 -17
  81. package/corpus/templates/clips/desktop/src/overlays/live-audio-bars.tsx +3 -1
  82. package/corpus/templates/clips/desktop/src/styles.css +13 -10
  83. package/corpus/templates/clips/desktop/src-tauri/src/recording_indicator.rs +2 -2
  84. package/corpus/templates/clips/desktop/src-tauri/src/whisper_speech.rs +36 -0
  85. package/corpus/templates/content/.agents/skills/security/SKILL.md +13 -2
  86. package/corpus/templates/content/actions/_builder-cms-read-client.ts +155 -34
  87. package/corpus/templates/content/actions/_builder-docs-client.ts +151 -30
  88. package/corpus/templates/content/actions/stage-builder-source-bulk-update.ts +5 -2
  89. package/corpus/templates/content/app/root.tsx +35 -14
  90. package/corpus/templates/content/changelog/2026-07-28-builder-backed-files-media-fields-now-accept-direct-file-url.md +6 -0
  91. package/corpus/templates/content/changelog/2026-07-28-builder-content-reads-now-negotiate-the-newest-mcp-protocol-.md +6 -0
  92. package/corpus/templates/content/changelog/2026-07-28-public-content-pages-load-faster-before-the-optional-ask-sid.md +6 -0
  93. package/corpus/templates/design/.agents/skills/security/SKILL.md +13 -2
  94. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +36 -16
  95. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +42 -3
  96. package/corpus/templates/design/actions/open-visual-edit.ts +2 -1
  97. package/corpus/templates/design/app/components/design/CanvasContextMenu.tsx +2 -2
  98. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +14 -15
  99. package/corpus/templates/design/app/components/design/ResponsiveInteractBar.tsx +314 -0
  100. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +88 -3
  101. package/corpus/templates/design/app/components/design/keyboard-shortcuts.ts +1 -1
  102. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +7 -6
  103. package/corpus/templates/design/app/i18n-data.ts +56 -11
  104. package/corpus/templates/design/app/i18n-responsive-interact.ts +183 -0
  105. package/corpus/templates/design/app/lib/agent-chat.ts +60 -0
  106. package/corpus/templates/design/app/pages/design-editor/responsive-interact.ts +89 -0
  107. package/corpus/templates/design/changelog/2026-07-28-design-edits-can-be-applied-through-the-host-coding-agent-fr.md +6 -0
  108. package/corpus/templates/design/changelog/2026-07-28-interact-mode-can-preview-designs-in-responsive-device-sizes.md +6 -0
  109. package/corpus/templates/design/changelog/2026-07-28-interact-mode-now-opens-a-full-screen-responsive-preview-wit.md +6 -0
  110. package/corpus/templates/design/changelog/2026-07-28-show-or-hide-design-editing-chrome-with-cmd-on-apple-devices.md +2 -2
  111. package/corpus/templates/design/changelog/2026-07-28-visual-edit-now-always-shows-the-live-running-app-in-the-can.md +6 -0
  112. package/corpus/templates/dispatch/.agents/skills/security/SKILL.md +13 -2
  113. package/corpus/templates/forms/.agents/skills/security/SKILL.md +13 -2
  114. package/corpus/templates/macros/.agents/skills/security/SKILL.md +13 -2
  115. package/corpus/templates/mail/.agents/skills/security/SKILL.md +13 -2
  116. package/corpus/templates/plan/.agents/skills/security/SKILL.md +13 -2
  117. package/corpus/templates/slides/.agents/skills/security/SKILL.md +13 -2
  118. package/corpus/templates/tasks/.agents/skills/security/SKILL.md +13 -2
  119. package/corpus/toolkit/CHANGELOG.md +13 -0
  120. package/corpus/toolkit/package.json +1 -1
  121. package/corpus/toolkit/src/chat-history.css +1 -2
  122. package/corpus/toolkit/src/composer/TiptapComposer.tsx +45 -0
  123. package/dist/a2a/client.d.ts +7 -0
  124. package/dist/a2a/client.d.ts.map +1 -1
  125. package/dist/a2a/client.js +8 -3
  126. package/dist/a2a/client.js.map +1 -1
  127. package/dist/a2a/server.d.ts.map +1 -1
  128. package/dist/a2a/server.js +18 -3
  129. package/dist/a2a/server.js.map +1 -1
  130. package/dist/a2a/types.d.ts +7 -0
  131. package/dist/a2a/types.d.ts.map +1 -1
  132. package/dist/a2a/types.js.map +1 -1
  133. package/dist/action.d.ts +15 -1
  134. package/dist/action.d.ts.map +1 -1
  135. package/dist/action.js +39 -16
  136. package/dist/action.js.map +1 -1
  137. package/dist/agent/engine/ai-sdk-engine.d.ts.map +1 -1
  138. package/dist/agent/engine/ai-sdk-engine.js +14 -10
  139. package/dist/agent/engine/ai-sdk-engine.js.map +1 -1
  140. package/dist/agent/production-agent.d.ts.map +1 -1
  141. package/dist/agent/production-agent.js +35 -7
  142. package/dist/agent/production-agent.js.map +1 -1
  143. package/dist/agent/thread-data-builder.d.ts +2 -0
  144. package/dist/agent/thread-data-builder.d.ts.map +1 -1
  145. package/dist/agent/thread-data-builder.js +3 -0
  146. package/dist/agent/thread-data-builder.js.map +1 -1
  147. package/dist/chat-threads/migrations.d.ts +21 -0
  148. package/dist/chat-threads/migrations.d.ts.map +1 -0
  149. package/dist/chat-threads/migrations.js +45 -0
  150. package/dist/chat-threads/migrations.js.map +1 -0
  151. package/dist/cli/create.d.ts.map +1 -1
  152. package/dist/cli/create.js +4 -0
  153. package/dist/cli/create.js.map +1 -1
  154. package/dist/cli/skills-content/design-visual-edit-skill.d.ts +1 -1
  155. package/dist/cli/skills-content/design-visual-edit-skill.d.ts.map +1 -1
  156. package/dist/cli/skills-content/design-visual-edit-skill.js +36 -16
  157. package/dist/cli/skills-content/design-visual-edit-skill.js.map +1 -1
  158. package/dist/cli/skills.d.ts.map +1 -1
  159. package/dist/cli/skills.js +15 -0
  160. package/dist/cli/skills.js.map +1 -1
  161. package/dist/client/AgentPanel.d.ts.map +1 -1
  162. package/dist/client/AgentPanel.js +6 -5
  163. package/dist/client/AgentPanel.js.map +1 -1
  164. package/dist/client/AssistantChat.d.ts +37 -0
  165. package/dist/client/AssistantChat.d.ts.map +1 -1
  166. package/dist/client/AssistantChat.js +41 -8
  167. package/dist/client/AssistantChat.js.map +1 -1
  168. package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
  169. package/dist/client/MultiTabAssistantChat.js +11 -10
  170. package/dist/client/MultiTabAssistantChat.js.map +1 -1
  171. package/dist/client/agent-chat-adapter.d.ts.map +1 -1
  172. package/dist/client/agent-chat-adapter.js +19 -3
  173. package/dist/client/agent-chat-adapter.js.map +1 -1
  174. package/dist/client/analytics.d.ts.map +1 -1
  175. package/dist/client/analytics.js +150 -101
  176. package/dist/client/analytics.js.map +1 -1
  177. package/dist/client/chat/legacy-chart-shorthand.d.ts +29 -0
  178. package/dist/client/chat/legacy-chart-shorthand.d.ts.map +1 -0
  179. package/dist/client/chat/legacy-chart-shorthand.js +330 -0
  180. package/dist/client/chat/legacy-chart-shorthand.js.map +1 -0
  181. package/dist/client/chat/markdown-renderer.d.ts.map +1 -1
  182. package/dist/client/chat/markdown-renderer.js +8 -2
  183. package/dist/client/chat/markdown-renderer.js.map +1 -1
  184. package/dist/client/chat/message-components.d.ts +2 -1
  185. package/dist/client/chat/message-components.d.ts.map +1 -1
  186. package/dist/client/chat/message-components.js +11 -4
  187. package/dist/client/chat/message-components.js.map +1 -1
  188. package/dist/client/chat/runtime.d.ts.map +1 -1
  189. package/dist/client/chat/runtime.js +2 -1
  190. package/dist/client/chat/runtime.js.map +1 -1
  191. package/dist/client/chat/tool-call-display.d.ts +4 -1
  192. package/dist/client/chat/tool-call-display.d.ts.map +1 -1
  193. package/dist/client/chat/tool-call-display.js +14 -8
  194. package/dist/client/chat/tool-call-display.js.map +1 -1
  195. package/dist/client/chat-model-groups.d.ts.map +1 -1
  196. package/dist/client/chat-model-groups.js +3 -0
  197. package/dist/client/chat-model-groups.js.map +1 -1
  198. package/dist/client/client-status-requests.d.ts +14 -0
  199. package/dist/client/client-status-requests.d.ts.map +1 -0
  200. package/dist/client/client-status-requests.js +126 -0
  201. package/dist/client/client-status-requests.js.map +1 -0
  202. package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
  203. package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
  204. package/dist/client/sse-event-processor.d.ts +7 -0
  205. package/dist/client/sse-event-processor.d.ts.map +1 -1
  206. package/dist/client/sse-event-processor.js +8 -3
  207. package/dist/client/sse-event-processor.js.map +1 -1
  208. package/dist/client/use-agent-engine-configured.d.ts.map +1 -1
  209. package/dist/client/use-agent-engine-configured.js +29 -43
  210. package/dist/client/use-agent-engine-configured.js.map +1 -1
  211. package/dist/client/use-chat-models.d.ts.map +1 -1
  212. package/dist/client/use-chat-models.js +11 -11
  213. package/dist/client/use-chat-models.js.map +1 -1
  214. package/dist/client/use-chat-threads.d.ts.map +1 -1
  215. package/dist/client/use-chat-threads.js +23 -7
  216. package/dist/client/use-chat-threads.js.map +1 -1
  217. package/dist/client/use-session.d.ts.map +1 -1
  218. package/dist/client/use-session.js +4 -4
  219. package/dist/client/use-session.js.map +1 -1
  220. package/dist/collab/awareness.d.ts +2 -2
  221. package/dist/collab/awareness.d.ts.map +1 -1
  222. package/dist/db/client.d.ts.map +1 -1
  223. package/dist/db/client.js +48 -4
  224. package/dist/db/client.js.map +1 -1
  225. package/dist/db/ensure-additive-columns.d.ts.map +1 -1
  226. package/dist/db/ensure-additive-columns.js +32 -21
  227. package/dist/db/ensure-additive-columns.js.map +1 -1
  228. package/dist/db/migrations.d.ts +9 -0
  229. package/dist/db/migrations.d.ts.map +1 -1
  230. package/dist/db/migrations.js +14 -3
  231. package/dist/db/migrations.js.map +1 -1
  232. package/dist/extensions/actions.js +1 -1
  233. package/dist/extensions/actions.js.map +1 -1
  234. package/dist/mcp/approval-store.d.ts +16 -0
  235. package/dist/mcp/approval-store.d.ts.map +1 -0
  236. package/dist/mcp/approval-store.js +85 -0
  237. package/dist/mcp/approval-store.js.map +1 -0
  238. package/dist/mcp/build-server.d.ts +1 -34
  239. package/dist/mcp/build-server.d.ts.map +1 -1
  240. package/dist/mcp/build-server.js +220 -23
  241. package/dist/mcp/build-server.js.map +1 -1
  242. package/dist/mcp/embed-app.js +1 -1
  243. package/dist/mcp/embed-app.js.map +1 -1
  244. package/dist/mcp/oauth-client-metadata.d.ts +15 -0
  245. package/dist/mcp/oauth-client-metadata.d.ts.map +1 -0
  246. package/dist/mcp/oauth-client-metadata.js +297 -0
  247. package/dist/mcp/oauth-client-metadata.js.map +1 -0
  248. package/dist/mcp/oauth-route.d.ts.map +1 -1
  249. package/dist/mcp/oauth-route.js +39 -53
  250. package/dist/mcp/oauth-route.js.map +1 -1
  251. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
  252. package/dist/mcp/screen-memory-stdio.js +304 -296
  253. package/dist/mcp/screen-memory-stdio.js.map +1 -1
  254. package/dist/mcp/server.d.ts +12 -25
  255. package/dist/mcp/server.d.ts.map +1 -1
  256. package/dist/mcp/server.js +24 -133
  257. package/dist/mcp/server.js.map +1 -1
  258. package/dist/mcp/stdio.d.ts.map +1 -1
  259. package/dist/mcp/stdio.js +36 -35
  260. package/dist/mcp/stdio.js.map +1 -1
  261. package/dist/mcp-client/manager.d.ts.map +1 -1
  262. package/dist/mcp-client/manager.js +6 -6
  263. package/dist/mcp-client/manager.js.map +1 -1
  264. package/dist/mcp-client/oauth-client.d.ts +13 -17
  265. package/dist/mcp-client/oauth-client.d.ts.map +1 -1
  266. package/dist/mcp-client/oauth-client.js +74 -16
  267. package/dist/mcp-client/oauth-client.js.map +1 -1
  268. package/dist/mcp-client/oauth-routes.d.ts +2 -2
  269. package/dist/mcp-client/oauth-routes.d.ts.map +1 -1
  270. package/dist/mcp-client/oauth-routes.js +16 -6
  271. package/dist/mcp-client/oauth-routes.js.map +1 -1
  272. package/dist/mcp-client/routes.js +5 -5
  273. package/dist/mcp-client/routes.js.map +1 -1
  274. package/dist/notifications/routes.d.ts +1 -1
  275. package/dist/progress/routes.d.ts +1 -1
  276. package/dist/resources/handlers.d.ts +1 -1
  277. package/dist/secrets/routes.d.ts +9 -9
  278. package/dist/server/agent-capabilities.d.ts.map +1 -1
  279. package/dist/server/agent-capabilities.js +21 -0
  280. package/dist/server/agent-capabilities.js.map +1 -1
  281. package/dist/server/agent-chat/action-filters-a2a.d.ts +14 -0
  282. package/dist/server/agent-chat/action-filters-a2a.d.ts.map +1 -1
  283. package/dist/server/agent-chat/action-filters-a2a.js +16 -0
  284. package/dist/server/agent-chat/action-filters-a2a.js.map +1 -1
  285. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  286. package/dist/server/agent-chat-plugin.js +11 -1
  287. package/dist/server/agent-chat-plugin.js.map +1 -1
  288. package/dist/server/transcribe-voice.js +12 -6
  289. package/dist/server/transcribe-voice.js.map +1 -1
  290. package/dist/templates/chat/.agents/skills/security/SKILL.md +13 -2
  291. package/dist/templates/default/.agents/skills/security/SKILL.md +13 -2
  292. package/dist/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  293. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  294. package/dist/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
  295. package/docs/content/template-design-collaboration-and-full-apps.mdx +3 -1
  296. package/package.json +7 -4
  297. package/src/a2a/client.ts +18 -4
  298. package/src/a2a/server.ts +19 -3
  299. package/src/a2a/types.ts +7 -0
  300. package/src/action.ts +43 -16
  301. package/src/agent/engine/ai-sdk-engine.ts +14 -10
  302. package/src/agent/production-agent.ts +41 -3
  303. package/src/agent/thread-data-builder.ts +5 -0
  304. package/src/chat-threads/migrations.ts +53 -0
  305. package/src/cli/create.ts +4 -0
  306. package/src/cli/skills-content/design-visual-edit-skill.ts +36 -16
  307. package/src/cli/skills.ts +16 -0
  308. package/src/client/AgentPanel.tsx +9 -5
  309. package/src/client/AssistantChat.tsx +138 -46
  310. package/src/client/MultiTabAssistantChat.tsx +16 -10
  311. package/src/client/agent-chat-adapter.ts +21 -3
  312. package/src/client/analytics.ts +159 -102
  313. package/src/client/chat/legacy-chart-shorthand.tsx +479 -0
  314. package/src/client/chat/markdown-renderer.tsx +23 -3
  315. package/src/client/chat/message-components.tsx +12 -5
  316. package/src/client/chat/runtime.ts +2 -1
  317. package/src/client/chat/tool-call-display.tsx +25 -2
  318. package/src/client/chat-model-groups.ts +3 -0
  319. package/src/client/client-status-requests.ts +161 -0
  320. package/src/client/settings/VoiceTranscriptionSection.tsx +2 -2
  321. package/src/client/sse-event-processor.ts +15 -3
  322. package/src/client/use-agent-engine-configured.ts +54 -50
  323. package/src/client/use-chat-models.ts +16 -11
  324. package/src/client/use-chat-threads.ts +32 -9
  325. package/src/client/use-session.ts +4 -5
  326. package/src/db/client.ts +83 -8
  327. package/src/db/ensure-additive-columns.ts +31 -20
  328. package/src/db/migrations.ts +22 -2
  329. package/src/extensions/actions.ts +1 -1
  330. package/src/mcp/approval-store.ts +99 -0
  331. package/src/mcp/build-server.ts +579 -303
  332. package/src/mcp/embed-app.ts +1 -1
  333. package/src/mcp/oauth-client-metadata.ts +380 -0
  334. package/src/mcp/oauth-route.ts +57 -52
  335. package/src/mcp/screen-memory-stdio.ts +400 -378
  336. package/src/mcp/server.ts +29 -145
  337. package/src/mcp/stdio.ts +72 -80
  338. package/src/mcp-client/manager.ts +6 -10
  339. package/src/mcp-client/oauth-client.ts +127 -36
  340. package/src/mcp-client/oauth-routes.ts +16 -6
  341. package/src/mcp-client/routes.ts +6 -5
  342. package/src/server/agent-capabilities.ts +20 -0
  343. package/src/server/agent-chat/action-filters-a2a.ts +27 -0
  344. package/src/server/agent-chat-plugin.ts +18 -0
  345. package/src/server/transcribe-voice.ts +14 -5
  346. package/src/templates/chat/.agents/skills/security/SKILL.md +13 -2
  347. package/src/templates/default/.agents/skills/security/SKILL.md +13 -2
  348. package/src/templates/workspace-core/.agents/skills/authentication/SKILL.md +5 -2
  349. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +18 -0
  350. package/src/templates/workspace-core/.agents/skills/security/SKILL.md +13 -2
@@ -638,6 +638,27 @@ function sqlAndArgs(sql: DbExecStatement): {
638
638
  : { rawSql: sql.sql, args: sql.args || [] };
639
639
  }
640
640
 
641
+ const POSTGRES_STATEMENT_TIMEOUT_HEADROOM_MS = 250;
642
+ const POSTGRES_MAX_INT = 2_147_483_647;
643
+
644
+ function hasExplicitDbTimeout(statement: DbExecStatement): boolean {
645
+ if (typeof statement === "string") return false;
646
+ const timeoutMs = Number(statement.timeoutMs);
647
+ return Number.isFinite(timeoutMs) && timeoutMs > 0;
648
+ }
649
+
650
+ function postgresStatementTimeoutMs(clientTimeoutMs: number): number {
651
+ const safeTimeoutMs = Math.max(
652
+ 1,
653
+ Math.min(POSTGRES_MAX_INT, Math.floor(clientTimeoutMs)),
654
+ );
655
+ const headroomMs = Math.min(
656
+ POSTGRES_STATEMENT_TIMEOUT_HEADROOM_MS,
657
+ Math.max(1, Math.floor(safeTimeoutMs * 0.1)),
658
+ );
659
+ return Math.max(1, safeTimeoutMs - headroomMs);
660
+ }
661
+
641
662
  export function dbExecQueryBudget(statement: DbExecStatement): {
642
663
  timeoutMs: number;
643
664
  maxAttempts: number;
@@ -1229,6 +1250,36 @@ async function createDbExecInternal(
1229
1250
  rowsAffected: result.rowCount ?? 0,
1230
1251
  };
1231
1252
  }
1253
+ async function queryNeonClientWithStatementTimeout(
1254
+ client: any,
1255
+ sql: Parameters<DbExec["execute"]>[0],
1256
+ remainingMs: () => number,
1257
+ markClientForDiscard: () => void,
1258
+ ) {
1259
+ const statementTimeoutMs = postgresStatementTimeoutMs(remainingMs());
1260
+ await queryNeonClient(
1261
+ client,
1262
+ `SET statement_timeout = ${statementTimeoutMs}`,
1263
+ remainingMs(),
1264
+ );
1265
+ try {
1266
+ return await queryNeonClient(client, sql, remainingMs());
1267
+ } finally {
1268
+ try {
1269
+ await queryNeonClient(
1270
+ client,
1271
+ "RESET statement_timeout",
1272
+ remainingMs(),
1273
+ );
1274
+ } catch (err) {
1275
+ markClientForDiscard();
1276
+ console.warn(
1277
+ "[db/neon] statement timeout reset failed; discarding connection:",
1278
+ err instanceof Error ? err.message : err,
1279
+ );
1280
+ }
1281
+ }
1282
+ }
1232
1283
  return {
1233
1284
  async execute(sql) {
1234
1285
  const { timeoutMs, maxAttempts } = dbExecQueryBudget(sql);
@@ -1276,17 +1327,25 @@ async function createDbExecInternal(
1276
1327
  released = true;
1277
1328
  client.release(err);
1278
1329
  };
1330
+ let discardClient = false;
1279
1331
 
1280
1332
  try {
1281
- const result = await queryNeonClient(
1282
- client,
1283
- sql,
1284
- remainingAttemptMs(),
1285
- );
1286
- releaseClient();
1333
+ const result = hasExplicitDbTimeout(sql)
1334
+ ? await queryNeonClientWithStatementTimeout(
1335
+ client,
1336
+ sql,
1337
+ remainingAttemptMs,
1338
+ () => {
1339
+ discardClient = true;
1340
+ },
1341
+ )
1342
+ : await queryNeonClient(client, sql, remainingAttemptMs());
1343
+ releaseClient(discardClient ? true : undefined);
1287
1344
  return result;
1288
1345
  } catch (err) {
1289
- releaseClient(isConnectionError(err) ? true : undefined);
1346
+ releaseClient(
1347
+ discardClient || isConnectionError(err) ? true : undefined,
1348
+ );
1290
1349
  throw err;
1291
1350
  }
1292
1351
  }, maxAttempts);
@@ -1317,7 +1376,23 @@ async function createDbExecInternal(
1317
1376
  client.release(err);
1318
1377
  };
1319
1378
  const tx: DbExec = {
1320
- execute: (sql) => queryNeonClient(client, sql),
1379
+ execute: async (sql) => {
1380
+ if (!hasExplicitDbTimeout(sql)) {
1381
+ return queryNeonClient(client, sql);
1382
+ }
1383
+ const { timeoutMs } = dbExecQueryBudget(sql);
1384
+ const startedAt = Date.now();
1385
+ const remainingMs = () =>
1386
+ Math.max(1, timeoutMs - (Date.now() - startedAt));
1387
+ const statementTimeoutMs =
1388
+ postgresStatementTimeoutMs(remainingMs());
1389
+ await queryNeonClient(
1390
+ client,
1391
+ `SET LOCAL statement_timeout = ${statementTimeoutMs}`,
1392
+ remainingMs(),
1393
+ );
1394
+ return queryNeonClient(client, sql, remainingMs());
1395
+ },
1321
1396
  };
1322
1397
  try {
1323
1398
  await queryNeonClient(client, "BEGIN");
@@ -154,24 +154,23 @@ async function introspectPostgresColumns(
154
154
  args.push(schema, table);
155
155
  return `(table_schema = ? AND table_name = ?)`;
156
156
  });
157
- try {
158
- const { rows } = await db.execute({
159
- sql: `SELECT table_schema, table_name, column_name
160
- FROM information_schema.columns
161
- WHERE ${predicates.join(" OR ")}`,
162
- args,
163
- });
164
- const columns = new Map<string, Set<string>>();
165
- for (const row of rows) {
166
- const key = `${String(row.table_schema)}.${String(row.table_name)}`;
167
- const tableColumns = columns.get(key) ?? new Set<string>();
168
- tableColumns.add(String(row.column_name));
169
- columns.set(key, tableColumns);
170
- }
171
- return columns;
172
- } catch {
173
- return null;
157
+ // Deliberately not caught: this one query now covers every table, so
158
+ // swallowing a failure here would skip the entire safety net while
159
+ // reporting a clean result. The caller records it as an error instead.
160
+ const { rows } = await db.execute({
161
+ sql: `SELECT table_schema, table_name, column_name
162
+ FROM information_schema.columns
163
+ WHERE ${predicates.join(" OR ")}`,
164
+ args,
165
+ });
166
+ const columns = new Map<string, Set<string>>();
167
+ for (const row of rows) {
168
+ const key = `${String(row.table_schema)}.${String(row.table_name)}`;
169
+ const tableColumns = columns.get(key) ?? new Set<string>();
170
+ tableColumns.add(String(row.column_name));
171
+ columns.set(key, tableColumns);
174
172
  }
173
+ return columns;
175
174
  }
176
175
 
177
176
  /**
@@ -343,9 +342,21 @@ export async function ensureAdditiveColumns(
343
342
  }
344
343
  }
345
344
 
346
- const postgresColumns = isPostgres()
347
- ? await introspectPostgresColumns(db, declaredTables)
348
- : null;
345
+ let postgresColumns: Map<string, Set<string>> | null = null;
346
+ if (isPostgres()) {
347
+ try {
348
+ postgresColumns = await introspectPostgresColumns(db, declaredTables);
349
+ } catch (err) {
350
+ // One batch probe now covers every table, so its failure means nothing
351
+ // was checked. Returning an empty-but-clean result here would be
352
+ // indistinguishable from "schema already correct".
353
+ result.errors.push({
354
+ column: "*",
355
+ error: describeSchemaDriftError(err),
356
+ });
357
+ return result;
358
+ }
359
+ }
349
360
 
350
361
  for (const config of declaredTables) {
351
362
  const tableName = config.name;
@@ -230,6 +230,15 @@ export interface MigrationEntry {
230
230
  * throws at startup (programmer error, not a runtime data problem).
231
231
  */
232
232
  name?: string;
233
+ /**
234
+ * JS step for a backfill SQL cannot express — e.g. a repair whose value comes
235
+ * from application-level parsing of a stored blob. Runs BEFORE this entry's
236
+ * SQL and before the bookkeeping row is written, so a throw leaves the
237
+ * migration unrecorded and it retries on the next boot. Pass `sql: {}` for a
238
+ * run-only entry. Give run-only entries a `name`: the legacy version gate
239
+ * would otherwise mark them applied via any later migration's MAX advance.
240
+ */
241
+ run?: () => Promise<void>;
233
242
  }
234
243
 
235
244
  function resolveMigrationSql(sql: MigrationSql, pg: boolean): string | null {
@@ -368,6 +377,7 @@ export function runMigrations(
368
377
  try {
369
378
  // D1 is SQLite-compatible
370
379
  const raw = resolveMigrationSql(m.sql, false);
380
+ if (m.run) await m.run();
371
381
  const recordStatements = [
372
382
  m.name
373
383
  ? d1
@@ -385,8 +395,13 @@ export function runMigrations(
385
395
 
386
396
  if (raw == null) {
387
397
  // Dialect-gated migration with no SQL for this dialect; still
388
- // record it so we don't retry forever.
389
- for (const stmt of recordStatements) await stmt.run();
398
+ // record it so we don't retry forever. Keep the name + legacy
399
+ // version rows atomic: if an isolate is interrupted between
400
+ // separate writes, the name row would suppress every retry even
401
+ // though the legacy bookkeeping row never landed.
402
+ if (recordStatements.length > 0) {
403
+ await d1.batch(recordStatements);
404
+ }
390
405
  continue;
391
406
  }
392
407
  const originalStatements = splitSqlStatements(raw);
@@ -595,6 +610,11 @@ export function runMigrations(
595
610
  recordSql.push({ sql: insertVersionSql, args: [m.version] });
596
611
  }
597
612
 
613
+ // A throw here escapes to the outer handler with nothing recorded,
614
+ // so the entry is retried on the next boot rather than being marked
615
+ // applied against work that never happened.
616
+ if (m.run) await m.run();
617
+
598
618
  if (raw == null) {
599
619
  // Dialect-gated migration with no SQL for this dialect; still mark
600
620
  // as applied so we don't retry forever.
@@ -623,7 +623,7 @@ export function createExtensionActionEntries(): Record<string, ActionEntry> {
623
623
  "update-extension": {
624
624
  tool: {
625
625
  description:
626
- 'Update an existing sandboxed Alpine.js mini-app extension. Pass exactly three fields: `id`, `operation`, and `payloadJson`. `payloadJson` is a JSON object encoded as a string so model gateways cannot fill its optional members with invalid empty placeholders. For operation="edit", pass {"edits":[...]} or {"patches":[...]} and optional format=true. For operation="replace", pass exactly one of content, contentFromAttachment, or contentFromWorkspaceFile; use this operation only for a user-requested broad visual rewrite or complete replacement body. For operation="metadata", pass name, description, or icon. Change sharing through set-resource-visibility instead. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url> directly.',
626
+ 'Update an existing sandboxed Alpine.js mini-app extension. Pass exactly three fields: `id`, `operation`, and `payloadJson`. `payloadJson` is a JSON object encoded as a string so model gateways cannot fill its optional members with invalid empty placeholders. For operation="edit", pass {"edits":[...]} or {"patches":[...]} and optional format=true — prefer several small, targeted edits over one large one; a single edit/replace body over roughly 8KB risks the model truncating its own payloadJson mid-generation, which arrives here as an empty or malformed call that must be retried from scratch. For operation="replace", pass exactly one of content, contentFromAttachment, or contentFromWorkspaceFile; use this operation only for a user-requested broad visual rewrite or complete replacement body. Do not inline large static datasets (full metric histories, big arrays) into the HTML/JS body — store them with extension-data-set and fetch them at runtime via extensionData.list()/get() instead, so edits stay small regardless of dataset size. For operation="metadata", pass name, description, or icon. Change sharing through set-resource-visibility instead. If the user is viewing the extension, use the extensionId from <current-screen> or <current-url> directly.',
627
627
  parameters: {
628
628
  type: "object",
629
629
  properties: {
@@ -0,0 +1,99 @@
1
+ import { getDbExec, intType, isPostgres } from "../db/client.js";
2
+ import { ensureTableExists } from "../db/ddl-guard.js";
3
+
4
+ let initPromise: Promise<void> | undefined;
5
+
6
+ async function ensureApprovalTable(): Promise<void> {
7
+ if (!initPromise) {
8
+ initPromise = (async () => {
9
+ const createSql = `
10
+ CREATE TABLE IF NOT EXISTS mcp_action_approvals (
11
+ nonce TEXT PRIMARY KEY,
12
+ caller_key TEXT NOT NULL,
13
+ action_name TEXT NOT NULL,
14
+ arguments_hash TEXT NOT NULL,
15
+ expires_at ${intType()} NOT NULL,
16
+ consumed_at ${intType()}
17
+ )
18
+ `;
19
+ if (isPostgres()) {
20
+ await ensureTableExists("mcp_action_approvals", createSql);
21
+ } else {
22
+ await getDbExec().execute(createSql);
23
+ }
24
+ })().catch((error) => {
25
+ initPromise = undefined;
26
+ throw error;
27
+ });
28
+ }
29
+ return initPromise;
30
+ }
31
+
32
+ export interface McpApprovalGrant {
33
+ nonce: string;
34
+ callerKey: string;
35
+ actionName: string;
36
+ argumentsHash: string;
37
+ expiresAt: number;
38
+ }
39
+
40
+ export async function createMcpApprovalGrant(
41
+ grant: McpApprovalGrant,
42
+ ): Promise<void> {
43
+ await ensureApprovalTable();
44
+ const client = getDbExec();
45
+ await client.execute({
46
+ sql: `INSERT INTO mcp_action_approvals (nonce, caller_key, action_name, arguments_hash, expires_at, consumed_at) VALUES (?, ?, ?, ?, ?, NULL)`,
47
+ args: [
48
+ grant.nonce,
49
+ grant.callerKey,
50
+ grant.actionName,
51
+ grant.argumentsHash,
52
+ grant.expiresAt,
53
+ ],
54
+ });
55
+
56
+ // This is storage hygiene only. A failed cleanup must never turn a failed
57
+ // grant insert/consume into success, and expired rows remain unusable because
58
+ // consumeMcpApprovalGrant checks expires_at in the atomic update below.
59
+ try {
60
+ await client.execute({
61
+ sql: `DELETE FROM mcp_action_approvals WHERE expires_at < ?`,
62
+ args: [Date.now() - 24 * 60 * 60_000],
63
+ });
64
+ } catch (error) {
65
+ console.warn("[mcp] Could not clean expired action approval grants", error);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Atomically consume an exact grant. The UPDATE predicate is the security
71
+ * boundary: only one hosted instance can move a matching, unexpired row from
72
+ * pending to consumed, so an accepted response is at-most-once even when the
73
+ * same signed requestState is replayed concurrently.
74
+ */
75
+ export async function consumeMcpApprovalGrant(
76
+ grant: McpApprovalGrant,
77
+ ): Promise<boolean> {
78
+ await ensureApprovalTable();
79
+ const now = Date.now();
80
+ const result = await getDbExec().execute({
81
+ sql: `UPDATE mcp_action_approvals
82
+ SET consumed_at = ?
83
+ WHERE nonce = ?
84
+ AND caller_key = ?
85
+ AND action_name = ?
86
+ AND arguments_hash = ?
87
+ AND consumed_at IS NULL
88
+ AND expires_at >= ?`,
89
+ args: [
90
+ now,
91
+ grant.nonce,
92
+ grant.callerKey,
93
+ grant.actionName,
94
+ grant.argumentsHash,
95
+ now,
96
+ ],
97
+ });
98
+ return result.rowsAffected === 1;
99
+ }