@vellumai/assistant 0.4.46 → 0.4.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/ARCHITECTURE.md +7 -7
  2. package/README.md +2 -23
  3. package/docs/architecture/integrations.md +45 -41
  4. package/docs/architecture/keychain-broker.md +3 -3
  5. package/docs/architecture/security.md +5 -5
  6. package/docs/runbook-trusted-contacts.md +3 -8
  7. package/hook-templates/debug-prompt-logger/hook.json +1 -1
  8. package/hook-templates/debug-prompt-logger/run.sh +1 -3
  9. package/package.json +1 -1
  10. package/src/__tests__/actor-token-service.test.ts +0 -1
  11. package/src/__tests__/anthropic-provider.test.ts +156 -0
  12. package/src/__tests__/approval-cascade.test.ts +810 -0
  13. package/src/__tests__/approval-primitive.test.ts +0 -1
  14. package/src/__tests__/approval-routes-http.test.ts +2 -0
  15. package/src/__tests__/assistant-attachments.test.ts +12 -34
  16. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +76 -0
  17. package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -1
  18. package/src/__tests__/browser-fill-credential.test.ts +5 -2
  19. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +2 -2
  20. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
  21. package/src/__tests__/channel-guardian.test.ts +0 -2
  22. package/src/__tests__/channel-readiness-routes.test.ts +35 -25
  23. package/src/__tests__/channel-readiness-service.test.ts +10 -9
  24. package/src/__tests__/checker.test.ts +9 -29
  25. package/src/__tests__/cli.test.ts +23 -0
  26. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +1 -1
  27. package/src/__tests__/computer-use-tools.test.ts +2 -19
  28. package/src/__tests__/config-watcher.test.ts +0 -1
  29. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  30. package/src/__tests__/context-image-dimensions.test.ts +332 -0
  31. package/src/__tests__/context-token-estimator.test.ts +196 -13
  32. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  33. package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
  34. package/src/__tests__/conversation-routes-guardian-reply.test.ts +144 -0
  35. package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
  36. package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
  37. package/src/__tests__/credential-broker-server-use.test.ts +22 -21
  38. package/src/__tests__/credential-broker.test.ts +2 -1
  39. package/src/__tests__/credential-metadata-store.test.ts +239 -26
  40. package/src/__tests__/credential-resolve.test.ts +5 -4
  41. package/src/__tests__/credential-security-e2e.test.ts +8 -8
  42. package/src/__tests__/credential-security-invariants.test.ts +111 -7
  43. package/src/__tests__/credential-vault-unit.test.ts +287 -54
  44. package/src/__tests__/credential-vault.test.ts +406 -12
  45. package/src/__tests__/credentials-cli.test.ts +82 -6
  46. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  47. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  48. package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
  49. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  50. package/src/__tests__/gemini-image-service.test.ts +75 -45
  51. package/src/__tests__/gemini-provider.test.ts +9 -6
  52. package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
  53. package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
  54. package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
  55. package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
  56. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  57. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  58. package/src/__tests__/guardian-grant-minting.test.ts +35 -0
  59. package/src/__tests__/guardian-routing-invariants.test.ts +0 -1
  60. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  61. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +0 -39
  62. package/src/__tests__/heartbeat-service.test.ts +0 -1
  63. package/src/__tests__/host-cu-proxy.test.ts +629 -0
  64. package/src/__tests__/host-shell-tool.test.ts +27 -15
  65. package/src/__tests__/http-user-message-parity.test.ts +1 -0
  66. package/src/__tests__/ingress-url-consistency.test.ts +14 -21
  67. package/src/__tests__/integration-status.test.ts +38 -25
  68. package/src/__tests__/intent-routing.test.ts +0 -1
  69. package/src/__tests__/invite-routes-http.test.ts +10 -9
  70. package/src/__tests__/keychain-broker-client.test.ts +11 -43
  71. package/src/__tests__/managed-proxy-context.test.ts +5 -3
  72. package/src/__tests__/media-generate-image.test.ts +63 -2
  73. package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
  74. package/src/__tests__/messaging-send-tool.test.ts +4 -6
  75. package/src/__tests__/notification-routing-intent.test.ts +0 -1
  76. package/src/__tests__/oauth-cli.test.ts +373 -14
  77. package/src/__tests__/oauth-provider-profiles.test.ts +9 -9
  78. package/src/__tests__/oauth-scope-policy.test.ts +4 -6
  79. package/src/__tests__/oauth-store.test.ts +756 -0
  80. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  81. package/src/__tests__/provider-error-scenarios.test.ts +0 -1
  82. package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
  83. package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
  84. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -1
  85. package/src/__tests__/public-ingress-urls.test.ts +15 -21
  86. package/src/__tests__/recording-handler.test.ts +3 -4
  87. package/src/__tests__/registry.test.ts +2 -2
  88. package/src/__tests__/runtime-events-sse.test.ts +55 -7
  89. package/src/__tests__/schedule-store.test.ts +0 -1
  90. package/src/__tests__/scheduler-recurrence.test.ts +0 -1
  91. package/src/__tests__/schema-transforms.test.ts +226 -0
  92. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  93. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  94. package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
  95. package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
  96. package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
  97. package/src/__tests__/secret-ingress-handler.test.ts +0 -1
  98. package/src/__tests__/secret-onetime-send.test.ts +5 -3
  99. package/src/__tests__/send-endpoint-busy.test.ts +21 -6
  100. package/src/__tests__/sequence-store.test.ts +0 -1
  101. package/src/__tests__/session-init.benchmark.test.ts +4 -5
  102. package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
  103. package/src/__tests__/skill-include-graph.test.ts +66 -0
  104. package/src/__tests__/skill-load-feature-flag.test.ts +0 -1
  105. package/src/__tests__/skill-load-tool.test.ts +149 -1
  106. package/src/__tests__/skill-projection-feature-flag.test.ts +0 -1
  107. package/src/__tests__/skills-uninstall.test.ts +3 -3
  108. package/src/__tests__/skills.test.ts +3 -12
  109. package/src/__tests__/slack-channel-config.test.ts +76 -11
  110. package/src/__tests__/slack-share-routes.test.ts +17 -14
  111. package/src/__tests__/system-prompt.test.ts +0 -1
  112. package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
  113. package/src/__tests__/telegram-invite-adapter.test.ts +18 -22
  114. package/src/__tests__/terminal-tools.test.ts +4 -3
  115. package/src/__tests__/test-support/computer-use-skill-harness.ts +3 -2
  116. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  117. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  118. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -1
  119. package/src/__tests__/tool-executor-shell-integration.test.ts +0 -1
  120. package/src/__tests__/tool-executor.test.ts +0 -1
  121. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  122. package/src/__tests__/trust-store-pattern-matches.test.ts +29 -0
  123. package/src/__tests__/trust-store.test.ts +1 -22
  124. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  125. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  126. package/src/__tests__/twilio-config.test.ts +2 -1
  127. package/src/__tests__/twilio-provider.test.ts +4 -2
  128. package/src/__tests__/twilio-routes.test.ts +5 -20
  129. package/src/__tests__/verification-control-plane-policy.test.ts +0 -1
  130. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  131. package/src/agent/ax-tree-compaction.test.ts +235 -0
  132. package/src/agent/loop.ts +76 -130
  133. package/src/calls/call-domain.ts +8 -10
  134. package/src/calls/relay-server.ts +9 -13
  135. package/src/calls/twilio-config.ts +4 -8
  136. package/src/calls/twilio-provider.ts +2 -1
  137. package/src/calls/twilio-rest.ts +2 -1
  138. package/src/calls/twilio-routes.ts +1 -2
  139. package/src/calls/voice-ingress-preflight.ts +1 -1
  140. package/src/cli/commands/browser-relay.ts +46 -15
  141. package/src/cli/commands/completions.ts +0 -3
  142. package/src/cli/commands/credentials.ts +110 -23
  143. package/src/cli/commands/oauth/apps.ts +255 -0
  144. package/src/cli/commands/oauth/connections.ts +299 -0
  145. package/src/cli/commands/oauth/index.ts +52 -0
  146. package/src/cli/commands/oauth/providers.ts +242 -0
  147. package/src/cli/commands/skills.ts +4 -338
  148. package/src/cli/program.ts +1 -5
  149. package/src/cli/reference.ts +1 -3
  150. package/src/cli.ts +3 -2
  151. package/src/config/assistant-feature-flags.ts +0 -3
  152. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +1 -1
  153. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
  154. package/src/config/bundled-skills/computer-use/SKILL.md +3 -6
  155. package/src/config/bundled-skills/computer-use/TOOLS.json +22 -4
  156. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
  157. package/src/config/bundled-skills/gmail/SKILL.md +4 -4
  158. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
  159. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
  160. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
  161. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
  162. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
  163. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
  164. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
  165. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
  166. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
  167. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
  168. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
  169. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
  170. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
  171. package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
  172. package/src/config/bundled-skills/google-calendar/calendar-client.ts +90 -44
  173. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
  174. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
  175. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
  176. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
  177. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
  178. package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
  179. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
  180. package/src/config/bundled-skills/messaging/SKILL.md +6 -6
  181. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
  182. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
  183. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
  184. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
  185. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
  186. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
  187. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
  188. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
  189. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
  190. package/src/config/bundled-skills/messaging/tools/shared.ts +12 -15
  191. package/src/config/bundled-skills/settings/SKILL.md +1 -1
  192. package/src/config/bundled-skills/settings/TOOLS.json +2 -8
  193. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +5 -33
  194. package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
  195. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
  196. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
  197. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
  198. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
  199. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
  200. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
  201. package/src/config/env-registry.ts +14 -83
  202. package/src/config/env.ts +11 -50
  203. package/src/config/feature-flag-registry.json +16 -16
  204. package/src/config/schema.ts +3 -1
  205. package/src/config/skills.ts +21 -2
  206. package/src/context/image-dimensions.ts +229 -0
  207. package/src/context/token-estimator.ts +75 -12
  208. package/src/context/window-manager.ts +49 -10
  209. package/src/daemon/assistant-attachments.ts +1 -13
  210. package/src/daemon/guardian-action-generators.ts +4 -5
  211. package/src/daemon/handlers/config-ingress.ts +8 -33
  212. package/src/daemon/handlers/config-slack-channel.ts +76 -56
  213. package/src/daemon/handlers/config-telegram.ts +53 -24
  214. package/src/daemon/handlers/sessions.ts +10 -24
  215. package/src/daemon/handlers/shared.ts +0 -130
  216. package/src/daemon/host-cu-proxy.ts +401 -0
  217. package/src/daemon/lifecycle.ts +39 -63
  218. package/src/daemon/message-protocol.ts +3 -0
  219. package/src/daemon/message-types/computer-use.ts +2 -119
  220. package/src/daemon/message-types/host-cu.ts +19 -0
  221. package/src/daemon/message-types/integrations.ts +1 -0
  222. package/src/daemon/message-types/messages.ts +3 -0
  223. package/src/daemon/server.ts +14 -21
  224. package/src/daemon/session-agent-loop-handlers.ts +2 -0
  225. package/src/daemon/session-attachments.ts +1 -2
  226. package/src/daemon/session-messaging.ts +3 -1
  227. package/src/daemon/session-slash.ts +1 -1
  228. package/src/daemon/session-surfaces.ts +40 -28
  229. package/src/daemon/session-tool-setup.ts +20 -11
  230. package/src/daemon/session.ts +139 -16
  231. package/src/daemon/tool-side-effects.ts +2 -8
  232. package/src/daemon/watch-handler.ts +2 -2
  233. package/src/email/providers/index.ts +2 -1
  234. package/src/events/tool-metrics-listener.ts +2 -2
  235. package/src/hooks/manager.ts +1 -4
  236. package/src/inbound/public-ingress-urls.ts +7 -7
  237. package/src/instrument.ts +15 -1
  238. package/src/logfire.ts +16 -5
  239. package/src/media/app-icon-generator.ts +30 -4
  240. package/src/media/avatar-router.ts +26 -3
  241. package/src/media/gemini-image-service.ts +28 -2
  242. package/src/memory/conversation-key-store.ts +21 -0
  243. package/src/memory/db-init.ts +4 -0
  244. package/src/memory/guardian-action-store.ts +1 -1
  245. package/src/memory/migrations/149-oauth-tables.ts +60 -0
  246. package/src/memory/migrations/index.ts +1 -0
  247. package/src/memory/schema/guardian.ts +1 -1
  248. package/src/memory/schema/index.ts +1 -0
  249. package/src/memory/schema/oauth.ts +65 -0
  250. package/src/messaging/provider.ts +19 -13
  251. package/src/messaging/providers/gmail/adapter.ts +40 -23
  252. package/src/messaging/providers/gmail/client.ts +283 -122
  253. package/src/messaging/providers/gmail/people-client.ts +32 -24
  254. package/src/messaging/providers/slack/adapter.ts +29 -19
  255. package/src/messaging/providers/slack/client.ts +265 -78
  256. package/src/messaging/providers/telegram-bot/adapter.ts +19 -18
  257. package/src/messaging/providers/whatsapp/adapter.ts +17 -11
  258. package/src/messaging/registry.ts +2 -31
  259. package/src/notifications/copy-composer.ts +0 -5
  260. package/src/notifications/signal.ts +4 -5
  261. package/src/oauth/byo-connection.test.ts +537 -0
  262. package/src/oauth/byo-connection.ts +128 -0
  263. package/src/oauth/connect-orchestrator.ts +139 -56
  264. package/src/oauth/connect-types.ts +17 -23
  265. package/src/oauth/connection-resolver.ts +58 -0
  266. package/src/oauth/connection.ts +38 -0
  267. package/src/oauth/manual-token-connection.ts +104 -0
  268. package/src/oauth/oauth-store.ts +496 -0
  269. package/src/oauth/platform-connection.test.ts +192 -0
  270. package/src/oauth/platform-connection.ts +111 -0
  271. package/src/oauth/provider-behaviors.ts +124 -0
  272. package/src/oauth/scope-policy.ts +9 -2
  273. package/src/oauth/seed-providers.ts +161 -0
  274. package/src/oauth/token-persistence.ts +74 -78
  275. package/src/permissions/checker.ts +8 -4
  276. package/src/permissions/defaults.ts +0 -1
  277. package/src/permissions/prompter.ts +10 -1
  278. package/src/permissions/trust-store.ts +13 -0
  279. package/src/prompts/__tests__/build-cli-reference-section.test.ts +3 -1
  280. package/src/prompts/system-prompt.ts +70 -45
  281. package/src/providers/anthropic/client.ts +133 -24
  282. package/src/providers/gemini/client.ts +15 -6
  283. package/src/providers/managed-proxy/constants.ts +2 -2
  284. package/src/providers/managed-proxy/context.ts +5 -1
  285. package/src/providers/ratelimit.ts +17 -0
  286. package/src/providers/registry.ts +2 -2
  287. package/src/providers/retry.ts +1 -27
  288. package/src/runtime/AGENTS.md +17 -0
  289. package/src/runtime/auth/route-policy.ts +0 -3
  290. package/src/runtime/channel-invite-transports/telegram.ts +2 -1
  291. package/src/runtime/channel-readiness-service.ts +168 -195
  292. package/src/runtime/channel-readiness-types.ts +4 -0
  293. package/src/runtime/channel-reply-delivery.ts +0 -40
  294. package/src/runtime/gateway-client.ts +0 -7
  295. package/src/runtime/guardian-action-conversation-turn.ts +1 -3
  296. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  297. package/src/runtime/guardian-action-message-composer.ts +3 -23
  298. package/src/runtime/http-server.ts +17 -10
  299. package/src/runtime/http-types.ts +2 -3
  300. package/src/runtime/middleware/rate-limiter.ts +74 -20
  301. package/src/runtime/middleware/twilio-validation.ts +1 -11
  302. package/src/runtime/pending-interactions.ts +14 -12
  303. package/src/runtime/routes/channel-delivery-routes.ts +0 -1
  304. package/src/runtime/routes/channel-readiness-routes.ts +2 -0
  305. package/src/runtime/routes/conversation-routes.ts +73 -19
  306. package/src/runtime/routes/diagnostics-routes.ts +11 -9
  307. package/src/runtime/routes/events-routes.ts +21 -11
  308. package/src/runtime/routes/guardian-approval-interception.ts +20 -5
  309. package/src/runtime/routes/host-cu-routes.ts +97 -0
  310. package/src/runtime/routes/inbound-stages/background-dispatch.ts +12 -111
  311. package/src/runtime/routes/integrations/slack/share.ts +6 -6
  312. package/src/runtime/routes/integrations/twilio.ts +6 -5
  313. package/src/runtime/routes/log-export-routes.ts +126 -8
  314. package/src/runtime/routes/secret-routes.ts +3 -2
  315. package/src/runtime/routes/settings-routes.ts +113 -48
  316. package/src/runtime/routes/surface-action-routes.ts +1 -1
  317. package/src/runtime/routes/watch-routes.ts +128 -0
  318. package/src/schedule/integration-status.ts +10 -8
  319. package/src/security/credential-key.ts +14 -0
  320. package/src/security/keychain-broker-client.ts +5 -6
  321. package/src/security/oauth2.ts +1 -1
  322. package/src/security/token-manager.ts +145 -43
  323. package/src/skills/catalog-install.ts +358 -0
  324. package/src/skills/include-graph.ts +32 -0
  325. package/src/telegram/bot-username.ts +2 -3
  326. package/src/tools/apps/definitions.ts +0 -5
  327. package/src/tools/assets/materialize.ts +0 -5
  328. package/src/tools/assets/search.ts +0 -5
  329. package/src/tools/browser/headless-browser.ts +1 -67
  330. package/src/tools/browser/network-recorder.ts +1 -1
  331. package/src/tools/browser/network-recording-types.ts +1 -1
  332. package/src/tools/claude-code/claude-code.ts +0 -5
  333. package/src/tools/computer-use/definitions.ts +46 -11
  334. package/src/tools/computer-use/registry.ts +4 -5
  335. package/src/tools/credentials/broker.ts +5 -4
  336. package/src/tools/credentials/metadata-store.ts +22 -74
  337. package/src/tools/credentials/resolve.ts +2 -1
  338. package/src/tools/credentials/vault.ts +139 -151
  339. package/src/tools/filesystem/edit.ts +1 -6
  340. package/src/tools/filesystem/read.ts +0 -5
  341. package/src/tools/filesystem/write.ts +1 -6
  342. package/src/tools/host-filesystem/edit.ts +1 -6
  343. package/src/tools/host-filesystem/read.ts +1 -6
  344. package/src/tools/host-filesystem/write.ts +1 -6
  345. package/src/tools/mcp/mcp-tool-factory.ts +18 -1
  346. package/src/tools/memory/definitions.ts +0 -5
  347. package/src/tools/network/web-fetch.ts +0 -5
  348. package/src/tools/network/web-search.ts +0 -5
  349. package/src/tools/registry.ts +2 -7
  350. package/src/tools/schema-transforms.ts +99 -0
  351. package/src/tools/skills/load.ts +62 -8
  352. package/src/tools/swarm/delegate.ts +0 -5
  353. package/src/tools/system/avatar-generator.ts +0 -5
  354. package/src/tools/ui-surface/definitions.ts +0 -15
  355. package/src/tools/watch/screen-watch.ts +0 -5
  356. package/src/tools/watch/watch-state.ts +0 -12
  357. package/src/util/logger.ts +7 -41
  358. package/src/util/platform.ts +9 -28
  359. package/src/version.ts +10 -0
  360. package/src/watcher/providers/github.ts +51 -52
  361. package/src/watcher/providers/gmail.ts +88 -80
  362. package/src/watcher/providers/google-calendar.ts +94 -86
  363. package/src/watcher/providers/linear.ts +87 -93
  364. package/src/__tests__/computer-use-session-compaction.test.ts +0 -143
  365. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -322
  366. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -166
  367. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -78
  368. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -105
  369. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -249
  370. package/src/__tests__/ride-shotgun-handler.test.ts +0 -452
  371. package/src/cli/commands/dev.ts +0 -129
  372. package/src/cli/commands/map.ts +0 -391
  373. package/src/cli/commands/oauth.ts +0 -77
  374. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -16
  375. package/src/daemon/computer-use-session.ts +0 -1020
  376. package/src/daemon/ride-shotgun-handler.ts +0 -567
  377. package/src/oauth/provider-profiles.ts +0 -192
  378. package/src/prompts/computer-use-prompt.ts +0 -98
  379. package/src/runtime/routes/computer-use-routes.ts +0 -641
  380. package/src/runtime/telegram-streaming-delivery.test.ts +0 -597
  381. package/src/runtime/telegram-streaming-delivery.ts +0 -383
  382. package/src/tools/computer-use/request-computer-control.ts +0 -61
