@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
@@ -44,10 +44,67 @@ mock.module("../tools/registry.js", () => ({
44
44
  registerTool: () => {},
45
45
  }));
46
46
 
47
+ // ---------------------------------------------------------------------------
48
+ // Mock oauth-store to avoid SQLite dependency in unit tests
49
+ // ---------------------------------------------------------------------------
50
+
51
+ let mockGetMostRecentAppByProvider: ReturnType<
52
+ typeof mock<(key: string) => unknown>
53
+ >;
54
+ let mockGetAppByProviderAndClientId: ReturnType<
55
+ typeof mock<(key: string, clientId: string) => unknown>
56
+ >;
57
+ let mockGetProvider: ReturnType<typeof mock<(key: string) => unknown>>;
58
+
59
+ mock.module("../oauth/oauth-store.js", () => {
60
+ mockGetMostRecentAppByProvider = mock(() => undefined);
61
+ mockGetAppByProviderAndClientId = mock(() => undefined);
62
+ mockGetProvider = mock(() => undefined);
63
+ return {
64
+ getMostRecentAppByProvider: mockGetMostRecentAppByProvider,
65
+ getAppByProviderAndClientId: mockGetAppByProviderAndClientId,
66
+ getProvider: mockGetProvider,
67
+ listConnections: mock(() => []),
68
+ seedProviders: mock(() => {}),
69
+ disconnectOAuthProvider: mock(async () => "not-found" as const),
70
+ };
71
+ });
72
+
73
+ // ---------------------------------------------------------------------------
74
+ // Mock public ingress URL — not available in unit tests. The connect
75
+ // orchestrator dynamically imports this for non-interactive flows.
76
+ // ---------------------------------------------------------------------------
77
+
78
+ mock.module("../inbound/public-ingress-urls.js", () => ({
79
+ getPublicBaseUrl: () => {
80
+ throw new Error("No public ingress URL configured");
81
+ },
82
+ }));
83
+
84
+ // ---------------------------------------------------------------------------
85
+ // Mock prepareOAuth2Flow — unit tests should not start real loopback HTTP
86
+ // servers. The connect orchestrator still runs its own validation logic
87
+ // (scope policy, non-interactive ingress checks, etc.) but the actual
88
+ // OAuth flow setup is stubbed.
89
+ // ---------------------------------------------------------------------------
90
+
91
+ mock.module("../security/oauth2.js", () => ({
92
+ prepareOAuth2Flow: mock(async () => ({
93
+ authUrl: "https://mock-auth-url.example.com/authorize",
94
+ state: "mock-state",
95
+ completion: new Promise(() => {}),
96
+ })),
97
+ startOAuth2Flow: mock(async () => ({
98
+ grantedScopes: [],
99
+ tokens: { access_token: "mock-token" },
100
+ })),
101
+ }));
102
+
47
103
  // ---------------------------------------------------------------------------
48
104
  // Imports under test
49
105
  // ---------------------------------------------------------------------------
50
106
 
107
+ import { credentialKey } from "../security/credential-key.js";
51
108
  import { getSecureKey, setSecureKey } from "../security/secure-keys.js";
52
109
  import { CredentialBroker } from "../tools/credentials/broker.js";
