@vellumai/assistant 0.4.44 → 0.4.45

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 (681) hide show
  1. package/.prettierignore +4 -0
  2. package/ARCHITECTURE.md +34 -31
  3. package/README.md +4 -4
  4. package/bun.lock +10 -35
  5. package/docs/architecture/integrations.md +102 -197
  6. package/docs/architecture/keychain-broker.md +1 -1
  7. package/docs/architecture/memory.md +2 -2
  8. package/docs/architecture/scheduling.md +1 -1
  9. package/docs/architecture/security.md +11 -11
  10. package/docs/error-handling.md +1 -1
  11. package/docs/trusted-contact-access.md +3 -3
  12. package/drizzle/meta/0000_snapshot.json +34 -100
  13. package/drizzle/meta/_journal.json +1 -1
  14. package/drizzle.config.ts +4 -4
  15. package/package.json +3 -2
  16. package/scripts/capture-x-graphql.ts +237 -141
  17. package/scripts/generate-bundled-tool-registry.ts +223 -0
  18. package/src/__tests__/access-request-decision.test.ts +0 -1
  19. package/src/__tests__/actor-token-service.test.ts +23 -24
  20. package/src/__tests__/agent-loop.test.ts +0 -131
  21. package/src/__tests__/always-loaded-tools-guard.test.ts +71 -0
  22. package/src/__tests__/amazon-cdp-integration.test.ts +11 -9
  23. package/src/__tests__/approval-primitive.test.ts +0 -1
  24. package/src/__tests__/approval-routes-http.test.ts +11 -1
  25. package/src/__tests__/asset-materialize-tool.test.ts +0 -1
  26. package/src/__tests__/asset-search-tool.test.ts +0 -1
  27. package/src/__tests__/assistant-attachment-directive.test.ts +1 -1
  28. package/src/__tests__/assistant-events-sse-hardening.test.ts +0 -1
  29. package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
  30. package/src/__tests__/assistant-feature-flags-integration.test.ts +70 -18
  31. package/src/__tests__/assistant-id-boundary-guard.test.ts +6 -6
  32. package/src/__tests__/attachments-store.test.ts +0 -1
  33. package/src/__tests__/avatar-e2e.test.ts +74 -115
  34. package/src/__tests__/avatar-router.test.ts +25 -62
  35. package/src/__tests__/browser-manager.test.ts +24 -0
  36. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +4 -3
  37. package/src/__tests__/browser-skill-endstate.test.ts +8 -11
  38. package/src/__tests__/btw-routes.test.ts +326 -0
  39. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +23 -9
  40. package/src/__tests__/call-controller.test.ts +0 -1
  41. package/src/__tests__/call-conversation-messages.test.ts +0 -1
  42. package/src/__tests__/call-domain.test.ts +0 -1
  43. package/src/__tests__/call-pointer-messages.test.ts +0 -1
  44. package/src/__tests__/call-recovery.test.ts +0 -1
  45. package/src/__tests__/call-routes-http.test.ts +0 -1
  46. package/src/__tests__/call-store.test.ts +0 -1
  47. package/src/__tests__/canonical-guardian-store.test.ts +0 -1
  48. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  49. package/src/__tests__/channel-approvals.test.ts +1 -1
  50. package/src/__tests__/channel-delivery-store.test.ts +0 -1
  51. package/src/__tests__/channel-guardian.test.ts +5 -7
  52. package/src/__tests__/channel-retry-sweep.test.ts +0 -1
  53. package/src/__tests__/checker.test.ts +4 -11
  54. package/src/__tests__/compaction.benchmark.test.ts +16 -14
  55. package/src/__tests__/computer-use-session-lifecycle.test.ts +10 -11
  56. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  57. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +2 -5
  58. package/src/__tests__/computer-use-tools.test.ts +35 -31
  59. package/src/__tests__/config-schema.test.ts +11 -15
  60. package/src/__tests__/config-watcher.test.ts +0 -1
  61. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  62. package/src/__tests__/conflict-store.test.ts +0 -1
  63. package/src/__tests__/connection-policy.test.ts +4 -7
  64. package/src/__tests__/contacts-tools.test.ts +0 -1
  65. package/src/__tests__/context-memory-e2e.test.ts +2 -4
  66. package/src/__tests__/context-overflow-reducer.test.ts +2 -4
  67. package/src/__tests__/context-window-manager.test.ts +147 -60
  68. package/src/__tests__/contradiction-checker.test.ts +0 -1
  69. package/src/__tests__/conversation-attention-store.test.ts +0 -1
  70. package/src/__tests__/conversation-attention-telegram.test.ts +1 -1
  71. package/src/__tests__/conversation-pairing.test.ts +2 -2
  72. package/src/__tests__/conversation-routes-guardian-reply.test.ts +25 -1
  73. package/src/__tests__/conversation-routes-slash-commands.test.ts +381 -0
  74. package/src/__tests__/conversation-store.test.ts +0 -1
  75. package/src/__tests__/conversation-unread-route.test.ts +1 -2
  76. package/src/__tests__/credential-security-invariants.test.ts +7 -8
  77. package/src/__tests__/cross-provider-web-search.test.ts +353 -0
  78. package/src/__tests__/daemon-assistant-events.test.ts +6 -7
  79. package/src/__tests__/db-schedule-syntax-migration.test.ts +15 -3
  80. package/src/__tests__/delete-managed-skill-tool.test.ts +5 -9
  81. package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -1
  82. package/src/__tests__/diagnostics-export.test.ts +189 -0
  83. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  84. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
  85. package/src/__tests__/entity-extractor.test.ts +0 -1
  86. package/src/__tests__/entity-search.test.ts +0 -1
  87. package/src/__tests__/ephemeral-permissions.test.ts +2 -4
  88. package/src/__tests__/file-read-tool.test.ts +86 -0
  89. package/src/__tests__/followup-tools.test.ts +0 -1
  90. package/src/__tests__/frontmatter.test.ts +77 -34
  91. package/src/__tests__/gateway-only-enforcement.test.ts +0 -1
  92. package/src/__tests__/gateway-only-guard.test.ts +1 -1
  93. package/src/__tests__/guardian-action-conversation-turn.test.ts +0 -1
  94. package/src/__tests__/guardian-action-followup-executor.test.ts +0 -1
  95. package/src/__tests__/guardian-action-followup-store.test.ts +0 -1
  96. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +0 -1
  97. package/src/__tests__/guardian-action-late-reply.test.ts +0 -1
  98. package/src/__tests__/guardian-action-store.test.ts +0 -1
  99. package/src/__tests__/guardian-action-sweep.test.ts +0 -1
  100. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +0 -1
  101. package/src/__tests__/guardian-dispatch.test.ts +1 -2
  102. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  103. package/src/__tests__/guardian-outbound-http.test.ts +0 -1
  104. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -1
  105. package/src/__tests__/guardian-routing-invariants.test.ts +1 -1
  106. package/src/__tests__/guardian-routing-state.test.ts +0 -1
  107. package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -1
  108. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +3 -5
  109. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +28 -426
  110. package/src/__tests__/host-bash-proxy.test.ts +335 -0
  111. package/src/__tests__/host-file-proxy.test.ts +374 -0
  112. package/src/__tests__/host-shell-tool.test.ts +147 -1
  113. package/src/__tests__/http-user-message-parity.test.ts +361 -0
  114. package/src/__tests__/inbound-invite-redemption.test.ts +0 -1
  115. package/src/__tests__/integration-status.test.ts +3 -8
  116. package/src/__tests__/intent-routing.test.ts +7 -46
  117. package/src/__tests__/invite-redemption-service.test.ts +0 -1
  118. package/src/__tests__/invite-routes-http.test.ts +0 -1
  119. package/src/__tests__/llm-usage-store.test.ts +0 -1
  120. package/src/__tests__/managed-avatar-client.test.ts +101 -55
  121. package/src/__tests__/managed-skill-lifecycle.test.ts +9 -18
  122. package/src/__tests__/managed-store.test.ts +94 -21
  123. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -1
  124. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +2 -4
  125. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -1
  126. package/src/__tests__/memory-recall-quality.test.ts +0 -1
  127. package/src/__tests__/memory-regressions.experimental.test.ts +0 -1
  128. package/src/__tests__/memory-regressions.test.ts +0 -1
  129. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -1
  130. package/src/__tests__/memory-upsert-concurrency.test.ts +0 -1
  131. package/src/__tests__/messaging-send-tool.test.ts +35 -0
  132. package/src/__tests__/messaging-skill-split.test.ts +138 -0
  133. package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -1
  134. package/src/__tests__/migration-export-http.test.ts +2 -3
  135. package/src/__tests__/migration-import-commit-http.test.ts +1 -2
  136. package/src/__tests__/migration-import-preflight-http.test.ts +1 -2
  137. package/src/__tests__/migration-validate-http.test.ts +1 -2
  138. package/src/__tests__/native-web-search.test.ts +475 -0
  139. package/src/__tests__/navigate-settings-tab.test.ts +84 -0
  140. package/src/__tests__/non-member-access-request.test.ts +0 -1
  141. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  142. package/src/__tests__/notification-decision-strategy.test.ts +6 -6
  143. package/src/__tests__/notification-deep-link.test.ts +7 -7
  144. package/src/__tests__/notification-guardian-path.test.ts +2 -3
  145. package/src/__tests__/notification-telegram-adapter.test.ts +1 -1
  146. package/src/__tests__/notification-thread-candidates.test.ts +4 -4
  147. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -1
  148. package/src/__tests__/playbook-execution.test.ts +0 -1
  149. package/src/__tests__/playbook-tools.test.ts +0 -1
  150. package/src/__tests__/profile-compiler.test.ts +0 -1
  151. package/src/__tests__/provider-managed-proxy-integration.test.ts +25 -0
  152. package/src/__tests__/qdrant-collection-migration.test.ts +223 -0
  153. package/src/__tests__/recording-handler.test.ts +30 -94
  154. package/src/__tests__/registry.test.ts +28 -35
  155. package/src/__tests__/relay-server.test.ts +0 -1
  156. package/src/__tests__/ride-shotgun-handler.test.ts +4 -20
  157. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
  158. package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
  159. package/src/__tests__/runtime-events-sse.test.ts +0 -1
  160. package/src/__tests__/sandbox-diagnostics.test.ts +0 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +30 -28
  162. package/src/__tests__/schedule-store.test.ts +441 -1
  163. package/src/__tests__/schedule-tools.test.ts +468 -7
  164. package/src/__tests__/scheduler-recurrence.test.ts +196 -23
  165. package/src/__tests__/scoped-approval-grants.test.ts +0 -1
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +0 -1
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +6 -3
  168. package/src/__tests__/secret-response-routing.test.ts +4 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +14 -2
  170. package/src/__tests__/send-notification-tool.test.ts +0 -7
  171. package/src/__tests__/sequence-store.test.ts +0 -1
  172. package/src/__tests__/server-history-render.test.ts +1 -2
  173. package/src/__tests__/session-abort-tool-results.test.ts +0 -1
  174. package/src/__tests__/session-agent-loop.test.ts +46 -6
  175. package/src/__tests__/session-confirmation-signals.test.ts +0 -1
  176. package/src/__tests__/session-conflict-gate.test.ts +2 -6
  177. package/src/__tests__/session-error.test.ts +5 -14
  178. package/src/__tests__/session-init.benchmark.test.ts +3 -5
  179. package/src/__tests__/session-load-history-repair.test.ts +0 -1
  180. package/src/__tests__/session-media-retry.test.ts +12 -74
  181. package/src/__tests__/session-pre-run-repair.test.ts +0 -1
  182. package/src/__tests__/session-profile-injection.test.ts +2 -6
  183. package/src/__tests__/session-provider-retry-repair.test.ts +2 -6
  184. package/src/__tests__/session-queue.test.ts +94 -139
  185. package/src/__tests__/session-skill-tools.test.ts +115 -115
  186. package/src/__tests__/session-slash-known.test.ts +0 -1
  187. package/src/__tests__/session-slash-queue.test.ts +0 -1
  188. package/src/__tests__/session-slash-unknown.test.ts +0 -1
  189. package/src/__tests__/session-surfaces-task-progress.test.ts +34 -0
  190. package/src/__tests__/session-usage.test.ts +0 -1
  191. package/src/__tests__/session-workspace-cache-state.test.ts +2 -6
  192. package/src/__tests__/session-workspace-injection.test.ts +2 -6
  193. package/src/__tests__/session-workspace-tool-tracking.test.ts +2 -6
  194. package/src/__tests__/skill-feature-flags-integration.test.ts +180 -184
  195. package/src/__tests__/skill-feature-flags.test.ts +125 -18
  196. package/src/__tests__/skill-load-feature-flag.test.ts +1 -2
  197. package/src/__tests__/skill-load-tool.test.ts +194 -2
  198. package/src/__tests__/skill-projection-feature-flag.test.ts +27 -16
  199. package/src/__tests__/skill-projection.benchmark.test.ts +15 -14
  200. package/src/__tests__/skills.test.ts +14 -53
  201. package/src/__tests__/slack-channel-config.test.ts +0 -1
  202. package/src/__tests__/slack-inbound-verification.test.ts +0 -1
  203. package/src/__tests__/slack-skill.test.ts +1 -1
  204. package/src/__tests__/subagent-tools.test.ts +2 -2
  205. package/src/__tests__/system-prompt.test.ts +4 -3
  206. package/src/__tests__/task-compiler.test.ts +0 -1
  207. package/src/__tests__/task-management-tools.test.ts +0 -1
  208. package/src/__tests__/task-memory-cleanup.test.ts +0 -1
  209. package/src/__tests__/task-runner.test.ts +0 -1
  210. package/src/__tests__/task-scheduler.test.ts +0 -1
  211. package/src/__tests__/terminal-tools.test.ts +0 -1
  212. package/src/__tests__/test-support/computer-use-skill-harness.ts +2 -4
  213. package/src/__tests__/thread-seed-composer.test.ts +5 -5
  214. package/src/__tests__/tool-approval-handler.test.ts +0 -1
  215. package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -1
  216. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -1
  217. package/src/__tests__/tool-executor.test.ts +8 -86
  218. package/src/__tests__/tool-grant-request-escalation.test.ts +0 -1
  219. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  220. package/src/__tests__/tool-preview-lifecycle.test.ts +416 -0
  221. package/src/__tests__/trust-store.test.ts +80 -4
  222. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  223. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +0 -1
  224. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -1
  225. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  226. package/src/__tests__/trusted-contact-verification.test.ts +0 -1
  227. package/src/__tests__/twilio-provider.test.ts +0 -1
  228. package/src/__tests__/twilio-routes.test.ts +0 -1
  229. package/src/__tests__/{request-file-tool.test.ts → ui-file-upload-surface.test.ts} +11 -72
  230. package/src/__tests__/update-bulletin.test.ts +0 -1
  231. package/src/__tests__/usage-cache-backfill-migration.test.ts +0 -1
  232. package/src/__tests__/usage-routes.test.ts +0 -1
  233. package/src/__tests__/verification-control-plane-policy.test.ts +4 -4
  234. package/src/__tests__/voice-invite-redemption.test.ts +0 -1
  235. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -1
  236. package/src/__tests__/voice-session-bridge.test.ts +9 -1
  237. package/src/__tests__/web-fetch.test.ts +57 -0
  238. package/src/__tests__/workspace-git-service.test.ts +5 -14
  239. package/src/__tests__/workspace-policy.test.ts +0 -1
  240. package/src/agent/loop.ts +22 -34
  241. package/src/bundler/bundle-signer.ts +4 -4
  242. package/src/calls/call-controller.ts +1 -1
  243. package/src/calls/relay-server.ts +1 -1
  244. package/src/calls/twilio-rest.ts +1 -1
  245. package/src/calls/voice-session-bridge.ts +3 -1
  246. package/src/cli/__tests__/notifications.test.ts +3 -4
  247. package/src/cli/commands/map.ts +2 -6
  248. package/src/cli/commands/mcp.ts +73 -15
  249. package/src/cli/commands/notifications.ts +4 -4
  250. package/src/cli/commands/sessions.ts +9 -1
  251. package/src/cli/commands/skills.ts +6 -10
  252. package/src/cli/http-client.ts +2 -3
  253. package/src/cli/main-screen.tsx +10 -10
  254. package/src/cli/program.ts +0 -4
  255. package/src/cli/reference.ts +0 -2
  256. package/src/cli.ts +15 -9
  257. package/src/config/__tests__/bundled-tool-registry-guard.test.ts +120 -0
  258. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +11 -0
  259. package/src/config/bundled-skills/app-builder/SKILL.md +6 -1
  260. package/src/config/bundled-skills/browser/SKILL.md +6 -1
  261. package/src/config/bundled-skills/chatgpt-import/SKILL.md +5 -1
  262. package/src/config/bundled-skills/claude-code/SKILL.md +5 -1
  263. package/src/config/bundled-skills/computer-use/SKILL.md +6 -1
  264. package/src/config/bundled-skills/computer-use/TOOLS.json +6 -69
  265. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +10 -1
  266. package/src/config/bundled-skills/contacts/SKILL.md +10 -1
  267. package/src/config/bundled-skills/contacts/TOOLS.json +35 -0
  268. package/src/config/bundled-skills/{messaging → contacts}/tools/google-contacts.ts +9 -2
  269. package/src/config/bundled-skills/document/SKILL.md +4 -1
  270. package/src/config/bundled-skills/doordash/SKILL.md +8 -1
  271. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +4 -1
  272. package/src/config/bundled-skills/followups/SKILL.md +4 -1
  273. package/src/config/bundled-skills/gmail/SKILL.md +180 -0
  274. package/src/config/bundled-skills/gmail/TOOLS.json +506 -0
  275. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +149 -0
  276. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +110 -0
  277. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-draft.ts +1 -1
  278. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-filters.ts +1 -1
  279. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-follow-up.ts +1 -1
  280. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-forward.ts +1 -1
  281. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +50 -0
  282. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-outreach-scan.ts +8 -90
  283. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-send-draft.ts +1 -1
  284. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-sender-digest.ts +2 -2
  285. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-trash.ts +1 -1
  286. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-unsubscribe.ts +1 -1
  287. package/src/config/bundled-skills/{messaging → gmail}/tools/gmail-vacation.ts +1 -1
  288. package/src/config/bundled-skills/gmail/tools/shared.ts +47 -0
  289. package/src/config/bundled-skills/google-calendar/SKILL.md +5 -1
  290. package/src/config/bundled-skills/image-studio/SKILL.md +5 -1
  291. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -1
  292. package/src/config/bundled-skills/media-processing/SKILL.md +7 -13
  293. package/src/config/bundled-skills/media-processing/TOOLS.json +0 -22
  294. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +12 -1
  295. package/src/config/bundled-skills/messaging/SKILL.md +23 -139
  296. package/src/config/bundled-skills/messaging/TOOLS.json +33 -1215
  297. package/src/config/bundled-skills/messaging/tools/gmail-mime-helpers.ts +42 -0
  298. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +165 -2
  299. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +1 -13
  300. package/src/config/bundled-skills/messaging/tools/shared.ts +81 -34
  301. package/src/config/bundled-skills/notifications/SKILL.md +5 -1
  302. package/src/config/bundled-skills/orchestration/SKILL.md +30 -0
  303. package/src/config/bundled-skills/orchestration/TOOLS.json +35 -0
  304. package/src/config/bundled-skills/{reminder/tools/reminder-create.ts → orchestration/tools/swarm-delegate.ts} +3 -3
  305. package/src/config/bundled-skills/phone-calls/SKILL.md +9 -1
  306. package/src/config/bundled-skills/playbooks/SKILL.md +4 -1
  307. package/src/config/bundled-skills/schedule/SKILL.md +70 -9
  308. package/src/config/bundled-skills/schedule/TOOLS.json +38 -6
  309. package/src/config/bundled-skills/screen-watch/SKILL.md +28 -0
  310. package/src/config/bundled-skills/screen-watch/TOOLS.json +35 -0
  311. package/src/config/bundled-skills/{reminder/tools/reminder-cancel.ts → screen-watch/tools/start-screen-watch.ts} +3 -3
  312. package/src/config/bundled-skills/sequences/SKILL.md +47 -0
  313. package/src/config/bundled-skills/sequences/TOOLS.json +340 -0
  314. package/src/config/bundled-skills/sequences/tools/sequence-update.ts +128 -0
  315. package/src/config/bundled-skills/sequences/tools/shared.ts +9 -0
  316. package/src/config/bundled-skills/settings/SKILL.md +12 -0
  317. package/src/config/bundled-skills/settings/TOOLS.json +112 -0
  318. package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +43 -0
  319. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +52 -0
  320. package/src/config/bundled-skills/{computer-use/tools/computer-use-right-click.ts → settings/tools/set-avatar.ts} +2 -6
  321. package/src/{tools/system/voice-config.ts → config/bundled-skills/settings/tools/voice-config-update.ts} +59 -96
  322. package/src/config/bundled-skills/skill-management/SKILL.md +18 -0
  323. package/src/config/bundled-skills/skill-management/TOOLS.json +90 -0
  324. package/src/config/bundled-skills/{computer-use/tools/computer-use-double-click.ts → skill-management/tools/delete-managed.ts} +2 -6
  325. package/src/config/bundled-skills/skill-management/tools/scaffold-managed.ts +12 -0
  326. package/src/config/bundled-skills/slack/SKILL.md +5 -1
  327. package/src/config/bundled-skills/subagent/SKILL.md +4 -1
  328. package/src/config/bundled-skills/tasks/SKILL.md +5 -2
  329. package/src/config/bundled-skills/transcribe/SKILL.md +4 -1
  330. package/src/config/bundled-skills/watcher/SKILL.md +4 -1
  331. package/src/config/bundled-tool-registry.ts +118 -107
  332. package/src/config/env.ts +5 -2
  333. package/src/config/feature-flag-registry.json +25 -9
  334. package/src/config/loader.ts +10 -2
  335. package/src/config/schema.ts +19 -16
  336. package/src/config/schemas/inference.ts +12 -22
  337. package/src/config/schemas/memory-storage.ts +19 -1
  338. package/src/config/schemas/platform.ts +0 -16
  339. package/src/config/skill-state.ts +11 -8
  340. package/src/config/skills.ts +83 -32
  341. package/src/context/token-estimator.ts +11 -0
  342. package/src/context/window-manager.ts +180 -151
  343. package/src/daemon/computer-use-session.ts +11 -43
  344. package/src/daemon/daemon-control.ts +4 -1
  345. package/src/daemon/handlers/config-channels.ts +5 -9
  346. package/src/daemon/handlers/config-ingress.ts +0 -4
  347. package/src/daemon/handlers/config-model.ts +7 -13
  348. package/src/daemon/handlers/config-telegram.ts +4 -8
  349. package/src/daemon/handlers/config-voice.ts +2 -5
  350. package/src/daemon/handlers/dictation.ts +2 -12
  351. package/src/daemon/handlers/identity.ts +0 -105
  352. package/src/daemon/handlers/recording.ts +3 -23
  353. package/src/daemon/handlers/session-history.ts +1 -1
  354. package/src/daemon/handlers/sessions.ts +53 -72
  355. package/src/daemon/handlers/shared.ts +7 -28
  356. package/src/daemon/handlers/skills.ts +31 -27
  357. package/src/daemon/host-bash-proxy.ts +148 -0
  358. package/src/daemon/host-file-proxy.ts +135 -0
  359. package/src/daemon/lifecycle.ts +49 -24
  360. package/src/daemon/mcp-reload-service.ts +123 -0
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/browser.ts +1 -1
  363. package/src/daemon/message-types/computer-use.ts +1 -4
  364. package/src/daemon/message-types/guardian-actions.ts +1 -1
  365. package/src/daemon/message-types/host-bash.ts +18 -0
  366. package/src/daemon/message-types/host-file.ts +44 -0
  367. package/src/daemon/message-types/integrations.ts +1 -67
  368. package/src/daemon/message-types/messages.ts +15 -0
  369. package/src/daemon/message-types/schedules.ts +11 -27
  370. package/src/daemon/message-types/sessions.ts +2 -1
  371. package/src/daemon/message-types/settings.ts +1 -1
  372. package/src/daemon/message-types/shared.ts +1 -1
  373. package/src/daemon/ride-shotgun-handler.ts +2 -42
  374. package/src/daemon/server.ts +43 -10
  375. package/src/daemon/session-agent-loop-handlers.ts +48 -7
  376. package/src/daemon/session-agent-loop.ts +97 -66
  377. package/src/daemon/session-attachments.ts +1 -1
  378. package/src/daemon/session-error.ts +17 -16
  379. package/src/daemon/session-lifecycle.ts +20 -1
  380. package/src/daemon/session-media-retry.ts +1 -15
  381. package/src/daemon/session-messaging.ts +14 -6
  382. package/src/daemon/session-process.ts +36 -7
  383. package/src/daemon/session-queue-manager.ts +62 -103
  384. package/src/daemon/session-runtime-assembly.ts +27 -0
  385. package/src/daemon/session-skill-tools.ts +12 -11
  386. package/src/daemon/session-slash.ts +7 -0
  387. package/src/daemon/session-surfaces.ts +19 -97
  388. package/src/daemon/session-tool-setup.ts +146 -6
  389. package/src/daemon/session.ts +77 -13
  390. package/src/errors.ts +0 -2
  391. package/src/export/formatter.ts +6 -0
  392. package/src/mcp/mcp-oauth-provider.ts +1 -3
  393. package/src/media/avatar-router.ts +20 -28
  394. package/src/media/avatar-types.ts +7 -14
  395. package/src/media/managed-avatar-client.ts +70 -34
  396. package/src/memory/conversation-title-service.ts +1 -2
  397. package/src/memory/db-init.ts +16 -0
  398. package/src/memory/embedding-backend.ts +129 -27
  399. package/src/memory/embedding-gemini.test.ts +256 -0
  400. package/src/memory/embedding-gemini.ts +47 -13
  401. package/src/memory/embedding-local.ts +14 -2
  402. package/src/memory/embedding-ollama.ts +15 -2
  403. package/src/memory/embedding-openai.ts +15 -2
  404. package/src/memory/embedding-types.test.ts +116 -0
  405. package/src/memory/embedding-types.ts +61 -0
  406. package/src/memory/fingerprint.ts +1 -1
  407. package/src/memory/indexer.ts +25 -1
  408. package/src/memory/job-handlers/embedding.test.ts +258 -0
  409. package/src/memory/job-handlers/embedding.ts +81 -1
  410. package/src/memory/job-handlers/index-maintenance.ts +35 -1
  411. package/src/memory/job-handlers/media-processing.ts +11 -1
  412. package/src/memory/job-utils.ts +21 -6
  413. package/src/memory/jobs-store.ts +5 -1
  414. package/src/memory/jobs-worker.ts +8 -0
  415. package/src/memory/message-content.ts +66 -0
  416. package/src/memory/migrations/100-core-tables.ts +1 -31
  417. package/src/memory/migrations/104-core-indexes.ts +0 -11
  418. package/src/memory/migrations/145-drop-accounts-table.ts +19 -0
  419. package/src/memory/migrations/146-schedule-oneshot-routing.ts +94 -0
  420. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +129 -0
  421. package/src/memory/migrations/148-drop-reminders-table.ts +18 -0
  422. package/src/memory/migrations/index.ts +4 -0
  423. package/src/memory/migrations/registry.ts +19 -0
  424. package/src/memory/qdrant-client.ts +158 -43
  425. package/src/memory/retriever.test.ts +0 -1
  426. package/src/memory/retriever.ts +12 -2
  427. package/src/memory/schema/infrastructure.ts +5 -29
  428. package/src/memory/search/formatting.ts +34 -9
  429. package/src/memory/search/semantic.ts +57 -2
  430. package/src/memory/search/types.ts +2 -1
  431. package/src/notifications/AGENTS.md +2 -2
  432. package/src/notifications/README.md +59 -58
  433. package/src/notifications/adapters/macos.ts +1 -1
  434. package/src/notifications/broadcaster.ts +5 -5
  435. package/src/notifications/copy-composer.ts +1 -1
  436. package/src/notifications/decision-engine.ts +2 -2
  437. package/src/notifications/destination-resolver.ts +2 -2
  438. package/src/notifications/emit-signal.ts +8 -8
  439. package/src/notifications/signal.ts +1 -1
  440. package/src/notifications/thread-seed-composer.ts +1 -1
  441. package/src/oauth/connect-orchestrator.ts +1 -1
  442. package/src/oauth/token-persistence.ts +1 -1
  443. package/src/permissions/checker.ts +12 -1
  444. package/src/permissions/defaults.ts +10 -14
  445. package/src/permissions/trust-store.ts +37 -0
  446. package/src/permissions/workspace-policy.ts +0 -1
  447. package/src/prompts/__tests__/build-cli-reference-section.test.ts +11 -0
  448. package/src/prompts/computer-use-prompt.ts +1 -1
  449. package/src/prompts/system-prompt.ts +29 -30
  450. package/src/prompts/templates/SOUL.md +1 -2
  451. package/src/prompts/templates/UPDATES.md +16 -7
  452. package/src/providers/anthropic/client.ts +87 -33
  453. package/src/providers/gemini/client.ts +6 -0
  454. package/src/providers/managed-proxy/constants.ts +5 -0
  455. package/src/providers/openai/client.ts +15 -0
  456. package/src/providers/registry.ts +2 -2
  457. package/src/providers/types.ts +24 -2
  458. package/src/runtime/AGENTS.md +18 -0
  459. package/src/runtime/assistant-event-hub.ts +2 -3
  460. package/src/runtime/assistant-event.ts +4 -4
  461. package/src/runtime/auth/__tests__/context.test.ts +5 -5
  462. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  463. package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -2
  464. package/src/runtime/auth/__tests__/{ipc-auth-context.test.ts → local-auth-context.test.ts} +21 -21
  465. package/src/runtime/auth/__tests__/route-policy.test.ts +2 -2
  466. package/src/runtime/auth/__tests__/scopes.test.ts +7 -7
  467. package/src/runtime/auth/__tests__/subject.test.ts +8 -8
  468. package/src/runtime/auth/__tests__/token-service.test.ts +0 -1
  469. package/src/runtime/auth/route-policy.ts +8 -4
  470. package/src/runtime/auth/scopes.ts +1 -1
  471. package/src/runtime/auth/subject.ts +4 -4
  472. package/src/runtime/auth/token-service.ts +0 -23
  473. package/src/runtime/auth/types.ts +3 -3
  474. package/src/runtime/guardian-action-followup-executor.ts +1 -1
  475. package/src/runtime/guardian-action-grant-minter.ts +1 -1
  476. package/src/runtime/guardian-action-service.ts +3 -3
  477. package/src/runtime/http-server.ts +15 -2
  478. package/src/runtime/invite-service.ts +3 -3
  479. package/src/runtime/local-actor-identity.ts +17 -22
  480. package/src/runtime/pending-interactions.ts +21 -9
  481. package/src/runtime/routes/app-management-routes.ts +2 -3
  482. package/src/runtime/routes/approval-routes.ts +1 -3
  483. package/src/runtime/routes/btw-routes.ts +155 -0
  484. package/src/runtime/routes/computer-use-routes.ts +77 -31
  485. package/src/runtime/routes/conversation-routes.ts +230 -46
  486. package/src/runtime/routes/diagnostics-routes.ts +63 -29
  487. package/src/runtime/routes/documents-routes.ts +2 -2
  488. package/src/runtime/routes/global-search-routes.ts +1 -1
  489. package/src/runtime/routes/host-bash-routes.ts +83 -0
  490. package/src/runtime/routes/host-file-routes.ts +79 -0
  491. package/src/runtime/routes/integrations/slack/share.ts +1 -1
  492. package/src/runtime/routes/log-export-routes.ts +120 -0
  493. package/src/runtime/routes/mcp-routes.ts +20 -0
  494. package/src/runtime/routes/migration-routes.ts +3 -3
  495. package/src/runtime/routes/pairing-routes.ts +1 -1
  496. package/src/runtime/routes/recording-routes.ts +6 -4
  497. package/src/runtime/routes/schedule-routes.ts +31 -5
  498. package/src/runtime/routes/session-management-routes.ts +2 -6
  499. package/src/runtime/routes/session-query-routes.ts +18 -15
  500. package/src/runtime/routes/settings-routes.ts +7 -261
  501. package/src/runtime/routes/skills-routes.ts +7 -6
  502. package/src/runtime/routes/subagents-routes.ts +4 -10
  503. package/src/runtime/routes/surface-action-routes.ts +3 -14
  504. package/src/runtime/routes/surface-content-routes.ts +22 -5
  505. package/src/runtime/routes/work-items-routes.ts +21 -25
  506. package/src/runtime/routes/workspace-routes.test.ts +3 -3
  507. package/src/runtime/routes/workspace-utils.ts +1 -1
  508. package/src/runtime/telegram-streaming-delivery.ts +3 -0
  509. package/src/runtime/verification-outbound-actions.ts +2 -2
  510. package/src/schedule/integration-status.ts +0 -6
  511. package/src/schedule/schedule-store.ts +234 -43
  512. package/src/schedule/scheduler.ts +73 -74
  513. package/src/security/oauth2.ts +1 -1
  514. package/src/sequence/store.ts +12 -2
  515. package/src/skills/frontmatter.ts +19 -77
  516. package/src/skills/managed-store.ts +11 -2
  517. package/src/subagent/manager.ts +5 -3
  518. package/src/tasks/ephemeral-permissions.ts +3 -5
  519. package/src/tools/AGENTS.md +0 -1
  520. package/src/tools/browser/browser-manager.ts +17 -11
  521. package/src/tools/browser/jit-auth.ts +4 -1
  522. package/src/tools/claude-code/claude-code.ts +1 -1
  523. package/src/tools/computer-use/definitions.ts +48 -60
  524. package/src/tools/document/document-tool.ts +6 -6
  525. package/src/tools/filesystem/edit.ts +2 -1
  526. package/src/tools/filesystem/read.ts +20 -2
  527. package/src/tools/filesystem/write.ts +2 -1
  528. package/src/tools/host-filesystem/edit.ts +17 -1
  529. package/src/tools/host-filesystem/read.ts +16 -1
  530. package/src/tools/host-filesystem/write.ts +15 -1
  531. package/src/tools/host-terminal/host-shell.ts +24 -0
  532. package/src/tools/memory/definitions.ts +45 -81
  533. package/src/tools/memory/handlers.test.ts +0 -1
  534. package/src/tools/memory/handlers.ts +1 -1
  535. package/src/tools/memory/register.ts +26 -60
  536. package/src/tools/network/script-proxy/session-manager.ts +6 -8
  537. package/src/tools/network/web-fetch.ts +7 -1
  538. package/src/tools/network/web-search.ts +2 -1
  539. package/src/tools/registry.ts +23 -0
  540. package/src/tools/schedule/create.ts +113 -5
  541. package/src/tools/schedule/list.ts +57 -15
  542. package/src/tools/schedule/update.ts +73 -3
  543. package/src/tools/shared/filesystem/image-read.ts +192 -0
  544. package/src/tools/side-effects.ts +1 -7
  545. package/src/tools/skills/delete-managed.ts +27 -64
  546. package/src/tools/skills/execute.ts +54 -0
  547. package/src/tools/skills/load.ts +127 -5
  548. package/src/tools/skills/scaffold-managed.ts +93 -172
  549. package/src/tools/subagent/message.ts +0 -7
  550. package/src/tools/subagent/spawn.ts +1 -1
  551. package/src/tools/swarm/delegate.ts +0 -3
  552. package/src/tools/system/avatar-generator.ts +13 -19
  553. package/src/tools/system/request-permission.ts +2 -1
  554. package/src/tools/terminal/safe-env.ts +1 -0
  555. package/src/tools/tool-manifest.ts +41 -47
  556. package/src/tools/types.ts +6 -2
  557. package/src/tools/ui-surface/definitions.ts +0 -55
  558. package/src/util/errors.ts +0 -10
  559. package/src/workspace/git-service.ts +0 -2
  560. package/src/__tests__/account-registry.test.ts +0 -258
  561. package/src/__tests__/email-classifier.test.ts +0 -25
  562. package/src/__tests__/gmail-integration.test.ts +0 -97
  563. package/src/__tests__/handle-user-message-secret-resume.test.ts +0 -172
  564. package/src/__tests__/managed-twitter-guardrails.test.ts +0 -357
  565. package/src/__tests__/recording-intent-fallback.test.ts +0 -199
  566. package/src/__tests__/recording-intent.test.ts +0 -985
  567. package/src/__tests__/recording-state-machine.test.ts +0 -1574
  568. package/src/__tests__/reminder-store.test.ts +0 -350
  569. package/src/__tests__/reminder.test.ts +0 -337
  570. package/src/__tests__/scan-result-store.test.ts +0 -121
  571. package/src/__tests__/twitter-platform-proxy-client.test.ts +0 -475
  572. package/src/__tests__/view-image-tool.test.ts +0 -241
  573. package/src/cli/commands/amazon/cart.ts +0 -513
  574. package/src/cli/commands/amazon/checkout.ts +0 -394
  575. package/src/cli/commands/amazon/client.ts +0 -513
  576. package/src/cli/commands/amazon/index.ts +0 -885
  577. package/src/cli/commands/amazon/product-details.ts +0 -145
  578. package/src/cli/commands/amazon/request-extractor.ts +0 -187
  579. package/src/cli/commands/amazon/search.ts +0 -76
  580. package/src/cli/commands/amazon/session.ts +0 -108
  581. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +0 -345
  582. package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +0 -252
  583. package/src/cli/commands/twitter/__tests__/oauth-client.test.ts +0 -151
  584. package/src/cli/commands/twitter/index.ts +0 -420
  585. package/src/cli/commands/twitter/oauth-client.ts +0 -60
  586. package/src/cli/commands/twitter/router.ts +0 -351
  587. package/src/cli/commands/twitter/types.ts +0 -30
  588. package/src/config/bundled-skills/agentmail/SKILL.md +0 -132
  589. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  590. package/src/config/bundled-skills/amazon/SKILL.md +0 -136
  591. package/src/config/bundled-skills/amazon/icon.svg +0 -13
  592. package/src/config/bundled-skills/api-mapping/SKILL.md +0 -78
  593. package/src/config/bundled-skills/api-mapping/icon.svg +0 -18
  594. package/src/config/bundled-skills/cli-discover/SKILL.md +0 -68
  595. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  596. package/src/config/bundled-skills/document-writer/SKILL.md +0 -195
  597. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +0 -140
  598. package/src/config/bundled-skills/email-setup/SKILL.md +0 -68
  599. package/src/config/bundled-skills/frontend-design/SKILL.md +0 -44
  600. package/src/config/bundled-skills/frontend-design/icon.svg +0 -16
  601. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +0 -452
  602. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +0 -203
  603. package/src/config/bundled-skills/influencer/SKILL.md +0 -144
  604. package/src/config/bundled-skills/influencer/scripts/client.ts +0 -1269
  605. package/src/config/bundled-skills/influencer/scripts/influencer.ts +0 -267
  606. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -65
  607. package/src/config/bundled-skills/macos-automation/icon.svg +0 -12
  608. package/src/config/bundled-skills/mcp-setup/SKILL.md +0 -75
  609. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +0 -184
  610. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +0 -80
  611. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -29
  612. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -56
  613. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -34
  614. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +0 -47
  615. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -31
  616. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +0 -67
  617. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +0 -97
  618. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +0 -87
  619. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +0 -135
  620. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -24
  621. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -201
  622. package/src/config/bundled-skills/messaging/tools/send-notification.ts +0 -1
  623. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +0 -27
  624. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +0 -48
  625. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +0 -27
  626. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +0 -56
  627. package/src/config/bundled-skills/notion/SKILL.md +0 -240
  628. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +0 -126
  629. package/src/config/bundled-skills/oauth-setup/SKILL.md +0 -143
  630. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -258
  631. package/src/config/bundled-skills/reminder/SKILL.md +0 -79
  632. package/src/config/bundled-skills/reminder/TOOLS.json +0 -89
  633. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -12
  634. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +0 -141
  635. package/src/config/bundled-skills/screen-recording/SKILL.md +0 -148
  636. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -69
  637. package/src/config/bundled-skills/skills-catalog/SKILL.md +0 -78
  638. package/src/config/bundled-skills/slack-app-setup/SKILL.md +0 -178
  639. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +0 -163
  640. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +0 -157
  641. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  642. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  643. package/src/config/bundled-skills/telegram-setup/SKILL.md +0 -105
  644. package/src/config/bundled-skills/time-based-actions/SKILL.md +0 -142
  645. package/src/config/bundled-skills/twilio-setup/SKILL.md +0 -232
  646. package/src/config/bundled-skills/twitter/SKILL.md +0 -206
  647. package/src/config/bundled-skills/twitter/icon.svg +0 -14
  648. package/src/config/bundled-skills/typescript-eval/SKILL.md +0 -60
  649. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +0 -214
  650. package/src/config/bundled-skills/voice-setup/SKILL.md +0 -131
  651. package/src/config/bundled-skills/voice-setup/icon.svg +0 -20
  652. package/src/daemon/handlers/pairing.ts +0 -119
  653. package/src/daemon/handlers/session-user-message.ts +0 -961
  654. package/src/daemon/recording-executor.ts +0 -180
  655. package/src/daemon/recording-intent-fallback.ts +0 -162
  656. package/src/daemon/recording-intent.ts +0 -493
  657. package/src/memory/account-store.ts +0 -117
  658. package/src/messaging/activity-analyzer.ts +0 -76
  659. package/src/messaging/email-classifier.ts +0 -208
  660. package/src/messaging/index.ts +0 -2
  661. package/src/messaging/outreach-classifier.ts +0 -185
  662. package/src/messaging/thread-summarizer.ts +0 -346
  663. package/src/messaging/types.ts +0 -17
  664. package/src/tools/browser/x-auto-navigate.ts +0 -254
  665. package/src/tools/credentials/account-registry.ts +0 -144
  666. package/src/tools/filesystem/view-image.ts +0 -244
  667. package/src/tools/reminder/reminder-store.ts +0 -194
  668. package/src/tools/reminder/reminder.ts +0 -158
  669. package/src/tools/system/navigate-settings.ts +0 -74
  670. package/src/tools/system/open-system-settings.ts +0 -85
  671. package/src/tools/system/version.ts +0 -54
  672. package/src/twitter/platform-proxy-client.ts +0 -408
  673. /package/src/config/bundled-skills/{messaging → gmail}/tools/scan-result-store.ts +0 -0
  674. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-analytics.ts +0 -0
  675. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-create.ts +0 -0
  676. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-delete.ts +0 -0
  677. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enroll.ts +0 -0
  678. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-enrollment-list.ts +0 -0
  679. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-get.ts +0 -0
  680. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-import.ts +0 -0
  681. /package/src/config/bundled-skills/{messaging → sequences}/tools/sequence-list.ts +0 -0
