@vellumai/assistant 0.4.42 → 0.4.44

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 (867) hide show
  1. package/.env.example +1 -6
  2. package/.prettierignore +3 -0
  3. package/ARCHITECTURE.md +140 -403
  4. package/Dockerfile +0 -1
  5. package/README.md +81 -92
  6. package/bun.lock +8 -2
  7. package/docs/architecture/integrations.md +81 -104
  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 -3
  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-asset.test.ts +1 -1
  33. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -9
  34. package/src/__tests__/call-controller.test.ts +4 -8
  35. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  36. package/src/__tests__/call-domain.test.ts +250 -8
  37. package/src/__tests__/call-pointer-message-composer.test.ts +14 -14
  38. package/src/__tests__/call-pointer-messages.test.ts +7 -11
  39. package/src/__tests__/call-recovery.test.ts +47 -0
  40. package/src/__tests__/call-routes-http.test.ts +13 -0
  41. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  42. package/src/__tests__/callback-handoff-copy.test.ts +5 -5
  43. package/src/__tests__/canonical-guardian-store.test.ts +3 -3
  44. package/src/__tests__/channel-approval-routes.test.ts +101 -134
  45. package/src/__tests__/channel-approval.test.ts +0 -201
  46. package/src/__tests__/channel-approvals.test.ts +2 -2
  47. package/src/__tests__/channel-delivery-store.test.ts +16 -24
  48. package/src/__tests__/channel-guardian.test.ts +641 -740
  49. package/src/__tests__/channel-invite-transport.test.ts +1 -2
  50. package/src/__tests__/channel-policy.test.ts +9 -12
  51. package/src/__tests__/channel-readiness-service.test.ts +156 -45
  52. package/src/__tests__/channel-reply-delivery.test.ts +3 -3
  53. package/src/__tests__/channel-retry-sweep.test.ts +7 -7
  54. package/src/__tests__/checker.test.ts +41 -35
  55. package/src/__tests__/chrome-cdp.test.ts +57 -17
  56. package/src/__tests__/cli-help-reference-sync.test.ts +26 -0
  57. package/src/__tests__/compaction.benchmark.test.ts +25 -5
  58. package/src/__tests__/computer-use-session-lifecycle.test.ts +1 -1
  59. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  60. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
  61. package/src/__tests__/config-loader-backfill.test.ts +310 -0
  62. package/src/__tests__/config-watcher.test.ts +1 -5
  63. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +3 -5
  64. package/src/__tests__/connection-policy.test.ts +3 -62
  65. package/src/__tests__/contacts-tools.test.ts +0 -2
  66. package/src/__tests__/context-memory-e2e.test.ts +11 -7
  67. package/src/__tests__/context-overflow-policy.test.ts +2 -2
  68. package/src/__tests__/context-window-manager.test.ts +220 -61
  69. package/src/__tests__/conversation-attention-store.test.ts +178 -2
  70. package/src/__tests__/conversation-attention-telegram.test.ts +8 -11
  71. package/src/__tests__/conversation-pairing.test.ts +14 -14
  72. package/src/__tests__/conversation-routes-guardian-reply.test.ts +7 -7
  73. package/src/__tests__/conversation-store.test.ts +2 -2
  74. package/src/__tests__/conversation-unread-route.test.ts +155 -0
  75. package/src/__tests__/credential-metadata-store.test.ts +0 -2
  76. package/src/__tests__/credential-security-invariants.test.ts +10 -16
  77. package/src/__tests__/credentials-cli.test.ts +49 -5
  78. package/src/__tests__/daemon-assistant-events.test.ts +4 -22
  79. package/src/__tests__/db-migration-rollback.test.ts +2 -2
  80. package/src/__tests__/deterministic-verification-control-plane.test.ts +19 -19
  81. package/src/__tests__/dictation-mode-detection.test.ts +1 -1
  82. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  83. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -6
  84. package/src/__tests__/email-cli.test.ts +12 -12
  85. package/src/__tests__/email-service-config-fallback.test.ts +1 -1
  86. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -18
  87. package/src/__tests__/error-handler-friendly-messages.test.ts +46 -0
  88. package/src/__tests__/event-bus.test.ts +0 -1
  89. package/src/__tests__/followup-tools.test.ts +0 -2
  90. package/src/__tests__/gateway-client-managed-outbound.test.ts +6 -6
  91. package/src/__tests__/gateway-only-enforcement.test.ts +13 -77
  92. package/src/__tests__/gateway-only-guard.test.ts +5 -0
  93. package/src/__tests__/guardian-action-conversation-turn.test.ts +3 -3
  94. package/src/__tests__/guardian-action-followup-executor.test.ts +29 -94
  95. package/src/__tests__/guardian-action-followup-store.test.ts +2 -12
  96. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +48 -194
  97. package/src/__tests__/guardian-action-late-reply.test.ts +12 -12
  98. package/src/__tests__/guardian-action-store.test.ts +2 -2
  99. package/src/__tests__/guardian-action-sweep.test.ts +5 -5
  100. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -3
  101. package/src/__tests__/guardian-dispatch.test.ts +5 -46
  102. package/src/__tests__/guardian-grant-minting.test.ts +5 -44
  103. package/src/__tests__/guardian-outbound-http.test.ts +95 -114
  104. package/src/__tests__/guardian-question-mode.test.ts +1 -4
  105. package/src/__tests__/guardian-routing-invariants.test.ts +5 -13
  106. package/src/__tests__/guardian-routing-state.test.ts +3 -3
  107. package/src/__tests__/guardian-verification-voice-binding.test.ts +64 -7
  108. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  109. package/src/__tests__/handle-user-message-secret-resume.test.ts +3 -5
  110. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +16 -34
  111. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  112. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  113. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  114. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  115. package/src/__tests__/heartbeat-service.test.ts +1 -1
  116. package/src/__tests__/host-shell-tool.test.ts +3 -12
  117. package/src/__tests__/inbound-invite-redemption.test.ts +2 -2
  118. package/src/__tests__/ingress-url-consistency.test.ts +0 -64
  119. package/src/__tests__/integration-status.test.ts +8 -8
  120. package/src/__tests__/intent-routing.test.ts +9 -13
  121. package/src/__tests__/invite-redemption-service.test.ts +4 -4
  122. package/src/__tests__/invite-routes-http.test.ts +10 -10
  123. package/src/__tests__/llm-usage-store.test.ts +45 -9
  124. package/src/__tests__/local-gateway-health.test.ts +209 -0
  125. package/src/__tests__/managed-avatar-client.test.ts +23 -12
  126. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -2
  127. package/src/__tests__/managed-store.test.ts +29 -12
  128. package/src/__tests__/managed-twitter-guardrails.test.ts +357 -0
  129. package/src/__tests__/mcp-cli.test.ts +1 -1
  130. package/src/__tests__/mcp-health-check.test.ts +1 -1
  131. package/src/__tests__/media-generate-image.test.ts +1 -1
  132. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -4
  133. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +9 -6
  134. package/src/__tests__/memory-regressions.test.ts +1 -166
  135. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  136. package/src/__tests__/migration-export-http.test.ts +2 -2
  137. package/src/__tests__/migration-transport.test.ts +44 -0
  138. package/src/__tests__/non-member-access-request.test.ts +49 -36
  139. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  140. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  141. package/src/__tests__/notification-decision-strategy.test.ts +4 -4
  142. package/src/__tests__/notification-deep-link.test.ts +3 -3
  143. package/src/__tests__/notification-guardian-path.test.ts +6 -44
  144. package/src/__tests__/notification-routing-intent.test.ts +11 -7
  145. package/src/__tests__/oauth-cli.test.ts +1 -1
  146. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -6
  147. package/src/__tests__/onboarding-template-contract.test.ts +2 -12
  148. package/src/__tests__/platform.test.ts +168 -5
  149. package/src/__tests__/playbook-execution.test.ts +0 -2
  150. package/src/__tests__/playbook-tools.test.ts +0 -2
  151. package/src/__tests__/pricing.test.ts +125 -0
  152. package/src/__tests__/provider-error-scenarios.test.ts +9 -3
  153. package/src/__tests__/provider-fail-open-selection.test.ts +12 -2
  154. package/src/__tests__/recording-handler.test.ts +46 -80
  155. package/src/__tests__/recording-state-machine.test.ts +112 -183
  156. package/src/__tests__/registry.test.ts +1 -1
  157. package/src/__tests__/relay-server.test.ts +69 -71
  158. package/src/__tests__/reminder-store.test.ts +3 -3
  159. package/src/__tests__/request-file-tool.test.ts +2 -2
  160. package/src/__tests__/ride-shotgun-handler.test.ts +2 -33
  161. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -3
  162. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  163. package/src/__tests__/scaffold-managed-skill-tool.test.ts +4 -4
  164. package/src/__tests__/schedule-store.test.ts +13 -4
  165. package/src/__tests__/schedule-tools.test.ts +0 -2
  166. package/src/__tests__/scheduler-recurrence.test.ts +3 -4
  167. package/src/__tests__/scoped-approval-grants.test.ts +3 -5
  168. package/src/__tests__/scoped-grant-security-matrix.test.ts +6 -8
  169. package/src/__tests__/secret-prompt-log-hygiene.test.ts +1 -1
  170. package/src/__tests__/secret-response-routing.test.ts +1 -1
  171. package/src/__tests__/send-endpoint-busy.test.ts +1 -4
  172. package/src/__tests__/sequence-store.test.ts +0 -2
  173. package/src/__tests__/server-history-render.test.ts +2 -199
  174. package/src/__tests__/session-abort-tool-results.test.ts +9 -3
  175. package/src/__tests__/session-agent-loop.test.ts +107 -3
  176. package/src/__tests__/session-confirmation-signals.test.ts +17 -49
  177. package/src/__tests__/session-conflict-gate.test.ts +9 -3
  178. package/src/__tests__/session-init.benchmark.test.ts +22 -13
  179. package/src/__tests__/session-load-history-repair.test.ts +6 -3
  180. package/src/__tests__/session-pre-run-repair.test.ts +9 -3
  181. package/src/__tests__/session-profile-injection.test.ts +9 -3
  182. package/src/__tests__/session-provider-retry-repair.test.ts +10 -4
  183. package/src/__tests__/session-queue.test.ts +10 -4
  184. package/src/__tests__/session-runtime-assembly.test.ts +28 -18
  185. package/src/__tests__/session-skill-tools.test.ts +2 -3
  186. package/src/__tests__/session-slash-known.test.ts +11 -4
  187. package/src/__tests__/session-slash-queue.test.ts +11 -4
  188. package/src/__tests__/session-slash-unknown.test.ts +12 -4
  189. package/src/__tests__/session-surfaces-deselection.test.ts +2 -2
  190. package/src/__tests__/session-surfaces-task-progress.test.ts +3 -3
  191. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -1
  192. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
  193. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
  194. package/src/__tests__/session-usage.test.ts +180 -0
  195. package/src/__tests__/session-workspace-cache-state.test.ts +8 -2
  196. package/src/__tests__/session-workspace-injection.test.ts +8 -2
  197. package/src/__tests__/session-workspace-tool-tracking.test.ts +8 -2
  198. package/src/__tests__/skill-feature-flags-integration.test.ts +5 -11
  199. package/src/__tests__/skill-feature-flags.test.ts +1 -0
  200. package/src/__tests__/skill-include-graph.test.ts +1 -0
  201. package/src/__tests__/skill-load-feature-flag.test.ts +3 -9
  202. package/src/__tests__/skill-load-tool.test.ts +90 -12
  203. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -15
  204. package/src/__tests__/skills-uninstall.test.ts +131 -0
  205. package/src/__tests__/skills.test.ts +32 -16
  206. package/src/__tests__/slack-block-formatting.test.ts +1 -1
  207. package/src/__tests__/slack-channel-config.test.ts +71 -12
  208. package/src/__tests__/slack-inbound-verification.test.ts +7 -7
  209. package/src/__tests__/slack-share-routes.test.ts +1 -1
  210. package/src/__tests__/slack-skill.test.ts +2 -2
  211. package/src/__tests__/slash-commands-catalog.test.ts +1 -0
  212. package/src/__tests__/slash-commands-resolver.test.ts +1 -0
  213. package/src/__tests__/starter-task-flow.test.ts +10 -20
  214. package/src/__tests__/subagent-manager-notify.test.ts +1 -1
  215. package/src/__tests__/subagent-tools.test.ts +2 -2
  216. package/src/__tests__/system-prompt.test.ts +7 -12
  217. package/src/__tests__/task-compiler.test.ts +0 -2
  218. package/src/__tests__/task-management-tools.test.ts +0 -2
  219. package/src/__tests__/task-runner.test.ts +0 -2
  220. package/src/__tests__/task-scheduler.test.ts +2 -2
  221. package/src/__tests__/telegram-bot-username-resolution.test.ts +46 -44
  222. package/src/__tests__/terminal-tools.test.ts +1 -11
  223. package/src/__tests__/thread-seed-composer.test.ts +3 -1
  224. package/src/__tests__/tool-approval-handler.test.ts +5 -7
  225. package/src/__tests__/tool-executor.test.ts +2 -2
  226. package/src/__tests__/tool-grant-request-escalation.test.ts +3 -5
  227. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  228. package/src/__tests__/tool-profiling-listener.test.ts +1 -1
  229. package/src/__tests__/tool-trace-listener.test.ts +1 -2
  230. package/src/__tests__/trace-emitter.test.ts +1 -1
  231. package/src/__tests__/trust-context-guards.test.ts +1 -1
  232. package/src/__tests__/trust-store.test.ts +48 -399
  233. package/src/__tests__/trusted-contact-approval-notifier.test.ts +6 -8
  234. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +5 -7
  235. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +6 -6
  236. package/src/__tests__/trusted-contact-multichannel.test.ts +54 -47
  237. package/src/__tests__/trusted-contact-verification.test.ts +12 -12
  238. package/src/__tests__/twilio-config.test.ts +11 -2
  239. package/src/__tests__/twilio-provider.test.ts +6 -4
  240. package/src/__tests__/twilio-routes.test.ts +408 -86
  241. package/src/__tests__/twitter-platform-proxy-client.test.ts +475 -0
  242. package/src/__tests__/update-bulletin-format.test.ts +1 -1
  243. package/src/__tests__/update-bulletin-state.test.ts +1 -1
  244. package/src/__tests__/update-bulletin.test.ts +4 -8
  245. package/src/__tests__/update-template-contract.test.ts +1 -1
  246. package/src/__tests__/usage-cache-backfill-migration.test.ts +406 -0
  247. package/src/__tests__/usage-routes.test.ts +23 -5
  248. package/src/__tests__/user-reference.test.ts +1 -1
  249. package/src/__tests__/{guardian-control-plane-policy.test.ts → verification-control-plane-policy.test.ts} +142 -170
  250. package/src/__tests__/{guardian-verification-intent-routing.test.ts → verification-session-intent-routing.test.ts} +16 -16
  251. package/src/__tests__/view-image-tool.test.ts +0 -2
  252. package/src/__tests__/voice-ingress-preflight.test.ts +36 -0
  253. package/src/__tests__/voice-invite-redemption.test.ts +18 -18
  254. package/src/__tests__/voice-scoped-grant-consumer.test.ts +7 -7
  255. package/src/__tests__/voice-session-bridge.test.ts +14 -16
  256. package/src/__tests__/workspace-policy.test.ts +1 -1
  257. package/src/approvals/AGENTS.md +4 -4
  258. package/src/approvals/approval-primitive.ts +2 -2
  259. package/src/approvals/guardian-decision-primitive.ts +1 -1
  260. package/src/approvals/guardian-request-resolvers.ts +3 -4
  261. package/src/bundler/app-bundler.ts +29 -217
  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} +14 -54
  290. package/src/{amazon → cli/commands/amazon}/request-extractor.ts +39 -3
  291. package/src/cli/commands/amazon/session.ts +108 -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} +15 -17
  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/cli/commands/twitter/__tests__/cli-read-routing.test.ts +345 -0
  316. package/src/cli/commands/twitter/__tests__/cli-routing.test.ts +252 -0
  317. package/src/{__tests__/twitter-oauth-client.test.ts → cli/commands/twitter/__tests__/oauth-client.test.ts} +2 -48
  318. package/src/cli/commands/twitter/index.ts +420 -0
  319. package/src/{twitter → cli/commands/twitter}/oauth-client.ts +1 -35
  320. package/src/cli/commands/twitter/router.ts +351 -0
  321. package/src/cli/commands/twitter/types.ts +30 -0
  322. package/src/cli/db.ts +1 -0
  323. package/src/cli/http-client.ts +87 -0
  324. package/src/cli/logger.ts +6 -0
  325. package/src/cli/main-screen.tsx +4 -3
  326. package/src/cli/output.ts +19 -0
  327. package/src/cli/program.ts +29 -27
  328. package/src/cli/reference.ts +27 -37
  329. package/src/cli.ts +452 -240
  330. package/src/config/assistant-feature-flags.ts +3 -15
  331. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +3 -6
  332. package/src/config/bundled-skills/agentmail/SKILL.md +4 -4
  333. package/src/config/bundled-skills/amazon/SKILL.md +15 -6
  334. package/src/config/bundled-skills/api-mapping/SKILL.md +4 -4
  335. package/src/config/bundled-skills/app-builder/SKILL.md +4 -9
  336. package/src/config/bundled-skills/app-builder/TOOLS.json +0 -4
  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 +23 -77
  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 -12
  348. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +1 -90
  349. package/src/config/bundled-skills/doordash/doordash-cli.ts +132 -109
  350. package/src/config/bundled-skills/doordash/lib/session.ts +22 -19
  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 +73 -144
  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 +8 -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 +196 -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 +151 -105
  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 +155 -55
  452. package/src/daemon/{ipc-contract.ts → message-protocol.ts} +49 -49
  453. package/src/daemon/{ipc-contract → message-types}/apps.ts +0 -25
  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 +30 -20
  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 +7 -1
  460. package/src/daemon/{ipc-contract → message-types}/shared.ts +0 -8
  461. package/src/daemon/{ipc-contract → message-types}/surfaces.ts +2 -0
  462. package/src/daemon/{ipc-contract → message-types}/workspace.ts +2 -2
  463. package/src/daemon/providers-setup.ts +0 -5
  464. package/src/daemon/recording-executor.ts +0 -7
  465. package/src/daemon/ride-shotgun-handler.ts +42 -14
  466. package/src/daemon/seed-files.ts +3 -27
  467. package/src/daemon/server.ts +134 -524
  468. package/src/daemon/session-agent-loop-handlers.ts +46 -9
  469. package/src/daemon/session-agent-loop.ts +86 -24
  470. package/src/daemon/session-attachments.ts +1 -1
  471. package/src/daemon/session-error.ts +1 -1
  472. package/src/daemon/session-history.ts +20 -15
  473. package/src/daemon/session-lifecycle.ts +9 -7
  474. package/src/daemon/session-memory.ts +15 -1
  475. package/src/daemon/session-messaging.ts +10 -6
  476. package/src/daemon/session-notifiers.ts +10 -8
  477. package/src/daemon/session-process.ts +34 -25
  478. package/src/daemon/session-queue-manager.ts +1 -1
  479. package/src/daemon/session-runtime-assembly.ts +6 -32
  480. package/src/daemon/session-surfaces.ts +187 -35
  481. package/src/daemon/session-tool-setup.ts +1 -1
  482. package/src/daemon/session-usage.ts +119 -18
  483. package/src/daemon/session.ts +11 -33
  484. package/src/daemon/tool-side-effects.ts +6 -5
  485. package/src/daemon/trace-emitter.ts +1 -1
  486. package/src/daemon/{guardian-verification-intent.ts → verification-session-intent.ts} +16 -16
  487. package/src/daemon/watch-handler.ts +2 -5
  488. package/src/email/service.ts +8 -8
  489. package/src/events/domain-events.ts +0 -1
  490. package/src/events/tool-notification-listener.ts +1 -1
  491. package/src/followups/followup-store.ts +1 -2
  492. package/src/followups/types.ts +0 -6
  493. package/src/heartbeat/heartbeat-service.ts +1 -1
  494. package/src/inbound/platform-callback-registration.ts +1 -1
  495. package/src/inbound/public-ingress-urls.ts +0 -8
  496. package/src/index.ts +12 -0
  497. package/src/mcp/client.ts +1 -1
  498. package/src/mcp/manager.ts +1 -1
  499. package/src/memory/app-store.ts +1 -60
  500. package/src/memory/{guardian-verification.ts → channel-verification-sessions.ts} +110 -93
  501. package/src/memory/conversation-attention-store.ts +154 -0
  502. package/src/memory/conversation-bootstrap.ts +1 -1
  503. package/src/memory/conversation-crud.ts +53 -1
  504. package/src/memory/conversation-display-order-migration.ts +2 -3
  505. package/src/memory/conversation-queries.ts +1 -29
  506. package/src/memory/conversation-title-service.ts +26 -21
  507. package/src/memory/db-connection.ts +1 -8
  508. package/src/memory/db-init.ts +20 -0
  509. package/src/memory/delivery-crud.ts +4 -34
  510. package/src/memory/external-conversation-store.ts +1 -1
  511. package/src/memory/format-recall.ts +47 -0
  512. package/src/memory/guardian-action-store.ts +4 -5
  513. package/src/memory/guardian-rate-limits.ts +0 -3
  514. package/src/memory/invite-store.ts +1 -1
  515. package/src/memory/job-handlers/backfill.ts +9 -2
  516. package/src/memory/job-handlers/extraction.ts +2 -7
  517. package/src/memory/job-handlers/summarization.ts +1 -1
  518. package/src/memory/llm-usage-store.ts +11 -0
  519. package/src/memory/migrations/114-notifications.ts +12 -40
  520. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +357 -0
  521. package/src/memory/migrations/141-rename-verification-table.ts +55 -0
  522. package/src/memory/migrations/142-rename-verification-session-id-column.ts +32 -0
  523. package/src/memory/migrations/143-rename-guardian-verification-values.ts +48 -0
  524. package/src/memory/migrations/144-rename-voice-to-phone.ts +147 -0
  525. package/src/memory/migrations/index.ts +5 -0
  526. package/src/memory/migrations/registry.ts +30 -0
  527. package/src/memory/qdrant-circuit-breaker.ts +5 -0
  528. package/src/memory/retriever.test.ts +707 -0
  529. package/src/memory/retriever.ts +120 -116
  530. package/src/memory/schema/calls.ts +3 -7
  531. package/src/memory/schema/guardian.ts +2 -2
  532. package/src/memory/schema/infrastructure.ts +0 -8
  533. package/src/memory/search/lexical.ts +4 -1
  534. package/src/memory/search/query-expansion.test.ts +70 -0
  535. package/src/memory/search/query-expansion.ts +118 -0
  536. package/src/memory/search/types.ts +18 -17
  537. package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
  538. package/src/messaging/providers/whatsapp/adapter.ts +1 -4
  539. package/src/messaging/registry.ts +0 -1
  540. package/src/notifications/README.md +13 -22
  541. package/src/notifications/adapters/macos.ts +1 -1
  542. package/src/notifications/conversation-pairing.ts +2 -2
  543. package/src/notifications/copy-composer.ts +2 -2
  544. package/src/notifications/decision-engine.ts +1 -10
  545. package/src/notifications/destination-resolver.ts +2 -3
  546. package/src/notifications/emit-signal.ts +2 -8
  547. package/src/notifications/guardian-question-mode.ts +5 -8
  548. package/src/notifications/signal.ts +1 -2
  549. package/src/notifications/types.ts +1 -1
  550. package/src/oauth/token-persistence.ts +25 -1
  551. package/src/permissions/checker.ts +4 -29
  552. package/src/permissions/defaults.ts +9 -9
  553. package/src/permissions/prompter.ts +1 -1
  554. package/src/permissions/secret-prompter.ts +1 -1
  555. package/src/permissions/shell-identity.ts +1 -1
  556. package/src/permissions/trust-store.ts +13 -76
  557. package/src/permissions/workspace-policy.ts +1 -1
  558. package/src/{config → prompts}/computer-use-prompt.ts +1 -1
  559. package/src/{config → prompts}/system-prompt.ts +44 -26
  560. package/src/{config → prompts}/templates/BOOTSTRAP.md +0 -3
  561. package/src/providers/registry.ts +2 -4
  562. package/src/runtime/AGENTS.md +6 -8
  563. package/src/runtime/access-request-helper.ts +36 -55
  564. package/src/runtime/actor-trust-resolver.ts +1 -24
  565. package/src/runtime/approval-message-composer.ts +6 -2
  566. package/src/runtime/assistant-event.ts +1 -1
  567. package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
  568. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +1 -1
  569. package/src/runtime/auth/__tests__/scopes.test.ts +2 -1
  570. package/src/runtime/auth/__tests__/subject.test.ts +32 -0
  571. package/src/runtime/auth/route-policy.ts +137 -25
  572. package/src/runtime/auth/scopes.ts +1 -0
  573. package/src/runtime/auth/subject.ts +9 -0
  574. package/src/runtime/auth/token-service.ts +12 -1
  575. package/src/runtime/auth/types.ts +1 -1
  576. package/src/runtime/channel-approval-types.ts +1 -1
  577. package/src/runtime/channel-approvals.ts +1 -1
  578. package/src/runtime/channel-invite-transport.ts +0 -2
  579. package/src/runtime/channel-invite-transports/slack.ts +5 -19
  580. package/src/runtime/channel-invite-transports/telegram.ts +17 -34
  581. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  582. package/src/runtime/channel-readiness-service.ts +24 -159
  583. package/src/runtime/channel-readiness-types.ts +5 -1
  584. package/src/runtime/channel-reply-delivery.ts +43 -3
  585. package/src/runtime/channel-retry-sweep.ts +14 -22
  586. package/src/runtime/{channel-guardian-service.ts → channel-verification-service.ts} +50 -53
  587. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -3
  588. package/src/runtime/gateway-client.ts +12 -15
  589. package/src/runtime/guardian-action-followup-executor.ts +8 -73
  590. package/src/runtime/guardian-action-grant-minter.ts +45 -61
  591. package/src/runtime/guardian-action-message-composer.ts +4 -4
  592. package/src/runtime/guardian-reply-router.ts +3 -3
  593. package/src/runtime/http-server.ts +133 -24
  594. package/src/runtime/http-types.ts +44 -1
  595. package/src/runtime/invite-instruction-generator.ts +1 -3
  596. package/src/runtime/invite-redemption-service.ts +5 -5
  597. package/src/runtime/invite-service.ts +7 -7
  598. package/src/runtime/local-actor-identity.ts +28 -2
  599. package/src/runtime/local-gateway-health.ts +275 -0
  600. package/src/runtime/middleware/error-handler.ts +14 -1
  601. package/src/runtime/middleware/twilio-validation.ts +3 -3
  602. package/src/runtime/migrations/migration-transport.ts +18 -3
  603. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  604. package/src/runtime/nl-approval-parser.ts +2 -3
  605. package/src/runtime/routes/access-request-decision.ts +2 -2
  606. package/src/runtime/routes/app-management-routes.ts +918 -0
  607. package/src/runtime/routes/approval-routes.ts +76 -7
  608. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +38 -203
  609. package/src/runtime/routes/brain-graph/brain-graph.html +1845 -0
  610. package/src/runtime/routes/brain-graph-routes.ts +4 -42
  611. package/src/runtime/routes/channel-delivery-routes.ts +5 -4
  612. package/src/runtime/routes/channel-route-shared.ts +1 -3
  613. package/src/runtime/routes/channel-routes.ts +1 -4
  614. package/src/runtime/routes/channel-verification-routes.ts +257 -0
  615. package/src/runtime/routes/computer-use-routes.ts +595 -0
  616. package/src/runtime/routes/contact-routes.ts +1 -317
  617. package/src/runtime/routes/conversation-attention-routes.ts +6 -5
  618. package/src/runtime/routes/conversation-routes.ts +20 -24
  619. package/src/runtime/routes/debug-routes.ts +1 -1
  620. package/src/runtime/routes/diagnostics-routes.ts +890 -0
  621. package/src/runtime/routes/documents-routes.ts +227 -0
  622. package/src/runtime/routes/guardian-approval-interception.ts +25 -48
  623. package/src/runtime/routes/guardian-bootstrap-routes.ts +3 -3
  624. package/src/runtime/routes/guardian-expiry-sweep.ts +2 -2
  625. package/src/runtime/routes/guardian-refresh-routes.ts +11 -6
  626. package/src/runtime/routes/inbound-conversation.ts +3 -10
  627. package/src/runtime/routes/inbound-message-handler.ts +7 -6
  628. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +22 -22
  629. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +44 -0
  630. package/src/runtime/routes/inbound-stages/background-dispatch.ts +140 -22
  631. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +4 -4
  632. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
  633. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +3 -3
  634. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  635. package/src/runtime/routes/inbound-stages/verification-intercept.ts +13 -14
  636. package/src/runtime/routes/integrations/slack/channel.ts +72 -0
  637. package/src/runtime/routes/{slack-share-routes.ts → integrations/slack/share.ts} +9 -9
  638. package/src/runtime/routes/integrations/telegram.ts +111 -0
  639. package/src/runtime/routes/integrations/twilio.ts +451 -0
  640. package/src/runtime/routes/invite-routes.ts +2 -2
  641. package/src/runtime/routes/pairing-routes.ts +1 -1
  642. package/src/runtime/routes/recording-routes.ts +332 -0
  643. package/src/{daemon/handlers/config-scheduling.ts → runtime/routes/schedule-routes.ts} +91 -106
  644. package/src/runtime/routes/session-management-routes.ts +167 -0
  645. package/src/runtime/routes/session-query-routes.ts +204 -0
  646. package/src/runtime/routes/settings-routes.ts +887 -0
  647. package/src/runtime/routes/skills-routes.ts +266 -0
  648. package/src/runtime/routes/subagents-routes.ts +246 -0
  649. package/src/runtime/routes/surface-action-routes.ts +100 -10
  650. package/src/runtime/routes/surface-content-routes.ts +1 -1
  651. package/src/runtime/routes/work-items-routes.ts +809 -0
  652. package/src/runtime/routes/workspace-routes.test.ts +778 -0
  653. package/src/runtime/routes/workspace-routes.ts +410 -0
  654. package/src/runtime/routes/workspace-utils.ts +88 -0
  655. package/src/runtime/telegram-streaming-delivery.test.ts +597 -0
  656. package/src/runtime/telegram-streaming-delivery.ts +380 -0
  657. package/src/runtime/tool-grant-request-helper.ts +1 -2
  658. package/src/runtime/trust-context-resolver.ts +0 -1
  659. package/src/runtime/{guardian-outbound-actions.ts → verification-outbound-actions.ts} +23 -188
  660. package/src/runtime/verification-rate-limiter.ts +2 -2
  661. package/src/runtime/{guardian-verification-templates.ts → verification-templates.ts} +2 -28
  662. package/src/schedule/integration-status.ts +2 -2
  663. package/src/schedule/schedule-store.ts +7 -9
  664. package/src/sequence/engine.ts +1 -1
  665. package/src/skills/active-skill-tools.ts +0 -8
  666. package/src/skills/clawhub.ts +1 -10
  667. package/src/skills/managed-store.ts +14 -4
  668. package/src/skills/slash-commands.ts +1 -1
  669. package/src/subagent/manager.ts +1 -1
  670. package/src/subagent/types.ts +1 -1
  671. package/src/tasks/SPEC.md +10 -10
  672. package/src/tasks/task-scheduler.ts +1 -1
  673. package/src/telegram/bot-username.ts +13 -0
  674. package/src/tools/AGENTS.md +38 -0
  675. package/src/tools/apps/executors.ts +0 -6
  676. package/src/tools/assets/materialize.ts +1 -1
  677. package/src/tools/assets/search.ts +1 -1
  678. package/src/tools/browser/browser-execution.ts +2 -2
  679. package/src/tools/browser/browser-manager.ts +88 -11
  680. package/src/tools/browser/browser-screencast.ts +1 -1
  681. package/src/tools/browser/headless-browser.ts +0 -17
  682. package/src/tools/browser/jit-auth.ts +1 -1
  683. package/src/tools/browser/recording-store.ts +19 -1
  684. package/src/tools/browser/runtime-check.ts +4 -2
  685. package/src/tools/calls/call-start.ts +3 -3
  686. package/src/tools/credentials/metadata-store.ts +0 -13
  687. package/src/tools/credentials/vault.ts +7 -31
  688. package/src/tools/document/editor-template.ts +10 -8
  689. package/src/tools/followups/followup_create.ts +0 -8
  690. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  691. package/src/tools/memory/definitions.ts +32 -10
  692. package/src/tools/memory/handlers.test.ts +573 -0
  693. package/src/tools/memory/handlers.ts +222 -65
  694. package/src/tools/memory/register.ts +53 -24
  695. package/src/tools/network/script-proxy/session-manager.ts +1 -12
  696. package/src/tools/schedule/update.ts +0 -8
  697. package/src/tools/skills/load.ts +3 -3
  698. package/src/tools/subagent/read.ts +1 -1
  699. package/src/tools/system/voice-config.ts +2 -14
  700. package/src/tools/terminal/safe-env.ts +5 -18
  701. package/src/tools/tool-approval-handler.ts +4 -4
  702. package/src/tools/tool-manifest.ts +4 -2
  703. package/src/tools/types.ts +1 -1
  704. package/src/tools/{guardian-control-plane-policy.ts → verification-control-plane-policy.ts} +37 -39
  705. package/src/twitter/platform-proxy-client.ts +408 -0
  706. package/src/usage/types.ts +21 -0
  707. package/src/util/canonicalize-identity.ts +2 -6
  708. package/src/util/errors.ts +12 -0
  709. package/src/util/platform.ts +93 -86
  710. package/src/util/pricing.ts +180 -43
  711. package/src/work-items/work-item-runner.ts +1 -1
  712. package/scripts/ipc/check-contract-inventory.ts +0 -107
  713. package/scripts/ipc/check-swift-decoder-drift.ts +0 -184
  714. package/scripts/ipc/generate-swift.ts +0 -528
  715. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -3043
  716. package/src/__tests__/app-migration.test.ts +0 -148
  717. package/src/__tests__/config-loader-migration.test.ts +0 -85
  718. package/src/__tests__/daemon-lifecycle.test.ts +0 -715
  719. package/src/__tests__/daemon-server-session-init.test.ts +0 -864
  720. package/src/__tests__/guardian-actions-endpoint.test.ts +0 -1452
  721. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +0 -228
  722. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -397
  723. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -218
  724. package/src/__tests__/handlers-slack-config.test.ts +0 -140
  725. package/src/__tests__/handlers-telegram-config.test.ts +0 -1317
  726. package/src/__tests__/handlers-twitter-config.test.ts +0 -1145
  727. package/src/__tests__/home-base-bootstrap.test.ts +0 -86
  728. package/src/__tests__/ingress-reconcile.test.ts +0 -606
  729. package/src/__tests__/integrations-cli.test.ts +0 -232
  730. package/src/__tests__/ipc-blob-store.test.ts +0 -329
  731. package/src/__tests__/ipc-contract-inventory.test.ts +0 -69
  732. package/src/__tests__/ipc-contract.test.ts +0 -76
  733. package/src/__tests__/ipc-protocol.test.ts +0 -120
  734. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -250
  735. package/src/__tests__/ipc-snapshot.test.ts +0 -2197
  736. package/src/__tests__/ipc-validate.test.ts +0 -471
  737. package/src/__tests__/migration-cli-flows.test.ts +0 -186
  738. package/src/__tests__/migration-ordering.test.ts +0 -267
  739. package/src/__tests__/oauth-connect-handler.test.ts +0 -361
  740. package/src/__tests__/platform-move-helper.test.ts +0 -108
  741. package/src/__tests__/platform-socket-path.test.ts +0 -52
  742. package/src/__tests__/platform-workspace-migration.test.ts +0 -1051
  743. package/src/__tests__/prebuilt-home-base-seed.test.ts +0 -79
  744. package/src/__tests__/recording-intent-handler.test.ts +0 -1155
  745. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +0 -127
  746. package/src/__tests__/sms-messaging-provider.test.ts +0 -156
  747. package/src/__tests__/tool-permission-simulate-handler.test.ts +0 -367
  748. package/src/__tests__/twitter-auth-handler.test.ts +0 -561
  749. package/src/__tests__/twitter-cli-error-shaping.test.ts +0 -224
  750. package/src/__tests__/twitter-cli-routing.test.ts +0 -286
  751. package/src/__tests__/work-item-output.test.ts +0 -150
  752. package/src/amazon/session.ts +0 -58
  753. package/src/cli/channels.ts +0 -51
  754. package/src/cli/influencer.ts +0 -319
  755. package/src/cli/integrations.ts +0 -372
  756. package/src/cli/ipc-client.ts +0 -88
  757. package/src/cli/twitter.ts +0 -1111
  758. package/src/config/bundled-skills/configure-settings/SKILL.md +0 -86
  759. package/src/config/bundled-skills/doordash/lib/shared/ipc.ts +0 -32
  760. package/src/config/bundled-skills/sms-setup/SKILL.md +0 -210
  761. package/src/config/core-schema.ts +0 -434
  762. package/src/config/memory-schema.ts +0 -617
  763. package/src/daemon/auth-manager.ts +0 -106
  764. package/src/daemon/handlers/apps.ts +0 -783
  765. package/src/daemon/handlers/avatar.ts +0 -73
  766. package/src/daemon/handlers/browser.ts +0 -3
  767. package/src/daemon/handlers/computer-use.ts +0 -231
  768. package/src/daemon/handlers/config-dispatch.ts +0 -29
  769. package/src/daemon/handlers/config-heartbeat.ts +0 -299
  770. package/src/daemon/handlers/config-inbox.ts +0 -457
  771. package/src/daemon/handlers/config-integrations.ts +0 -409
  772. package/src/daemon/handlers/config-platform.ts +0 -77
  773. package/src/daemon/handlers/config-slack.ts +0 -41
  774. package/src/daemon/handlers/config-tools.ts +0 -226
  775. package/src/daemon/handlers/config-trust.ts +0 -135
  776. package/src/daemon/handlers/config.ts +0 -64
  777. package/src/daemon/handlers/contacts.ts +0 -193
  778. package/src/daemon/handlers/diagnostics.ts +0 -382
  779. package/src/daemon/handlers/documents.ts +0 -188
  780. package/src/daemon/handlers/guardian-actions.ts +0 -82
  781. package/src/daemon/handlers/home-base.ts +0 -82
  782. package/src/daemon/handlers/index.ts +0 -222
  783. package/src/daemon/handlers/misc.ts +0 -1139
  784. package/src/daemon/handlers/navigate-settings.ts +0 -29
  785. package/src/daemon/handlers/oauth-connect.ts +0 -202
  786. package/src/daemon/handlers/open-bundle-handler.ts +0 -88
  787. package/src/daemon/handlers/publish.ts +0 -176
  788. package/src/daemon/handlers/signing.ts +0 -56
  789. package/src/daemon/handlers/subagents.ts +0 -286
  790. package/src/daemon/handlers/twitter-auth.ts +0 -220
  791. package/src/daemon/handlers/work-items.ts +0 -796
  792. package/src/daemon/handlers/workspace-files.ts +0 -84
  793. package/src/daemon/handlers.ts +0 -16
  794. package/src/daemon/ipc-blob-store.ts +0 -246
  795. package/src/daemon/ipc-contract-inventory.json +0 -348
  796. package/src/daemon/ipc-contract-inventory.ts +0 -202
  797. package/src/daemon/ipc-handler.ts +0 -120
  798. package/src/daemon/ipc-protocol.ts +0 -85
  799. package/src/daemon/ipc-validate.ts +0 -254
  800. package/src/home-base/app-link-store.ts +0 -78
  801. package/src/home-base/bootstrap.ts +0 -74
  802. package/src/home-base/prebuilt/brain-graph.html +0 -1483
  803. package/src/home-base/prebuilt/index.html +0 -702
  804. package/src/home-base/prebuilt/seed-metadata.json +0 -21
  805. package/src/home-base/prebuilt/seed.ts +0 -122
  806. package/src/home-base/prebuilt-home-base-updater.ts +0 -36
  807. package/src/memory/app-migration.ts +0 -114
  808. package/src/memory/channel-delivery-store.ts +0 -40
  809. package/src/memory/channel-guardian-store.ts +0 -83
  810. package/src/memory/conversation-store.ts +0 -102
  811. package/src/memory/schema-migration.ts +0 -38
  812. package/src/messaging/providers/sms/adapter.ts +0 -232
  813. package/src/messaging/providers/sms/client.ts +0 -93
  814. package/src/messaging/providers/sms/types.ts +0 -7
  815. package/src/migrations/config-merge.ts +0 -62
  816. package/src/migrations/data-layout.ts +0 -89
  817. package/src/migrations/data-merge.ts +0 -44
  818. package/src/migrations/hooks-merge.ts +0 -118
  819. package/src/migrations/index.ts +0 -6
  820. package/src/migrations/log.ts +0 -28
  821. package/src/migrations/skills-merge.ts +0 -44
  822. package/src/migrations/workspace-layout.ts +0 -94
  823. package/src/notifications/adapters/sms.ts +0 -94
  824. package/src/runtime/channel-approval-parser.ts +0 -123
  825. package/src/runtime/channel-invite-transports/sms.ts +0 -53
  826. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +0 -82
  827. package/src/runtime/routes/integration-routes.ts +0 -381
  828. package/src/runtime/routes/twilio-routes.ts +0 -1251
  829. package/src/twitter/client.ts +0 -979
  830. package/src/twitter/router.ts +0 -131
  831. package/src/twitter/session.ts +0 -54
  832. package/src/util/cookie-session.ts +0 -114
  833. package/src/watcher/providers/slack.ts +0 -282
  834. /package/src/{amazon → cli/commands/amazon}/cart.ts +0 -0
  835. /package/src/{amazon → cli/commands/amazon}/checkout.ts +0 -0
  836. /package/src/{amazon → cli/commands/amazon}/product-details.ts +0 -0
  837. /package/src/{amazon → cli/commands/amazon}/search.ts +0 -0
  838. /package/src/config/{calls-schema.ts → schemas/calls.ts} +0 -0
  839. /package/src/config/{elevenlabs-schema.ts → schemas/elevenlabs.ts} +0 -0
  840. /package/src/config/{mcp-schema.ts → schemas/mcp.ts} +0 -0
  841. /package/src/config/{notifications-schema.ts → schemas/notifications.ts} +0 -0
  842. /package/src/config/{sandbox-schema.ts → schemas/sandbox.ts} +0 -0
  843. /package/src/config/{skills-schema.ts → schemas/skills.ts} +0 -0
  844. /package/src/daemon/{ipc-contract → message-types}/browser.ts +0 -0
  845. /package/src/daemon/{ipc-contract → message-types}/contacts.ts +0 -0
  846. /package/src/daemon/{ipc-contract → message-types}/documents.ts +0 -0
  847. /package/src/daemon/{ipc-contract → message-types}/guardian-actions.ts +0 -0
  848. /package/src/daemon/{ipc-contract → message-types}/inbox.ts +0 -0
  849. /package/src/daemon/{ipc-contract → message-types}/messages.ts +0 -0
  850. /package/src/daemon/{ipc-contract → message-types}/pairing.ts +0 -0
  851. /package/src/daemon/{ipc-contract → message-types}/schedules.ts +0 -0
  852. /package/src/daemon/{ipc-contract → message-types}/settings.ts +0 -0
  853. /package/src/daemon/{ipc-contract → message-types}/skills.ts +0 -0
  854. /package/src/daemon/{ipc-contract → message-types}/subagents.ts +0 -0
  855. /package/src/daemon/{ipc-contract → message-types}/trust.ts +0 -0
  856. /package/src/daemon/{ipc-contract → message-types}/work-items.ts +0 -0
  857. /package/src/{cli/email-guardrails.ts → email/guardrails.ts} +0 -0
  858. /package/src/{config → prompts}/__tests__/build-cli-reference-section.test.ts +0 -0
  859. /package/src/{config → prompts}/templates/IDENTITY.md +0 -0
  860. /package/src/{config → prompts}/templates/SOUL.md +0 -0
  861. /package/src/{config → prompts}/templates/UPDATES.md +0 -0
  862. /package/src/{config → prompts}/templates/USER.md +0 -0
  863. /package/src/{config → prompts}/update-bulletin-format.ts +0 -0
  864. /package/src/{config → prompts}/update-bulletin-state.ts +0 -0
  865. /package/src/{config → prompts}/update-bulletin-template-path.ts +0 -0
  866. /package/src/{config → prompts}/update-bulletin.ts +0 -0
  867. /package/src/{config → prompts}/user-reference.ts +0 -0