@@ -1,13 +1,12 @@
1
1
  import { getConfig } from "../config/loader.js";
2
2
 
3
3
  /**
4
- * Read the Telegram bot username from config, falling back to the
5
- * TELEGRAM_BOT_USERNAME env var.
4
+ * Read the Telegram bot username from config.
6
5
  */
7
6
  export function getTelegramBotUsername(): string | undefined {
8
7
  const value = getConfig().telegram.botUsername;
9
8
  if (value.trim().length > 0) {
10
9
  return value.trim();
11
10
  }
12
- return process.env.TELEGRAM_BOT_USERNAME || undefined;
11
+ return undefined;
13
12
  }
@@ -51,11 +51,6 @@ const appOpenTool: Tool = {
51
51
  description:
52
52
  "Display mode. 'preview' shows an inline preview card in chat. 'workspace' opens the full app in a workspace panel. Defaults to 'workspace'.",
53
53
  },
54
- reason: {
55
- type: "string",
56
- description:
57
- "Brief non-technical explanation of what you are opening and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
58
- },
59
54
  },
60
55
  required: ["app_id"],
61
56
  },
@@ -95,11 +95,6 @@ const definition: ToolDefinition = {
95
95
  description:
96
96
  "Path where the file should be written, relative to (or inside) the sandbox working directory.",
97
97
  },
