@vellumai/assistant 0.4.41 → 0.4.43

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 (843) hide show
  1. package/.env.example +1 -6
  2. package/.prettierignore +3 -0
  3. package/ARCHITECTURE.md +131 -393
  4. package/Dockerfile +0 -1
  5. package/README.md +73 -83
  6. package/bun.lock +8 -2
  7. package/docs/architecture/integrations.md +16 -21
  8. package/docs/architecture/memory.md +1 -1
  9. package/docs/architecture/scheduling.md +63 -63
  10. package/docs/architecture/security.md +3 -3
  11. package/docs/runbook-trusted-contacts.md +11 -12
  12. package/docs/trusted-contact-access.md +39 -39
  13. package/package.json +5 -8
  14. package/src/__tests__/access-request-decision.test.ts +4 -4
  15. package/src/__tests__/active-skill-tools.test.ts +49 -34
  16. package/src/__tests__/actor-token-service.test.ts +55 -85
  17. package/src/__tests__/amazon-cdp-integration.test.ts +14 -26
  18. package/src/__tests__/app-bundler.test.ts +14 -368
  19. package/src/__tests__/app-compiler.test.ts +0 -1
  20. package/src/__tests__/app-executors.test.ts +10 -1
  21. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
  22. package/src/__tests__/approval-primitive.test.ts +2 -4
  23. package/src/__tests__/approval-routes-http.test.ts +1 -1
  24. package/src/__tests__/asset-materialize-tool.test.ts +1 -4
  25. package/src/__tests__/asset-search-tool.test.ts +1 -4
  26. package/src/__tests__/assistant-attachments.test.ts +23 -0
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +4 -8
  28. package/src/__tests__/assistant-id-boundary-guard.test.ts +5 -5
  29. package/src/__tests__/attachments-store.test.ts +1 -4
  30. package/src/__tests__/avatar-e2e.test.ts +43 -23
  31. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  32. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -9
  33. package/src/__tests__/call-controller.test.ts +4 -8
  34. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  35. package/src/__tests__/call-domain.test.ts +250 -8
  36. package/src/__tests__/call-pointer-message-composer.test.ts +14 -14
  37. package/src/__tests__/call-pointer-messages.test.ts +7 -11
  38. package/src/__tests__/call-recovery.test.ts +47 -0
  39. package/src/__tests__/call-routes-http.test.ts +13 -0
  40. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  41. package/src/__tests__/callback-handoff-copy.test.ts +5 -5
  42. package/src/__tests__/canonical-guardian-store.test.ts +3 -3
  43. package/src/__tests__/channel-approval-routes.test.ts +101 -134
  44. package/src/__tests__/channel-approval.test.ts +0 -201
  45. package/src/__tests__/channel-approvals.test.ts +2 -2
  46. package/src/__tests__/channel-delivery-store.test.ts +16 -24
  47. package/src/__tests__/channel-guardian.test.ts +641 -740
  48. package/src/__tests__/channel-invite-transport.test.ts +1 -2
  49. package/src/__tests__/channel-policy.test.ts +9 -12
  50. package/src/__tests__/channel-readiness-service.test.ts +156 -45
  51. package/src/__tests__/channel-reply-delivery.test.ts +3 -3
  52. package/src/__tests__/channel-retry-sweep.test.ts +7 -7
  53. package/src/__tests__/checker.test.ts +10 -7
  54. package/src/__tests__/chrome-cdp.test.ts +57 -17
  55. package/src/__tests__/cli-help-reference-sync.test.ts +26 -0
  56. package/src/__tests__/compaction.benchmark.test.ts +25 -5
  57. package/src/__tests__/computer-use-session-lifecycle.test.ts +1 -1
  58. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  59. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
  60. package/src/__tests__/config-loader-backfill.test.ts +310 -0
  61. package/src/__tests__/config-watcher.test.ts +1 -5
  62. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +3 -5
  63. package/src/__tests__/connection-policy.test.ts +3 -62
  64. package/src/__tests__/contacts-tools.test.ts +0 -2
  65. package/src/__tests__/context-memory-e2e.test.ts +11 -7
  66. package/src/__tests__/context-overflow-policy.test.ts +2 -2
  67. package/src/__tests__/context-window-manager.test.ts +220 -61
  68. package/src/__tests__/conversation-attention-store.test.ts +178 -2
  69. package/src/__tests__/conversation-attention-telegram.test.ts +8 -11
  70. package/src/__tests__/conversation-pairing.test.ts +14 -14
  71. package/src/__tests__/conversation-routes-guardian-reply.test.ts +1 -1
  72. package/src/__tests__/conversation-store.test.ts +2 -2
  73. package/src/__tests__/conversation-unread-route.test.ts +155 -0
  74. package/src/__tests__/credential-metadata-store.test.ts +0 -2
  75. package/src/__tests__/credential-security-invariants.test.ts +9 -16
  76. package/src/__tests__/credentials-cli.test.ts +49 -5
  77. package/src/__tests__/daemon-assistant-events.test.ts +4 -22
  78. package/src/__tests__/db-migration-rollback.test.ts +2 -2
  79. package/src/__tests__/deterministic-verification-control-plane.test.ts +19 -19
  80. package/src/__tests__/dictation-mode-detection.test.ts +1 -1
  81. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  82. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -6
  83. package/src/__tests__/email-cli.test.ts +12 -12
  84. package/src/__tests__/email-service-config-fallback.test.ts +1 -1
  85. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -18
  86. package/src/__tests__/event-bus.test.ts +0 -1
  87. package/src/__tests__/followup-tools.test.ts +0 -2
  88. package/src/__tests__/gateway-client-managed-outbound.test.ts +6 -6
  89. package/src/__tests__/gateway-only-enforcement.test.ts +13 -77
  90. package/src/__tests__/gateway-only-guard.test.ts +5 -0
  91. package/src/__tests__/guardian-action-conversation-turn.test.ts +3 -3
  92. package/src/__tests__/guardian-action-followup-executor.test.ts +29 -94
  93. package/src/__tests__/guardian-action-followup-store.test.ts +2 -12
  94. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +48 -194
  95. package/src/__tests__/guardian-action-late-reply.test.ts +12 -12
  96. package/src/__tests__/guardian-action-store.test.ts +2 -2
  97. package/src/__tests__/guardian-action-sweep.test.ts +5 -5
  98. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -3
  99. package/src/__tests__/guardian-dispatch.test.ts +5 -46
  100. package/src/__tests__/guardian-grant-minting.test.ts +5 -44
  101. package/src/__tests__/guardian-outbound-http.test.ts +95 -114
  102. package/src/__tests__/guardian-question-mode.test.ts +1 -4
  103. package/src/__tests__/guardian-routing-invariants.test.ts +5 -13
  104. package/src/__tests__/guardian-routing-state.test.ts +3 -3
  105. package/src/__tests__/guardian-verification-voice-binding.test.ts +64 -7
  106. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  107. package/src/__tests__/handle-user-message-secret-resume.test.ts +3 -5
  108. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +16 -34
  109. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  110. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  111. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  112. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  113. package/src/__tests__/heartbeat-service.test.ts +1 -1
  114. package/src/__tests__/home-base-bootstrap.test.ts +0 -2
  115. package/src/__tests__/host-shell-tool.test.ts +3 -12
  116. package/src/__tests__/inbound-invite-redemption.test.ts +2 -2
  117. package/src/__tests__/ingress-url-consistency.test.ts +0 -64
  118. package/src/__tests__/integration-status.test.ts +8 -8
  119. package/src/__tests__/intent-routing.test.ts +9 -13
  120. package/src/__tests__/invite-redemption-service.test.ts +4 -4
  121. package/src/__tests__/invite-routes-http.test.ts +10 -10
  122. package/src/__tests__/llm-usage-store.test.ts +45 -9
  123. package/src/__tests__/local-gateway-health.test.ts +209 -0
  124. package/src/__tests__/managed-avatar-client.test.ts +23 -12
  125. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -2
  126. package/src/__tests__/managed-store.test.ts +29 -12
  127. package/src/__tests__/managed-twitter-guardrails.test.ts +353 -0
  128. package/src/__tests__/mcp-cli.test.ts +1 -1
  129. package/src/__tests__/mcp-health-check.test.ts +1 -1
  130. package/src/__tests__/media-generate-image.test.ts +1 -1
  131. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -4
  132. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +9 -6
  133. package/src/__tests__/memory-regressions.test.ts +1 -166
  134. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  135. package/src/__tests__/migration-export-http.test.ts +2 -2
  136. package/src/__tests__/migration-transport.test.ts +44 -0
  137. package/src/__tests__/non-member-access-request.test.ts +49 -36
  138. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  139. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  140. package/src/__tests__/notification-decision-strategy.test.ts +4 -4
  141. package/src/__tests__/notification-deep-link.test.ts +3 -3
  142. package/src/__tests__/notification-guardian-path.test.ts +6 -44
  143. package/src/__tests__/notification-routing-intent.test.ts +11 -7
  144. package/src/__tests__/oauth-cli.test.ts +1 -1
  145. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -6
  146. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  147. package/src/__tests__/platform.test.ts +168 -5
  148. package/src/__tests__/playbook-execution.test.ts +0 -2
  149. package/src/__tests__/playbook-tools.test.ts +0 -2
  150. package/src/__tests__/pricing.test.ts +125 -0
  151. package/src/__tests__/provider-error-scenarios.test.ts +9 -3
  152. package/src/__tests__/recording-handler.test.ts +46 -80
  153. package/src/__tests__/recording-state-machine.test.ts +112 -183
  154. package/src/__tests__/registry.test.ts +1 -1
  155. package/src/__tests__/relay-server.test.ts +69 -71
  156. package/src/__tests__/reminder-store.test.ts +3 -3
  157. package/src/__tests__/request-file-tool.test.ts +2 -2
  158. package/src/__tests__/ride-shotgun-handler.test.ts +2 -33
  159. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -3
  160. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +4 -4
  162. package/src/__tests__/schedule-store.test.ts +13 -4
  163. package/src/__tests__/schedule-tools.test.ts +0 -2
  164. package/src/__tests__/scheduler-recurrence.test.ts +3 -4
  165. package/src/__tests__/scoped-approval-grants.test.ts +3 -5
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +6 -8
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +1 -1
  168. package/src/__tests__/secret-response-routing.test.ts +1 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  170. package/src/__tests__/sequence-store.test.ts +0 -2
  171. package/src/__tests__/server-history-render.test.ts +2 -199
  172. package/src/__tests__/session-abort-tool-results.test.ts +9 -3
  173. package/src/__tests__/session-agent-loop.test.ts +107 -3
  174. package/src/__tests__/session-confirmation-signals.test.ts +10 -4
  175. package/src/__tests__/session-conflict-gate.test.ts +9 -3
  176. package/src/__tests__/session-init.benchmark.test.ts +22 -13
  177. package/src/__tests__/session-load-history-repair.test.ts +6 -3
  178. package/src/__tests__/session-pre-run-repair.test.ts +9 -3
  179. package/src/__tests__/session-profile-injection.test.ts +9 -3
  180. package/src/__tests__/session-provider-retry-repair.test.ts +10 -4
  181. package/src/__tests__/session-queue.test.ts +10 -4
  182. package/src/__tests__/session-runtime-assembly.test.ts +28 -18
  183. package/src/__tests__/session-skill-tools.test.ts +2 -3
  184. package/src/__tests__/session-slash-known.test.ts +11 -4
  185. package/src/__tests__/session-slash-queue.test.ts +11 -4
  186. package/src/__tests__/session-slash-unknown.test.ts +12 -4
  187. package/src/__tests__/session-surfaces-deselection.test.ts +2 -2
  188. package/src/__tests__/session-surfaces-task-progress.test.ts +3 -3
  189. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -1
  190. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
  191. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
  192. package/src/__tests__/session-usage.test.ts +180 -0
  193. package/src/__tests__/session-workspace-cache-state.test.ts +8 -2
  194. package/src/__tests__/session-workspace-injection.test.ts +8 -2
  195. package/src/__tests__/session-workspace-tool-tracking.test.ts +8 -2
  196. package/src/__tests__/skill-feature-flags-integration.test.ts +5 -11
  197. package/src/__tests__/skill-feature-flags.test.ts +1 -0
  198. package/src/__tests__/skill-include-graph.test.ts +1 -0
  199. package/src/__tests__/skill-load-feature-flag.test.ts +3 -9
  200. package/src/__tests__/skill-load-tool.test.ts +90 -12
  201. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -15
  202. package/src/__tests__/skills-uninstall.test.ts +131 -0
  203. package/src/__tests__/skills.test.ts +32 -16
  204. package/src/__tests__/slack-block-formatting.test.ts +1 -1
  205. package/src/__tests__/slack-channel-config.test.ts +71 -12
  206. package/src/__tests__/slack-inbound-verification.test.ts +7 -7
  207. package/src/__tests__/slack-share-routes.test.ts +1 -1
  208. package/src/__tests__/slack-skill.test.ts +2 -2
  209. package/src/__tests__/slash-commands-catalog.test.ts +1 -0
  210. package/src/__tests__/slash-commands-resolver.test.ts +1 -0
  211. package/src/__tests__/starter-task-flow.test.ts +1 -1
  212. package/src/__tests__/subagent-manager-notify.test.ts +1 -1
  213. package/src/__tests__/subagent-tools.test.ts +2 -2
  214. package/src/__tests__/system-prompt.test.ts +4 -8
  215. package/src/__tests__/task-compiler.test.ts +0 -2
  216. package/src/__tests__/task-management-tools.test.ts +0 -2
  217. package/src/__tests__/task-runner.test.ts +0 -2
  218. package/src/__tests__/task-scheduler.test.ts +2 -2
  219. package/src/__tests__/telegram-bot-username-resolution.test.ts +46 -44
  220. package/src/__tests__/terminal-tools.test.ts +1 -11
  221. package/src/__tests__/thread-seed-composer.test.ts +3 -1
  222. package/src/__tests__/tool-approval-handler.test.ts +5 -7
  223. package/src/__tests__/tool-executor.test.ts +2 -2
  224. package/src/__tests__/tool-grant-request-escalation.test.ts +3 -5
  225. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  226. package/src/__tests__/tool-profiling-listener.test.ts +1 -1
  227. package/src/__tests__/tool-trace-listener.test.ts +1 -2
  228. package/src/__tests__/trace-emitter.test.ts +1 -1
  229. package/src/__tests__/trust-context-guards.test.ts +1 -1
  230. package/src/__tests__/trust-store.test.ts +44 -395
  231. package/src/__tests__/trusted-contact-approval-notifier.test.ts +6 -8
  232. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +5 -7
  233. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +6 -6
  234. package/src/__tests__/trusted-contact-multichannel.test.ts +54 -47
  235. package/src/__tests__/trusted-contact-verification.test.ts +12 -12
  236. package/src/__tests__/twilio-config.test.ts +11 -2
  237. package/src/__tests__/twilio-provider.test.ts +6 -4
  238. package/src/__tests__/twilio-routes.test.ts +408 -86
  239. package/src/__tests__/twitter-platform-proxy-client.test.ts +450 -0
  240. package/src/__tests__/update-bulletin-format.test.ts +1 -1
  241. package/src/__tests__/update-bulletin-state.test.ts +1 -1
  242. package/src/__tests__/update-bulletin.test.ts +4 -8
  243. package/src/__tests__/update-template-contract.test.ts +1 -1
  244. package/src/__tests__/usage-cache-backfill-migration.test.ts +406 -0
  245. package/src/__tests__/usage-routes.test.ts +23 -5
  246. package/src/__tests__/user-reference.test.ts +1 -1
  247. package/src/__tests__/{guardian-control-plane-policy.test.ts → verification-control-plane-policy.test.ts} +142 -170
  248. package/src/__tests__/{guardian-verification-intent-routing.test.ts → verification-session-intent-routing.test.ts} +16 -16
  249. package/src/__tests__/view-image-tool.test.ts +0 -2
  250. package/src/__tests__/voice-ingress-preflight.test.ts +36 -0
  251. package/src/__tests__/voice-invite-redemption.test.ts +18 -18
  252. package/src/__tests__/voice-scoped-grant-consumer.test.ts +7 -7
  253. package/src/__tests__/voice-session-bridge.test.ts +14 -16
  254. package/src/__tests__/workspace-policy.test.ts +1 -1
  255. package/src/approvals/AGENTS.md +4 -4
  256. package/src/approvals/approval-primitive.ts +2 -2
  257. package/src/approvals/guardian-decision-primitive.ts +1 -1
  258. package/src/approvals/guardian-request-resolvers.ts +3 -4
  259. package/src/bundler/app-bundler.ts +29 -217
  260. package/src/bundler/app-compiler.ts +131 -103
  261. package/src/bundler/compiler-tools.ts +248 -0
  262. package/src/calls/active-call-lease.ts +207 -0
  263. package/src/calls/call-constants.ts +0 -7
  264. package/src/calls/call-controller.ts +1 -1
  265. package/src/calls/call-conversation-messages.ts +6 -6
  266. package/src/calls/call-domain.ts +73 -38
  267. package/src/calls/call-pointer-message-composer.ts +6 -6
  268. package/src/calls/call-pointer-messages.ts +14 -13
  269. package/src/calls/call-recovery.ts +2 -0
  270. package/src/calls/call-store.ts +21 -28
  271. package/src/calls/guardian-action-sweep.ts +6 -8
  272. package/src/calls/guardian-dispatch.ts +2 -6
  273. package/src/calls/relay-access-wait.ts +4 -4
  274. package/src/calls/relay-server.ts +69 -80
  275. package/src/calls/relay-setup-router.ts +16 -21
  276. package/src/calls/relay-verification.ts +27 -28
  277. package/src/calls/twilio-config.ts +28 -3
  278. package/src/calls/twilio-provider.ts +5 -5
  279. package/src/calls/twilio-rest.ts +26 -27
  280. package/src/calls/twilio-routes.ts +67 -54
  281. package/src/calls/types.ts +8 -8
  282. package/src/calls/voice-ingress-preflight.ts +110 -0
  283. package/src/calls/voice-session-bridge.ts +7 -7
  284. package/src/channels/config.ts +1 -10
  285. package/src/{config/channel-permission-profiles.ts → channels/permission-profiles.ts} +1 -1
  286. package/src/channels/types.ts +2 -13
  287. package/src/cli/__tests__/notifications.test.ts +1 -1
  288. package/src/{amazon → cli/commands/amazon}/client.ts +99 -42
  289. package/src/cli/{amazon.ts → commands/amazon/index.ts} +12 -17
  290. package/src/{amazon → cli/commands/amazon}/request-extractor.ts +39 -3
  291. package/src/cli/commands/amazon/session.ts +116 -0
  292. package/src/cli/{audit.ts → commands/audit.ts} +2 -4
  293. package/src/cli/{autonomy.ts → commands/autonomy.ts} +1 -3
  294. package/src/cli/commands/browser-relay.ts +520 -0
  295. package/src/cli/commands/channel-verification-sessions.ts +442 -0
  296. package/src/cli/{completions.ts → commands/completions.ts} +1 -3
  297. package/src/cli/{config.ts → commands/config.ts} +3 -5
  298. package/src/cli/{contacts.ts → commands/contacts.ts} +263 -16
  299. package/src/cli/{credentials.ts → commands/credentials.ts} +9 -10
  300. package/src/cli/{default-action.ts → commands/default-action.ts} +3 -3
  301. package/src/cli/{dev.ts → commands/dev.ts} +4 -6
  302. package/src/cli/{doctor.ts → commands/doctor.ts} +36 -60
  303. package/src/cli/{email.ts → commands/email.ts} +2 -2
  304. package/src/cli/{keys.ts → commands/keys.ts} +6 -6
  305. package/src/cli/{map.ts → commands/map.ts} +85 -93
  306. package/src/cli/{mcp.ts → commands/mcp.ts} +5 -7
  307. package/src/cli/{memory.ts → commands/memory.ts} +6 -7
  308. package/src/cli/{notifications.ts → commands/notifications.ts} +8 -10
  309. package/src/cli/{oauth.ts → commands/oauth.ts} +2 -2
  310. package/src/cli/commands/platform.ts +176 -0
  311. package/src/cli/{sequence.ts → commands/sequence.ts} +3 -3
  312. package/src/cli/{sessions.ts → commands/sessions.ts} +32 -52
  313. package/src/cli/commands/skills.ts +498 -0
  314. package/src/cli/{trust.ts → commands/trust.ts} +2 -4
  315. package/src/{__tests__/twitter-cli-error-shaping.test.ts → cli/commands/twitter/__tests__/cli-error-shaping.test.ts} +43 -2
  316. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +483 -0
  317. package/src/{__tests__/twitter-cli-routing.test.ts → cli/commands/twitter/__tests__/cli-routing.test.ts} +130 -4
  318. package/src/{__tests__/twitter-oauth-client.test.ts → cli/commands/twitter/__tests__/oauth-client.test.ts} +2 -2
  319. package/src/{twitter → cli/commands/twitter}/client.ts +17 -7
  320. package/src/cli/{twitter.ts → commands/twitter/index.ts} +322 -273
  321. package/src/cli/commands/twitter/router.ts +396 -0
  322. package/src/cli/commands/twitter/session.ts +121 -0
  323. package/src/cli/db.ts +1 -0
  324. package/src/cli/http-client.ts +87 -0
  325. package/src/cli/logger.ts +6 -0
  326. package/src/cli/main-screen.tsx +4 -3
  327. package/src/cli/output.ts +19 -0
  328. package/src/cli/program.ts +29 -27
  329. package/src/cli/reference.ts +27 -37
  330. package/src/cli.ts +452 -240
  331. package/src/config/assistant-feature-flags.ts +3 -15
  332. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +3 -6
  333. package/src/config/bundled-skills/agentmail/SKILL.md +4 -4
  334. package/src/config/bundled-skills/amazon/SKILL.md +15 -5
  335. package/src/config/bundled-skills/api-mapping/SKILL.md +4 -4
  336. package/src/config/bundled-skills/app-builder/SKILL.md +21 -6
  337. package/src/config/bundled-skills/browser/SKILL.md +4 -5
  338. package/src/config/bundled-skills/chatgpt-import/SKILL.md +4 -4
  339. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  340. package/src/config/bundled-skills/claude-code/SKILL.md +4 -4
  341. package/src/config/bundled-skills/cli-discover/SKILL.md +4 -4
  342. package/src/config/bundled-skills/computer-use/SKILL.md +4 -4
  343. package/src/config/bundled-skills/contacts/SKILL.md +87 -229
  344. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +4 -4
  345. package/src/config/bundled-skills/document/SKILL.md +4 -3
  346. package/src/config/bundled-skills/document-writer/SKILL.md +4 -4
  347. package/src/config/bundled-skills/doordash/SKILL.md +4 -11
  348. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +8 -16
  349. package/src/config/bundled-skills/doordash/doordash-cli.ts +120 -86
  350. package/src/config/bundled-skills/doordash/lib/session.ts +1 -2
  351. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +26 -9
  352. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +140 -0
  353. package/src/config/bundled-skills/email-setup/SKILL.md +4 -4
  354. package/src/config/bundled-skills/followups/SKILL.md +4 -3
  355. package/src/config/bundled-skills/frontend-design/SKILL.md +2 -0
  356. package/src/config/bundled-skills/google-calendar/SKILL.md +4 -4
  357. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +4 -6
  358. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +26 -41
  359. package/src/config/bundled-skills/image-studio/SKILL.md +4 -5
  360. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -1
  361. package/src/config/bundled-skills/influencer/SKILL.md +19 -19
  362. package/src/{influencer → config/bundled-skills/influencer/scripts}/client.ts +73 -56
  363. package/src/config/bundled-skills/influencer/scripts/influencer.ts +267 -0
  364. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -2
  365. package/src/config/bundled-skills/macos-automation/SKILL.md +4 -5
  366. package/src/config/bundled-skills/mcp-setup/SKILL.md +4 -4
  367. package/src/config/bundled-skills/media-processing/SKILL.md +3 -2
  368. package/src/config/bundled-skills/messaging/SKILL.md +6 -33
  369. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -5
  370. package/src/config/bundled-skills/notifications/SKILL.md +4 -4
  371. package/src/config/bundled-skills/notion/SKILL.md +4 -4
  372. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +4 -5
  373. package/src/config/bundled-skills/oauth-setup/SKILL.md +4 -5
  374. package/src/config/bundled-skills/phone-calls/SKILL.md +24 -458
  375. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +83 -0
  376. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +57 -0
  377. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +67 -0
  378. package/src/config/bundled-skills/playbooks/SKILL.md +4 -3
  379. package/src/config/bundled-skills/public-ingress/SKILL.md +65 -14
  380. package/src/config/bundled-skills/reminder/SKILL.md +4 -3
  381. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +4 -6
  382. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  383. package/src/config/bundled-skills/screen-recording/SKILL.md +4 -3
  384. package/src/config/bundled-skills/self-upgrade/SKILL.md +4 -4
  385. package/src/config/bundled-skills/skills-catalog/SKILL.md +4 -4
  386. package/src/config/bundled-skills/slack/SKILL.md +4 -8
  387. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +1 -1
  388. package/src/config/bundled-skills/slack-app-setup/SKILL.md +66 -88
  389. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +4 -5
  390. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +4 -5
  391. package/src/config/bundled-skills/start-the-day/SKILL.md +4 -4
  392. package/src/config/bundled-skills/subagent/SKILL.md +4 -3
  393. package/src/config/bundled-skills/tasks/SKILL.md +4 -3
  394. package/src/config/bundled-skills/telegram-setup/SKILL.md +63 -112
  395. package/src/config/bundled-skills/time-based-actions/SKILL.md +4 -3
  396. package/src/config/bundled-skills/transcribe/SKILL.md +4 -3
  397. package/src/config/bundled-skills/twilio-setup/SKILL.md +23 -50
  398. package/src/config/bundled-skills/twitter/SKILL.md +56 -14
  399. package/src/config/bundled-skills/typescript-eval/SKILL.md +4 -4
  400. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +4 -5
  401. package/src/config/bundled-skills/voice-setup/SKILL.md +19 -45
  402. package/src/config/bundled-skills/watcher/SKILL.md +4 -3
  403. package/src/config/env-registry.ts +1 -10
  404. package/src/config/feature-flag-registry.json +0 -16
  405. package/src/config/loader.ts +78 -38
  406. package/src/config/schema.ts +143 -106
  407. package/src/config/schemas/channels.ts +80 -0
  408. package/src/config/schemas/heartbeat.ts +51 -0
  409. package/src/config/schemas/inference.ts +136 -0
  410. package/src/config/schemas/ingress.ts +81 -0
  411. package/src/config/schemas/logging.ts +21 -0
  412. package/src/config/schemas/memory-lifecycle.ts +67 -0
  413. package/src/config/schemas/memory-processing.ts +215 -0
  414. package/src/config/schemas/memory-retrieval.ts +222 -0
  415. package/src/config/schemas/memory-storage.ts +83 -0
  416. package/src/config/schemas/memory.ts +58 -0
  417. package/src/config/schemas/platform.ts +64 -0
  418. package/src/config/schemas/security.ts +54 -0
  419. package/src/config/schemas/swarm.ts +50 -0
  420. package/src/config/schemas/timeouts.ts +47 -0
  421. package/src/config/{agent-schema.ts → schemas/workspace-git.ts} +0 -97
  422. package/src/config/skill-state.ts +3 -13
  423. package/src/config/skills.ts +233 -75
  424. package/src/config/types.ts +1 -20
  425. package/src/contacts/contact-store.ts +12 -49
  426. package/src/contacts/contacts-write.ts +1 -5
  427. package/src/contacts/index.ts +0 -2
  428. package/src/contacts/types.ts +0 -8
  429. package/src/context/window-manager.ts +73 -14
  430. package/src/daemon/assistant-attachments.ts +9 -0
  431. package/src/daemon/computer-use-session.ts +3 -3
  432. package/src/daemon/connection-policy.ts +6 -21
  433. package/src/daemon/context-overflow-policy.ts +1 -1
  434. package/src/daemon/daemon-control.ts +46 -54
  435. package/src/daemon/doordash-steps.ts +1 -1
  436. package/src/daemon/handlers/config-channels.ts +407 -71
  437. package/src/daemon/handlers/config-ingress.ts +17 -85
  438. package/src/daemon/handlers/config-model.ts +145 -123
  439. package/src/daemon/handlers/config-slack-channel.ts +43 -29
  440. package/src/daemon/handlers/config-telegram.ts +32 -27
  441. package/src/daemon/handlers/config-voice.ts +1 -4
  442. package/src/daemon/handlers/dictation.ts +11 -16
  443. package/src/daemon/handlers/identity.ts +5 -6
  444. package/src/daemon/handlers/pairing.ts +5 -13
  445. package/src/daemon/handlers/recording.ts +97 -199
  446. package/src/daemon/handlers/session-history.ts +110 -96
  447. package/src/daemon/handlers/session-user-message.ts +29 -57
  448. package/src/daemon/handlers/sessions.ts +240 -137
  449. package/src/daemon/handlers/shared.ts +62 -95
  450. package/src/daemon/handlers/skills.ts +492 -543
  451. package/src/daemon/lifecycle.ts +168 -55
  452. package/src/daemon/main.ts +1 -0
  453. package/src/daemon/{ipc-contract.ts → message-protocol.ts} +49 -49
  454. package/src/daemon/{ipc-contract → message-types}/computer-use.ts +0 -3
  455. package/src/daemon/{ipc-contract → message-types}/diagnostics.ts +0 -16
  456. package/src/daemon/{ipc-contract → message-types}/integrations.ts +29 -13
  457. package/src/daemon/{ipc-contract → message-types}/memory.ts +8 -0
  458. package/src/daemon/{ipc-contract → message-types}/notifications.ts +15 -1
  459. package/src/daemon/{ipc-contract → message-types}/sessions.ts +1 -0
  460. package/src/daemon/{ipc-contract → message-types}/shared.ts +0 -8
  461. package/src/daemon/{ipc-contract → message-types}/workspace.ts +2 -2
  462. package/src/daemon/providers-setup.ts +0 -5
  463. package/src/daemon/recording-executor.ts +0 -7
  464. package/src/daemon/ride-shotgun-handler.ts +9 -13
  465. package/src/daemon/server.ts +136 -510
  466. package/src/daemon/session-agent-loop-handlers.ts +22 -7
  467. package/src/daemon/session-agent-loop.ts +86 -24
  468. package/src/daemon/session-attachments.ts +1 -1
  469. package/src/daemon/session-error.ts +1 -1
  470. package/src/daemon/session-history.ts +20 -15
  471. package/src/daemon/session-lifecycle.ts +9 -7
  472. package/src/daemon/session-memory.ts +15 -1
  473. package/src/daemon/session-messaging.ts +10 -6
  474. package/src/daemon/session-notifiers.ts +10 -8
  475. package/src/daemon/session-process.ts +34 -25
  476. package/src/daemon/session-queue-manager.ts +1 -1
  477. package/src/daemon/session-runtime-assembly.ts +6 -25
  478. package/src/daemon/session-surfaces.ts +2 -2
  479. package/src/daemon/session-tool-setup.ts +1 -1
  480. package/src/daemon/session-usage.ts +119 -18
  481. package/src/daemon/session.ts +13 -9
  482. package/src/daemon/tool-side-effects.ts +6 -5
  483. package/src/daemon/trace-emitter.ts +1 -1
  484. package/src/daemon/{guardian-verification-intent.ts → verification-session-intent.ts} +16 -16
  485. package/src/daemon/watch-handler.ts +2 -5
  486. package/src/email/service.ts +8 -8
  487. package/src/events/domain-events.ts +0 -1
  488. package/src/events/tool-notification-listener.ts +1 -1
  489. package/src/followups/followup-store.ts +1 -2
  490. package/src/followups/types.ts +0 -6
  491. package/src/heartbeat/heartbeat-service.ts +1 -1
  492. package/src/inbound/platform-callback-registration.ts +1 -1
  493. package/src/inbound/public-ingress-urls.ts +0 -8
  494. package/src/index.ts +12 -0
  495. package/src/mcp/client.ts +1 -1
  496. package/src/mcp/manager.ts +1 -1
  497. package/src/memory/app-store.ts +1 -42
  498. package/src/memory/{guardian-verification.ts → channel-verification-sessions.ts} +110 -93
  499. package/src/memory/conversation-attention-store.ts +154 -0
  500. package/src/memory/conversation-bootstrap.ts +1 -1
  501. package/src/memory/conversation-crud.ts +53 -1
  502. package/src/memory/conversation-display-order-migration.ts +2 -3
  503. package/src/memory/conversation-queries.ts +1 -29
  504. package/src/memory/conversation-title-service.ts +26 -21
  505. package/src/memory/db-connection.ts +1 -8
  506. package/src/memory/db-init.ts +20 -0
  507. package/src/memory/delivery-crud.ts +4 -34
  508. package/src/memory/external-conversation-store.ts +1 -1
  509. package/src/memory/format-recall.ts +47 -0
  510. package/src/memory/guardian-action-store.ts +4 -5
  511. package/src/memory/guardian-rate-limits.ts +0 -3
  512. package/src/memory/invite-store.ts +1 -1
  513. package/src/memory/job-handlers/backfill.ts +9 -2
  514. package/src/memory/job-handlers/extraction.ts +2 -7
  515. package/src/memory/job-handlers/summarization.ts +1 -1
  516. package/src/memory/llm-usage-store.ts +11 -0
  517. package/src/memory/migrations/114-notifications.ts +12 -40
  518. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +357 -0
  519. package/src/memory/migrations/141-rename-verification-table.ts +55 -0
  520. package/src/memory/migrations/142-rename-verification-session-id-column.ts +32 -0
  521. package/src/memory/migrations/143-rename-guardian-verification-values.ts +48 -0
  522. package/src/memory/migrations/144-rename-voice-to-phone.ts +147 -0
  523. package/src/memory/migrations/index.ts +5 -0
  524. package/src/memory/migrations/registry.ts +30 -0
  525. package/src/memory/qdrant-circuit-breaker.ts +5 -0
  526. package/src/memory/retriever.test.ts +707 -0
  527. package/src/memory/retriever.ts +120 -116
  528. package/src/memory/schema/calls.ts +3 -7
  529. package/src/memory/schema/guardian.ts +2 -2
  530. package/src/memory/search/lexical.ts +4 -1
  531. package/src/memory/search/query-expansion.test.ts +70 -0
  532. package/src/memory/search/query-expansion.ts +118 -0
  533. package/src/memory/search/types.ts +18 -17
  534. package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
  535. package/src/messaging/providers/whatsapp/adapter.ts +1 -4
  536. package/src/messaging/registry.ts +0 -1
  537. package/src/notifications/README.md +13 -22
  538. package/src/notifications/adapters/macos.ts +1 -1
  539. package/src/notifications/conversation-pairing.ts +2 -2
  540. package/src/notifications/copy-composer.ts +2 -2
  541. package/src/notifications/decision-engine.ts +1 -10
  542. package/src/notifications/destination-resolver.ts +2 -3
  543. package/src/notifications/emit-signal.ts +2 -8
  544. package/src/notifications/guardian-question-mode.ts +5 -8
  545. package/src/notifications/signal.ts +1 -2
  546. package/src/notifications/types.ts +1 -1
  547. package/src/oauth/token-persistence.ts +25 -1
  548. package/src/permissions/checker.ts +4 -29
  549. package/src/permissions/defaults.ts +6 -6
  550. package/src/permissions/prompter.ts +1 -1
  551. package/src/permissions/secret-prompter.ts +1 -1
  552. package/src/permissions/shell-identity.ts +1 -1
  553. package/src/permissions/trust-store.ts +13 -76
  554. package/src/permissions/workspace-policy.ts +1 -1
  555. package/src/{config → prompts}/computer-use-prompt.ts +1 -1
  556. package/src/{config → prompts}/system-prompt.ts +40 -21
  557. package/src/runtime/AGENTS.md +6 -8
  558. package/src/runtime/access-request-helper.ts +36 -55
  559. package/src/runtime/actor-trust-resolver.ts +1 -24
  560. package/src/runtime/approval-message-composer.ts +6 -2
  561. package/src/runtime/assistant-event.ts +1 -1
  562. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +1 -1
  563. package/src/runtime/auth/__tests__/subject.test.ts +32 -0
  564. package/src/runtime/auth/route-policy.ts +140 -24
  565. package/src/runtime/auth/subject.ts +9 -0
  566. package/src/runtime/auth/token-service.ts +11 -0
  567. package/src/runtime/auth/types.ts +1 -1
  568. package/src/runtime/channel-approval-types.ts +1 -1
  569. package/src/runtime/channel-approvals.ts +1 -1
  570. package/src/runtime/channel-invite-transport.ts +0 -2
  571. package/src/runtime/channel-invite-transports/slack.ts +5 -19
  572. package/src/runtime/channel-invite-transports/telegram.ts +17 -34
  573. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  574. package/src/runtime/channel-readiness-service.ts +24 -159
  575. package/src/runtime/channel-readiness-types.ts +5 -1
  576. package/src/runtime/channel-reply-delivery.ts +43 -3
  577. package/src/runtime/channel-retry-sweep.ts +14 -22
  578. package/src/runtime/{channel-guardian-service.ts → channel-verification-service.ts} +50 -53
  579. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -3
  580. package/src/runtime/gateway-client.ts +12 -15
  581. package/src/runtime/guardian-action-followup-executor.ts +8 -73
  582. package/src/runtime/guardian-action-grant-minter.ts +45 -61
  583. package/src/runtime/guardian-action-message-composer.ts +4 -4
  584. package/src/runtime/guardian-reply-router.ts +3 -3
  585. package/src/runtime/http-server.ts +133 -24
  586. package/src/runtime/http-types.ts +34 -1
  587. package/src/runtime/invite-instruction-generator.ts +1 -3
  588. package/src/runtime/invite-redemption-service.ts +5 -5
  589. package/src/runtime/invite-service.ts +7 -7
  590. package/src/runtime/local-actor-identity.ts +28 -2
  591. package/src/runtime/local-gateway-health.ts +275 -0
  592. package/src/runtime/middleware/twilio-validation.ts +3 -3
  593. package/src/runtime/migrations/migration-transport.ts +18 -3
  594. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  595. package/src/runtime/nl-approval-parser.ts +2 -3
  596. package/src/runtime/routes/access-request-decision.ts +2 -2
  597. package/src/runtime/routes/app-management-routes.ts +921 -0
  598. package/src/runtime/routes/approval-routes.ts +76 -7
  599. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +38 -203
  600. package/src/runtime/routes/channel-delivery-routes.ts +5 -4
  601. package/src/runtime/routes/channel-route-shared.ts +1 -3
  602. package/src/runtime/routes/channel-routes.ts +1 -4
  603. package/src/runtime/routes/channel-verification-routes.ts +257 -0
  604. package/src/runtime/routes/computer-use-routes.ts +595 -0
  605. package/src/runtime/routes/contact-routes.ts +1 -317
  606. package/src/runtime/routes/conversation-attention-routes.ts +6 -5
  607. package/src/runtime/routes/conversation-routes.ts +11 -18
  608. package/src/runtime/routes/debug-routes.ts +1 -1
  609. package/src/runtime/routes/diagnostics-routes.ts +813 -0
  610. package/src/runtime/routes/documents-routes.ts +227 -0
  611. package/src/runtime/routes/guardian-approval-interception.ts +25 -48
  612. package/src/runtime/routes/guardian-bootstrap-routes.ts +3 -3
  613. package/src/runtime/routes/guardian-expiry-sweep.ts +2 -2
  614. package/src/runtime/routes/guardian-refresh-routes.ts +11 -6
  615. package/src/runtime/routes/inbound-conversation.ts +3 -10
  616. package/src/runtime/routes/inbound-message-handler.ts +7 -6
  617. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +22 -22
  618. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +44 -0
  619. package/src/runtime/routes/inbound-stages/background-dispatch.ts +140 -22
  620. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +4 -4
  621. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
  622. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +3 -3
  623. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  624. package/src/runtime/routes/inbound-stages/verification-intercept.ts +13 -14
  625. package/src/runtime/routes/integrations/slack/channel.ts +72 -0
  626. package/src/runtime/routes/{slack-share-routes.ts → integrations/slack/share.ts} +9 -9
  627. package/src/runtime/routes/integrations/telegram.ts +111 -0
  628. package/src/runtime/routes/integrations/twilio.ts +451 -0
  629. package/src/runtime/routes/invite-routes.ts +2 -2
  630. package/src/runtime/routes/pairing-routes.ts +1 -1
  631. package/src/runtime/routes/recording-routes.ts +332 -0
  632. package/src/{daemon/handlers/config-scheduling.ts → runtime/routes/schedule-routes.ts} +91 -106
  633. package/src/runtime/routes/session-management-routes.ts +167 -0
  634. package/src/runtime/routes/session-query-routes.ts +204 -0
  635. package/src/runtime/routes/settings-routes.ts +977 -0
  636. package/src/runtime/routes/skills-routes.ts +266 -0
  637. package/src/runtime/routes/subagents-routes.ts +246 -0
  638. package/src/runtime/routes/surface-action-routes.ts +100 -10
  639. package/src/runtime/routes/surface-content-routes.ts +1 -1
  640. package/src/runtime/routes/work-items-routes.ts +809 -0
  641. package/src/runtime/routes/workspace-routes.test.ts +778 -0
  642. package/src/runtime/routes/workspace-routes.ts +410 -0
  643. package/src/runtime/routes/workspace-utils.ts +88 -0
  644. package/src/runtime/telegram-streaming-delivery.test.ts +597 -0
  645. package/src/runtime/telegram-streaming-delivery.ts +380 -0
  646. package/src/runtime/tool-grant-request-helper.ts +1 -2
  647. package/src/runtime/trust-context-resolver.ts +0 -1
  648. package/src/runtime/{guardian-outbound-actions.ts → verification-outbound-actions.ts} +23 -188
  649. package/src/runtime/verification-rate-limiter.ts +2 -2
  650. package/src/runtime/{guardian-verification-templates.ts → verification-templates.ts} +2 -28
  651. package/src/schedule/integration-status.ts +2 -2
  652. package/src/schedule/schedule-store.ts +7 -9
  653. package/src/sequence/engine.ts +1 -1
  654. package/src/skills/active-skill-tools.ts +0 -8
  655. package/src/skills/clawhub.ts +1 -10
  656. package/src/skills/managed-store.ts +14 -4
  657. package/src/skills/slash-commands.ts +1 -1
  658. package/src/subagent/manager.ts +1 -1
  659. package/src/subagent/types.ts +1 -1
  660. package/src/tasks/SPEC.md +10 -10
  661. package/src/tasks/task-scheduler.ts +1 -1
  662. package/src/telegram/bot-username.ts +13 -0
  663. package/src/tools/assets/materialize.ts +1 -1
  664. package/src/tools/assets/search.ts +1 -1
  665. package/src/tools/browser/browser-execution.ts +2 -2
  666. package/src/tools/browser/browser-manager.ts +88 -11
  667. package/src/tools/browser/browser-screencast.ts +1 -1
  668. package/src/tools/browser/headless-browser.ts +0 -17
  669. package/src/tools/browser/jit-auth.ts +1 -1
  670. package/src/tools/browser/recording-store.ts +19 -1
  671. package/src/tools/browser/runtime-check.ts +4 -2
  672. package/src/tools/calls/call-start.ts +3 -3
  673. package/src/tools/credentials/metadata-store.ts +0 -13
  674. package/src/tools/credentials/vault.ts +7 -31
  675. package/src/tools/followups/followup_create.ts +0 -8
  676. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  677. package/src/tools/memory/definitions.ts +32 -10
  678. package/src/tools/memory/handlers.test.ts +573 -0
  679. package/src/tools/memory/handlers.ts +222 -65
  680. package/src/tools/memory/register.ts +53 -24
  681. package/src/tools/network/script-proxy/session-manager.ts +1 -12
  682. package/src/tools/schedule/update.ts +0 -8
  683. package/src/tools/skills/load.ts +3 -3
  684. package/src/tools/subagent/read.ts +1 -1
  685. package/src/tools/system/voice-config.ts +2 -14
  686. package/src/tools/terminal/safe-env.ts +5 -18
  687. package/src/tools/tool-approval-handler.ts +4 -4
  688. package/src/tools/tool-manifest.ts +4 -2
  689. package/src/tools/types.ts +1 -1
  690. package/src/tools/{guardian-control-plane-policy.ts → verification-control-plane-policy.ts} +37 -39
  691. package/src/twitter/platform-proxy-client.ts +405 -0
  692. package/src/usage/types.ts +21 -0
  693. package/src/util/canonicalize-identity.ts +2 -6
  694. package/src/util/cookie-session.ts +35 -51
  695. package/src/util/platform.ts +93 -86
  696. package/src/util/pricing.ts +180 -43
  697. package/src/work-items/work-item-runner.ts +1 -1
  698. package/scripts/ipc/check-contract-inventory.ts +0 -107
  699. package/scripts/ipc/check-swift-decoder-drift.ts +0 -184
  700. package/scripts/ipc/generate-swift.ts +0 -528
  701. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -3043
  702. package/src/__tests__/app-migration.test.ts +0 -148
  703. package/src/__tests__/config-loader-migration.test.ts +0 -85
  704. package/src/__tests__/daemon-lifecycle.test.ts +0 -715
  705. package/src/__tests__/daemon-server-session-init.test.ts +0 -864
  706. package/src/__tests__/guardian-actions-endpoint.test.ts +0 -1452
  707. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +0 -228
  708. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -397
  709. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -218
  710. package/src/__tests__/handlers-slack-config.test.ts +0 -140
  711. package/src/__tests__/handlers-telegram-config.test.ts +0 -1317
  712. package/src/__tests__/handlers-twitter-config.test.ts +0 -1145
  713. package/src/__tests__/ingress-reconcile.test.ts +0 -606
  714. package/src/__tests__/integrations-cli.test.ts +0 -232
  715. package/src/__tests__/ipc-blob-store.test.ts +0 -329
  716. package/src/__tests__/ipc-contract-inventory.test.ts +0 -69
  717. package/src/__tests__/ipc-contract.test.ts +0 -76
  718. package/src/__tests__/ipc-protocol.test.ts +0 -120
  719. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -250
  720. package/src/__tests__/ipc-snapshot.test.ts +0 -2197
  721. package/src/__tests__/ipc-validate.test.ts +0 -471
  722. package/src/__tests__/migration-cli-flows.test.ts +0 -186
  723. package/src/__tests__/migration-ordering.test.ts +0 -267
  724. package/src/__tests__/oauth-connect-handler.test.ts +0 -361
  725. package/src/__tests__/platform-move-helper.test.ts +0 -108
  726. package/src/__tests__/platform-socket-path.test.ts +0 -52
  727. package/src/__tests__/platform-workspace-migration.test.ts +0 -1051
  728. package/src/__tests__/recording-intent-handler.test.ts +0 -1155
  729. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +0 -127
  730. package/src/__tests__/sms-messaging-provider.test.ts +0 -156
  731. package/src/__tests__/tool-permission-simulate-handler.test.ts +0 -367
  732. package/src/__tests__/twitter-auth-handler.test.ts +0 -561
  733. package/src/__tests__/work-item-output.test.ts +0 -150
  734. package/src/amazon/session.ts +0 -58
  735. package/src/cli/channels.ts +0 -51
  736. package/src/cli/influencer.ts +0 -319
  737. package/src/cli/integrations.ts +0 -372
  738. package/src/cli/ipc-client.ts +0 -88
  739. package/src/config/bundled-skills/configure-settings/SKILL.md +0 -86
  740. package/src/config/bundled-skills/doordash/lib/shared/ipc.ts +0 -32
  741. package/src/config/bundled-skills/sms-setup/SKILL.md +0 -210
  742. package/src/config/core-schema.ts +0 -434
  743. package/src/config/memory-schema.ts +0 -617
  744. package/src/daemon/auth-manager.ts +0 -106
  745. package/src/daemon/handlers/apps.ts +0 -758
  746. package/src/daemon/handlers/avatar.ts +0 -73
  747. package/src/daemon/handlers/browser.ts +0 -3
  748. package/src/daemon/handlers/computer-use.ts +0 -231
  749. package/src/daemon/handlers/config-dispatch.ts +0 -29
  750. package/src/daemon/handlers/config-heartbeat.ts +0 -299
  751. package/src/daemon/handlers/config-inbox.ts +0 -457
  752. package/src/daemon/handlers/config-integrations.ts +0 -409
  753. package/src/daemon/handlers/config-platform.ts +0 -77
  754. package/src/daemon/handlers/config-slack.ts +0 -41
  755. package/src/daemon/handlers/config-tools.ts +0 -226
  756. package/src/daemon/handlers/config-trust.ts +0 -135
  757. package/src/daemon/handlers/config.ts +0 -64
  758. package/src/daemon/handlers/contacts.ts +0 -193
  759. package/src/daemon/handlers/diagnostics.ts +0 -382
  760. package/src/daemon/handlers/documents.ts +0 -188
  761. package/src/daemon/handlers/guardian-actions.ts +0 -82
  762. package/src/daemon/handlers/home-base.ts +0 -82
  763. package/src/daemon/handlers/index.ts +0 -222
  764. package/src/daemon/handlers/misc.ts +0 -1139
  765. package/src/daemon/handlers/navigate-settings.ts +0 -29
  766. package/src/daemon/handlers/oauth-connect.ts +0 -202
  767. package/src/daemon/handlers/open-bundle-handler.ts +0 -88
  768. package/src/daemon/handlers/publish.ts +0 -176
  769. package/src/daemon/handlers/signing.ts +0 -56
  770. package/src/daemon/handlers/subagents.ts +0 -286
  771. package/src/daemon/handlers/twitter-auth.ts +0 -220
  772. package/src/daemon/handlers/work-items.ts +0 -796
  773. package/src/daemon/handlers/workspace-files.ts +0 -84
  774. package/src/daemon/handlers.ts +0 -16
  775. package/src/daemon/ipc-blob-store.ts +0 -246
  776. package/src/daemon/ipc-contract-inventory.json +0 -348
  777. package/src/daemon/ipc-contract-inventory.ts +0 -202
  778. package/src/daemon/ipc-handler.ts +0 -120
  779. package/src/daemon/ipc-protocol.ts +0 -85
  780. package/src/daemon/ipc-validate.ts +0 -254
  781. package/src/memory/app-migration.ts +0 -114
  782. package/src/memory/channel-delivery-store.ts +0 -40
  783. package/src/memory/channel-guardian-store.ts +0 -83
  784. package/src/memory/conversation-store.ts +0 -102
  785. package/src/memory/schema-migration.ts +0 -38
  786. package/src/messaging/providers/sms/adapter.ts +0 -232
  787. package/src/messaging/providers/sms/client.ts +0 -93
  788. package/src/messaging/providers/sms/types.ts +0 -7
  789. package/src/migrations/config-merge.ts +0 -62
  790. package/src/migrations/data-layout.ts +0 -89
  791. package/src/migrations/data-merge.ts +0 -44
  792. package/src/migrations/hooks-merge.ts +0 -118
  793. package/src/migrations/index.ts +0 -6
  794. package/src/migrations/log.ts +0 -28
  795. package/src/migrations/skills-merge.ts +0 -44
  796. package/src/migrations/workspace-layout.ts +0 -94
  797. package/src/notifications/adapters/sms.ts +0 -94
  798. package/src/runtime/channel-approval-parser.ts +0 -123
  799. package/src/runtime/channel-invite-transports/sms.ts +0 -53
  800. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +0 -82
  801. package/src/runtime/routes/integration-routes.ts +0 -381
  802. package/src/runtime/routes/twilio-routes.ts +0 -1251
  803. package/src/twitter/router.ts +0 -131
  804. package/src/twitter/session.ts +0 -54
  805. package/src/watcher/providers/slack.ts +0 -282
  806. /package/src/{amazon → cli/commands/amazon}/cart.ts +0 -0
  807. /package/src/{amazon → cli/commands/amazon}/checkout.ts +0 -0
  808. /package/src/{amazon → cli/commands/amazon}/product-details.ts +0 -0
  809. /package/src/{amazon → cli/commands/amazon}/search.ts +0 -0
  810. /package/src/{twitter → cli/commands/twitter}/oauth-client.ts +0 -0
  811. /package/src/config/{calls-schema.ts → schemas/calls.ts} +0 -0
  812. /package/src/config/{elevenlabs-schema.ts → schemas/elevenlabs.ts} +0 -0
  813. /package/src/config/{mcp-schema.ts → schemas/mcp.ts} +0 -0
  814. /package/src/config/{notifications-schema.ts → schemas/notifications.ts} +0 -0
  815. /package/src/config/{sandbox-schema.ts → schemas/sandbox.ts} +0 -0
  816. /package/src/config/{skills-schema.ts → schemas/skills.ts} +0 -0
  817. /package/src/daemon/{ipc-contract → message-types}/apps.ts +0 -0
  818. /package/src/daemon/{ipc-contract → message-types}/browser.ts +0 -0
  819. /package/src/daemon/{ipc-contract → message-types}/contacts.ts +0 -0
  820. /package/src/daemon/{ipc-contract → message-types}/documents.ts +0 -0
  821. /package/src/daemon/{ipc-contract → message-types}/guardian-actions.ts +0 -0
  822. /package/src/daemon/{ipc-contract → message-types}/inbox.ts +0 -0
  823. /package/src/daemon/{ipc-contract → message-types}/messages.ts +0 -0
  824. /package/src/daemon/{ipc-contract → message-types}/pairing.ts +0 -0
  825. /package/src/daemon/{ipc-contract → message-types}/schedules.ts +0 -0
  826. /package/src/daemon/{ipc-contract → message-types}/settings.ts +0 -0
  827. /package/src/daemon/{ipc-contract → message-types}/skills.ts +0 -0
  828. /package/src/daemon/{ipc-contract → message-types}/subagents.ts +0 -0
  829. /package/src/daemon/{ipc-contract → message-types}/surfaces.ts +0 -0
  830. /package/src/daemon/{ipc-contract → message-types}/trust.ts +0 -0
  831. /package/src/daemon/{ipc-contract → message-types}/work-items.ts +0 -0
  832. /package/src/{cli/email-guardrails.ts → email/guardrails.ts} +0 -0
  833. /package/src/{config → prompts}/__tests__/build-cli-reference-section.test.ts +0 -0
  834. /package/src/{config → prompts}/templates/BOOTSTRAP.md +0 -0
  835. /package/src/{config → prompts}/templates/IDENTITY.md +0 -0
  836. /package/src/{config → prompts}/templates/SOUL.md +0 -0
  837. /package/src/{config → prompts}/templates/UPDATES.md +0 -0
  838. /package/src/{config → prompts}/templates/USER.md +0 -0
  839. /package/src/{config → prompts}/update-bulletin-format.ts +0 -0
  840. /package/src/{config → prompts}/update-bulletin-state.ts +0 -0
  841. /package/src/{config → prompts}/update-bulletin-template-path.ts +0 -0
  842. /package/src/{config → prompts}/update-bulletin.ts +0 -0
  843. /package/src/{config → prompts}/user-reference.ts +0 -0
