@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,567 +0,0 @@
1
- import { randomUUID } from "node:crypto";
2
-
3
- import { autoNavigate } from "../tools/browser/auto-navigate.js";
4
- import {
5
- type CdpSession,
6
- ensureChromeWithCdp,
7
- minimizeChromeWindow,
8
- } from "../tools/browser/chrome-cdp.js";
9
- import { NetworkRecorder } from "../tools/browser/network-recorder.js";
10
- import type { SessionRecording } from "../tools/browser/network-recording-types.js";
11
- import { saveRecording } from "../tools/browser/recording-store.js";
12
- import type { WatchSession } from "../tools/watch/watch-state.js";
13
- import {
14
- fireWatchCompletionNotifier,
15
- fireWatchStartNotifier,
16
- registerWatchCompletionNotifier,
17
- unregisterWatchCompletionNotifier,
18
- watchSessions,
19
- } from "../tools/watch/watch-state.js";
20
- import { getLogger } from "../util/logger.js";
21
- import type { HandlerContext } from "./handlers/shared.js";
22
- import type { RideShotgunStart, RideShotgunStop } from "./message-protocol.js";
23
- import { generateSummary, lastSummaryBySession } from "./watch-handler.js";
24
-
25
- const log = getLogger("ride-shotgun-handler");
26
-
27
- /** Active network recorders keyed by watchId. */
28
- const activeRecorders = new Map<string, NetworkRecorder>();
29
-
30
- /** Active CDP sessions keyed by watchId — tracks browser ownership for cleanup. */
31
- const activeCdpSessions = new Map<string, CdpSession>();
32
-
33
- /** Active progress interval timers keyed by watchId, cleared on session completion. */
34
- const activeProgressIntervals = new Map<string, NodeJS.Timeout>();
35
-
36
- /** Return domain-specific URL patterns that indicate a successful login. */
37
- function getLoginSignals(_targetDomain?: string): string[] {
38
- // DoorDash and general fallback
39
- return [
40
- "/graphql/postLoginQuery",
41
- "/graphql/homePageFacetFeed",
42
- "/graphql/getConsumerOrdersWithDetails",
43
- ];
44
- }
45
-
46
- /**
47
- * Complete a session — finalize recording (if learn mode), generate summary, fire notifier.
48
- * Shared by both the duration timeout and the early-stop handler.
49
- */
50
- async function completeSession(session: WatchSession): Promise<void> {
51
- if (session.status !== "active") return; // already completing/completed
52
-
53
- session.status = "completing";
54
- if (session.timeoutHandle) {
55
- clearTimeout(session.timeoutHandle);
56
- session.timeoutHandle = undefined;
57
- }
58
-
59
- // Clear progress interval timer if one was registered for this session
60
- const progressTimer = activeProgressIntervals.get(session.watchId);
61
- if (progressTimer) {
62
- clearInterval(progressTimer);
63
- activeProgressIntervals.delete(session.watchId);
64
- }
65
-
66
- const { watchId, sessionId } = session;
67
- log.info(
68
- { watchId, sessionId, observationCount: session.observations.length },
69
- "Session completing...",
70
- );
71
-
72
- // In learn mode, stop recording and save — skip the LLM summary (not needed)
73
- if (session.isLearnMode && session.recordingId) {
74
- const hasRecorder = activeRecorders.has(watchId);
75
-
76
- if (hasRecorder) {
77
- session.savedRecordingPath = await finalizeLearnRecording(
78
- watchId,
79
- session,
80
- session.recordingId,
81
- );
82
- }
83
-
84
- // Clean up the CDP session — minimize if we launched Chrome, leave it alone otherwise
85
- const cdpSession = activeCdpSessions.get(watchId);
86
- if (cdpSession) {
87
- activeCdpSessions.delete(watchId);
88
- if (cdpSession.launchedByUs) {
89
- try {
90
- await minimizeChromeWindow(cdpSession.baseUrl);
91
- log.info({ watchId }, "Minimized assistant-launched Chrome window");
92
- } catch (err) {
93
- log.debug({ err, watchId }, "Failed to minimize Chrome window");
94
- }
95
- }
96
- }
97
-
98
- // Use bootstrapFailureReason as the primary discriminator — hasRecorder
99
- // alone can't distinguish "browser never launched" from "recorder failed
100
- // after retries" since both leave activeRecorders empty.
101
- const summary = session.bootstrapFailureReason
102
- ? `Learn session failed — ${session.bootstrapFailureReason}`
103
- : session.savedRecordingPath
104
- ? "Learn session completed — recording saved."
105
- : "Learn session completed — recording failed to save.";
106
-
107
- lastSummaryBySession.set(sessionId, summary);
108
- session.status = "completed";
109
- log.info(
110
- {
111
- watchId,
112
- sessionId,
113
- hasRecorder,
114
- bootstrapFailureReason: session.bootstrapFailureReason,
115
- },
116
- "Learn session complete — firing completion notifier",
117
- );
118
- fireWatchCompletionNotifier(sessionId, session);
119
- log.info({ watchId, sessionId }, "Completion notifier fired");
120
- return;
121
- }
122
-
123
- await generateSummary(session);
124
- session.status = "completed";
125
- }
126
-
127
- export async function handleRideShotgunStart(
128
- msg: RideShotgunStart,
129
- ctx: HandlerContext,
130
- ): Promise<void> {
131
- const watchId = randomUUID();
132
- const sessionId = randomUUID();
133
- const { durationSeconds, intervalSeconds } = msg;
134
- const mode = msg.mode ?? "observe";
135
- const targetDomain = msg.targetDomain;
136
- const isLearnMode = mode === "learn";
137
- const recordingId = isLearnMode ? randomUUID() : undefined;
138
-
139
- const session: WatchSession = {
140
- watchId,
141
- sessionId,
142
- focusArea: isLearnMode
143
- ? `Learn mode: recording network traffic and screen observations${
144
- targetDomain ? ` for ${targetDomain}` : ""
145
- }`
146
- : "General workflow observation",
147
- durationSeconds,
148
- intervalSeconds,
149
- observations: [],
150
- commentaryCount: 0,
151
- status: "active",
152
- startedAt: Date.now(),
153
- isRideShotgun: true,
154
- isLearnMode,
155
- targetDomain,
156
- recordingId,
157
- };
158
-
159
- watchSessions.set(watchId, session);
160
- log.debug(
161
- {
162
- watchId,
163
- sessionId,
164
- durationSeconds,
165
- intervalSeconds,
166
- mode,
167
- targetDomain,
168
- },
169
- "Session created and stored in watchSessions map",
170
- );
171
-
172
- // In learn mode, ensure Chrome is available with CDP, then connect for network recording.
173
- if (isLearnMode) {
174
- const startRecording = async () => {
175
- // Ensure Chrome is running with CDP — launches it if needed
176
- let cdpSession: CdpSession;
177
- try {
178
- cdpSession = await ensureChromeWithCdp({
179
- startUrl: targetDomain ? `https://${targetDomain}` : undefined,
180
- });
181
- // If session completed while we were awaiting Chrome, skip storing to avoid a stale map entry
182
- if (session.status !== "active") {
183
- log.info(
184
- { watchId, status: session.status },
185
- "Session no longer active after CDP launch — skipping recording",
186
- );
187
- // If we launched Chrome, minimize it since completeSession already ran and won't find it
188
- if (cdpSession.launchedByUs) {
189
- try {
190
- await minimizeChromeWindow(cdpSession.baseUrl);
191
- log.info(
192
- { watchId },
193
- "Minimized assistant-launched Chrome window (post-session)",
194
- );
195
- } catch (err) {
196
- log.debug(
197
- { err, watchId },
198
- "Failed to minimize Chrome window (post-session)",
199
- );
200
- }
201
- }
202
- return;
203
- }
204
- activeCdpSessions.set(watchId, cdpSession);
205
- log.info(
206
- {
207
- watchId,
208
- launchedByUs: cdpSession.launchedByUs,
209
- baseUrl: cdpSession.baseUrl,
210
- },
211
- "CDP session established",
212
- );
213
- } catch (err) {
214
- log.warn(
215
- { err, watchId },
216
- "Failed to ensure Chrome with CDP — cannot start recording",
217
- );
218
- ctx.send({
219
- type: "ride_shotgun_error",
220
- watchId,
221
- sessionId,
222
- message:
223
- "Failed to start browser — Chrome CDP could not be launched.",
224
- });
225
- // Fail-fast: complete the session immediately instead of waiting for timeout
226
- session.bootstrapFailureReason = "browser could not be started.";
227
- await completeSession(session);
228
- return;
229
- }
230
-
231
- const cdpBaseUrl = cdpSession.baseUrl;
232
-
233
- for (let attempt = 0; attempt < 10; attempt++) {
234
- // Check if session is still active before each attempt
235
- if (session.status !== "active") {
236
- log.info(
237
- { watchId, attempt, status: session.status },
238
- "Session no longer active — aborting recording start",
239
- );
240
- return;
241
- }
242
- try {
243
- const recorder = new NetworkRecorder(targetDomain, cdpBaseUrl);
244
- recorder.loginSignals = getLoginSignals(targetDomain);
245
- await recorder.startDirect();
246
- // If session completed while we were connecting, stop immediately to avoid leak
247
- if (session.status !== "active") {
248
- log.info(
249
- { watchId, attempt },
250
- "Session completed during CDP connect — stopping recorder to prevent leak",
251
- );
252
- await recorder.stop();
253
- return;
254
- }
255
- activeRecorders.set(watchId, recorder);
256
- log.info(
257
- { watchId, targetDomain, attempt },
258
- "Network recording started for learn session",
259
- );
260
-
261
- // Send periodic progress updates with network entry counts and idle detection
262
- let lastNetworkEntryCount = 0;
263
- let lastActivityTimestamp = Date.now();
264
- let idleHintSent = false;
265
-
266
- const progressInterval: NodeJS.Timeout = setInterval(() => {
267
- if (session.status !== "active") {
268
- clearInterval(progressInterval);
269
- return;
270
- }
271
-
272
- const currentCount = recorder.entryCount;
273
-
274
- // Track activity: reset idle timer when count changes
275
- if (currentCount !== lastNetworkEntryCount) {
276
- lastNetworkEntryCount = currentCount;
277
- lastActivityTimestamp = Date.now();
278
- // If we previously sent an idle hint, clear it now that activity resumed
279
- if (idleHintSent) {
280
- idleHintSent = false;
281
- log.info(
282
- { watchId, currentCount },
283
- "Activity resumed — clearing idleHint",
284
- );
285
- ctx.send({
286
- type: "ride_shotgun_progress",
287
- watchId,
288
- message: `Recording network traffic...`,
289
- networkEntryCount: currentCount,
290
- statusMessage: "Recording network traffic...",
291
- idleHint: false,
292
- });
293
- return;
294
- }
295
- }
296
-
297
- // Idle detection: if some initial activity happened and no new entries for 15s, hint once
298
- const idleMs = Date.now() - lastActivityTimestamp;
299
- let idleHint: boolean | undefined;
300
- if (!idleHintSent && currentCount > 0 && idleMs >= 15_000) {
301
- idleHint = true;
302
- idleHintSent = true;
303
- log.info(
304
- { watchId, currentCount, idleMs },
305
- "Idle detected — sending idleHint",
306
- );
307
- }
308
-
309
- ctx.send({
310
- type: "ride_shotgun_progress",
311
- watchId,
312
- message: `Recording network traffic...`,
313
- networkEntryCount: currentCount,
314
- statusMessage: "Recording network traffic...",
315
- ...(idleHint !== undefined ? { idleHint } : {}),
316
- });
317
- }, 5000);
318
- activeProgressIntervals.set(watchId, progressInterval);
319
-
320
- if (msg.autoNavigate && targetDomain) {
321
- const navDomain = msg.navigateDomain ?? targetDomain;
322
- const abortSignal = { aborted: false };
323
- const checkInterval = setInterval(() => {
324
- if (session.status !== "active") {
325
- abortSignal.aborted = true;
326
- clearInterval(checkInterval);
327
- }
328
- }, 1000);
329
- autoNavigate(navDomain, {
330
- abortSignal,
331
- onProgress: (progress) => {
332
- // Send progress to connected client
333
- if (progress.type === "visiting" && progress.url) {
334
- const shortUrl = progress.url.replace(/^https?:\/\//, "");
335
- ctx.send({
336
- type: "ride_shotgun_progress",
337
- watchId,
338
- message: `[${progress.pageNumber || "?"}] ${shortUrl}`,
339
- });
340
- }
341
- },
342
- cdpBaseUrl,
343
- })
344
- .then((visited) => {
345
- clearInterval(checkInterval);
346
- log.info(
347
- { watchId, visitedPages: visited.length },
348
- "Generic auto-navigation finished",
349
- );
350
- if (session.status === "active") {
351
- completeSession(session);
352
- }
353
- })
354
- .catch((err) => {
355
- clearInterval(checkInterval);
356
- log.warn({ err, watchId }, "Generic auto-navigation failed");
357
- if (session.status === "active") {
358
- completeSession(session);
359
- }
360
- });
361
- } else if (msg.autoNavigate === false && targetDomain) {
362
- // Manual mode: just record network traffic until timeout or early stop — no login detection shortcut.
363
- } else {
364
- // No targetDomain or targetDomain without explicit autoNavigate=false: use login detection
365
- recorder.onLoginDetected = () => {
366
- log.info(
367
- { watchId },
368
- "Login detected — auto-stopping learn session",
369
- );
370
- completeSession(session);
371
- };
372
- }
373
-
374
- return;
375
- } catch (err) {
376
- if (attempt < 9) {
377
- log.debug({ attempt, watchId }, "CDP not ready, retrying in 2s...");
378
- await new Promise((r) => setTimeout(r, 2000));
379
- } else {
380
- log.warn(
381
- { err, watchId },
382
- "Failed to start network recording after 10 attempts",
383
- );
384
- ctx.send({
385
- type: "ride_shotgun_error",
386
- watchId,
387
- sessionId,
388
- message: "Failed to start network recording after 10 attempts.",
389
- });
390
- session.bootstrapFailureReason =
391
- "network recording could not be started after 10 attempts.";
392
- await completeSession(session);
393
- }
394
- }
395
- }
396
- };
397
- // Don't block session start — record in background
398
- startRecording();
399
- }
400
-
401
- // Set timeout for duration expiry
402
- session.timeoutHandle = setTimeout(() => {
403
- if (
404
- session.isLearnMode &&
405
- !activeRecorders.has(watchId) &&
406
- !session.bootstrapFailureReason
407
- ) {
408
- session.bootstrapFailureReason =
409
- "session timed out before recording could start.";
410
- }
411
- completeSession(session);
412
- }, durationSeconds * 1000);
413
-
414
- // Register completion notifier to send summary back to client
415
- registerWatchCompletionNotifier(
416
- sessionId,
417
- (_completedSession: WatchSession) => {
418
- const summary = lastSummaryBySession.get(sessionId) ?? "";
419
- const observationCount = _completedSession.observations.length;
420
-
421
- log.info(
422
- {
423
- watchId,
424
- sessionId,
425
- observationCount,
426
- summaryLength: summary.length,
427
- },
428
- "Completion notifier firing — sending ride_shotgun_result to client",
429
- );
430
-
431
- ctx.send({
432
- type: "ride_shotgun_result",
433
- sessionId,
434
- watchId,
435
- summary,
436
- observationCount,
437
- recordingId,
438
- recordingPath: _completedSession.savedRecordingPath,
439
- });
440
-
441
- unregisterWatchCompletionNotifier(sessionId);
442
- lastSummaryBySession.delete(sessionId);
443
- log.debug(
444
- { watchId, sessionId, observationCount, recordingId },
445
- "Ride shotgun result sent successfully",
446
- );
447
- },
448
- );
449
-
450
- // Fire start notifier
451
- fireWatchStartNotifier(sessionId, session);
452
-
453
- // Send watch_started so the Swift client knows the watchId/sessionId
454
- ctx.send({
455
- type: "watch_started",
456
- sessionId,
457
- watchId,
458
- durationSeconds,
459
- intervalSeconds,
460
- });
461
-
462
- log.info(
463
- { watchId, sessionId, durationSeconds, intervalSeconds, mode },
464
- "Ride shotgun session started",
465
- );
466
- }
467
-
468
- export async function handleRideShotgunStop(
469
- msg: RideShotgunStop,
470
- _ctx: HandlerContext,
471
- ): Promise<void> {
472
- const { watchId } = msg;
473
- const session = watchSessions.get(watchId);
474
- if (!session) {
475
- log.warn({ watchId }, "ride_shotgun_stop: session not found");
476
- return;
477
- }
478
- log.info({ watchId, sessionId: session.sessionId }, "Early stop requested");
479
- await completeSession(session);
480
- }
481
-
482
- /**
483
- * Stop network recording, extract cookies, build and save the SessionRecording.
484
- */
485
- async function finalizeLearnRecording(
486
- watchId: string,
487
- session: WatchSession,
488
- recordingId: string,
489
- ): Promise<string | undefined> {
490
- try {
491
- const recorder = activeRecorders.get(watchId);
492
-
493
- // Extract cookies before stopping (needs the CDP connection alive)
494
- const cookies = recorder
495
- ? await recorder.extractCookies(session.targetDomain)
496
- : [];
497
-
498
- const networkEntries = recorder ? await recorder.stop() : [];
499
- activeRecorders.delete(watchId);
500
-
501
- // Save cookies to the encrypted credential store (keyed by target domain)
502
- // so they don't need to be persisted in the plaintext recording file.
503
- if (session.targetDomain && cookies.length > 0) {
504
- const { setSecureKeyAsync } = await import("../security/secure-keys.js");
505
- const { upsertCredentialMetadata } =
506
- await import("../tools/credentials/metadata-store.js");
507
-
508
- const service = session.targetDomain;
509
- const field = "session:cookies";
510
- const storageKey = `credential:${service}:${field}`;
511
- const stored = await setSecureKeyAsync(
512
- storageKey,
513
- JSON.stringify(cookies),
514
- );
515
- if (stored) {
516
- try {
517
- upsertCredentialMetadata(service, field, {});
518
- } catch {
519
- // Non-critical: metadata upsert is best-effort
520
- }
521
- log.info(
522
- { targetDomain: service, cookieCount: cookies.length },
523
- "Cookies saved to credential store",
524
- );
525
- } else {
526
- log.warn(
527
- { targetDomain: service },
528
- "Failed to save cookies to credential store",
529
- );
530
- }
531
- }
532
-
533
- const recording: SessionRecording = {
534
- id: recordingId,
535
- startedAt: session.startedAt,
536
- endedAt: Date.now(),
537
- targetDomain: session.targetDomain,
538
- networkEntries,
539
- cookies: [], // Cookies saved to credential store — never persisted in recording
540
- observations: session.observations.map((obs) => ({
541
- ocrText: obs.ocrText,
542
- appName: obs.appName,
543
- windowTitle: obs.windowTitle,
544
- timestamp: obs.timestamp,
545
- captureIndex: obs.captureIndex,
546
- })),
547
- };
548
-
549
- const path = saveRecording(recording);
550
- log.info(
551
- {
552
- recordingId,
553
- networkEntries: networkEntries.length,
554
- cookies: cookies.length,
555
- observations: session.observations.length,
556
- },
557
- "Learn recording finalized and saved",
558
- );
559
- return path;
560
- } catch (err) {
561
- log.error(
562
- { err, watchId, recordingId },
563
- "Failed to finalize learn recording",
564
- );
565
- return undefined;
566
- }
567
- }