@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
@@ -60,7 +60,6 @@ mock.module("../util/logger.js", () => ({
60
60
  ...realLogger,
61
61
  getLogger: () => noopLogger,
62
62
  getCliLogger: () => noopLogger,
63
- isDebug: () => false,
64
63
  truncateForLog: (v: string) => v,
65
64
  initLogger: () => {},
66
65
  pruneOldLogFiles: () => 0,
@@ -675,15 +674,6 @@ describe("ingress-dependent setup skills declare public-ingress", () => {
675
674
  expect(includes).toContain("public-ingress");
676
675
  });
677
676
 
678
- test("google-oauth-setup includes public-ingress", () => {
679
- const includes = readSkillIncludes(
680
- FIRST_PARTY_SKILLS_DIR,
681
- "google-oauth-setup",
682
- );
683
- expect(includes).toBeDefined();
684
- expect(includes).toContain("public-ingress");
685
- });
686
-
687
677
  test("slack-oauth-setup includes browser", () => {
688
678
  const includes = readSkillIncludes(
689
679
  FIRST_PARTY_SKILLS_DIR,
@@ -728,15 +718,16 @@ describe("bundled computer-use skill", () => {
728
718
  expect(cuSkill!.disableModelInvocation).toBe(true);
729
719
  });
730
720
 
731
- test("computer-use skill has a valid tool manifest with 12 tools", () => {
721
+ test("computer-use skill has a valid tool manifest with 11 tools", () => {
732
722
  const catalog = loadSkillCatalog();
733
723
  const cuSkill = catalog.find((s) => s.id === "computer-use");
734
724
  expect(cuSkill).toBeDefined();
735
725
  expect(cuSkill!.toolManifest).toBeDefined();
736
726
  expect(cuSkill!.toolManifest!.present).toBe(true);
737
727
  expect(cuSkill!.toolManifest!.valid).toBe(true);
738
- expect(cuSkill!.toolManifest!.toolCount).toBe(10);
728
+ expect(cuSkill!.toolManifest!.toolCount).toBe(11);
739
729
  expect(cuSkill!.toolManifest!.toolNames).toEqual([
730
+ "computer_use_observe",
740
731
  "computer_use_click",
741
732
  "computer_use_type_text",
742
733
  "computer_use_key",
@@ -75,13 +75,11 @@ mock.module("../util/logger.js", () => ({
75
75
  debug: () => {},
76
76
  trace: () => {},
77
77
  fatal: () => {},
78
- isDebug: () => false,
79
78
  child: () => ({
80
79
  info: () => {},
81
80
  warn: () => {},
82
81
  error: () => {},
83
82
  debug: () => {},
84
- isDebug: () => false,
85
83
  }),
86
84
  }),
87
85
  }));
@@ -116,6 +114,46 @@ mock.module("../security/secure-keys.js", () => {
116
114
  };
117
115
  });
118
116
 
117
+ // Mock oauth-store (getConnectionByProvider)
118
+ let oauthConnectionStore: Record<
119
+ string,
120
+ { id: string; status: string; accountInfo?: string | null }
121
+ > = {};
122
+
123
+ mock.module("../oauth/oauth-store.js", () => ({
124
+ getConnectionByProvider: (providerKey: string) =>
125
+ oauthConnectionStore[providerKey] ?? undefined,
126
+ createConnection: () => ({ id: "test-conn-id" }),
127
+ updateConnection: () => true,
128
+ deleteConnection: (id: string) => {
129
+ for (const [key, conn] of Object.entries(oauthConnectionStore)) {
130
+ if (conn.id === id) {
131
+ delete oauthConnectionStore[key];
132
+ return true;
133
+ }
134
+ }
135
+ return false;
136
+ },
137
+ upsertApp: async () => ({ id: "test-app-id" }),
138
+ }));
139
+
140
+ // Mock manual-token-connection
141
+ mock.module("../oauth/manual-token-connection.js", () => ({
142
+ ensureManualTokenConnection: async (
143
+ providerKey: string,
144
+ accountInfo?: string,
145
+ ) => {
146
+ oauthConnectionStore[providerKey] = {
147
+ id: `conn-${providerKey}`,
148
+ status: "active",
149
+ accountInfo: accountInfo ?? null,
150
+ };
151
+ },
152
+ removeManualTokenConnection: (providerKey: string) => {
153
+ delete oauthConnectionStore[providerKey];
154
+ },
155
+ }));
156
+
119
157
  // Mock credential metadata store
120
158
  let credentialMetadataStore: Array<{
121
159
  service: string;
@@ -172,6 +210,7 @@ import {
172
210
  getSlackChannelConfig,
173
211
  setSlackChannelConfig,
174
212
  } from "../daemon/handlers/config-slack-channel.js";
213
+ import { credentialKey } from "../security/credential-key.js";
175
214
 
176
215
  afterAll(() => {
177
216
  globalThis.fetch = originalFetch;
@@ -186,6 +225,7 @@ describe("Slack channel config handler", () => {
186
225
  beforeEach(() => {
187
226
  secureKeyStore = {};
188
227
  credentialMetadataStore = [];
228
+ oauthConnectionStore = {};
189
229
  configStore = {};
190
230
  globalThis.fetch = originalFetch;
191
231
  });
@@ -198,9 +238,13 @@ describe("Slack channel config handler", () => {
198
238
  expect(result.connected).toBe(false);
199
239
  });
200
240
 
201
- test("GET returns connected: true when both tokens are set", () => {
202
- secureKeyStore["credential:slack_channel:bot_token"] = "xoxb-test";
203
- secureKeyStore["credential:slack_channel:app_token"] = "xapp-test";
241
+ test("GET returns connected: true when oauth_connection is active and both keys exist", () => {
242
+ oauthConnectionStore["slack_channel"] = {
243
+ id: "conn-slack",
244
+ status: "active",
245
+ };
246
+ secureKeyStore[credentialKey("slack_channel", "bot_token")] = "xoxb-test";
247
+ secureKeyStore[credentialKey("slack_channel", "app_token")] = "xapp-test";
204
248
 
205
249
  const result = getSlackChannelConfig();
206
250
  expect(result.success).toBe(true);
@@ -209,8 +253,29 @@ describe("Slack channel config handler", () => {
209
253
  expect(result.connected).toBe(true);
210
254
  });
211
255
 
256
+ test("GET reports per-field token presence independently of connection row", () => {
257
+ // Only bot_token in keychain, no app_token, but connection row exists
258
+ oauthConnectionStore["slack_channel"] = {
259
+ id: "conn-slack",
260
+ status: "active",
261
+ };
262
+ secureKeyStore[credentialKey("slack_channel", "bot_token")] = "xoxb-test";
263
+
264
+ const result = getSlackChannelConfig();
265
+ expect(result.success).toBe(true);
266
+ expect(result.hasBotToken).toBe(true);
267
+ expect(result.hasAppToken).toBe(false);
268
+ // connected requires both keys AND connection row
269
+ expect(result.connected).toBe(false);
270
+ });
271
+
212
272
  test("GET returns metadata from config when available", () => {
213
- secureKeyStore["credential:slack_channel:bot_token"] = "xoxb-test";
273
+ oauthConnectionStore["slack_channel"] = {
274
+ id: "conn-slack",
275
+ status: "active",
276
+ };
277
+ secureKeyStore[credentialKey("slack_channel", "bot_token")] = "xoxb-test";
278
+ secureKeyStore[credentialKey("slack_channel", "app_token")] = "xapp-test";
214
279
  configStore = {
215
280
  slack: {
216
281
  teamId: "T123",
@@ -240,7 +305,7 @@ describe("Slack channel config handler", () => {
240
305
  );
241
306
  expect(result.success).toBe(true);
242
307
  expect(result.hasAppToken).toBe(true);
243
- expect(secureKeyStore["credential:slack_channel:app_token"]).toBe(
308
+ expect(secureKeyStore[credentialKey("slack_channel", "app_token")]).toBe(
244
309
  "xapp-valid-token-123",
245
310
  );
246
311
  });
@@ -296,8 +361,8 @@ describe("Slack channel config handler", () => {
296
361
  });
297
362
 
298
363
  test("DELETE clears credentials and config", async () => {
299
- secureKeyStore["credential:slack_channel:bot_token"] = "xoxb-test";
300
- secureKeyStore["credential:slack_channel:app_token"] = "xapp-test";
364
+ secureKeyStore[credentialKey("slack_channel", "bot_token")] = "xoxb-test";
365
+ secureKeyStore[credentialKey("slack_channel", "app_token")] = "xapp-test";
301
366
  credentialMetadataStore.push({
302
367
  service: "slack_channel",
303
368
  field: "bot_token",
@@ -322,10 +387,10 @@ describe("Slack channel config handler", () => {
322
387
  expect(result.connected).toBe(false);
323
388
 
324
389
  expect(
325
- secureKeyStore["credential:slack_channel:bot_token"],
390
+ secureKeyStore[credentialKey("slack_channel", "bot_token")],
326
391
  ).toBeUndefined();
327
392
  expect(
328
- secureKeyStore["credential:slack_channel:app_token"],
393
+ secureKeyStore[credentialKey("slack_channel", "app_token")],
329
394
  ).toBeUndefined();
330
395
  expect(credentialMetadataStore).toHaveLength(0);
331
396
 
@@ -10,6 +10,12 @@ mock.module("../security/secure-keys.js", () => ({
10
10
  setSecureKeyAsync: async () => {},
11
11
  }));
12
12
 
13
+ let connectionByProvider: Record<string, unknown> = {};
14
+ mock.module("../oauth/oauth-store.js", () => ({
15
+ getConnectionByProvider: (key: string) =>
16
+ connectionByProvider[key] ?? undefined,
17
+ }));
18
+
13
19
  let listConversationsResult: unknown = { ok: true, channels: [] };
14
20
  let postMessageResult: unknown = {
15
21
  ok: true,
@@ -84,6 +90,7 @@ function makeRequest(body: unknown): Request {
84
90
 
85
91
  beforeEach(() => {
86
92
  secureKeyValues.clear();
93
+ connectionByProvider = {};
87
94
  listConversationsResult = { ok: true, channels: [] };
88
95
  userInfoResults = new Map();
89
96
  appStoreResult = null;
@@ -104,8 +111,9 @@ describe("handleListSlackChannels", () => {
104
111
  });
105
112
 
106
113
  test("returns channels sorted by type then name", async () => {
114
+ connectionByProvider["integration:slack"] = { id: "conn-slack-1" };
107
115
  secureKeyValues.set(
108
- "credential:integration:slack:access_token",
116
+ "oauth_connection/conn-slack-1/access_token",
109
117
  "xoxb-test",
110
118
  );
111
119
 
@@ -174,15 +182,6 @@ describe("handleListSlackChannels", () => {
174
182
  isPrivate: true,
175
183
  });
176
184
  });
177
-
178
- test("falls back to legacy bot token", async () => {
179
- secureKeyValues.set("credential:slack_channel:bot_token", "xoxb-legacy");
180
-
181
- listConversationsResult = { ok: true, channels: [] };
182
-
183
- const res = await handleListSlackChannels();
184
- expect(res.status).toBe(200);
185
- });
186
185
  });
187
186
 
188
187
  describe("handleShareToSlackChannel", () => {
@@ -193,8 +192,9 @@ describe("handleShareToSlackChannel", () => {
193
192
  });
194
193
 
195
194
  test("returns 400 for malformed JSON", async () => {
195
+ connectionByProvider["integration:slack"] = { id: "conn-slack-1" };
196
196
  secureKeyValues.set(
197
- "credential:integration:slack:access_token",
197
+ "oauth_connection/conn-slack-1/access_token",
198
198
  "xoxb-test",
199
199
  );
200
200
  const req = new Request("http://localhost/v1/slack/share", {
@@ -207,8 +207,9 @@ describe("handleShareToSlackChannel", () => {
207
207
  });
208
208
 
209
209
  test("returns 400 when missing required fields", async () => {
210
+ connectionByProvider["integration:slack"] = { id: "conn-slack-1" };
210
211
  secureKeyValues.set(
211
- "credential:integration:slack:access_token",
212
+ "oauth_connection/conn-slack-1/access_token",
212
213
  "xoxb-test",
213
214
  );
214
215
  const req = makeRequest({ appId: "app1" });
@@ -219,8 +220,9 @@ describe("handleShareToSlackChannel", () => {
219
220
  });
220
221
 
221
222
  test("returns 404 when app not found", async () => {
223
+ connectionByProvider["integration:slack"] = { id: "conn-slack-1" };
222
224
  secureKeyValues.set(
223
- "credential:integration:slack:access_token",
225
+ "oauth_connection/conn-slack-1/access_token",
224
226
  "xoxb-test",
225
227
  );
226
228
  appStoreResult = null;
@@ -230,8 +232,9 @@ describe("handleShareToSlackChannel", () => {
230
232
  });
231
233
 
232
234
  test("posts message and returns success", async () => {
235
+ connectionByProvider["integration:slack"] = { id: "conn-slack-1" };
233
236
  secureKeyValues.set(
234
- "credential:integration:slack:access_token",
237
+ "oauth_connection/conn-slack-1/access_token",
235
238
  "xoxb-test",
236
239
  );
237
240
  appStoreResult = {
@@ -53,7 +53,6 @@ mock.module("../util/logger.js", () => ({
53
53
  ...realLogger,
54
54
  getLogger: () => noopLogger,
55
55
  getCliLogger: () => noopLogger,
56
- isDebug: () => false,
57
56
  truncateForLog: (v: string) => v,
58
57
  initLogger: () => {},
59
58
  pruneOldLogFiles: () => 0,
@@ -38,6 +38,9 @@ mock.module("../config/loader.js", () => ({
38
38
 
39
39
  mock.module("../security/secure-keys.js", () => ({
40
40
  getSecureKey: (_keyId: string) => mockSecureKey,
41
+ setSecureKey: (_account: string, _value: string) => true,
42
+ deleteSecureKey: (_account: string) => "deleted" as const,
43
+ listSecureKeys: () => [] as string[],
41
44
  }));
42
45
 
43
46
  // Suppress logger output during tests
@@ -7,44 +7,42 @@
7
7
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
8
8
 
9
9
  import type { ChannelId } from "../channels/types.js";
10
- import { telegramInviteAdapter } from "../runtime/channel-invite-transports/telegram.js";
11
10
 
12
11
  // Mock credential metadata so tests don't depend on local persisted state.
13
12
  mock.module("../tools/credentials/metadata-store.js", () => ({
14
13
  getCredentialMetadata: () => undefined,
15
14
  }));
16
15
 
16
+ // Mock getTelegramBotUsername — the env var fallback was removed so we
17
+ // control the return value directly via a mutable variable.
18
+ let mockBotUsername: string | undefined;
19
+ mock.module("../telegram/bot-username.js", () => ({
20
+ getTelegramBotUsername: () => mockBotUsername,
21
+ }));
22
+
23
+ import { telegramInviteAdapter } from "../runtime/channel-invite-transports/telegram.js";
24
+
17
25
  // ---------------------------------------------------------------------------
18
26
  // Helpers
19
27
  // ---------------------------------------------------------------------------
20
28
 
21
29
  const CHANNEL: ChannelId = "telegram" as ChannelId;
22
30
 
23
- function setEnv(key: string, value: string | undefined) {
24
- if (value === undefined) {
25
- delete process.env[key];
26
- } else {
27
- process.env[key] = value;
28
- }
29
- }
30
-
31
31
  // ---------------------------------------------------------------------------
32
32
  // buildShareLink
33
33
  // ---------------------------------------------------------------------------
34
34
 
35
35
  describe("telegramInviteAdapter.buildShareLink", () => {
36
- let originalBotUsername: string | undefined;
37
-
38
36
  beforeEach(() => {
39
- originalBotUsername = process.env.TELEGRAM_BOT_USERNAME;
37
+ mockBotUsername = undefined;
40
38
  });
41
39
 
42
40
  afterEach(() => {
43
- setEnv("TELEGRAM_BOT_USERNAME", originalBotUsername);
41
+ mockBotUsername = undefined;
44
42
  });
45
43
 
46
44
  test("builds a deep link with iv_ prefix", () => {
47
- setEnv("TELEGRAM_BOT_USERNAME", "TestBot");
45
+ mockBotUsername = "TestBot";
48
46
 
49
47
  const link = telegramInviteAdapter.buildShareLink!({
50
48
  rawToken: "abc123",
@@ -56,7 +54,7 @@ describe("telegramInviteAdapter.buildShareLink", () => {
56
54
  });
57
55
 
58
56
  test("throws when bot username is not configured", () => {
59
- setEnv("TELEGRAM_BOT_USERNAME", undefined);
57
+ mockBotUsername = undefined;
60
58
 
61
59
  expect(() =>
62
60
  telegramInviteAdapter.buildShareLink!({
@@ -138,25 +136,23 @@ describe("telegramInviteAdapter.extractInboundToken", () => {
138
136
  // ---------------------------------------------------------------------------
139
137
 
140
138
  describe("telegramInviteAdapter.resolveChannelHandle", () => {
141
- let originalBotUsername: string | undefined;
142
-
143
139
  beforeEach(() => {
144
- originalBotUsername = process.env.TELEGRAM_BOT_USERNAME;
140
+ mockBotUsername = undefined;
145
141
  });
146
142
 
147
143
  afterEach(() => {
148
- setEnv("TELEGRAM_BOT_USERNAME", originalBotUsername);
144
+ mockBotUsername = undefined;
149
145
  });
150
146
 
151
- test("returns @-prefixed bot username from env", () => {
152
- setEnv("TELEGRAM_BOT_USERNAME", "MyBot");
147
+ test("returns @-prefixed bot username from config", () => {
148
+ mockBotUsername = "MyBot";
153
149
 
154
150
  const handle = telegramInviteAdapter.resolveChannelHandle!();
155
151
  expect(handle).toBe("@MyBot");
156
152
  });
157
153
 
158
154
  test("returns undefined when bot username is not configured", () => {
159
- setEnv("TELEGRAM_BOT_USERNAME", undefined);
155
+ mockBotUsername = undefined;
160
156
 
161
157
  const handle = telegramInviteAdapter.resolveChannelHandle!();
162
158
  expect(handle).toBeUndefined();
@@ -457,10 +457,10 @@ describe("buildSanitizedEnv", () => {
457
457
  });
458
458
 
459
459
  test("injects INTERNAL_GATEWAY_BASE_URL from gateway config", () => {
460
- process.env.GATEWAY_INTERNAL_BASE_URL = "http://gateway.internal:9000/";
460
+ process.env.GATEWAY_PORT = "9000";
461
461
  const env = buildSanitizedEnv();
462
- expect(env.INTERNAL_GATEWAY_BASE_URL).toBe("http://gateway.internal:9000");
463
- delete process.env.GATEWAY_INTERNAL_BASE_URL;
462
+ expect(env.INTERNAL_GATEWAY_BASE_URL).toBe("http://127.0.0.1:9000");
463
+ delete process.env.GATEWAY_PORT;
464
464
  });
465
465
 
466
466
  test("result is a plain object with no prototype-inherited secrets", () => {
@@ -485,6 +485,7 @@ describe("buildSanitizedEnv", () => {
485
485
  "SSH_AGENT_PID",
486
486
  "GPG_TTY",
487
487
  "GNUPGHOME",
488
+ "VELLUM_DEV",
488
489
  "INTERNAL_GATEWAY_BASE_URL",
489
490
  "VELLUM_DATA_DIR",
490
491
  ];
@@ -2,8 +2,9 @@
2
2
  * Reusable constants and helpers for the computer-use skill migration test suite.
3
3
  */
4
4
 
5
- /** The 10 computer_use_* action tool names provided by the bundled computer-use skill. */
5
+ /** The 11 computer_use_* action tool names provided by the bundled computer-use skill. */
6
6
  export const COMPUTER_USE_TOOL_NAMES = [
7
+ "computer_use_observe",
7
8
  "computer_use_click",
8
9
  "computer_use_type_text",
9
10
  "computer_use_key",
@@ -20,7 +21,7 @@ export const COMPUTER_USE_TOOL_NAMES = [
20
21
  export const COMPUTER_USE_SKILL_ID = "computer-use";
21
22
 
22
23
  /** Number of computer_use_* tools. */
23
- export const COMPUTER_USE_TOOL_COUNT = COMPUTER_USE_TOOL_NAMES.length; // 10
24
+ export const COMPUTER_USE_TOOL_COUNT = COMPUTER_USE_TOOL_NAMES.length; // 11
24
25
 
25
26
  import { expect } from "bun:test";
26
27
 
@@ -21,7 +21,6 @@ mock.module("../util/logger.js", () => ({
21
21
  new Proxy({} as Record<string, unknown>, {
22
22
  get: () => () => {},
23
23
  }),
24
- isDebug: () => false,
25
24
  truncateForLog: (value: string) => value,
26
25
  }));
27
26
 
@@ -44,7 +44,6 @@ mock.module("../util/logger.js", () => ({
44
44
  new Proxy({} as Record<string, unknown>, {
45
45
  get: () => () => {},
46
46
  }),
47
- isDebug: () => false,
48
47
  }));
49
48
 
50
49
  // Allow toggling between no-rule and matched-rule paths
@@ -59,7 +59,6 @@ mock.module("../util/logger.js", () => ({
59
59
  new Proxy({} as Record<string, unknown>, {
60
60
  get: () => () => {},
61
61
  }),
62
- isDebug: () => false,
63
62
  truncateForLog: (value: string) => value,
64
63
  }));
65
64
 
@@ -68,7 +68,6 @@ mock.module("../util/logger.js", () => ({
68
68
  new Proxy({} as Record<string, unknown>, {
69
69
  get: () => () => {},
70
70
  }),
71
- isDebug: () => false,
72
71
  truncateForLog: (value: string) => value,
73
72
  }));
74
73
 
@@ -103,7 +103,6 @@ mock.module("../util/logger.js", () => ({
103
103
  new Proxy({} as Record<string, unknown>, {
104
104
  get: () => () => {},
105
105
  }),
106
- isDebug: () => false,
107
106
  truncateForLog: (value: string) => value,
108
107
  }));
109
108
 
@@ -31,7 +31,6 @@ mock.module("../util/logger.js", () => ({
31
31
  new Proxy({} as Record<string, unknown>, {
32
32
  get: () => () => {},
33
33
  }),
34
- isDebug: () => false,
35
34
  truncateForLog: (value: string) => value,
36
35
  }));
37
36
 
@@ -0,0 +1,29 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { patternMatchesCandidate } from "../permissions/trust-store.js";
4
+
5
+ describe("patternMatchesCandidate", () => {
6
+ test("exact match", () => {
7
+ expect(patternMatchesCandidate("bash:git commit", "bash:git commit")).toBe(
8
+ true,
9
+ );
10
+ });
11
+
12
+ test("glob match", () => {
13
+ expect(patternMatchesCandidate("bash:git *", "bash:git commit")).toBe(true);
14
+ });
15
+
16
+ test("no match", () => {
17
+ expect(patternMatchesCandidate("bash:git *", "file_write:/foo")).toBe(
18
+ false,
19
+ );
20
+ });
21
+
22
+ test("globstar matches anything", () => {
23
+ expect(patternMatchesCandidate("**", "bash:anything")).toBe(true);
24
+ });
25
+
26
+ test("invalid pattern returns false", () => {
27
+ expect(patternMatchesCandidate("[", "bash:anything")).toBe(false);
28
+ });
29
+ });
@@ -778,7 +778,6 @@ describe("Trust Store", () => {
778
778
  "computer_use_drag",
779
779
  "computer_use_key",
780
780
  "computer_use_open_app",
781
- "computer_use_request_control",
782
781
  "computer_use_run_applescript",
783
782
  "computer_use_scroll",
784
783
  "computer_use_type_text",
@@ -901,22 +900,6 @@ describe("Trust Store", () => {
901
900
  );
902
901
  });
903
902
 
904
- test("findHighestPriorityRule matches default ask for computer_use_request_control", () => {
905
- const match = findHighestPriorityRule(
906
- "computer_use_request_control",
907
- ["computer_use_request_control:"],
908
- "/tmp",
909
- );
910
- expect(match).not.toBeNull();
911
- expect(match!.id).toBe("default:ask-computer_use_request_control-global");
912
- expect(match!.decision).toBe("ask");
913
- expect(match!.priority).toBe(
914
- DEFAULT_PRIORITY_BY_ID.get(
915
- "default:ask-computer_use_request_control-global",
916
- )!,
917
- );
918
- });
919
-
920
903
  test("bootstrap delete rule matches only when workingDir is the workspace dir", () => {
921
904
  const workspaceDir = join(testDir, "workspace");
922
905
  // Should match when workingDir is the workspace directory — the bootstrap
@@ -1755,11 +1738,7 @@ describe("computer-use tool trust rule matching", () => {
1755
1738
  test("actionable CU tools have default ask trust rules", () => {
1756
1739
  // Actionable CU tools (those that perform screen interactions) should
1757
1740
  // have default "ask" rules so strict mode prompts before use.
1758
- const actionableCuTools = [
1759
- "computer_use_click",
1760
- "computer_use_type_text",
1761
- "computer_use_request_control",
1762
- ];
1741
+ const actionableCuTools = ["computer_use_click", "computer_use_type_text"];
1763
1742
 
1764
1743
  for (const name of actionableCuTools) {
1765
1744
  const rule = findHighestPriorityRule(name, [name], "/tmp/test");
@@ -42,7 +42,6 @@ mock.module("../util/logger.js", () => ({
42
42
  new Proxy({} as Record<string, unknown>, {
43
43
  get: () => () => {},
44
44
  }),
45
- isDebug: () => false,
46
45
  truncateForLog: (value: string) => value,
47
46
  }));
48
47
 
@@ -45,7 +45,6 @@ mock.module("../util/logger.js", () => ({
45
45
  new Proxy({} as Record<string, unknown>, {
46
46
  get: () => () => {},
47
47
  }),
48
- isDebug: () => false,
49
48
  truncateForLog: (value: string) => value,
50
49
  }));
51
50
 
@@ -26,11 +26,12 @@ mock.module("../inbound/public-ingress-urls.js", () => ({
26
26
  }));
27
27
 
28
28
  import { getTwilioConfig } from "../calls/twilio-config.js";
29
+ import { credentialKey } from "../security/credential-key.js";
29
30
 
30
31
  describe("twilio-config", () => {
31
32
  beforeEach(() => {
32
33
  mockSecureKeys = {
33
- "credential:twilio:auth_token": "test_auth_token",
34
+ [credentialKey("twilio", "auth_token")]: "test_auth_token",
34
35
  };
35
36
  mockLoadConfigResult = {
36
37
  twilio: {
@@ -8,6 +8,8 @@ import { tmpdir } from "node:os";
8
8
  import { join } from "node:path";
9
9
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
10
10
 
11
+ import { credentialKey } from "../security/credential-key.js";
12
+
11
13
  const testDir = mkdtempSync(join(tmpdir(), "twilio-provider-test-"));
12
14
 
13
15
  mock.module("../util/platform.js", () => ({
@@ -40,8 +42,8 @@ mock.module("../config/loader.js", () => ({
40
42
 
41
43
  mock.module("../security/secure-keys.js", () => ({
42
44
  getSecureKey: (key: string) => {
43
- if (key === "credential:twilio:auth_token") return mockAuthToken;
44
- if (key === "credential:twilio:account_sid") return mockAccountSid;
45
+ if (key === credentialKey("twilio", "auth_token")) return mockAuthToken;
46
+ if (key === credentialKey("twilio", "account_sid")) return mockAccountSid;
45
47
  return undefined;
46
48
  },
47
49
  }));