@vellumai/assistant 0.4.46 → 0.4.49

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 (382) hide show
  1. package/ARCHITECTURE.md +7 -7
  2. package/README.md +2 -23
  3. package/docs/architecture/integrations.md +45 -41
  4. package/docs/architecture/keychain-broker.md +3 -3
  5. package/docs/architecture/security.md +5 -5
  6. package/docs/runbook-trusted-contacts.md +3 -8
  7. package/hook-templates/debug-prompt-logger/hook.json +1 -1
  8. package/hook-templates/debug-prompt-logger/run.sh +1 -3
  9. package/package.json +1 -1
  10. package/src/__tests__/actor-token-service.test.ts +0 -1
  11. package/src/__tests__/anthropic-provider.test.ts +156 -0
  12. package/src/__tests__/approval-cascade.test.ts +810 -0
  13. package/src/__tests__/approval-primitive.test.ts +0 -1
  14. package/src/__tests__/approval-routes-http.test.ts +2 -0
  15. package/src/__tests__/assistant-attachments.test.ts +12 -34
  16. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
  17. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
  18. package/src/__tests__/browser-fill-credential.test.ts +5 -2
  19. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  20. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
  21. package/src/__tests__/channel-guardian.test.ts +0 -2
  22. package/src/__tests__/channel-readiness-routes.test.ts +35 -25
  23. package/src/__tests__/channel-readiness-service.test.ts +10 -9
  24. package/src/__tests__/checker.test.ts +9 -29
  25. package/src/__tests__/cli.test.ts +23 -0
  26. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  27. package/src/__tests__/computer-use-tools.test.ts +2 -19
  28. package/src/__tests__/config-watcher.test.ts +0 -1
  29. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  30. package/src/__tests__/context-image-dimensions.test.ts +332 -0
  31. package/src/__tests__/context-token-estimator.test.ts +196 -13
  32. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  33. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  34. package/src/__tests__/conversation-routes-guardian-reply.test.ts +144 -0
  35. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  36. package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
  37. package/src/__tests__/credential-broker-server-use.test.ts +22 -21
  38. package/src/__tests__/credential-broker.test.ts +2 -1
  39. package/src/__tests__/credential-metadata-store.test.ts +239 -26
  40. package/src/__tests__/credential-resolve.test.ts +5 -4
  41. package/src/__tests__/credential-security-e2e.test.ts +8 -8
  42. package/src/__tests__/credential-security-invariants.test.ts +111 -7
  43. package/src/__tests__/credential-vault-unit.test.ts +287 -54
  44. package/src/__tests__/credential-vault.test.ts +406 -12
  45. package/src/__tests__/credentials-cli.test.ts +82 -6
  46. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  47. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  48. package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
  49. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  50. package/src/__tests__/gemini-image-service.test.ts +75 -45
  51. package/src/__tests__/gemini-provider.test.ts +9 -6
  52. package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
  53. package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
  54. package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
  55. package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
  56. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  57. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  58. package/src/__tests__/guardian-grant-minting.test.ts +35 -0
  59. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  60. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  61. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
  62. package/src/__tests__/heartbeat-service.test.ts +0 -1
  63. package/src/__tests__/host-cu-proxy.test.ts +629 -0
  64. package/src/__tests__/host-shell-tool.test.ts +27 -15
  65. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  66. package/src/__tests__/ingress-url-consistency.test.ts +14 -21
  67. package/src/__tests__/integration-status.test.ts +38 -25
  68. package/src/__tests__/intent-routing.test.ts +0 -1
  69. package/src/__tests__/invite-routes-http.test.ts +10 -9
  70. package/src/__tests__/keychain-broker-client.test.ts +11 -43
  71. package/src/__tests__/managed-proxy-context.test.ts +5 -3
  72. package/src/__tests__/media-generate-image.test.ts +63 -2
  73. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
  74. package/src/__tests__/messaging-send-tool.test.ts +4 -6
  75. package/src/__tests__/notification-routing-intent.test.ts +0 -1
  76. package/src/__tests__/oauth-cli.test.ts +373 -14
  77. package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
  78. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  79. package/src/__tests__/oauth-store.test.ts +756 -0
  80. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  81. package/src/__tests__/provider-error-scenarios.test.ts +0 -1
  82. package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
  83. package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
  84. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
  85. package/src/__tests__/public-ingress-urls.test.ts +15 -21
  86. package/src/__tests__/recording-handler.test.ts +3 -4
  87. package/src/__tests__/registry.test.ts +2 -2
  88. package/src/__tests__/runtime-events-sse.test.ts +55 -7
  89. package/src/__tests__/schedule-store.test.ts +0 -1
  90. package/src/__tests__/scheduler-recurrence.test.ts +0 -1
  91. package/src/__tests__/schema-transforms.test.ts +226 -0
  92. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  93. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  94. package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
  95. package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
  96. package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
  97. package/src/__tests__/secret-ingress-handler.test.ts +0 -1
  98. package/src/__tests__/secret-onetime-send.test.ts +5 -3
  99. package/src/__tests__/send-endpoint-busy.test.ts +21 -6
  100. package/src/__tests__/sequence-store.test.ts +0 -1
  101. package/src/__tests__/session-init.benchmark.test.ts +4 -5
  102. package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
  103. package/src/__tests__/skill-include-graph.test.ts +66 -0
  104. package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
  105. package/src/__tests__/skill-load-tool.test.ts +149 -1
  106. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  107. package/src/__tests__/skills-uninstall.test.ts +3 -3
  108. package/src/__tests__/skills.test.ts +3 -12
  109. package/src/__tests__/slack-channel-config.test.ts +76 -11
  110. package/src/__tests__/slack-share-routes.test.ts +17 -14
  111. package/src/__tests__/system-prompt.test.ts +0 -1
  112. package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
  113. package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
  114. package/src/__tests__/terminal-tools.test.ts +4 -3
  115. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  116. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  117. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  118. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  119. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  120. package/src/__tests__/tool-executor.test.ts +0 -1
  121. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  122. package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
  123. package/src/__tests__/trust-store.test.ts +1 -22
  124. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  125. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  126. package/src/__tests__/twilio-config.test.ts +2 -1
  127. package/src/__tests__/twilio-provider.test.ts +4 -2
  128. package/src/__tests__/twilio-routes.test.ts +5 -20
  129. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  130. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  131. package/src/agent/ax-tree-compaction.test.ts +235 -0
  132. package/src/agent/loop.ts +76 -130
  133. package/src/calls/call-domain.ts +8 -10
  134. package/src/calls/relay-server.ts +9 -13
  135. package/src/calls/twilio-config.ts +4 -8
  136. package/src/calls/twilio-provider.ts +2 -1
  137. package/src/calls/twilio-rest.ts +2 -1
  138. package/src/calls/twilio-routes.ts +1 -2
  139. package/src/calls/voice-ingress-preflight.ts +1 -1
  140. package/src/cli/commands/browser-relay.ts +46 -15
  141. package/src/cli/commands/completions.ts +0 -3
  142. package/src/cli/commands/credentials.ts +110 -23
  143. package/src/cli/commands/oauth/apps.ts +255 -0
  144. package/src/cli/commands/oauth/connections.ts +299 -0
  145. package/src/cli/commands/oauth/index.ts +52 -0
  146. package/src/cli/commands/oauth/providers.ts +242 -0
  147. package/src/cli/commands/skills.ts +4 -338
  148. package/src/cli/program.ts +1 -5
  149. package/src/cli/reference.ts +1 -3
  150. package/src/cli.ts +3 -2
  151. package/src/config/assistant-feature-flags.ts +0 -3
  152. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  153. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
  154. package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
  155. package/src/config/bundled-skills/computer-use/TOOLS.json +22 -4
  156. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
  157. package/src/config/bundled-skills/gmail/SKILL.md +4 -4
  158. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
  159. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
  160. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
  161. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
  162. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
  163. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
  164. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
  165. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
  166. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
  167. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
  168. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
  169. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
  170. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
  171. package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
  172. package/src/config/bundled-skills/google-calendar/calendar-client.ts +90 -44
  173. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
  174. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
  175. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
  176. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
  177. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
  178. package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
  179. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
  180. package/src/config/bundled-skills/messaging/SKILL.md +6 -6
  181. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
  182. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
  183. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
  184. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
  185. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
  186. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
  187. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
  188. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
  189. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
  190. package/src/config/bundled-skills/messaging/tools/shared.ts +12 -15
  191. package/src/config/bundled-skills/settings/SKILL.md +1 -1
  192. package/src/config/bundled-skills/settings/TOOLS.json +2 -8
  193. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
  194. package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
  195. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
  196. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
  197. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
  198. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
  199. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
  200. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
  201. package/src/config/env-registry.ts +14 -83
  202. package/src/config/env.ts +11 -50
  203. package/src/config/feature-flag-registry.json +16 -16
  204. package/src/config/schema.ts +3 -1
  205. package/src/config/skills.ts +21 -2
  206. package/src/context/image-dimensions.ts +229 -0
  207. package/src/context/token-estimator.ts +75 -12
  208. package/src/context/window-manager.ts +49 -10
  209. package/src/daemon/assistant-attachments.ts +1 -13
  210. package/src/daemon/guardian-action-generators.ts +4 -5
  211. package/src/daemon/handlers/config-ingress.ts +8 -33
  212. package/src/daemon/handlers/config-slack-channel.ts +76 -56
  213. package/src/daemon/handlers/config-telegram.ts +53 -24
  214. package/src/daemon/handlers/sessions.ts +10 -24
  215. package/src/daemon/handlers/shared.ts +0 -130
  216. package/src/daemon/host-cu-proxy.ts +401 -0
  217. package/src/daemon/lifecycle.ts +39 -63
  218. package/src/daemon/message-protocol.ts +3 -0
  219. package/src/daemon/message-types/computer-use.ts +2 -119
  220. package/src/daemon/message-types/host-cu.ts +19 -0
  221. package/src/daemon/message-types/integrations.ts +1 -0
  222. package/src/daemon/message-types/messages.ts +3 -0
  223. package/src/daemon/server.ts +14 -21
  224. package/src/daemon/session-agent-loop-handlers.ts +2 -0
  225. package/src/daemon/session-attachments.ts +1 -2
  226. package/src/daemon/session-messaging.ts +3 -1
  227. package/src/daemon/session-slash.ts +1 -1
  228. package/src/daemon/session-surfaces.ts +40 -28
  229. package/src/daemon/session-tool-setup.ts +20 -11
  230. package/src/daemon/session.ts +139 -16
  231. package/src/daemon/tool-side-effects.ts +2 -8
  232. package/src/daemon/watch-handler.ts +2 -2
  233. package/src/email/providers/index.ts +2 -1
  234. package/src/events/tool-metrics-listener.ts +2 -2
  235. package/src/hooks/manager.ts +1 -4
  236. package/src/inbound/public-ingress-urls.ts +7 -7
  237. package/src/instrument.ts +15 -1
  238. package/src/logfire.ts +16 -5
  239. package/src/media/app-icon-generator.ts +30 -4
  240. package/src/media/avatar-router.ts +26 -3
  241. package/src/media/gemini-image-service.ts +28 -2
  242. package/src/memory/conversation-key-store.ts +21 -0
  243. package/src/memory/db-init.ts +4 -0
  244. package/src/memory/guardian-action-store.ts +1 -1
  245. package/src/memory/migrations/149-oauth-tables.ts +60 -0
  246. package/src/memory/migrations/index.ts +1 -0
  247. package/src/memory/schema/guardian.ts +1 -1
  248. package/src/memory/schema/index.ts +1 -0
  249. package/src/memory/schema/oauth.ts +65 -0
  250. package/src/messaging/provider.ts +19 -13
  251. package/src/messaging/providers/gmail/adapter.ts +40 -23
  252. package/src/messaging/providers/gmail/client.ts +283 -122
  253. package/src/messaging/providers/gmail/people-client.ts +32 -24
  254. package/src/messaging/providers/slack/adapter.ts +29 -19
  255. package/src/messaging/providers/slack/client.ts +265 -78
  256. package/src/messaging/providers/telegram-bot/adapter.ts +19 -18
  257. package/src/messaging/providers/whatsapp/adapter.ts +17 -11
  258. package/src/messaging/registry.ts +2 -31
  259. package/src/notifications/copy-composer.ts +0 -5
  260. package/src/notifications/signal.ts +4 -5
  261. package/src/oauth/byo-connection.test.ts +537 -0
  262. package/src/oauth/byo-connection.ts +128 -0
  263. package/src/oauth/connect-orchestrator.ts +139 -56
  264. package/src/oauth/connect-types.ts +17 -23
  265. package/src/oauth/connection-resolver.ts +58 -0
  266. package/src/oauth/connection.ts +38 -0
  267. package/src/oauth/manual-token-connection.ts +104 -0
  268. package/src/oauth/oauth-store.ts +496 -0
  269. package/src/oauth/platform-connection.test.ts +192 -0
  270. package/src/oauth/platform-connection.ts +111 -0
  271. package/src/oauth/provider-behaviors.ts +124 -0
  272. package/src/oauth/scope-policy.ts +9 -2
  273. package/src/oauth/seed-providers.ts +161 -0
  274. package/src/oauth/token-persistence.ts +74 -78
  275. package/src/permissions/checker.ts +8 -4
  276. package/src/permissions/defaults.ts +0 -1
  277. package/src/permissions/prompter.ts +10 -1
  278. package/src/permissions/trust-store.ts +13 -0
  279. package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
  280. package/src/prompts/system-prompt.ts +70 -45
  281. package/src/providers/anthropic/client.ts +133 -24
  282. package/src/providers/gemini/client.ts +15 -6
  283. package/src/providers/managed-proxy/constants.ts +2 -2
  284. package/src/providers/managed-proxy/context.ts +5 -1
  285. package/src/providers/ratelimit.ts +17 -0
  286. package/src/providers/registry.ts +2 -2
  287. package/src/providers/retry.ts +1 -27
  288. package/src/runtime/AGENTS.md +17 -0
  289. package/src/runtime/auth/route-policy.ts +0 -3
  290. package/src/runtime/channel-invite-transports/telegram.ts +2 -1
  291. package/src/runtime/channel-readiness-service.ts +168 -195
  292. package/src/runtime/channel-readiness-types.ts +4 -0
  293. package/src/runtime/channel-reply-delivery.ts +0 -40
  294. package/src/runtime/gateway-client.ts +0 -7
  295. package/src/runtime/guardian-action-conversation-turn.ts +1 -3
  296. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  297. package/src/runtime/guardian-action-message-composer.ts +3 -23
  298. package/src/runtime/http-server.ts +17 -10
  299. package/src/runtime/http-types.ts +2 -3
  300. package/src/runtime/middleware/rate-limiter.ts +74 -20
  301. package/src/runtime/middleware/twilio-validation.ts +1 -11
  302. package/src/runtime/pending-interactions.ts +14 -12
  303. package/src/runtime/routes/channel-delivery-routes.ts +0 -1
  304. package/src/runtime/routes/channel-readiness-routes.ts +2 -0
  305. package/src/runtime/routes/conversation-routes.ts +73 -19
  306. package/src/runtime/routes/diagnostics-routes.ts +11 -9
  307. package/src/runtime/routes/events-routes.ts +21 -11
  308. package/src/runtime/routes/guardian-approval-interception.ts +20 -5
  309. package/src/runtime/routes/host-cu-routes.ts +97 -0
  310. package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
  311. package/src/runtime/routes/integrations/slack/share.ts +6 -6
  312. package/src/runtime/routes/integrations/twilio.ts +6 -5
  313. package/src/runtime/routes/log-export-routes.ts +126 -8
  314. package/src/runtime/routes/secret-routes.ts +3 -2
  315. package/src/runtime/routes/settings-routes.ts +113 -48
  316. package/src/runtime/routes/surface-action-routes.ts +1 -1
  317. package/src/runtime/routes/watch-routes.ts +128 -0
  318. package/src/schedule/integration-status.ts +10 -8
  319. package/src/security/credential-key.ts +14 -0
  320. package/src/security/keychain-broker-client.ts +5 -6
  321. package/src/security/oauth2.ts +1 -1
  322. package/src/security/token-manager.ts +145 -43
  323. package/src/skills/catalog-install.ts +358 -0
  324. package/src/skills/include-graph.ts +32 -0
  325. package/src/telegram/bot-username.ts +2 -3
  326. package/src/tools/apps/definitions.ts +0 -5
  327. package/src/tools/assets/materialize.ts +0 -5
  328. package/src/tools/assets/search.ts +0 -5
  329. package/src/tools/browser/headless-browser.ts +1 -67
  330. package/src/tools/browser/network-recorder.ts +1 -1
  331. package/src/tools/browser/network-recording-types.ts +1 -1
  332. package/src/tools/claude-code/claude-code.ts +0 -5
  333. package/src/tools/computer-use/definitions.ts +46 -11
  334. package/src/tools/computer-use/registry.ts +4 -5
  335. package/src/tools/credentials/broker.ts +5 -4
  336. package/src/tools/credentials/metadata-store.ts +22 -74
  337. package/src/tools/credentials/resolve.ts +2 -1
  338. package/src/tools/credentials/vault.ts +139 -151
  339. package/src/tools/filesystem/edit.ts +1 -6
  340. package/src/tools/filesystem/read.ts +0 -5
  341. package/src/tools/filesystem/write.ts +1 -6
  342. package/src/tools/host-filesystem/edit.ts +1 -6
  343. package/src/tools/host-filesystem/read.ts +1 -6
  344. package/src/tools/host-filesystem/write.ts +1 -6
  345. package/src/tools/mcp/mcp-tool-factory.ts +18 -1
  346. package/src/tools/memory/definitions.ts +0 -5
  347. package/src/tools/network/web-fetch.ts +0 -5
  348. package/src/tools/network/web-search.ts +0 -5
  349. package/src/tools/registry.ts +2 -7
  350. package/src/tools/schema-transforms.ts +99 -0
  351. package/src/tools/skills/load.ts +62 -8
  352. package/src/tools/swarm/delegate.ts +0 -5
  353. package/src/tools/system/avatar-generator.ts +0 -5
  354. package/src/tools/ui-surface/definitions.ts +0 -15
  355. package/src/tools/watch/screen-watch.ts +0 -5
  356. package/src/tools/watch/watch-state.ts +0 -12
  357. package/src/util/logger.ts +7 -41
  358. package/src/util/platform.ts +9 -28
  359. package/src/version.ts +10 -0
  360. package/src/watcher/providers/github.ts +51 -52
  361. package/src/watcher/providers/gmail.ts +88 -80
  362. package/src/watcher/providers/google-calendar.ts +94 -86
  363. package/src/watcher/providers/linear.ts +87 -93
  364. package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
  365. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
  366. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
  367. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
  368. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
  369. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
  370. package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
  371. package/src/cli/commands/dev.ts +0 -129
  372. package/src/cli/commands/map.ts +0 -391
  373. package/src/cli/commands/oauth.ts +0 -77
  374. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -16
  375. package/src/daemon/computer-use-session.ts +0 -1020
  376. package/src/daemon/ride-shotgun-handler.ts +0 -567
  377. package/src/oauth/provider-profiles.ts +0 -192
  378. package/src/prompts/computer-use-prompt.ts +0 -98
  379. package/src/runtime/routes/computer-use-routes.ts +0 -641
  380. package/src/runtime/telegram-streaming-delivery.test.ts +0 -597
  381. package/src/runtime/telegram-streaming-delivery.ts +0 -383
  382. package/src/tools/computer-use/request-computer-control.ts +0 -61
