@vellumai/assistant 0.12.1 → 0.12.2-dev.202609162214.308bda0

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 (859) hide show
  1. package/.env.example +2 -0
  2. package/AGENTS.md +5 -1
  3. package/ARCHITECTURE.md +20 -21
  4. package/Dockerfile +7 -7
  5. package/docs/architecture/integrations.md +7 -0
  6. package/docs/architecture/memory.md +11 -2
  7. package/docs/architecture/turn-actor.md +15 -8
  8. package/docs/credential-execution-service.md +1 -1
  9. package/docs/desktop-browser-cli.md +35 -0
  10. package/docs/guardian-request-flow.md +16 -0
  11. package/node_modules/@vellumai/environments/src/shell.test.ts +21 -0
  12. package/node_modules/@vellumai/environments/src/shell.ts +24 -0
  13. package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +8 -2
  14. package/node_modules/@vellumai/slack-text/src/index.ts +13 -8
  15. package/node_modules/@vellumai/slack-text/src/label-resolution-entities.test.ts +95 -0
  16. package/openapi.yaml +564 -111
  17. package/package.json +7 -4
  18. package/scripts/bundled-plugin-packages.ts +154 -0
  19. package/scripts/generate-bundled-plugin-packages.ts +29 -0
  20. package/scripts/postinstall.ts +33 -0
  21. package/scripts/smoke-desktop-browser-cli.ts +280 -0
  22. package/scripts/smoke-desktop-window-theme.ts +186 -0
  23. package/scripts/sync-llm-catalog.ts +3 -0
  24. package/scripts/test.ts +15 -13
  25. package/scripts/voice-ttft-spike.ts +2 -2
  26. package/src/__tests__/agent-loop.test.ts +124 -0
  27. package/src/__tests__/always-loaded-tools-guard.test.ts +18 -10
  28. package/src/__tests__/anthropic-provider.test.ts +0 -63
  29. package/src/__tests__/app-compiler.test.ts +6 -0
  30. package/src/__tests__/app-control-tool-schemas.test.ts +5 -2
  31. package/src/__tests__/app-dir-path-guard.test.ts +1 -3
  32. package/src/__tests__/approval-interception-trust-gates.test.ts +40 -0
  33. package/src/__tests__/assistant-event-hub-machine-name.test.ts +6 -7
  34. package/src/__tests__/assistant-event-hub.test.ts +44 -0
  35. package/src/__tests__/attachments-store.test.ts +22 -3
  36. package/src/__tests__/channel-approval.test.ts +9 -14
  37. package/src/__tests__/channel-reply-delivery.test.ts +56 -0
  38. package/src/__tests__/computer-use-screenshot-attachments.test.ts +411 -0
  39. package/src/__tests__/computer-use-screenshot-selection.test.ts +50 -0
  40. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  41. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +5 -2
  42. package/src/__tests__/computer-use-tools.test.ts +19 -7
  43. package/src/__tests__/config-schema-cmd.test.ts +2 -2
  44. package/src/__tests__/config-schema.test.ts +29 -30
  45. package/src/__tests__/config-sounds-sync.test.ts +23 -0
  46. package/src/__tests__/config-watcher.test.ts +23 -8
  47. package/src/__tests__/connection-model-compat.test.ts +2 -2
  48. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  49. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  50. package/src/__tests__/conversation-agent-loop.test.ts +257 -6
  51. package/src/__tests__/conversation-attachments.test.ts +106 -0
  52. package/src/__tests__/conversation-error.test.ts +4 -1
  53. package/src/__tests__/conversation-fork-crud.test.ts +191 -0
  54. package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -1
  55. package/src/__tests__/conversation-pairing.test.ts +26 -0
  56. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +4 -10
  57. package/src/__tests__/conversation-queue.test.ts +48 -207
  58. package/src/__tests__/conversation-retry-discard.test.ts +54 -1
  59. package/src/__tests__/conversation-runtime-assembly.test.ts +33 -3
  60. package/src/__tests__/conversation-skill-tools.test.ts +27 -0
  61. package/src/__tests__/conversation-surfaces-app-control.test.ts +8 -3
  62. package/src/__tests__/conversation-surfaces-point-at-budget.test.ts +1 -0
  63. package/src/__tests__/conversation-surfaces-point-at-capability.test.ts +1 -0
  64. package/src/__tests__/conversation-surfaces-task-progress.test.ts +67 -0
  65. package/src/__tests__/conversation-title-service.test.ts +14 -10
  66. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +3 -5
  67. package/src/__tests__/conversation-tool-setup-attribution.test.ts +51 -0
  68. package/src/__tests__/credential-execution-client.test.ts +70 -53
  69. package/src/__tests__/credential-record-retire.test.ts +171 -1
  70. package/src/__tests__/credential-routes.test.ts +250 -3
  71. package/src/__tests__/credential-security-invariants.test.ts +5 -3
  72. package/src/__tests__/cu-unified-flow.test.ts +14 -4
  73. package/src/__tests__/db-conversation-tool-surface.test.ts +144 -0
  74. package/src/__tests__/document-sync-tags.test.ts +25 -0
  75. package/src/__tests__/drain-kick-guard.test.ts +0 -2
  76. package/src/__tests__/drain-requeue-on-contention.test.ts +0 -6
  77. package/src/__tests__/events-tail-route.test.ts +33 -0
  78. package/src/__tests__/evict-conversations-for-reload.test.ts +1 -1
  79. package/src/__tests__/external-plugin-loader.test.ts +52 -0
  80. package/src/__tests__/git-porcelain.test.ts +47 -0
  81. package/src/__tests__/headless-browser-mode.test.ts +48 -0
  82. package/src/__tests__/heartbeat-service.test.ts +56 -40
  83. package/src/__tests__/helpers/set-workspace-mcp.ts +11 -0
  84. package/src/__tests__/host-bash-proxy.test.ts +26 -45
  85. package/src/__tests__/host-browser-proxy.test.ts +6 -17
  86. package/src/__tests__/host-cu-proxy.test.ts +712 -18
  87. package/src/__tests__/host-file-proxy-targeted.test.ts +23 -0
  88. package/src/__tests__/host-file-proxy.test.ts +11 -23
  89. package/src/__tests__/host-transfer-proxy-targeted.test.ts +30 -9
  90. package/src/__tests__/inference-profile-session-handler.test.ts +26 -0
  91. package/src/__tests__/list-all-apps.test.ts +40 -8
  92. package/src/__tests__/list-messages-camera-frame.test.ts +121 -0
  93. package/src/__tests__/list-messages-tool-merge.test.ts +85 -1
  94. package/src/__tests__/llm-catalog-parity.test.ts +51 -3
  95. package/src/__tests__/managed-store.test.ts +121 -0
  96. package/src/__tests__/mcp-auth-routes.test.ts +104 -8
  97. package/src/__tests__/mcp-client-auth.test.ts +54 -0
  98. package/src/__tests__/mcp-config-secret-boundary.test.ts +78 -136
  99. package/src/__tests__/mcp-health-check.test.ts +40 -43
  100. package/src/__tests__/mcp-list-plugin-servers.test.ts +85 -42
  101. package/src/__tests__/mcp-tool-annotations-risk.test.ts +4 -2
  102. package/src/__tests__/message-deleted-hook-dispatch.test.ts +119 -0
  103. package/src/__tests__/messages-after-tiebreaker.test.ts +91 -0
  104. package/src/__tests__/messages-read-boundary-guard.test.ts +1 -1
  105. package/src/__tests__/messaging-send-tool.test.ts +355 -548
  106. package/src/__tests__/model-intents.test.ts +3 -0
  107. package/src/__tests__/notification-vellum-adapter.test.ts +85 -2
  108. package/src/__tests__/oauth-apps-routes.test.ts +1 -0
  109. package/src/__tests__/oauth-commands-routes.test.ts +282 -101
  110. package/src/__tests__/oauth-connect-orchestrator.test.ts +2 -0
  111. package/src/__tests__/oauth-provider-profiles.test.ts +18 -0
  112. package/src/__tests__/oauth-provider-serializer.test.ts +23 -0
  113. package/src/__tests__/oauth-providers-routes.test.ts +3 -0
  114. package/src/__tests__/openai-provider.test.ts +1 -0
  115. package/src/__tests__/outlook-messaging-provider.test.ts +6 -6
  116. package/src/__tests__/persist-media-references.test.ts +50 -0
  117. package/src/__tests__/platform-callback-registration.test.ts +8 -16
  118. package/src/__tests__/platform-client-verify-credential.test.ts +2 -0
  119. package/src/__tests__/plugin-import-boundary-guard.test.ts +13 -0
  120. package/src/__tests__/qdrant-manager.test.ts +132 -0
  121. package/src/__tests__/resolve-app.test.ts +135 -0
  122. package/src/__tests__/run-conversation-turn-persistence.test.ts +138 -1
  123. package/src/__tests__/scaffold-managed-skill-tool.test.ts +317 -6
  124. package/src/__tests__/schedule-routes.test.ts +20 -0
  125. package/src/__tests__/scheduler-result-notification.test.ts +23 -4
  126. package/src/__tests__/script-proxy-certs.test.ts +35 -0
  127. package/src/__tests__/secret-routes-acp-guard.test.ts +59 -1
  128. package/src/__tests__/secret-routes-platform-proxy.test.ts +86 -31
  129. package/src/__tests__/secret-routes-scrub.test.ts +22 -27
  130. package/src/__tests__/secure-keys-managed-failover.test.ts +8 -0
  131. package/src/__tests__/secure-keys.test.ts +7 -3
  132. package/src/__tests__/service-account-token.test.ts +247 -0
  133. package/src/__tests__/skill-feature-flags-integration.test.ts +1 -1
  134. package/src/__tests__/skill-feature-flags.test.ts +2 -2
  135. package/src/__tests__/skills.test.ts +20 -4
  136. package/src/__tests__/source-fingerprint.test.ts +184 -0
  137. package/src/__tests__/subagent-tool-gate-mode.test.ts +239 -3
  138. package/src/__tests__/subagent-tools.test.ts +3 -2
  139. package/src/__tests__/telephony-tts-guard.test.ts +38 -3
  140. package/src/__tests__/terminal-tools.test.ts +8 -0
  141. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  142. package/src/__tests__/tool-result-metadata-plumbing.test.ts +63 -0
  143. package/src/__tests__/ui-channel-variants.test.ts +1 -56
  144. package/src/__tests__/unicode.test.ts +49 -0
  145. package/src/__tests__/user-plugin-loader.test.ts +21 -0
  146. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +4 -0
  147. package/src/__tests__/watch-retro-tool-availability.test.ts +8 -17
  148. package/src/__tests__/workspace-git-service.test.ts +26 -0
  149. package/src/__tests__/workspace-migration-154-repair-retired-codex-gpt-5-4-model-ids.test.ts +336 -0
  150. package/src/acp/__tests__/acp-claude-oauth.test.ts +257 -6
  151. package/src/acp/__tests__/acp-credentials.test.ts +13 -0
  152. package/src/acp/__tests__/agent-process.test.ts +258 -4
  153. package/src/acp/__tests__/auth-required.test.ts +96 -0
  154. package/src/acp/__tests__/claude-token-refresh.test.ts +257 -0
  155. package/src/acp/__tests__/client-handler.test.ts +90 -2
  156. package/src/acp/__tests__/helpers/acp-model-option.ts +51 -0
  157. package/src/acp/__tests__/prepare-agent-env.test.ts +60 -1
  158. package/src/acp/__tests__/session-manager-persistence.test.ts +5 -1
  159. package/src/acp/__tests__/session-manager-resume.test.ts +270 -6
  160. package/src/acp/__tests__/session-manager-usage.test.ts +4 -2
  161. package/src/acp/__tests__/session-manager.test.ts +895 -4
  162. package/src/acp/acp-claude-oauth.ts +328 -14
  163. package/src/acp/acp-credentials.ts +19 -0
  164. package/src/acp/agent-process.test.ts +4 -1
  165. package/src/acp/agent-process.ts +96 -10
  166. package/src/acp/auth-required.ts +50 -1
  167. package/src/acp/auto-install.test.ts +9 -7
  168. package/src/acp/claude-token-refresh.ts +150 -0
  169. package/src/acp/client-handler.ts +16 -3
  170. package/src/acp/model-config.test.ts +166 -0
  171. package/src/acp/model-config.ts +138 -0
  172. package/src/acp/prepare-agent-env.ts +21 -6
  173. package/src/acp/resolve-agent.test.ts +220 -6
  174. package/src/acp/resolve-agent.ts +88 -23
  175. package/src/acp/session-manager.test.ts +196 -3
  176. package/src/acp/session-manager.ts +441 -18
  177. package/src/acp/session-snapshot.ts +260 -0
  178. package/src/acp/types.ts +50 -5
  179. package/src/agent/loop.ts +20 -0
  180. package/src/api/attachment-provenance.test.ts +68 -0
  181. package/src/api/computer-use-tool.test.ts +55 -0
  182. package/src/api/computer-use-tool.ts +27 -0
  183. package/src/api/events/acp-session-model-update.test.ts +88 -0
  184. package/src/api/events/acp-session-model-update.ts +46 -0
  185. package/src/api/events/app-files-changed.ts +4 -3
  186. package/src/api/events/assistant-outbound-attachment.ts +3 -0
  187. package/src/api/events/desktop-activity-changed.ts +10 -0
  188. package/src/api/events/notification-intent.ts +2 -0
  189. package/src/api/events/user-message-echo.ts +7 -1
  190. package/src/api/index.ts +17 -0
  191. package/src/api/responses/conversation-message.ts +8 -0
  192. package/src/approvals/approval-primitive.ts +5 -2
  193. package/src/approvals/scoped-approval-grants.ts +6 -2
  194. package/src/apps/app-store.ts +7 -6
  195. package/src/apps/resolve-app.ts +81 -0
  196. package/src/apps/source-fingerprint.ts +266 -0
  197. package/src/avatar/identity-avatar.ts +7 -2
  198. package/src/browser/operations.ts +2 -1
  199. package/src/browser/types.ts +7 -0
  200. package/src/browser/virtual-desktop-target.ts +34 -0
  201. package/src/bundler/app-compiler.ts +15 -0
  202. package/src/calls/__tests__/barge-in-guard.test.ts +81 -0
  203. package/src/{__tests__ → calls/__tests__}/call-controller.test.ts +503 -82
  204. package/src/{__tests__ → calls/__tests__}/media-stream-audio-transcode.test.ts +1 -1
  205. package/src/{__tests__ → calls/__tests__}/media-stream-output.test.ts +37 -8
  206. package/src/{__tests__ → calls/__tests__}/media-stream-parser.test.ts +1 -1
  207. package/src/{__tests__ → calls/__tests__}/media-stream-server-integration.test.ts +150 -57
  208. package/src/{__tests__ → calls/__tests__}/media-stream-stt-session.test.ts +5 -5
  209. package/src/{__tests__ → calls/__tests__}/media-turn-detector.test.ts +1 -1
  210. package/src/{live-voice → calls}/__tests__/progress-narration.test.ts +27 -4
  211. package/src/{live-voice → calls}/__tests__/progress-phrases.test.ts +1 -1
  212. package/src/calls/__tests__/voice-control-protocol.test.ts +151 -27
  213. package/src/calls/__tests__/voice-leg-coordinator.test.ts +229 -0
  214. package/src/calls/__tests__/voice-progress-cadence.test.ts +274 -0
  215. package/src/{__tests__/voice-session-bridge.test.ts → calls/__tests__/voice-session-bridge-turn-flow.test.ts} +20 -12
  216. package/src/calls/__tests__/voice-session-bridge.test.ts +140 -3
  217. package/src/calls/__tests__/voice-triage-escalate.test.ts +105 -0
  218. package/src/calls/barge-in-guard.ts +118 -0
  219. package/src/calls/call-constants.ts +24 -4
  220. package/src/calls/call-controller.ts +499 -199
  221. package/src/calls/call-transport.ts +16 -0
  222. package/src/calls/media-stream-output.ts +32 -0
  223. package/src/calls/media-stream-server.ts +82 -30
  224. package/src/calls/media-stream-stt-session.ts +15 -0
  225. package/src/{live-voice → calls}/progress-narration.ts +17 -4
  226. package/src/calls/resolve-call-tts-provider.ts +33 -2
  227. package/src/calls/tts-call-strategy.ts +9 -5
  228. package/src/calls/types.ts +2 -0
  229. package/src/calls/voice-control-protocol.ts +194 -21
  230. package/src/calls/voice-leg-coordinator.ts +189 -0
  231. package/src/calls/voice-progress-cadence.ts +423 -0
  232. package/src/calls/voice-session-bridge.ts +140 -76
  233. package/src/calls/voice-triage-escalate.ts +178 -59
  234. package/src/cli/commands/__tests__/apps.test.ts +245 -0
  235. package/src/cli/commands/__tests__/bash.test.ts +53 -0
  236. package/src/cli/commands/__tests__/browser.test.ts +84 -3
  237. package/src/cli/commands/__tests__/cli-test-harness.ts +21 -3
  238. package/src/cli/commands/__tests__/plugins.test.ts +85 -0
  239. package/src/cli/commands/__tests__/roadmap.help.test.ts +19 -0
  240. package/src/cli/commands/__tests__/schedules.test.ts +14 -0
  241. package/src/cli/commands/apps.help.ts +67 -13
  242. package/src/cli/commands/apps.ts +183 -0
  243. package/src/cli/commands/bash.help.ts +9 -13
  244. package/src/cli/commands/bash.ts +7 -25
  245. package/src/cli/commands/browser.help.ts +43 -0
  246. package/src/cli/commands/browser.ts +52 -8
  247. package/src/cli/commands/channels/__tests__/send.test.ts +218 -0
  248. package/src/cli/commands/channels/index.help.ts +70 -2
  249. package/src/cli/commands/channels/index.ts +16 -3
  250. package/src/cli/commands/channels/send.ts +128 -0
  251. package/src/cli/commands/credentials.help.ts +9 -5
  252. package/src/cli/commands/credentials.ts +2 -2
  253. package/src/cli/commands/mcp.help.ts +8 -8
  254. package/src/cli/commands/mcp.ts +1 -1
  255. package/src/cli/commands/oauth/index.help.ts +10 -0
  256. package/src/cli/commands/oauth/providers.ts +12 -0
  257. package/src/cli/commands/oauth/request.test.ts +179 -2
  258. package/src/cli/commands/oauth/request.ts +41 -10
  259. package/src/cli/commands/oauth/status.ts +5 -0
  260. package/src/cli/commands/plugins.ts +73 -23
  261. package/src/cli/commands/roadmap.help.ts +5 -1
  262. package/src/cli/commands/roadmap.ts +1 -1
  263. package/src/cli/commands/schedules.ts +2 -0
  264. package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
  265. package/src/cli/lib/__tests__/install-from-github.test.ts +219 -0
  266. package/src/cli/lib/__tests__/install-from-platform.test.ts +77 -2
  267. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +45 -3
  268. package/src/cli/lib/__tests__/local-plugin-upgrade.test.ts +251 -0
  269. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +65 -2
  270. package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +14 -0
  271. package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +27 -1
  272. package/src/cli/lib/__tests__/plugin-details.test.ts +35 -2
  273. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +20 -0
  274. package/src/cli/lib/__tests__/plugins-install-offline.test.ts +43 -0
  275. package/src/cli/lib/__tests__/search-plugins.test.ts +31 -0
  276. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +122 -5
  277. package/src/cli/lib/bundled-marketplace.json +962 -81
  278. package/src/cli/lib/bundled-plugin-packages.json +786 -0
  279. package/src/cli/lib/bundled-plugin-packages.ts +87 -0
  280. package/src/cli/lib/diff-plugin.ts +1 -1
  281. package/src/cli/lib/inspect-plugin.ts +87 -12
  282. package/src/cli/lib/install-from-github.ts +150 -94
  283. package/src/cli/lib/install-from-platform.ts +14 -9
  284. package/src/cli/lib/list-installed-plugins.ts +21 -35
  285. package/src/cli/lib/plugin-catalog-cache.ts +22 -3
  286. package/src/cli/lib/plugin-catalog-local.ts +13 -3
  287. package/src/cli/lib/plugin-catalog-platform.ts +6 -1
  288. package/src/cli/lib/plugin-catalog-resolve.ts +20 -0
  289. package/src/cli/lib/plugin-details.ts +33 -8
  290. package/src/cli/lib/plugin-marketplace.ts +121 -21
  291. package/src/cli/lib/plugin-pin-history.ts +5 -2
  292. package/src/cli/lib/search-plugins.ts +58 -16
  293. package/src/cli/lib/uninstall-plugin.ts +59 -1
  294. package/src/cli/lib/upgrade-plugin.ts +61 -8
  295. package/src/cli/output.ts +18 -4
  296. package/src/config/__tests__/default-profile-catalog.test.ts +22 -0
  297. package/src/config/__tests__/default-provider.test.ts +4 -0
  298. package/src/config/__tests__/memory-retrospective-schema.test.ts +15 -1
  299. package/src/config/__tests__/platform-identity.test.ts +255 -0
  300. package/src/config/__tests__/platform-rehydration.test.ts +99 -9
  301. package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +21 -0
  302. package/src/config/acp-agent-write.ts +43 -0
  303. package/src/config/acp-defaults.test.ts +13 -3
  304. package/src/config/acp-defaults.ts +23 -6
  305. package/src/config/acp-schema.test.ts +81 -0
  306. package/src/config/acp-schema.ts +30 -2
  307. package/src/config/bundled-skills/acp/SKILL.md +23 -15
  308. package/src/config/bundled-skills/acp/TOOLS.json +7 -3
  309. package/src/config/bundled-skills/app-builder/SKILL.md +12 -9
  310. package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +1 -1
  311. package/src/config/bundled-skills/computer-use/SKILL.md +59 -2
  312. package/src/config/bundled-skills/computer-use/TOOLS.json +101 -2
  313. package/src/config/bundled-skills/computer-use/tools/computer-use-sequence.ts +12 -0
  314. package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -1
  315. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -1
  316. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -1
  317. package/src/config/bundled-skills/messaging/SKILL.md +3 -3
  318. package/src/config/bundled-skills/messaging/TOOLS.json +3 -3
  319. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +67 -139
  320. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +1 -1
  321. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -1
  322. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -1
  323. package/src/config/bundled-skills/schedule/SKILL.md +7 -8
  324. package/src/config/bundled-skills/screen-annotation/SKILL.md +10 -3
  325. package/src/config/bundled-skills/screen-annotation/tools/screen-annotation.test.ts +4 -1
  326. package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
  327. package/src/config/bundled-skills/skill-management/TOOLS.json +13 -9
  328. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +5 -2
  329. package/src/config/default-profile-catalog.ts +1 -1
  330. package/src/config/env.ts +2 -2
  331. package/src/config/feature-flag-registry.json +33 -13
  332. package/src/config/loader.ts +11 -17
  333. package/src/config/memory-v3-gate.test.ts +31 -0
  334. package/src/config/memory-v3-gate.ts +20 -16
  335. package/src/config/platform-identity.ts +201 -0
  336. package/src/config/platform-rehydration.ts +11 -27
  337. package/src/config/profile-text-generation.test.ts +51 -0
  338. package/src/config/profile-text-generation.ts +51 -0
  339. package/src/config/schema.ts +2 -2
  340. package/src/config/schemas/__tests__/live-voice.test.ts +8 -158
  341. package/src/config/schemas/__tests__/voice.test.ts +148 -0
  342. package/src/config/schemas/calls.ts +1 -28
  343. package/src/config/schemas/live-voice.ts +1 -173
  344. package/src/config/schemas/llm.ts +7 -2
  345. package/src/config/schemas/mcp.ts +15 -9
  346. package/src/config/schemas/memory-retrospective.ts +10 -0
  347. package/src/config/schemas/monitoring.ts +9 -0
  348. package/src/config/schemas/services.ts +18 -0
  349. package/src/config/schemas/skills.ts +0 -14
  350. package/src/config/schemas/voice.ts +150 -0
  351. package/src/config/skills.ts +13 -21
  352. package/src/credential-execution/ces-runtime.ts +2 -2
  353. package/src/credential-execution/executable-discovery.ts +36 -134
  354. package/src/credential-execution/process-manager.test.ts +37 -42
  355. package/src/credential-execution/process-manager.ts +24 -19
  356. package/src/credential-health/credential-health-service.ts +11 -17
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +47 -0
  358. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -121
  359. package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +5 -1
  360. package/src/daemon/__tests__/skill-memory-refresh-mtime.test.ts +133 -0
  361. package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +36 -0
  362. package/src/daemon/app-change-notify.ts +45 -0
  363. package/src/daemon/assistant-attachments.ts +20 -12
  364. package/src/daemon/config-watcher.ts +13 -194
  365. package/src/daemon/conversation-agent-loop-handlers.ts +74 -3
  366. package/src/daemon/conversation-agent-loop.ts +12 -0
  367. package/src/daemon/conversation-attachments.ts +93 -12
  368. package/src/daemon/conversation-client-surface.ts +26 -0
  369. package/src/daemon/conversation-error.ts +3 -2
  370. package/src/daemon/conversation-media-retry.ts +2 -1
  371. package/src/daemon/conversation-process.ts +35 -64
  372. package/src/daemon/conversation-runtime-assembly.ts +21 -8
  373. package/src/daemon/conversation-skill-tools.ts +13 -31
  374. package/src/daemon/conversation-store.ts +1 -1
  375. package/src/daemon/conversation-surfaces.ts +21 -10
  376. package/src/daemon/conversation-tool-setup.ts +135 -109
  377. package/src/daemon/conversation-turn-finalize.ts +26 -13
  378. package/src/daemon/conversation.ts +17 -3
  379. package/src/daemon/daemon-control.ts +3 -7
  380. package/src/daemon/dictation-profile-store.ts +2 -1
  381. package/src/daemon/handlers/shared.ts +2 -1
  382. package/src/daemon/handlers/skills.ts +6 -3
  383. package/src/daemon/host-bash-proxy.ts +8 -12
  384. package/src/daemon/host-browser-proxy.ts +15 -1
  385. package/src/daemon/host-cu-proxy.ts +275 -45
  386. package/src/daemon/host-file-proxy.ts +8 -10
  387. package/src/daemon/host-proxy-preactivation.ts +4 -1
  388. package/src/daemon/host-transfer-proxy.ts +14 -18
  389. package/src/daemon/lifecycle.ts +4 -9
  390. package/src/daemon/mcp-reload-service.ts +13 -6
  391. package/src/daemon/message-types/shared.ts +1 -0
  392. package/src/daemon/message-types/sync.ts +2 -0
  393. package/src/daemon/orphan-reaper.ts +4 -3
  394. package/src/daemon/persist-media-references.ts +20 -3
  395. package/src/daemon/providers-setup.ts +5 -1
  396. package/src/daemon/reaction-history-render.ts +2 -1
  397. package/src/daemon/shutdown-handlers.ts +1 -9
  398. package/src/daemon/skill-memory-refresh.ts +64 -0
  399. package/src/daemon/tool-setup-types.ts +6 -0
  400. package/src/daemon/tool-side-effects.ts +7 -18
  401. package/src/daemon/wake-conversation-ops.ts +38 -15
  402. package/src/desktop/__tests__/fake-desktop.ts +123 -0
  403. package/src/desktop/desktop-automation-lease.test.ts +351 -0
  404. package/src/desktop/desktop-automation-lease.ts +306 -0
  405. package/src/desktop/desktop-browser-client.test.ts +413 -0
  406. package/src/desktop/desktop-browser-client.ts +430 -0
  407. package/src/desktop/desktop-browser-cursor.ts +40 -0
  408. package/src/desktop/desktop-browser-endpoint.test.ts +78 -0
  409. package/src/desktop/desktop-browser-endpoint.ts +145 -0
  410. package/src/desktop/desktop-browser-operations.ts +130 -0
  411. package/src/desktop/desktop-chrome-policy.test.ts +79 -0
  412. package/src/desktop/desktop-chrome-policy.ts +47 -0
  413. package/src/desktop/desktop-chrome-session.test.ts +48 -0
  414. package/src/desktop/desktop-chrome-session.ts +87 -0
  415. package/src/desktop/desktop-dependencies.test.ts +131 -0
  416. package/src/desktop/desktop-dependencies.ts +329 -0
  417. package/src/desktop/desktop-display.ts +9 -0
  418. package/src/desktop/desktop-panel-config.test.ts +135 -0
  419. package/src/desktop/desktop-panel-config.ts +162 -0
  420. package/src/desktop/desktop-session-manager.test.ts +813 -0
  421. package/src/desktop/desktop-session-manager.ts +970 -0
  422. package/src/desktop/desktop-stream-bridge.test.ts +395 -0
  423. package/src/desktop/desktop-stream-bridge.ts +214 -0
  424. package/src/desktop/desktop-wallpaper.test.ts +191 -0
  425. package/src/desktop/desktop-wallpaper.ts +113 -0
  426. package/src/desktop/desktop-window-drag.ts +177 -0
  427. package/src/desktop/desktop-window-manager-config.test.ts +230 -0
  428. package/src/desktop/desktop-window-manager-config.ts +238 -0
  429. package/src/desktop/desktop-window-theme.ts +170 -0
  430. package/src/desktop/virtual-desktop-feature.ts +18 -0
  431. package/src/desktop/virtual-desktop-platform.test.ts +61 -0
  432. package/src/heartbeat/heartbeat-service.ts +21 -3
  433. package/src/home/__tests__/feed-writer.test.ts +22 -0
  434. package/src/home/feed-writer.ts +11 -2
  435. package/src/hooks/types.ts +33 -0
  436. package/src/i18n/AGENTS.md +22 -0
  437. package/src/i18n/__tests__/i18n.test.ts +112 -0
  438. package/src/i18n/index.ts +16 -0
  439. package/src/i18n/locales.ts +93 -0
  440. package/src/i18n/messages.ts +70 -0
  441. package/src/i18n/title.ts +25 -0
  442. package/src/inbound/platform-callback-registration.ts +4 -5
  443. package/src/ipc/__tests__/browser-ipc.test.ts +230 -2
  444. package/src/ipc/__tests__/cancel-on-disconnect.test.ts +54 -0
  445. package/src/ipc/assistant-server.ts +15 -1
  446. package/src/ipc/cli-client.ts +13 -5
  447. package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +143 -0
  448. package/src/live-voice/__tests__/live-voice-events.test.ts +9 -7
  449. package/src/live-voice/__tests__/live-voice-look-follow-up.test.ts +374 -0
  450. package/src/live-voice/__tests__/live-voice-metrics.test.ts +0 -3
  451. package/src/live-voice/__tests__/live-voice-progress.test.ts +94 -15
  452. package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +19 -0
  453. package/src/live-voice/__tests__/live-voice-sight-frame-echo.test.ts +238 -0
  454. package/src/live-voice/__tests__/live-voice-vad.test.ts +660 -5
  455. package/src/live-voice/__tests__/protocol.test.ts +95 -0
  456. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +13 -69
  457. package/src/live-voice/__tests__/session-controls.test.ts +156 -0
  458. package/src/live-voice/live-voice-metrics.ts +9 -0
  459. package/src/live-voice/live-voice-photo.ts +25 -6
  460. package/src/live-voice/live-voice-session.ts +1081 -760
  461. package/src/live-voice/protocol.ts +89 -2
  462. package/src/live-voice/session-controls.ts +197 -0
  463. package/src/mcp/__tests__/credential-target.test.ts +59 -0
  464. package/src/mcp/__tests__/effective-config.test.ts +13 -2
  465. package/src/mcp/__tests__/manager-state.test.ts +128 -0
  466. package/src/mcp/__tests__/manager-tool-caps.test.ts +111 -0
  467. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +20 -6
  468. package/src/mcp/__tests__/mcp-auth-state-target.test.ts +49 -0
  469. package/src/mcp/__tests__/plugin-mcp-oauth-cleanup.test.ts +107 -0
  470. package/src/mcp/__tests__/plugin-mcp-oauth-provider-isolation.test.ts +89 -0
  471. package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +63 -11
  472. package/src/mcp/__tests__/reload-signal-emission.test.ts +39 -2
  473. package/src/mcp/__tests__/startup.test.ts +30 -7
  474. package/src/mcp/__tests__/tool-caps.test.ts +107 -0
  475. package/src/mcp/__tests__/workspace-mcp-config.test.ts +135 -0
  476. package/src/mcp/client.ts +64 -16
  477. package/src/mcp/credential-target.ts +105 -0
  478. package/src/mcp/effective-config.ts +45 -18
  479. package/src/mcp/manager.ts +201 -81
  480. package/src/mcp/mcp-auth-orchestrator.ts +17 -4
  481. package/src/mcp/mcp-auth-state.ts +38 -6
  482. package/src/mcp/mcp-header-store.ts +29 -45
  483. package/src/mcp/mcp-oauth-provider.ts +101 -33
  484. package/src/mcp/spec-schema.ts +111 -0
  485. package/src/mcp/startup.ts +41 -17
  486. package/src/mcp/tool-caps.ts +176 -0
  487. package/src/mcp/workspace-mcp-config.ts +188 -0
  488. package/src/messaging/provider-message-metadata.ts +3 -3
  489. package/src/messaging/provider.ts +10 -3
  490. package/src/messaging/providers/__tests__/proactive-address.test.ts +95 -0
  491. package/src/messaging/providers/callback-routing.ts +18 -0
  492. package/src/messaging/providers/channel-transport.ts +56 -0
  493. package/src/messaging/providers/discord/transport.ts +17 -0
  494. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +6 -17
  495. package/src/messaging/providers/slack/adapter.ts +7 -44
  496. package/src/messaging/providers/slack/transport.ts +16 -0
  497. package/src/messaging/providers/telegram-bot/adapter.ts +1 -48
  498. package/src/messaging/providers/telegram-bot/client.ts +0 -26
  499. package/src/messaging/providers/telegram-bot/transport.ts +20 -0
  500. package/src/messaging/providers/whatsapp/adapter.ts +1 -48
  501. package/src/messaging/providers/whatsapp/transport.ts +18 -0
  502. package/src/monitoring/__tests__/mount-watch.test.ts +236 -0
  503. package/src/monitoring/__tests__/workspace-git-heartbeat.test.ts +8 -0
  504. package/src/monitoring/mount-watch.ts +348 -0
  505. package/src/monitoring/plugin-auto-update.ts +6 -0
  506. package/src/monitoring/worker.ts +9 -0
  507. package/src/notifications/__tests__/assistant-reply-producer.test.ts +55 -0
  508. package/src/notifications/__tests__/copy-composer.test.ts +70 -0
  509. package/src/notifications/__tests__/decision-engine.test.ts +175 -0
  510. package/src/notifications/__tests__/guardian-feed-projection.test.ts +158 -2
  511. package/src/notifications/__tests__/home-feed-side-effect.test.ts +153 -3
  512. package/src/notifications/__tests__/schedule-result-producer.test.ts +99 -3
  513. package/src/notifications/adapters/macos.ts +3 -0
  514. package/src/notifications/assistant-reply-producer.ts +8 -3
  515. package/src/notifications/conversation-pairing.ts +36 -16
  516. package/src/notifications/copy-composer.ts +11 -3
  517. package/src/notifications/decision-engine.ts +43 -8
  518. package/src/notifications/delivered-post-record.ts +11 -1
  519. package/src/notifications/guardian-feed-projection.ts +125 -5
  520. package/src/notifications/home-feed-side-effect.ts +55 -7
  521. package/src/notifications/schedule-result-producer.ts +64 -22
  522. package/src/oauth/AGENTS.md +4 -0
  523. package/src/oauth/__tests__/identity-verifier.test.ts +36 -1
  524. package/src/oauth/__tests__/seed-providers-managed.test.ts +149 -0
  525. package/src/oauth/byo-connection.test.ts +105 -0
  526. package/src/oauth/byo-connection.ts +36 -6
  527. package/src/oauth/connection-resolver.test.ts +100 -0
  528. package/src/oauth/connection-resolver.ts +120 -3
  529. package/src/oauth/identity-verifier.ts +24 -0
  530. package/src/oauth/oauth-store.ts +11 -1
  531. package/src/oauth/provider-serializer.ts +10 -0
  532. package/src/oauth/scope-utils.ts +24 -0
  533. package/src/oauth/seed-providers.ts +367 -27
  534. package/src/onboarding/checkin-event.ts +2 -1
  535. package/src/outbound-proxy/certs.ts +3 -5
  536. package/src/permissions/checker.test.ts +11 -6
  537. package/src/permissions/confirmation-guardian-request.test.ts +16 -0
  538. package/src/permissions/confirmation-guardian-request.ts +2 -3
  539. package/src/persistence/attachments-store.ts +84 -44
  540. package/src/persistence/compaction-log-store-clickhouse.ts +3 -3
  541. package/src/persistence/conversation-crud.ts +182 -83
  542. package/src/persistence/conversation-lineage.ts +12 -4
  543. package/src/persistence/conversation-plugin-facade.ts +13 -0
  544. package/src/persistence/conversation-queries.ts +2 -2
  545. package/src/persistence/conversation-title-placeholders.ts +23 -0
  546. package/src/persistence/conversation-title-service.ts +9 -26
  547. package/src/persistence/conversation-tool-surface.ts +86 -0
  548. package/src/persistence/conversation-types.test.ts +32 -0
  549. package/src/persistence/conversation-types.ts +26 -4
  550. package/src/persistence/embeddings/qdrant-manager.ts +163 -18
  551. package/src/persistence/llm-request-log-sink-clickhouse.ts +3 -3
  552. package/src/persistence/llm-request-log-source-clickhouse.ts +3 -3
  553. package/src/persistence/message-cursor.ts +78 -0
  554. package/src/persistence/message-reads.ts +30 -0
  555. package/src/persistence/migrations/157-invite-contact-id.ts +18 -6
  556. package/src/persistence/migrations/378-create-conversation-tool-surfaces.test.ts +78 -0
  557. package/src/persistence/migrations/378-create-conversation-tool-surfaces.ts +29 -0
  558. package/src/persistence/migrations/379-oauth-providers-response-ok-field.test.ts +92 -0
  559. package/src/persistence/migrations/379-oauth-providers-response-ok-field.ts +32 -0
  560. package/src/persistence/migrations/__tests__/157-invite-contact-id.test.ts +149 -0
  561. package/src/persistence/schema/conversation-tool-surfaces.ts +22 -0
  562. package/src/persistence/schema/index.ts +1 -0
  563. package/src/persistence/schema/memory-core.ts +5 -0
  564. package/src/persistence/schema/oauth.ts +1 -0
  565. package/src/persistence/steps.ts +15 -3
  566. package/src/platform/client.test.ts +4 -2
  567. package/src/platform/client.ts +2 -10
  568. package/src/plugin-api/constants.ts +2 -0
  569. package/src/plugin-api/conversation-turn.ts +31 -7
  570. package/src/plugin-api/index.ts +10 -1
  571. package/src/plugin-api/plugin-channel-turn-trust.test.ts +133 -0
  572. package/src/plugin-api/plugin-channel-turn-trust.ts +71 -0
  573. package/src/plugin-api/types.ts +2 -0
  574. package/src/plugins/__tests__/installed-plugin-dirs.test.ts +14 -1
  575. package/src/plugins/__tests__/mcp-servers.test.ts +38 -8
  576. package/src/plugins/defaults/index.ts +2 -0
  577. package/src/plugins/defaults/memory/AGENTS.md +14 -2
  578. package/src/plugins/defaults/memory/__tests__/buffer-file.test.ts +365 -0
  579. package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +43 -0
  580. package/src/plugins/defaults/memory/__tests__/fixtures/buffer-appender.ts +17 -0
  581. package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +46 -0
  582. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-backfill.test.ts +118 -0
  583. package/src/plugins/defaults/memory/__tests__/memory-retrospective-cursor-preserve.test.ts +83 -0
  584. package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +9 -5
  585. package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +66 -10
  586. package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +20 -0
  587. package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +219 -0
  588. package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +31 -0
  589. package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +63 -0
  590. package/src/plugins/defaults/memory/__tests__/memory-run-evidence.test.ts +161 -0
  591. package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +4 -0
  592. package/src/plugins/defaults/memory/buffer-file.ts +354 -0
  593. package/src/plugins/defaults/memory/buffer-format.ts +40 -0
  594. package/src/plugins/defaults/memory/context-search/agent-runner.ts +3 -3
  595. package/src/plugins/defaults/memory/context-search/format.ts +4 -2
  596. package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +7 -3
  597. package/src/plugins/defaults/memory/context-search/sources/workspace.ts +4 -2
  598. package/src/plugins/defaults/memory/graph/capability-seed.ts +6 -8
  599. package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -42
  600. package/src/plugins/defaults/memory/hooks/init.ts +10 -0
  601. package/src/plugins/defaults/memory/hooks/message-deleted.ts +21 -0
  602. package/src/plugins/defaults/memory/hooks/shutdown.ts +2 -0
  603. package/src/plugins/defaults/memory/injectors.ts +4 -3
  604. package/src/plugins/defaults/memory/jobs-worker.ts +13 -0
  605. package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +34 -60
  606. package/src/plugins/defaults/memory/memory-retrospective-cursor-backfill.ts +126 -0
  607. package/src/plugins/defaults/memory/memory-retrospective-cursor-preserve.ts +79 -0
  608. package/src/plugins/defaults/memory/memory-retrospective-cursor.ts +28 -0
  609. package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +3 -5
  610. package/src/plugins/defaults/memory/memory-retrospective-job.ts +67 -184
  611. package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +1 -1
  612. package/src/plugins/defaults/memory/memory-retrospective-state.ts +312 -71
  613. package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +2 -1
  614. package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +5 -3
  615. package/src/plugins/defaults/memory/memory-run-evidence.ts +213 -0
  616. package/src/plugins/defaults/memory/skill-md-mtime-poll.ts +9 -0
  617. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +1 -1
  618. package/src/plugins/defaults/memory/startup.ts +28 -2
  619. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +407 -99
  620. package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +10 -0
  621. package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +107 -7
  622. package/src/plugins/defaults/memory/substrate/__tests__/skill-content.test.ts +7 -9
  623. package/src/plugins/defaults/memory/substrate/consolidation-job.ts +307 -86
  624. package/src/plugins/defaults/memory/substrate/consolidation-tool-surface.ts +34 -0
  625. package/src/plugins/defaults/memory/substrate/page-index.ts +7 -1
  626. package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +89 -49
  627. package/src/plugins/defaults/memory/substrate/skill-content.ts +2 -2
  628. package/src/plugins/defaults/memory/substrate/sweep-job.ts +1 -1
  629. package/src/plugins/defaults/memory/tools.ts +1 -1
  630. package/src/plugins/defaults/memory/v1/graph/consolidation.ts +4 -2
  631. package/src/plugins/defaults/memory/v1/graph/extraction.ts +4 -1
  632. package/src/plugins/defaults/memory/v1/graph/retriever.ts +4 -1
  633. package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +5 -0
  634. package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +5 -2
  635. package/src/plugins/defaults/memory/v2/reranker.ts +7 -1
  636. package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +24 -0
  637. package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +81 -1
  638. package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +87 -0
  639. package/src/plugins/defaults/memory/v3/__tests__/pool-select.test.ts +125 -0
  640. package/src/plugins/defaults/memory/v3/__tests__/sections.test.ts +26 -0
  641. package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -0
  642. package/src/plugins/defaults/memory/v3/card.ts +4 -2
  643. package/src/plugins/defaults/memory/v3/injector.ts +212 -178
  644. package/src/plugins/defaults/memory/v3/orchestrate.ts +86 -22
  645. package/src/plugins/defaults/memory/v3/pool-select.ts +13 -8
  646. package/src/plugins/defaults/memory/v3/sections.ts +10 -3
  647. package/src/plugins/defaults/memory/v3/shadow-plugin.ts +13 -1
  648. package/src/plugins/defaults/memory/worker.ts +6 -0
  649. package/src/plugins/defaults/tool-result-truncate/terminal.ts +1 -46
  650. package/src/plugins/external-plugin-loader.ts +49 -86
  651. package/src/plugins/installed-plugin-dirs.ts +6 -4
  652. package/src/plugins/mcp-servers.ts +24 -90
  653. package/src/plugins/mtime-cache.ts +2 -1
  654. package/src/plugins/user-loader.ts +2 -1
  655. package/src/providers/__tests__/connection-model-compat.test.ts +3 -3
  656. package/src/providers/__tests__/retry-callsite.test.ts +41 -0
  657. package/src/providers/__tests__/retry-outbound-sanitize.test.ts +176 -0
  658. package/src/providers/anthropic/client.ts +0 -47
  659. package/src/providers/gemini/client.ts +9 -23
  660. package/src/providers/gemini-thought-signature.test.ts +63 -0
  661. package/src/providers/gemini-thought-signature.ts +44 -0
  662. package/src/providers/inference/__tests__/endpoint-probe.test.ts +87 -3
  663. package/src/providers/inference/adapter-factory.ts +6 -0
  664. package/src/providers/inference/auth.ts +2 -3
  665. package/src/providers/inference/connection-availability.ts +27 -8
  666. package/src/providers/inference/endpoint-probe.ts +36 -12
  667. package/src/providers/inference/resolve-auth.ts +22 -4
  668. package/src/providers/inference/service-account-token.ts +248 -0
  669. package/src/providers/jev/client.test.ts +260 -0
  670. package/src/providers/jev/client.ts +518 -0
  671. package/src/providers/model-catalog.ts +92 -3
  672. package/src/providers/model-intents.ts +10 -5
  673. package/src/providers/openai/__tests__/chat-completions-output-token-limit.test.ts +141 -0
  674. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +146 -18
  675. package/src/providers/openai/__tests__/chat-completions-provider-thought-signature.test.ts +613 -0
  676. package/src/providers/openai/__tests__/google-thought-signature.test.ts +235 -0
  677. package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +83 -1
  678. package/src/providers/openai/chat-completions-provider.ts +212 -79
  679. package/src/providers/openai/codex-models.ts +0 -4
  680. package/src/providers/openai/google-thought-signature.ts +320 -0
  681. package/src/providers/openai/responses-provider.ts +9 -2
  682. package/src/providers/opencode/client.test.ts +240 -4
  683. package/src/providers/opencode/client.ts +129 -3
  684. package/src/providers/openrouter/client.ts +20 -0
  685. package/src/providers/outbound-request-sanitize.ts +96 -0
  686. package/src/providers/retry.ts +30 -19
  687. package/src/providers/unparseable-tool-args.ts +5 -1
  688. package/src/runtime/AGENTS.md +9 -3
  689. package/src/runtime/__tests__/agent-wake.test.ts +86 -1
  690. package/src/runtime/__tests__/channel-send.test.ts +443 -0
  691. package/src/runtime/__tests__/desktop-stream-upgrade.test.ts +132 -0
  692. package/src/runtime/__tests__/host-observe.test.ts +40 -1
  693. package/src/runtime/__tests__/live-voice-upgrade.test.ts +58 -0
  694. package/src/runtime/__tests__/runtime-ws-test-utils.ts +72 -0
  695. package/src/runtime/__tests__/watch-stream-upgrade.test.ts +59 -0
  696. package/src/runtime/agent-wake.ts +22 -5
  697. package/src/runtime/assistant-event-hub.ts +21 -3
  698. package/src/runtime/auth/same-actor.ts +38 -3
  699. package/src/runtime/channel-send.ts +316 -0
  700. package/src/runtime/guardian-action-service.ts +2 -17
  701. package/src/runtime/guardian-reply-router.ts +1 -8
  702. package/src/runtime/host-observe.ts +11 -1
  703. package/src/runtime/http-server.ts +160 -151
  704. package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +89 -0
  705. package/src/runtime/migrations/vbundle-import-policy.ts +33 -11
  706. package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +16 -5
  707. package/src/runtime/routes/__tests__/acp-routes.test.ts +178 -4
  708. package/src/runtime/routes/__tests__/apps-refresh-route.test.ts +275 -0
  709. package/src/runtime/routes/__tests__/channel-send-routes.test.ts +127 -0
  710. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +108 -1
  711. package/src/runtime/routes/__tests__/default-provider-routes.test.ts +2 -2
  712. package/src/runtime/routes/__tests__/dictation-cleanup-guard.test.ts +107 -0
  713. package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +24 -2
  714. package/src/runtime/routes/__tests__/mcp-add-default-risk.test.ts +16 -12
  715. package/src/runtime/routes/__tests__/plugins-routes.test.ts +127 -3
  716. package/src/runtime/routes/acp-claude-auth-routes.ts +11 -3
  717. package/src/runtime/routes/acp-routes.test.ts +15 -0
  718. package/src/runtime/routes/acp-routes.ts +84 -165
  719. package/src/runtime/routes/app-management-routes.ts +90 -2
  720. package/src/runtime/routes/app-routes.ts +1 -1
  721. package/src/runtime/routes/browser-context.ts +39 -0
  722. package/src/runtime/routes/browser-routes.ts +16 -47
  723. package/src/runtime/routes/browser-tabs-routes.ts +72 -29
  724. package/src/runtime/routes/channel-route-shared.ts +1 -9
  725. package/src/runtime/routes/channel-send-routes.ts +85 -0
  726. package/src/runtime/routes/conversation-list-routes.ts +14 -3
  727. package/src/runtime/routes/conversation-query-routes.ts +40 -0
  728. package/src/runtime/routes/conversation-routes.ts +45 -7
  729. package/src/runtime/routes/credential-routes.ts +20 -14
  730. package/src/runtime/routes/desktop-setup-routes.test.ts +89 -0
  731. package/src/runtime/routes/desktop-setup-routes.ts +41 -0
  732. package/src/runtime/routes/diagnostics-routes.ts +61 -4
  733. package/src/runtime/routes/events-routes.ts +4 -0
  734. package/src/runtime/routes/guardian-approval-interception.ts +24 -0
  735. package/src/runtime/routes/host-cu-routes.ts +6 -0
  736. package/src/runtime/routes/inbound-message-handler.ts +2 -3
  737. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +1 -1
  738. package/src/runtime/routes/inbound-stages/background-dispatch.ts +7 -4
  739. package/src/runtime/routes/index.ts +4 -2
  740. package/src/runtime/routes/inference-profile-session-handler.ts +11 -1
  741. package/src/runtime/routes/inference-profiles-routes.ts +9 -0
  742. package/src/runtime/routes/log-export-routes.ts +2 -0
  743. package/src/runtime/routes/mcp-auth-routes.ts +141 -137
  744. package/src/runtime/routes/migration-routes.ts +6 -20
  745. package/src/runtime/routes/oauth-commands-routes.ts +98 -45
  746. package/src/runtime/routes/oauth-providers.ts +11 -0
  747. package/src/runtime/routes/oauth-request-hints.test.ts +246 -0
  748. package/src/runtime/routes/oauth-request-hints.ts +149 -0
  749. package/src/runtime/routes/platform-routes.ts +18 -15
  750. package/src/runtime/routes/plugins-routes.ts +83 -50
  751. package/src/runtime/routes/schedule-routes.ts +2 -0
  752. package/src/runtime/routes/secret-routes.ts +99 -119
  753. package/src/runtime/routes/workspace-routes.test.ts +55 -26
  754. package/src/runtime/routes/workspace-routes.ts +46 -63
  755. package/src/runtime/routes/workspace-tree-walk.test.ts +244 -0
  756. package/src/runtime/routes/workspace-tree-walk.ts +240 -0
  757. package/src/runtime/routes/workspace-utils.ts +17 -0
  758. package/src/runtime/services/__tests__/conversation-serializer.test.ts +28 -0
  759. package/src/runtime/services/conversation-serializer.ts +16 -3
  760. package/src/runtime/sync/resource-sync-events.ts +6 -1
  761. package/src/schedule/__tests__/worker-mcp-bootstrap.test.ts +107 -0
  762. package/src/schedule/__tests__/worker-mcp-readiness.test.ts +173 -0
  763. package/src/schedule/__tests__/worker-mcp-tools.test.ts +13 -47
  764. package/src/schedule/run-script.ts +4 -3
  765. package/src/schedule/schedule-store.ts +9 -2
  766. package/src/schedule/scheduler.ts +47 -11
  767. package/src/schedule/tool-surface-readiness.ts +65 -0
  768. package/src/schedule/worker-mcp.ts +85 -0
  769. package/src/schedule/worker.ts +9 -31
  770. package/src/security/__tests__/ces-http-record-backend.test.ts +137 -0
  771. package/src/security/ces-http-record-backend.ts +120 -0
  772. package/src/security/ces-rpc-record-backend.ts +7 -0
  773. package/src/security/secure-keys.ts +60 -48
  774. package/src/security/untrusted-content.ts +3 -1
  775. package/src/skills/__tests__/workspace-skill-md-signature.test.ts +60 -0
  776. package/src/skills/managed-store.ts +153 -31
  777. package/src/skills/workspace-skill-md-signature.ts +50 -0
  778. package/src/subagent/consult-context.ts +12 -25
  779. package/src/tools/__tests__/side-effect-abort-guard.test.ts +1 -0
  780. package/src/tools/acp/list-agents.test.ts +3 -1
  781. package/src/tools/acp/spawn.test.ts +146 -11
  782. package/src/tools/acp/spawn.ts +21 -3
  783. package/src/tools/acp/status.test.ts +349 -0
  784. package/src/tools/acp/status.ts +112 -9
  785. package/src/tools/app-control/skill-proxy-bridge.ts +2 -1
  786. package/src/tools/browser/browser-execution.ts +45 -14
  787. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +69 -0
  788. package/src/tools/browser/cdp-client/accessibility-snapshot.ts +9 -3
  789. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +1 -0
  790. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +2 -1
  791. package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +5 -0
  792. package/src/tools/browser/cdp-client/extension-cdp-client.ts +3 -2
  793. package/src/tools/browser/network-recorder.ts +2 -1
  794. package/src/tools/capability-offer.test.ts +22 -2
  795. package/src/tools/capability-offer.ts +16 -1
  796. package/src/tools/computer-use/definitions.ts +123 -5
  797. package/src/tools/computer-use/skill-proxy-bridge.ts +2 -1
  798. package/src/tools/credentials/metadata-store.ts +100 -0
  799. package/src/tools/filesystem/search.ts +2 -1
  800. package/src/tools/host-filesystem/edit.test.ts +2 -1
  801. package/src/tools/host-filesystem/edit.ts +2 -2
  802. package/src/tools/host-filesystem/read.test.ts +2 -1
  803. package/src/tools/host-filesystem/read.ts +2 -2
  804. package/src/tools/host-filesystem/transfer.test.ts +2 -1
  805. package/src/tools/host-filesystem/transfer.ts +2 -2
  806. package/src/tools/host-filesystem/write.test.ts +2 -1
  807. package/src/tools/host-filesystem/write.ts +2 -2
  808. package/src/tools/host-terminal/host-shell.test.ts +16 -0
  809. package/src/tools/host-terminal/host-shell.ts +16 -26
  810. package/src/tools/network/web-search.ts +6 -1
  811. package/src/tools/policy-context.ts +6 -7
  812. package/src/tools/shared/filesystem/file-ops-service.ts +1 -31
  813. package/src/tools/shared/shell-output.test.ts +10 -0
  814. package/src/tools/shared/shell-output.ts +14 -2
  815. package/src/tools/skills/find-similar-skills.test.ts +214 -2
  816. package/src/tools/skills/find-similar-skills.ts +62 -9
  817. package/src/tools/skills/resolve-execute-invocation.ts +24 -0
  818. package/src/tools/skills/sandbox-runner.ts +13 -2
  819. package/src/tools/skills/scaffold-managed.ts +78 -16
  820. package/src/tools/subagent/spawn.ts +5 -8
  821. package/src/tools/terminal/__tests__/safe-env.test.ts +33 -4
  822. package/src/tools/terminal/__tests__/sanitized-bash.test.ts +43 -0
  823. package/src/tools/terminal/safe-env.ts +35 -24
  824. package/src/tools/terminal/sanitized-bash.ts +118 -0
  825. package/src/tools/terminal/shell-launch.test.ts +162 -0
  826. package/src/tools/terminal/shell.test.ts +29 -0
  827. package/src/tools/terminal/shell.ts +13 -7
  828. package/src/tools/ui-surface/channel-variants.ts +10 -59
  829. package/src/tools/watch/watch-retro-report.ts +0 -8
  830. package/src/types/host-capabilities.ts +5 -3
  831. package/src/util/__tests__/language-subtag.test.ts +23 -1
  832. package/src/util/abort-reasons.ts +12 -1
  833. package/src/util/ca-bundle.ts +13 -0
  834. package/src/util/host-process.test.ts +17 -1
  835. package/src/util/host-process.ts +24 -0
  836. package/src/util/language-subtag.ts +16 -0
  837. package/src/util/platform.ts +8 -0
  838. package/src/util/plugin-manifest.ts +203 -0
  839. package/src/util/unicode.ts +44 -1
  840. package/src/watch/watch-retro.ts +6 -8
  841. package/src/watch/watch-timeline.ts +2 -2
  842. package/src/workflows/run-manager.ts +2 -1
  843. package/src/workspace/git-porcelain.ts +66 -0
  844. package/src/workspace/git-service.ts +6 -55
  845. package/src/workspace/migrations/154-repair-retired-codex-gpt-5-4-model-ids.ts +258 -0
  846. package/src/workspace/migrations/155-move-front-model-config-to-voice.ts +78 -0
  847. package/src/workspace/migrations/156-extract-workspace-mcp-json.ts +214 -0
  848. package/src/workspace/migrations/__tests__/155-move-front-model-config-to-voice.test.ts +102 -0
  849. package/src/workspace/migrations/__tests__/156-extract-workspace-mcp-json.test.ts +199 -0
  850. package/src/workspace/migrations/registry.ts +6 -0
  851. package/src/__tests__/app-source-watcher.test.ts +0 -218
  852. package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -359
  853. package/src/__tests__/speaker-identification.test.ts +0 -56
  854. package/src/calls/speaker-identification.ts +0 -233
  855. package/src/daemon/app-source-watcher.ts +0 -218
  856. package/src/messaging/providers/whatsapp/client.ts +0 -29
  857. package/src/runtime/routes/debug-bash-routes.ts +0 -173
  858. package/src/util/fs-watcher-error.ts +0 -36
  859. /package/src/{live-voice → calls}/progress-phrases.ts +0 -0