98
- reason: {
99
- type: "string",
100
- description:
101
- "Brief non-technical explanation of what you are saving and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
102
- },
103
98
  },
104
99
  required: ["attachment_id", "destination_path"],
105
100
  },
@@ -298,11 +298,6 @@ const definition: ToolDefinition = {
298
298
  type: "number",
299
299
  description: `Maximum results to return (default ${DEFAULT_LIMIT}, max ${MAX_RESULTS}).`,
300
300
  },
301
- reason: {
302
- type: "string",
303
- description:
304
- "Brief non-technical explanation of what you are searching for and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
305
- },
306
301
  },
307
302
  required: [],
308
303
  },
@@ -44,11 +44,6 @@ class BrowserNavigateTool implements Tool {
44
44
  description:
45
45
  "If true, allows navigation to localhost/private-network hosts. Disabled by default for SSRF safety.",
46
46
  },
47
- reason: {
48
- type: "string",
49
- description:
50
- "Brief non-technical explanation of what you are navigating to and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
51
- },
52
47
  },
53
48
  required: ["url"],
54
49
  },
@@ -80,13 +75,7 @@ class BrowserSnapshotTool implements Tool {
80
75
  description: this.description,
81
76
  input_schema: {
82
77
  type: "object",
83
- properties: {
84
- reason: {
85
- type: "string",
86
- description:
87
- "Brief non-technical explanation of what you are inspecting and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
88
- },
89
- },
78
+ properties: {},
90
79
  },
91
80
  };