@@ -1,13 +1,22 @@
1
1
  import { getConfig } from "../../config/loader.js";
2
2
  import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
3
3
  import {
4
- getProviderProfile,
4
+ disconnectOAuthProvider,
5
+ getAppByProviderAndClientId,
6
+ getMostRecentAppByProvider,
7
+ getProvider,
8
+ } from "../../oauth/oauth-store.js";
9
+ import {
10
+ getProviderBehavior,
5
11
  resolveService,
6
12
  SERVICE_ALIASES,
7
- } from "../../oauth/provider-profiles.js";
13
+ } from "../../oauth/provider-behaviors.js";
8
14
  import { RiskLevel } from "../../permissions/types.js";
9
15
  import type { ToolDefinition } from "../../providers/types.js";
10
- import type { TokenEndpointAuthMethod } from "../../security/oauth2.js";
16
+ import { buildAssistantEvent } from "../../runtime/assistant-event.js";
17
+ import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
18
+ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../../runtime/assistant-scope.js";
19
+ import { credentialKey } from "../../security/credential-key.js";
11
20
  import {
12
21
  deleteSecureKeyAsync,
13
22
  getSecureKey,
@@ -32,27 +41,6 @@ import { toPolicyFromInput, validatePolicyInput } from "./policy-validate.js";
32
41
 
33
42
  const log = getLogger("credential-vault");
34
43
 
35
- /**
36
- * Look up a stored OAuth field (e.g. client_id or client_secret) for a service.
37
- * Checks both the canonical and alias service names.
38
- */
39
- function findStoredOAuthField(
40
- service: string,
41
- field: string,
42
- ): string | undefined {
43
- const servicesToCheck = [service];
44
- // Also check the alias if the input is the canonical name, or vice versa
45
- for (const [alias, canonical] of Object.entries(SERVICE_ALIASES)) {
46
- if (canonical === service) servicesToCheck.push(alias);
47
- if (alias === service) servicesToCheck.push(canonical);
48
- }
49
- for (const svc of servicesToCheck) {
50
- const value = getSecureKey(`credential:${svc}:${field}`);
51
- if (value) return value;
52
- }
53
- return undefined;
54
- }
55
-
56
44
  class CredentialStoreTool implements Tool {
57
45
  name = "credential_store";
58
46
  description =
@@ -124,16 +112,6 @@ class CredentialStoreTool implements Tool {
124
112
  description:
125
113
  'Human-readable description of intended usage (for store/prompt actions), e.g. "GitHub login for pushing changes"',
126
114
  },
127
- auth_url: {
128
- type: "string",
129
- description:
130
- "OAuth2 authorization endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
131
- },
132
- token_url: {
133
- type: "string",
134
- description:
135
- "OAuth2 token endpoint (only for oauth2_connect action). Auto-filled for well-known services (gmail, slack).",
136
- },
137
115
  scopes: {
138
116
  type: "array",
139
117
  items: { type: "string" },
@@ -145,27 +123,11 @@ class CredentialStoreTool implements Tool {
145
123
  description:
146
124
  "OAuth2 client ID (only for oauth2_connect action). If omitted, looked up from previously stored credentials.",
147
125
  },
148
- extra_params: {
149
- type: "object",
150
- description:
151
- "Extra query params for OAuth2 auth URL (only for oauth2_connect action)",
152
- },
153
- userinfo_url: {
154
- type: "string",
155
- description:
156
- "Endpoint to fetch account info after OAuth2 auth (only for oauth2_connect action)",
157
- },
158
126
  client_secret: {
159
127
  type: "string",
160
128
  description:
161
129
  "OAuth2 client secret for providers that require it (e.g. Google, Slack). If omitted, looked up from previously stored credentials; if still absent, PKCE-only is used (only for oauth2_connect action)",
162
130
  },
163
- token_endpoint_auth_method: {
164
- type: "string",
165
- enum: ["client_secret_basic", "client_secret_post"],
166
- description:
167
- 'How to send client credentials at the token endpoint: "client_secret_post" (default, in POST body) or "client_secret_basic" (HTTP Basic Auth header). Only for oauth2_connect action.',
168
- },
169
131
  alias: {
170
132
  type: "string",
171
133
  description:
@@ -206,11 +168,6 @@ class CredentialStoreTool implements Tool {
206
168
  description:
207
169
  "Templates describing how to inject this credential into proxied requests (for store and prompt actions)",
208
170
  },
209
- reason: {
210
- type: "string",
211
- description:
212
- "Brief non-technical explanation of what you are doing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
213
- },
214
171
  },
215
172
  required: ["action"],
216
173
  },
@@ -359,7 +316,7 @@ class CredentialStoreTool implements Tool {
359
316
  };
360
317
  }
361
318
 
362
- const key = `credential:${service}:${field}`;
319
+ const key = credentialKey(service, field);
363
320
  const ok = await setSecureKeyAsync(key, value);
364
321
  if (!ok) {
365
322
  return {
@@ -422,7 +379,7 @@ class CredentialStoreTool implements Tool {
422
379
  const entries = allMetadata
423
380
  .filter((m) => {
424
381
  if (secureKeySet)
425
- return secureKeySet.has(`credential:${m.service}:${m.field}`);
382
+ return secureKeySet.has(credentialKey(m.service, m.field));
426
383
  return true;
427
384
  })
428
385
  .map((m) => {
@@ -472,7 +429,7 @@ class CredentialStoreTool implements Tool {
472
429
  };
473
430
  }
474
431
 
475
- const key = `credential:${service}:${field}`;
432
+ const key = credentialKey(service, field);
476
433
  const result = await deleteSecureKeyAsync(key);
477
434
  if (result === "error") {
478
435
  return {
@@ -494,6 +451,21 @@ class CredentialStoreTool implements Tool {
494
451
  "metadata delete failed after removing credential",
495
452
  );
496
453
  }
454
+ // Also clean up any OAuth connection for this service (best-effort)
455
+ try {
456
+ const oauthResult = await disconnectOAuthProvider(service);
457
+ if (oauthResult === "error") {
458
+ log.warn(
459
+ { service },
460
+ "OAuth disconnect failed after removing credential — secure key deletion error",
461
+ );
462
+ }
463
+ } catch (err) {
464
+ log.warn(
465
+ { service, err },
466
+ "OAuth disconnect failed after removing credential",
467
+ );
468
+ }
497
469
  return {
498
470
  content: `Deleted credential for ${service}/${field}.`,
499
471
  isError: false,
@@ -712,7 +684,7 @@ class CredentialStoreTool implements Tool {
712
684
  }
713
685
 
714
686
  // Default: persist to keychain
715
- const key = `credential:${service}:${field}`;
687
+ const key = credentialKey(service, field);
716
688
  const ok = await setSecureKeyAsync(key, result.value);
717
689
  if (!ok) {
718
690
  return {
@@ -754,51 +726,44 @@ class CredentialStoreTool implements Tool {
754
726
  // Resolve aliases (e.g. "gmail" → "integration:gmail")
755
727
  const service = resolveService(rawService);
756
728
 
757
- // Fill missing params from provider profile
758
- const profile = getProviderProfile(service);
759
-
760
- // Look up client_id/client_secret from stored credentials if not provided
761
- const clientId =
762
- (input.client_id as string | undefined) ??
763
- findStoredOAuthField(service, "client_id");
764
- const clientSecret =
765
- (input.client_secret as string | undefined) ??
766
- findStoredOAuthField(service, "client_secret");
729
+ // Code-side behavioral fields (identityVerifier, setup, etc.)
730
+ const behavior = getProviderBehavior(service);
731
+ // Protocol-level config from the DB (authUrl, tokenUrl, scopes, etc.)
732
+ const providerRow = getProvider(service);
733
+
734
+ // Resolve client_id and client_secret.
735
+ // Priority:
736
+ // 1. Explicit input from the caller
737
+ // 2. oauth-store DB when clientId is already known, look up the
738
+ // matching app so the secret comes from the same app. Only fall
739
+ // back to the most-recent-app heuristic when clientId is unknown.
740
+ let clientId = input.client_id as string | undefined;
741
+ let clientSecret = input.client_secret as string | undefined;
742
+
743
+ if (!clientId || !clientSecret) {
744
+ const dbApp = clientId
745
+ ? getAppByProviderAndClientId(service, clientId)
746
+ : getMostRecentAppByProvider(service);
747
+ if (dbApp) {
748
+ if (!clientId) clientId = dbApp.clientId;
749
+ if (!clientSecret) {
750
+ clientSecret = getSecureKey(
751
+ `oauth_app/${dbApp.id}/client_secret`,
752
+ );
753
+ }
754
+ }
755
+ }
767
756
 
768
757
  // Early guardrails that stay in vault.ts (credential resolution is vault-specific)
769
758
  const inputScopes = input.scopes as string[] | undefined;
770
759
 
771
- if (profile) {
772
- // Profile-based provider (well-known like gmail, slack, twitter):
773
- // Don't pass authUrl/tokenUrl the orchestrator resolves those from the profile.
774
- // Pass user-provided scopes as requestedScopes so the scope policy engine is invoked.
775
- // If no scopes provided, pass neither — let the orchestrator use profile defaults via scope policy.
776
- } else {
777
- // Custom/unknown provider: require authUrl, tokenUrl, scopes from input
778
- if (!input.auth_url)
779
- return {
780
- content:
781
- "Error: auth_url is required for oauth2_connect action (no well-known config for this service)",
782
- isError: true,
783
- };
784
- if (!input.token_url)
785
- return {
786
- content:
787
- "Error: token_url is required for oauth2_connect action (no well-known config for this service)",
788
- isError: true,
789
- };
790
- if (!inputScopes)
791
- return {
792
- content:
793
- "Error: scopes is required for oauth2_connect action (no well-known config for this service)",
794
- isError: true,
795
- };
760
+ if (!providerRow) {
761
+ return {
762
+ content: `Error: no OAuth provider registered for "${service}". Ensure the provider is seeded in the database.`,
763
+ isError: true,
764
+ };
796
765
  }
797
766
 
798
- const authUrl =
799
- (input.auth_url as string | undefined) ?? profile?.authUrl;
800
- const tokenUrl =
801
- (input.token_url as string | undefined) ?? profile?.tokenUrl;
802
767
  if (!clientId)
803
768
  return {
804
769
  content:
@@ -810,10 +775,10 @@ class CredentialStoreTool implements Tool {
810
775
  // agent to collect it from the user rather than letting it improvise
811
776
  // browser-automation workarounds that inevitably fail.
812
777
  const requiresSecret =
813
- profile?.setup?.requiresClientSecret ??
814
- !!(profile?.tokenEndpointAuthMethod || profile?.extraParams);
778
+ behavior?.setup?.requiresClientSecret ??
779
+ !!(providerRow.tokenEndpointAuthMethod || providerRow.extraParams);
815
780
  if (requiresSecret && !clientSecret) {
816
- const skillId = profile?.setupSkillId;
781
+ const skillId = behavior?.setupSkillId;
817
782
  const skillHint = skillId
818
783
  ? `\n\nLoad the "${skillId}" skill for provider-specific instructions on obtaining the client secret.`
819
784
  : '\n\nUse credential_store with action "prompt" to securely collect the client_secret from the user before calling oauth2_connect again.';
@@ -823,25 +788,8 @@ class CredentialStoreTool implements Tool {
823
788
  };
824
789
  }
825
790
 
826
- try {
827
- assertMetadataWritable();
828
- } catch {
829
- return {
830
- content:
831
- "Error: credential metadata file has an unrecognized version; cannot store credentials",
832
- isError: true,
833
- };
834
- }
835
-
836
- const tokenEndpointAuthMethod =
837
- (input.token_endpoint_auth_method as
838
- | TokenEndpointAuthMethod
839
- | undefined) ?? profile?.tokenEndpointAuthMethod;
840
-
841
- // Delegate to the shared orchestrator.
842
- // For profile-based providers, pass user scopes as requestedScopes so the
843
- // scope policy engine (resolveScopes) is invoked. For custom providers,
844
- // pass scopes directly as an explicit override.
791
+ // Delegate to the shared orchestrator — it resolves authUrl, tokenUrl,
792
+ // extraParams, userinfoUrl, and tokenEndpointAuthMethod from the DB.
845
793
  const result = await orchestrateOAuthConnect({
846
794
  service: rawService,
847
795
  clientId,
@@ -849,24 +797,45 @@ class CredentialStoreTool implements Tool {
849
797
  isInteractive: !!context.isInteractive,
850
798
  sendToClient: context.sendToClient,
851
799
  allowedTools: input.allowed_tools as string[] | undefined,
852
- authUrl,
853
- tokenUrl,
854
- ...(profile
855
- ? {
856
- // Profile-based: let orchestrator resolve scopes via policy engine.
857
- // Only pass requestedScopes if the user explicitly provided scopes.
858
- ...(inputScopes ? { requestedScopes: inputScopes } : {}),
859
- }
860
- : {
861
- // Custom provider: explicit scopes override (bypasses policy engine)
862
- scopes: inputScopes,
863
- }),
864
- extraParams:
865
- (input.extra_params as Record<string, string> | undefined) ??
866
- profile?.extraParams,
867
- userinfoUrl:
868
- (input.userinfo_url as string | undefined) ?? profile?.userinfoUrl,
869
- tokenEndpointAuthMethod,
800
+ ...(inputScopes ? { requestedScopes: inputScopes } : {}),
801
+ onDeferredComplete: (deferredResult) => {
802
+ // Emit oauth_connect_result to all connected SSE clients so the
803
+ // UI can update immediately when the deferred browser flow completes.
804
+ assistantEventHub
805
+ .publish(
806
+ buildAssistantEvent(DAEMON_INTERNAL_ASSISTANT_ID, {
807
+ type: "oauth_connect_result",
808
+ success: deferredResult.success,
809
+ service: deferredResult.service,
810
+ accountInfo: deferredResult.accountInfo,
811
+ error: deferredResult.error,
812
+ }),
813
+ )
814
+ .catch((err) => {
815
+ log.warn(
816
+ { err, service: deferredResult.service },
817
+ "Failed to publish oauth_connect_result event",
818
+ );
819
+ });
820
+
821
+ if (deferredResult.success) {
822
+ log.info(
823
+ {
824
+ service: deferredResult.service,
825
+ accountInfo: deferredResult.accountInfo,
826
+ },
827
+ "Deferred OAuth connect completed successfully",
828
+ );
829
+ } else {
830
+ log.warn(
831
+ {
832
+ service: deferredResult.service,
833
+ err: deferredResult.error,
834
+ },
835
+ "Deferred OAuth connect failed",
836
+ );
837
+ }
838
+ },
870
839
  });
871
840
 
872
841
  if (!result.success) {
@@ -897,8 +866,8 @@ class CredentialStoreTool implements Tool {
897
866
  };
898
867
  }
899
868
  const resolvedService = resolveService(rawService);
900
- const profile = getProviderProfile(resolvedService);
901
- if (!profile) {
869
+ const descProviderRow = getProvider(resolvedService);
870
+ if (!descProviderRow) {
902
871
  return {
903
872
  content: `No well-known OAuth config found for "${rawService}". Available services: ${Object.keys(
904
873
  SERVICE_ALIASES,
@@ -907,11 +876,17 @@ class CredentialStoreTool implements Tool {
907
876
  };
908
877
  }
909
878
 
879
+ const descBehavior = getProviderBehavior(resolvedService);
880
+
910
881
  // Compute the redirect URI based on callback transport
911
882
  let redirectUri: string;
912
- const transport = profile.callbackTransport ?? "gateway";
913
- if (transport === "loopback" && profile.loopbackPort) {
914
- redirectUri = `http://127.0.0.1:${profile.loopbackPort}/oauth/callback`;
883
+ const transport =
884
+ (descProviderRow.callbackTransport as
885
+ | "loopback"
886
+ | "gateway"
887
+ | null) ?? "gateway";
888
+ if (transport === "loopback" && descProviderRow.loopbackPort) {
889
+ redirectUri = `http://127.0.0.1:${descProviderRow.loopbackPort}/oauth/callback`;
915
890
  } else if (transport === "loopback") {
916
891
  redirectUri =
917
892
  "(automatic — no redirect URI needed, uses random localhost port)";
@@ -925,26 +900,39 @@ class CredentialStoreTool implements Tool {
925
900
  redirectUri = `${baseUrl}/webhooks/oauth/callback`;
926
901
  } catch {
927
902
  redirectUri =
928
- "(requires INGRESS_PUBLIC_BASE_URL — not currently configured)";
903
+ "(requires ingress.publicBaseUrl — not currently configured)";
929
904
  }
930
905
  }
931
906
 
932
907
  // Prefer explicit setup metadata, fall back to heuristic
933
908
  const requiresClientSecret =
934
- profile.setup?.requiresClientSecret ??
935
- !!(profile.tokenEndpointAuthMethod || profile.extraParams);
909
+ descBehavior?.setup?.requiresClientSecret ??
910
+ !!(
911
+ descProviderRow.tokenEndpointAuthMethod ||
912
+ descProviderRow.extraParams
913
+ );
914
+
915
+ const descDefaultScopes: string[] = descProviderRow.defaultScopes
916
+ ? JSON.parse(descProviderRow.defaultScopes)
917
+ : [];
936
918
 
937
919
  const info: Record<string, unknown> = {
938
920
  service: resolvedService,
939
- authUrl: profile.authUrl,
940
- tokenUrl: profile.tokenUrl,
941
- scopes: profile.defaultScopes,
921
+ authUrl: descProviderRow.authUrl,
922
+ tokenUrl: descProviderRow.tokenUrl,
923
+ scopes: descDefaultScopes,
942
924
  callbackTransport: transport,
943
925
  redirectUri,
944
926
  requiresClientSecret,
945
927
  };
946
- if (profile.setup) info.setup = profile.setup;
947
- if (profile.extraParams) info.extraParams = profile.extraParams;
928
+ if (descBehavior?.setup) info.setup = descBehavior.setup;
929
+ if (descProviderRow.extraParams) {
930
+ try {
931
+ info.extraParams = JSON.parse(descProviderRow.extraParams);
932
+ } catch {
933
+ // Non-fatal
934
+ }
935
+ }
948
936
 
949
937
  return { content: JSON.stringify(info, null, 2), isError: false };
950
938
  }
@@ -38,13 +38,8 @@ class FileEditTool implements Tool {
38
38
  description:
39
39
  "Replace all occurrences of old_string instead of requiring a unique match (default: false)",
40
40
  },
41
- reason: {
42
- type: "string",
43
- description:
44
- "Brief non-technical explanation of why this file is being edited, shown to the user as a status update. Use simple language a non-technical person would understand.",
45
- },
46
41
  },
47
- required: ["path", "old_string", "new_string", "reason"],
42
+ required: ["path", "old_string", "new_string"],
48
43
  },
49
44
  };
50
45
  }
@@ -38,11 +38,6 @@ class FileReadTool implements Tool {
38
38
  type: "number",
39
39
  description: "Maximum number of lines to read",
40
40
  },
41
- reason: {
42
- type: "string",
43
- description:
44
- "Brief non-technical explanation of what you are reading and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
45
- },
46
41
  },
47
42
  required: ["path"],
48
43
  },
@@ -28,13 +28,8 @@ class FileWriteTool implements Tool {
28
28
  type: "string",
29
29
  description: "The content to write to the file",
30
30
  },
31
- reason: {
32
- type: "string",
33
- description:
34
- "Brief non-technical explanation of why this file is being written, shown to the user as a status update. Use simple language a non-technical person would understand.",
35
- },
36
31
  },
37
- required: ["path", "content", "reason"],
32
+ required: ["path", "content"],
38
33
  },
39
34
  };
40
35
  }
@@ -35,13 +35,8 @@ class HostFileEditTool implements Tool {
35
35
  description:
36
36
  "Replace all occurrences instead of requiring a unique match (default: false)",
37
37
  },
38
- reason: {
39
- type: "string",
40
- description:
41
- "Brief non-technical explanation of why this file is being edited, shown to the user as a status update. Use simple language a non-technical person would understand.",
42
- },
43
38
  },
44
- required: ["path", "old_string", "new_string", "reason"],
39
+ required: ["path", "old_string", "new_string"],
45
40
  },
46
41
  };
47
42
  }
@@ -29,13 +29,8 @@ class HostFileReadTool implements Tool {
29
29
  type: "number",
30
30
  description: "Maximum number of lines to read",
31
31
  },
32
- reason: {
33
- type: "string",
34
- description:
35
- "Brief non-technical explanation of why this file is being read, shown to the user as a status update. Use simple language a non-technical person would understand.",
36
- },
37
32
  },
38
- required: ["path", "reason"],
33
+ required: ["path"],
39
34
  },