@@ -1,1155 +0,0 @@
1
- import * as net from "node:net";
2
- import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
3
-
4
- const actualEnv = await import("../config/env.js");
5
- mock.module("../config/env.js", () => ({
6
- ...actualEnv,
7
- isHttpAuthDisabled: () => true,
8
- isMonitoringEnabled: () => false,
9
- }));
10
-
11
- // ─── Mocks (must be before any imports that depend on them) ─────────────────
12
-
13
- const noop = () => {};
14
- const noopLogger = {
15
- info: noop,
16
- warn: noop,
17
- error: noop,
18
- debug: noop,
19
- trace: noop,
20
- fatal: noop,
21
- child: () => noopLogger,
22
- };
23
-
24
- // eslint-disable-next-line @typescript-eslint/no-require-imports
25
- const realLogger = require("../util/logger.js");
26
- mock.module("../util/logger.js", () => ({
27
- ...realLogger,
28
- getLogger: () => noopLogger,
29
- isDebug: () => false,
30
- truncateForLog: (v: string) => v,
31
- }));
32
-
33
- mock.module("../config/loader.js", () => ({
34
- getConfig: () => ({
35
- ui: {},
36
-
37
- daemon: { standaloneRecording: true },
38
- provider: "mock-provider",
39
- model: "mock-model",
40
- permissions: { mode: "workspace" },
41
- apiKeys: {},
42
- sandbox: { enabled: false },
43
- timeouts: { toolExecutionTimeoutSec: 30, permissionTimeoutSec: 5 },
44
- skills: { load: { extraDirs: [] } },
45
- secretDetection: { enabled: false, allowOneTimeSend: false },
46
- contextWindow: {
47
- enabled: true,
48
- maxInputTokens: 180000,
49
- targetInputTokens: 110000,
50
- compactThreshold: 0.8,
51
- preserveRecentUserTurns: 8,
52
- summaryMaxTokens: 1200,
53
- chunkTokens: 12000,
54
- },
55
- }),
56
- invalidateConfigCache: noop,
57
- loadConfig: noop,
58
- saveConfig: noop,
59
- loadRawConfig: () => ({}),
60
- saveRawConfig: noop,
61
- getNestedValue: () => undefined,
62
- setNestedValue: noop,
63
- }));
64
-
65
- // ── Mock identity-helpers ──────────────────────────────────────────────────
66
-
67
- let mockAssistantName: string | null = null;
68
-
69
- mock.module("../daemon/identity-helpers.js", () => ({
70
- getAssistantName: () => mockAssistantName,
71
- }));
72
-
73
- // ── Mock recording-intent — we control the resolution result ───────────────
74
- //
75
- // Bun's mock.module() is global and persists across test files in the same
76
- // process (no per-file isolation). To prevent this mock from breaking
77
- // recording-intent.test.ts (which tests the REAL resolveRecordingIntent),
78
- // we capture real function references before mocking and use a globalThis
79
- // flag to conditionally delegate to them. The flag is only true while this
80
- // file's tests are running; after this file completes (afterAll), the mock
81
- // transparently delegates to the real implementation.
82
-
83
- type RecordingIntentResult =
84
- | { kind: "none" }
85
- | { kind: "start_only" }
86
- | { kind: "stop_only" }
87
- | { kind: "start_with_remainder"; remainder: string }
88
- | { kind: "stop_with_remainder"; remainder: string }
89
- | { kind: "start_and_stop_only" }
90
- | { kind: "start_and_stop_with_remainder"; remainder: string }
91
- | { kind: "restart_only" }
92
- | { kind: "restart_with_remainder"; remainder: string }
93
- | { kind: "pause_only" }
94
- | { kind: "resume_only" };
95
-
96
- let mockIntentResult: RecordingIntentResult = { kind: "none" };
97
-
98
- // Capture real function references BEFORE mock.module replaces the module.
99
- // require() at this point returns the real module since mock.module has not
100
- // been called yet for this specifier.
101
- // eslint-disable-next-line @typescript-eslint/no-require-imports
102
- const _realRecordingIntentMod = require("../daemon/recording-intent.js");
103
- const _realResolveRecordingIntent =
104
- _realRecordingIntentMod.resolveRecordingIntent;
105
- const _realStripDynamicNames = _realRecordingIntentMod.stripDynamicNames;
106
-
107
- // Flag: when true, the mock returns controlled test values; when false, it
108
- // delegates to the real implementation. Starts false so that if the mock
109
- // bleeds to other test files, those files get the real behavior.
110
- (globalThis as any).__riHandlerUseMockIntent = false;
111
-
112
- mock.module("../daemon/recording-intent.js", () => ({
113
- resolveRecordingIntent: (...args: any[]) => {
114
- if ((globalThis as any).__riHandlerUseMockIntent) return mockIntentResult;
115
- return _realResolveRecordingIntent(...args);
116
- },
117
- stripDynamicNames: (...args: any[]) => {
118
- if ((globalThis as any).__riHandlerUseMockIntent) return args[0];
119
- return _realStripDynamicNames(...args);
120
- },
121
- }));
122
-
123
- // ── Mock recording-executor — we control the execution output ──────────────
124
- //
125
- // Same transparent-mock pattern as recording-intent above. We try to capture
126
- // the real exports before mocking; if the require fails (e.g., due to missing
127
- // transitive dependencies when this file runs in isolation), we fall back to
128
- // the controlled mock since the real module is not needed in that scenario.
129
-
130
- interface RecordingExecutionOutput {
131
- handled: boolean;
132
- responseText?: string;
133
- remainderText?: string;
134
- pendingStart?: boolean;
135
- pendingStop?: boolean;
136
- pendingRestart?: boolean;
137
- recordingStarted?: boolean;
138
- }
139
-
140
- let mockExecuteResult: RecordingExecutionOutput = { handled: false };
141
- let executorCalled = false;
142
-
143
- let _realExecuteRecordingIntent: ((...args: any[]) => any) | null = null;
144
- try {
145
- // eslint-disable-next-line @typescript-eslint/no-require-imports
146
- const _mod = require("../daemon/recording-executor.js");
147
- _realExecuteRecordingIntent = _mod.executeRecordingIntent;
148
- } catch {
149
- // Transitive dependency loading may fail when this file runs alone;
150
- // the controlled mock will be used exclusively in that case.
151
- }
152
-
153
- mock.module("../daemon/recording-executor.js", () => ({
154
- executeRecordingIntent: (...args: any[]) => {
155
- if ((globalThis as any).__riHandlerUseMockIntent) {
156
- executorCalled = true;
157
- return mockExecuteResult;
158
- }
159
- if (_realExecuteRecordingIntent)
160
- return _realExecuteRecordingIntent(...args);
161
- // Fallback if real function was not captured
162
- return { handled: false };
163
- },
164
- }));
165
-
166
- // ── Mock recording handlers ────────────────────────────────────────────────
167
- //
168
- // Same transparent-mock pattern. The intent test file re-mocks this module
169
- // inside its own describe block, which will override this mock for those tests.
170
- // The transparent fallback here ensures that if a third test file imports
171
- // handlers/recording.js, it gets the real behavior.
172
-
173
- let recordingStartCalled = false;
174
- let _recordingStopCalled = false;
175
- let recordingRestartCalled = false;
176
- let recordingPauseCalled = false;
177
- let recordingResumeCalled = false;
178
-
179
- let _realHandleRecordingStart: ((...args: any[]) => any) | null = null;
180
- let _realHandleRecordingStop: ((...args: any[]) => any) | null = null;
181
- let _realHandleRecordingRestart: ((...args: any[]) => any) | null = null;
182
- let _realHandleRecordingPause: ((...args: any[]) => any) | null = null;
183
- let _realHandleRecordingResume: ((...args: any[]) => any) | null = null;
184
- let _realIsRecordingIdle: ((...args: any[]) => any) | null = null;
185
- let _realRecordingHandlers: any = {};
186
- let _realResetRecordingState: ((...args: any[]) => any) | null = null;
187
-
188
- try {
189
- // eslint-disable-next-line @typescript-eslint/no-require-imports
190
- const _mod = require("../daemon/handlers/recording.js");
191
- _realHandleRecordingStart = _mod.handleRecordingStart;
192
- _realHandleRecordingStop = _mod.handleRecordingStop;
193
- _realHandleRecordingRestart = _mod.handleRecordingRestart;
194
- _realHandleRecordingPause = _mod.handleRecordingPause;
195
- _realHandleRecordingResume = _mod.handleRecordingResume;
196
- _realIsRecordingIdle = _mod.isRecordingIdle;
197
- _realRecordingHandlers = _mod.recordingHandlers ?? {};
198
- _realResetRecordingState = _mod.__resetRecordingState;
199
- } catch {
200
- // Same as above — controlled mock will be used exclusively.
201
- }
202
-
203
- mock.module("../daemon/handlers/recording.js", () => ({
204
- handleRecordingStart: (...args: any[]) => {
205
- if ((globalThis as any).__riHandlerUseMockIntent) {
206
- recordingStartCalled = true;
207
- return "mock-recording-id";
208
- }
209
- return _realHandleRecordingStart?.(...args);
210
- },
211
- handleRecordingStop: (...args: any[]) => {
212
- if ((globalThis as any).__riHandlerUseMockIntent) {
213
- _recordingStopCalled = true;
214
- return "mock-recording-id";
215
- }
216
- return _realHandleRecordingStop?.(...args);
217
- },
218
- handleRecordingRestart: (...args: any[]) => {
219
- if ((globalThis as any).__riHandlerUseMockIntent) {
220
- recordingRestartCalled = true;
221
- return {
222
- initiated: true,
223
- responseText: "Restarting screen recording.",
224
- operationToken: "mock-token",
225
- };
226
- }
227
- return _realHandleRecordingRestart?.(...args);
228
- },
229
- handleRecordingPause: (...args: any[]) => {
230
- if ((globalThis as any).__riHandlerUseMockIntent) {
231
- recordingPauseCalled = true;
232
- return "mock-recording-id";
233
- }
234
- return _realHandleRecordingPause?.(...args);
235
- },
236
- handleRecordingResume: (...args: any[]) => {
237
- if ((globalThis as any).__riHandlerUseMockIntent) {
238
- recordingResumeCalled = true;
239
- return "mock-recording-id";
240
- }
241
- return _realHandleRecordingResume?.(...args);
242
- },
243
- isRecordingIdle: (...args: any[]) => {
244
- if ((globalThis as any).__riHandlerUseMockIntent) return true;
245
- return _realIsRecordingIdle?.(...args) ?? true;
246
- },
247
- recordingHandlers: _realRecordingHandlers,
248
- __resetRecordingState: (...args: any[]) => {
249
- if ((globalThis as any).__riHandlerUseMockIntent) return;
250
- return _realResetRecordingState?.(...args);
251
- },
252
- }));
253
-
254
- // ── Mock conversation store ────────────────────────────────────────────────
255
-
256
- mock.module("../memory/conversation-store.js", () => ({
257
- getConversationThreadType: () => "default",
258
- setConversationOriginChannelIfUnset: () => {},
259
- updateConversationContextWindow: () => {},
260
- deleteMessageById: () => {},
261
- updateConversationUsage: () => {},
262
- provenanceFromTrustContext: () => ({
263
- source: "user",
264
- trustContext: undefined,
265
- }),
266
- getConversationOriginInterface: () => null,
267
- getConversationOriginChannel: () => null,
268
- getMessages: () => [],
269
- addMessage: () => ({ id: "msg-mock", role: "assistant", content: "" }),
270
- createConversation: (titleOrOpts?: string | { title?: string }) => {
271
- const title =
272
- typeof titleOrOpts === "string"
273
- ? titleOrOpts
274
- : (titleOrOpts?.title ?? "Untitled");
275
- return { id: "conv-mock", title };
276
- },
277
- getConversation: () => ({ id: "conv-mock" }),
278
- updateConversationTitle: noop,
279
- clearAll: noop,
280
- listConversations: () => [],
281
- countConversations: () => 0,
282
- searchConversations: () => [],
283
- deleteConversation: noop,
284
- }));
285
-
286
- mock.module("../memory/conversation-title-service.js", () => ({
287
- GENERATING_TITLE: "(generating\u2026)",
288
- queueGenerateConversationTitle: noop,
289
- UNTITLED_FALLBACK: "Untitled",
290
- }));
291
-
292
- mock.module("../memory/attachments-store.js", () => ({
293
- getAttachmentsForMessage: () => [],
294
- uploadFileBackedAttachment: () => ({ id: "att-mock" }),
295
- linkAttachmentToMessage: noop,
296
- setAttachmentThumbnail: noop,
297
- }));
298
-
299
- // ── Mock security ──────────────────────────────────────────────────────────
300
-
301
- mock.module("../security/secret-ingress.js", () => ({
302
- checkIngressForSecrets: () => ({ blocked: false }),
303
- }));
304
-
305
- mock.module("../security/secret-scanner.js", () => ({
306
- redactSecrets: (text: string) => text,
307
- compileCustomPatterns: () => [],
308
- }));
309
-
310
- // ── Mock classifier (for task_submit fallthrough) ──────────────────────────
311
-
312
- let classifierCalled = false;
313
-
314
- mock.module("../daemon/classifier.js", () => ({
315
- classifyInteraction: async () => {
316
- classifierCalled = true;
317
- return "text_qa";
318
- },
319
- }));
320
-
321
- // ── Mock slash commands ────────────────────────────────────────────────────
322
-
323
- mock.module("../skills/slash-commands.js", () => ({
324
- parseSlashCandidate: () => ({ kind: "none" }),
325
- }));
326
-
327
- // ── Mock computer-use handler ──────────────────────────────────────────────
328
-
329
- mock.module("../daemon/handlers/computer-use.js", () => ({
330
- handleCuSessionCreate: noop,
331
- }));
332
-
333
- // ── Mock provider ──────────────────────────────────────────────────────────
334
-
335
- mock.module("../providers/provider-send-message.js", () => ({
336
- getConfiguredProvider: () => null,
337
- extractText: (_response: unknown) => "",
338
- createTimeout: (_ms: number) => ({
339
- signal: new AbortController().signal,
340
- cleanup: () => {},
341
- }),
342
- userMessage: (text: string) => ({ role: "user", content: text }),
343
- }));
344
-
345
- // ── Mock external conversation store ───────────────────────────────────────
346
-
347
- mock.module("../memory/external-conversation-store.js", () => ({
348
- getBindingByChannelChat: () => null,
349
- getBindingsForConversations: () => new Map(),
350
- upsertBinding: () => {},
351
- upsertOutboundBinding: () => {},
352
- }));
353
-
354
- // ── Mock subagent manager ──────────────────────────────────────────────────
355
-
356
- mock.module("../subagent/index.js", () => ({
357
- getSubagentManager: () => ({
358
- abortAllForParent: noop,
359
- }),
360
- }));
361
-
362
- // ── Mock IPC protocol helpers ──────────────────────────────────────────────
363
-
364
- const actualIpcProtocol = await import("../daemon/ipc-protocol.js");
365
- mock.module("../daemon/ipc-protocol.js", () => ({
366
- ...actualIpcProtocol,
367
- normalizeThreadType: (t: string) => t ?? "primary",
368
- }));
369
-
370
- // ── Mock session error helpers ─────────────────────────────────────────────
371
-
372
- mock.module("../daemon/session-error.js", () => ({
373
- classifySessionError: () => ({
374
- code: "UNKNOWN",
375
- userMessage: "error",
376
- retryable: false,
377
- }),
378
- buildSessionErrorMessage: () => ({ type: "error", message: "error" }),
379
- }));
380
-
381
- // ── Mock video thumbnail ───────────────────────────────────────────────────
382
-
383
- mock.module("../daemon/video-thumbnail.js", () => ({
384
- generateVideoThumbnail: async () => null,
385
- }));
386
-
387
- // ── Mock IPC blob store ────────────────────────────────────────────────────
388
-
389
- mock.module("../daemon/ipc-blob-store.js", () => ({
390
- isValidBlobId: () => false,
391
- resolveBlobPath: () => "",
392
- deleteBlob: noop,
393
- }));
394
-
395
- // ── Mock channels/types ────────────────────────────────────────────────────
396
-
397
- mock.module("../channels/types.js", () => ({
398
- parseChannelId: () => "vellum",
399
- parseInterfaceId: () => "vellum",
400
- isChannelId: () => true,
401
- }));
402
-
403
- // ─── Imports (after mocks) ──────────────────────────────────────────────────
404
-
405
- import type { HandlerContext } from "../daemon/handlers/shared.js";
406
- import { DebouncerMap } from "../util/debounce.js";
407
-
408
- // ─── Helpers ────────────────────────────────────────────────────────────────
409
-
410
- function createCtx(overrides?: Partial<HandlerContext>): {
411
- ctx: HandlerContext;
412
- sent: Array<{ type: string; [k: string]: unknown }>;
413
- fakeSocket: net.Socket;
414
- } {
415
- const sent: Array<{ type: string; [k: string]: unknown }> = [];
416
- const fakeSocket = {} as net.Socket;
417
- const socketToSession = new Map<net.Socket, string>();
418
-
419
- // Create a fake session that fulfills minimum interface for handleUserMessage
420
- const fakeSession = {
421
- hasEscalationHandler: () => true,
422
- traceEmitter: { emit: noop },
423
- enqueueMessage: () => ({ rejected: false, queued: false }),
424
- setTurnChannelContext: noop,
425
- setTurnInterfaceContext: noop,
426
- setAssistantId: noop,
427
- setChannelCapabilities: noop,
428
- setTrustContext: noop,
429
- setAuthContext: noop,
430
- setCommandIntent: noop,
431
- updateClient: noop,
432
- processMessage: async () => {},
433
- getQueueDepth: () => 0,
434
- setPreactivatedSkillIds: noop,
435
- redirectToSecurePrompt: noop,
436
- setEscalationHandler: noop,
437
- dispose: noop,
438
- hasPendingConfirmation: () => false,
439
- hasPendingSecret: () => false,
440
- isProcessing: () => false,
441
- messages: [] as any[],
442
- };
443
-
444
- const sessions = new Map<string, any>();
445
-
446
- const ctx: HandlerContext = {
447
- sessions,
448
- socketToSession,
449
- cuSessions: new Map(),
450
- socketToCuSession: new Map(),
451
- cuObservationParseSequence: new Map(),
452
- socketSandboxOverride: new Map(),
453
- sharedRequestTimestamps: [],
454
- debounceTimers: new DebouncerMap({ defaultDelayMs: 200 }),
455
- suppressConfigReload: false,
456
- setSuppressConfigReload: noop,
457
- updateConfigFingerprint: noop,
458
- send: (_socket, msg) => {
459
- sent.push(msg as { type: string; [k: string]: unknown });
460
- },
461
- broadcast: noop,
462
- clearAllSessions: () => 0,
463
- getOrCreateSession: async (conversationId: string) => {
464
- sessions.set(conversationId, fakeSession);
465
- return fakeSession as any;
466
- },
467
- touchSession: noop,
468
- ...overrides,
469
- };
470
-
471
- return { ctx, sent, fakeSocket };
472
- }
473
-
474
- function resetMockState(): void {
475
- // Enable mock mode for this file's tests
476
- (globalThis as any).__riHandlerUseMockIntent = true;
477
- mockIntentResult = { kind: "none" };
478
- mockExecuteResult = { handled: false };
479
- mockAssistantName = null;
480
- recordingStartCalled = false;
481
- _recordingStopCalled = false;
482
- recordingRestartCalled = false;
483
- recordingPauseCalled = false;
484
- recordingResumeCalled = false;
485
- executorCalled = false;
486
- classifierCalled = false;
487
- }
488
-
489
- // Disable mock mode after all tests in this file complete, so that if the
490
- // mock bleeds to other test files they get the real implementation.
491
- afterAll(() => {
492
- (globalThis as any).__riHandlerUseMockIntent = false;
493
- });
494
-
495
- // ─── Tests ──────────────────────────────────────────────────────────────────
496
-
497
- describe("recording intent handler integration — handleTaskSubmit", () => {
498
- beforeEach(resetMockState);
499
-
500
- test("start_only → executeRecordingIntent called, sends task_routed + text_delta + message_complete, returns early", async () => {
501
- mockIntentResult = { kind: "start_only" };
502
- mockExecuteResult = {
503
- handled: true,
504
- responseText: "Starting screen recording.",
505
- recordingStarted: true,
506
- };
507
- const { ctx, sent, fakeSocket } = createCtx();
508
-
509
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
510
- await handleTaskSubmit(
511
- { type: "task_submit", task: "record my screen", source: "voice" } as any,
512
- fakeSocket,
513
- ctx,
514
- );
515
-
516
- expect(executorCalled).toBe(true);
517
- expect(classifierCalled).toBe(false);
518
-
519
- const types = sent.map((m) => m.type);
520
- expect(types).toContain("task_routed");
521
- expect(types).toContain("assistant_text_delta");
522
- expect(types).toContain("message_complete");
523
-
524
- const textDelta = sent.find((m) => m.type === "assistant_text_delta");
525
- expect(textDelta?.text).toBe("Starting screen recording.");
526
- });
527
-
528
- test("stop_only → executeRecordingIntent called, sends task_routed + text_delta + message_complete, returns early", async () => {
529
- mockIntentResult = { kind: "stop_only" };
530
- mockExecuteResult = {
531
- handled: true,
532
- responseText: "Stopping the recording.",
533
- };
534
- const { ctx, sent, fakeSocket } = createCtx();
535
-
536
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
537
- await handleTaskSubmit(
538
- { type: "task_submit", task: "stop recording", source: "voice" } as any,
539
- fakeSocket,
540
- ctx,
541
- );
542
-
543
- expect(executorCalled).toBe(true);
544
- expect(classifierCalled).toBe(false);
545
-
546
- const types = sent.map((m) => m.type);
547
- expect(types).toContain("task_routed");
548
- expect(types).toContain("assistant_text_delta");
549
- expect(types).toContain("message_complete");
550
-
551
- const textDelta = sent.find((m) => m.type === "assistant_text_delta");
552
- expect(textDelta?.text).toBe("Stopping the recording.");
553
- });
554
-
555
- test("start_with_remainder → defers recording, falls through to classifier with remaining text", async () => {
556
- mockIntentResult = {
557
- kind: "start_with_remainder",
558
- remainder: "open Safari",
559
- };
560
- mockExecuteResult = {
561
- handled: false,
562
- remainderText: "open Safari",
563
- pendingStart: true,
564
- };
565
- const { ctx, sent, fakeSocket } = createCtx();
566
-
567
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
568
- await handleTaskSubmit(
569
- {
570
- type: "task_submit",
571
- task: "open Safari and record my screen",
572
- source: "voice",
573
- } as any,
574
- fakeSocket,
575
- ctx,
576
- );
577
-
578
- expect(classifierCalled).toBe(true);
579
-
580
- // Should NOT have recording-only messages before the classifier output
581
- const recordingSpecific = sent.filter(
582
- (m) =>
583
- m.type === "assistant_text_delta" &&
584
- typeof m.text === "string" &&
585
- (m.text.includes("Starting screen recording") ||
586
- m.text.includes("Stopping the recording")),
587
- );
588
- expect(recordingSpecific).toHaveLength(0);
589
- });
590
-
591
- test("none → does NOT call executeRecordingIntent, falls through to classifier", async () => {
592
- mockIntentResult = { kind: "none" };
593
- const { ctx, sent: _sent, fakeSocket } = createCtx();
594
-
595
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
596
- await handleTaskSubmit(
597
- { type: "task_submit", task: "hello world", source: "voice" } as any,
598
- fakeSocket,
599
- ctx,
600
- );
601
-
602
- expect(executorCalled).toBe(false);
603
- expect(classifierCalled).toBe(true);
604
- });
605
-
606
- test("restart_only → executeRecordingIntent called, sends task_routed + text_delta + message_complete, returns early", async () => {
607
- mockIntentResult = { kind: "restart_only" };
608
- mockExecuteResult = {
609
- handled: true,
610
- responseText: "Restarting screen recording.",
611
- };
612
- const { ctx, sent, fakeSocket } = createCtx();
613
-
614
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
615
- await handleTaskSubmit(
616
- {
617
- type: "task_submit",
618
- task: "restart the recording",
619
- source: "voice",
620
- } as any,
621
- fakeSocket,
622
- ctx,
623
- );
624
-
625
- expect(executorCalled).toBe(true);
626
- expect(classifierCalled).toBe(false);
627
-
628
- const types = sent.map((m) => m.type);
629
- expect(types).toContain("task_routed");
630
- expect(types).toContain("assistant_text_delta");
631
- expect(types).toContain("message_complete");
632
-
633
- const textDelta = sent.find((m) => m.type === "assistant_text_delta");
634
- expect(textDelta?.text).toBe("Restarting screen recording.");
635
- });
636
-
637
- test("pause_only → executeRecordingIntent called, sends task_routed + text_delta + message_complete, returns early", async () => {
638
- mockIntentResult = { kind: "pause_only" };
639
- mockExecuteResult = {
640
- handled: true,
641
- responseText: "Pausing the recording.",
642
- };
643
- const { ctx, sent, fakeSocket } = createCtx();
644
-
645
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
646
- await handleTaskSubmit(
647
- {
648
- type: "task_submit",
649
- task: "pause the recording",
650
- source: "voice",
651
- } as any,
652
- fakeSocket,
653
- ctx,
654
- );
655
-
656
- expect(executorCalled).toBe(true);
657
- expect(classifierCalled).toBe(false);
658
-
659
- const types = sent.map((m) => m.type);
660
- expect(types).toContain("task_routed");
661
- expect(types).toContain("assistant_text_delta");
662
- expect(types).toContain("message_complete");
663
-
664
- const textDelta = sent.find((m) => m.type === "assistant_text_delta");
665
- expect(textDelta?.text).toBe("Pausing the recording.");
666
- });
667
-
668
- test("resume_only → executeRecordingIntent called, sends task_routed + text_delta + message_complete, returns early", async () => {
669
- mockIntentResult = { kind: "resume_only" };
670
- mockExecuteResult = {
671
- handled: true,
672
- responseText: "Resuming the recording.",
673
- };
674
- const { ctx, sent, fakeSocket } = createCtx();
675
-
676
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
677
- await handleTaskSubmit(
678
- {
679
- type: "task_submit",
680
- task: "resume the recording",
681
- source: "voice",
682
- } as any,
683
- fakeSocket,
684
- ctx,
685
- );
686
-
687
- expect(executorCalled).toBe(true);
688
- expect(classifierCalled).toBe(false);
689
-
690
- const types = sent.map((m) => m.type);
691
- expect(types).toContain("task_routed");
692
- expect(types).toContain("assistant_text_delta");
693
- expect(types).toContain("message_complete");
694
-
695
- const textDelta = sent.find((m) => m.type === "assistant_text_delta");
696
- expect(textDelta?.text).toBe("Resuming the recording.");
697
- });
698
-
699
- test("restart_with_remainder → defers restart, falls through to classifier with remaining text", async () => {
700
- mockIntentResult = {
701
- kind: "restart_with_remainder",
702
- remainder: "open Safari",
703
- };
704
- mockExecuteResult = {
705
- handled: false,
706
- remainderText: "open Safari",
707
- pendingRestart: true,
708
- };
709
- const { ctx, sent, fakeSocket } = createCtx();
710
-
711
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
712
- await handleTaskSubmit(
713
- {
714
- type: "task_submit",
715
- task: "restart the recording and open Safari",
716
- source: "voice",
717
- } as any,
718
- fakeSocket,
719
- ctx,
720
- );
721
-
722
- expect(classifierCalled).toBe(true);
723
-
724
- // Should NOT have restart-specific messages before classifier output
725
- const recordingSpecific = sent.filter(
726
- (m) =>
727
- m.type === "assistant_text_delta" &&
728
- typeof m.text === "string" &&
729
- m.text.includes("Restarting screen recording"),
730
- );
731
- expect(recordingSpecific).toHaveLength(0);
732
- });
733
-
734
- test("commandIntent restart → routes directly via handleRecordingRestart, returns early", async () => {
735
- // commandIntent bypasses text-based intent resolution entirely
736
- mockIntentResult = { kind: "none" }; // should not matter
737
- const { ctx, sent, fakeSocket } = createCtx();
738
-
739
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
740
- await handleTaskSubmit(
741
- {
742
- type: "task_submit",
743
- task: "restart recording",
744
- source: "voice",
745
- commandIntent: { domain: "screen_recording", action: "restart" },
746
- } as any,
747
- fakeSocket,
748
- ctx,
749
- );
750
-
751
- expect(recordingRestartCalled).toBe(true);
752
- expect(classifierCalled).toBe(false);
753
-
754
- const types = sent.map((m) => m.type);
755
- expect(types).toContain("task_routed");
756
- expect(types).toContain("assistant_text_delta");
757
- expect(types).toContain("message_complete");
758
- });
759
-
760
- test("commandIntent pause → routes directly via handleRecordingPause, returns early", async () => {
761
- mockIntentResult = { kind: "none" };
762
- const { ctx, sent, fakeSocket } = createCtx();
763
-
764
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
765
- await handleTaskSubmit(
766
- {
767
- type: "task_submit",
768
- task: "pause recording",
769
- source: "voice",
770
- commandIntent: { domain: "screen_recording", action: "pause" },
771
- } as any,
772
- fakeSocket,
773
- ctx,
774
- );
775
-
776
- expect(recordingPauseCalled).toBe(true);
777
- expect(classifierCalled).toBe(false);
778
-
779
- const types = sent.map((m) => m.type);
780
- expect(types).toContain("task_routed");
781
- expect(types).toContain("assistant_text_delta");
782
- expect(types).toContain("message_complete");
783
- });
784
-
785
- test("commandIntent resume → routes directly via handleRecordingResume, returns early", async () => {
786
- mockIntentResult = { kind: "none" };
787
- const { ctx, sent, fakeSocket } = createCtx();
788
-
789
- const { handleTaskSubmit } = await import("../daemon/handlers/misc.js");
790
- await handleTaskSubmit(
791
- {
792
- type: "task_submit",
793
- task: "resume recording",
794
- source: "voice",
795
- commandIntent: { domain: "screen_recording", action: "resume" },
796
- } as any,
797
- fakeSocket,
798
- ctx,
799
- );
800
-
801
- expect(recordingResumeCalled).toBe(true);
802
- expect(classifierCalled).toBe(false);
803
-
804
- const types = sent.map((m) => m.type);
805
- expect(types).toContain("task_routed");
806
- expect(types).toContain("assistant_text_delta");
807
- expect(types).toContain("message_complete");
808
- });
809
- });
810
-
811
- describe("recording intent handler integration — handleUserMessage", () => {
812
- beforeEach(resetMockState);
813
-
814
- test("start_only → executeRecordingIntent called, sends text_delta + message_complete, returns early", async () => {
815
- mockIntentResult = { kind: "start_only" };
816
- mockExecuteResult = {
817
- handled: true,
818
- responseText: "Starting screen recording.",
819
- recordingStarted: true,
820
- };
821
- const { ctx, sent, fakeSocket } = createCtx();
822
-
823
- const { handleUserMessage } =
824
- await import("../daemon/handlers/sessions.js");
825
- await handleUserMessage(
826
- {
827
- type: "user_message",
828
- sessionId: "test-session",
829
- content: "record my screen",
830
- interface: "vellum",
831
- } as any,
832
- fakeSocket,
833
- ctx,
834
- );
835
-
836
- expect(executorCalled).toBe(true);
837
-
838
- const types = sent.map((m) => m.type);
839
- expect(types).toContain("assistant_text_delta");
840
- expect(types).toContain("message_complete");
841
-
842
- // message_complete should be the last message sent (recording returned early)
843
- const lastMsg = sent[sent.length - 1];
844
- expect(lastMsg.type).toBe("message_complete");
845
- });
846
-
847
- test("stop_only → executeRecordingIntent called, sends text_delta + message_complete, returns early", async () => {
848
- mockIntentResult = { kind: "stop_only" };
849
- mockExecuteResult = {
850
- handled: true,
851
- responseText: "Stopping the recording.",
852
- };
853
- const { ctx, sent, fakeSocket } = createCtx();
854
-
855
- const { handleUserMessage } =
856
- await import("../daemon/handlers/sessions.js");
857
- await handleUserMessage(
858
- {
859
- type: "user_message",
860
- sessionId: "test-session",
861
- content: "stop recording",
862
- interface: "vellum",
863
- } as any,
864
- fakeSocket,
865
- ctx,
866
- );
867
-
868
- expect(executorCalled).toBe(true);
869
-
870
- const types = sent.map((m) => m.type);
871
- expect(types).toContain("assistant_text_delta");
872
- expect(types).toContain("message_complete");
873
-
874
- const lastMsg = sent[sent.length - 1];
875
- expect(lastMsg.type).toBe("message_complete");
876
- });
877
-
878
- test("start_with_remainder → does NOT return early, proceeds to normal message processing", async () => {
879
- mockIntentResult = {
880
- kind: "start_with_remainder",
881
- remainder: "open Safari",
882
- };
883
- mockExecuteResult = {
884
- handled: false,
885
- remainderText: "open Safari",
886
- pendingStart: true,
887
- };
888
- const { ctx, sent, fakeSocket } = createCtx();
889
-
890
- const { handleUserMessage } =
891
- await import("../daemon/handlers/sessions.js");
892
- await handleUserMessage(
893
- {
894
- type: "user_message",
895
- sessionId: "test-session",
896
- content: "open Safari and record my screen",
897
- interface: "vellum",
898
- } as any,
899
- fakeSocket,
900
- ctx,
901
- );
902
-
903
- // Should deferred recording start and proceed to normal processing
904
- expect(recordingStartCalled).toBe(true);
905
-
906
- // Should NOT have recording-specific intercept messages
907
- const recordingSpecific = sent.filter(
908
- (m) =>
909
- m.type === "assistant_text_delta" &&
910
- typeof m.text === "string" &&
911
- (m.text.includes("Starting screen recording") ||
912
- m.text.includes("Stopping the recording")),
913
- );
914
- expect(recordingSpecific).toHaveLength(0);
915
- });
916
-
917
- test("none → does NOT intercept, proceeds to normal message processing", async () => {
918
- mockIntentResult = { kind: "none" };
919
- const { ctx, sent, fakeSocket } = createCtx();
920
-
921
- const { handleUserMessage } =
922
- await import("../daemon/handlers/sessions.js");
923
- await handleUserMessage(
924
- {
925
- type: "user_message",
926
- sessionId: "test-session",
927
- content: "hello world",
928
- interface: "vellum",
929
- } as any,
930
- fakeSocket,
931
- ctx,
932
- );
933
-
934
- expect(executorCalled).toBe(false);
935
-
936
- // Should NOT have recording-specific messages
937
- const recordingSpecific = sent.filter(
938
- (m) =>
939
- m.type === "assistant_text_delta" &&
940
- typeof m.text === "string" &&
941
- (m.text.includes("Starting screen recording") ||
942
- m.text.includes("Stopping the recording")),
943
- );
944
- expect(recordingSpecific).toHaveLength(0);
945
- });
946
-
947
- test("restart_only → executeRecordingIntent called, sends text_delta + message_complete, returns early", async () => {
948
- mockIntentResult = { kind: "restart_only" };
949
- mockExecuteResult = {
950
- handled: true,
951
- responseText: "Restarting screen recording.",
952
- };
953
- const { ctx, sent, fakeSocket } = createCtx();
954
-
955
- const { handleUserMessage } =
956
- await import("../daemon/handlers/sessions.js");
957
- await handleUserMessage(
958
- {
959
- type: "user_message",
960
- sessionId: "test-session",
961
- content: "restart the recording",
962
- interface: "vellum",
963
- } as any,
964
- fakeSocket,
965
- ctx,
966
- );
967
-
968
- expect(executorCalled).toBe(true);
969
-
970
- const types = sent.map((m) => m.type);
971
- expect(types).toContain("assistant_text_delta");
972
- expect(types).toContain("message_complete");
973
-
974
- const lastMsg = sent[sent.length - 1];
975
- expect(lastMsg.type).toBe("message_complete");
976
- });
977
-
978
- test("pause_only → executeRecordingIntent called, sends text_delta + message_complete, returns early", async () => {
979
- mockIntentResult = { kind: "pause_only" };
980
- mockExecuteResult = {
981
- handled: true,
982
- responseText: "Pausing the recording.",
983
- };
984
- const { ctx, sent, fakeSocket } = createCtx();
985
-
986
- const { handleUserMessage } =
987
- await import("../daemon/handlers/sessions.js");
988
- await handleUserMessage(
989
- {
990
- type: "user_message",
991
- sessionId: "test-session",
992
- content: "pause the recording",
993
- interface: "vellum",
994
- } as any,
995
- fakeSocket,
996
- ctx,
997
- );
998
-
999
- expect(executorCalled).toBe(true);
1000
-
1001
- const types = sent.map((m) => m.type);
1002
- expect(types).toContain("assistant_text_delta");
1003
- expect(types).toContain("message_complete");
1004
-
1005
- const lastMsg = sent[sent.length - 1];
1006
- expect(lastMsg.type).toBe("message_complete");
1007
- });
1008
-
1009
- test("resume_only → executeRecordingIntent called, sends text_delta + message_complete, returns early", async () => {
1010
- mockIntentResult = { kind: "resume_only" };
1011
- mockExecuteResult = {
1012
- handled: true,
1013
- responseText: "Resuming the recording.",
1014
- };
1015
- const { ctx, sent, fakeSocket } = createCtx();
1016
-
1017
- const { handleUserMessage } =
1018
- await import("../daemon/handlers/sessions.js");
1019
- await handleUserMessage(
1020
- {
1021
- type: "user_message",
1022
- sessionId: "test-session",
1023
- content: "resume the recording",
1024
- interface: "vellum",
1025
- } as any,
1026
- fakeSocket,
1027
- ctx,
1028
- );
1029
-
1030
- expect(executorCalled).toBe(true);
1031
-
1032
- const types = sent.map((m) => m.type);
1033
- expect(types).toContain("assistant_text_delta");
1034
- expect(types).toContain("message_complete");
1035
-
1036
- const lastMsg = sent[sent.length - 1];
1037
- expect(lastMsg.type).toBe("message_complete");
1038
- });
1039
-
1040
- test("restart_with_remainder → defers restart, continues with remaining text", async () => {
1041
- mockIntentResult = {
1042
- kind: "restart_with_remainder",
1043
- remainder: "open Safari",
1044
- };
1045
- mockExecuteResult = {
1046
- handled: false,
1047
- remainderText: "open Safari",
1048
- pendingRestart: true,
1049
- };
1050
- const { ctx, sent, fakeSocket } = createCtx();
1051
-
1052
- const { handleUserMessage } =
1053
- await import("../daemon/handlers/sessions.js");
1054
- await handleUserMessage(
1055
- {
1056
- type: "user_message",
1057
- sessionId: "test-session",
1058
- content: "restart the recording and open Safari",
1059
- interface: "vellum",
1060
- } as any,
1061
- fakeSocket,
1062
- ctx,
1063
- );
1064
-
1065
- // Deferred restart should have been executed
1066
- expect(recordingRestartCalled).toBe(true);
1067
-
1068
- // Should NOT have restart-specific intercept messages
1069
- const recordingSpecific = sent.filter(
1070
- (m) =>
1071
- m.type === "assistant_text_delta" &&
1072
- typeof m.text === "string" &&
1073
- m.text.includes("Restarting screen recording"),
1074
- );
1075
- expect(recordingSpecific).toHaveLength(0);
1076
- });
1077
-
1078
- test("commandIntent restart → routes directly via handleRecordingRestart, returns early", async () => {
1079
- mockIntentResult = { kind: "none" };
1080
- const { ctx, sent, fakeSocket } = createCtx();
1081
-
1082
- const { handleUserMessage } =
1083
- await import("../daemon/handlers/sessions.js");
1084
- await handleUserMessage(
1085
- {
1086
- type: "user_message",
1087
- sessionId: "test-session",
1088
- content: "restart recording",
1089
- interface: "vellum",
1090
- commandIntent: { domain: "screen_recording", action: "restart" },
1091
- } as any,
1092
- fakeSocket,
1093
- ctx,
1094
- );
1095
-
1096
- expect(recordingRestartCalled).toBe(true);
1097
-
1098
- const types = sent.map((m) => m.type);
1099
- expect(types).toContain("assistant_text_delta");
1100
- expect(types).toContain("message_complete");
1101
-
1102
- const lastMsg = sent[sent.length - 1];
1103
- expect(lastMsg.type).toBe("message_complete");
1104
- });
1105
-
1106
- test("commandIntent pause → routes directly via handleRecordingPause, returns early", async () => {
1107
- mockIntentResult = { kind: "none" };
1108
- const { ctx, sent, fakeSocket } = createCtx();
1109
-
1110
- const { handleUserMessage } =
1111
- await import("../daemon/handlers/sessions.js");
1112
- await handleUserMessage(
1113
- {
1114
- type: "user_message",
1115
- sessionId: "test-session",
1116
- content: "pause recording",
1117
- interface: "vellum",
1118
- commandIntent: { domain: "screen_recording", action: "pause" },
1119
- } as any,
1120
- fakeSocket,
1121
- ctx,
1122
- );
1123
-
1124
- expect(recordingPauseCalled).toBe(true);
1125
-
1126
- const types = sent.map((m) => m.type);
1127
- expect(types).toContain("assistant_text_delta");
1128
- expect(types).toContain("message_complete");
1129
- });
1130
-
1131
- test("commandIntent resume → routes directly via handleRecordingResume, returns early", async () => {
1132
- mockIntentResult = { kind: "none" };
1133
- const { ctx, sent, fakeSocket } = createCtx();
1134
-
1135
- const { handleUserMessage } =
1136
- await import("../daemon/handlers/sessions.js");
1137
- await handleUserMessage(
1138
- {
1139
- type: "user_message",
1140
- sessionId: "test-session",
1141
- content: "resume recording",
1142
- interface: "vellum",
1143
- commandIntent: { domain: "screen_recording", action: "resume" },
1144
- } as any,
1145
- fakeSocket,
1146
- ctx,
1147
- );
1148
-
1149
- expect(recordingResumeCalled).toBe(true);
1150
-
1151
- const types = sent.map((m) => m.type);
1152
- expect(types).toContain("assistant_text_delta");
1153
- expect(types).toContain("message_complete");
1154
- });
1155
- });