53
110
  import {
@@ -108,7 +165,7 @@ describe("CredentialBroker transient credentials", () => {
108
165
  const result = broker.consume(auth.token.tokenId);
109
166
  expect(result.success).toBe(true);
110
167
  expect(result.value).toBe("one-time-secret");
111
- expect(result.storageKey).toBe("credential:svc:key");
168
+ expect(result.storageKey).toBe(credentialKey("svc", "key"));
112
169
 
113
170
  // Second authorize + consume should NOT have the transient value
114
171
  const auth2 = broker.authorize({
@@ -148,7 +205,7 @@ describe("CredentialBroker transient credentials", () => {
148
205
  upsertCredentialMetadata("github", "token", {
149
206
  allowedTools: ["browser_fill_credential"],
150
207
  });
151
- setSecureKey("credential:github:token", "stored-value");
208
+ setSecureKey(credentialKey("github", "token"), "stored-value");
152
209
  broker.injectTransient("github", "token", "transient-value");
153
210
 
154
211
  // First fill uses transient
@@ -411,7 +468,7 @@ describe("credential_store tool — prompt action", () => {
411
468
  expect(result.content).not.toContain("prompt-secret-val");
412
469
 
413
470
  // Verify stored
414
- expect(getSecureKey("credential:test-prompt:api_key")).toBe(
471
+ expect(getSecureKey(credentialKey("test-prompt", "api_key"))).toBe(
415
472
  "prompt-secret-val",
416
473
  );
417
474
  });
@@ -472,18 +529,50 @@ describe("credential_store tool — prompt action", () => {
472
529
  // ---------------------------------------------------------------------------
473
530
 
474
531
  describe("credential_store tool — oauth2_connect error paths", () => {
532
+ /** Well-known provider rows returned by the mocked getProvider */
533
+ const wellKnownProviders: Record<string, object> = {
534
+ "integration:gmail": {
535
+ key: "integration:gmail",
536
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
537
+ tokenUrl: "https://oauth2.googleapis.com/token",
538
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
539
+ scopePolicy: JSON.stringify({}),
540
+ callbackTransport: "loopback",
541
+ loopbackPort: 8756,
542
+ },
543
+ "integration:slack": {
544
+ key: "integration:slack",
545
+ authUrl: "https://slack.com/oauth/v2/authorize",
546
+ tokenUrl: "https://slack.com/api/oauth.v2.access",
547
+ defaultScopes: JSON.stringify(["channels:read"]),
548
+ scopePolicy: JSON.stringify({}),
549
+ },
550
+ };
551
+
475
552
  beforeEach(() => {
476
553
  if (existsSync(TEST_DIR)) rmSync(TEST_DIR, { recursive: true });
477
554
  mkdirSync(TEST_DIR, { recursive: true });
478
555
  _setStorePath(STORE_PATH);
479
556
  _resetBackend();
480
557
  _setMetadataPath(join(TEST_DIR, "metadata.json"));
558
+ // Return well-known provider rows so vault.ts knows gmail/slack are
559
+ // registered, and custom providers return undefined.
560
+ mockGetProvider.mockImplementation(
561
+ (key: string) => wellKnownProviders[key] ?? undefined,
562
+ );
563
+ mockGetMostRecentAppByProvider.mockClear();
564
+ mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
565
+ mockGetAppByProviderAndClientId.mockClear();
566
+ mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
481
567
  });
482
568
 
483
569
  afterEach(() => {
484
570
  _setMetadataPath(null);
485
571
  _setStorePath(null);
486
572
  _resetBackend();
573
+ mockGetProvider.mockImplementation(() => undefined);
574
+ mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
575
+ mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
487
576
  });
488
577
 
489
578
  test("requires service parameter", async () => {
@@ -495,55 +584,38 @@ describe("credential_store tool — oauth2_connect error paths", () => {
495
584
  expect(result.content).toContain("service is required");
496
585
  });
497
586
 
498
- test("requires auth_url for unknown service", async () => {
499
- const result = await credentialStoreTool.execute(
500
- {
501
- action: "oauth2_connect",
502
- service: "custom-svc",
503
- token_url: "https://t",
504
- scopes: ["read"],
505
- },
506
- _ctx,
507
- );
508
- expect(result.isError).toBe(true);
509
- expect(result.content).toContain("auth_url is required");
510
- });
511
-
512
- test("requires token_url for unknown service", async () => {
513
- const result = await credentialStoreTool.execute(
514
- {
515
- action: "oauth2_connect",
516
- service: "custom-svc",
517
- auth_url: "https://a",
518
- scopes: ["read"],
519
- },
520
- _ctx,
521
- );
522
- expect(result.isError).toBe(true);
523
- expect(result.content).toContain("token_url is required");
524
- });
525
-
526
- test("requires scopes for unknown service", async () => {
587
+ test("rejects unknown service without registered provider", async () => {
527
588
  const result = await credentialStoreTool.execute(
528
589
  {
529
590
  action: "oauth2_connect",
530
591
  service: "custom-svc",
531
592
  auth_url: "https://a",
532
593
  token_url: "https://t",
594
+ scopes: ["read"],
533
595
  },
534
596
  _ctx,
535
597
  );
536
598
  expect(result.isError).toBe(true);
537
- expect(result.content).toContain("scopes is required");
599
+ expect(result.content).toContain("no OAuth provider registered");
538
600
  });
539
601
 
540
602
  test("requires client_id", async () => {
603
+ mockGetProvider.mockImplementation((key: string) => {
604
+ if (key === "custom-svc") {
605
+ return {
606
+ key: "custom-svc",
607
+ authUrl: "https://auth.example.com",
608
+ tokenUrl: "https://token.example.com",
609
+ defaultScopes: JSON.stringify(["read"]),
610
+ scopePolicy: JSON.stringify({}),
611
+ };
612
+ }
613
+ return wellKnownProviders[key] ?? undefined;
614
+ });
541
615
  const result = await credentialStoreTool.execute(
542
616
  {
543
617
  action: "oauth2_connect",
544
618
  service: "custom-svc",
545
- auth_url: "https://auth.example.com",
546
- token_url: "https://token.example.com",
547
619
  scopes: ["read"],
548
620
  },
549
621
  _ctx,
@@ -553,6 +625,21 @@ describe("credential_store tool — oauth2_connect error paths", () => {
553
625
  });
554
626
 
555
627
  test("requires interactive context", async () => {
628
+ // Register custom-svc as a provider so the orchestrator finds it
629
+ // and reaches the non-interactive check (gateway transport).
630
+ mockGetProvider.mockImplementation((key: string) => {
631
+ if (key === "custom-svc") {
632
+ return {
633
+ key: "custom-svc",
634
+ authUrl: "https://auth.example.com",
635
+ tokenUrl: "https://token.example.com",
636
+ defaultScopes: JSON.stringify(["read"]),
637
+ scopePolicy: JSON.stringify({}),
638
+ };
639
+ }
640
+ return wellKnownProviders[key] ?? undefined;
641
+ });
642
+
556
643
  const result = await credentialStoreTool.execute(
557
644
  {
558
645
  action: "oauth2_connect",
@@ -595,16 +682,25 @@ describe("credential_store tool — oauth2_connect error paths", () => {
595
682
  expect(result.content).toContain("client_id is required");
596
683
  });
597
684
 
598
- test("uses stored client_id from secure storage", async () => {
599
- // Store both client_id and client_secret for the service — the
600
- // requiresClientSecret guardrail will short-circuit if client_secret
601
- // is missing, so we need both to validate that stored client_id
602
- // is resolved correctly.
603
- setSecureKey(
604
- "credential:integration:gmail:client_id",
605
- "stored-client-id-123",
606
- );
607
- setSecureKey("credential:integration:gmail:client_secret", "test-secret");
685
+ test("uses stored client_id from oauth-store DB", async () => {
686
+ // Mock getMostRecentAppByProvider to return an app with a client_id
687
+ // and store client_secret in the secure store.
688
+ mockGetMostRecentAppByProvider.mockImplementation(() => ({
689
+ id: "test-app-id",
690
+ providerKey: "integration:gmail",
691
+ clientId: "stored-client-id-123",
692
+ createdAt: Date.now(),
693
+ }));
694
+ mockGetProvider.mockImplementation(() => ({
695
+ key: "integration:gmail",
696
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
697
+ tokenUrl: "https://oauth2.googleapis.com/token",
698
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
699
+ scopePolicy: JSON.stringify({}),
700
+ callbackTransport: "loopback",
701
+ loopbackPort: 8756,
702
+ }));
703
+ setSecureKey("oauth_app/test-app-id/client_secret", "test-secret");
608
704
 
609
705
  const result = await credentialStoreTool.execute(
610
706
  {
@@ -621,26 +717,163 @@ describe("credential_store tool — oauth2_connect error paths", () => {
621
717
  expect(result.content).toContain("To connect gmail, open this link");
622
718
  expect(result.content).not.toContain("client_id is required");
623
719
  expect(result.content).not.toContain("client_secret is required");
720
+
721
+ // Reset mocks
722
+ mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
723
+ mockGetProvider.mockImplementation(() => undefined);
624
724
  });
625
725
 
626
- test("rejects when client_secret is missing for service that requires it", async () => {
627
- // Store only client_id client_secret is intentionally absent to
628
- // validate the requiresClientSecret guardrail.
629
- setSecureKey(
630
- "credential:integration:gmail:client_id",
631
- "stored-client-id-456",
726
+ test("uses getAppByProviderAndClientId when client_id is provided without client_secret", async () => {
727
+ // When client_id is supplied but client_secret is not, the vault should
728
+ // look up the matching app via getAppByProviderAndClientId (not the
729
+ // most-recent-app heuristic) so the secret comes from the correct app.
730
+ mockGetAppByProviderAndClientId.mockImplementation(
731
+ (providerKey: string, cId: string) => {
732
+ if (
733
+ providerKey === "integration:gmail" &&
734
+ cId === "caller-supplied-client-id"
735
+ ) {
736
+ return {
737
+ id: "matched-app-id",
738
+ providerKey: "integration:gmail",
739
+ clientId: "caller-supplied-client-id",
740
+ createdAt: Date.now(),
741
+ };
742
+ }
743
+ return undefined;
744
+ },
745
+ );
746
+ mockGetProvider.mockImplementation(() => ({
747
+ key: "integration:gmail",
748
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
749
+ tokenUrl: "https://oauth2.googleapis.com/token",
750
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
751
+ scopePolicy: JSON.stringify({}),
752
+ callbackTransport: "loopback",
753
+ loopbackPort: 8756,
754
+ }));
755
+ setSecureKey("oauth_app/matched-app-id/client_secret", "matched-secret");
756
+
757
+ const result = await credentialStoreTool.execute(
758
+ {
759
+ action: "oauth2_connect",
760
+ service: "gmail",
761
+ client_id: "caller-supplied-client-id",
762
+ },
763
+ { ..._ctx, isInteractive: false },
632
764
  );
633
765
 
766
+ // Should succeed — client_secret resolved from the matched app
767
+ expect(result.isError).toBe(false);
768
+ expect(result.content).toContain("To connect gmail, open this link");
769
+ // getMostRecentAppByProvider should NOT have been called since client_id was known
770
+ expect(mockGetMostRecentAppByProvider).not.toHaveBeenCalled();
771
+
772
+ // Reset mocks
773
+ mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
774
+ mockGetProvider.mockImplementation(() => undefined);
775
+ });
776
+
777
+ test("falls back to getMostRecentAppByProvider when client_id is not provided", async () => {
778
+ // When neither client_id nor client_secret is provided, the vault should
779
+ // use getMostRecentAppByProvider (the fallback heuristic).
780
+ mockGetMostRecentAppByProvider.mockImplementation(() => ({
781
+ id: "recent-app-id",
782
+ providerKey: "integration:gmail",
783
+ clientId: "recent-client-id",
784
+ createdAt: Date.now(),
785
+ }));
786
+ mockGetProvider.mockImplementation(() => ({
787
+ key: "integration:gmail",
788
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
789
+ tokenUrl: "https://oauth2.googleapis.com/token",
790
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
791
+ scopePolicy: JSON.stringify({}),
792
+ callbackTransport: "loopback",
793
+ loopbackPort: 8756,
794
+ }));
795
+ setSecureKey("oauth_app/recent-app-id/client_secret", "recent-secret");
796
+
634
797
  const result = await credentialStoreTool.execute(
635
798
  {
636
799
  action: "oauth2_connect",
637
800
  service: "gmail",
638
801
  },
802
+ { ..._ctx, isInteractive: false },
803
+ );
804
+
805
+ expect(result.isError).toBe(false);
806
+ expect(result.content).toContain("To connect gmail, open this link");
807
+ // getAppByProviderAndClientId should NOT have been called since client_id was unknown
808
+ expect(mockGetAppByProviderAndClientId).not.toHaveBeenCalled();
809
+
810
+ // Reset mocks
811
+ mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
812
+ mockGetProvider.mockImplementation(() => undefined);
813
+ });
814
+
815
+ test("getAppByProviderAndClientId returning undefined leaves client_secret unresolved", async () => {
816
+ // When client_id is provided but getAppByProviderAndClientId returns no
817
+ // matching app, client_secret remains unresolved and the vault should
818
+ // report the missing secret error.
819
+ mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
820
+ mockGetProvider.mockImplementation(() => ({
821
+ key: "integration:gmail",
822
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
823
+ tokenUrl: "https://oauth2.googleapis.com/token",
824
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
825
+ }));
826
+
827
+ const result = await credentialStoreTool.execute(
828
+ {
829
+ action: "oauth2_connect",
830
+ service: "gmail",
831
+ client_id: "unknown-client-id",
832
+ },
639
833
  _ctx,
640
834
  );
641
835
 
642
836
  expect(result.isError).toBe(true);
643
837
  expect(result.content).toContain("client_secret is required for gmail");
838
+ // getMostRecentAppByProvider should NOT have been called
839
+ expect(mockGetMostRecentAppByProvider).not.toHaveBeenCalled();
840
+
841
+ // Reset mocks
842
+ mockGetAppByProviderAndClientId.mockImplementation(() => undefined);
843
+ mockGetProvider.mockImplementation(() => undefined);
844
+ });
845
+
846
+ test("rejects when client_secret is missing for service that requires it", async () => {
847
+ // Mock getMostRecentAppByProvider to return an app with client_id but
848
+ // no client_secret in secure storage — validates the requiresClientSecret
849
+ // guardrail.
850
+ mockGetMostRecentAppByProvider.mockImplementation(() => ({
851
+ id: "test-app-id-no-secret",
852
+ providerKey: "integration:gmail",
853
+ clientId: "stored-client-id-456",
854
+ createdAt: Date.now(),
855
+ }));
856
+ mockGetProvider.mockImplementation(() => ({
857
+ key: "integration:gmail",
858
+ authUrl: "https://accounts.google.com/o/oauth2/v2/auth",
859
+ tokenUrl: "https://oauth2.googleapis.com/token",
860
+ defaultScopes: JSON.stringify(["https://mail.google.com/"]),
861
+ }));
862
+
863
+ const result = await credentialStoreTool.execute(
864
+ {
865
+ action: "oauth2_connect",
866
+ service: "gmail",
867
+ },
868
+ _ctx,
869
+ );
870
+
871
+ expect(result.isError).toBe(true);
872
+ expect(result.content).toContain("client_secret is required for gmail");
873
+
874
+ // Reset mocks
875
+ mockGetMostRecentAppByProvider.mockImplementation(() => undefined);
876
+ mockGetProvider.mockImplementation(() => undefined);
644
877
  });
645
878
  });
646
879
 
@@ -786,7 +1019,7 @@ describe("credential_store tool — store validation edge cases", () => {
786
1019
  );
787
1020
 
788
1021
  // Verify stored
789
- expect(getSecureKey("credential:del-test:key")).toBe("secret");
1022
+ expect(getSecureKey(credentialKey("del-test", "key"))).toBe("secret");
790
1023
  const { getCredentialMetadata } =
791
1024
  await import("../tools/credentials/metadata-store.js");
792
1025
  expect(getCredentialMetadata("del-test", "key")).toBeDefined();
@@ -803,7 +1036,7 @@ describe("credential_store tool — store validation edge cases", () => {
803
1036
  expect(result.isError).toBe(false);
804
1037
 
805
1038
  // Both should be gone
806
- expect(getSecureKey("credential:del-test:key")).toBeUndefined();
1039
+ expect(getSecureKey(credentialKey("del-test", "key"))).toBeUndefined();
807
1040
  expect(getCredentialMetadata("del-test", "key")).toBeUndefined();
808
1041
  });
809
1042
  });
@@ -892,7 +1125,7 @@ describe("CredentialBroker — serverUseById edge cases", () => {
892
1125
  },
893
1126
  ],
894
1127
  });
895
- setSecureKey("credential:multi:api_key", "multi-secret");
1128
+ setSecureKey(credentialKey("multi", "api_key"), "multi-secret");
896
1129
 
897
1130
  const result = broker.serverUseById({
898
1131
  credentialId: meta.credentialId,