@@ -1,4 +1,3 @@
1
- import * as net from "node:net";
2
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
3
2
 
4
3
  // ─── Mocks (must be before any imports that depend on them) ─────────────────
@@ -53,7 +52,7 @@ mock.module("../config/loader.js", () => ({
53
52
  const mockMessages: Array<{ id: string; role: string; content: string }> = [];
54
53
  let mockMessageIdCounter = 0;
55
54
 
56
- mock.module("../memory/conversation-store.js", () => ({
55
+ mock.module("../memory/conversation-crud.js", () => ({
57
56
  getConversationThreadType: () => "default",
58
57
  setConversationOriginChannelIfUnset: () => {},
59
58
  updateConversationContextWindow: () => {},
@@ -135,7 +134,7 @@ import {
135
134
  recordingHandlers,
136
135
  } from "../daemon/handlers/recording.js";
137
136
  import type { HandlerContext } from "../daemon/handlers/shared.js";
138
- import type { RecordingStatus } from "../daemon/ipc-contract/computer-use.js";
137
+ import type { RecordingStatus } from "../daemon/message-types/computer-use.js";
139
138
  import { executeRecordingIntent } from "../daemon/recording-executor.js";
140
139
  import { DebouncerMap } from "../util/debounce.js";
141
140
 
@@ -147,28 +146,24 @@ const ALLOWED_RECORDINGS_DIR = `${process.env.HOME}/Library/Application Support/
147
146
  function createCtx(): {
148
147
  ctx: HandlerContext;
149
148
  sent: Array<{ type: string; [k: string]: unknown }>;
150
- fakeSocket: net.Socket;
151
149
  } {
152
150
  const sent: Array<{ type: string; [k: string]: unknown }> = [];
153
- const fakeSocket = {} as net.Socket;
154
- const socketToSession = new Map<net.Socket, string>();
155
151
 
156
152
  const ctx: HandlerContext = {
157
153
  sessions: new Map(),
158
- socketToSession,
159
154
  cuSessions: new Map(),
160
- socketToCuSession: new Map(),
161
155
  cuObservationParseSequence: new Map(),
162
- socketSandboxOverride: new Map(),
163
156
  sharedRequestTimestamps: [],
164
157
  debounceTimers: new DebouncerMap({ defaultDelayMs: 200 }),
165
158
  suppressConfigReload: false,
166
159
  setSuppressConfigReload: noop,
167
160
  updateConfigFingerprint: noop,
168
- send: (_socket, msg) => {
161
+ send: (msg) => {
162
+ sent.push(msg as { type: string; [k: string]: unknown });
163
+ },
164
+ broadcast: (msg) => {
169
165
  sent.push(msg as { type: string; [k: string]: unknown });
170
166
  },
171
- broadcast: noop,
172
167
  clearAllSessions: () => 0,
173
168
  getOrCreateSession: () => {
174
169
  throw new Error("not implemented");
@@ -176,7 +171,7 @@ function createCtx(): {
176
171
  touchSession: noop,
177
172
  };
178
173
 
179
- return { ctx, sent, fakeSocket };
174
+ return { ctx, sent };
180
175
  }
181
176
 
182
177
  // ─── Restart state machine tests ────────────────────────────────────────────
@@ -189,21 +184,19 @@ describe("handleRecordingRestart", () => {
189
184
  });
190
185
 
191
186
  test("sends recording_stop and defers start until stop-ack", () => {
192
- const { ctx, sent, fakeSocket } = createCtx();
187
+ const { ctx, sent } = createCtx();
193
188
  const conversationId = "conv-restart-1";
194
- ctx.socketToSession.set(fakeSocket, conversationId);
195
189
 
196
190
  // Start a recording first
197
191
  const originalId = handleRecordingStart(
198
192
  conversationId,
199
193
  undefined,
200
- fakeSocket,
201
194
  ctx,
202
195
  );
203
196
  expect(originalId).not.toBeNull();
204
197
  sent.length = 0;
205
198
 
206
- const result = handleRecordingRestart(conversationId, fakeSocket, ctx);
199
+ const result = handleRecordingRestart(conversationId, ctx);
207
200
 
208
201
  expect(result.initiated).toBe(true);
209
202
  expect(result.operationToken).toBeTruthy();
@@ -222,7 +215,7 @@ describe("handleRecordingRestart", () => {
222
215
  status: "stopped",
223
216
  attachToConversationId: conversationId,
224
217
  };
225
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
218
+ recordingHandlers.recording_status(stoppedStatus, ctx);
226
219
 
227
220
  // NOW the deferred recording_start should have been sent
228
221
  const startMsgsAfterAck = sent.filter((m) => m.type === "recording_start");
@@ -231,9 +224,9 @@ describe("handleRecordingRestart", () => {
231
224
  });
232
225
 
233
226
  test('returns "no active recording" with reason when nothing is recording', () => {
234
- const { ctx, fakeSocket } = createCtx();
227
+ const { ctx } = createCtx();
235
228
 
236
- const result = handleRecordingRestart("conv-no-rec", fakeSocket, ctx);
229
+ const result = handleRecordingRestart("conv-no-rec", ctx);
237
230
 
238
231
  expect(result.initiated).toBe(false);
239
232
  expect(result.reason).toBe("no_active_recording");
@@ -241,18 +234,16 @@ describe("handleRecordingRestart", () => {
241
234
  });
242
235
 
243
236
  test("generates unique operation token for each restart", () => {
244
- const { ctx, sent, fakeSocket } = createCtx();
237
+ const { ctx, sent } = createCtx();
245
238
  const conversationId = "conv-restart-unique";
246
- ctx.socketToSession.set(fakeSocket, conversationId);
247
239
 
248
240
  // First restart cycle
249
241
  const originalId = handleRecordingStart(
250
242
  conversationId,
251
243
  undefined,
252
- fakeSocket,
253
244
  ctx,
254
245
  );
255
- const result1 = handleRecordingRestart(conversationId, fakeSocket, ctx);
246
+ const result1 = handleRecordingRestart(conversationId, ctx);
256
247
 
257
248
  // Simulate the stop-ack to trigger the deferred start
258
249
  const stoppedStatus1: RecordingStatus = {
@@ -261,7 +252,7 @@ describe("handleRecordingRestart", () => {
261
252
  status: "stopped",
262
253
  attachToConversationId: conversationId,
263
254
  };
264
- recordingHandlers.recording_status(stoppedStatus1, fakeSocket, ctx);
255
+ recordingHandlers.recording_status(stoppedStatus1, ctx);
265
256
 
266
257
  // Simulate the first restart completing (started status)
267
258
  const startMsg1 = sent.filter((m) => m.type === "recording_start").pop();
@@ -271,11 +262,11 @@ describe("handleRecordingRestart", () => {
271
262
  status: "started",
272
263
  operationToken: result1.operationToken,
273
264
  };
274
- recordingHandlers.recording_status(status1, fakeSocket, ctx);
265
+ recordingHandlers.recording_status(status1, ctx);
275
266
 
276
267
  // Second restart cycle
277
268
  sent.length = 0;
278
- const result2 = handleRecordingRestart(conversationId, fakeSocket, ctx);
269
+ const result2 = handleRecordingRestart(conversationId, ctx);
279
270
 
280
271
  expect(result1.operationToken).not.toBe(result2.operationToken);
281
272
  });
@@ -291,20 +282,17 @@ describe("restart_cancelled status", () => {
291
282
  });
292
283
 
293
284
  test('emits restart_cancelled response, never "new recording started"', () => {
294
- const { ctx, sent, fakeSocket } = createCtx();
285
+ const { ctx, sent } = createCtx();
295
286
  const conversationId = "conv-cancel-1";
296
- ctx.socketToSession.set(fakeSocket, conversationId);
297
287
 
298
288
  // Start -> restart
299
289
  const originalId = handleRecordingStart(
300
290
  conversationId,
301
291
  undefined,
302
- fakeSocket,
303
292
  ctx,
304
293
  );
305
294
  const restartResult = handleRecordingRestart(
306
295
  conversationId,
307
- fakeSocket,
308
296
  ctx,
309
297
  );
310
298
  expect(restartResult.initiated).toBe(true);
@@ -316,7 +304,7 @@ describe("restart_cancelled status", () => {
316
304
  status: "stopped",
317
305
  attachToConversationId: conversationId,
318
306
  };
319
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
307
+ recordingHandlers.recording_status(stoppedStatus, ctx);
320
308
 
321
309
  // Get the new recording ID from the deferred recording_start message
322
310
  const startMsg = sent.filter((m) => m.type === "recording_start").pop();
@@ -330,7 +318,7 @@ describe("restart_cancelled status", () => {
330
318
  attachToConversationId: conversationId,
331
319
  operationToken: restartResult.operationToken,
332
320
  };
333
- recordingHandlers.recording_status(cancelStatus, fakeSocket, ctx);
321
+ recordingHandlers.recording_status(cancelStatus, ctx);
334
322
 
335
323
  // Should have emitted the cancellation message
336
324
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -351,19 +339,16 @@ describe("restart_cancelled status", () => {
351
339
  });
352
340
 
353
341
  test("cleans up restart state on cancel", () => {
354
- const { ctx, sent, fakeSocket } = createCtx();
342
+ const { ctx, sent } = createCtx();
355
343
  const conversationId = "conv-cancel-cleanup";
356
- ctx.socketToSession.set(fakeSocket, conversationId);
357
344
 
358
345
  const originalId = handleRecordingStart(
359
346
  conversationId,
360
347
  undefined,
361
- fakeSocket,
362
348
  ctx,
363
349
  );
364
350
  const restartResult = handleRecordingRestart(
365
351
  conversationId,
366
- fakeSocket,
367
352
  ctx,
368
353
  );
369
354
 
@@ -377,7 +362,7 @@ describe("restart_cancelled status", () => {
377
362
  status: "stopped",
378
363
  attachToConversationId: conversationId,
379
364
  };
380
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
365
+ recordingHandlers.recording_status(stoppedStatus, ctx);
381
366
 
382
367
  // Still not idle — the new recording has started
383
368
  expect(isRecordingIdle()).toBe(false);
@@ -390,7 +375,7 @@ describe("restart_cancelled status", () => {
390
375
  attachToConversationId: conversationId,
391
376
  operationToken: restartResult.operationToken,
392
377
  };
393
- recordingHandlers.recording_status(cancelStatus, fakeSocket, ctx);
378
+ recordingHandlers.recording_status(cancelStatus, ctx);
394
379
 
395
380
  // After cancel: truly idle
396
381
  expect(isRecordingIdle()).toBe(true);
@@ -408,20 +393,17 @@ describe("stale completion guard (operation token)", () => {
408
393
  });
409
394
 
410
395
  test("rejects recording_status with stale operation token", () => {
411
- const { ctx, sent, fakeSocket } = createCtx();
396
+ const { ctx, sent } = createCtx();
412
397
  const conversationId = "conv-stale-1";
413
- ctx.socketToSession.set(fakeSocket, conversationId);
414
398
 
415
399
  // Start recording -> restart (creates operation token)
416
400
  const originalId = handleRecordingStart(
417
401
  conversationId,
418
402
  undefined,
419
- fakeSocket,
420
403
  ctx,
421
404
  );
422
405
  const restartResult = handleRecordingRestart(
423
406
  conversationId,
424
- fakeSocket,
425
407
  ctx,
426
408
  );
427
409
  expect(restartResult.initiated).toBe(true);
@@ -433,7 +415,7 @@ describe("stale completion guard (operation token)", () => {
433
415
  status: "stopped",
434
416
  attachToConversationId: conversationId,
435
417
  };
436
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
418
+ recordingHandlers.recording_status(stoppedStatus, ctx);
437
419
 
438
420
  const startMsg = sent.filter((m) => m.type === "recording_start").pop();
439
421
  sent.length = 0;
@@ -445,7 +427,7 @@ describe("stale completion guard (operation token)", () => {
445
427
  status: "started",
446
428
  operationToken: "old-stale-token-from-previous-cycle",
447
429
  };
448
- recordingHandlers.recording_status(staleStatus, fakeSocket, ctx);
430
+ recordingHandlers.recording_status(staleStatus, ctx);
449
431
 
450
432
  // Should have been rejected — no "started" confirmation messages
451
433
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -456,19 +438,16 @@ describe("stale completion guard (operation token)", () => {
456
438
  });
457
439
 
458
440
  test("accepts recording_status with matching operation token", () => {
459
- const { ctx, sent, fakeSocket } = createCtx();
441
+ const { ctx, sent } = createCtx();
460
442
  const conversationId = "conv-matching-1";
461
- ctx.socketToSession.set(fakeSocket, conversationId);
462
443
 
463
444
  const originalId = handleRecordingStart(
464
445
  conversationId,
465
446
  undefined,
466
- fakeSocket,
467
447
  ctx,
468
448
  );
469
449
  const restartResult = handleRecordingRestart(
470
450
  conversationId,
471
- fakeSocket,
472
451
  ctx,
473
452
  );
474
453
 
@@ -479,7 +458,7 @@ describe("stale completion guard (operation token)", () => {
479
458
  status: "stopped",
480
459
  attachToConversationId: conversationId,
481
460
  };
482
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
461
+ recordingHandlers.recording_status(stoppedStatus, ctx);
483
462
 
484
463
  const startMsg = sent.filter((m) => m.type === "recording_start").pop();
485
464
 
@@ -490,22 +469,20 @@ describe("stale completion guard (operation token)", () => {
490
469
  status: "started",
491
470
  operationToken: restartResult.operationToken,
492
471
  };
493
- recordingHandlers.recording_status(validStatus, fakeSocket, ctx);
472
+ recordingHandlers.recording_status(validStatus, ctx);
494
473
 
495
474
  // Should have been accepted — restart token cleared
496
475
  expect(getActiveRestartToken()).toBeNull();
497
476
  });
498
477
 
499
478
  test("allows tokenless recording_status during active restart (old recording ack)", async () => {
500
- const { ctx, sent, fakeSocket } = createCtx();
479
+ const { ctx, sent } = createCtx();
501
480
  const conversationId = "conv-tokenless-1";
502
- ctx.socketToSession.set(fakeSocket, conversationId);
503
481
 
504
482
  // Start recording -> restart (creates operation token)
505
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
483
+ handleRecordingStart(conversationId, undefined, ctx);
506
484
  const restartResult = handleRecordingRestart(
507
485
  conversationId,
508
- fakeSocket,
509
486
  ctx,
510
487
  );
511
488
  expect(restartResult.initiated).toBe(true);
@@ -525,7 +502,7 @@ describe("stale completion guard (operation token)", () => {
525
502
  attachToConversationId: conversationId,
526
503
  // No operationToken — from old recording, should be allowed
527
504
  };
528
- await recordingHandlers.recording_status(tokenlessStatus, fakeSocket, ctx);
505
+ await recordingHandlers.recording_status(tokenlessStatus, ctx);
529
506
 
530
507
  // Should have triggered the deferred restart start
531
508
  const newStartMsgs = sent.filter((m) => m.type === "recording_start");
@@ -539,21 +516,18 @@ describe("stale completion guard (operation token)", () => {
539
516
  });
540
517
 
541
518
  test("no ghost state after restart stop/start handoff", () => {
542
- const { ctx, sent, fakeSocket } = createCtx();
519
+ const { ctx, sent } = createCtx();
543
520
  const conversationId = "conv-ghost-1";
544
- ctx.socketToSession.set(fakeSocket, conversationId);
545
521
 
546
522
  const originalId = handleRecordingStart(
547
523
  conversationId,
548
524
  undefined,
549
- fakeSocket,
550
525
  ctx,
551
526
  );
552
527
 
553
528
  // Restart sends stop and defers start until stop-ack
554
529
  const restartResult = handleRecordingRestart(
555
530
  conversationId,
556
- fakeSocket,
557
531
  ctx,
558
532
  );
559
533
  expect(restartResult.initiated).toBe(true);
@@ -565,7 +539,7 @@ describe("stale completion guard (operation token)", () => {
565
539
  status: "stopped",
566
540
  attachToConversationId: conversationId,
567
541
  };
568
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
542
+ recordingHandlers.recording_status(stoppedStatus, ctx);
569
543
 
570
544
  // The new recording should be active (not the old one)
571
545
  const startMsgs = sent.filter((m) => m.type === "recording_start");
@@ -585,14 +559,12 @@ describe("handleRecordingPause", () => {
585
559
  });
586
560
 
587
561
  test("sends recording_pause for active recording", () => {
588
- const { ctx, sent, fakeSocket } = createCtx();
562
+ const { ctx, sent } = createCtx();
589
563
  const conversationId = "conv-pause-1";
590
- ctx.socketToSession.set(fakeSocket, conversationId);
591
564
 
592
565
  const recordingId = handleRecordingStart(
593
566
  conversationId,
594
567
  undefined,
595
- fakeSocket,
596
568
  ctx,
597
569
  );
598
570
  expect(recordingId).not.toBeNull();
@@ -614,11 +586,10 @@ describe("handleRecordingPause", () => {
614
586
  });
615
587
 
616
588
  test("resolves to globally active recording from different conversation", () => {
617
- const { ctx, sent, fakeSocket } = createCtx();
589
+ const { ctx, sent } = createCtx();
618
590
  const convA = "conv-owner-pause";
619
- ctx.socketToSession.set(fakeSocket, convA);
620
591
 
621
- const recordingId = handleRecordingStart(convA, undefined, fakeSocket, ctx);
592
+ const recordingId = handleRecordingStart(convA, undefined, ctx);
622
593
  sent.length = 0;
623
594
 
624
595
  const result = handleRecordingPause("conv-other-pause", ctx);
@@ -632,14 +603,12 @@ describe("handleRecordingResume", () => {
632
603
  });
633
604
 
634
605
  test("sends recording_resume for active recording", () => {
635
- const { ctx, sent, fakeSocket } = createCtx();
606
+ const { ctx, sent } = createCtx();
636
607
  const conversationId = "conv-resume-1";
637
- ctx.socketToSession.set(fakeSocket, conversationId);
638
608
 
639
609
  const recordingId = handleRecordingStart(
640
610
  conversationId,
641
611
  undefined,
642
- fakeSocket,
643
612
  ctx,
644
613
  );
645
614
  expect(recordingId).not.toBeNull();
@@ -673,18 +642,17 @@ describe("isRecordingIdle", () => {
673
642
  });
674
643
 
675
644
  test("returns false when recording is active", () => {
676
- const { ctx, fakeSocket } = createCtx();
677
- handleRecordingStart("conv-idle-1", undefined, fakeSocket, ctx);
645
+ const { ctx } = createCtx();
646
+ handleRecordingStart("conv-idle-1", undefined, ctx);
678
647
  expect(isRecordingIdle()).toBe(false);
679
648
  });
680
649
 
681
650
  test("returns false when mid-restart (between stop-ack and start confirmation)", () => {
682
- const { ctx, fakeSocket } = createCtx();
651
+ const { ctx } = createCtx();
683
652
  const conversationId = "conv-idle-restart";
684
- ctx.socketToSession.set(fakeSocket, conversationId);
685
653
 
686
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
687
- handleRecordingRestart(conversationId, fakeSocket, ctx);
654
+ handleRecordingStart(conversationId, undefined, ctx);
655
+ handleRecordingRestart(conversationId, ctx);
688
656
 
689
657
  // Mid-restart: the old recording maps are still present AND there's a
690
658
  // pending restart, so the system is not idle
@@ -692,19 +660,16 @@ describe("isRecordingIdle", () => {
692
660
  });
693
661
 
694
662
  test("returns true after restart completes", () => {
695
- const { ctx, sent, fakeSocket } = createCtx();
663
+ const { ctx, sent } = createCtx();
696
664
  const conversationId = "conv-idle-complete";
697
- ctx.socketToSession.set(fakeSocket, conversationId);
698
665
 
699
666
  const originalId = handleRecordingStart(
700
667
  conversationId,
701
668
  undefined,
702
- fakeSocket,
703
669
  ctx,
704
670
  );
705
671
  const restartResult = handleRecordingRestart(
706
672
  conversationId,
707
- fakeSocket,
708
673
  ctx,
709
674
  );
710
675
 
@@ -715,7 +680,7 @@ describe("isRecordingIdle", () => {
715
680
  status: "stopped",
716
681
  attachToConversationId: conversationId,
717
682
  };
718
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
683
+ recordingHandlers.recording_status(stoppedStatus, ctx);
719
684
 
720
685
  // Simulate the new recording starting
721
686
  const startMsg = sent.filter((m) => m.type === "recording_start").pop();
@@ -725,7 +690,7 @@ describe("isRecordingIdle", () => {
725
690
  status: "started",
726
691
  operationToken: restartResult.operationToken,
727
692
  };
728
- recordingHandlers.recording_status(startedStatus, fakeSocket, ctx);
693
+ recordingHandlers.recording_status(startedStatus, ctx);
729
694
 
730
695
  // Restart is complete, but recording is still active
731
696
  expect(getActiveRestartToken()).toBeNull();
@@ -742,22 +707,20 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
742
707
  });
743
708
 
744
709
  test("restart_only executes actual restart (deferred start)", () => {
745
- const { ctx, sent, fakeSocket } = createCtx();
710
+ const { ctx, sent } = createCtx();
746
711
  const conversationId = "conv-exec-restart";
747
- ctx.socketToSession.set(fakeSocket, conversationId);
748
712
 
749
713
  // Start a recording first
750
714
  const originalId = handleRecordingStart(
751
715
  conversationId,
752
716
  undefined,
753
- fakeSocket,
754
717
  ctx,
755
718
  );
756
719
  sent.length = 0;
757
720
 
758
721
  const result = executeRecordingIntent(
759
722
  { kind: "restart_only" },
760
- { conversationId, socket: fakeSocket, ctx },
723
+ { conversationId, ctx },
761
724
  );
762
725
 
763
726
  expect(result.handled).toBe(true);
@@ -776,7 +739,7 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
776
739
  status: "stopped",
777
740
  attachToConversationId: conversationId,
778
741
  };
779
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
742
+ recordingHandlers.recording_status(stoppedStatus, ctx);
780
743
 
781
744
  // NOW the deferred start should have been sent
782
745
  const startMsgsAfterAck = sent.filter((m) => m.type === "recording_start");
@@ -784,11 +747,11 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
784
747
  });
785
748
 
786
749
  test('restart_only returns "no active recording" when idle', () => {
787
- const { ctx, fakeSocket } = createCtx();
750
+ const { ctx } = createCtx();
788
751
 
789
752
  const result = executeRecordingIntent(
790
753
  { kind: "restart_only" },
791
- { conversationId: "conv-no-rec", socket: fakeSocket, ctx },
754
+ { conversationId: "conv-no-rec", ctx },
792
755
  );
793
756
 
794
757
  expect(result.handled).toBe(true);
@@ -796,11 +759,11 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
796
759
  });
797
760
 
798
761
  test("restart_with_remainder returns deferred restart", () => {
799
- const { ctx, fakeSocket } = createCtx();
762
+ const { ctx } = createCtx();
800
763
 
801
764
  const result = executeRecordingIntent(
802
765
  { kind: "restart_with_remainder", remainder: "do something else" },
803
- { conversationId: "conv-rem", socket: fakeSocket, ctx },
766
+ { conversationId: "conv-rem", ctx },
804
767
  );
805
768
 
806
769
  expect(result.handled).toBe(false);
@@ -809,16 +772,15 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
809
772
  });
810
773
 
811
774
  test("pause_only executes actual pause", () => {
812
- const { ctx, sent, fakeSocket } = createCtx();
775
+ const { ctx, sent } = createCtx();
813
776
  const conversationId = "conv-exec-pause";
814
- ctx.socketToSession.set(fakeSocket, conversationId);
815
777
 
816
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
778
+ handleRecordingStart(conversationId, undefined, ctx);
817
779
  sent.length = 0;
818
780
 
819
781
  const result = executeRecordingIntent(
820
782
  { kind: "pause_only" },
821
- { conversationId, socket: fakeSocket, ctx },
783
+ { conversationId, ctx },
822
784
  );
823
785
 
824
786
  expect(result.handled).toBe(true);
@@ -829,11 +791,11 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
829
791
  });
830
792
 
831
793
  test('pause_only returns "no active recording" when idle', () => {
832
- const { ctx, fakeSocket } = createCtx();
794
+ const { ctx } = createCtx();
833
795
 
834
796
  const result = executeRecordingIntent(
835
797
  { kind: "pause_only" },
836
- { conversationId: "conv-no-rec", socket: fakeSocket, ctx },
798
+ { conversationId: "conv-no-rec", ctx },
837
799
  );
838
800
 
839
801
  expect(result.handled).toBe(true);
@@ -841,16 +803,15 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
841
803
  });
842
804
 
843
805
  test("resume_only executes actual resume", () => {
844
- const { ctx, sent, fakeSocket } = createCtx();
806
+ const { ctx, sent } = createCtx();
845
807
  const conversationId = "conv-exec-resume";
846
- ctx.socketToSession.set(fakeSocket, conversationId);
847
808
 
848
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
809
+ handleRecordingStart(conversationId, undefined, ctx);
849
810
  sent.length = 0;
850
811
 
851
812
  const result = executeRecordingIntent(
852
813
  { kind: "resume_only" },
853
- { conversationId, socket: fakeSocket, ctx },
814
+ { conversationId, ctx },
854
815
  );
855
816
 
856
817
  expect(result.handled).toBe(true);
@@ -861,11 +822,11 @@ describe("executeRecordingIntent — restart/pause/resume", () => {
861
822
  });
862
823
 
863
824
  test('resume_only returns "no active recording" when idle', () => {
864
- const { ctx, fakeSocket } = createCtx();
825
+ const { ctx } = createCtx();
865
826
 
866
827
  const result = executeRecordingIntent(
867
828
  { kind: "resume_only" },
868
- { conversationId: "conv-no-rec", socket: fakeSocket, ctx },
829
+ { conversationId: "conv-no-rec", ctx },
869
830
  );
870
831
 
871
832
  expect(result.handled).toBe(true);
@@ -881,13 +842,12 @@ describe("recording_status paused/resumed", () => {
881
842
  });
882
843
 
883
844
  test("handles paused status without error", () => {
884
- const { ctx, fakeSocket } = createCtx();
845
+ const { ctx } = createCtx();
885
846
  const conversationId = "conv-status-paused";
886
847
 
887
848
  const recordingId = handleRecordingStart(
888
849
  conversationId,
889
850
  undefined,
890
- fakeSocket,
891
851
  ctx,
892
852
  );
893
853
  expect(recordingId).not.toBeNull();
@@ -899,18 +859,17 @@ describe("recording_status paused/resumed", () => {
899
859
  };
900
860
 
901
861
  expect(() => {
902
- recordingHandlers.recording_status(statusMsg, fakeSocket, ctx);
862
+ recordingHandlers.recording_status(statusMsg, ctx);
903
863
  }).not.toThrow();
904
864
  });
905
865
 
906
866
  test("handles resumed status without error", () => {
907
- const { ctx, fakeSocket } = createCtx();
867
+ const { ctx } = createCtx();
908
868
  const conversationId = "conv-status-resumed";
909
869
 
910
870
  const recordingId = handleRecordingStart(
911
871
  conversationId,
912
872
  undefined,
913
- fakeSocket,
914
873
  ctx,
915
874
  );
916
875
  expect(recordingId).not.toBeNull();
@@ -922,7 +881,7 @@ describe("recording_status paused/resumed", () => {
922
881
  };
923
882
 
924
883
  expect(() => {
925
- recordingHandlers.recording_status(statusMsg, fakeSocket, ctx);
884
+ recordingHandlers.recording_status(statusMsg, ctx);
926
885
  }).not.toThrow();
927
886
  });
928
887
  });
@@ -937,17 +896,15 @@ describe("failure during restart", () => {
937
896
  });
938
897
 
939
898
  test("failed status during restart clears pending restart state (old recording fails)", () => {
940
- const { ctx, sent, fakeSocket } = createCtx();
899
+ const { ctx, sent } = createCtx();
941
900
  const conversationId = "conv-fail-restart";
942
- ctx.socketToSession.set(fakeSocket, conversationId);
943
901
 
944
902
  const originalId = handleRecordingStart(
945
903
  conversationId,
946
904
  undefined,
947
- fakeSocket,
948
905
  ctx,
949
906
  );
950
- handleRecordingRestart(conversationId, fakeSocket, ctx);
907
+ handleRecordingRestart(conversationId, ctx);
951
908
  sent.length = 0;
952
909
 
953
910
  // Simulate the old recording failing to stop (before stop-ack)
@@ -958,7 +915,7 @@ describe("failure during restart", () => {
958
915
  error: "Permission denied",
959
916
  attachToConversationId: conversationId,
960
917
  };
961
- recordingHandlers.recording_status(failedStatus, fakeSocket, ctx);
918
+ recordingHandlers.recording_status(failedStatus, ctx);
962
919
 
963
920
  // Restart state and deferred restart should be cleaned up
964
921
  expect(getActiveRestartToken()).toBeNull();
@@ -966,19 +923,16 @@ describe("failure during restart", () => {
966
923
  });
967
924
 
968
925
  test("failed status during restart clears state (new recording fails after deferred start)", () => {
969
- const { ctx, sent, fakeSocket } = createCtx();
926
+ const { ctx, sent } = createCtx();
970
927
  const conversationId = "conv-fail-restart-new";
971
- ctx.socketToSession.set(fakeSocket, conversationId);
972
928
 
973
929
  const originalId = handleRecordingStart(
974
930
  conversationId,
975
931
  undefined,
976
- fakeSocket,
977
932
  ctx,
978
933
  );
979
934
  const restartResult = handleRecordingRestart(
980
935
  conversationId,
981
- fakeSocket,
982
936
  ctx,
983
937
  );
984
938
 
@@ -989,7 +943,7 @@ describe("failure during restart", () => {
989
943
  status: "stopped",
990
944
  attachToConversationId: conversationId,
991
945
  };
992
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
946
+ recordingHandlers.recording_status(stoppedStatus, ctx);
993
947
 
994
948
  const startMsg = sent.filter((m) => m.type === "recording_start").pop();
995
949
  sent.length = 0;
@@ -1003,7 +957,7 @@ describe("failure during restart", () => {
1003
957
  attachToConversationId: conversationId,
1004
958
  operationToken: restartResult.operationToken,
1005
959
  };
1006
- recordingHandlers.recording_status(failedStatus, fakeSocket, ctx);
960
+ recordingHandlers.recording_status(failedStatus, ctx);
1007
961
 
1008
962
  // Restart state should be cleaned up
1009
963
  expect(getActiveRestartToken()).toBeNull();
@@ -1019,15 +973,14 @@ describe("start_and_stop_only fallback to plain start when idle", () => {
1019
973
  });
1020
974
 
1021
975
  test("falls back to handleRecordingStart when no active recording", () => {
1022
- const { ctx, sent, fakeSocket } = createCtx();
976
+ const { ctx, sent } = createCtx();
1023
977
  const conversationId = "conv-stop-start-idle";
1024
- ctx.socketToSession.set(fakeSocket, conversationId);
1025
978
 
1026
979
  // No recording is active — start_and_stop_only should fall back to a
1027
980
  // plain start rather than returning "No active recording to restart."
1028
981
  const result = executeRecordingIntent(
1029
982
  { kind: "start_and_stop_only" },
1030
- { conversationId, socket: fakeSocket, ctx },
983
+ { conversationId, ctx },
1031
984
  );
1032
985
 
1033
986
  expect(result.handled).toBe(true);
@@ -1042,15 +995,13 @@ describe("start_and_stop_only fallback to plain start when idle", () => {
1042
995
  });
1043
996
 
1044
997
  test("goes through restart when a recording is active (deferred start)", () => {
1045
- const { ctx, sent, fakeSocket } = createCtx();
998
+ const { ctx, sent } = createCtx();
1046
999
  const conversationId = "conv-stop-start-active";
1047
- ctx.socketToSession.set(fakeSocket, conversationId);
1048
1000
 
1049
1001
  // Start a recording first
1050
1002
  const originalId = handleRecordingStart(
1051
1003
  conversationId,
1052
1004
  undefined,
1053
- fakeSocket,
1054
1005
  ctx,
1055
1006
  );
1056
1007
  expect(originalId).not.toBeNull();
@@ -1059,7 +1010,7 @@ describe("start_and_stop_only fallback to plain start when idle", () => {
1059
1010
  // Now start_and_stop_only should go through handleRecordingRestart
1060
1011
  const result = executeRecordingIntent(
1061
1012
  { kind: "start_and_stop_only" },
1062
- { conversationId, socket: fakeSocket, ctx },
1013
+ { conversationId, ctx },
1063
1014
  );
1064
1015
 
1065
1016
  expect(result.handled).toBe(true);
@@ -1081,7 +1032,7 @@ describe("start_and_stop_only fallback to plain start when idle", () => {
1081
1032
  status: "stopped",
1082
1033
  attachToConversationId: conversationId,
1083
1034
  };
1084
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1035
+ recordingHandlers.recording_status(stoppedStatus, ctx);
1085
1036
 
1086
1037
  // NOW the deferred start should have been sent
1087
1038
  const startMsgsAfterAck = sent.filter((m) => m.type === "recording_start");
@@ -1097,12 +1048,12 @@ describe("start_and_stop_with_remainder fallback to plain start when idle", () =
1097
1048
  });
1098
1049
 
1099
1050
  test("sets pendingStart (not pendingRestart) when no active recording", () => {
1100
- const { ctx, fakeSocket } = createCtx();
1051
+ const { ctx } = createCtx();
1101
1052
  const conversationId = "conv-rem-idle";
1102
1053
 
1103
1054
  const result = executeRecordingIntent(
1104
1055
  { kind: "start_and_stop_with_remainder", remainder: "do something" },
1105
- { conversationId, socket: fakeSocket, ctx },
1056
+ { conversationId, ctx },
1106
1057
  );
1107
1058
 
1108
1059
  expect(result.handled).toBe(false);
@@ -1112,16 +1063,15 @@ describe("start_and_stop_with_remainder fallback to plain start when idle", () =
1112
1063
  });
1113
1064
 
1114
1065
  test("sets pendingRestart when a recording is active", () => {
1115
- const { ctx, fakeSocket } = createCtx();
1066
+ const { ctx } = createCtx();
1116
1067
  const conversationId = "conv-rem-active";
1117
- ctx.socketToSession.set(fakeSocket, conversationId);
1118
1068
 
1119
1069
  // Start a recording first
1120
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
1070
+ handleRecordingStart(conversationId, undefined, ctx);
1121
1071
 
1122
1072
  const result = executeRecordingIntent(
1123
1073
  { kind: "start_and_stop_with_remainder", remainder: "do something" },
1124
- { conversationId, socket: fakeSocket, ctx },
1074
+ { conversationId, ctx },
1125
1075
  );
1126
1076
 
1127
1077
  expect(result.handled).toBe(false);
@@ -1141,14 +1091,13 @@ describe("deferred restart prevents race condition", () => {
1141
1091
  });
1142
1092
 
1143
1093
  test("recording_start is NOT sent until client acks the stop", () => {
1144
- const { ctx, sent, fakeSocket } = createCtx();
1094
+ const { ctx, sent } = createCtx();
1145
1095
  const conversationId = "conv-deferred-race";
1146
- ctx.socketToSession.set(fakeSocket, conversationId);
1147
1096
 
1148
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
1097
+ handleRecordingStart(conversationId, undefined, ctx);
1149
1098
  sent.length = 0;
1150
1099
 
1151
- handleRecordingRestart(conversationId, fakeSocket, ctx);
1100
+ handleRecordingRestart(conversationId, ctx);
1152
1101
 
1153
1102
  // Only recording_stop should have been sent — no recording_start yet
1154
1103
  expect(sent.filter((m) => m.type === "recording_stop")).toHaveLength(1);
@@ -1160,12 +1109,11 @@ describe("deferred restart prevents race condition", () => {
1160
1109
 
1161
1110
  test("stop-ack timeout cleans up deferred restart state", () => {
1162
1111
  // This test uses a real timer via bun's jest-compatible API
1163
- const { ctx, fakeSocket } = createCtx();
1112
+ const { ctx } = createCtx();
1164
1113
  const conversationId = "conv-deferred-timeout";
1165
- ctx.socketToSession.set(fakeSocket, conversationId);
1166
1114
 
1167
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
1168
- handleRecordingRestart(conversationId, fakeSocket, ctx);
1115
+ handleRecordingStart(conversationId, undefined, ctx);
1116
+ handleRecordingRestart(conversationId, ctx);
1169
1117
 
1170
1118
  // Mid-restart: not idle
1171
1119
  expect(isRecordingIdle()).toBe(false);
@@ -1176,18 +1124,17 @@ describe("deferred restart prevents race condition", () => {
1176
1124
  });
1177
1125
 
1178
1126
  test("cross-conversation restart: conversation B restarts recording owned by A", () => {
1179
- const { ctx, sent, fakeSocket } = createCtx();
1127
+ const { ctx, sent } = createCtx();
1180
1128
  const convA = "conv-owner-A";
1181
1129
  const convB = "conv-requester-B";
1182
- ctx.socketToSession.set(fakeSocket, convA);
1183
1130
 
1184
1131
  // Conversation A starts a recording
1185
- const originalId = handleRecordingStart(convA, undefined, fakeSocket, ctx);
1132
+ const originalId = handleRecordingStart(convA, undefined, ctx);
1186
1133
  expect(originalId).not.toBeNull();
1187
1134
  sent.length = 0;
1188
1135
 
1189
1136
  // Conversation B requests a restart (cross-conversation via global fallback)
1190
- const result = handleRecordingRestart(convB, fakeSocket, ctx);
1137
+ const result = handleRecordingRestart(convB, ctx);
1191
1138
  expect(result.initiated).toBe(true);
1192
1139
  expect(result.operationToken).toBeTruthy();
1193
1140
 
@@ -1203,7 +1150,7 @@ describe("deferred restart prevents race condition", () => {
1203
1150
  status: "stopped",
1204
1151
  attachToConversationId: convA,
1205
1152
  };
1206
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1153
+ recordingHandlers.recording_status(stoppedStatus, ctx);
1207
1154
 
1208
1155
  // The deferred recording_start MUST have been triggered even though the
1209
1156
  // stopped callback resolved to conversation A (owner), not B (requester).
@@ -1223,7 +1170,7 @@ describe("deferred restart prevents race condition", () => {
1223
1170
  operationToken: result.operationToken,
1224
1171
  attachToConversationId: convB,
1225
1172
  };
1226
- recordingHandlers.recording_status(startedStatus, fakeSocket, ctx);
1173
+ recordingHandlers.recording_status(startedStatus, ctx);
1227
1174
 
1228
1175
  // Restart cycle must be fully complete: activeRestartToken cleared
1229
1176
  expect(getActiveRestartToken()).toBeNull();
@@ -1239,20 +1186,18 @@ describe("deferred restart prevents race condition", () => {
1239
1186
  status: "stopped",
1240
1187
  attachToConversationId: convB,
1241
1188
  };
1242
- recordingHandlers.recording_status(newStoppedStatus, fakeSocket, ctx);
1189
+ recordingHandlers.recording_status(newStoppedStatus, ctx);
1243
1190
 
1244
1191
  expect(isRecordingIdle()).toBe(true);
1245
1192
  });
1246
1193
 
1247
1194
  test("normal stop (non-restart) does not trigger deferred start", () => {
1248
- const { ctx, sent, fakeSocket } = createCtx();
1195
+ const { ctx, sent } = createCtx();
1249
1196
  const conversationId = "conv-normal-stop";
1250
- ctx.socketToSession.set(fakeSocket, conversationId);
1251
1197
 
1252
1198
  const recordingId = handleRecordingStart(
1253
1199
  conversationId,
1254
1200
  undefined,
1255
- fakeSocket,
1256
1201
  ctx,
1257
1202
  );
1258
1203
  expect(recordingId).not.toBeNull();
@@ -1268,7 +1213,7 @@ describe("deferred restart prevents race condition", () => {
1268
1213
  status: "stopped",
1269
1214
  attachToConversationId: conversationId,
1270
1215
  };
1271
- recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1216
+ recordingHandlers.recording_status(stoppedStatus, ctx);
1272
1217
 
1273
1218
  // Should NOT have sent a recording_start (no deferred restart pending)
1274
1219
  const startMsgs = sent.filter((m) => m.type === "recording_start");
@@ -1287,15 +1232,13 @@ describe("restart finalization", () => {
1287
1232
  });
1288
1233
 
1289
1234
  test("publishes previous recording attachment on restart", async () => {
1290
- const { ctx, sent, fakeSocket } = createCtx();
1235
+ const { ctx, sent } = createCtx();
1291
1236
  const conversationId = "conv-fin-publish";
1292
- ctx.socketToSession.set(fakeSocket, conversationId);
1293
1237
 
1294
1238
  // Start a recording
1295
1239
  const originalId = handleRecordingStart(
1296
1240
  conversationId,
1297
1241
  undefined,
1298
- fakeSocket,
1299
1242
  ctx,
1300
1243
  );
1301
1244
  expect(originalId).not.toBeNull();
@@ -1303,7 +1246,6 @@ describe("restart finalization", () => {
1303
1246
  // Trigger restart
1304
1247
  const restartResult = handleRecordingRestart(
1305
1248
  conversationId,
1306
- fakeSocket,
1307
1249
  ctx,
1308
1250
  );
1309
1251
  expect(restartResult.initiated).toBe(true);
@@ -1318,7 +1260,7 @@ describe("restart finalization", () => {
1318
1260
  durationMs: 5000,
1319
1261
  attachToConversationId: conversationId,
1320
1262
  };
1321
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1263
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1322
1264
 
1323
1265
  // Verify: a new recording_start IPC was sent (deferred start triggered)
1324
1266
  const startMsgs = sent.filter((m) => m.type === "recording_start");
@@ -1346,22 +1288,19 @@ describe("restart finalization", () => {
1346
1288
  });
1347
1289
 
1348
1290
  test("restart + picker cancel preserves previous publish", async () => {
1349
- const { ctx, sent, fakeSocket } = createCtx();
1291
+ const { ctx, sent } = createCtx();
1350
1292
  const conversationId = "conv-fin-cancel-preserve";
1351
- ctx.socketToSession.set(fakeSocket, conversationId);
1352
1293
 
1353
1294
  // Start a recording
1354
1295
  const originalId = handleRecordingStart(
1355
1296
  conversationId,
1356
1297
  undefined,
1357
- fakeSocket,
1358
1298
  ctx,
1359
1299
  );
1360
1300
 
1361
1301
  // Restart
1362
1302
  const restartResult = handleRecordingRestart(
1363
1303
  conversationId,
1364
- fakeSocket,
1365
1304
  ctx,
1366
1305
  );
1367
1306
  expect(restartResult.initiated).toBe(true);
@@ -1375,7 +1314,7 @@ describe("restart finalization", () => {
1375
1314
  durationMs: 3000,
1376
1315
  attachToConversationId: conversationId,
1377
1316
  };
1378
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1317
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1379
1318
 
1380
1319
  // Capture sent messages so far (should include old recording's attachment)
1381
1320
  const preCancelTextDeltas = sent.filter(
@@ -1400,7 +1339,7 @@ describe("restart finalization", () => {
1400
1339
  attachToConversationId: conversationId,
1401
1340
  operationToken: restartResult.operationToken,
1402
1341
  };
1403
- await recordingHandlers.recording_status(cancelStatus, fakeSocket, ctx);
1342
+ await recordingHandlers.recording_status(cancelStatus, ctx);
1404
1343
 
1405
1344
  // Verify: the old recording's attachment messages are still in sent
1406
1345
  const postCancelTextDeltas = sent.filter(
@@ -1426,22 +1365,19 @@ describe("restart finalization", () => {
1426
1365
  });
1427
1366
 
1428
1367
  test("emits truthful failure text when previous finalize fails", async () => {
1429
- const { ctx, sent, fakeSocket } = createCtx();
1368
+ const { ctx, sent } = createCtx();
1430
1369
  const conversationId = "conv-fin-fail-truth";
1431
- ctx.socketToSession.set(fakeSocket, conversationId);
1432
1370
 
1433
1371
  // Start a recording
1434
1372
  const originalId = handleRecordingStart(
1435
1373
  conversationId,
1436
1374
  undefined,
1437
- fakeSocket,
1438
1375
  ctx,
1439
1376
  );
1440
1377
 
1441
1378
  // Restart
1442
1379
  const restartResult = handleRecordingRestart(
1443
1380
  conversationId,
1444
- fakeSocket,
1445
1381
  ctx,
1446
1382
  );
1447
1383
  expect(restartResult.initiated).toBe(true);
@@ -1455,7 +1391,7 @@ describe("restart finalization", () => {
1455
1391
  // No filePath — recording stopped without producing a file
1456
1392
  attachToConversationId: conversationId,
1457
1393
  };
1458
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1394
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1459
1395
 
1460
1396
  // Verify: error message text is sent (not "Screen recording complete")
1461
1397
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -1479,22 +1415,19 @@ describe("restart finalization", () => {
1479
1415
  });
1480
1416
 
1481
1417
  test("preserves previous attachment when new start fails", async () => {
1482
- const { ctx, sent, fakeSocket } = createCtx();
1418
+ const { ctx, sent } = createCtx();
1483
1419
  const conversationId = "conv-fin-new-fail";
1484
- ctx.socketToSession.set(fakeSocket, conversationId);
1485
1420
 
1486
1421
  // Start a recording
1487
1422
  const originalId = handleRecordingStart(
1488
1423
  conversationId,
1489
1424
  undefined,
1490
- fakeSocket,
1491
1425
  ctx,
1492
1426
  );
1493
1427
 
1494
1428
  // Restart
1495
1429
  const restartResult = handleRecordingRestart(
1496
1430
  conversationId,
1497
- fakeSocket,
1498
1431
  ctx,
1499
1432
  );
1500
1433
  expect(restartResult.initiated).toBe(true);
@@ -1516,7 +1449,7 @@ describe("restart finalization", () => {
1516
1449
  durationMs: 4000,
1517
1450
  attachToConversationId: conversationId,
1518
1451
  };
1519
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1452
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1520
1453
 
1521
1454
  // Verify: old recording attachment is published (finalization succeeded)
1522
1455
  const textDeltas = sent.filter((m) => m.type === "assistant_text_delta");
@@ -1551,22 +1484,19 @@ describe("restart finalization", () => {
1551
1484
  });
1552
1485
 
1553
1486
  test("duplicate stopped callback does not double-attach", async () => {
1554
- const { ctx, sent, fakeSocket } = createCtx();
1487
+ const { ctx, sent } = createCtx();
1555
1488
  const conversationId = "conv-fin-dup-stop";
1556
- ctx.socketToSession.set(fakeSocket, conversationId);
1557
1489
 
1558
1490
  // Start a recording
1559
1491
  const originalId = handleRecordingStart(
1560
1492
  conversationId,
1561
1493
  undefined,
1562
- fakeSocket,
1563
1494
  ctx,
1564
1495
  );
1565
1496
 
1566
1497
  // Restart
1567
1498
  const restartResult = handleRecordingRestart(
1568
1499
  conversationId,
1569
- fakeSocket,
1570
1500
  ctx,
1571
1501
  );
1572
1502
  expect(restartResult.initiated).toBe(true);
@@ -1581,7 +1511,7 @@ describe("restart finalization", () => {
1581
1511
  durationMs: 2000,
1582
1512
  attachToConversationId: conversationId,
1583
1513
  };
1584
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1514
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1585
1515
 
1586
1516
  // Count attachment-related messages after first callback
1587
1517
  const firstCallAttachmentMsgs = sent.filter(
@@ -1598,7 +1528,7 @@ describe("restart finalization", () => {
1598
1528
  expect(firstCallMsgCount).toBe(1);
1599
1529
 
1600
1530
  // Send stopped again with same recordingId (duplicate)
1601
- await recordingHandlers.recording_status(stoppedStatus, fakeSocket, ctx);
1531
+ await recordingHandlers.recording_status(stoppedStatus, ctx);
1602
1532
 
1603
1533
  // Verify: only one attachment message exists in sent — the duplicate was
1604
1534
  // rejected by the idempotency guard in finalizeAndPublishRecording
@@ -1626,15 +1556,14 @@ describe("restart finalization", () => {
1626
1556
  expect(getActiveRestartToken()).toBeNull();
1627
1557
 
1628
1558
  // Start a recording, verify not idle
1629
- const { ctx, fakeSocket } = createCtx();
1559
+ const { ctx } = createCtx();
1630
1560
  const conversationId = "conv-fin-sanity";
1631
- ctx.socketToSession.set(fakeSocket, conversationId);
1632
1561
 
1633
- handleRecordingStart(conversationId, undefined, fakeSocket, ctx);
1562
+ handleRecordingStart(conversationId, undefined, ctx);
1634
1563
  expect(isRecordingIdle()).toBe(false);
1635
1564
 
1636
1565
  // Restart, verify token is set
1637
- handleRecordingRestart(conversationId, fakeSocket, ctx);
1566
+ handleRecordingRestart(conversationId, ctx);
1638
1567
  expect(getActiveRestartToken()).not.toBeNull();
1639
1568
 
1640
1569
  // Reset everything, verify clean state