@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
@@ -112,9 +112,11 @@ mock.module("../calls/twilio-provider.js", () => ({
112
112
  },
113
113
  }));
114
114
 
115
+ import { credentialKey } from "../security/credential-key.js";
116
+
115
117
  const secureKeyStore: Record<string, string | undefined> = {
116
- "credential:twilio:account_sid": "AC_test",
117
- "credential:twilio:auth_token": "test_token",
118
+ [credentialKey("twilio", "account_sid")]: "AC_test",
119
+ [credentialKey("twilio", "auth_token")]: "test_token",
118
120
  };
119
121
 
120
122
  mock.module("../security/secure-keys.js", () => ({
@@ -37,7 +37,6 @@ const ALLOWLIST = new Set([
37
37
  // --- Documentation and comments that mention the port for explanatory purposes ---
38
38
  "AGENTS.md", // documents the gateway-only rule itself
39
39
  "ARCHITECTURE.md", // architecture overview with port references
40
- "assistant/docs/runbook-trusted-contacts.md", // operator runbook targeting runtime-only /v1/contacts endpoints
41
40
  "assistant/src/runtime/middleware/twilio-validation.ts", // comment explaining proxy URL rewriting
42
41
  ]);
43
42
 
@@ -100,10 +100,13 @@ describe("generateImage", () => {
100
100
  test("generate mode returns images from response parts", async () => {
101
101
  fakeResponse = imageResponse("image/png", "abc123");
102
102
 
103
- const result = await generateImage("test-key", {
104
- prompt: "a cat",
105
- mode: "generate",
106
- });
103
+ const result = await generateImage(
104
+ { type: "direct", apiKey: "test-key" },
105
+ {
106
+ prompt: "a cat",
107
+ mode: "generate",
108
+ },
109
+ );
107
110
 
108
111
  expect(result.images).toHaveLength(1);
109
112
  expect(result.images[0].mimeType).toBe("image/png");
@@ -114,10 +117,13 @@ describe("generateImage", () => {
114
117
  test("generate mode collects text commentary from response", async () => {
115
118
  fakeResponse = imageWithTextResponse("Here is your image");
116
119
 
117
- const result = await generateImage("test-key", {
118
- prompt: "a dog",
119
- mode: "generate",
120
- });
120
+ const result = await generateImage(
121
+ { type: "direct", apiKey: "test-key" },
122
+ {
123
+ prompt: "a dog",
124
+ mode: "generate",
125
+ },
126
+ );
121
127
 
122
128
  expect(result.text).toBe("Here is your image");
123
129
  expect(result.images).toHaveLength(1);
@@ -126,11 +132,14 @@ describe("generateImage", () => {
126
132
  test("edit mode passes source images as inline data", async () => {
127
133
  fakeResponse = imageResponse();
128
134
 
129
- await generateImage("test-key", {
130
- prompt: "remove background",
131
- mode: "edit",
132
- sourceImages: [{ mimeType: "image/jpeg", dataBase64: "srcdata" }],
133
- });
135
+ await generateImage(
136
+ { type: "direct", apiKey: "test-key" },
137
+ {
138
+ prompt: "remove background",
139
+ mode: "edit",
140
+ sourceImages: [{ mimeType: "image/jpeg", dataBase64: "srcdata" }],
141
+ },
142
+ );
134
143
 
135
144
  expect(lastGenerateParams).not.toBeNull();
136
145
  const contents = (lastGenerateParams as Record<string, unknown>)
@@ -148,11 +157,14 @@ describe("generateImage", () => {
148
157
  test("model validation rejects unknown models and defaults", async () => {
149
158
  fakeResponse = imageResponse();
150
159
 
151
- await generateImage("test-key", {
152
- prompt: "test",
153
- mode: "generate",
154
- model: "invalid-model",
155
- });
160
+ await generateImage(
161
+ { type: "direct", apiKey: "test-key" },
162
+ {
163
+ prompt: "test",
164
+ mode: "generate",
165
+ model: "invalid-model",
166
+ },
167
+ );
156
168
 
157
169
  expect(lastGenerateParams).not.toBeNull();
158
170
  expect((lastGenerateParams as Record<string, unknown>).model).toBe(
@@ -163,11 +175,14 @@ describe("generateImage", () => {
163
175
  test("model validation accepts allowed models", async () => {
164
176
  fakeResponse = imageResponse();
165
177
 
166
- await generateImage("test-key", {
167
- prompt: "test",
168
- mode: "generate",
169
- model: "gemini-3-pro-image",
170
- });
178
+ await generateImage(
179
+ { type: "direct", apiKey: "test-key" },
180
+ {
181
+ prompt: "test",
182
+ mode: "generate",
183
+ model: "gemini-3-pro-image",
184
+ },
185
+ );
171
186
 
172
187
  expect((lastGenerateParams as Record<string, unknown>).model).toBe(
173
188
  "gemini-3-pro-image",
@@ -177,11 +192,14 @@ describe("generateImage", () => {
177
192
  test("variants makes parallel calls", async () => {
178
193
  fakeResponse = imageResponse();
179
194
 
180
- const result = await generateImage("test-key", {
181
- prompt: "test",
182
- mode: "generate",
183
- variants: 3,
184
- });
195
+ const result = await generateImage(
196
+ { type: "direct", apiKey: "test-key" },
197
+ {
198
+ prompt: "test",
199
+ mode: "generate",
200
+ variants: 3,
201
+ },
202
+ );
185
203
 
186
204
  expect(generateCallCount).toBe(3);
187
205
  expect(result.images).toHaveLength(3);
@@ -190,11 +208,14 @@ describe("generateImage", () => {
190
208
  test("variants are clamped to 1-4", async () => {
191
209
  fakeResponse = imageResponse();
192
210
 
193
- await generateImage("test-key", {
194
- prompt: "test",
195
- mode: "generate",
196
- variants: 10,
197
- });
211
+ await generateImage(
212
+ { type: "direct", apiKey: "test-key" },
213
+ {
214
+ prompt: "test",
215
+ mode: "generate",
216
+ variants: 10,
217
+ },
218
+ );
198
219
 
199
220
  expect(generateCallCount).toBe(4);
200
221
  });
@@ -202,10 +223,13 @@ describe("generateImage", () => {
202
223
  test("variants defaults to 1", async () => {
203
224
  fakeResponse = imageResponse();
204
225
 
205
- await generateImage("test-key", {
206
- prompt: "test",
207
- mode: "generate",
208
- });
226
+ await generateImage(
227
+ { type: "direct", apiKey: "test-key" },
228
+ {
229
+ prompt: "test",
230
+ mode: "generate",
231
+ },
232
+ );
209
233
 
210
234
  expect(generateCallCount).toBe(1);
211
235
  });
@@ -213,10 +237,13 @@ describe("generateImage", () => {
213
237
  test("handles empty candidates gracefully", async () => {
214
238
  fakeResponse = { candidates: [] };
215
239
 
216
- const result = await generateImage("test-key", {
217
- prompt: "test",
218
- mode: "generate",
219
- });
240
+ const result = await generateImage(
241
+ { type: "direct", apiKey: "test-key" },
242
+ {
243
+ prompt: "test",
244
+ mode: "generate",
245
+ },
246
+ );
220
247
 
221
248
  expect(result.images).toHaveLength(0);
222
249
  expect(result.text).toBeUndefined();
@@ -225,10 +252,13 @@ describe("generateImage", () => {
225
252
  test("response config includes TEXT and IMAGE modalities", async () => {
226
253
  fakeResponse = imageResponse();
227
254
 
228
- await generateImage("test-key", {
229
- prompt: "test",
230
- mode: "generate",
231
- });
255
+ await generateImage(
256
+ { type: "direct", apiKey: "test-key" },
257
+ {
258
+ prompt: "test",
259
+ mode: "generate",
260
+ },
261
+ );
232
262
 
233
263
  const config = (lastGenerateParams as Record<string, unknown>)
234
264
  .config as Record<string, unknown>;
@@ -739,14 +739,17 @@ describe("GeminiProvider", () => {
739
739
  expect(lastConstructorOpts).toEqual({ apiKey: "test-key" });
740
740
  });
741
741
 
742
- test("sets httpOptions.baseUrl when managedBaseUrl is provided", () => {
742
+ test("sets vertexai mode with httpOptions.baseUrl when managedBaseUrl is provided", () => {
743
743
  new GeminiProvider("managed-key", "gemini-3-flash", {
744
- managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/gemini",
744
+ managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/vertex",
745
745
  });
746
746
  expect(lastConstructorOpts).toEqual({
747
- apiKey: "managed-key",
747
+ vertexai: true,
748
+ project: "proxy",
749
+ location: "us-central1",
748
750
  httpOptions: {
749
- baseUrl: "https://platform.example.com/v1/runtime-proxy/gemini",
751
+ baseUrl: "https://platform.example.com/v1/runtime-proxy/vertex",
752
+ headers: { Authorization: "Bearer managed-key" },
750
753
  },
751
754
  });
752
755
  });
@@ -756,7 +759,7 @@ describe("GeminiProvider", () => {
756
759
  "managed-key",
757
760
  "gemini-3-flash",
758
761
  {
759
- managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/gemini",
762
+ managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/vertex",
760
763
  },
761
764
  );
762
765
 
@@ -781,7 +784,7 @@ describe("GeminiProvider", () => {
781
784
  "managed-key",
782
785
  "gemini-3-flash",
783
786
  {
784
- managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/gemini",
787
+ managedBaseUrl: "https://platform.example.com/v1/runtime-proxy/vertex",
785
788
  },
786
789
  );
787
790
 
@@ -181,25 +181,6 @@ describe("guardian-action-conversation-turn", () => {
181
181
  expect(result.replyText).toBe("Sure, I'll call them back right away.");
182
182
  });
183
183
 
184
- test('classifies "send a text message" as message_back', async () => {
185
- const generator = createMockGenerator({
186
- disposition: "message_back",
187
- replyText: "Got it, I'll send them a text message.",
188
- });
189
-
190
- const result = await processGuardianFollowUpTurn(
191
- {
192
- questionText: "What is the gate code?",
193
- lateAnswerText: "The gate code is 1234",
194
- guardianReply: "Just send them a text",
195
- },
196
- generator,
197
- );
198
-
199
- expect(result.disposition).toBe("message_back");
200
- expect(result.replyText).toBe("Got it, I'll send them a text message.");
201
- });
202
-
203
184
  test('classifies "never mind" as decline', async () => {
204
185
  const generator = createMockGenerator({
205
186
  disposition: "decline",
@@ -448,19 +429,6 @@ describe("guardian-action-conversation-turn", () => {
448
429
  expect(updated!.followupAction).toBe("call_back");
449
430
  });
450
431
 
451
- test("message_back disposition transitions to dispatching with message_back action", () => {
452
- const { request } = createAwaitingChoiceRequest("conv-turn-7");
453
-
454
- const updated = progressFollowupState(
455
- request.id,
456
- "dispatching",
457
- "message_back",
458
- );
459
- expect(updated).not.toBeNull();
460
- expect(updated!.followupState).toBe("dispatching");
461
- expect(updated!.followupAction).toBe("message_back");
462
- });
463
-
464
432
  test("decline disposition finalizes to declined", () => {
465
433
  const { request } = createAwaitingChoiceRequest("conv-turn-8");
466
434
 
@@ -488,7 +456,7 @@ describe("guardian-action-conversation-turn", () => {
488
456
  const second = progressFollowupState(
489
457
  request.id,
490
458
  "dispatching",
491
- "message_back",
459
+ "call_back",
492
460
  );
493
461
  expect(second).toBeNull();
494
462
 
@@ -33,8 +33,6 @@ const ALL_SCENARIOS: GuardianActionMessageScenario[] = [
33
33
  "guardian_superseded_remap",
34
34
  "guardian_unknown_code",
35
35
  "guardian_auto_matched",
36
- "outbound_message_copy",
37
- "followup_message_sent",
38
36
  "followup_call_started",
39
37
  "followup_action_failed",
40
38
  "guardian_answer_delivery_failed",
@@ -110,24 +108,6 @@ describe("guardian-action-copy-generator", () => {
110
108
  });
111
109
  expect(msg).toContain("QFOO12");
112
110
  });
113
-
114
- test("outbound_message_copy includes lateAnswerText and questionText", () => {
115
- const msg = getGuardianActionFallbackMessage({
116
- scenario: "outbound_message_copy",
117
- questionText: "When is the appointment?",
118
- lateAnswerText: "It is at 3pm tomorrow.",
119
- });
120
- expect(msg).toContain("When is the appointment?");
121
- expect(msg).toContain("It is at 3pm tomorrow.");
122
- });
123
-
124
- test("outbound_message_copy without lateAnswerText still includes questionText", () => {
125
- const msg = getGuardianActionFallbackMessage({
126
- scenario: "outbound_message_copy",
127
- questionText: "Is the office open?",
128
- });
129
- expect(msg).toContain("Is the office open?");
130
- });
131
111
  });
132
112
 
133
113
  // -----------------------------------------------------------------------
@@ -127,10 +127,7 @@ function resetTables(): void {
127
127
  * Create a request in `dispatching` state ready for the executor.
128
128
  * The call session has fromNumber='+15550001111' (the counterparty).
129
129
  */
130
- function createDispatchingRequest(
131
- convId: string,
132
- action: "call_back" | "message_back",
133
- ) {
130
+ function createDispatchingRequest(convId: string, action: "call_back") {
134
131
  ensureConversation(convId);
135
132
  const session = createCallSession({
136
133
  conversationId: convId,
@@ -284,30 +281,6 @@ describe("guardian-action-followup-executor", () => {
284
281
  });
285
282
  });
286
283
 
287
- // ── message_back (unsupported) error path ─────────────────────────────
288
-
289
- describe("message_back", () => {
290
- test("returns failure and finalizes as failed when message_back is dispatched", async () => {
291
- const { request } = createDispatchingRequest(
292
- "exec-msg-1",
293
- "message_back",
294
- );
295
-
296
- const result = await executeFollowupAction(request.id, "message_back");
297
-
298
- expect(result.ok).toBe(false);
299
- if (!result.ok) {
300
- expect(result.error).toContain("Unsupported action");
301
- expect(result.error).toContain("message_back");
302
- }
303
- expect(result.guardianReplyText.length).toBeGreaterThan(0);
304
-
305
- const updated = getGuardianActionRequest(request.id);
306
- expect(updated!.followupState).toBe("failed");
307
- expect(updated!.followupCompletedAt).toBeGreaterThan(0);
308
- });
309
- });
310
-
311
284
  // ── Error handling ──────────────────────────────────────────────────
312
285
 
313
286
  describe("error handling", () => {
@@ -314,7 +314,7 @@ describe("guardian-action-followup-store", () => {
314
314
  const request = createTestRequest("conv-followup-15");
315
315
  markTimedOutWithReason(request.id, "call_timeout");
316
316
  startFollowupFromExpiredRequest(request.id, "Late answer");
317
- progressFollowupState(request.id, "dispatching", "message_back");
317
+ progressFollowupState(request.id, "dispatching", "call_back");
318
318
 
319
319
  const result = finalizeFollowup(request.id, "failed");
320
320
  expect(result).not.toBeNull();
@@ -35,7 +35,6 @@ mock.module("../util/logger.js", () => ({
35
35
  new Proxy({} as Record<string, unknown>, {
36
36
  get: () => () => {},
37
37
  }),
38
- isDebug: () => false,
39
38
  truncateForLog: (value: string) => value,
40
39
  }));
41
40
 
@@ -21,7 +21,6 @@ mock.module("../util/logger.js", () => ({
21
21
  new Proxy({} as Record<string, unknown>, {
22
22
  get: () => () => {},
23
23
  }),
24
- isDebug: () => false,
25
24
  truncateForLog: (value: string) => value,
26
25
  }));
27
26
 
@@ -50,6 +50,7 @@ import type { TrustContext } from "../daemon/session-runtime-assembly.js";
50
50
  import { getDb, initializeDb, resetDb } from "../memory/db.js";
51
51
  import {
52
52
  createApprovalRequest,
53
+ getPendingApprovalForRequest,
53
54
  type GuardianApprovalRequest,
54
55
  } from "../memory/guardian-approvals.js";
55
56
  import * as approvalMessageComposer from "../runtime/approval-message-composer.js";
@@ -247,6 +248,40 @@ describe("guardian grant minting on tool-approval decisions", () => {
247
248
  composeSpy.mockRestore();
248
249
  });
249
250
 
251
+ test("guardian reaction approve_always is downgraded to one-time approval", async () => {
252
+ const requestId = "req-grant-reaction-1";
253
+ const approval = createTestGuardianApproval(requestId, {
254
+ conversationId: CONVERSATION_ID,
255
+ channel: "slack",
256
+ guardianChatId: GUARDIAN_CHAT,
257
+ });
258
+ const handleConfirmationResponse = registerPendingInteraction(
259
+ requestId,
260
+ CONVERSATION_ID,
261
+ TOOL_NAME,
262
+ TOOL_INPUT,
263
+ );
264
+
265
+ const result = await handleApprovalInterception({
266
+ conversationId: "guardian-conv-1",
267
+ callbackData: "reaction:white_check_mark",
268
+ content: "",
269
+ conversationExternalId: GUARDIAN_CHAT,
270
+ sourceChannel: "slack",
271
+ actorExternalId: GUARDIAN_USER,
272
+ replyCallbackUrl: "https://gateway.test/deliver",
273
+ trustCtx: makeTrustContext(),
274
+ assistantId: ASSISTANT_ID,
275
+ });
276
+
277
+ expect(result.handled).toBe(true);
278
+ expect(result.type).toBe("guardian_decision_applied");
279
+ expect(handleConfirmationResponse).toHaveBeenCalledWith(requestId, "allow");
280
+
281
+ const updatedApproval = getPendingApprovalForRequest(approval.requestId);
282
+ expect(updatedApproval).toBeNull();
283
+ });
284
+
250
285
  // ── 2. approve_once for non-tool-approval does NOT mint a grant ──
251
286
 
252
287
  test("approve_once for informational request (no toolName) does NOT mint a grant", async () => {
@@ -42,7 +42,6 @@ mock.module("../util/logger.js", () => ({
42
42
  new Proxy({} as Record<string, unknown>, {
43
43
  get: () => () => {},
44
44
  }),
45
- isDebug: () => false,
46
45
  truncateForLog: (value: string) => value,
47
46
  }));
48
47
 
@@ -57,7 +57,6 @@ mock.module("../security/secure-keys.js", () => ({
57
57
 
58
58
  mock.module("../config/env.js", () => ({
59
59
  isHttpAuthDisabled: () => true,
60
- getTwilioUserPhoneNumber: () => null,
61
60
  }));
62
61
 
63
62
  mock.module("../inbound/public-ingress-urls.js", () => ({
@@ -147,7 +147,6 @@ import { handleConfirmationResponse } from "../daemon/handlers/sessions.js";
147
147
 
148
148
  interface TestSession {
149
149
  messages: Array<{ role: string; content: unknown[] }>;
150
- hasEscalationHandler: () => boolean;
151
150
  setChannelCapabilities: (caps: unknown) => void;
152
151
  isProcessing: () => boolean;
153
152
  hasPendingConfirmation: (requestId: string) => boolean;
@@ -181,8 +180,6 @@ function createContext(session: TestSession): {
181
180
  const sent: ServerMessage[] = [];
182
181
  const ctx: HandlerContext = {
183
182
  sessions: new Map(),
184
- cuSessions: new Map(),
185
- cuObservationParseSequence: new Map(),
186
183
  sharedRequestTimestamps: [],
187
184
  debounceTimers: new DebouncerMap({ defaultDelayMs: 100 }),
188
185
  suppressConfigReload: false,
@@ -202,7 +199,6 @@ function createContext(session: TestSession): {
202
199
  function makeSession(overrides: Partial<TestSession> = {}): TestSession {
203
200
  return {
204
201
  messages: [],
205
- hasEscalationHandler: () => true,
206
202
  setChannelCapabilities: () => {},
207
203
  isProcessing: () => false,
208
204
  hasPendingConfirmation: () => true,
@@ -277,39 +273,4 @@ describe("handleConfirmationResponse canonical status sync", () => {
277
273
  );
278
274
  expect(resolveMock).toHaveBeenCalledWith("req-confirm-allow");
279
275
  });
280
-
281
- test("syncs canonical status to denied for deny decisions in CU sessions", () => {
282
- const cuSession = {
283
- hasPendingConfirmation: (requestId: string) =>
284
- requestId === "req-confirm-deny",
285
- handleConfirmationResponse: mock(() => {}),
286
- };
287
- const { ctx } = createContext(
288
- makeSession({
289
- hasPendingConfirmation: () => false,
290
- }),
291
- );
292
- ctx.cuSessions.set("cu-1", cuSession as any);
293
-
294
- const msg: ConfirmationResponse = {
295
- type: "confirmation_response",
296
- requestId: "req-confirm-deny",
297
- decision: "always_deny",
298
- };
299
-
300
- handleConfirmationResponse(msg, ctx);
301
-
302
- expect(
303
- (cuSession.handleConfirmationResponse as any).mock.calls.length,
304
- ).toBe(1);
305
- expect((cuSession.handleConfirmationResponse as any).mock.calls[0]).toEqual(
306
- ["req-confirm-deny", "always_deny", undefined, undefined],
307
- );
308
- expect(resolveCanonicalGuardianRequestMock).toHaveBeenCalledWith(
309
- "req-confirm-deny",
310
- "pending",
311
- { status: "denied" },
312
- );
313
- expect(resolveMock).toHaveBeenCalledWith("req-confirm-deny");
314
- });
315
276
  });
@@ -67,7 +67,6 @@ mock.module("../util/logger.js", () => ({
67
67
  warn: () => {},
68
68
  error: () => {},
69
69
  }),
70
- isDebug: () => false,
71
70
  }));
72
71
 
73
72
  // Mock conversation title service