40
35
  };
41
36
  }
@@ -27,13 +27,8 @@ class HostFileWriteTool implements Tool {
27
27
  type: "string",
28
28
  description: "The content to write to the file",
29
29
  },
30
- reason: {
31
- type: "string",
32
- description:
33
- "Brief non-technical explanation of why this file is being written, shown to the user as a status update. Use simple language a non-technical person would understand.",
34
- },
35
30
  },
36
- required: ["path", "content", "reason"],
31
+ required: ["path", "content"],
37
32
  },
38
33
  };
39
34
  }
@@ -2,6 +2,7 @@ import type { McpServerConfig } from "../../config/schemas/mcp.js";
2
2
  import type { McpServerManager } from "../../mcp/manager.js";
3
3
  import { RiskLevel } from "../../permissions/types.js";
4
4
  import type { ToolDefinition } from "../../providers/types.js";
5
+ import { schemaDefinesProperty } from "../schema-transforms.js";
5
6
  import type { Tool, ToolContext, ToolExecutionResult } from "../types.js";
6
7
 
7
8
  const riskMap: Record<string, RiskLevel> = {
@@ -36,6 +37,10 @@ export function createMcpTool(
36
37
  ): Tool {
37
38
  const namespacedName = mcpToolName(serverId, metadata.name);
38
39
  const riskLevel = riskMap[serverConfig.defaultRiskLevel] ?? RiskLevel.High;
40
+ const serverDefinesReason = schemaDefinesProperty(
41
+ metadata.inputSchema,
42
+ "reason",
43
+ );
39
44
 
40
45
  return {
41
46
  name: namespacedName,
@@ -59,7 +64,19 @@ export function createMcpTool(
59
64
  _context: ToolContext,
60
65
  ): Promise<ToolExecutionResult> {
61
66
  try {
62
- const result = await manager.callTool(serverId, metadata.name, input);
67
+ // Strip injected reason before sending to MCP server
68
+ const { reason: _reason, ...mcpInput } = input as Record<
69
+ string,
70
+ unknown
71
+ > & {
72
+ reason?: unknown;
73
+ };
74
+ const forwardInput = serverDefinesReason ? input : mcpInput;
75
+ const result = await manager.callTool(
76
+ serverId,
77
+ metadata.name,
78
+ forwardInput,
79
+ );
63
80
  return {
64
81
  content: result.content,
65
82
  isError: result.isError,
@@ -62,11 +62,6 @@ const memoryManageProperties = {
62
62
  type: "string" as const,
63
63
  description: "Short subject/topic label, 2-8 words (optional, save only)",
64
64
  },
65
- reason: {
66
- type: "string" as const,
67
- description:
68
- "Brief non-technical explanation shown to the user as a status update",
69
- },
70
65
  };
71
66
 
72
67
  export const memoryManageDefinition: ToolDefinition = {
@@ -863,11 +863,6 @@ class WebFetchTool implements Tool {
863
863
  description:
864
864
  "If true, allows requests to localhost/private-network hosts. Disabled by default for SSRF safety.",
865
865
  },
866
- reason: {
867
- type: "string",
868
- description:
869
- "Brief non-technical explanation of what you are fetching and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
870
- },
871
866
  },
872
867
  required: ["url"],
873
868
  },
@@ -302,11 +302,6 @@ class WebSearchTool implements Tool {
302
302
  description:
303
303
  'Filter by recency: "pd" (past day), "pw" (past week), "pm" (past month), "py" (past year). Only used with Brave provider.',
304
304
  },
305
- reason: {
306
- type: "string",
307
- description:
308
- "Brief non-technical explanation of what you are searching for and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
309
- },
310
305
  },
311
306
  required: ["query"],
312
307
  },
@@ -4,7 +4,6 @@ import { getLogger } from "../util/logger.js";
4
4
  import { coreAppProxyTools } from "./apps/definitions.js";
5
5
  import { registerAppTools } from "./apps/registry.js";
6
6
  import { allComputerUseTools } from "./computer-use/definitions.js";
7
- import { requestComputerControlTool } from "./computer-use/request-computer-control.js";
8
7
  import { hostFileEditTool } from "./host-filesystem/edit.js";
9
8
  import { hostFileReadTool } from "./host-filesystem/read.js";
10
9
  import { hostFileWriteTool } from "./host-filesystem/write.js";
@@ -300,8 +299,8 @@ export function getSkillRefCount(skillId: string): number {
300
299
  }
301
300
 
302
301
  export function getAllToolDefinitions(): ToolDefinition[] {
303
- // Exclude proxy tools (e.g. computer_use_* tools) — they are only used
304
- // by ComputerUseSession which builds its own tool definitions list.
302
+ // Exclude proxy tools (e.g. computer_use_* tools) — they are projected
303
+ // into sessions by the skill system, not via the global tool list.
305
304
  // Exclude skill-origin tools — they are managed by the session-level
306
305
  // skill projection system (projectSkillTools) and must not leak into
307
306
  // the base tool list, which is shared across sessions via the global
@@ -341,9 +340,6 @@ export async function initializeTools(): Promise<void> {
341
340
  registerTool(tool);
342
341
  }
343
342
 
344
- // The escalation tool is registered in core so text_qa sessions can execute it.
345
- // The 12 action tools are provided by the bundled computer-use skill.
346
- registerTool(requestComputerControlTool);
347
343
  registerUiSurfaceTools();
348
344
  registerAppTools();
349
345
 
@@ -367,7 +363,6 @@ export async function initializeTools(): Promise<void> {
367
363
  ...lazyTools.map((t: LazyToolDescriptor) => t.name),
368
364
  ...hostTools.map((t: Tool) => t.name),
369
365
  ...allComputerUseTools.map((t: Tool) => t.name),
370
- requestComputerControlTool.name,
371
366
  ...allUiSurfaceTools.map((t: Tool) => t.name),
372
367
  ...coreAppProxyTools.map((t: Tool) => t.name),
373
368
  ]);