@@ -38,23 +38,16 @@ import {
38
38
  import { openInHostBrowser } from "../util/browser.js";
39
39
  import { getLogger } from "../util/logger.js";
40
40
  import { APP_VERSION } from "../version.js";
41
+ import {
42
+ MCP_OAUTH_CREDENTIAL_LEAVES,
43
+ mcpOAuthCredentialKey,
44
+ type McpOAuthCredentialTarget,
45
+ pluginMcpOAuthCredentialPrefix,
46
+ workspaceMcpOAuthCredentialTarget,
47
+ } from "./credential-target.js";
41
48
 
42
49
  const log = getLogger("mcp-oauth");
43
50
 
44
- // Credential store key helpers
45
- function tokensKey(serverId: string): string {
46
- return `mcp:${serverId}:tokens`;
47
- }
48
- function clientInfoKey(serverId: string): string {
49
- return `mcp:${serverId}:client_info`;
50
- }
51
- function discoveryKey(serverId: string): string {
52
- return `mcp:${serverId}:discovery`;
53
- }
54
- function clientBindingKey(serverId: string): string {
55
- return `mcp:${serverId}:client_binding`;
56
- }
57
-
58
51
  /**
59
52
  * Logo shown on an authorization server's consent screen.
60
53
  *
@@ -91,12 +84,15 @@ export interface McpOAuthProviderOptions {
91
84
  * URL to the IPC caller (CLI / web client).
92
85
  */
93
86
  onAuthorizationUrl?: (url: string) => void;
87
+ /** Credential identity. Defaults to the legacy workspace server id. */
88
+ credentialTarget?: McpOAuthCredentialTarget;
94
89
  }
