@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,129 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { join } from "node:path";
3
-
4
- import type { Command } from "commander";
5
-
6
- import { getDaemonStatus, stopDaemon } from "../../daemon/lifecycle.js";
7
- import { log } from "../logger.js";
8
-
9
- export function registerDevCommand(program: Command): void {
10
- program
11
- .command("dev")
12
- .description("Run the assistant in dev mode")
13
- .option(
14
- "--watch",
15
- "Auto-restart on source file changes (disruptive during Claude Code sessions)",
16
- )
17
- .addHelpText(
18
- "after",
19
- `
20
- Starts the assistant in foreground dev mode for local development. If an
21
- existing assistant is running, it is stopped first (waits up to 5 seconds
22
- for an unresponsive assistant before force-killing it).
23
-
24
- Behavioral notes:
25
- - Sets VELLUM_DEBUG=1 for DEBUG-level logging
26
- - Sets VELLUM_LOG_STDERR=1 so logs stream to stderr (visible in terminal)
27
- - Sets BASE_DATA_DIR to the repository root
28
- - The assistant runs in the foreground; press Ctrl+C to stop
29
-
30
- The --watch flag passes bun --watch to the child process, which
31
- auto-restarts the assistant whenever source files change. This is useful
32
- during development but disruptive if a Claude Code session is active,
33
- since the restart kills the running assistant mid-conversation.
34
-
35
- Examples:
36
- $ assistant dev
37
- $ assistant dev --watch`,
38
- )
39
- .action(async (opts: { watch?: boolean }) => {
40
- let status = await getDaemonStatus();
41
- if (status.running) {
42
- log.info("Stopping existing assistant...");
43
- const stopResult = await stopDaemon();
44
- if (!stopResult.stopped && stopResult.reason === "stop_failed") {
45
- log.error(
46
- "Failed to stop existing assistant — process survived SIGKILL",
47
- );
48
- process.exit(1);
49
- }
50
- } else if (status.pid) {
51
- // PID file references a live process but the socket is unresponsive.
52
- // This can happen during the daemon startup window before the socket
53
- // is bound. Wait briefly for it to come up before replacing.
54
- log.info(
55
- "Assistant process alive but socket unresponsive — waiting for startup...",
56
- );
57
- const maxWait = 5000;
58
- const interval = 500;
59
- let waited = 0;
60
- let resolved = false;
61
- while (waited < maxWait) {
62
- await new Promise((r) => setTimeout(r, interval));
63
- waited += interval;
64
- status = await getDaemonStatus();
65
- if (status.running) {
66
- // Socket came up — stop the daemon normally.
67
- log.info("Assistant became responsive, stopping it...");
68
- const stopResult = await stopDaemon();
69
- if (!stopResult.stopped && stopResult.reason === "stop_failed") {
70
- log.error(
71
- "Failed to stop existing assistant — process survived SIGKILL",
72
- );
73
- process.exit(1);
74
- }
75
- resolved = true;
76
- break;
77
- }
78
- if (!status.pid) {
79
- // Process exited on its own — PID file already cleaned up.
80
- resolved = true;
81
- break;
82
- }
83
- }
84
- if (!resolved) {
85
- // Still alive but unresponsive after waiting — stop it via stopDaemon()
86
- // which handles SIGTERM → SIGKILL escalation and PID file cleanup.
87
- log.info("Assistant still unresponsive after wait — stopping it...");
88
- const stopResult = await stopDaemon();
89
- if (!stopResult.stopped && stopResult.reason === "stop_failed") {
90
- log.error(
91
- "Failed to stop existing assistant — process survived SIGKILL",
92
- );
93
- process.exit(1);
94
- }
95
- }
96
- }
97
-
98
- const mainPath = `${import.meta.dirname}/../../daemon/main.ts`;
99
-
100
- const useWatch = opts.watch === true;
101
- log.info(
102
- `Starting assistant in dev mode${
103
- useWatch ? " with file watching" : ""
104
- } (Ctrl+C to stop)`,
105
- );
106
-
107
- const repoRoot = join(import.meta.dirname, "..", "..", "..", "..");
108
- const args = useWatch ? ["--watch", "run", mainPath] : ["run", mainPath];
109
- const child = spawn("bun", args, {
110
- stdio: "inherit",
111
- env: {
112
- ...process.env,
113
- BASE_DATA_DIR: repoRoot,
114
- VELLUM_LOG_STDERR: "1",
115
- VELLUM_DEBUG: "1",
116
- },
117
- });
118
-
119
- const forward = (signal: NodeJS.Signals) => {
120
- child.kill(signal);
121
- };
122
- process.on("SIGINT", () => forward("SIGINT"));
123
- process.on("SIGTERM", () => forward("SIGTERM"));
124
-
125
- child.on("exit", (code) => {
126
- process.exit(code ?? 0);
127
- });
128
- });
129
- }
@@ -1,391 +0,0 @@
1
- /**
2
- * CLI command: `assistant map <domain>`
3
- *
4
- * Launches Chrome with CDP, starts a Ride Shotgun learn session to auto-navigate
5
- * the given domain, then analyzes captured network traffic into a deduplicated API map.
6
- */
7
-
8
- import { Command } from "commander";
9
- import { parse as parseTld } from "tldts";
10
-
11
- import {
12
- analyzeApiMap,
13
- printApiMapTable,
14
- saveApiMap,
15
- } from "../../tools/browser/api-map.js";
16
- import { ensureChromeWithCdp } from "../../tools/browser/chrome-cdp.js";
17
- import { loadRecording } from "../../tools/browser/recording-store.js";
18
- import { httpSend } from "../http-client.js";
19
- import { getCliLogger } from "../logger.js";
20
-
21
- const log = getCliLogger("cli:map");
22
-
23
- /**
24
- * Extract the registrable base domain from a hostname.
25
- * e.g. "open.spotify.com" → "spotify.com", "connect.garmin.com" → "garmin.com"
26
- * Falls back to the input if tldts can't parse it.
27
- */
28
- function getBaseDomain(domain: string): string {
29
- const result = parseTld(domain);
30
- return result.domain ?? domain;
31
- }
32
-
33
- // ---------------------------------------------------------------------------
34
- // Helpers
35
- // ---------------------------------------------------------------------------
36
-
37
- function output(data: unknown, json: boolean): void {
38
- process.stdout.write(
39
- json ? JSON.stringify(data) + "\n" : JSON.stringify(data, null, 2) + "\n",
40
- );
41
- }
42
-
43
- function outputError(message: string, code = 1): void {
44
- output({ ok: false, error: message }, true);
45
- process.exitCode = code;
46
- }
47
-
48
- function getJson(cmd: Command): boolean {
49
- let c: Command | null = cmd;
50
- while (c) {
51
- if ((c.opts() as { json?: boolean }).json) return true;
52
- c = c.parent;
53
- }
54
- return false;
55
- }
56
-
57
- /**
58
- * Bring the Chrome CDP tab to the foreground so the user sees the right window.
59
- * Optionally navigates to a URL first (used when Chrome was already running).
60
- */
61
- async function bringChromeToFront(
62
- cdpBase: string,
63
- navigateUrl?: string,
64
- ): Promise<string | null> {
65
- try {
66
- const res = await fetch(`${cdpBase}/json/list`);
67
- if (!res.ok) return null;
68
- const targets = (await res.json()) as Array<{
69
- type: string;
70
- url: string;
71
- webSocketDebuggerUrl: string;
72
- }>;
73
- const pageTarget = targets.find((t) => t.type === "page");
74
- if (!pageTarget?.webSocketDebuggerUrl) return null;
75
-
76
- const ws = new WebSocket(pageTarget.webSocketDebuggerUrl);
77
- await new Promise<void>((resolve, reject) => {
78
- ws.onopen = () => resolve();
79
- ws.onerror = (e) => reject(new Error(`CDP WebSocket error: ${e}`));
80
- });
81
-
82
- let nextId = 1;
83
- const cdpSend = (
84
- method: string,
85
- params?: Record<string, unknown>,
86
- ): Promise<unknown> =>
87
- new Promise((resolve, reject) => {
88
- const id = nextId++;
89
- const cleanup = () => {
90
- clearTimeout(timeout);
91
- ws.removeEventListener("message", handler);
92
- ws.removeEventListener("close", onClose);
93
- ws.removeEventListener("error", onError);
94
- };
95
- const timeout = setTimeout(() => {
96
- cleanup();
97
- reject(new Error(`CDP command ${method} timed out`));
98
- }, 5000);
99
- const onClose = () => {
100
- cleanup();
101
- reject(new Error("WebSocket closed before CDP response"));
102
- };
103
- const onError = (e: Event) => {
104
- cleanup();
105
- reject(new Error(`WebSocket error: ${e}`));
106
- };
107
- const handler = (event: MessageEvent) => {
108
- const msg = JSON.parse(String(event.data));
109
- if (msg.id === id) {
110
- cleanup();
111
- if (msg.error) reject(new Error(msg.error.message));
112
- else resolve(msg.result);
113
- }
114
- };
115
- ws.addEventListener("message", handler);
116
- ws.addEventListener("close", onClose);
117
- ws.addEventListener("error", onError);
118
- ws.send(JSON.stringify({ id, method, params }));
119
- });
120
-
121
- if (navigateUrl) {
122
- await cdpSend("Page.navigate", { url: navigateUrl });
123
- // Brief wait for navigation to start
124
- await new Promise((r) => setTimeout(r, 500));
125
- }
126
-
127
- await cdpSend("Page.bringToFront");
128
- const tabUrl = navigateUrl ?? pageTarget.url;
129
- ws.close();
130
- return tabUrl;
131
- } catch {
132
- return null;
133
- }
134
- }
135
-
136
- // ---------------------------------------------------------------------------
137
- // Ride Shotgun learn session helper
138
- // ---------------------------------------------------------------------------
139
-
140
- interface LearnResult {
141
- recordingId?: string;
142
- recordingPath?: string;
143
- }
144
-
145
- async function startLearnSession(
146
- navigateDomain: string,
147
- recordDomain: string,
148
- durationSeconds: number,
149
- autoNavigate: boolean = true,
150
- ): Promise<LearnResult> {
151
- const cdpSession = await ensureChromeWithCdp({
152
- startUrl: `https://${navigateDomain}/`,
153
- });
154
-
155
- // Activate the Chrome window so the user knows which tab to watch
156
- const tabUrl = await bringChromeToFront(
157
- cdpSession.baseUrl,
158
- `https://${navigateDomain}/`,
159
- );
160
- if (tabUrl) {
161
- process.stderr.write(`Chrome is ready — using tab at ${tabUrl}\n`);
162
- }
163
-
164
- // Start ride shotgun via HTTP
165
- const response = await httpSend("/v1/computer-use/ride-shotgun/start", {
166
- method: "POST",
167
- body: JSON.stringify({
168
- durationSeconds,
169
- intervalSeconds: 5,
170
- mode: "learn",
171
- targetDomain: recordDomain,
172
- navigateDomain,
173
- autoNavigate,
174
- }),
175
- });
176
-
177
- if (!response.ok) {
178
- const body = await response.text();
179
- throw new Error(
180
- `Failed to start learn session: ${response.status} ${body}`,
181
- );
182
- }
183
-
184
- const startResult = (await response.json()) as {
185
- watchId?: string;
186
- sessionId?: string;
187
- };
188
-
189
- if (!startResult.watchId) {
190
- throw new Error("Ride-shotgun start response missing watchId");
191
- }
192
-
193
- // Poll the status endpoint using watchId to correlate completion
194
- const { watchId } = startResult;
195
- const timeoutMs = (durationSeconds + 30) * 1000;
196
- const pollIntervalMs = 2000;
197
- const startTime = Date.now();
198
-
199
- return new Promise<LearnResult>((resolve, reject) => {
200
- const tick = async () => {
201
- if (Date.now() - startTime > timeoutMs) {
202
- reject(
203
- new Error(`Learn session timed out after ${durationSeconds + 30}s`),
204
- );
205
- return;
206
- }
207
-
208
- try {
209
- const statusRes = await httpSend(
210
- `/v1/computer-use/ride-shotgun/status/${watchId}`,
211
- { method: "GET" },
212
- );
213
- if (!statusRes.ok) {
214
- setTimeout(tick, pollIntervalMs);
215
- return;
216
- }
217
-
218
- const status = (await statusRes.json()) as {
219
- status: string;
220
- recordingId?: string;
221
- savedRecordingPath?: string;
222
- bootstrapFailureReason?: string;
223
- };
224
-
225
- if (status.bootstrapFailureReason) {
226
- reject(
227
- new Error(`Learn session failed: ${status.bootstrapFailureReason}`),
228
- );
229
- return;
230
- }
231
-
232
- if (status.status === "completed") {
233
- if (status.recordingId) {
234
- resolve({
235
- recordingId: status.recordingId,
236
- recordingPath: status.savedRecordingPath,
237
- });
238
- } else {
239
- reject(
240
- new Error("Learn session completed but no recording was saved."),
241
- );
242
- }
243
- return;
244
- }
245
- } catch {
246
- // Status endpoint not reachable — continue polling
247
- }
248
-
249
- setTimeout(tick, pollIntervalMs);
250
- };
251
-
252
- setTimeout(tick, pollIntervalMs);
253
- });
254
- }
255
-
256
- // ---------------------------------------------------------------------------
257
- // Command registration
258
- // ---------------------------------------------------------------------------
259
-
260
- export function registerMapCommand(program: Command): void {
261
- program
262
- .command("map")
263
- .description(
264
- "Auto-navigate a domain and produce a deduplicated API map. " +
265
- "Launches Chrome with CDP, starts a Ride Shotgun learn session, " +
266
- "then analyzes captured network traffic.",
267
- )
268
- .argument("<domain>", "Domain to map (e.g., example.com)")
269
- .option("--duration <seconds>", "Recording duration in seconds")
270
- .option(
271
- "--manual",
272
- "Manual mode: browse the site yourself while network traffic is recorded",
273
- )
274
- .option("--json", "Machine-readable JSON output")
275
- .addHelpText(
276
- "after",
277
- `
278
- Arguments:
279
- domain The domain to map (e.g. example.com, open.spotify.com). Subdomains
280
- are navigated directly but network traffic is recorded for the
281
- entire base domain (e.g. open.spotify.com navigates that subdomain
282
- but records all *.spotify.com traffic).
283
-
284
- Two modes of operation:
285
- auto (default) The assistant auto-navigates the site using Ride Shotgun,
286
- clicking links and exploring pages autonomously. Default
287
- duration: 120 seconds.
288
- --manual You browse the site yourself while network traffic is
289
- recorded in the background. Default duration: 60 seconds.
290
-
291
- How it works:
292
- 1. Launches Chrome with Chrome DevTools Protocol (CDP) enabled
293
- 2. Starts a Ride Shotgun learn session to capture network traffic
294
- 3. Deduplicates captured requests into unique API endpoints
295
- 4. Saves the API map to disk and prints a summary table
296
-
297
- The assistant must be running (the learn session is coordinated through it).
298
-
299
- Examples:
300
- $ assistant map example.com
301
- $ assistant map open.spotify.com --duration 180
302
- $ assistant map garmin.com --manual`,
303
- )
304
- .action(
305
- async (
306
- domain: string,
307
- opts: { duration?: string; manual?: boolean; json?: boolean },
308
- cmd: Command,
309
- ) => {
310
- const json = getJson(cmd);
311
- const manual = opts.manual ?? false;
312
- const duration = opts.duration
313
- ? parseInt(opts.duration, 10)
314
- : manual
315
- ? 60
316
- : 120;
317
-
318
- try {
319
- // Split into navigation domain (what Chrome browses) and recording domain (network filter).
320
- // e.g. "open.spotify.com" → navigate open.spotify.com, record *.spotify.com
321
- const navigateDomain = domain;
322
- const recordDomain = getBaseDomain(domain);
323
-
324
- if (!json) {
325
- if (manual) {
326
- log.info(
327
- `Starting manual API map session for ${domain} (${duration}s)...`,
328
- );
329
- log.info(
330
- "Browse the site manually. Press Ctrl+C or wait for idle detection to stop recording.",
331
- );
332
- } else if (navigateDomain !== recordDomain) {
333
- log.info(
334
- `Starting API map session: navigating ${navigateDomain}, recording *.${recordDomain} (${duration}s)...`,
335
- );
336
- } else {
337
- log.info(
338
- `Starting API map session for ${domain} (${duration}s)...`,
339
- );
340
- }
341
- }
342
- const result = await startLearnSession(
343
- navigateDomain,
344
- recordDomain,
345
- duration,
346
- !manual,
347
- );
348
-
349
- if (!result.recordingId) {
350
- outputError("Recording completed but no recording ID returned");
351
- return;
352
- }
353
-
354
- // 2. Load the recording
355
- const recording = loadRecording(result.recordingId);
356
- if (!recording) {
357
- outputError(`Failed to load recording ${result.recordingId}`);
358
- return;
359
- }
360
-
361
- // 3. Analyze the API map
362
- const apiMap = analyzeApiMap(recording.networkEntries, domain);
363
-
364
- // 4. Save the API map
365
- const savedPath = saveApiMap(domain, apiMap);
366
-
367
- // 5. Display results
368
- if (!json) {
369
- printApiMapTable(apiMap);
370
- log.info(`API map saved to: ${savedPath}`);
371
- }
372
-
373
- // 6. Output JSON result
374
- output(
375
- {
376
- ok: true,
377
- domain,
378
- recordingId: result.recordingId,
379
- savedPath,
380
- totalRequests: apiMap.totalRequests,
381
- endpointCount: apiMap.endpoints.length,
382
- apiMap,
383
- },
384
- json,
385
- );
386
- } catch (err) {
387
- outputError(err instanceof Error ? err.message : String(err));
388
- }
389
- },
390
- );
391
- }
@@ -1,77 +0,0 @@
1
- import type { Command } from "commander";
2
-
3
- import { withValidToken } from "../../security/token-manager.js";
4
- import { shouldOutputJson, writeOutput } from "../output.js";
5
-
6
- export function registerOAuthCommand(program: Command): void {
7
- const oauth = program
8
- .command("oauth")
9
- .description("Manage OAuth tokens for connected integrations")
10
- .option("--json", "Machine-readable compact JSON output");
11
-
12
- oauth.addHelpText(
13
- "after",
14
- `
15
- OAuth tokens are managed automatically — the "token" command returns a
16
- guaranteed-valid access token, refreshing transparently if the stored token
17
- is expired or near-expiry. Callers never need to handle refresh themselves.
18
-
19
- The <service> argument is the short integration name (e.g. "twitter", "gmail",
20
- "slack"). Internally this maps to credential:integration:<service>:access_token.
21
-
22
- Examples:
23
- $ assistant oauth token twitter
24
- $ assistant oauth token twitter --json
25
- $ TOKEN=$(assistant oauth token gmail)
26
- $ curl -H "Authorization: Bearer $(assistant oauth token twitter)" https://api.x.com/2/tweets`,
27
- );
28
-
29
- // ---------------------------------------------------------------------------
30
- // token — return a guaranteed-valid access token
31
- // ---------------------------------------------------------------------------
32
-
33
- oauth
34
- .command("token <service>")
35
- .description(
36
- "Print a valid OAuth access token for a service, refreshing if expired",
37
- )
38
- .addHelpText(
39
- "after",
40
- `
41
- Arguments:
42
- service Integration name without the "integration:" prefix
43
- (e.g. "twitter", "gmail", "slack")
44
-
45
- Returns a valid OAuth access token for the given service. If the stored token
46
- is expired or near-expiry, it is refreshed automatically before being returned.
47
- The refresh uses the stored refresh token and OAuth2 configuration from
48
- credential metadata — no additional input is required.
49
-
50
- In human mode, prints the bare token to stdout (suitable for shell substitution).
51
- In JSON mode (--json), prints {"ok": true, "token": "..."}.
52
-
53
- Exits with code 1 if no access token exists for the service, no refresh token
54
- is available, or the token refresh fails (e.g. revoked credentials).
55
-
56
- Examples:
57
- $ assistant oauth token twitter
58
- $ assistant oauth token gmail --json
59
- $ export TOKEN=$(assistant oauth token twitter)`,
60
- )
61
- .action(async (service: string, _opts: unknown, cmd: Command) => {
62
- try {
63
- const qualifiedService = `integration:${service}`;
64
- const token = await withValidToken(qualifiedService, async (t) => t);
65
-
66
- if (shouldOutputJson(cmd)) {
67
- writeOutput(cmd, { ok: true, token });
68
- } else {
69
- process.stdout.write(token + "\n");
70
- }
71
- } catch (err) {
72
- const message = err instanceof Error ? err.message : String(err);
73
- writeOutput(cmd, { ok: false, error: message });
74
- process.exitCode = 1;
75
- }
76
- });
77
- }
@@ -1,16 +0,0 @@
1
- import { forwardComputerUseProxyTool } from "../../../../tools/computer-use/skill-proxy-bridge.js";
2
- import type {
3
- ToolContext,
4
- ToolExecutionResult,
5
- } from "../../../../tools/types.js";
6
-
7
- export async function run(
8
- input: Record<string, unknown>,
9
- context: ToolContext,
10
- ): Promise<ToolExecutionResult> {
11
- return forwardComputerUseProxyTool(
12
- "computer_use_request_control",
13
- input,
14
- context,
15
- );
16
- }