@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
@@ -835,312 +835,320 @@ export async function queryScreenMemoryContextForStore(args, storeDir, env) {
835
835
  export async function runScreenMemoryMCPStdio(opts = {}) {
836
836
  const env = opts.env ?? process.env;
837
837
  const storeDir = opts.storeDir ?? defaultStoreDir(env);
838
- const { Server } = await import("@modelcontextprotocol/sdk/server/index.js");
839
- const { StdioServerTransport } = await import("@modelcontextprotocol/sdk/server/stdio.js");
840
- const { CallToolRequestSchema, ListToolsRequestSchema } = await import("@modelcontextprotocol/sdk/types.js");
841
- const server = new Server({ name: "clips-screen-memory", version: "0.1.0" }, { capabilities: { tools: {} } });
842
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
843
- tools: screenMemoryMcpToolDefinitions(),
844
- }));
845
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
846
- const name = request.params?.name;
847
- const args = (request.params?.arguments ?? {});
848
- if (name === "screen_memory_status") {
849
- const config = readFeatureConfig(storeDir);
850
- const segments = recentSegments(storeDir, 24 * 60);
851
- return textResult({
852
- enabled: config.enabled === true,
853
- paused: config.paused === true,
854
- retentionHours: config.retentionHours ?? 24,
855
- maxBytes: config.maxBytes ?? 20 * 1024 * 1024 * 1024,
856
- segmentCount: segments.length,
857
- totalBytes: segments.reduce((sum, segment) => sum + (segment.bytes || 0), 0),
858
- note: "The Screen Memory store is connected. Local archive paths are intentionally not exposed to agents.",
859
- });
860
- }
861
- if (name === "screen_memory_recent_context") {
862
- const result = await queryScreenMemoryContextForStore({
863
- query: typeof args.query === "string" ? args.query : undefined,
864
- sinceMinutes: typeof args.minutes === "number" ? args.minutes : undefined,
865
- limit: typeof args.limit === "number" ? args.limit : undefined,
866
- }, storeDir, env);
867
- const sanitizedEvidence = result.evidence.map((item) => ({
868
- ...item,
869
- excerpt: redactCredentialText(item.excerpt),
870
- }));
871
- const sanitizedItems = result.items.map((item) => ({
872
- ...item,
873
- text: redactCredentialText(item.text),
874
- sourceFile: "local-screen-memory",
875
- }));
876
- const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
877
- const packet = {
878
- question: typeof args.query === "string" && args.query.trim()
879
- ? redactCredentialText(args.query.trim().slice(0, 4_000))
880
- : "Recent Screen Memory context",
881
- evidence: sanitizedEvidence.slice(0, 20).map((item) => ({
882
- id: item.id,
883
- momentId: item.momentId,
884
- sourceType: item.sourceType,
885
- capturedAt: item.capturedAt,
886
- excerpt: item.excerpt.slice(0, 1_200),
887
- })),
888
- };
889
- appendEgressReceipt(storeDir, requestId, "recent-context", packet.evidence);
890
- return textResult(
891
- // Keep the old MCP envelope available while adding the typed contract.
892
- {
893
- events: sanitizedItems,
894
- ...result,
895
- items: sanitizedItems,
896
- evidence: sanitizedEvidence,
897
- contextFiles: [],
898
- egress: {
899
- requestId,
900
- packet,
901
- note: "A content-free local activity receipt was recorded before this bounded text packet was returned.",
902
- },
903
- });
904
- }
905
- if (name === "screen_memory_recent_segments") {
906
- const minutes = typeof args.minutes === "number" ? args.minutes : 30;
907
- const segments = recentSegments(storeDir, minutes);
908
- const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
909
- const packet = {
910
- question: `List recent Rewind segment references from the previous ${Math.max(1, Math.min(minutes, 24 * 60))} minutes`,
911
- evidence: segments.slice(0, 20).map((segment) => ({
912
- id: segment.id,
913
- momentId: `segment:${segment.id}`,
914
- sourceType: "app-context",
915
- capturedAt: segment.startedAt,
916
- excerpt: `Local media segment reference from ${segment.startedAt} to ${segment.endedAt}; media path and bytes were not exposed.`,
917
- })),
918
- };
919
- appendEgressReceipt(storeDir, requestId, "recent-segments", packet.evidence);
920
- return textResult({
921
- localOnly: true,
922
- mediaApprovalRequired: true,
923
- segments: segments.map((segment) => ({
924
- id: segment.id,
925
- startedAt: segment.startedAt,
926
- endedAt: segment.endedAt,
927
- mimeType: segment.mimeType,
928
- durationMs: segment.durationMs,
929
- })),
930
- egress: {
931
- requestId,
932
- packet,
933
- note: "A content-free local activity receipt was recorded before this bounded metadata packet was returned.",
934
- },
935
- });
936
- }
937
- if (name === "screen_memory_search_chapters") {
938
- if (typeof args.query !== "string" || !args.query.trim())
939
- throw new Error("query is required.");
940
- const document = readScreenMemoryChapters(storeDir);
941
- if (!document)
942
- throw new Error("No valid local Rewind chapters index is available yet.");
943
- const minutes = typeof args.minutes === "number" && Number.isFinite(args.minutes)
944
- ? Math.max(1, Math.min(Math.trunc(args.minutes), 24 * 60))
945
- : null;
946
- const cutoff = minutes ? Date.now() - minutes * 60_000 : null;
947
- const boundedDocument = cutoff
948
- ? {
949
- ...document,
950
- chapters: document.chapters.filter((chapter) => Date.parse(chapter.endedAt) >= cutoff),
951
- }
952
- : document;
953
- const candidates = searchScreenMemoryChapters(boundedDocument, args.query.trim(), typeof args.limit === "number" ? args.limit : 5, typeof args.clientHint === "string" ? args.clientHint : undefined);
954
- const ambiguous = candidates.length > 1 &&
955
- Math.abs(candidates[0].score - candidates[1].score) <= 0.05;
956
- const packet = {
957
- question: redactCredentialText(args.query.trim().slice(0, 4_000)),
958
- evidence: candidates.map((chapter) => ({
959
- id: chapter.id,
960
- momentId: chapter.id,
961
- sourceType: "chapter",
962
- capturedAt: chapter.startedAt,
963
- excerpt: redactCredentialText(`${chapter.label}: ${chapter.summary}`).slice(0, 1_200),
964
- })),
965
- };
966
- const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
967
- appendEgressReceipt(storeDir, requestId, "search-chapters", packet.evidence);
968
- return textResult({
969
- localOnly: true,
970
- generatedAt: document.generatedAt,
971
- state: document.state,
972
- coverage: document.coverage,
973
- gaps: isRecord(document.coverage) && Array.isArray(document.coverage.gaps)
974
- ? document.coverage.gaps
975
- : [],
976
- indexState: candidates.some((candidate) => candidate.indexState === "pending")
977
- ? "pending"
978
- : candidates.some((candidate) => candidate.indexState === "partial")
979
- ? "partial"
980
- : "ready",
981
- ambiguous,
982
- candidates: candidates.map(projectScreenMemoryChapterCandidate),
983
- egress: {
984
- requestId,
985
- packet,
986
- note: "A content-free local activity receipt was recorded before this bounded chapter packet was returned.",
987
- },
988
- });
989
- }
990
- if (name === "screen_memory_frame_at") {
991
- if (typeof args.timestamp !== "string")
992
- throw new Error("timestamp is required.");
993
- const frame = readScreenMemoryFrame(storeDir, args.timestamp, opts.decodeFrame ?? decodeFrameWithFfmpeg);
994
- appendLocalEvidenceReceipt(storeDir, "frame-at", [
995
- { timestamp: frame.timestamp, segmentId: frame.segmentId },
996
- ]);
997
- return {
998
- content: [
999
- {
1000
- type: "text",
1001
- text: JSON.stringify({
1002
- localOnly: true,
1003
- timestamp: frame.timestamp,
1004
- segmentId: frame.segmentId,
1005
- coverage: "retained clean segment",
1006
- note: "This is a bounded local image read. Request screen_memory_request_clip for motion or audio.",
1007
- }),
838
+ const { Server } = await import("@modelcontextprotocol/server");
839
+ const { serveStdio } = await import("@modelcontextprotocol/server/stdio");
840
+ const stdio = serveStdio(() => {
841
+ const server = new Server({ name: "clips-screen-memory", version: "0.1.0" }, { capabilities: { tools: {} } });
842
+ server.setRequestHandler("tools/list", async () => ({
843
+ tools: screenMemoryMcpToolDefinitions(),
844
+ }));
845
+ server.setRequestHandler("tools/call", async (request) => {
846
+ const name = request.params?.name;
847
+ const args = (request.params?.arguments ?? {});
848
+ if (name === "screen_memory_status") {
849
+ const config = readFeatureConfig(storeDir);
850
+ const segments = recentSegments(storeDir, 24 * 60);
851
+ return textResult({
852
+ enabled: config.enabled === true,
853
+ paused: config.paused === true,
854
+ retentionHours: config.retentionHours ?? 24,
855
+ maxBytes: config.maxBytes ?? 20 * 1024 * 1024 * 1024,
856
+ segmentCount: segments.length,
857
+ totalBytes: segments.reduce((sum, segment) => sum + (segment.bytes || 0), 0),
858
+ note: "The Screen Memory store is connected. Local archive paths are intentionally not exposed to agents.",
859
+ });
860
+ }
861
+ if (name === "screen_memory_recent_context") {
862
+ const result = await queryScreenMemoryContextForStore({
863
+ query: typeof args.query === "string" ? args.query : undefined,
864
+ sinceMinutes: typeof args.minutes === "number" ? args.minutes : undefined,
865
+ limit: typeof args.limit === "number" ? args.limit : undefined,
866
+ }, storeDir, env);
867
+ const sanitizedEvidence = result.evidence.map((item) => ({
868
+ ...item,
869
+ excerpt: redactCredentialText(item.excerpt),
870
+ }));
871
+ const sanitizedItems = result.items.map((item) => ({
872
+ ...item,
873
+ text: redactCredentialText(item.text),
874
+ sourceFile: "local-screen-memory",
875
+ }));
876
+ const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
877
+ const packet = {
878
+ question: typeof args.query === "string" && args.query.trim()
879
+ ? redactCredentialText(args.query.trim().slice(0, 4_000))
880
+ : "Recent Screen Memory context",
881
+ evidence: sanitizedEvidence.slice(0, 20).map((item) => ({
882
+ id: item.id,
883
+ momentId: item.momentId,
884
+ sourceType: item.sourceType,
885
+ capturedAt: item.capturedAt,
886
+ excerpt: item.excerpt.slice(0, 1_200),
887
+ })),
888
+ };
889
+ appendEgressReceipt(storeDir, requestId, "recent-context", packet.evidence);
890
+ return textResult(
891
+ // Keep the old MCP envelope available while adding the typed contract.
892
+ {
893
+ events: sanitizedItems,
894
+ ...result,
895
+ items: sanitizedItems,
896
+ evidence: sanitizedEvidence,
897
+ contextFiles: [],
898
+ egress: {
899
+ requestId,
900
+ packet,
901
+ note: "A content-free local activity receipt was recorded before this bounded text packet was returned.",
1008
902
  },
1009
- frame.image,
1010
- ],
1011
- };
1012
- }
1013
- if (name === "screen_memory_contact_sheet") {
1014
- const document = readScreenMemoryChapters(storeDir);
1015
- const chapter = typeof args.chapterId === "string"
1016
- ? document?.chapters.find((candidate) => candidate.id === args.chapterId)
1017
- : undefined;
1018
- const startAt = chapter?.startedAt ??
1019
- (typeof args.startAt === "string" ? args.startAt : null);
1020
- const endAt = chapter?.endedAt ??
1021
- (typeof args.endAt === "string" ? args.endAt : null);
1022
- if (!startAt || !endAt || !isTimestamp(startAt) || !isTimestamp(endAt))
1023
- throw new Error("Provide a valid chapterId or RFC3339 startAt and endAt.");
1024
- const durationMs = Date.parse(endAt) - Date.parse(startAt);
1025
- if (!contactSheetRangeIsValid(durationMs, Boolean(chapter)))
1026
- throw new Error("A contact sheet range must be between zero and five minutes.");
1027
- if (Date.parse(endAt) > Date.now() + 5_000)
1028
- throw new Error("A Rewind contact sheet cannot include future time.");
1029
- const count = Math.min(Math.max(Math.trunc(typeof args.count === "number" ? args.count : 4), 1), 8);
1030
- const representative = (chapter?.representativeMoments ?? [])
1031
- .filter((moment) => Date.parse(moment.capturedAt) >= Date.parse(startAt) &&
1032
- Date.parse(moment.capturedAt) <= Date.parse(endAt))
1033
- .map((moment) => moment.capturedAt);
1034
- const timestamps = selectContactSheetTimestamps(startAt, endAt, count, representative);
1035
- const decoder = opts.decodeFrame ?? decodeFrameWithFfmpeg;
1036
- const frames = timestamps.flatMap((timestamp) => {
1037
- try {
1038
- return [readScreenMemoryFrame(storeDir, timestamp, decoder)];
1039
- }
1040
- catch {
1041
- // A chapter may span a brief coverage gap. Keep the clean retained
1042
- // frames instead of failing the entire bounded contact sheet.
1043
- return [];
903
+ });
904
+ }
905
+ if (name === "screen_memory_recent_segments") {
906
+ const minutes = typeof args.minutes === "number" ? args.minutes : 30;
907
+ const segments = recentSegments(storeDir, minutes);
908
+ const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
909
+ const packet = {
910
+ question: `List recent Rewind segment references from the previous ${Math.max(1, Math.min(minutes, 24 * 60))} minutes`,
911
+ evidence: segments.slice(0, 20).map((segment) => ({
912
+ id: segment.id,
913
+ momentId: `segment:${segment.id}`,
914
+ sourceType: "app-context",
915
+ capturedAt: segment.startedAt,
916
+ excerpt: `Local media segment reference from ${segment.startedAt} to ${segment.endedAt}; media path and bytes were not exposed.`,
917
+ })),
918
+ };
919
+ appendEgressReceipt(storeDir, requestId, "recent-segments", packet.evidence);
920
+ return textResult({
921
+ localOnly: true,
922
+ mediaApprovalRequired: true,
923
+ segments: segments.map((segment) => ({
924
+ id: segment.id,
925
+ startedAt: segment.startedAt,
926
+ endedAt: segment.endedAt,
927
+ mimeType: segment.mimeType,
928
+ durationMs: segment.durationMs,
929
+ })),
930
+ egress: {
931
+ requestId,
932
+ packet,
933
+ note: "A content-free local activity receipt was recorded before this bounded metadata packet was returned.",
934
+ },
935
+ });
936
+ }
937
+ if (name === "screen_memory_search_chapters") {
938
+ if (typeof args.query !== "string" || !args.query.trim())
939
+ throw new Error("query is required.");
940
+ const document = readScreenMemoryChapters(storeDir);
941
+ if (!document)
942
+ throw new Error("No valid local Rewind chapters index is available yet.");
943
+ const minutes = typeof args.minutes === "number" && Number.isFinite(args.minutes)
944
+ ? Math.max(1, Math.min(Math.trunc(args.minutes), 24 * 60))
945
+ : null;
946
+ const cutoff = minutes ? Date.now() - minutes * 60_000 : null;
947
+ const boundedDocument = cutoff
948
+ ? {
949
+ ...document,
950
+ chapters: document.chapters.filter((chapter) => Date.parse(chapter.endedAt) >= cutoff),
951
+ }
952
+ : document;
953
+ const candidates = searchScreenMemoryChapters(boundedDocument, args.query.trim(), typeof args.limit === "number" ? args.limit : 5, typeof args.clientHint === "string" ? args.clientHint : undefined);
954
+ const ambiguous = candidates.length > 1 &&
955
+ Math.abs(candidates[0].score - candidates[1].score) <= 0.05;
956
+ const packet = {
957
+ question: redactCredentialText(args.query.trim().slice(0, 4_000)),
958
+ evidence: candidates.map((chapter) => ({
959
+ id: chapter.id,
960
+ momentId: chapter.id,
961
+ sourceType: "chapter",
962
+ capturedAt: chapter.startedAt,
963
+ excerpt: redactCredentialText(`${chapter.label}: ${chapter.summary}`).slice(0, 1_200),
964
+ })),
965
+ };
966
+ const requestId = `egress-mcp-${Date.now()}-${process.pid}`;
967
+ appendEgressReceipt(storeDir, requestId, "search-chapters", packet.evidence);
968
+ return textResult({
969
+ localOnly: true,
970
+ generatedAt: document.generatedAt,
971
+ state: document.state,
972
+ coverage: document.coverage,
973
+ gaps: isRecord(document.coverage) &&
974
+ Array.isArray(document.coverage.gaps)
975
+ ? document.coverage.gaps
976
+ : [],
977
+ indexState: candidates.some((candidate) => candidate.indexState === "pending")
978
+ ? "pending"
979
+ : candidates.some((candidate) => candidate.indexState === "partial")
980
+ ? "partial"
981
+ : "ready",
982
+ ambiguous,
983
+ candidates: candidates.map(projectScreenMemoryChapterCandidate),
984
+ egress: {
985
+ requestId,
986
+ packet,
987
+ note: "A content-free local activity receipt was recorded before this bounded chapter packet was returned.",
988
+ },
989
+ });
990
+ }
991
+ if (name === "screen_memory_frame_at") {
992
+ if (typeof args.timestamp !== "string")
993
+ throw new Error("timestamp is required.");
994
+ const frame = readScreenMemoryFrame(storeDir, args.timestamp, opts.decodeFrame ?? decodeFrameWithFfmpeg);
995
+ appendLocalEvidenceReceipt(storeDir, "frame-at", [
996
+ { timestamp: frame.timestamp, segmentId: frame.segmentId },
997
+ ]);
998
+ return {
999
+ content: [
1000
+ {
1001
+ type: "text",
1002
+ text: JSON.stringify({
1003
+ localOnly: true,
1004
+ timestamp: frame.timestamp,
1005
+ segmentId: frame.segmentId,
1006
+ coverage: "retained clean segment",
1007
+ note: "This is a bounded local image read. Request screen_memory_request_clip for motion or audio.",
1008
+ }),
1009
+ },
1010
+ frame.image,
1011
+ ],
1012
+ };
1013
+ }
1014
+ if (name === "screen_memory_contact_sheet") {
1015
+ const document = readScreenMemoryChapters(storeDir);
1016
+ const chapter = typeof args.chapterId === "string"
1017
+ ? document?.chapters.find((candidate) => candidate.id === args.chapterId)
1018
+ : undefined;
1019
+ const startAt = chapter?.startedAt ??
1020
+ (typeof args.startAt === "string" ? args.startAt : null);
1021
+ const endAt = chapter?.endedAt ??
1022
+ (typeof args.endAt === "string" ? args.endAt : null);
1023
+ if (!startAt ||
1024
+ !endAt ||
1025
+ !isTimestamp(startAt) ||
1026
+ !isTimestamp(endAt))
1027
+ throw new Error("Provide a valid chapterId or RFC3339 startAt and endAt.");
1028
+ const durationMs = Date.parse(endAt) - Date.parse(startAt);
1029
+ if (!contactSheetRangeIsValid(durationMs, Boolean(chapter)))
1030
+ throw new Error("A contact sheet range must be between zero and five minutes.");
1031
+ if (Date.parse(endAt) > Date.now() + 5_000)
1032
+ throw new Error("A Rewind contact sheet cannot include future time.");
1033
+ const count = Math.min(Math.max(Math.trunc(typeof args.count === "number" ? args.count : 4), 1), 8);
1034
+ const representative = (chapter?.representativeMoments ?? [])
1035
+ .filter((moment) => Date.parse(moment.capturedAt) >= Date.parse(startAt) &&
1036
+ Date.parse(moment.capturedAt) <= Date.parse(endAt))
1037
+ .map((moment) => moment.capturedAt);
1038
+ const timestamps = selectContactSheetTimestamps(startAt, endAt, count, representative);
1039
+ const decoder = opts.decodeFrame ?? decodeFrameWithFfmpeg;
1040
+ const frames = timestamps.flatMap((timestamp) => {
1041
+ try {
1042
+ return [readScreenMemoryFrame(storeDir, timestamp, decoder)];
1043
+ }
1044
+ catch {
1045
+ // A chapter may span a brief coverage gap. Keep the clean retained
1046
+ // frames instead of failing the entire bounded contact sheet.
1047
+ return [];
1048
+ }
1049
+ });
1050
+ if (frames.length === 0) {
1051
+ throw new Error("No clean retained Rewind frames cover the requested contact-sheet range.");
1044
1052
  }
1045
- });
1046
- if (frames.length === 0) {
1047
- throw new Error("No clean retained Rewind frames cover the requested contact-sheet range.");
1053
+ appendLocalEvidenceReceipt(storeDir, "contact-sheet", frames.map(({ timestamp, segmentId }) => ({
1054
+ timestamp,
1055
+ segmentId,
1056
+ })));
1057
+ return {
1058
+ content: [
1059
+ {
1060
+ type: "text",
1061
+ text: JSON.stringify({
1062
+ localOnly: true,
1063
+ chapterId: chapter?.id ?? null,
1064
+ startAt: new Date(Date.parse(startAt)).toISOString(),
1065
+ endAt: new Date(Date.parse(endAt)).toISOString(),
1066
+ frameCount: frames.length,
1067
+ selection: representative.length
1068
+ ? "representative moments then even coverage"
1069
+ : "even temporal coverage",
1070
+ frames: frames.map(({ timestamp, segmentId }) => ({
1071
+ timestamp,
1072
+ segmentId,
1073
+ })),
1074
+ }),
1075
+ },
1076
+ ...frames.map((frame) => frame.image),
1077
+ ],
1078
+ };
1048
1079
  }
1049
- appendLocalEvidenceReceipt(storeDir, "contact-sheet", frames.map(({ timestamp, segmentId }) => ({ timestamp, segmentId })));
1050
- return {
1051
- content: [
1052
- {
1053
- type: "text",
1054
- text: JSON.stringify({
1055
- localOnly: true,
1056
- chapterId: chapter?.id ?? null,
1057
- startAt: new Date(Date.parse(startAt)).toISOString(),
1058
- endAt: new Date(Date.parse(endAt)).toISOString(),
1059
- frameCount: frames.length,
1060
- selection: representative.length
1061
- ? "representative moments then even coverage"
1062
- : "even temporal coverage",
1063
- frames: frames.map(({ timestamp, segmentId }) => ({
1064
- timestamp,
1065
- segmentId,
1066
- })),
1067
- }),
1080
+ if (name === "screen_memory_request_clip") {
1081
+ const range = parseHandoffRange(args);
1082
+ const config = readFeatureConfig(storeDir);
1083
+ const requestId = `handoff-${randomUUID()}`;
1084
+ const reason = typeof args.reason === "string"
1085
+ ? redactCredentialText(args.reason.trim().slice(0, 500))
1086
+ : "Visual or audio context requested by the agent";
1087
+ const request = {
1088
+ requestId,
1089
+ status: "pending",
1090
+ requestedAt: new Date().toISOString(),
1091
+ ...range,
1092
+ reason,
1093
+ includeMicrophone: args.includeMicrophone !== false,
1094
+ includeSystemAudio: args.includeSystemAudio !== false,
1095
+ reviewRequired: config.reviewBeforeSending !== false,
1096
+ agentClipRetention: config.agentClipRetention ?? "forever",
1097
+ };
1098
+ writePrivateJson(handoffPath(storeDir, requestId), request);
1099
+ appendEgressEvent(storeDir, {
1100
+ requestId,
1101
+ occurredAt: request.requestedAt,
1102
+ state: "handoff-requested",
1103
+ operation: "request-clip",
1104
+ receipt: {
1105
+ mediaInterval: { startAt: range.startAt, endAt: range.endAt },
1106
+ reviewRequired: request.reviewRequired,
1068
1107
  },
1069
- ...frames.map((frame) => frame.image),
1070
- ],
1071
- };
1072
- }
1073
- if (name === "screen_memory_request_clip") {
1074
- const range = parseHandoffRange(args);
1075
- const config = readFeatureConfig(storeDir);
1076
- const requestId = `handoff-${randomUUID()}`;
1077
- const reason = typeof args.reason === "string"
1078
- ? redactCredentialText(args.reason.trim().slice(0, 500))
1079
- : "Visual or audio context requested by the agent";
1080
- const request = {
1081
- requestId,
1082
- status: "pending",
1083
- requestedAt: new Date().toISOString(),
1084
- ...range,
1085
- reason,
1086
- includeMicrophone: args.includeMicrophone !== false,
1087
- includeSystemAudio: args.includeSystemAudio !== false,
1088
- reviewRequired: config.reviewBeforeSending !== false,
1089
- agentClipRetention: config.agentClipRetention ?? "forever",
1090
- };
1091
- writePrivateJson(handoffPath(storeDir, requestId), request);
1092
- appendEgressEvent(storeDir, {
1093
- requestId,
1094
- occurredAt: request.requestedAt,
1095
- state: "handoff-requested",
1096
- operation: "request-clip",
1097
- receipt: {
1098
- mediaInterval: { startAt: range.startAt, endAt: range.endAt },
1108
+ evidenceCount: 0,
1109
+ packetBytes: 0,
1110
+ error: null,
1111
+ });
1112
+ return textResult({
1113
+ requestId,
1114
+ status: "pending",
1115
+ startAt: range.startAt,
1116
+ endAt: range.endAt,
1099
1117
  reviewRequired: request.reviewRequired,
1100
- },
1101
- evidenceCount: 0,
1102
- packetBytes: 0,
1103
- error: null,
1104
- });
1105
- return textResult({
1106
- requestId,
1107
- status: "pending",
1108
- startAt: range.startAt,
1109
- endAt: range.endAt,
1110
- reviewRequired: request.reviewRequired,
1111
- note: request.reviewRequired
1112
- ? "Clips is waiting for the user to review this bounded range. Poll screen_memory_handoff_status."
1113
- : "Clips is processing the explicitly requested bounded range. Poll screen_memory_handoff_status.",
1114
- });
1115
- }
1116
- if (name === "screen_memory_handoff_status") {
1117
- if (typeof args.requestId !== "string") {
1118
- throw new Error("requestId is required.");
1118
+ note: request.reviewRequired
1119
+ ? "Clips is waiting for the user to review this bounded range. Poll screen_memory_handoff_status."
1120
+ : "Clips is processing the explicitly requested bounded range. Poll screen_memory_handoff_status.",
1121
+ });
1119
1122
  }
1120
- const parsed = JSON.parse(fs.readFileSync(handoffPath(storeDir, args.requestId), "utf-8"));
1121
- return textResult({
1122
- requestId: parsed.requestId,
1123
- status: parsed.status,
1124
- startAt: parsed.startAt,
1125
- endAt: parsed.endAt,
1126
- recordingId: parsed.recordingId,
1127
- agentUrl: parsed.agentUrl,
1128
- contextUrl: parsed.contextUrl,
1129
- expiresAt: parsed.expiresAt,
1130
- autoDeleteAt: parsed.autoDeleteAt,
1131
- autoDeletedAt: parsed.autoDeletedAt,
1132
- error: parsed.error,
1133
- });
1134
- }
1135
- throw new Error(`Unknown Screen Memory tool: ${name}`);
1136
- });
1123
+ if (name === "screen_memory_handoff_status") {
1124
+ if (typeof args.requestId !== "string") {
1125
+ throw new Error("requestId is required.");
1126
+ }
1127
+ const parsed = JSON.parse(fs.readFileSync(handoffPath(storeDir, args.requestId), "utf-8"));
1128
+ return textResult({
1129
+ requestId: parsed.requestId,
1130
+ status: parsed.status,
1131
+ startAt: parsed.startAt,
1132
+ endAt: parsed.endAt,
1133
+ recordingId: parsed.recordingId,
1134
+ agentUrl: parsed.agentUrl,
1135
+ contextUrl: parsed.contextUrl,
1136
+ expiresAt: parsed.expiresAt,
1137
+ autoDeleteAt: parsed.autoDeleteAt,
1138
+ autoDeletedAt: parsed.autoDeletedAt,
1139
+ error: parsed.error,
1140
+ });
1141
+ }
1142
+ throw new Error(`Unknown Screen Memory tool: ${name}`);
1143
+ });
1144
+ return server;
1145
+ }, { legacy: "serve" });
1137
1146
  log(`Serving local Screen Memory from ${storeDir}`);
1138
- const transport = new StdioServerTransport();
1139
- await server.connect(transport);
1140
1147
  await new Promise((resolve) => {
1141
- transport.onclose = resolve;
1148
+ process.stdin.once("end", resolve);
1142
1149
  process.once("SIGINT", resolve);
1143
1150
  process.once("SIGTERM", resolve);
1144
1151
  });
1152
+ await stdio.close();
1145
1153
  }
1146
1154
  //# sourceMappingURL=screen-memory-stdio.js.map