@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,597 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
2
-
3
- import type { ChannelDeliveryResult } from "./gateway-client.js";
4
-
5
- // ---------------------------------------------------------------------------
6
- // Mocks
7
- // ---------------------------------------------------------------------------
8
-
9
- let callCount = 0;
10
- const mockDeliverChannelReply = mock(
11
- async (): Promise<ChannelDeliveryResult> => {
12
- callCount++;
13
- return { ok: true, messageId: 99 + callCount };
14
- },
15
- );
16
-
17
- mock.module("./gateway-client.js", () => ({
18
- deliverChannelReply: mockDeliverChannelReply,
19
- }));
20
-
21
- mock.module("../util/logger.js", () => ({
22
- getLogger: () =>
23
- new Proxy({} as Record<string, unknown>, {
24
- get: () => () => {},
25
- }),
26
- }));
27
-
28
- import { TelegramStreamingDelivery } from "./telegram-streaming-delivery.js";
29
-
30
- // ---------------------------------------------------------------------------
31
- // Helpers
32
- // ---------------------------------------------------------------------------
33
-
34
- type CallArgs = [string, Record<string, unknown>, string];
35
-
36
- /** Extract the payload (second argument) from the Nth mock call. */
37
- function callPayload(n: number): Record<string, unknown> {
38
- const args = mockDeliverChannelReply.mock.calls[n] as unknown as CallArgs;
39
- return args[1];
40
- }
41
-
42
- function createDelivery(): TelegramStreamingDelivery {
43
- return new TelegramStreamingDelivery({
44
- callbackUrl: "http://test/deliver",
45
- chatId: "123",
46
- mintBearerToken: () => "test-token",
47
- });
48
- }
49
-
50
- /** Flush all pending microtasks / promise callbacks. */
51
- async function flushPromises(): Promise<void> {
52
- // Multiple rounds to handle chained .then() callbacks
53
- for (let i = 0; i < 10; i++) {
54
- await new Promise((resolve) => setTimeout(resolve, 0));
55
- }
56
- }
57
-
58
- // ---------------------------------------------------------------------------
59
- // Tests
60
- // ---------------------------------------------------------------------------
61
-
62
- describe("TelegramStreamingDelivery", () => {
63
- beforeEach(() => {
64
- callCount = 0;
65
- mockDeliverChannelReply.mockReset();
66
- mockDeliverChannelReply.mockImplementation(
67
- async (): Promise<ChannelDeliveryResult> => {
68
- callCount++;
69
- return { ok: true, messageId: 99 + callCount };
70
- },
71
- );
72
- });
73
-
74
- afterEach(() => {
75
- mockDeliverChannelReply.mockReset();
76
- });
77
-
78
- // ── Test 1: initial send when buffer reaches MIN_INITIAL_CHARS ──────
79
- test("sends initial message when buffer reaches MIN_INITIAL_CHARS", async () => {
80
- const delivery = createDelivery();
81
- // MIN_INITIAL_CHARS is 20; send 25 chars
82
- delivery.onEvent({
83
- type: "assistant_text_delta",
84
- text: "a".repeat(25),
85
- });
86
-
87
- await flushPromises();
88
-
89
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
90
- const payload = callPayload(0);
91
- expect(payload.text).toBe("a".repeat(25));
92
- // Initial send should NOT have a messageId (it's a new message)
93
- expect(payload.messageId).toBeUndefined();
94
- });
95
-
96
- // ── Test 2: edits message with accumulated text on finish() ─────────
97
- test("edits message with accumulated text on finish()", async () => {
98
- const delivery = createDelivery();
99
- // First: send enough to trigger initial send
100
- delivery.onEvent({
101
- type: "assistant_text_delta",
102
- text: "a".repeat(25),
103
- });
104
- await flushPromises();
105
-
106
- // Then add more text and finish
107
- delivery.onEvent({
108
- type: "assistant_text_delta",
109
- text: "b".repeat(10),
110
- });
111
- await delivery.finish();
112
-
113
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(2);
114
-
115
- // First call: new message (no messageId)
116
- const firstPayload = callPayload(0);
117
- expect(firstPayload.messageId).toBeUndefined();
118
-
119
- // Second call: edit (with messageId from first call)
120
- const secondPayload = callPayload(1);
121
- expect(secondPayload.messageId).toBe(100); // first call returns messageId: 100
122
- expect(secondPayload.text).toBe("a".repeat(25) + "b".repeat(10));
123
- });
124
-
125
- // ── Test 3: sends remainder as new message when messageId missing ───
126
- test("sends remainder as new message when messageId is missing", async () => {
127
- // First call: no messageId in response; second call: with messageId
128
- mockDeliverChannelReply.mockReset();
129
- let localCallCount = 0;
130
- mockDeliverChannelReply.mockImplementation(
131
- async (): Promise<ChannelDeliveryResult> => {
132
- localCallCount++;
133
- if (localCallCount === 1) return { ok: true }; // no messageId
134
- return { ok: true, messageId: 200 };
135
- },
136
- );
137
-
138
- const delivery = createDelivery();
139
- delivery.onEvent({
140
- type: "assistant_text_delta",
141
- text: "a".repeat(25),
142
- });
143
- await flushPromises();
144
-
145
- delivery.onEvent({
146
- type: "assistant_text_delta",
147
- text: "b".repeat(10),
148
- });
149
- await delivery.finish();
150
-
151
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(2);
152
-
153
- // The initial text was already delivered (just without a messageId),
154
- // so the second call should contain only the remainder (buffer text)
155
- const secondPayload = callPayload(1);
156
- expect(secondPayload.text).toBe("b".repeat(10));
157
- // It's sent as a new message (no messageId in payload) since the first
158
- // call didn't return one
159
- expect(secondPayload.messageId).toBeUndefined();
160
- });
161
-
162
- // ── Test 4: sends full text when initial send fails ─────────────────
163
- test("sends full text when initial send fails", async () => {
164
- mockDeliverChannelReply.mockReset();
165
- let localCallCount = 0;
166
- mockDeliverChannelReply.mockImplementation(
167
- async (): Promise<ChannelDeliveryResult> => {
168
- localCallCount++;
169
- if (localCallCount === 1) throw new Error("Network error");
170
- return { ok: true, messageId: 300 };
171
- },
172
- );
173
-
174
- const delivery = createDelivery();
175
- delivery.onEvent({
176
- type: "assistant_text_delta",
177
- text: "a".repeat(25),
178
- });
179
- await flushPromises();
180
-
181
- // The initial send failed; buffer should be restored
182
- await delivery.finish();
183
-
184
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(2);
185
-
186
- // The finish() call should send the complete accumulated text
187
- const secondPayload = callPayload(1);
188
- expect(secondPayload.text).toBe("a".repeat(25));
189
- expect(delivery.finishSucceeded).toBe(true);
190
- });
191
-
192
- // ── Test 5: tool_use_start between text segments produces single message ─
193
- test("tool_use_start between text segments produces single message", async () => {
194
- const delivery = createDelivery();
195
-
196
- // Send enough text to trigger initial message (>= MIN_INITIAL_CHARS=20)
197
- delivery.onEvent({
198
- type: "assistant_text_delta",
199
- text: "Yeah, still here! ", // 18 chars
200
- });
201
- delivery.onEvent({
202
- type: "assistant_text_delta",
203
- text: "aa", // Push past 20 chars
204
- });
205
- await flushPromises();
206
-
207
- // Initial message sent
208
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
209
- const initialPayload = callPayload(0);
210
- expect(initialPayload.messageId).toBeUndefined(); // new message
211
-
212
- // tool_use_start — should NOT finalize/reset message state
213
- delivery.onEvent({
214
- type: "tool_use_start",
215
- toolName: "memory_recall",
216
- input: {},
217
- });
218
- await flushPromises();
219
-
220
- // More text after the tool call
221
- delivery.onEvent({
222
- type: "assistant_text_delta",
223
- text: "What do you need?",
224
- });
225
-
226
- await delivery.finish();
227
-
228
- // The final edit should be to the SAME message (same messageId),
229
- // containing the full combined text
230
- const lastCallIndex = mockDeliverChannelReply.mock.calls.length - 1;
231
- const lastPayload = callPayload(lastCallIndex);
232
- expect(lastPayload.messageId).toBe(100); // same messageId as initial
233
- expect(lastPayload.text).toBe("Yeah, still here! aaWhat do you need?");
234
- });
235
-
236
- // ── Test 5b: multiple tool calls between text segments ──────────────
237
- test("multiple tool calls between text segments produce single message", async () => {
238
- const delivery = createDelivery();
239
-
240
- delivery.onEvent({
241
- type: "assistant_text_delta",
242
- text: "a".repeat(25),
243
- });
244
- await flushPromises();
245
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
246
-
247
- // Two consecutive tool calls
248
- delivery.onEvent({ type: "tool_use_start", toolName: "tool1", input: {} });
249
- delivery.onEvent({ type: "tool_use_start", toolName: "tool2", input: {} });
250
-
251
- // More text after both tool calls
252
- delivery.onEvent({
253
- type: "assistant_text_delta",
254
- text: "b".repeat(10),
255
- });
256
- await delivery.finish();
257
-
258
- // All text should be in the same message
259
- const lastCallIndex = mockDeliverChannelReply.mock.calls.length - 1;
260
- const lastPayload = callPayload(lastCallIndex);
261
- expect(lastPayload.messageId).toBe(100);
262
- expect(lastPayload.text).toBe("a".repeat(25) + "b".repeat(10));
263
- });
264
-
265
- // ── Test 5c: tool_use_start before any text is a no-op ─────────────
266
- test("tool_use_start before any text is a no-op", async () => {
267
- const delivery = createDelivery();
268
-
269
- delivery.onEvent({
270
- type: "tool_use_start",
271
- toolName: "init_tool",
272
- input: {},
273
- });
274
- await flushPromises();
275
-
276
- // No messages should have been sent
277
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(0);
278
-
279
- // Subsequent text should work normally
280
- delivery.onEvent({
281
- type: "assistant_text_delta",
282
- text: "a".repeat(25),
283
- });
284
- await flushPromises();
285
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
286
-
287
- await delivery.finish();
288
- expect(delivery.finishSucceeded).toBe(true);
289
- });
290
-
291
- // ── Test 5d: tool_use_start at end of response finalizes on finish ──
292
- test("tool_use_start at end of response finalizes on finish", async () => {
293
- const delivery = createDelivery();
294
-
295
- delivery.onEvent({
296
- type: "assistant_text_delta",
297
- text: "a".repeat(25),
298
- });
299
- await flushPromises();
300
-
301
- delivery.onEvent({
302
- type: "tool_use_start",
303
- toolName: "final_tool",
304
- input: {},
305
- });
306
- await delivery.finish();
307
-
308
- // The text should have been delivered via the initial message + a final edit
309
- expect(delivery.finishSucceeded).toBe(true);
310
- expect(delivery.hasDeliveredText).toBe(true);
311
- });
312
-
313
- // ── Test 5e: text exceeding max length after tool pause splits at length boundary ─
314
- test("text exceeding max length after tool pause splits at length boundary", async () => {
315
- const delivery = createDelivery();
316
-
317
- // Send ~3900 chars
318
- delivery.onEvent({
319
- type: "assistant_text_delta",
320
- text: "a".repeat(3900),
321
- });
322
- await flushPromises();
323
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
324
-
325
- // Tool call (should not split)
326
- delivery.onEvent({ type: "tool_use_start", toolName: "lookup", input: {} });
327
-
328
- // Send 200 more chars (total 4100 > 4000 limit)
329
- delivery.onEvent({
330
- type: "assistant_text_delta",
331
- text: "b".repeat(200),
332
- });
333
-
334
- await delivery.finish();
335
- await flushPromises();
336
-
337
- // Should have split at 4000-char boundary:
338
- // 1. Initial message (3900 chars)
339
- // 2. Edit at boundary (4000 chars)
340
- // 3. Overflow new message (100 chars)
341
- const calls = mockDeliverChannelReply.mock.calls.length;
342
- expect(calls).toBe(3);
343
-
344
- // Edit at boundary
345
- const editPayload = callPayload(1);
346
- expect((editPayload.text as string).length).toBe(4000);
347
- expect(editPayload.messageId).toBeDefined();
348
-
349
- // Overflow as new message
350
- const overflowPayload = callPayload(2);
351
- expect((overflowPayload.text as string).length).toBe(100);
352
- expect(overflowPayload.messageId).toBeUndefined();
353
- });
354
-
355
- // ── Test 5f: preserves below-threshold text across tool_use_start ───
356
- test("preserves below-threshold text across tool_use_start", async () => {
357
- const delivery = createDelivery();
358
-
359
- // Send text below MIN_INITIAL_CHARS threshold
360
- delivery.onEvent({
361
- type: "assistant_text_delta",
362
- text: "Hi! ", // 4 chars, well below 20
363
- });
364
- await flushPromises();
365
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(0); // not sent yet
366
-
367
- // tool_use_start
368
- delivery.onEvent({
369
- type: "tool_use_start",
370
- toolName: "memory_recall",
371
- input: {},
372
- });
373
- await flushPromises();
374
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(0); // still not sent
375
-
376
- // More text after tool (enough to trigger initial send when combined)
377
- delivery.onEvent({
378
- type: "assistant_text_delta",
379
- text: "What can I help with?", // 21 chars, combined = 25 >= 20
380
- });
381
- await flushPromises();
382
-
383
- // Should have sent initial message with ALL text (pre-tool + post-tool)
384
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
385
- const payload = callPayload(0);
386
- expect(payload.text).toBe("Hi! What can I help with?");
387
-
388
- await delivery.finish();
389
- expect(delivery.finishSucceeded).toBe(true);
390
- });
391
-
392
- // ── Test 5g: delivers below-threshold text when tool_use_start is followed by finish ─
393
- test("delivers below-threshold text when tool_use_start is followed by finish", async () => {
394
- const delivery = createDelivery();
395
-
396
- delivery.onEvent({
397
- type: "assistant_text_delta",
398
- text: "Hi!", // 3 chars
399
- });
400
- delivery.onEvent({
401
- type: "tool_use_start",
402
- toolName: "lookup",
403
- input: {},
404
- });
405
-
406
- await delivery.finish();
407
-
408
- // The "Hi!" should have been sent as a new message during finish
409
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
410
- const payload = callPayload(0);
411
- expect(payload.text).toBe("Hi!");
412
- expect(delivery.finishSucceeded).toBe(true);
413
- });
414
-
415
- // ── Test 5h: no-messageId response doesn't cause duplicate messages on continued deltas ─
416
- test("no-messageId response doesn't cause duplicate messages on continued deltas", async () => {
417
- // Simulate the exact bug from the screenshot: initial send succeeds
418
- // without messageId, then more deltas create overlapping new messages
419
- mockDeliverChannelReply.mockReset();
420
- mockDeliverChannelReply.mockImplementation(
421
- async (): Promise<ChannelDeliveryResult> => {
422
- // All sends return no messageId (simulates gateway omitting it)
423
- return { ok: true };
424
- },
425
- );
426
-
427
- const delivery = createDelivery();
428
-
429
- // First batch: triggers sendInitialMessage (>= 20 chars)
430
- delivery.onEvent({
431
- type: "assistant_text_delta",
432
- text: "Alright, hit me with something",
433
- });
434
- await flushPromises();
435
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
436
- expect(callPayload(0).text).toBe("Alright, hit me with something");
437
-
438
- // More deltas arrive — should NOT trigger another sendInitialMessage
439
- delivery.onEvent({
440
- type: "assistant_text_delta",
441
- text: " longer and let's see if it comes through as one",
442
- });
443
- await flushPromises();
444
- // Still only 1 call — text accumulates in buffer
445
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
446
-
447
- delivery.onEvent({
448
- type: "assistant_text_delta",
449
- text: " message now!",
450
- });
451
- await delivery.finish();
452
-
453
- // finish() should send the remainder as a single new message
454
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(2);
455
- const finishPayload = callPayload(1);
456
- expect(finishPayload.text).toBe(
457
- " longer and let's see if it comes through as one message now!",
458
- );
459
- expect(finishPayload.messageId).toBeUndefined();
460
- expect(delivery.finishSucceeded).toBe(true);
461
- });
462
-
463
- // ── Test 5i: combined threshold accounts for pre-tool currentMessageText ─
464
- test("combined threshold accounts for pre-tool currentMessageText", async () => {
465
- const delivery = createDelivery();
466
-
467
- // Send 15 chars (below 20 threshold)
468
- delivery.onEvent({
469
- type: "assistant_text_delta",
470
- text: "Hello, world!! ", // 15 chars
471
- });
472
- await flushPromises();
473
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(0);
474
-
475
- // tool_use_start moves 15 chars to currentMessageText
476
- delivery.onEvent({
477
- type: "tool_use_start",
478
- toolName: "lookup",
479
- input: {},
480
- });
481
-
482
- // Send only 6 more chars — buffer alone (6) < 20, but combined (21) >= 20
483
- delivery.onEvent({
484
- type: "assistant_text_delta",
485
- text: "Great!",
486
- });
487
- await flushPromises();
488
-
489
- // Should have triggered initial send with combined text
490
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
491
- expect(callPayload(0).text).toBe("Hello, world!! Great!");
492
-
493
- await delivery.finish();
494
- expect(delivery.finishSucceeded).toBe(true);
495
- });
496
-
497
- // ── Test 6: skips final edit when text hasn't changed ───────────────
498
- test("skips final edit when text hasn't changed", async () => {
499
- const delivery = createDelivery();
500
-
501
- // Feed exactly MIN_INITIAL_CHARS (20) to trigger initial send
502
- delivery.onEvent({
503
- type: "assistant_text_delta",
504
- text: "a".repeat(20),
505
- });
506
- await flushPromises();
507
-
508
- // Initial send should have fired
509
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
510
-
511
- // Call finish() with no additional text
512
- await delivery.finish();
513
-
514
- // Should NOT have made a second call since text hasn't changed
515
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
516
- expect(delivery.finishSucceeded).toBe(true);
517
- });
518
-
519
- // ── Test 7: splits message at TELEGRAM_MAX_TEXT_LEN boundary ────────
520
- test("splits message at TELEGRAM_MAX_TEXT_LEN boundary", async () => {
521
- const delivery = createDelivery();
522
-
523
- // Send initial chunk to start a message (>= 20 chars)
524
- delivery.onEvent({
525
- type: "assistant_text_delta",
526
- text: "a".repeat(25),
527
- });
528
- await flushPromises();
529
-
530
- // Initial send fired
531
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
532
-
533
- // Now send enough to exceed TELEGRAM_MAX_TEXT_LEN (4000) when combined
534
- // with the initial 25 chars. The edit is throttled, so the buffer
535
- // accumulates until finish() flushes it. finish() has its own overflow
536
- // handling that splits at the 4000-char boundary.
537
- delivery.onEvent({
538
- type: "assistant_text_delta",
539
- text: "b".repeat(4500),
540
- });
541
-
542
- // Call finish() to flush — this triggers the overflow split in finish()
543
- await delivery.finish();
544
- await flushPromises();
545
-
546
- // finish() should have: (1) edited the current message with up to 4000
547
- // chars, then (2) sent the overflow as a new message.
548
- // Total calls: 1 (initial) + 1 (edit at boundary) + 1 (overflow new message) = 3
549
- expect(mockDeliverChannelReply.mock.calls.length).toBe(3);
550
-
551
- // The second call (edit at boundary) should have text of length 4000
552
- const editPayload = callPayload(1);
553
- expect((editPayload.text as string).length).toBe(4000);
554
- expect(editPayload.messageId).toBeDefined();
555
-
556
- // The third call (overflow) should be a new message (no messageId in payload)
557
- const overflowPayload = callPayload(2);
558
- expect(overflowPayload.messageId).toBeUndefined();
559
- // Overflow should contain the remainder: 25 + 4500 - 4000 = 525 chars
560
- expect((overflowPayload.text as string).length).toBe(525);
561
-
562
- expect(delivery.finishSucceeded).toBe(true);
563
- });
564
-
565
- // ── Test 8: ignores events after finish() is called ─────────────────
566
- test("ignores events after finish() is called", async () => {
567
- const delivery = createDelivery();
568
-
569
- // Send initial text to trigger a message
570
- delivery.onEvent({
571
- type: "assistant_text_delta",
572
- text: "a".repeat(25),
573
- });
574
- await flushPromises();
575
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(1);
576
-
577
- // Finish
578
- await delivery.finish();
579
-
580
- const callsAfterFinish = mockDeliverChannelReply.mock.calls.length;
581
-
582
- // Now send more events -- they should be ignored
583
- delivery.onEvent({
584
- type: "assistant_text_delta",
585
- text: "ignored text",
586
- });
587
- delivery.onEvent({
588
- type: "tool_use_start",
589
- toolName: "ignored_tool",
590
- input: {},
591
- });
592
- await flushPromises();
593
-
594
- // No additional calls should have been made
595
- expect(mockDeliverChannelReply).toHaveBeenCalledTimes(callsAfterFinish);
596
- });
597
- });