95
90
 
96
91
  export class McpOAuthProvider implements OAuthClientProvider {
97
92
  private readonly serverId: string;
98
93
  private readonly serverUrl: string;
99
94
  private readonly interactive: boolean;
95
+ private readonly credentialTarget: McpOAuthCredentialTarget;
100
96
  private _codeVerifier: string | undefined;
101
97
  private _state: string | undefined;
102
98
  private _redirectUrl: string | undefined;
@@ -121,6 +117,8 @@ export class McpOAuthProvider implements OAuthClientProvider {
121
117
  this.serverUrl = serverUrl;
122
118
  this.interactive = interactive;
123
119
  this._onAuthorizationUrl = options.onAuthorizationUrl;
120
+ this.credentialTarget =
121
+ options.credentialTarget ?? workspaceMcpOAuthCredentialTarget(serverId);
124
122
  }
125
123
 
126
124
  // --- redirectUrl ---
@@ -167,7 +165,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
167
165
  // --- Tokens ---
168
166
 
169
167
  async tokens(): Promise<OAuthTokens | undefined> {
170
- const raw = await getSecureKeyAsync(tokensKey(this.serverId));
168
+ const raw = await getSecureKeyAsync(
169
+ mcpOAuthCredentialKey(this.credentialTarget, "tokens"),
170
+ );
171
171
  if (!raw) {
172
172
  return undefined;
173
173
  }
@@ -191,7 +191,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
191
191
  // the previous refresh_token when the incoming response omits one.
192
192
  let toPersist: OAuthTokens = tokens;
193
193
  if (!tokens.refresh_token) {
194
- const previous = await getSecureKeyAsync(tokensKey(this.serverId));
194
+ const previous = await getSecureKeyAsync(
195
+ mcpOAuthCredentialKey(this.credentialTarget, "tokens"),
196
+ );
195
197
  if (previous) {
196
198
  try {
197
199
  const parsed = JSON.parse(previous) as OAuthTokens;
@@ -204,7 +206,7 @@ export class McpOAuthProvider implements OAuthClientProvider {
204
206
  }
205
207
  }
206
208
  const ok = await setSecureKeyAsync(
207
- tokensKey(this.serverId),
209
+ mcpOAuthCredentialKey(this.credentialTarget, "tokens"),
208
210
  JSON.stringify(toPersist),
209
211
  );
210
212
  if (!ok) {
@@ -263,7 +265,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
263
265
  * fronts the resource.
264
266
  */
265
267
  async clientInformation(): Promise<OAuthClientInformationMixed | undefined> {
266
- const raw = await getSecureKeyAsync(clientInfoKey(this.serverId));
268
+ const raw = await getSecureKeyAsync(
269
+ mcpOAuthCredentialKey(this.credentialTarget, "client_info"),
270
+ );
267
271
  if (!raw) {
268
272
  return undefined;
269
273
  }
@@ -294,7 +298,7 @@ export class McpOAuthProvider implements OAuthClientProvider {
294
298
  info: OAuthClientInformationMixed,
295
299
  ): Promise<void> {
296
300
  const ok = await setSecureKeyAsync(
297
- clientInfoKey(this.serverId),
301
+ mcpOAuthCredentialKey(this.credentialTarget, "client_info"),
298
302
  JSON.stringify(info),
299
303
  );
300
304
  if (!ok) {
@@ -313,7 +317,7 @@ export class McpOAuthProvider implements OAuthClientProvider {
313
317
  redirectUri: this._redirectUrl,
314
318
  };
315
319
  const boundOk = await setSecureKeyAsync(
316
- clientBindingKey(this.serverId),
320
+ mcpOAuthCredentialKey(this.credentialTarget, "client_binding"),
317
321
  JSON.stringify(binding),
318
322
  );
319
323
  if (!boundOk) {
@@ -349,7 +353,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
349
353
  * redirect check already covers the case this plugin actually changes.
350
354
  */
351
355
  private async describeStaleBinding(): Promise<string | null> {
352
- const raw = await getSecureKeyAsync(clientBindingKey(this.serverId));
356
+ const raw = await getSecureKeyAsync(
357
+ mcpOAuthCredentialKey(this.credentialTarget, "client_binding"),
358
+ );
353
359
  if (!raw) {
354
360
  // Registered before the binding was recorded. Keep it: discarding
355
361
  // every pre-existing registration would remake all of them at once.
@@ -410,7 +416,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
410
416
  // --- Discovery State ---
411
417
 
412
418
  async discoveryState(): Promise<OAuthDiscoveryState | undefined> {
413
- const raw = await getSecureKeyAsync(discoveryKey(this.serverId));
419
+ const raw = await getSecureKeyAsync(
420
+ mcpOAuthCredentialKey(this.credentialTarget, "discovery"),
421
+ );
414
422
  if (!raw) {
415
423
  return undefined;
416
424
  }
@@ -423,7 +431,7 @@ export class McpOAuthProvider implements OAuthClientProvider {
423
431
 
424
432
  async saveDiscoveryState(state: OAuthDiscoveryState): Promise<void> {
425
433
  const ok = await setSecureKeyAsync(
426
- discoveryKey(this.serverId),
434
+ mcpOAuthCredentialKey(this.credentialTarget, "discovery"),
427
435
  JSON.stringify(state),
428
436
  );
429
437
  if (!ok) {
@@ -498,7 +506,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
498
506
  );
499
507
 
500
508
  if (scope === "all" || scope === "tokens") {
501
- const result = await deleteSecureKeyAsync(tokensKey(this.serverId));
509
+ const result = await deleteSecureKeyAsync(
510
+ mcpOAuthCredentialKey(this.credentialTarget, "tokens"),
511
+ );
502
512
  if (result === "error") {
503
513
  log.warn(
504
514
  { serverId: this.serverId },
@@ -512,7 +522,9 @@ export class McpOAuthProvider implements OAuthClientProvider {
512
522
  }
513
523
  }
514
524
  if (scope === "all" || scope === "client") {
515
- const result = await deleteSecureKeyAsync(clientInfoKey(this.serverId));
525
+ const result = await deleteSecureKeyAsync(
526
+ mcpOAuthCredentialKey(this.credentialTarget, "client_info"),
527
+ );
516
528
  if (result === "error") {
517
529
  log.warn(
518
530
  { serverId: this.serverId },
@@ -527,14 +539,18 @@ export class McpOAuthProvider implements OAuthClientProvider {
527
539
  // The binding describes the registration being dropped, so it goes
528
540
  // with it. Leaving it would let a later registration inherit the
529
541
  // previous one's issuer and redirect URI.
530
- await deleteSecureKeyAsync(clientBindingKey(this.serverId));
542
+ await deleteSecureKeyAsync(
543
+ mcpOAuthCredentialKey(this.credentialTarget, "client_binding"),
544
+ );
531
545
  }
532
546
  if (scope === "all" || scope === "verifier") {
533
547
  this._codeVerifier = undefined;
534
548
  this._state = undefined;
535
549
  }
536
550
  if (scope === "all" || scope === "discovery") {
537
- const result = await deleteSecureKeyAsync(discoveryKey(this.serverId));
551
+ const result = await deleteSecureKeyAsync(
552
+ mcpOAuthCredentialKey(this.credentialTarget, "discovery"),
553
+ );
538
554
  if (result === "error") {
539
555
  log.warn(
540
556
  { serverId: this.serverId },
@@ -617,8 +633,10 @@ export class McpOAuthProvider implements OAuthClientProvider {
617
633
  /**
618
634
  * Check whether OAuth tokens exist in the credential store for a server.
619
635
  */
620
- export async function hasMcpOAuthTokens(serverId: string): Promise<boolean> {
621
- const raw = await getSecureKeyAsync(tokensKey(serverId));
636
+ export async function hasMcpOAuthTokens(
637
+ target: McpOAuthCredentialTarget,
638
+ ): Promise<boolean> {
639
+ const raw = await getSecureKeyAsync(mcpOAuthCredentialKey(target, "tokens"));
622
640
  return raw != null && raw.length > 0;
623
641
  }
624
642
 
@@ -631,10 +649,14 @@ export async function deleteMcpOAuthCredentials(
631
649
  ): Promise<{ ok: boolean; failedKeys: string[] }> {
632
650
  const [tokensResult, clientResult, bindingResult, discoveryResult] =
633
651
  await Promise.all([
634
- deleteSecureKeyAsync(tokensKey(serverId)),
635
- deleteSecureKeyAsync(clientInfoKey(serverId)),
636
- deleteSecureKeyAsync(clientBindingKey(serverId)),
637
- deleteSecureKeyAsync(discoveryKey(serverId)),
652
+ ...MCP_OAUTH_CREDENTIAL_LEAVES.map((leaf) =>
653
+ deleteSecureKeyAsync(
654
+ mcpOAuthCredentialKey(
655
+ workspaceMcpOAuthCredentialTarget(serverId),
656
+ leaf,
657
+ ),
658
+ ),
659
+ ),
638
660
  ]);
639
661
  const results = [
640
662
  { key: "tokens", result: tokensResult },
@@ -660,3 +682,49 @@ export async function deleteMcpOAuthCredentials(
660
682
  );
661
683
  return { ok, failedKeys };
662
684
  }
685
+
686
+ export interface PluginMcpOAuthCleanupResult {
687
+ readonly ok: boolean;
688
+ readonly unreachable: boolean;
689
+ readonly matchedKeys: string[];
690
+ readonly failedKeys: string[];
691
+ }
692
+
693
+ /** Delete every endpoint-scoped MCP OAuth record owned by one plugin. */
694
+ export async function deletePluginMcpOAuthCredentials(
695
+ pluginName: string,
696
+ ): Promise<PluginMcpOAuthCleanupResult> {
697
+ const { listSecureKeysAsync } = await import("../security/secure-keys.js");
698
+ const listed = await listSecureKeysAsync();
699
+ if (listed.unreachable) {
700
+ return {
701
+ ok: false,
702
+ unreachable: true,
703
+ matchedKeys: [],
704
+ failedKeys: [],
705
+ };
706
+ }
707
+
708
+ const prefix = pluginMcpOAuthCredentialPrefix(pluginName);
709
+ const matchedKeys = listed.accounts.filter((key) => key.startsWith(prefix));
710
+ const deletionResults = await Promise.all(
711
+ matchedKeys.map(async (key) => {
712
+ try {
713
+ return { key, result: await deleteSecureKeyAsync(key) };
714
+ } catch {
715
+ return { key, result: "error" as const };
716
+ }
717
+ }),
718
+ );
719
+ const failedKeys = deletionResults
720
+ .filter(({ result }) => result === "error")
721
+ .map(({ key }) => key);
722
+ const ok = failedKeys.length === 0;
723
+ if (!ok) {
724
+ log.warn(
725
+ { pluginName, failedKeys },
726
+ "Some plugin MCP OAuth credentials could not be deleted",
727
+ );
728
+ }
729
+ return { ok, unreachable: false, matchedKeys, failedKeys };
730
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Agent Plugins 1.0.0 `mcp.json` wire schema and projections onto the
3
+ * assistant's in-memory `McpTransport` union.
4
+ *
5
+ * Workspace `/workspace/mcp.json` and each plugin's root `mcp.json` share
6
+ * this document shape. Origin (`workspace` vs `plugin`) is resolved from
7
+ * which file was read, never from a field in the file.
8
+ */
9
+
10
+ import { z } from "zod";
11
+
12
+ import type { McpTransport } from "../config/schemas/mcp.js";
13
+
14
+ /** Canonical `$schema` value for an Agent Plugins 1.0.0 MCP document. */
15
+ export const AGENT_PLUGINS_MCP_SCHEMA_URL =
16
+ "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json";
17
+
18
+ const SpecStdioServerSchema = z.object({
19
+ type: z.literal("stdio"),
20
+ command: z.string().min(1),
21
+ args: z.array(z.string()).optional(),
22
+ env: z.record(z.string(), z.string()).optional(),
23
+ cwd: z.string().optional(),
24
+ });
25
+
26
+ /**
27
+ * Remote MCP entry. Agent Plugins 1.0.0 requires `type` and names no
28
+ * default. MCP's current remote transport is Streamable HTTP, so this
29
+ * host fills omitted `type` and the Claude-style `http` alias as
30
+ * `streamable-http`. `sse` stays explicit.
31
+ */
32
+ const SpecHttpServerSchema = z.object({
33
+ type: z
34
+ .union([
35
+ z.literal("streamable-http"),
36
+ z.literal("sse"),
37
+ z.literal("http").transform(() => "streamable-http" as const),
38
+ ])
39
+ .default("streamable-http"),
40
+ url: z.string().min(1),
41
+ headers: z.record(z.string(), z.string()).optional(),
42
+ });
43
+
44
+ export const SpecMcpServerSchema = z.union([
45
+ SpecStdioServerSchema,
46
+ SpecHttpServerSchema,
47
+ ]);
48
+
49
+ export const SpecMcpDocumentSchema = z.object({
50
+ $schema: z.string().optional(),
51
+ mcpServers: z.record(z.string(), z.unknown()),
52
+ });
53
+
54
+ export type SpecMcpServer = z.infer<typeof SpecMcpServerSchema>;
55
+ export type SpecMcpDocument = z.infer<typeof SpecMcpDocumentSchema>;
56
+
57
+ /**
58
+ * Project one spec-shaped entry onto the assistant's transport union. The
59
+ * two vocabularies already agree on type names and required fields, so this
60
+ * is a field copy plus an optional expander for plugin path variables.
61
+ */
62
+ export function projectSpecServerToTransport(
63
+ entry: SpecMcpServer,
64
+ expand?: (value: string) => string,
65
+ ): McpTransport {
66
+ if (entry.type === "stdio") {
67
+ const map = expand ?? ((value: string) => value);
68
+ return {
69
+ type: "stdio",
70
+ command: entry.command,
71
+ args: (entry.args ?? []).map(map),
72
+ ...(entry.env && {
73
+ env: Object.fromEntries(
74
+ Object.entries(entry.env).map(([key, value]) => [key, map(value)]),
75
+ ),
76
+ }),
77
+ };
78
+ }
79
+ return {
80
+ type: entry.type,
81
+ url: entry.url,
82
+ ...(entry.headers && { headers: entry.headers }),
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Project an in-memory transport onto a spec server entry. Headers are
88
+ * omitted: workspace secrets live in the credential store, and a write
89
+ * must not copy them into `mcp.json`.
90
+ */
91
+ export function projectTransportToSpecServer(
92
+ transport: McpTransport,
93
+ ): Record<string, unknown> {
94
+ if (transport.type === "stdio") {
95
+ const entry: Record<string, unknown> = {
96
+ type: "stdio",
97
+ command: transport.command,
98
+ };
99
+ if (transport.args && transport.args.length > 0) {
100
+ entry.args = transport.args;
101
+ }
102
+ if (transport.env) {
103
+ entry.env = transport.env;
104
+ }
105
+ return entry;
106
+ }
107
+ return {
108
+ type: transport.type,
109
+ url: transport.url,
110
+ };
111
+ }
@@ -13,13 +13,20 @@
13
13
  * further process that starts hosting turns has one call to make.
14
14
  */
15
15
 
16
- import { getConfig, invalidateConfigCache } from "../config/loader.js";
16
+ import { invalidateConfigCache } from "../config/loader.js";
17
17
  import type { McpConfig } from "../config/schemas/mcp.js";
18
18
  import { createMcpToolsFromServer } from "../tools/mcp/mcp-tool-factory.js";
19
19
  import { registerMcpTools, unregisterAllMcpTools } from "../tools/registry.js";
20
20
  import { getLogger } from "../util/logger.js";
21
21
  import { buildEffectiveMcpConfig } from "./effective-config.js";
22
22
  import { getMcpServerManager, stopMcpServerManager } from "./manager.js";
23
+ import {
24
+ EMPTY_MCP_STARTUP_SNAPSHOT,
25
+ type McpStartupSnapshot,
26
+ } from "./tool-caps.js";
27
+ import { loadWorkspaceMcpConfig } from "./workspace-mcp-config.js";
28
+
29
+ export type { McpStartupSnapshot } from "./tool-caps.js";
23
30
 
24
31
  const log = getLogger("mcp-startup");
25
32
 
@@ -36,22 +43,29 @@ const log = getLogger("mcp-startup");
36
43
  * is a startup step in processes whose other work must not be held hostage to
37
44
  * a third-party server being up.
38
45
  *
39
- * @param workspaceMcpConfig The `mcp` block of the assistant config, if any.
40
- * @returns The number of tools registered across all servers.
46
+ * @param workspaceMcpConfig The projected workspace MCP config. Callers
47
+ * that omit it read `/workspace/mcp.json`.
48
+ * @returns A count snapshot of configured/connected servers and the tools
49
+ * that reached this process's registry after caps.
41
50
  */
42
51
  export async function startConfiguredMcpServers(
43
52
  workspaceMcpConfig?: McpConfig,
44
- ): Promise<number> {
45
- let registered = 0;
53
+ ): Promise<McpStartupSnapshot> {
54
+ let snapshot: McpStartupSnapshot = EMPTY_MCP_STARTUP_SNAPSHOT;
46
55
  try {
47
- const mcpConfig = buildEffectiveMcpConfig(workspaceMcpConfig);
48
- if (Object.keys(mcpConfig.servers).length === 0) {
49
- return 0;
56
+ const mcpConfig = buildEffectiveMcpConfig(
57
+ workspaceMcpConfig ?? loadWorkspaceMcpConfig(),
58
+ );
59
+ const configuredServerCount = Object.keys(mcpConfig.servers).length;
60
+ snapshot = { ...EMPTY_MCP_STARTUP_SNAPSHOT, configuredServerCount };
61
+ if (configuredServerCount === 0) {
62
+ return snapshot;
50
63
  }
51
64
 
52
65
  const manager = getMcpServerManager();
53
- const serverToolInfos = await manager.start(mcpConfig);
54
- for (const { serverId, serverConfig, tools } of serverToolInfos) {
66
+ const started = await manager.start(mcpConfig);
67
+ let registered = 0;
68
+ for (const { serverId, serverConfig, tools } of started.servers) {
55
69
  const mcpTools = createMcpToolsFromServer(
56
70
  tools,
57
71
  serverId,
@@ -60,16 +74,26 @@ export async function startConfiguredMcpServers(
60
74
  );
61
75
  registered += registerMcpTools(serverId, mcpTools).length;
62
76
  }
77
+ snapshot = {
78
+ configuredServerCount: started.configuredServerCount,
79
+ connectedServerCount: started.connectedServerCount,
80
+ discoveredToolCount: started.discoveredToolCount,
81
+ registeredToolCount: registered,
82
+ droppedToolCount: started.droppedToolCount,
83
+ truncatedServerIds: started.truncatedServerIds,
84
+ errorServerCount: started.errorServerCount,
85
+ needsAuthServerCount: started.needsAuthServerCount,
86
+ };
63
87
  } catch (err) {
64
88
  log.error(
65
- { err },
89
+ { err, ...snapshot },
66
90
  "MCP server initialization failed, continuing without MCP tools",
67
91
  );
68
- return registered;
92
+ return snapshot;
69
93
  }
70
94
 
71
- log.info({ toolCount: registered }, "MCP tools registered");
72
- return registered;
95
+ log.info(snapshot, "MCP tools registered");
96
+ return snapshot;
73
97
  }
74
98
 
75
99
  /**
@@ -87,9 +111,9 @@ export async function startConfiguredMcpServers(
87
111
  * The window between the teardown and the reconnect has no MCP tools
88
112
  * registered, so an `mcp__*` call landing inside it fails as an unknown tool.
89
113
  *
90
- * @returns The number of tools registered after the reconnect.
114
+ * @returns A count snapshot of the tools registered after the reconnect.
91
115
  */
92
- export async function restartConfiguredMcpServers(): Promise<number> {
116
+ export async function restartConfiguredMcpServers(): Promise<McpStartupSnapshot> {
93
117
  try {
94
118
  await stopMcpServerManager();
95
119
  } catch (err) {
@@ -97,5 +121,5 @@ export async function restartConfiguredMcpServers(): Promise<number> {
97
121
  }
98
122
  unregisterAllMcpTools();
99
123
  invalidateConfigCache();
100
- return startConfiguredMcpServers(getConfig().mcp);
124
+ return startConfiguredMcpServers(loadWorkspaceMcpConfig());
101
125
  }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Code-owned MCP tool-count caps and the selection used when they bind.
3
+ *
4
+ * Caps live here, not in workspace config: migration 153 strips
5
+ * `maxTools` / `globalMaxTools` from `config.json`. The numbers are a
6
+ * context-window budget, not a permission gate. Allowlists and risk
7
+ * still decide what a turn may call.
8
+ *
9
+ * The global cap is applied by a deterministic round-robin across
10
+ * servers sorted by id. Insertion order must not empty a later server
11
+ * while earlier ones keep every tool.
12
+ */
13
+
14
+ import {
15
+ MCP_GLOBAL_MAX_TOOLS,
16
+ MCP_MAX_TOOLS_PER_SERVER,
17
+ } from "../config/schemas/mcp.js";
18
+
19
+ export interface McpServerToolSet<T> {
20
+ serverId: string;
21
+ tools: readonly T[];
22
+ }
23
+
24
+ export interface McpToolCapDecision {
25
+ serverId: string;
26
+ discovered: number;
27
+ kept: number;
28
+ droppedByPerServerCap: number;
29
+ droppedByGlobalCap: number;
30
+ }
31
+
32
+ export interface McpToolCapResult<T> {
33
+ servers: Array<{ serverId: string; tools: T[] }>;
34
+ discoveredToolCount: number;
35
+ keptToolCount: number;
36
+ droppedToolCount: number;
37
+ globalCap: number;
38
+ perServerCap: number;
39
+ decisions: McpToolCapDecision[];
40
+ }
41
+
42
+ export function applyMcpToolCaps<T>(
43
+ servers: ReadonlyArray<McpServerToolSet<T>>,
44
+ options?: { globalMax?: number; perServerMax?: number },
45
+ ): McpToolCapResult<T> {
46
+ const globalCap = options?.globalMax ?? MCP_GLOBAL_MAX_TOOLS;
47
+ const perServerCap = options?.perServerMax ?? MCP_MAX_TOOLS_PER_SERVER;
48
+ const discoveredToolCount = servers.reduce(
49
+ (sum, server) => sum + server.tools.length,
50
+ 0,
51
+ );
52
+
53
+ const afterPerServer = servers.map((server) => {
54
+ const droppedByPerServerCap = Math.max(
55
+ 0,
56
+ server.tools.length - perServerCap,
57
+ );
58
+ return {
59
+ serverId: server.serverId,
60
+ tools: server.tools.slice(0, perServerCap),
61
+ discovered: server.tools.length,
62
+ droppedByPerServerCap,
63
+ };
64
+ });
65
+
66
+ const afterPerServerCount = afterPerServer.reduce(
67
+ (sum, server) => sum + server.tools.length,
68
+ 0,
69
+ );
70
+ if (afterPerServerCount <= globalCap) {
71
+ const decisions = afterPerServer.map((server) => ({
72
+ serverId: server.serverId,
73
+ discovered: server.discovered,
74
+ kept: server.tools.length,
75
+ droppedByPerServerCap: server.droppedByPerServerCap,
76
+ droppedByGlobalCap: 0,
77
+ }));
78
+ return {
79
+ servers: afterPerServer.map((server) => ({
80
+ serverId: server.serverId,
81
+ tools: [...server.tools],
82
+ })),
83
+ discoveredToolCount,
84
+ keptToolCount: afterPerServerCount,
85
+ droppedToolCount: discoveredToolCount - afterPerServerCount,
86
+ globalCap,
87
+ perServerCap,
88
+ decisions,
89
+ };
90
+ }
91
+
92
+ const order = [...afterPerServer].sort((a, b) =>
93
+ a.serverId.localeCompare(b.serverId),
94
+ );
95
+ const selected = new Map<string, T[]>(
96
+ order.map((server) => [server.serverId, []]),
97
+ );
98
+ const cursors = new Map<string, number>(
99
+ order.map((server) => [server.serverId, 0]),
100
+ );
101
+ let kept = 0;
102
+ let progressed = true;
103
+ while (kept < globalCap && progressed) {
104
+ progressed = false;
105
+ for (const server of order) {
106
+ if (kept >= globalCap) {
107
+ break;
108
+ }
109
+ const cursor = cursors.get(server.serverId) ?? 0;
110
+ const tool = server.tools[cursor];
111
+ if (tool !== undefined) {
112
+ selected.get(server.serverId)?.push(tool);
113
+ cursors.set(server.serverId, cursor + 1);
114
+ kept += 1;
115
+ progressed = true;
116
+ }
117
+ }
118
+ }
119
+
120
+ const decisions = afterPerServer.map((server) => {
121
+ const keptTools = selected.get(server.serverId) ?? [];
122
+ return {
123
+ serverId: server.serverId,
124
+ discovered: server.discovered,
125
+ kept: keptTools.length,
126
+ droppedByPerServerCap: server.droppedByPerServerCap,
127
+ droppedByGlobalCap: server.tools.length - keptTools.length,
128
+ };
129
+ });
130
+
131
+ return {
132
+ servers: afterPerServer.map((server) => ({
133
+ serverId: server.serverId,
134
+ tools: [...(selected.get(server.serverId) ?? [])],
135
+ })),
136
+ discoveredToolCount,
137
+ keptToolCount: kept,
138
+ droppedToolCount: discoveredToolCount - kept,
139
+ globalCap,
140
+ perServerCap,
141
+ decisions,
142
+ };
143
+ }
144
+
145
+ export interface McpStartupSnapshot {
146
+ configuredServerCount: number;
147
+ connectedServerCount: number;
148
+ discoveredToolCount: number;
149
+ registeredToolCount: number;
150
+ droppedToolCount: number;
151
+ truncatedServerIds: string[];
152
+ errorServerCount: number;
153
+ needsAuthServerCount: number;
154
+ }
155
+
156
+ export const EMPTY_MCP_STARTUP_SNAPSHOT: McpStartupSnapshot = {
157
+ configuredServerCount: 0,
158
+ connectedServerCount: 0,
159
+ discoveredToolCount: 0,
160
+ registeredToolCount: 0,
161
+ droppedToolCount: 0,
162
+ truncatedServerIds: [],
163
+ errorServerCount: 0,
164
+ needsAuthServerCount: 0,
165
+ };
166
+
167
+ export function truncatedServerIdsFromCaps(
168
+ decisions: readonly McpToolCapDecision[],
169
+ ): string[] {
170
+ return decisions
171
+ .filter(
172
+ (decision) =>
173
+ decision.droppedByPerServerCap > 0 || decision.droppedByGlobalCap > 0,
174
+ )
175
+ .map((decision) => decision.serverId);
176
+ }