@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
@@ -171,6 +171,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
171
171
  hasPendingConfirmation: () => false,
172
172
  setHostBashProxy: () => {},
173
173
  setHostFileProxy: () => {},
174
+ setHostCuProxy: () => {},
174
175
  } as unknown as import("../daemon/session.js").Session;
175
176
 
176
177
  const req = new Request("http://localhost/v1/messages", {
@@ -246,6 +247,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
246
247
  hasPendingConfirmation: () => false,
247
248
  setHostBashProxy: () => {},
248
249
  setHostFileProxy: () => {},
250
+ setHostCuProxy: () => {},
249
251
  } as unknown as import("../daemon/session.js").Session;
250
252
 
251
253
  const req = new Request("http://localhost/v1/messages", {
@@ -317,6 +319,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
317
319
  requestId === "tool-approval-live",
318
320
  setHostBashProxy: () => {},
319
321
  setHostFileProxy: () => {},
322
+ setHostCuProxy: () => {},
320
323
  } as unknown as import("../daemon/session.js").Session;
321
324
 
322
325
  const req = new Request("http://localhost/v1/messages", {
@@ -392,6 +395,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
392
395
  hasPendingConfirmation: (id: string) => id === "tool-req-code-1",
393
396
  setHostBashProxy: () => {},
394
397
  setHostFileProxy: () => {},
398
+ setHostCuProxy: () => {},
395
399
  } as unknown as import("../daemon/session.js").Session;
396
400
 
397
401
  const req = new Request("http://localhost/v1/messages", {
@@ -463,6 +467,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
463
467
  hasPendingConfirmation: (id: string) => id === "pending-reject-1",
464
468
  setHostBashProxy: () => {},
465
469
  setHostFileProxy: () => {},
470
+ setHostCuProxy: () => {},
466
471
  } as unknown as import("../daemon/session.js").Session;
467
472
 
468
473
  const req = new Request("http://localhost/v1/messages", {
@@ -528,6 +533,7 @@ describe("handleSendMessage canonical guardian reply interception", () => {
528
533
  hasPendingConfirmation: (id: string) => id === "pending-1",
529
534
  setHostBashProxy: () => {},
530
535
  setHostFileProxy: () => {},
536
+ setHostCuProxy: () => {},
531
537
  } as unknown as import("../daemon/session.js").Session;
532
538
 
533
539
  const req = new Request("http://localhost/v1/messages", {
@@ -559,4 +565,142 @@ describe("handleSendMessage canonical guardian reply interception", () => {
559
565
  expect(persistUserMessage).toHaveBeenCalledTimes(1);
560
566
  expect(runAgentLoop).toHaveBeenCalledTimes(1);
561
567
  });
568
+
569
+ test("desktop sessions do not pass approvalConversationGenerator to routeGuardianReply", async () => {
570
+ listPendingByDestinationMock.mockReturnValue([
571
+ { id: "pending-1", kind: "access_request" },
572
+ ]);
573
+ listCanonicalMock.mockReturnValue([]);
574
+ routeGuardianReplyMock.mockResolvedValue({
575
+ consumed: false,
576
+ decisionApplied: false,
577
+ type: "not_consumed",
578
+ });
579
+
580
+ const mockGenerator = mock(async () => ({}));
581
+ const persistUserMessage = mock(async () => "persisted-user-id");
582
+ const runAgentLoop = mock(async () => undefined);
583
+ const session = {
584
+ setTrustContext: () => {},
585
+ updateClient: () => {},
586
+ emitConfirmationStateChanged: () => {},
587
+ emitActivityState: () => {},
588
+ setTurnChannelContext: () => {},
589
+ setTurnInterfaceContext: () => {},
590
+ ensureActorScopedHistory: async () => {},
591
+ usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
592
+ isProcessing: () => false,
593
+ hasAnyPendingConfirmation: () => false,
594
+ denyAllPendingConfirmations: () => {},
595
+ enqueueMessage: () => ({ queued: true, requestId: "queued-id" }),
596
+ persistUserMessage,
597
+ runAgentLoop,
598
+ getMessages: () => [] as unknown[],
599
+ assistantId: "self",
600
+ trustContext: undefined,
601
+ hasPendingConfirmation: () => false,
602
+ setHostBashProxy: () => {},
603
+ setHostFileProxy: () => {},
604
+ setHostCuProxy: () => {},
605
+ } as unknown as import("../daemon/session.js").Session;
606
+
607
+ const req = new Request("http://localhost/v1/messages", {
608
+ method: "POST",
609
+ headers: { "Content-Type": "application/json" },
610
+ body: JSON.stringify({
611
+ conversationKey: "guardian-thread-key",
612
+ content: "no sorry, beats 0 and 3 should be new threads",
613
+ sourceChannel: "vellum",
614
+ interface: "macos",
615
+ }),
616
+ });
617
+
618
+ await handleSendMessage(
619
+ req,
620
+ {
621
+ sendMessageDeps: {
622
+ getOrCreateSession: async () => session,
623
+ assistantEventHub: { publish: async () => {} } as any,
624
+ resolveAttachments: () => [],
625
+ },
626
+ approvalConversationGenerator: mockGenerator as any,
627
+ },
628
+ testAuthContext,
629
+ );
630
+
631
+ expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
632
+ const routerCall = (routeGuardianReplyMock as any).mock
633
+ .calls[0][0] as Record<string, unknown>;
634
+ // Desktop (vellum) should suppress the NL engine
635
+ expect(routerCall.approvalConversationGenerator).toBeUndefined();
636
+ });
637
+
638
+ test("channel sessions pass approvalConversationGenerator to routeGuardianReply", async () => {
639
+ listPendingByDestinationMock.mockReturnValue([
640
+ { id: "pending-1", kind: "access_request" },
641
+ ]);
642
+ listCanonicalMock.mockReturnValue([]);
643
+ routeGuardianReplyMock.mockResolvedValue({
644
+ consumed: false,
645
+ decisionApplied: false,
646
+ type: "not_consumed",
647
+ });
648
+
649
+ const mockGenerator = mock(async () => ({}));
650
+ const persistUserMessage = mock(async () => "persisted-user-id");
651
+ const runAgentLoop = mock(async () => undefined);
652
+ const session = {
653
+ setTrustContext: () => {},
654
+ updateClient: () => {},
655
+ emitConfirmationStateChanged: () => {},
656
+ emitActivityState: () => {},
657
+ setTurnChannelContext: () => {},
658
+ setTurnInterfaceContext: () => {},
659
+ ensureActorScopedHistory: async () => {},
660
+ usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
661
+ isProcessing: () => false,
662
+ hasAnyPendingConfirmation: () => false,
663
+ denyAllPendingConfirmations: () => {},
664
+ enqueueMessage: () => ({ queued: true, requestId: "queued-id" }),
665
+ persistUserMessage,
666
+ runAgentLoop,
667
+ getMessages: () => [] as unknown[],
668
+ assistantId: "self",
669
+ trustContext: undefined,
670
+ hasPendingConfirmation: () => false,
671
+ setHostBashProxy: () => {},
672
+ setHostFileProxy: () => {},
673
+ setHostCuProxy: () => {},
674
+ } as unknown as import("../daemon/session.js").Session;
675
+
676
+ const req = new Request("http://localhost/v1/messages", {
677
+ method: "POST",
678
+ headers: { "Content-Type": "application/json" },
679
+ body: JSON.stringify({
680
+ conversationKey: "guardian-thread-key",
681
+ content: "no sorry, beats 0 and 3 should be new threads",
682
+ sourceChannel: "telegram",
683
+ interface: "telegram",
684
+ }),
685
+ });
686
+
687
+ await handleSendMessage(
688
+ req,
689
+ {
690
+ sendMessageDeps: {
691
+ getOrCreateSession: async () => session,
692
+ assistantEventHub: { publish: async () => {} } as any,
693
+ resolveAttachments: () => [],
694
+ },
695
+ approvalConversationGenerator: mockGenerator as any,
696
+ },
697
+ testAuthContext,
698
+ );
699
+
700
+ expect(routeGuardianReplyMock).toHaveBeenCalledTimes(1);
701
+ const routerCall = (routeGuardianReplyMock as any).mock
702
+ .calls[0][0] as Record<string, unknown>;
703
+ // Channel sessions should receive the NL engine
704
+ expect(routerCall.approvalConversationGenerator).toBe(mockGenerator);
705
+ });
562
706
  });
@@ -203,6 +203,7 @@ function makeSession() {
203
203
  hasPendingConfirmation: () => false,
204
204
  setHostBashProxy: () => {},
205
205
  setHostFileProxy: () => {},
206
+ setHostCuProxy: () => {},
206
207
  usageStats: {
207
208
  inputTokens: 1000,
208
209
  outputTokens: 500,
@@ -49,6 +49,7 @@ mock.module("../tools/registry.js", () => ({
49
49
  // Imports under test
50
50
  // ---------------------------------------------------------------------------
51
51
 
52
+ import { credentialKey } from "../security/credential-key.js";
52
53
  import { setSecureKey } from "../security/secure-keys.js";
53
54
  import { CredentialBroker } from "../tools/credentials/broker.js";
54
55
  import {
@@ -92,7 +93,7 @@ describe("CredentialBroker.browserFill", () => {
92
93
  upsertCredentialMetadata("github", "token", {
93
94
  allowedTools: ["browser_fill_credential"],
94
95
  });
95
- setSecureKey("credential:github:token", "ghp_secret123");
96
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
96
97
 
97
98
  let filledValue: string | undefined;
98
99
  const result = await broker.browserFill({
@@ -114,7 +115,7 @@ describe("CredentialBroker.browserFill", () => {
114
115
  upsertCredentialMetadata("github", "token", {
115
116
  allowedTools: ["browser_fill_credential"],
116
117
  });
117
- setSecureKey("credential:github:token", "ghp_secret123");
118
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
118
119
 
119
120
  const result = await broker.browserFill({
120
121
  service: "github",
@@ -167,7 +168,7 @@ describe("CredentialBroker.browserFill", () => {
167
168
  upsertCredentialMetadata("github", "token", {
168
169
  allowedTools: ["browser_fill_credential"],
169
170
  });
170
- setSecureKey("credential:github:token", "ghp_secret123");
171
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
171
172
 
172
173
  const result = await broker.browserFill({
173
174
  service: "github",
@@ -193,8 +194,8 @@ describe("CredentialBroker.browserFill", () => {
193
194
  upsertCredentialMetadata("github", "password", {
194
195
  allowedTools: ["browser_fill_credential"],
195
196
  });
196
- setSecureKey("credential:github:username", "octocat");
197
- setSecureKey("credential:github:password", "hunter2");
197
+ setSecureKey(credentialKey("github", "username"), "octocat");
198
+ setSecureKey(credentialKey("github", "password"), "hunter2");
198
199
 
199
200
  const filled: Record<string, string> = {};
200
201
 
@@ -227,7 +228,7 @@ describe("CredentialBroker.browserFill", () => {
227
228
  allowedTools: ["browser_fill_credential"],
228
229
  allowedDomains: ["github.com"],
229
230
  });
230
- setSecureKey("credential:github:token", "ghp_secret123");
231
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
231
232
 
232
233
  const result = await broker.browserFill({
233
234
  service: "github",
@@ -245,7 +246,7 @@ describe("CredentialBroker.browserFill", () => {
245
246
  allowedTools: ["browser_fill_credential"],
246
247
  allowedDomains: ["github.com"],
247
248
  });
248
- setSecureKey("credential:github:token", "ghp_secret123");
249
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
249
250
 
250
251
  const result = await broker.browserFill({
251
252
  service: "github",
@@ -263,7 +264,7 @@ describe("CredentialBroker.browserFill", () => {
263
264
  allowedTools: ["browser_fill_credential"],
264
265
  allowedDomains: ["github.com"],
265
266
  });
266
- setSecureKey("credential:github:token", "ghp_secret123");
267
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
267
268
 
268
269
  const result = await broker.browserFill({
269
270
  service: "github",
@@ -286,7 +287,7 @@ describe("CredentialBroker.browserFill", () => {
286
287
  allowedTools: ["browser_fill_credential"],
287
288
  allowedDomains: ["github.com"],
288
289
  });
289
- setSecureKey("credential:github:token", "ghp_secret123");
290
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
290
291
 
291
292
  const result = await broker.browserFill({
292
293
  service: "github",
@@ -305,7 +306,7 @@ describe("CredentialBroker.browserFill", () => {
305
306
  upsertCredentialMetadata("github", "token", {
306
307
  allowedTools: ["browser_fill_credential"],
307
308
  });
308
- setSecureKey("credential:github:token", "ghp_secret123");
309
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
309
310
 
310
311
  // No domain provided and no allowedDomains policy — should succeed
311
312
  const result = await broker.browserFill({
@@ -322,7 +323,7 @@ describe("CredentialBroker.browserFill", () => {
322
323
  upsertCredentialMetadata("github", "token", {
323
324
  allowedTools: ["other_tool"],
324
325
  });
325
- setSecureKey("credential:github:token", "ghp_secret123");
326
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
326
327
 
327
328
  let fillCalled = false;
328
329
  const result = await broker.browserFill({
@@ -343,7 +344,7 @@ describe("CredentialBroker.browserFill", () => {
343
344
 
344
345
  test("denies fill when allowedTools is empty (fail-closed)", async () => {
345
346
  upsertCredentialMetadata("github", "token", { allowedTools: [] });
346
- setSecureKey("credential:github:token", "ghp_secret123");
347
+ setSecureKey(credentialKey("github", "token"), "ghp_secret123");
347
348
 
348
349
  const result = await broker.browserFill({
349
350
  service: "github",
@@ -362,7 +363,7 @@ describe("CredentialBroker.browserFill", () => {
362
363
  upsertCredentialMetadata("github", "token", {
363
364
  allowedTools: ["browser_fill_credential"],
364
365
  });
365
- setSecureKey("credential:github:token", "ghp_supersecret");
366
+ setSecureKey(credentialKey("github", "token"), "ghp_supersecret");
366
367
 
367
368
  const result = await broker.browserFill({
368
369
  service: "github",
@@ -388,7 +389,7 @@ describe("CredentialBroker.browserFill", () => {
388
389
  allowedTools: ["s3_upload", "cloudfront_invalidate"],
389
390
  allowedDomains: [],
390
391
  });
391
- setSecureKey("credential:aws:access_key", "AKIA_test");
392
+ setSecureKey(credentialKey("aws", "access_key"), "AKIA_test");
392
393
 
393
394
  let fillCalled = false;
394
395
  const result = await broker.browserFill({
@@ -413,7 +414,7 @@ describe("CredentialBroker.browserFill", () => {
413
414
  allowedTools: ["browser_fill_credential"],
414
415
  allowedDomains: ["github.com"],
415
416
  });
416
- setSecureKey("credential:github:pat", "ghp_fill_test");
417
+ setSecureKey(credentialKey("github", "pat"), "ghp_fill_test");
417
418
 
418
419
  let fillCalled = false;
419
420
  const result = await broker.browserFill({
@@ -437,7 +438,7 @@ describe("CredentialBroker.browserFill", () => {
437
438
  allowedTools: ["slack_post"],
438
439
  allowedDomains: ["slack.com"],
439
440
  });
440
- setSecureKey("credential:slack:bot_token", "xoxb-test");
441
+ setSecureKey(credentialKey("slack", "bot_token"), "xoxb-test");
441
442
 
442
443
  const result = await broker.browserFill({
443
444
  service: "slack",
@@ -460,7 +461,7 @@ describe("CredentialBroker.browserFill", () => {
460
461
  upsertCredentialMetadata("custom", "key", {
461
462
  allowedTools: [],
462
463
  });
463
- setSecureKey("credential:custom:key", "secret");
464
+ setSecureKey(credentialKey("custom", "key"), "secret");
464
465
 
465
466
  const result = await broker.browserFill({
466
467
  service: "custom",
@@ -490,7 +491,7 @@ describe("CredentialBroker.browserFill", () => {
490
491
  upsertCredentialMetadata("github", "token", {
491
492
  allowedTools: ["browser_fill_credential"],
492
493
  });
493
- setSecureKey("credential:github:token", "ghp_updated");
494
+ setSecureKey(credentialKey("github", "token"), "ghp_updated");
494
495
 
495
496
  let filledValue: string | undefined;
496
497
  const result = await broker.browserFill({
@@ -514,8 +515,8 @@ describe("CredentialBroker.browserFill", () => {
514
515
  upsertCredentialMetadata("github", "password", {
515
516
  allowedTools: ["other_tool"],
516
517
  });
517
- setSecureKey("credential:github:username", "octocat");
518
- setSecureKey("credential:github:password", "hunter2");
518
+ setSecureKey(credentialKey("github", "username"), "octocat");
519
+ setSecureKey(credentialKey("github", "password"), "hunter2");
519
520
 
520
521
  // username allows browser_fill_credential
521
522
  const r1 = await broker.browserFill({
@@ -548,8 +549,8 @@ describe("CredentialBroker.browserFill", () => {
548
549
  allowedTools: ["browser_fill_credential"],
549
550
  allowedDomains: ["gitlab.com"],
550
551
  });
551
- setSecureKey("credential:github:token", "gh_tok");
552
- setSecureKey("credential:gitlab:token", "gl_tok");
552
+ setSecureKey(credentialKey("github", "token"), "gh_tok");
553
+ setSecureKey(credentialKey("gitlab", "token"), "gl_tok");
553
554
 
554
555
  // github credential on github.com succeeds
555
556
  let filled1 = "";
@@ -48,6 +48,7 @@ mock.module("../tools/registry.js", () => ({
48
48
  // Imports under test
49
49
  // ---------------------------------------------------------------------------
50
50
 
51
+ import { credentialKey } from "../security/credential-key.js";
51
52
  import { setSecureKey } from "../security/secure-keys.js";
52
53
  import { CredentialBroker } from "../tools/credentials/broker.js";
53
54
  import {
@@ -85,7 +86,7 @@ describe("CredentialBroker.serverUse", () => {
85
86
  upsertCredentialMetadata("vercel", "api_token", {
86
87
  allowedTools: ["publish_page"],
87
88
  });
88
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
89
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
89
90
 
90
91
  const result = await broker.serverUse({
91
92
  service: "vercel",
@@ -109,7 +110,7 @@ describe("CredentialBroker.serverUse", () => {
109
110
  upsertCredentialMetadata("vercel", "api_token", {
110
111
  allowedTools: ["publish_page"],
111
112
  });
112
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
113
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
113
114
 
114
115
  const result = await broker.serverUse({
115
116
  service: "vercel",
@@ -161,7 +162,7 @@ describe("CredentialBroker.serverUse", () => {
161
162
  upsertCredentialMetadata("vercel", "api_token", {
162
163
  allowedTools: ["publish_page"],
163
164
  });
164
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
165
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
165
166
 
166
167
  const result = await broker.serverUse({
167
168
  service: "vercel",
@@ -182,7 +183,7 @@ describe("CredentialBroker.serverUse", () => {
182
183
  upsertCredentialMetadata("vercel", "api_token", {
183
184
  allowedTools: ["publish_page"],
184
185
  });
185
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
186
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
186
187
 
187
188
  const result = await broker.serverUse({
188
189
  service: "vercel",
@@ -201,7 +202,7 @@ describe("CredentialBroker.serverUse", () => {
201
202
  allowedTools: ["publish_page"],
202
203
  allowedDomains: ["vercel.com"],
203
204
  });
204
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
205
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
205
206
 
206
207
  const result = await broker.serverUse({
207
208
  service: "vercel",
@@ -222,7 +223,7 @@ describe("CredentialBroker.serverUse", () => {
222
223
  allowedTools: ["publish_page"],
223
224
  allowedDomains: [],
224
225
  });
225
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
226
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
226
227
 
227
228
  const result = await broker.serverUse({
228
229
  service: "vercel",
@@ -247,7 +248,7 @@ describe("CredentialBroker.serverUse", () => {
247
248
  upsertCredentialMetadata("aws", "access_key", {
248
249
  allowedTools: ["deploy_lambda", "s3_upload"],
249
250
  });
250
- setSecureKey("credential:aws:access_key", "AKIA_test");
251
+ setSecureKey(credentialKey("aws", "access_key"), "AKIA_test");
251
252
 
252
253
  const result = await broker.serverUse({
253
254
  service: "aws",
@@ -270,7 +271,7 @@ describe("CredentialBroker.serverUse", () => {
270
271
  upsertCredentialMetadata("stripe", "secret_key", {
271
272
  allowedTools: [],
272
273
  });
273
- setSecureKey("credential:stripe:secret_key", "sk_test_xyz");
274
+ setSecureKey(credentialKey("stripe", "secret_key"), "sk_test_xyz");
274
275
 
275
276
  const result = await broker.serverUse({
276
277
  service: "stripe",
@@ -291,7 +292,7 @@ describe("CredentialBroker.serverUse", () => {
291
292
  allowedTools: ["git_push"],
292
293
  allowedDomains: ["github.com"],
293
294
  });
294
- setSecureKey("credential:github:oauth_token", "gho_test");
295
+ setSecureKey(credentialKey("github", "oauth_token"), "gho_test");
295
296
 
296
297
  const result = await broker.serverUse({
297
298
  service: "github",
@@ -322,7 +323,7 @@ describe("CredentialBroker.serverUse", () => {
322
323
  upsertCredentialMetadata("vercel", "api_token", {
323
324
  allowedTools: ["publish_page", "unpublish_page"],
324
325
  });
325
- setSecureKey("credential:vercel:api_token", "tok_updated");
326
+ setSecureKey(credentialKey("vercel", "api_token"), "tok_updated");
326
327
 
327
328
  const result = await broker.serverUse({
328
329
  service: "vercel",
@@ -342,8 +343,8 @@ describe("CredentialBroker.serverUse", () => {
342
343
  upsertCredentialMetadata("vercel", "deploy_hook", {
343
344
  allowedTools: ["trigger_deploy"],
344
345
  });
345
- setSecureKey("credential:vercel:api_token", "tok_api");
346
- setSecureKey("credential:vercel:deploy_hook", "hook_secret");
346
+ setSecureKey(credentialKey("vercel", "api_token"), "tok_api");
347
+ setSecureKey(credentialKey("vercel", "deploy_hook"), "hook_secret");
347
348
 
348
349
  // api_token should deny trigger_deploy
349
350
  const r1 = await broker.serverUse({
@@ -377,8 +378,8 @@ describe("CredentialBroker.serverUse", () => {
377
378
  upsertCredentialMetadata("gitlab", "api_token", {
378
379
  allowedTools: ["gitlab_api"],
379
380
  });
380
- setSecureKey("credential:github:api_token", "gh_tok");
381
- setSecureKey("credential:gitlab:api_token", "gl_tok");
381
+ setSecureKey(credentialKey("github", "api_token"), "gh_tok");
382
+ setSecureKey(credentialKey("gitlab", "api_token"), "gl_tok");
382
383
 
383
384
  // github credential should not serve gitlab tool
384
385
  const r1 = broker.serverUseById({
@@ -395,8 +396,8 @@ describe("CredentialBroker.serverUse", () => {
395
396
  upsertCredentialMetadata("gitlab", "api_token", {
396
397
  allowedTools: ["gitlab_api"],
397
398
  });
398
- setSecureKey("credential:github:api_token", "gh_tok");
399
- setSecureKey("credential:gitlab:api_token", "gl_tok");
399
+ setSecureKey(credentialKey("github", "api_token"), "gh_tok");
400
+ setSecureKey(credentialKey("gitlab", "api_token"), "gl_tok");
400
401
 
401
402
  // github credential should not serve gitlab tool
402
403
  const r1 = await broker.serverUse({
@@ -458,7 +459,7 @@ describe("CredentialBroker.serverUseById", () => {
458
459
  },
459
460
  ],
460
461
  });
461
- setSecureKey("credential:fal:api_key", "fal-secret-key");
462
+ setSecureKey(credentialKey("fal", "api_key"), "fal-secret-key");
462
463
 
463
464
  const result = broker.serverUseById({
464
465
  credentialId: meta.credentialId,
@@ -483,7 +484,7 @@ describe("CredentialBroker.serverUseById", () => {
483
484
  const meta = upsertCredentialMetadata("fal", "api_key", {
484
485
  allowedTools: ["media_proxy"],
485
486
  });
486
- setSecureKey("credential:fal:api_key", "fal-secret-key");
487
+ setSecureKey(credentialKey("fal", "api_key"), "fal-secret-key");
487
488
 
488
489
  const result = broker.serverUseById({
489
490
  credentialId: meta.credentialId,
@@ -514,7 +515,7 @@ describe("CredentialBroker.serverUseById", () => {
514
515
  allowedTools: ["media_proxy"],
515
516
  allowedDomains: ["github.com"],
516
517
  });
517
- setSecureKey("credential:github:oauth_token", "gho_test");
518
+ setSecureKey(credentialKey("github", "oauth_token"), "gho_test");
518
519
 
519
520
  const result = broker.serverUseById({
520
521
  credentialId: meta.credentialId,
@@ -531,7 +532,7 @@ describe("CredentialBroker.serverUseById", () => {
531
532
  const meta = upsertCredentialMetadata("vercel", "api_token", {
532
533
  allowedTools: ["media_proxy"],
533
534
  });
534
- setSecureKey("credential:vercel:api_token", "test-vercel-token");
535
+ setSecureKey(credentialKey("vercel", "api_token"), "test-vercel-token");
535
536
 
536
537
  const result = broker.serverUseById({
537
538
  credentialId: meta.credentialId,
@@ -547,7 +548,7 @@ describe("CredentialBroker.serverUseById", () => {
547
548
  const meta = upsertCredentialMetadata("stripe", "secret_key", {
548
549
  allowedTools: [],
549
550
  });
550
- setSecureKey("credential:stripe:secret_key", "sk_test_xyz");
551
+ setSecureKey(credentialKey("stripe", "secret_key"), "sk_test_xyz");
551
552
 
552
553
  const result = broker.serverUseById({
553
554
  credentialId: meta.credentialId,
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
4
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
5
5
 
6
+ import { credentialKey } from "../security/credential-key.js";
6
7
  import { CredentialBroker } from "../tools/credentials/broker.js";
7
8
  import {
8
9
  _setMetadataPath,
@@ -125,7 +126,7 @@ describe("CredentialBroker", () => {
125
126
 
126
127
  const result = broker.consume(auth.token.tokenId);
127
128
  expect(result.success).toBe(true);
128
- expect(result.storageKey).toBe("credential:github:token");
129
+ expect(result.storageKey).toBe(credentialKey("github", "token"));
129
130
  });
130
131
 
131
132
  test("rejects double consumption", () => {