92
81
  }
@@ -122,11 +111,6 @@ class BrowserScreenshotTool implements Tool {
122
111
  description:
123
112
  "Capture the full scrollable page instead of just the viewport.",
124
113
  },
125
- reason: {
126
- type: "string",
127
- description:
128
- "Brief non-technical explanation of what you are capturing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
129
- },
130
114
  },
131
115
  },
132
116
  };
@@ -163,11 +147,6 @@ class BrowserCloseTool implements Tool {
163
147
  description:
164
148
  "If true, close all browser pages and the browser context. Default: false (close only the current session page).",
165
149
  },
166
- reason: {
167
- type: "string",
168
- description:
169
- "Brief non-technical explanation of what you are doing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
170
- },
171
150
  },
172
151
  },
173
152
  };
@@ -214,11 +193,6 @@ class BrowserClickTool implements Tool {
214
193
  description:
215
194
  "Max time in ms to wait for the element to be clickable (default: 10000).",
216
195
  },
217
- reason: {
218
- type: "string",
219
- description:
220
- "Brief non-technical explanation of what you are clicking and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
221
- },
222
196
  },
223
197
  },
224
198
  };
@@ -273,11 +247,6 @@ class BrowserTypeTool implements Tool {
273
247
  type: "boolean",
274
248
  description: "If true, press Enter after typing the text.",
275
249
  },