@@ -1,985 +0,0 @@
1
- import { beforeEach, describe, expect, mock, test } from "bun:test";
2
-
3
- import {
4
- type RecordingIntentResult as _RecordingIntentResult,
5
- resolveRecordingIntent,
6
- } from "../daemon/recording-intent.js";
7
-
8
- // ─── resolveRecordingIntent ─────────────────────────────────────────────────
9
-
10
- describe("resolveRecordingIntent", () => {
11
- // ── Start detection (covers legacy detectRecordingIntent behavior) ───────
12
-
13
- describe("start intent detection", () => {
14
- test.each([
15
- "record my screen",
16
- "Record My Screen",
17
- "record the screen",
18
- "screen recording",
19
- "screen record",
20
- "start recording",
21
- "begin recording",
22
- "capture my screen",
23
- "capture my display",
24
- "capture screen",
25
- "make a recording",
26
- ])('detects start intent in "%s"', (text) => {
27
- const result = resolveRecordingIntent(text);
28
- expect(result.kind).toBe("start_only");
29
- });
30
-
31
- // "make a screen recording" is detected as recording intent but resolves
32
- // to start_with_remainder because the strip patterns match "screen recording"
33
- // first, leaving "make a" as residual text.
34
- test('detects start intent in "make a screen recording" (with residual remainder)', () => {
35
- const result = resolveRecordingIntent("make a screen recording");
36
- expect(result.kind).toBe("start_with_remainder");
37
- });
38
-
39
- test.each([
40
- "",
41
- "hello world",
42
- "open Safari",
43
- "take a screenshot",
44
- "what time is it?",
45
- "record a note",
46
- "make a note",
47
- "start the timer",
48
- ])('does not detect start intent in "%s"', (text) => {
49
- expect(resolveRecordingIntent(text)).toEqual({ kind: "none" });
50
- });
51
-
52
- test("is case-insensitive", () => {
53
- expect(resolveRecordingIntent("RECORD MY SCREEN").kind).toBe(
54
- "start_only",
55
- );
56
- expect(resolveRecordingIntent("Screen Recording").kind).toBe(
57
- "start_only",
58
- );
59
- expect(resolveRecordingIntent("START RECORDING").kind).toBe("start_only");
60
- });
61
- });
62
-
63
- // ── Pure start (covers legacy isRecordingOnly behavior) ─────────────────
64
-
65
- describe("pure start (recording-only)", () => {
66
- test.each([
67
- "record my screen",
68
- "Record my screen",
69
- "start recording",
70
- "screen recording",
71
- "begin recording",
72
- "capture my screen",
73
- "make a recording",
74
- ])('resolves as start_only for pure recording request "%s"', (text) => {
75
- expect(resolveRecordingIntent(text)).toEqual({ kind: "start_only" });
76
- });
77
-
78
- test("resolves as start_only when polite fillers surround the recording request", () => {
79
- expect(resolveRecordingIntent("please record my screen")).toEqual({
80
- kind: "start_only",
81
- });
82
- expect(resolveRecordingIntent("can you start recording")).toEqual({
83
- kind: "start_only",
84
- });
85
- expect(
86
- resolveRecordingIntent("could you record my screen please"),
87
- ).toEqual({ kind: "start_only" });
88
- expect(resolveRecordingIntent("hey, start recording now")).toEqual({
89
- kind: "start_only",
90
- });
91
- expect(resolveRecordingIntent("just record my screen, thanks")).toEqual({
92
- kind: "start_only",
93
- });
94
- expect(resolveRecordingIntent("can you start recording?")).toEqual({
95
- kind: "start_only",
96
- });
97
- });
98
-
99
- test.each([
100
- "record my screen and then open Safari",
101
- "do this task and record my screen",
102
- "record my screen while I work on the document",
103
- "open Chrome and start recording",
104
- "record my screen and send it to Bob",
105
- ])('resolves as start_with_remainder for mixed-intent "%s"', (text) => {
106
- expect(resolveRecordingIntent(text).kind).toBe("start_with_remainder");
107
- });
108
-
109
- test("handles punctuation in recording-only prompts", () => {
110
- expect(resolveRecordingIntent("record my screen!")).toEqual({
111
- kind: "start_only",
112
- });
113
- expect(resolveRecordingIntent("start recording.")).toEqual({
114
- kind: "start_only",
115
- });
116
- expect(resolveRecordingIntent("screen recording?")).toEqual({
117
- kind: "start_only",
118
- });
119
- });
120
- });
121
-
122
- // ── Stop detection (covers legacy detectStopRecordingIntent behavior) ───
123
-
124
- describe("stop intent detection", () => {
125
- test.each([
126
- "stop recording",
127
- "stop the recording",
128
- "end recording",
129
- "end the recording",
130
- "finish recording",
131
- "finish the recording",
132
- "halt recording",
133
- "halt the recording",
134
- ])('detects stop intent in "%s"', (text) => {
135
- expect(resolveRecordingIntent(text).kind).toBe("stop_only");
136
- });
137
-
138
- test.each([
139
- "",
140
- "hello world",
141
- "stop it",
142
- "end it",
143
- "quit",
144
- "take a screenshot",
145
- "stop the music",
146
- ])('does not detect stop intent in "%s"', (text) => {
147
- expect(resolveRecordingIntent(text)).toEqual({ kind: "none" });
148
- });
149
-
150
- test("is case-insensitive", () => {
151
- expect(resolveRecordingIntent("STOP RECORDING").kind).toBe("stop_only");
152
- expect(resolveRecordingIntent("Stop The Recording").kind).toBe(
153
- "stop_only",
154
- );
155
- expect(resolveRecordingIntent("END RECORDING").kind).toBe("stop_only");
156
- });
157
- });
158
-
159
- // ── Pure stop (covers legacy isStopRecordingOnly behavior) ──────────────
160
-
161
- describe("pure stop (stop-recording-only)", () => {
162
- test.each([
163
- "stop recording",
164
- "stop the recording",
165
- "end recording",
166
- "end the recording",
167
- "finish recording",
168
- "halt recording",
169
- ])('resolves as stop_only for pure stop request "%s"', (text) => {
170
- expect(resolveRecordingIntent(text)).toEqual({ kind: "stop_only" });
171
- });
172
-
173
- test("resolves as stop_only when polite fillers surround the stop request", () => {
174
- expect(resolveRecordingIntent("please stop recording")).toEqual({
175
- kind: "stop_only",
176
- });
177
- expect(resolveRecordingIntent("can you stop the recording?")).toEqual({
178
- kind: "stop_only",
179
- });
180
- expect(
181
- resolveRecordingIntent("could you end the recording please"),
182
- ).toEqual({ kind: "stop_only" });
183
- expect(resolveRecordingIntent("stop the recording now")).toEqual({
184
- kind: "stop_only",
185
- });
186
- expect(resolveRecordingIntent("just stop recording, thanks")).toEqual({
187
- kind: "stop_only",
188
- });
189
- });
190
-
191
- test("resolves as stop_with_remainder when stop has additional task", () => {
192
- const r1 = resolveRecordingIntent("stop recording and open Chrome");
193
- expect(r1.kind).toBe("stop_with_remainder");
194
- if (r1.kind === "stop_with_remainder") {
195
- expect(r1.remainder).toContain("open Chrome");
196
- }
197
- });
198
-
199
- test("handles ambiguous phrases as none", () => {
200
- expect(resolveRecordingIntent("end it")).toEqual({ kind: "none" });
201
- expect(resolveRecordingIntent("stop")).toEqual({ kind: "none" });
202
- expect(resolveRecordingIntent("quit")).toEqual({ kind: "none" });
203
- });
204
-
205
- test("handles punctuation", () => {
206
- expect(resolveRecordingIntent("stop recording!")).toEqual({
207
- kind: "stop_only",
208
- });
209
- expect(resolveRecordingIntent("stop recording.")).toEqual({
210
- kind: "stop_only",
211
- });
212
- expect(resolveRecordingIntent("end the recording?")).toEqual({
213
- kind: "stop_only",
214
- });
215
- });
216
- });
217
-
218
- // ── Remainder extraction (covers legacy strip* behavior) ────────────────
219
-
220
- describe("remainder extraction", () => {
221
- test("extracts remainder when start intent is mixed with other task", () => {
222
- const r1 = resolveRecordingIntent("open Safari and record my screen");
223
- expect(r1.kind).toBe("start_with_remainder");
224
- if (r1.kind === "start_with_remainder") {
225
- expect(r1.remainder).toBe("open Safari");
226
- }
227
-
228
- const r2 = resolveRecordingIntent("do this task and start recording");
229
- expect(r2.kind).toBe("start_with_remainder");
230
- if (r2.kind === "start_with_remainder") {
231
- expect(r2.remainder).toContain("do this task");
232
- }
233
- });
234
-
235
- test("extracts remainder when stop intent is mixed with other task", () => {
236
- const r1 = resolveRecordingIntent("open Chrome and stop recording");
237
- expect(r1.kind).toBe("stop_with_remainder");
238
- if (r1.kind === "stop_with_remainder") {
239
- expect(r1.remainder).toBe("open Chrome");
240
- }
241
-
242
- const r2 = resolveRecordingIntent("save the file and end the recording");
243
- expect(r2.kind).toBe("stop_with_remainder");
244
- if (r2.kind === "stop_with_remainder") {
245
- expect(r2.remainder).toContain("save the file");
246
- }
247
- });
248
-
249
- test("remainder does not contain double spaces", () => {
250
- const r1 = resolveRecordingIntent(
251
- "open Safari and also record my screen please",
252
- );
253
- if (r1.kind === "start_with_remainder") {
254
- expect(r1.remainder).not.toContain(" ");
255
- }
256
-
257
- const r2 = resolveRecordingIntent(
258
- "open Safari and also stop recording please",
259
- );
260
- if (r2.kind === "stop_with_remainder") {
261
- expect(r2.remainder).not.toContain(" ");
262
- }
263
- });
264
- });
265
-
266
- // ── Interrogative gate (covers legacy isInterrogative behavior) ─────────
267
-
268
- describe("interrogative gate", () => {
269
- test.each([
270
- "how do I stop recording?",
271
- "how do I record my screen?",
272
- "what does screen recording do?",
273
- "why is screen recording not working?",
274
- "when should I stop recording?",
275
- "where does the recording file go?",
276
- "which display should I record?",
277
- "What is the screen recording feature?",
278
- "How do I start recording on Mac?",
279
- "how can I record my screen?",
280
- "why did the recording stop?",
281
- ])('returns none for question: "%s"', (text) => {
282
- expect(resolveRecordingIntent(text)).toEqual({ kind: "none" });
283
- });
284
-
285
- test.each([
286
- "record my screen",
287
- "stop recording",
288
- "open Chrome and record my screen",
289
- "can you record my screen?",
290
- "could you stop recording please",
291
- "start recording",
292
- "please record my screen",
293
- ])('does not block command: "%s"', (text) => {
294
- expect(resolveRecordingIntent(text).kind).not.toBe("none");
295
- });
296
-
297
- test("strips dynamic name before checking interrogative", () => {
298
- expect(
299
- resolveRecordingIntent("Nova, how do I stop recording?", ["Nova"]),
300
- ).toEqual({ kind: "none" });
301
- expect(
302
- resolveRecordingIntent("Nova, record my screen", ["Nova"]).kind,
303
- ).toBe("start_only");
304
- });
305
-
306
- test("handles polite prefix before question word", () => {
307
- expect(
308
- resolveRecordingIntent("please, how do I stop recording?"),
309
- ).toEqual({ kind: "none" });
310
- expect(
311
- resolveRecordingIntent("hey, what does screen recording do?"),
312
- ).toEqual({ kind: "none" });
313
- });
314
-
315
- // Interrogative gate for new patterns
316
- test("returns none for question about restart", () => {
317
- expect(resolveRecordingIntent("how do I restart recording?")).toEqual({
318
- kind: "none",
319
- });
320
- });
321
-
322
- test("returns none for question about pause", () => {
323
- expect(resolveRecordingIntent("how can I pause recording?")).toEqual({
324
- kind: "none",
325
- });
326
- });
327
-
328
- test("returns none for question about resume", () => {
329
- expect(resolveRecordingIntent("how do I resume recording?")).toEqual({
330
- kind: "none",
331
- });
332
- });
333
-
334
- // ── Indirect informational patterns ───────────────────────────────────
335
-
336
- test.each([
337
- "can you tell me how to stop recording?",
338
- "could you tell me how to stop recording?",
339
- "would you tell me how to stop recording?",
340
- "explain how to stop the recording",
341
- "tell me how recording works",
342
- "describe how screen recording works",
343
- "show me how to record my screen",
344
- "is there a way to stop recording?",
345
- "is there a method to pause recording?",
346
- "are there any ways to record my screen?",
347
- "I'd like to know how to stop recording",
348
- "I would like to know how to pause the recording",
349
- "I want to know how to start recording",
350
- "do you know how to start recording?",
351
- "can I learn how to record my screen?",
352
- "can you explain how to record my screen?",
353
- "tell me about how screen recording works",
354
- "explain to me how to stop recording",
355
- "tell me what screen recording does",
356
- "describe how to start a recording",
357
- "please, tell me how to stop recording",
358
- "hey, can you explain how to record my screen?",
359
- ])('returns none for indirect informational question: "%s"', (text) => {
360
- expect(resolveRecordingIntent(text)).toEqual({ kind: "none" });
361
- });
362
-
363
- test("indirect informational with dynamic name returns none", () => {
364
- expect(
365
- resolveRecordingIntent("Nova, can you tell me how to stop recording?", [
366
- "Nova",
367
- ]),
368
- ).toEqual({ kind: "none" });
369
- expect(
370
- resolveRecordingIntent("Nova, explain how to record my screen", [
371
- "Nova",
372
- ]),
373
- ).toEqual({ kind: "none" });
374
- expect(
375
- resolveRecordingIntent("hey Nova, is there a way to stop recording?", [
376
- "Nova",
377
- ]),
378
- ).toEqual({ kind: "none" });
379
- });
380
-
381
- // ── Polite imperatives that should still execute (NOT none) ──────────
382
-
383
- test.each([
384
- ["can you stop recording?", "stop_only"],
385
- ["could you record my screen?", "start_only"],
386
- ["can you pause the recording?", "pause_only"],
387
- ["would you resume recording?", "resume_only"],
388
- ["please stop recording", "stop_only"],
389
- ["can you start recording?", "start_only"],
390
- ["could you stop the recording please", "stop_only"],
391
- ] as const)(
392
- 'polite imperative "%s" resolves to %s (not none)',
393
- (text, expected) => {
394
- expect(resolveRecordingIntent(text).kind).toBe(expected);
395
- },
396
- );
397
- });
398
-
399
- // ── Mixed-intent with remainder (regression coverage) ────────────────────
400
-
401
- describe("mixed-intent with remainder", () => {
402
- test('"stop recording and start a new one and open safari" → restart_with_remainder', () => {
403
- const result = resolveRecordingIntent(
404
- "stop recording and start a new one and open safari",
405
- );
406
- expect(result.kind).toBe("restart_with_remainder");
407
- if (result.kind === "restart_with_remainder") {
408
- expect(result.remainder).toContain("open safari");
409
- }
410
- });
411
-
412
- test('"record my screen and open Chrome and go to google.com" → start_with_remainder', () => {
413
- const result = resolveRecordingIntent(
414
- "record my screen and open Chrome and go to google.com",
415
- );
416
- expect(result.kind).toBe("start_with_remainder");
417
- if (result.kind === "start_with_remainder") {
418
- expect(result.remainder).toContain("open Chrome");
419
- expect(result.remainder).toContain("google.com");
420
- }
421
- });
422
-
423
- test('"stop recording and send the file to Bob" → stop_with_remainder', () => {
424
- const result = resolveRecordingIntent(
425
- "stop recording and send the file to Bob",
426
- );
427
- expect(result.kind).toBe("stop_with_remainder");
428
- if (result.kind === "stop_with_remainder") {
429
- expect(result.remainder).toContain("send the file to Bob");
430
- }
431
- });
432
- });
433
-
434
- // ── Dynamic names ──────────────────────────────────────────────────────────
435
-
436
- describe("dynamic name handling", () => {
437
- test.each([
438
- ["Nova, record my screen", ["Nova"], "start_only"],
439
- ["hey Nova, start recording", ["Nova"], "start_only"],
440
- ["hey, Nova, start recording", ["Nova"], "start_only"],
441
- ["Nova, stop recording", ["Nova"], "stop_only"],
442
- ["Nova, hello", ["Nova"], "none"],
443
- ] as const)(
444
- '"%s" with names %j resolves to %s',
445
- (text, names, expected) => {
446
- expect(resolveRecordingIntent(text, [...names]).kind).toBe(expected);
447
- },
448
- );
449
-
450
- test("mixed intent with dynamic name extracts remainder", () => {
451
- const result = resolveRecordingIntent(
452
- "Nova, open Safari and record my screen",
453
- ["Nova"],
454
- );
455
- expect(result.kind).toBe("start_with_remainder");
456
- if (result.kind === "start_with_remainder") {
457
- expect(result.remainder).toContain("open Safari");
458
- }
459
- });
460
-
461
- test("dynamic name stripping is case-insensitive", () => {
462
- expect(
463
- resolveRecordingIntent("nova, record my screen", ["Nova"]).kind,
464
- ).toBe("start_only");
465
- expect(
466
- resolveRecordingIntent("NOVA, stop recording", ["Nova"]).kind,
467
- ).toBe("stop_only");
468
- expect(
469
- resolveRecordingIntent("Hey NOVA, start recording", ["nova"]).kind,
470
- ).toBe("start_only");
471
- });
472
-
473
- test("handles multiple dynamic names", () => {
474
- expect(
475
- resolveRecordingIntent("Jarvis, record my screen", ["Nova", "Jarvis"])
476
- .kind,
477
- ).toBe("start_only");
478
- expect(
479
- resolveRecordingIntent("Nova, stop recording", ["Nova", "Jarvis"]).kind,
480
- ).toBe("stop_only");
481
- });
482
-
483
- test("handles empty dynamic names array", () => {
484
- expect(resolveRecordingIntent("record my screen", []).kind).toBe(
485
- "start_only",
486
- );
487
- expect(resolveRecordingIntent("stop recording", []).kind).toBe(
488
- "stop_only",
489
- );
490
- });
491
-
492
- test("handles colon separator after name", () => {
493
- expect(
494
- resolveRecordingIntent("Nova: record my screen", ["Nova"]).kind,
495
- ).toBe("start_only");
496
- });
497
-
498
- test("interrogative with name prefix returns none", () => {
499
- expect(
500
- resolveRecordingIntent("hey Nova, how do I stop recording?", ["Nova"]),
501
- ).toEqual({ kind: "none" });
502
- });
503
- });
504
-
505
- // ── Start + stop combined ──────────────────────────────────────────────────
506
-
507
- describe("combined start and stop", () => {
508
- test('start and stop: "stop recording and record my screen"', () => {
509
- const result = resolveRecordingIntent(
510
- "stop recording and record my screen",
511
- );
512
- expect(result.kind).toBe("start_and_stop_only");
513
- });
514
-
515
- test('start and stop: "stop recording and start recording"', () => {
516
- const result = resolveRecordingIntent(
517
- "stop recording and start recording",
518
- );
519
- expect(result.kind).toBe("start_and_stop_only");
520
- });
521
- });
522
-
523
- // ── Restart compound detection ────────────────────────────────────────────
524
-
525
- describe("restart compound detection", () => {
526
- test('"restart the recording" → restart_only', () => {
527
- expect(resolveRecordingIntent("restart the recording")).toEqual({
528
- kind: "restart_only",
529
- });
530
- });
531
-
532
- test('"restart recording" → restart_only', () => {
533
- expect(resolveRecordingIntent("restart recording")).toEqual({
534
- kind: "restart_only",
535
- });
536
- });
537
-
538
- test('"redo the recording" → restart_only', () => {
539
- expect(resolveRecordingIntent("redo the recording")).toEqual({
540
- kind: "restart_only",
541
- });
542
- });
543
-
544
- test('"stop recording and start a new one" → restart_only', () => {
545
- expect(
546
- resolveRecordingIntent("stop recording and start a new one"),
547
- ).toEqual({ kind: "restart_only" });
548
- });
549
-
550
- test('"stop the recording and start a new one" → restart_only', () => {
551
- expect(
552
- resolveRecordingIntent("stop the recording and start a new one"),
553
- ).toEqual({ kind: "restart_only" });
554
- });
555
-
556
- test('"stop the recording and begin a fresh" → restart_only', () => {
557
- expect(
558
- resolveRecordingIntent("stop the recording and begin a fresh"),
559
- ).toEqual({ kind: "restart_only" });
560
- });
561
-
562
- test('"stop and restart the recording" → restart_only', () => {
563
- expect(resolveRecordingIntent("stop and restart the recording")).toEqual({
564
- kind: "restart_only",
565
- });
566
- });
567
-
568
- test('"stop recording and start a new" → restart_only', () => {
569
- expect(resolveRecordingIntent("stop recording and start a new")).toEqual({
570
- kind: "restart_only",
571
- });
572
- });
573
-
574
- test('"stop recording and start another" → restart_only', () => {
575
- expect(
576
- resolveRecordingIntent("stop recording and start another"),
577
- ).toEqual({ kind: "restart_only" });
578
- });
579
-
580
- test('"stop recording and start another." → restart_only (trailing period)', () => {
581
- expect(
582
- resolveRecordingIntent("stop recording and start another."),
583
- ).toEqual({ kind: "restart_only" });
584
- });
585
-
586
- test('"stop recording and start a new!" → restart_only (trailing exclamation)', () => {
587
- expect(resolveRecordingIntent("stop recording and start a new!")).toEqual(
588
- { kind: "restart_only" },
589
- );
590
- });
591
-
592
- test('restart with remainder: "restart recording and open safari"', () => {
593
- const result = resolveRecordingIntent(
594
- "restart recording and open safari",
595
- );
596
- expect(result.kind).toBe("restart_with_remainder");
597
- if (result.kind === "restart_with_remainder") {
598
- expect(result.remainder).toContain("open safari");
599
- }
600
- });
601
-
602
- test("restart with polite fillers resolves as restart_only", () => {
603
- expect(resolveRecordingIntent("please restart the recording")).toEqual({
604
- kind: "restart_only",
605
- });
606
- expect(resolveRecordingIntent("can you restart recording")).toEqual({
607
- kind: "restart_only",
608
- });
609
- });
610
-
611
- test("restart takes precedence over independent start/stop", () => {
612
- // "stop recording and start a new one" should be restart, not start_and_stop
613
- const result = resolveRecordingIntent(
614
- "stop recording and start a new one",
615
- );
616
- expect(result.kind).toBe("restart_only");
617
- });
618
-
619
- test('"stop recording and start a new recording" → restart_only', () => {
620
- expect(
621
- resolveRecordingIntent("stop recording and start a new recording"),
622
- ).toEqual({ kind: "restart_only" });
623
- });
624
-
625
- test('"stop the recording and start another recording" → restart_only', () => {
626
- expect(
627
- resolveRecordingIntent(
628
- "stop the recording and start another recording",
629
- ),
630
- ).toEqual({ kind: "restart_only" });
631
- });
632
-
633
- // False positive guards: "start another/new <non-recording>" should NOT trigger restart
634
- test('"stop recording and start another tab" should NOT trigger restart', () => {
635
- const result = resolveRecordingIntent(
636
- "stop recording and start another tab",
637
- );
638
- expect(result.kind).toBe("stop_with_remainder");
639
- });
640
-
641
- test('"stop recording and start another window" should NOT trigger restart', () => {
642
- const result = resolveRecordingIntent(
643
- "stop recording and start another window",
644
- );
645
- expect(result.kind).toBe("stop_with_remainder");
646
- });
647
-
648
- test('"stop recording and start a new project" should NOT trigger restart', () => {
649
- const result = resolveRecordingIntent(
650
- "stop recording and start a new project",
651
- );
652
- expect(result.kind).toBe("stop_with_remainder");
653
- });
654
-
655
- test('"stop the recording and begin a fresh session" should NOT trigger restart', () => {
656
- const result = resolveRecordingIntent(
657
- "stop the recording and begin a fresh session",
658
- );
659
- expect(result.kind).toBe("stop_with_remainder");
660
- });
661
- });
662
-
663
- // ── Pause detection ───────────────────────────────────────────────────────
664
-
665
- describe("pause detection", () => {
666
- test('"pause recording" → pause_only', () => {
667
- expect(resolveRecordingIntent("pause recording")).toEqual({
668
- kind: "pause_only",
669
- });
670
- });
671
-
672
- test('"pause the recording" → pause_only', () => {
673
- expect(resolveRecordingIntent("pause the recording")).toEqual({
674
- kind: "pause_only",
675
- });
676
- });
677
-
678
- test("pause with polite fillers resolves as pause_only", () => {
679
- expect(resolveRecordingIntent("please pause the recording")).toEqual({
680
- kind: "pause_only",
681
- });
682
- expect(resolveRecordingIntent("can you pause recording")).toEqual({
683
- kind: "pause_only",
684
- });
685
- });
686
- });
687
-
688
- // ── Resume detection ──────────────────────────────────────────────────────
689
-
690
- describe("resume detection", () => {
691
- test('"resume recording" → resume_only', () => {
692
- expect(resolveRecordingIntent("resume recording")).toEqual({
693
- kind: "resume_only",
694
- });
695
- });
696
-
697
- test('"resume the recording" → resume_only', () => {
698
- expect(resolveRecordingIntent("resume the recording")).toEqual({
699
- kind: "resume_only",
700
- });
701
- });
702
-
703
- test('"unpause the recording" → resume_only', () => {
704
- expect(resolveRecordingIntent("unpause the recording")).toEqual({
705
- kind: "resume_only",
706
- });
707
- });
708
-
709
- test("resume with polite fillers resolves as resume_only", () => {
710
- expect(resolveRecordingIntent("please resume the recording")).toEqual({
711
- kind: "resume_only",
712
- });
713
- });
714
- });
715
-
716
- // ── False positive guards ─────────────────────────────────────────────────
717
-
718
- describe("false positive guards", () => {
719
- test('"I recorded a restart" → none', () => {
720
- expect(resolveRecordingIntent("I recorded a restart")).toEqual({
721
- kind: "none",
722
- });
723
- });
724
-
725
- test('"the pause button is broken" → none (no recording mention)', () => {
726
- expect(resolveRecordingIntent("the pause button is broken")).toEqual({
727
- kind: "none",
728
- });
729
- });
730
-
731
- test('"resume my work" → none (no recording mention)', () => {
732
- expect(resolveRecordingIntent("resume my work")).toEqual({
733
- kind: "none",
734
- });
735
- });
736
- });
737
-
738
- // ── No recording intent ────────────────────────────────────────────────────
739
-
740
- describe("no recording intent", () => {
741
- test.each(["open Safari", "I broke the record", "", "hello world"])(
742
- 'returns none for "%s"',
743
- (text) => {
744
- expect(resolveRecordingIntent(text)).toEqual({ kind: "none" });
745
- },
746
- );
747
- });
748
-
749
- // ── Works without dynamic names parameter ──────────────────────────────────
750
-
751
- test("works without dynamic names parameter", () => {
752
- expect(resolveRecordingIntent("record my screen")).toEqual({
753
- kind: "start_only",
754
- });
755
- expect(resolveRecordingIntent("stop recording")).toEqual({
756
- kind: "stop_only",
757
- });
758
- });
759
- });
760
-
761
- // ─── executeRecordingIntent ─────────────────────────────────────────────────
762
-
763
- describe("executeRecordingIntent", () => {
764
- // Mock the recording handlers module
765
- const mockHandleRecordingStart = mock(
766
- (): string | null => "mock-recording-id",
767
- );
768
- const mockHandleRecordingStop = mock(
769
- (): string | undefined => "mock-recording-id",
770
- );
771
- const mockHandleRecordingRestart = mock(
772
- (): {
773
- initiated: boolean;
774
- operationToken?: string;
775
- responseText: string;
776
- } => ({
777
- initiated: true,
778
- operationToken: "mock-token",
779
- responseText: "Restarting screen recording.",
780
- }),
781
- );
782
- const mockHandleRecordingPause = mock(
783
- (): string | undefined => "mock-recording-id",
784
- );
785
- const mockHandleRecordingResume = mock(
786
- (): string | undefined => "mock-recording-id",
787
- );
788
-
789
- mock.module("../daemon/handlers/recording.js", () => ({
790
- handleRecordingStart: mockHandleRecordingStart,
791
- handleRecordingStop: mockHandleRecordingStop,
792
- handleRecordingRestart: mockHandleRecordingRestart,
793
- handleRecordingPause: mockHandleRecordingPause,
794
- handleRecordingResume: mockHandleRecordingResume,
795
- isRecordingIdle: () => true,
796
- }));
797
-
798
- // Dynamically import so the mock takes effect
799
- let executeRecordingIntent: typeof import("../daemon/recording-executor.js").executeRecordingIntent;
800
-
801
- // Must await the dynamic import before running tests
802
- const setupPromise = import("../daemon/recording-executor.js").then((mod) => {
803
- executeRecordingIntent = mod.executeRecordingIntent;
804
- });
805
-
806
- const mockContext = {
807
- conversationId: "conv-123",
808
- socket: {} as any,
809
- ctx: {} as any,
810
- };
811
-
812
- beforeEach(async () => {
813
- await setupPromise;
814
- mockHandleRecordingStart.mockReset();
815
- mockHandleRecordingStop.mockReset();
816
- mockHandleRecordingRestart.mockReset();
817
- mockHandleRecordingPause.mockReset();
818
- mockHandleRecordingResume.mockReset();
819
- // Default: start succeeds (returns recording ID)
820
- mockHandleRecordingStart.mockReturnValue("mock-recording-id");
821
- // Default: stop succeeds (returns recording ID)
822
- mockHandleRecordingStop.mockReturnValue("mock-recording-id");
823
- // Default: restart succeeds
824
- mockHandleRecordingRestart.mockReturnValue({
825
- initiated: true,
826
- operationToken: "mock-token",
827
- responseText: "Restarting screen recording.",
828
- });
829
- // Default: pause succeeds
830
- mockHandleRecordingPause.mockReturnValue("mock-recording-id");
831
- // Default: resume succeeds
832
- mockHandleRecordingResume.mockReturnValue("mock-recording-id");
833
- });
834
-
835
- test("none → returns { handled: false }", () => {
836
- const result = executeRecordingIntent({ kind: "none" }, mockContext);
837
- expect(result).toEqual({ handled: false });
838
- });
839
-
840
- test("start_only → calls handleRecordingStart, returns handled with start text", () => {
841
- const result = executeRecordingIntent({ kind: "start_only" }, mockContext);
842
- expect(mockHandleRecordingStart).toHaveBeenCalledTimes(1);
843
- expect(result).toEqual({
844
- handled: true,
845
- recordingStarted: true,
846
- responseText: "Starting screen recording.",
847
- });
848
- });
849
-
850
- test("start_only when recording already active → returns handled with already-active text", () => {
851
- mockHandleRecordingStart.mockReturnValue(null);
852
- const result = executeRecordingIntent({ kind: "start_only" }, mockContext);
853
- expect(mockHandleRecordingStart).toHaveBeenCalledTimes(1);
854
- expect(result).toEqual({
855
- handled: true,
856
- recordingStarted: false,
857
- responseText: "A recording is already active.",
858
- });
859
- });
860
-
861
- test("stop_only → calls handleRecordingStop, returns handled with stop text", () => {
862
- const result = executeRecordingIntent({ kind: "stop_only" }, mockContext);
863
- expect(mockHandleRecordingStop).toHaveBeenCalledTimes(1);
864
- expect(result).toEqual({
865
- handled: true,
866
- responseText: "Stopping the recording.",
867
- });
868
- });
869
-
870
- test("stop_only when no active recording → returns handled with no-active text", () => {
871
- mockHandleRecordingStop.mockReturnValue(undefined);
872
- const result = executeRecordingIntent({ kind: "stop_only" }, mockContext);
873
- expect(result).toEqual({
874
- handled: true,
875
- responseText: "No active recording to stop.",
876
- });
877
- });
878
-
879
- test("start_with_remainder → returns not handled with remainder and pendingStart", () => {
880
- const result = executeRecordingIntent(
881
- { kind: "start_with_remainder", remainder: "open Safari" },
882
- mockContext,
883
- );
884
- expect(result).toEqual({
885
- handled: false,
886
- remainderText: "open Safari",
887
- pendingStart: true,
888
- });
889
- });
890
-
891
- test("stop_with_remainder → returns not handled with remainder and pendingStop", () => {
892
- const result = executeRecordingIntent(
893
- { kind: "stop_with_remainder", remainder: "open Chrome" },
894
- mockContext,
895
- );
896
- expect(result).toEqual({
897
- handled: false,
898
- remainderText: "open Chrome",
899
- pendingStop: true,
900
- });
901
- });
902
-
903
- test("start_and_stop_only → routes through handleRecordingRestart, returns handled", () => {
904
- const result = executeRecordingIntent(
905
- { kind: "start_and_stop_only" },
906
- mockContext,
907
- );
908
- expect(mockHandleRecordingRestart).toHaveBeenCalledTimes(1);
909
- expect(result).toEqual({
910
- handled: true,
911
- recordingStarted: true,
912
- responseText: "Stopping current recording and starting a new one.",
913
- });
914
- });
915
-
916
- test("start_and_stop_only when restart fails → returns handled with restart failure text", () => {
917
- mockHandleRecordingRestart.mockReturnValue({
918
- initiated: false,
919
- responseText: "No active recording to restart.",
920
- });
921
- const result = executeRecordingIntent(
922
- { kind: "start_and_stop_only" },
923
- mockContext,
924
- );
925
- expect(mockHandleRecordingRestart).toHaveBeenCalledTimes(1);
926
- expect(result).toEqual({
927
- handled: true,
928
- recordingStarted: false,
929
- responseText: "No active recording to restart.",
930
- });
931
- });
932
-
933
- test("start_and_stop_with_remainder → returns not handled with remainder and pendingStart when idle", () => {
934
- const result = executeRecordingIntent(
935
- { kind: "start_and_stop_with_remainder", remainder: "open Safari" },
936
- mockContext,
937
- );
938
- expect(result).toEqual({
939
- handled: false,
940
- remainderText: "open Safari",
941
- pendingStart: true,
942
- });
943
- });
944
-
945
- // ── New intent kinds ──────────────────────────────────────────────────────
946
-
947
- test("restart_only → returns handled with restart text", () => {
948
- const result = executeRecordingIntent(
949
- { kind: "restart_only" },
950
- mockContext,
951
- );
952
- expect(result).toEqual({
953
- handled: true,
954
- responseText: "Restarting screen recording.",
955
- });
956
- });
957
-
958
- test("restart_with_remainder → returns not handled with remainder and pendingRestart", () => {
959
- const result = executeRecordingIntent(
960
- { kind: "restart_with_remainder", remainder: "and open safari" },
961
- mockContext,
962
- );
963
- expect(result).toEqual({
964
- handled: false,
965
- remainderText: "and open safari",
966
- pendingRestart: true,
967
- });
968
- });
969
-
970
- test("pause_only → returns handled with pause text", () => {
971
- const result = executeRecordingIntent({ kind: "pause_only" }, mockContext);
972
- expect(result).toEqual({
973
- handled: true,
974
- responseText: "Pausing the recording.",
975
- });
976
- });
977
-
978
- test("resume_only → returns handled with resume text", () => {
979
- const result = executeRecordingIntent({ kind: "resume_only" }, mockContext);
980
- expect(result).toEqual({
981
- handled: true,
982
- responseText: "Resuming the recording.",
983
- });
984
- });
985
- });