276
- reason: {
277
- type: "string",
278
- description:
279
- "Brief non-technical explanation of what you are typing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
280
- },
281
250
  },
282
251
  required: ["text"],
283
252
  },
@@ -323,11 +292,6 @@ class BrowserPressKeyTool implements Tool {
323
292
  type: "string",
324
293
  description: "Optional CSS selector to target.",
325
294
  },
326
- reason: {
327
- type: "string",
328
- description:
329
- "Brief non-technical explanation of what you are doing and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
330
- },
331
295
  },
332
296
  required: ["key"],
333
297
  },
@@ -378,11 +342,6 @@ class BrowserScrollTool implements Tool {
378
342
  type: "string",
379
343
  description: "Optional CSS selector of element to scroll within.",
380
344
  },
381
- reason: {
382
- type: "string",
383
- description:
384
- "Brief non-technical explanation of what you are scrolling to see and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
385
- },
386
345
  },
387
346
  required: ["direction"],
388
347
  },
@@ -437,11 +396,6 @@ class BrowserSelectOptionTool implements Tool {
437
396
  type: "number",
438
397
  description: "The zero-based index of the <option> to select.",
439
398
  },
440
- reason: {
441
- type: "string",
442
- description:
443
- "Brief non-technical explanation of what you are selecting and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
444
- },
445
399
  },
446
400
  },
447
401
  };
@@ -483,11 +437,6 @@ class BrowserHoverTool implements Tool {
483
437
  description:
484
438
  "A CSS selector to target. Used as fallback when element_id is not available.",
485
439
  },
486
- reason: {
487
- type: "string",
488
- description:
489
- "Brief non-technical explanation of what you are hovering over and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
490
- },
491
440
  },
492
441
  },
493
442
  };
@@ -537,11 +486,6 @@ class BrowserWaitForTool implements Tool {
537
486
  description:
538
487
  "Maximum wait time in milliseconds (default and max: 30000).",
539
488
  },
540
- reason: {
541
- type: "string",
542
- description:
543
- "Brief non-technical explanation of what you are waiting for and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
544
- },
545
489
  },
546
490
  },
547
491
  };
@@ -578,11 +522,6 @@ class BrowserExtractTool implements Tool {
578
522
  description:
579
523
  "If true, include a list of links found on the page (up to 200).",
580
524
  },
581
- reason: {
582
- type: "string",
583
- description:
584
- "Brief non-technical explanation of what you are extracting and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
585
- },
586
525
  },
587
526
  },
588
527
  };
@@ -634,11 +573,6 @@ class BrowserFillCredentialTool implements Tool {
634
573
  type: "boolean",
635
574
  description: "Press Enter after filling",
636
575
  },
637
- reason: {
638
- type: "string",
639
- description:
640
- "Brief non-technical explanation of what you are filling in and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
641
- },
642
576
  },
643
577
  required: ["service", "field"],
644
578
  },
@@ -1,5 +1,5 @@
1
1
  /**
2
- * CDP Network recorder for Ride Shotgun "learn" mode.
2
+ * CDP Network recorder.
3
3
  *
4
4
  * Connects directly to Chrome's CDP WebSocket endpoint to record
5
5
  * Network.* events across all tabs the user browses.
@@ -1,4 +1,4 @@
1
- /** Types for CDP network recording used by Ride Shotgun "learn" mode. */
1
+ /** Types for CDP network recording. */
2
2
 
3
3
  export interface NetworkRecordedRequest {
4
4
  method: string;
@@ -123,11 +123,6 @@ export const claudeCodeTool: Tool = {
123
123
  description:
124
124
  "Worker profile that scopes tool access. Defaults to general (backward compatible).",
125
125
  },
126
- reason: {
127
- type: "string",
128
- description:
129
- "Brief non-technical explanation of what you are delegating and why, shown to the user as a status update. Use simple language a non-technical person would understand.",
130
- },
131
126
  },
132
127
  },
133
128
  };
@@ -34,7 +34,7 @@ const reasonProperty = {
34
34
  export const computerUseClickTool: Tool = {
35
35
  name: "computer_use_click",
36
36
  description:
37
- "Click on a UI element by its [ID] from the accessibility tree, or at raw screen coordinates as fallback. Supports single click, double-click, and right-click via the click_type parameter.",
37
+ "Click an element on screen. Prefer element_id (from the accessibility tree) over x/y coordinates.",
38
38
  category: "computer-use",
39
39
  defaultRiskLevel: RiskLevel.Low,
40
40
  executionMode: "proxy",
@@ -86,7 +86,7 @@ export const computerUseClickTool: Tool = {
86
86
  export const computerUseTypeTextTool: Tool = {
87
87
  name: "computer_use_type_text",
88
88
  description:
89
- "Type text at the current cursor position. The target field must already be focused (click it first).",
89
+ "Type text at the current cursor position. First click a text field (by element_id) to focus it, then call this tool. If a field shows 'FOCUSED', skip the click.",
90
90
  category: "computer-use",
91
91
  defaultRiskLevel: RiskLevel.Low,
92
92
  executionMode: "proxy",
@@ -352,13 +352,7 @@ export const computerUseOpenAppTool: Tool = {
352
352
  export const computerUseRunAppleScriptTool: Tool = {
353
353
  name: "computer_use_run_applescript",
354
354
  description:
355
- "Execute an AppleScript to control applications via Apple's scripting bridge. " +
356
- "Use this for operations that are more reliable through scripting than UI interaction: " +
357
- "setting a browser URL directly, navigating Finder to a path, querying app state " +
358
- "(tab count, window titles, document status), or clicking deeply nested menu items. " +
359
- "The script's return value (if any) will be reported back. " +
360
- 'NEVER use "do shell script" — it is blocked for security. ' +
361
- "Keep scripts short and targeted to a single operation.",
355
+ "Run an AppleScript command. Prefer this over click/type when possible — it doesn't move the cursor or interrupt the user. Never use 'do shell script' inside AppleScript (blocked for security).",
362
356
  category: "computer-use",
363
357
  defaultRiskLevel: RiskLevel.Low,
364
358
  executionMode: "proxy",
@@ -395,7 +389,8 @@ export const computerUseRunAppleScriptTool: Tool = {
395
389
 
396
390
  export const computerUseDoneTool: Tool = {
397
391
  name: "computer_use_done",
398
- description: "Task is complete",
392
+ description:
393
+ "Signal that the computer use task is complete. Provide a summary of what was accomplished. This ends the computer use session.",
399
394
  category: "computer-use",
400
395
  defaultRiskLevel: RiskLevel.Low,
401
396
  executionMode: "proxy",
@@ -428,7 +423,7 @@ export const computerUseDoneTool: Tool = {
428
423
  export const computerUseRespondTool: Tool = {
429
424
  name: "computer_use_respond",
430
425
  description:
431
- "Respond directly to the user with a text answer. Use this when the user is asking a question (about their schedule, meetings, calendar, etc.) rather than asking you to control the computer.",
426
+ "Respond to the user with a text answer instead of performing computer actions. Use this when you can answer directly without interacting with the screen.",
432
427
  category: "computer-use",
433
428
  defaultRiskLevel: RiskLevel.Low,
434
429
  executionMode: "proxy",
@@ -458,11 +453,41 @@ export const computerUseRespondTool: Tool = {
458
453
  execute: proxyExecute,
459
454
  };
460
455
 
456
+ // ---------------------------------------------------------------------------
457
+ // observe
458
+ // ---------------------------------------------------------------------------
459
+
460
+ export const computerUseObserveTool: Tool = {
461
+ name: "computer_use_observe",
462
+ description:
463
+ "Capture the current screen state. Returns the accessibility tree with [ID] element references and optionally a screenshot.\n\nThe accessibility tree shows interactive elements like [3] AXButton 'Save' or [17] AXTextField 'Search'. Use element_id to target these elements in subsequent actions — this is much more reliable than pixel coordinates.\n\nCall this before your first computer use action, or to check screen state without acting.",
464
+ category: "computer-use",
465
+ defaultRiskLevel: RiskLevel.Low,
466
+ executionMode: "proxy",
467
+
468
+ getDefinition(): ToolDefinition {
469
+ return {
470
+ name: this.name,
471
+ description: this.description,
472
+ input_schema: {
473
+ type: "object",
474
+ properties: {
475
+ reason: reasonProperty,
476
+ },
477
+ required: ["reason"],
478
+ },
479
+ };
480
+ },
481
+
482
+ execute: proxyExecute,
483
+ };
484
+
461
485
  // ---------------------------------------------------------------------------
462
486
  // All tools exported as array for convenience
463
487
  // ---------------------------------------------------------------------------
464
488
 
465
489
  export const allComputerUseTools: Tool[] = [
490
+ computerUseObserveTool,
466
491
  computerUseClickTool,
467
492
  computerUseTypeTextTool,
468
493
  computerUseKeyTool,
@@ -474,3 +499,13 @@ export const allComputerUseTools: Tool[] = [
474
499
  computerUseDoneTool,
475
500
  computerUseRespondTool,
476
501
  ];
502
+
503
+ /**
504
+ * Tools safe for the legacy fallback path (no skill projection).
505
+ *
506
+ * Excludes `computer_use_observe` because the macOS client doesn't handle it
507
+ * in the legacy code path — it falls back to `.done` which skips sending an
508
+ * observation, causing the daemon to block on `pendingObservation` until timeout.
509
+ */
510
+ export const legacyFallbackComputerUseTools: Tool[] =
511
+ allComputerUseTools.filter((t) => t.name !== "computer_use_observe");
@@ -1,11 +1,10 @@
1
1
  /**
2
2
  * Registers computer-use tools with the daemon's tool registry.
3
3
  *
4
- * The 12 computer_use_* action tools and the computer_use_request_control
5
- * escalation tool are now provided by the bundled computer-use skill.
6
- * This module retains registerComputerUseActionTools() for backward
7
- * compatibility (used by tests), but it is no longer called during
8
- * normal startup.
4
+ * The computer_use_* action tools are now provided by the bundled
5
+ * computer-use skill. This module retains registerComputerUseActionTools()
6
+ * for backward compatibility (used by tests), but it is no longer called
7
+ * during normal startup.
9
8
  */
10
9
 
11
10
  import { registerTool } from "../registry.js";
@@ -1,5 +1,6 @@
1
1
  import { v4 as uuid } from "uuid";
2
2
 
3
+ import { credentialKey } from "../../security/credential-key.js";
3
4
  import { getSecureKey } from "../../security/secure-keys.js";
4
5
  import { getLogger } from "../../util/logger.js";
5
6
  import type {
@@ -46,7 +47,7 @@ export class CredentialBroker {
46
47
  * browserFill or consume call for this service/field pair, then discarded.
47
48
  */
48
49
  injectTransient(service: string, field: string, value: string): void {
49
- const key = `credential:${service}:${field}`;
50
+ const key = credentialKey(service, field);
50
51
  this.transientValues.set(key, { value });
51
52
  log.info(
52
53
  { service, field },
@@ -123,7 +124,7 @@ export class CredentialBroker {
123
124
  }
124
125
 
125
126
  token.consumed = true;
126
- const storageKey = `credential:${token.service}:${token.field}`;
127
+ const storageKey = credentialKey(token.service, token.field);
127
128
  // Check for transient value first (one-time send) — consume and return the value
128
129
  // directly since transient values are never persisted to secure storage.
129
130
  const transient = this.transientValues.get(storageKey);
@@ -211,7 +212,7 @@ export class CredentialBroker {
211
212
  }
212
213
  }
213
214
 
214
- const storageKey = `credential:${request.service}:${request.field}`;
215
+ const storageKey = credentialKey(request.service, request.field);
215
216
  // Check transient values first (one-time send), then fall back to keychain.
216
217
  // Deletion is deferred until after a successful fill so the value survives
217
218
  // transient failures (e.g. stale element, page navigation, Playwright timeout).
@@ -299,7 +300,7 @@ export class CredentialBroker {
299
300
  };
300
301
  }
301
302
 
302
- const storageKey = `credential:${request.service}:${request.field}`;
303
+ const storageKey = credentialKey(request.service, request.field);
303
304
  const transient = this.transientValues.get(storageKey);
304
305
  const value = transient?.value ?? getSecureKey(storageKey);
305
306
  if (!value) {
@@ -4,6 +4,11 @@
4
4
  * Persists non-secret metadata about credentials (policy, timestamps, IDs)
5
5
  * in a versioned JSON file under protected storage. Secret values remain
6
6
  * in the secure key backend only.
7
+ *
8
+ * OAuth-specific fields (expiresAt, grantedScopes, oauth2TokenUrl,
9
+ * oauth2ClientId, oauth2TokenEndpointAuthMethod, hasRefreshToken) are now
10
+ * exclusively managed by the SQLite oauth-store and have been removed
11
+ * from this interface as of v5.
7
12
  */
8
13
 
9
14
  import { randomUUID } from "node:crypto";
@@ -21,16 +26,6 @@ export interface CredentialMetadata {
21
26
  allowedTools: string[];
22
27
  allowedDomains: string[];
23
28
  usageDescription?: string;
24
- expiresAt?: number;
25
- grantedScopes?: string[];
26
- /** OAuth2 token endpoint — enables autonomous token refresh without an IntegrationDefinition. */
27
- oauth2TokenUrl?: string;
28
- /** OAuth2 client ID — paired with oauth2TokenUrl for refresh. */
29
- oauth2ClientId?: string;
30
- /** OAuth2 client secret — for providers that require it (e.g. Slack). Stored in metadata for autonomous refresh. */
31
- oauth2ClientSecret?: string;
32
- /** How the client authenticates at the token endpoint (client_secret_basic or client_secret_post). */
33
- oauth2TokenEndpointAuthMethod?: string;
34
29
  /** Human-friendly name for this credential (e.g. "fal-primary"). */
35
30
  alias?: string;
36
31
  /** Templates describing how to inject this credential into proxied requests. */
@@ -40,7 +35,7 @@ export interface CredentialMetadata {
40
35
  }
41
36
 
42
37
  /** Current on-disk schema version. */
43
- const CURRENT_VERSION = 2;
38
+ const CURRENT_VERSION = 5;
44
39
 
45
40
  interface MetadataFile {
46
41
  version: typeof CURRENT_VERSION;
@@ -88,9 +83,10 @@ function isValidCredentialRecord(
88
83
  }
89
84
 
90
85
  /**
91
- * Migrate a v1 record to v2 by backfilling new optional fields with defaults.
86
+ * Migrate any record to v5 by stripping OAuth-specific fields that are
87
+ * now exclusively managed by the SQLite oauth-store.
92
88
  */
93
- function migrateRecordV1toV2(
89
+ function migrateRecordToV5(
94
90
  record: Record<string, unknown>,
95
91
  ): CredentialMetadata {
96
92
  return {
@@ -107,27 +103,6 @@ function migrateRecordV1toV2(
107
103
  typeof record.usageDescription === "string"
108
104
  ? record.usageDescription
109
105
  : undefined,
110
- expiresAt:
111
- typeof record.expiresAt === "number" ? record.expiresAt : undefined,
112
- grantedScopes: Array.isArray(record.grantedScopes)
113
- ? (record.grantedScopes as string[])
114
- : undefined,
115
- oauth2TokenUrl:
116
- typeof record.oauth2TokenUrl === "string"
117
- ? record.oauth2TokenUrl
118
- : undefined,
119
- oauth2ClientId:
120
- typeof record.oauth2ClientId === "string"
121
- ? record.oauth2ClientId
122
- : undefined,
123
- oauth2ClientSecret:
124
- typeof record.oauth2ClientSecret === "string"
125
- ? record.oauth2ClientSecret
126
- : undefined,
127
- oauth2TokenEndpointAuthMethod:
128
- typeof record.oauth2TokenEndpointAuthMethod === "string"
129
- ? record.oauth2TokenEndpointAuthMethod
130
- : undefined,
131
106
  alias: typeof record.alias === "string" ? record.alias : undefined,
132
107
  injectionTemplates: Array.isArray(record.injectionTemplates)
133
108
  ? (record.injectionTemplates as CredentialInjectionTemplate[])
@@ -148,7 +123,13 @@ function loadFile(): LoadResult {
148
123
  return { version: CURRENT_VERSION, credentials: [] };
149
124
  }
150
125
  const fileVersion = typeof data.version === "number" ? data.version : 1;
151
- if (fileVersion !== 1 && fileVersion !== 2) {
126
+ if (
127
+ fileVersion !== 1 &&
128
+ fileVersion !== 2 &&
129
+ fileVersion !== 3 &&
130
+ fileVersion !== 4 &&
131
+ fileVersion !== 5
132
+ ) {
152
133
  // Unrecognized version (future, fractional, negative, zero) — refuse to touch it
153
134
  return { unknownVersion: true };
154
135
  }
@@ -159,8 +140,12 @@ function loadFile(): LoadResult {
159
140
  const validRecords = rawCredentials.filter(isValidCredentialRecord);
160
141
 
161
142
  if (fileVersion < CURRENT_VERSION) {
162
- // Migrate from v1 to v2 and persist the upgrade so we don't re-migrate on every read
163
- const credentials = validRecords.map(migrateRecordV1toV2);
143
+ // Migrate all older versions to v5 by stripping OAuth-specific fields
144
+ // and removing ghost refresh_token records
145
+ const filtered = validRecords.filter(
146
+ (r) => (r as Record<string, unknown>).field !== "refresh_token",
147
+ );
148
+ const credentials = filtered.map(migrateRecordToV5);
164
149
  const migrated: MetadataFile = { version: CURRENT_VERSION, credentials };
165
150
  try {
166
151
  saveFile(migrated);
@@ -214,14 +199,6 @@ export function upsertCredentialMetadata(
214
199
  allowedTools?: string[];
215
200
  allowedDomains?: string[];
216
201
  usageDescription?: string;
217
- /** Pass `null` to explicitly clear a previously-set expiry. */
218
- expiresAt?: number | null;
219
- grantedScopes?: string[];
220
- oauth2TokenUrl?: string;
221
- oauth2ClientId?: string;
222
- /** Pass `null` to explicitly clear a previously-set client secret. */
223
- oauth2ClientSecret?: string | null;
224
- oauth2TokenEndpointAuthMethod?: string;
225
202
  /** Pass `null` to explicitly clear a previously-set alias. */
226
203
  alias?: string | null;
227
204
  /** Pass `null` to explicitly clear injection templates. */
@@ -248,29 +225,6 @@ export function upsertCredentialMetadata(
248
225
  existing.allowedDomains = policy.allowedDomains;
249
226
  if (policy?.usageDescription !== undefined)
250
227
  existing.usageDescription = policy.usageDescription;
251
- if (policy?.expiresAt !== undefined) {
252
- if (policy.expiresAt == null) {
253
- delete existing.expiresAt;
254
- } else {
255
- existing.expiresAt = policy.expiresAt;
256
- }
257
- }
258
- if (policy?.grantedScopes !== undefined)
259
- existing.grantedScopes = policy.grantedScopes;
260
- if (policy?.oauth2TokenUrl !== undefined)
261
- existing.oauth2TokenUrl = policy.oauth2TokenUrl;
262
- if (policy?.oauth2ClientId !== undefined)
263
- existing.oauth2ClientId = policy.oauth2ClientId;
264
- if (policy?.oauth2ClientSecret !== undefined) {
265
- if (policy.oauth2ClientSecret == null) {
266
- delete existing.oauth2ClientSecret;
267
- } else {
268
- existing.oauth2ClientSecret = policy.oauth2ClientSecret;
269
- }
270
- }
271
- if (policy?.oauth2TokenEndpointAuthMethod !== undefined)
272
- existing.oauth2TokenEndpointAuthMethod =
273
- policy.oauth2TokenEndpointAuthMethod;
274
228
  if (policy?.alias !== undefined) {
275
229
  if (policy.alias == null) {
276
230
  delete existing.alias;
@@ -297,12 +251,6 @@ export function upsertCredentialMetadata(
297
251
  allowedTools: policy?.allowedTools ?? [],
298
252
  allowedDomains: policy?.allowedDomains ?? [],
299
253
  usageDescription: policy?.usageDescription,
300
- expiresAt: policy?.expiresAt ?? undefined,
301
- grantedScopes: policy?.grantedScopes,
302
- oauth2TokenUrl: policy?.oauth2TokenUrl,
303
- oauth2ClientId: policy?.oauth2ClientId,
304
- oauth2ClientSecret: policy?.oauth2ClientSecret ?? undefined,
305
- oauth2TokenEndpointAuthMethod: policy?.oauth2TokenEndpointAuthMethod,
306
254
  alias: policy?.alias ?? undefined,
307
255
  injectionTemplates: policy?.injectionTemplates ?? undefined,
308
256
  createdAt: now,
@@ -6,6 +6,7 @@
6
6
  * secure key naming convention.
7
7
  */
8
8
 
9
+ import { credentialKey } from "../../security/credential-key.js";
9
10
  import { matchHostPattern } from "./host-pattern-match.js";
10
11
  import {
11
12
  type CredentialMetadata,
@@ -33,7 +34,7 @@ function toResolved(metadata: CredentialMetadata): ResolvedCredential {
33
34
  credentialId: metadata.credentialId,
34
35
  service: metadata.service,
35
36
  field: metadata.field,
36
- storageKey: `credential:${metadata.service}:${metadata.field}`,
37
+ storageKey: credentialKey(metadata.service, metadata.field),
37
38
  alias: metadata.alias,
38
39
  injectionTemplates: metadata.injectionTemplates ?? [],
39
40
  metadata,