@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,7 +1,5 @@
1
- import { chmodSync, existsSync, readFileSync, statSync } from "node:fs";
2
- import * as net from "node:net";
1
+ import { existsSync, readFileSync } from "node:fs";
3
2
  import { join } from "node:path";
4
- import * as tls from "node:tls";
5
3
 
6
4
  import {
7
5
  createAssistantMessage,
@@ -14,61 +12,51 @@ import {
14
12
  parseInterfaceId,
15
13
  } from "../channels/types.js";
16
14
  import { getConfig } from "../config/loader.js";
17
- import { buildSystemPrompt } from "../config/system-prompt.js";
18
15
  import { onContactChange } from "../contacts/contact-events.js";
19
16
  import type { HeartbeatService } from "../heartbeat/heartbeat-service.js";
20
- import { bootstrapHomeBaseAppLink } from "../home-base/bootstrap.js";
21
17
  import * as attachmentsStore from "../memory/attachments-store.js";
22
18
  import {
23
19
  createCanonicalGuardianRequest,
24
20
  generateCanonicalRequestCode,
25
21
  } from "../memory/canonical-guardian-store.js";
26
- import * as conversationStore from "../memory/conversation-store.js";
27
- import { provenanceFromTrustContext } from "../memory/conversation-store.js";
22
+ import {
23
+ addMessage,
24
+ getConversationMemoryScopeId,
25
+ getConversationThreadType,
26
+ provenanceFromTrustContext,
27
+ setConversationOriginChannelIfUnset,
28
+ setConversationOriginInterfaceIfUnset,
29
+ } from "../memory/conversation-crud.js";
30
+ import { buildSystemPrompt } from "../prompts/system-prompt.js";
28
31
  import { RateLimitProvider } from "../providers/ratelimit.js";
29
32
  import {
30
33
  getFailoverProvider,
31
34
  initializeProviders,
32
35
  } from "../providers/registry.js";
36
+ import { buildAssistantEvent } from "../runtime/assistant-event.js";
37
+ import { assistantEventHub } from "../runtime/assistant-event-hub.js";
33
38
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
39
+ import { getSigningKeyFingerprint } from "../runtime/auth/token-service.js";
34
40
  import { bridgeConfirmationRequestToGuardian } from "../runtime/confirmation-request-guardian-bridge.js";
35
41
  import * as pendingInteractions from "../runtime/pending-interactions.js";
36
42
  import { checkIngressForSecrets } from "../security/secret-ingress.js";
37
43
  import { getSubagentManager } from "../subagent/index.js";
38
44
  import { IngressBlockedError } from "../util/errors.js";
39
45
  import { getLogger } from "../util/logger.js";
40
- import { getLocalIPv4 } from "../util/network-info.js";
41
46
  import {
42
47
  getSandboxWorkingDir,
43
- getSocketPath,
44
- getTCPHost,
45
- getTCPPort,
46
48
  getWorkspacePromptPath,
47
- isIOSPairingEnabled,
48
- isTCPEnabled,
49
- removeSocketFile,
50
49
  } from "../util/platform.js";
51
50
  import { registerDaemonCallbacks } from "../work-items/work-item-runner.js";
52
- import { AuthManager } from "./auth-manager.js";
53
51
  import { ComputerUseSession } from "./computer-use-session.js";
54
52
  import { ConfigWatcher } from "./config-watcher.js";
55
- import {
56
- handleMessage,
57
- type HandlerContext,
58
- type SessionCreateOptions,
59
- } from "./handlers.js";
60
53
  import { parseIdentityFields } from "./handlers/identity.js";
61
- import { cleanupRecordingsOnDisconnect } from "./handlers/recording.js";
62
- import { ensureBlobDir, sweepStaleBlobs } from "./ipc-blob-store.js";
63
- import { IpcSender } from "./ipc-handler.js";
64
- import {
65
- createMessageParser,
66
- MAX_LINE_SIZE,
67
- normalizeThreadType,
68
- serialize,
69
- type ServerMessage,
70
- } from "./ipc-protocol.js";
71
- import { validateClientMessage } from "./ipc-validate.js";
54
+ import type {
55
+ HandlerContext,
56
+ SessionCreateOptions,
57
+ } from "./handlers/shared.js";
58
+ import type { SkillOperationContext } from "./handlers/skills.js";
59
+ import type { ServerMessage } from "./message-protocol.js";
72
60
  import {
73
61
  DEFAULT_MEMORY_POLICY,
74
62
  Session,
@@ -77,7 +65,6 @@ import {
77
65
  import { SessionEvictor } from "./session-evictor.js";
78
66
  import { resolveChannelCapabilities } from "./session-runtime-assembly.js";
79
67
  import { resolveSlash } from "./session-slash.js";
80
- import { ensureTlsCert } from "./tls-certs.js";
81
68
 
82
69
  const log = getLogger("server");
83
70
 
@@ -132,7 +119,7 @@ function resolveTurnInterface(sourceInterface?: string): InterfaceId {
132
119
  function resolveCanonicalRequestSourceType(
133
120
  sourceChannel: string | undefined,
134
121
  ): "desktop" | "channel" | "voice" {
135
- if (sourceChannel === "voice") {
122
+ if (sourceChannel === "phone") {
136
123
  return "voice";
137
124
  }
138
125
  if (sourceChannel === "vellum") {
@@ -168,7 +155,7 @@ function makePendingInteractionRegistrar(
168
155
  },
169
156
  });
170
157
 
171
- // Create a canonical guardian request so IPC/HTTP handlers can find it
158
+ // Create a canonical guardian request so HTTP handlers can find it
172
159
  // via applyCanonicalGuardianDecision.
173
160
  try {
174
161
  const trustContext = session.trustContext;
@@ -217,29 +204,19 @@ function makePendingInteractionRegistrar(
217
204
  }
218
205
 
219
206
  export class DaemonServer {
220
- private server: net.Server | null = null;
221
- private tcpServer: tls.Server | null = null;
222
207
  private sessions = new Map<string, Session>();
223
- private socketToSession = new Map<net.Socket, string>();
224
208
  private cuSessions = new Map<string, ComputerUseSession>();
225
- private socketToCuSession = new Map<net.Socket, Set<string>>();
226
- private connectedSockets = new Set<net.Socket>();
227
- private socketSandboxOverride = new Map<net.Socket, boolean>();
228
209
  private cuObservationParseSequence = new Map<string, number>();
229
210
  private sessionOptions = new Map<string, SessionCreateOptions>();
230
211
  private sessionCreating = new Map<string, Promise<Session>>();
231
212
  private sharedRequestTimestamps: number[] = [];
232
- private socketPath: string;
233
213
  private httpPort: number | undefined;
234
- private blobSweepTimer: ReturnType<typeof setInterval> | null = null;
235
214
  private unsubscribeContactChange: (() => void) | null = null;
236
- private static readonly MAX_CONNECTIONS = 50;
237
215
  private evictor: SessionEvictor;
216
+ private _hubChain: Promise<void> = Promise.resolve();
238
217
 
239
218
  // Composed subsystems
240
- private auth = new AuthManager();
241
219
  private configWatcher = new ConfigWatcher();
242
- private ipc = new IpcSender();
243
220
 
244
221
  /**
245
222
  * Logical assistant identifier used when publishing to the assistant-events hub.
@@ -254,11 +231,10 @@ export class DaemonServer {
254
231
  }
255
232
 
256
233
  private deriveMemoryPolicy(conversationId: string): SessionMemoryPolicy {
257
- const threadType =
258
- conversationStore.getConversationThreadType(conversationId);
234
+ const threadType = getConversationThreadType(conversationId);
259
235
  if (threadType === "private") {
260
236
  return {
261
- scopeId: conversationStore.getConversationMemoryScopeId(conversationId),
237
+ scopeId: getConversationMemoryScopeId(conversationId),
262
238
  includeDefaultFallback: true,
263
239
  strictSideEffects: true,
264
240
  };
@@ -279,7 +255,6 @@ export class DaemonServer {
279
255
  }
280
256
 
281
257
  constructor() {
282
- this.socketPath = getSocketPath();
283
258
  this.evictor = new SessionEvictor(this.sessions);
284
259
  getSubagentManager().sharedRequestTimestamps = this.sharedRequestTimestamps;
285
260
  this.evictor.onEvict = (sessionId: string) => {
@@ -342,20 +317,29 @@ export class DaemonServer {
342
317
  };
343
318
  }
344
319
 
345
- // ── Send / Broadcast wrappers ───────────────────────────────────────
320
+ // ── Broadcast / Event publishing ──────────────────────────────────
346
321
 
347
- private send(socket: net.Socket, msg: ServerMessage): void {
348
- this.ipc.send(socket, msg, this.socketToSession, this.assistantId);
322
+ /**
323
+ * Publish `msg` as an `AssistantEvent` to the process-level hub.
324
+ * Publications are serialized via a promise chain so subscribers
325
+ * always observe events in send order.
326
+ */
327
+ private publishAssistantEvent(msg: ServerMessage, sessionId?: string): void {
328
+ const id = this.assistantId ?? "default";
329
+ const event = buildAssistantEvent(id, msg, sessionId);
330
+ this._hubChain = this._hubChain
331
+ .then(() => assistantEventHub.publish(event))
332
+ .catch((err: unknown) => {
333
+ log.warn(
334
+ { err },
335
+ "assistant-events hub subscriber threw during broadcast",
336
+ );
337
+ });
349
338
  }
350
339
 
351
- broadcast(msg: ServerMessage, excludeSocket?: net.Socket): void {
352
- this.ipc.broadcast(
353
- this.auth.getAuthenticatedSockets(),
354
- msg,
355
- this.socketToSession,
356
- this.assistantId,
357
- excludeSocket,
358
- );
340
+ broadcast(msg: ServerMessage): void {
341
+ const sessionId = extractSessionId(msg);
342
+ this.publishAssistantEvent(msg, sessionId);
359
343
  }
360
344
 
361
345
  private broadcastIdentityChanged(): void {
@@ -381,21 +365,10 @@ export class DaemonServer {
381
365
  // ── Server lifecycle ────────────────────────────────────────────────
382
366
 
383
367
  async start(): Promise<void> {
384
- removeSocketFile(this.socketPath);
385
-
386
368
  const config = getConfig();
387
369
  initializeProviders(config);
388
370
  this.configWatcher.initFingerprint(config);
389
371
 
390
- try {
391
- bootstrapHomeBaseAppLink();
392
- } catch (err) {
393
- log.warn(
394
- { err },
395
- "Failed to bootstrap Home Base app link at daemon startup",
396
- );
397
- }
398
-
399
372
  this.evictor.start();
400
373
 
401
374
  registerDaemonCallbacks({
@@ -404,16 +377,6 @@ export class DaemonServer {
404
377
  broadcast: (msg) => this.broadcast(msg),
405
378
  });
406
379
 
407
- ensureBlobDir();
408
- this.blobSweepTimer = setInterval(
409
- () => {
410
- sweepStaleBlobs(30 * 60 * 1000).catch((err) => {
411
- log.warn({ err }, "Blob sweep failed");
412
- });
413
- },
414
- 5 * 60 * 1000,
415
- );
416
-
417
380
  this.configWatcher.start(
418
381
  () => this.evictSessionsForReload(),
419
382
  () => this.broadcastIdentityChanged(),
@@ -424,140 +387,17 @@ export class DaemonServer {
424
387
  this.broadcast({ type: "contacts_changed" });
425
388
  });
426
389
 
427
- this.auth.initToken();
428
-
429
- let tlsCreds: { cert: string; key: string; fingerprint: string } | null =
430
- null;
431
- if (isTCPEnabled()) {
432
- try {
433
- tlsCreds = await ensureTlsCert();
434
- } catch (err) {
435
- log.error(
436
- { err },
437
- "Failed to generate TLS certificate — TCP listener will not start",
438
- );
439
- }
440
- }
441
-
442
- return new Promise((resolve, reject) => {
443
- this.server = net.createServer((socket) => {
444
- this.handleConnection(socket);
445
- });
446
-
447
- const oldUmask = process.umask(0o177);
448
-
449
- this.server.once("error", (err) => {
450
- process.umask(oldUmask);
451
- log.error(
452
- { err, socketPath: this.socketPath },
453
- "Server failed to start (is another daemon already running?)",
454
- );
455
- reject(err);
456
- });
457
-
458
- this.server.listen(this.socketPath, () => {
459
- process.umask(oldUmask);
460
- this.server!.removeAllListeners("error");
461
- this.server!.on("error", (err) => {
462
- log.error(
463
- { err, socketPath: this.socketPath },
464
- "Server socket error while running",
465
- );
466
- });
467
- chmodSync(this.socketPath, 0o600);
468
- // Validate the chmod actually took effect — some filesystems
469
- // (e.g. FAT32 mounts, container overlays) silently ignore chmod.
470
- const socketStat = statSync(this.socketPath);
471
- if ((socketStat.mode & 0o077) !== 0) {
472
- const actual = "0o" + (socketStat.mode & 0o777).toString(8);
473
- log.error(
474
- { socketPath: this.socketPath, mode: actual },
475
- "IPC socket is accessible by other users (expected 0600) — filesystem may not support Unix permissions",
476
- );
477
- }
478
- log.info({ socketPath: this.socketPath }, "Daemon server listening");
479
-
480
- if (tlsCreds) {
481
- const tcpPort = getTCPPort();
482
- const tcpHost = getTCPHost();
483
- this.tcpServer = tls.createServer(
484
- { cert: tlsCreds.cert, key: tlsCreds.key },
485
- (socket) => {
486
- this.handleConnection(socket);
487
- },
488
- );
489
- this.tcpServer.on("error", (err) => {
490
- log.error({ err, tcpPort }, "TLS TCP server error");
491
- });
492
- const fingerprint = tlsCreds.fingerprint;
493
- this.tcpServer.listen(tcpPort, tcpHost, () => {
494
- const localIP = getLocalIPv4();
495
- log.info(
496
- {
497
- tcpPort,
498
- tcpHost,
499
- fingerprint,
500
- localIP,
501
- iosPairing: isIOSPairingEnabled(),
502
- },
503
- "TLS TCP listener started",
504
- );
505
- if (isIOSPairingEnabled() && localIP) {
506
- log.warn(
507
- { localIP, tcpPort },
508
- "iOS pairing enabled — daemon is reachable on the local network at %s:%d",
509
- localIP,
510
- tcpPort,
511
- );
512
- }
513
- });
514
- }
515
-
516
- resolve();
517
- });
518
- });
390
+ log.info("DaemonServer started (HTTP-only mode)");
519
391
  }
520
392
 
521
393
  async stop(): Promise<void> {
522
394
  getSubagentManager().disposeAll();
523
395
  this.evictor.stop();
524
- if (this.blobSweepTimer) {
525
- clearInterval(this.blobSweepTimer);
526
- this.blobSweepTimer = null;
527
- }
528
396
  this.configWatcher.stop();
529
397
  if (this.unsubscribeContactChange) {
530
398
  this.unsubscribeContactChange();
531
399
  this.unsubscribeContactChange = null;
532
400
  }
533
- this.auth.cleanupAll();
534
-
535
- const serverClosed = new Promise<void>((resolve) => {
536
- if (this.server) {
537
- this.server.close(() => {
538
- try {
539
- removeSocketFile(this.socketPath);
540
- } catch (err) {
541
- log.warn(
542
- { err, socketPath: this.socketPath },
543
- "Failed to remove socket file during shutdown",
544
- );
545
- }
546
- resolve();
547
- });
548
- } else {
549
- resolve();
550
- }
551
- });
552
-
553
- const tcpServerClosed = new Promise<void>((resolve) => {
554
- if (this.tcpServer) {
555
- this.tcpServer.close(() => resolve());
556
- this.tcpServer = null;
557
- } else {
558
- resolve();
559
- }
560
- });
561
401
 
562
402
  for (const session of this.sessions.values()) {
563
403
  session.dispose();
@@ -568,225 +408,10 @@ export class DaemonServer {
568
408
  cuSession.abort();
569
409
  }
570
410
  this.cuSessions.clear();
571
- this.socketToCuSession.clear();
572
411
 
573
- for (const socket of this.connectedSockets) {
574
- socket.destroy();
575
- }
576
- this.connectedSockets.clear();
577
- this.socketToSession.clear();
578
- this.socketSandboxOverride.clear();
579
- this.cuObservationParseSequence.clear();
580
-
581
- await Promise.all([serverClosed, tcpServerClosed]);
582
412
  log.info("Daemon server stopped");
583
413
  }
584
414
 
585
- // ── Connection handling ─────────────────────────────────────────────
586
-
587
- private handleConnection(socket: net.Socket): void {
588
- if (this.connectedSockets.size >= DaemonServer.MAX_CONNECTIONS) {
589
- log.warn(
590
- {
591
- current: this.connectedSockets.size,
592
- max: DaemonServer.MAX_CONNECTIONS,
593
- },
594
- "Connection limit reached, rejecting client",
595
- );
596
- socket.once("error", (err) => {
597
- log.error({ err }, "Socket error while rejecting connection");
598
- });
599
- socket.write(
600
- serialize({
601
- type: "error",
602
- message: `Connection limit reached (max ${DaemonServer.MAX_CONNECTIONS})`,
603
- }),
604
- );
605
- socket.destroy();
606
- return;
607
- }
608
-
609
- log.info("Client connected");
610
- this.connectedSockets.add(socket);
611
- const parser = createMessageParser({ maxLineSize: MAX_LINE_SIZE });
612
-
613
- if (this.auth.shouldAutoAuth()) {
614
- this.auth.markAuthenticated(socket);
615
- log.warn(
616
- "Auto-authenticated client (VELLUM_DAEMON_NOAUTH is set — token auth bypassed)",
617
- );
618
- this.send(socket, { type: "auth_result", success: true });
619
- this.sendInitialSession(socket).catch((err) => {
620
- log.error(
621
- { err },
622
- "Failed to send initial session info after auto-auth",
623
- );
624
- });
625
- }
626
-
627
- this.auth.startTimeout(socket, () => {
628
- this.send(socket, { type: "error", message: "Authentication timeout" });
629
- socket.destroy();
630
- });
631
-
632
- socket.on("data", (data) => {
633
- const chunkReceivedAtMs = Date.now();
634
- const parseStartNs = process.hrtime.bigint();
635
- let parsed;
636
- try {
637
- parsed = parser.feedRaw(data.toString());
638
- } catch (err) {
639
- log.error(
640
- { err },
641
- "IPC parse error (malformed JSON or message exceeded size limit), dropping client",
642
- );
643
- socket.write(
644
- serialize({
645
- type: "error",
646
- message: `IPC parse error: ${(err as Error).message}`,
647
- }),
648
- );
649
- socket.destroy();
650
- return;
651
- }
652
- const parsedAtMs = Date.now();
653
- const parseDurationMs =
654
- Number(process.hrtime.bigint() - parseStartNs) / 1_000_000;
655
- for (const entry of parsed) {
656
- const msg = entry.msg;
657
- if (
658
- typeof msg === "object" &&
659
- msg != null &&
660
- (msg as { type?: unknown }).type === "cu_observation"
661
- ) {
662
- const maybeSessionId = (msg as { sessionId?: unknown }).sessionId;
663
- const sessionId =
664
- typeof maybeSessionId === "string" ? maybeSessionId : "unknown";
665
- const previousSequence =
666
- this.cuObservationParseSequence.get(sessionId) ?? 0;
667
- const sequence = previousSequence + 1;
668
- this.cuObservationParseSequence.set(sessionId, sequence);
669
- log.info(
670
- {
671
- sessionId,
672
- sequence,
673
- chunkReceivedAtMs,
674
- parsedAtMs,
675
- parseDurationMs,
676
- messageBytes: entry.rawByteLength,
677
- },
678
- "IPC_METRIC cu_observation_parse",
679
- );
680
- }
681
- const result = validateClientMessage(msg);
682
- if (!result.valid) {
683
- log.warn(
684
- { reason: result.reason },
685
- "Invalid IPC message, dropping client",
686
- );
687
- socket.write(
688
- serialize({
689
- type: "error",
690
- message: `Invalid message: ${result.reason}`,
691
- }),
692
- );
693
- socket.destroy();
694
- return;
695
- }
696
-
697
- // Auth gate
698
- if (!this.auth.isAuthenticated(socket)) {
699
- this.auth.clearTimeout(socket);
700
-
701
- if (result.message.type === "auth") {
702
- const authMsg = result.message as { type: "auth"; token: string };
703
- if (this.auth.authenticate(socket, authMsg.token)) {
704
- this.send(socket, { type: "auth_result", success: true });
705
- this.sendInitialSession(socket).catch((err) => {
706
- log.error(
707
- { err },
708
- "Failed to send initial session info after auth",
709
- );
710
- });
711
- } else {
712
- this.send(socket, {
713
- type: "auth_result",
714
- success: false,
715
- message: "Invalid token",
716
- });
717
- socket.destroy();
718
- }
719
- continue;
720
- }
721
-
722
- log.warn(
723
- { type: result.message.type },
724
- "Unauthenticated client sent non-auth message, disconnecting",
725
- );
726
- this.send(socket, {
727
- type: "error",
728
- message: "Authentication required",
729
- });
730
- socket.destroy();
731
- return;
732
- }
733
-
734
- // Already-authenticated socket sending auth (e.g. auto-auth'd + local token)
735
- if (result.message.type === "auth") {
736
- this.send(socket, { type: "auth_result", success: true });
737
- continue;
738
- }
739
-
740
- this.dispatchMessage(result.message, socket);
741
- }
742
- });
743
-
744
- socket.on("close", () => {
745
- this.auth.cleanupSocket(socket);
746
- this.connectedSockets.delete(socket);
747
- this.socketSandboxOverride.delete(socket);
748
- const sessionId = this.socketToSession.get(socket);
749
- if (sessionId) {
750
- const session = this.sessions.get(sessionId);
751
- if (session) {
752
- session.abort();
753
- }
754
- getSubagentManager().abortAllForParent(sessionId);
755
- }
756
- // Clean up recording state for recordings whose owning conversation is
757
- // bound to the disconnecting socket. Runs outside the sessionId check
758
- // because recordings may be keyed to a different conversation than the
759
- // socket's current session.
760
- cleanupRecordingsOnDisconnect(socket, (convId) => {
761
- for (const [s, sid] of this.socketToSession.entries()) {
762
- if (sid === convId) return s;
763
- }
764
- return undefined;
765
- });
766
- this.socketToSession.delete(socket);
767
- const cuSessionIds = this.socketToCuSession.get(socket);
768
- if (cuSessionIds) {
769
- for (const cuSessionId of cuSessionIds) {
770
- this.cuObservationParseSequence.delete(cuSessionId);
771
- const cuSession = this.cuSessions.get(cuSessionId);
772
- if (cuSession) {
773
- cuSession.abort();
774
- this.cuSessions.delete(cuSessionId);
775
- }
776
- }
777
- }
778
- this.socketToCuSession.delete(socket);
779
- log.info("Client disconnected");
780
- });
781
-
782
- socket.on("error", (err) => {
783
- log.error(
784
- { err, remoteAddress: socket.remoteAddress },
785
- "Client socket error",
786
- );
787
- });
788
- }
789
-
790
415
  // ── Session management ──────────────────────────────────────────────
791
416
 
792
417
  setHttpPort(port: number): void {
@@ -795,6 +420,7 @@ export class DaemonServer {
795
420
  type: "daemon_status",
796
421
  httpPort: port,
797
422
  version: daemonVersion,
423
+ keyFingerprint: getSigningKeyFingerprint(),
798
424
  });
799
425
  }
800
426
 
@@ -841,49 +467,12 @@ export class DaemonServer {
841
467
  return changed;
842
468
  }
843
469
 
844
- private async sendInitialSession(socket: net.Socket): Promise<void> {
845
- const conversation = conversationStore.getLatestConversation();
846
- if (!conversation) {
847
- this.send(socket, {
848
- type: "daemon_status",
849
- httpPort: this.httpPort,
850
- version: daemonVersion,
851
- });
852
- return;
853
- }
854
-
855
- await this.getOrCreateSession(conversation.id, undefined, false);
856
-
857
- this.send(socket, {
858
- type: "session_info",
859
- sessionId: conversation.id,
860
- title: conversation.title ?? "New Conversation",
861
- threadType: normalizeThreadType(conversation.threadType),
862
- });
863
-
864
- this.send(socket, {
865
- type: "daemon_status",
866
- httpPort: this.httpPort,
867
- version: daemonVersion,
868
- });
869
- }
870
-
871
470
  private async getOrCreateSession(
872
471
  conversationId: string,
873
- socket?: net.Socket,
874
- rebindClient = true,
875
472
  options?: SessionCreateOptions,
876
473
  ): Promise<Session> {
877
474
  let session = this.sessions.get(conversationId);
878
- const sendToClient = socket
879
- ? (msg: ServerMessage) => this.send(socket, msg)
880
- : () => {};
881
- const maybeBindClient = (target: Session): void => {
882
- if (!rebindClient || !socket) return;
883
- target.updateClient(sendToClient);
884
- target.setSandboxOverride(this.socketSandboxOverride.get(socket));
885
- getSubagentManager().updateParentSender(conversationId, sendToClient);
886
- };
475
+ const sendToClient = () => {};
887
476
 
888
477
  if (options && Object.values(options).some((v) => v !== undefined)) {
889
478
  this.sessionOptions.set(conversationId, {
@@ -901,7 +490,6 @@ export class DaemonServer {
901
490
  const pending = this.sessionCreating.get(conversationId);
902
491
  if (pending) {
903
492
  session = await pending;
904
- maybeBindClient(session);
905
493
  return session;
906
494
  }
907
495
 
@@ -936,19 +524,14 @@ export class DaemonServer {
936
524
  provider,
937
525
  systemPrompt,
938
526
  maxTokens,
939
- rebindClient ? sendToClient : () => {},
527
+ sendToClient,
940
528
  workingDir,
941
- (msg) => this.broadcast(msg, socket),
529
+ (msg) => this.broadcast(msg),
942
530
  memoryPolicy,
943
531
  );
944
- if (!socket) {
945
- newSession.updateClient(sendToClient, true);
946
- }
532
+ newSession.updateClient(sendToClient, true);
947
533
  await newSession.loadFromDb();
948
534
  this.applyTransportMetadata(newSession, storedOptions);
949
- if (rebindClient && socket) {
950
- newSession.setSandboxOverride(this.socketSandboxOverride.get(socket));
951
- }
952
535
  this.sessions.set(conversationId, newSession);
953
536
  return newSession;
954
537
  })();
@@ -961,23 +544,19 @@ export class DaemonServer {
961
544
  }
962
545
  this.evictor.touch(conversationId);
963
546
  } else {
964
- maybeBindClient(session);
965
547
  this.applyTransportMetadata(session, options);
966
548
  this.evictor.touch(conversationId);
967
549
  }
968
550
  return session;
969
551
  }
970
552
 
971
- // ── Message dispatch ────────────────────────────────────────────────
553
+ // ── Handler context ────────────────────────────────────────────────
972
554
 
973
555
  private handlerContext(): HandlerContext {
974
556
  return {
975
557
  sessions: this.sessions,
976
- socketToSession: this.socketToSession,
977
558
  cuSessions: this.cuSessions,
978
- socketToCuSession: this.socketToCuSession,
979
559
  cuObservationParseSequence: this.cuObservationParseSequence,
980
- socketSandboxOverride: this.socketSandboxOverride,
981
560
  sharedRequestTimestamps: this.sharedRequestTimestamps,
982
561
  debounceTimers: this.configWatcher.timers,
983
562
  suppressConfigReload: this.configWatcher.suppressConfigReload,
@@ -987,39 +566,28 @@ export class DaemonServer {
987
566
  updateConfigFingerprint: () => {
988
567
  this.configWatcher.updateFingerprint();
989
568
  },
990
- send: (socket, msg) => this.send(socket, msg),
569
+ send: (msg) => this.broadcast(msg),
991
570
  broadcast: (msg) => this.broadcast(msg),
992
571
  clearAllSessions: () => this.clearAllSessions(),
993
- getOrCreateSession: (id, socket?, rebind?, options?) =>
994
- this.getOrCreateSession(id, socket, rebind, options),
572
+ getOrCreateSession: (id, options?) =>
573
+ this.getOrCreateSession(id, options),
995
574
  touchSession: (id) => this.evictor.touch(id),
996
575
  heartbeatService: this._heartbeatService,
997
576
  };
998
577
  }
999
578
 
1000
- private dispatchMessage(
1001
- msg: Parameters<typeof handleMessage>[0],
1002
- socket: net.Socket,
1003
- ): void {
1004
- if (msg.type !== "ping") {
1005
- const now = Date.now();
1006
- if (
1007
- now - this.configWatcher.lastConfigRefreshTime >=
1008
- ConfigWatcher.REFRESH_INTERVAL_MS
1009
- ) {
1010
- try {
1011
- const changed = this.configWatcher.refreshConfigFromSources();
1012
- if (changed) this.evictSessionsForReload();
1013
- this.configWatcher.lastConfigRefreshTime = now;
1014
- } catch (err) {
1015
- log.warn(
1016
- { err },
1017
- "Failed to refresh config from secure sources before handling IPC message",
1018
- );
1019
- }
1020
- }
1021
- }
1022
- handleMessage(msg, socket, this.handlerContext());
579
+ /** Public subset of handler context for skill management HTTP routes. */
580
+ getSkillContext(): SkillOperationContext {
581
+ return {
582
+ debounceTimers: this.configWatcher.timers,
583
+ setSuppressConfigReload: (value: boolean) => {
584
+ this.configWatcher.suppressConfigReload = value;
585
+ },
586
+ updateConfigFingerprint: () => {
587
+ this.configWatcher.updateFingerprint();
588
+ },
589
+ broadcast: (msg) => this.broadcast(msg),
590
+ };
1023
591
  }
1024
592
 
1025
593
  // ── HTTP message processing ─────────────────────────────────────────
@@ -1048,12 +616,7 @@ export class DaemonServer {
1048
616
  );
1049
617
  }
1050
618
 
1051
- const session = await this.getOrCreateSession(
1052
- conversationId,
1053
- undefined,
1054
- true,
1055
- options,
1056
- );
619
+ const session = await this.getOrCreateSession(conversationId, options);
1057
620
 
1058
621
  if (session.isProcessing()) {
1059
622
  throw new Error("Session is already processing a message");
@@ -1121,12 +684,21 @@ export class DaemonServer {
1121
684
 
1122
685
  // Register pending interactions so channel approval interception can
1123
686
  // find the session by requestId when confirmation/secret events fire.
1124
- const onEvent = makePendingInteractionRegistrar(session, conversationId);
687
+ const registrar = makePendingInteractionRegistrar(session, conversationId);
688
+ const onEvent = options?.onEvent
689
+ ? (msg: ServerMessage) => {
690
+ registrar(msg);
691
+ try {
692
+ options.onEvent!(msg);
693
+ } catch (err) {
694
+ log.error(
695
+ { err, conversationId },
696
+ "onEvent callback failed; continuing agent loop",
697
+ );
698
+ }
699
+ }
700
+ : registrar;
1125
701
  if (options?.isInteractive === true) {
1126
- // Interactive HTTP paths (e.g. channel ingress) still run without an IPC
1127
- // socket. Route prompter events through the registrar callback so
1128
- // confirmation_request/secret_request events are tracked, and mark the
1129
- // session interactive so prompt decisions are not auto-denied.
1130
702
  session.updateClient(onEvent, false);
1131
703
  }
1132
704
 
@@ -1136,8 +708,6 @@ export class DaemonServer {
1136
708
  isUserMessage: true,
1137
709
  })
1138
710
  .finally(() => {
1139
- // Only reset if no other caller (e.g. a real IPC client) has rebound
1140
- // the session's sender while the agent loop was running.
1141
711
  if (
1142
712
  options?.isInteractive === true &&
1143
713
  session.getCurrentSender() === onEvent
@@ -1192,7 +762,7 @@ export class DaemonServer {
1192
762
  : {}),
1193
763
  };
1194
764
  const userMsg = createUserMessage(content, attachments);
1195
- const persisted = await conversationStore.addMessage(
765
+ const persisted = await addMessage(
1196
766
  conversationId,
1197
767
  "user",
1198
768
  JSON.stringify(userMsg.content),
@@ -1202,7 +772,7 @@ export class DaemonServer {
1202
772
 
1203
773
  if (serverTurnCtx) {
1204
774
  try {
1205
- conversationStore.setConversationOriginChannelIfUnset(
775
+ setConversationOriginChannelIfUnset(
1206
776
  conversationId,
1207
777
  serverTurnCtx.userMessageChannel,
1208
778
  );
@@ -1215,7 +785,7 @@ export class DaemonServer {
1215
785
  }
1216
786
  if (serverInterfaceCtx) {
1217
787
  try {
1218
- conversationStore.setConversationOriginInterfaceIfUnset(
788
+ setConversationOriginInterfaceIfUnset(
1219
789
  conversationId,
1220
790
  serverInterfaceCtx.userMessageInterface,
1221
791
  );
@@ -1228,7 +798,7 @@ export class DaemonServer {
1228
798
  }
1229
799
 
1230
800
  const assistantMsg = createAssistantMessage(slashResult.message);
1231
- await conversationStore.addMessage(
801
+ await addMessage(
1232
802
  conversationId,
1233
803
  "assistant",
1234
804
  JSON.stringify(assistantMsg.content),
@@ -1259,12 +829,21 @@ export class DaemonServer {
1259
829
 
1260
830
  // Register pending interactions so channel approval interception can
1261
831
  // find the session by requestId when confirmation/secret events fire.
1262
- const onEvent = makePendingInteractionRegistrar(session, conversationId);
832
+ const registrar = makePendingInteractionRegistrar(session, conversationId);
833
+ const onEvent = options?.onEvent
834
+ ? (msg: ServerMessage) => {
835
+ registrar(msg);
836
+ try {
837
+ options.onEvent!(msg);
838
+ } catch (err) {
839
+ log.error(
840
+ { err, conversationId },
841
+ "onEvent callback failed; continuing agent loop",
842
+ );
843
+ }
844
+ }
845
+ : registrar;
1263
846
  if (options?.isInteractive === true) {
1264
- // Interactive HTTP paths (e.g. channel ingress) still run without an IPC
1265
- // socket. Route prompter events through the registrar callback so
1266
- // confirmation_request/secret_request events are tracked, and mark the
1267
- // session interactive so prompt decisions are not auto-denied.
1268
847
  session.updateClient(onEvent, false);
1269
848
  }
1270
849
 
@@ -1274,8 +853,6 @@ export class DaemonServer {
1274
853
  isUserMessage: true,
1275
854
  });
1276
855
  } finally {
1277
- // Only reset if no other caller (e.g. a real IPC client) has rebound
1278
- // the session's sender while the agent loop was running.
1279
856
  if (
1280
857
  options?.isInteractive === true &&
1281
858
  session.getCurrentSender() === onEvent
@@ -1292,15 +869,48 @@ export class DaemonServer {
1292
869
  * The handler manages busy-state checking and queueing itself.
1293
870
  */
1294
871
  async getSessionForMessages(conversationId: string): Promise<Session> {
1295
- return this.getOrCreateSession(conversationId, undefined, true);
872
+ return this.getOrCreateSession(conversationId);
1296
873
  }
1297
874
 
1298
875
  /**
1299
876
  * Look up an active session by ID without creating one.
1300
877
  * Checks both normal sessions and computer-use sessions so the HTTP
1301
- * surface-action path is consistent with IPC dispatch.
878
+ * surface-action path is consistent with dispatch.
1302
879
  */
1303
880
  findSession(sessionId: string): Session | ComputerUseSession | undefined {
1304
881
  return this.cuSessions.get(sessionId) ?? this.sessions.get(sessionId);
1305
882
  }
883
+
884
+ /**
885
+ * Look up an active session that owns a given surfaceId.
886
+ * Falls back across both normal and computer-use sessions.
887
+ */
888
+ findSessionBySurfaceId(
889
+ surfaceId: string,
890
+ ): Session | ComputerUseSession | undefined {
891
+ for (const s of this.cuSessions.values()) {
892
+ if (s.surfaceState.has(surfaceId)) return s;
893
+ }
894
+ for (const s of this.sessions.values()) {
895
+ if (s.surfaceState.has(surfaceId)) return s;
896
+ }
897
+ return undefined;
898
+ }
899
+
900
+ /**
901
+ * Expose the handler context for use by session management HTTP routes.
902
+ * The context is built on-the-fly so it always reflects the current server state.
903
+ */
904
+ getHandlerContext(): HandlerContext {
905
+ return this.handlerContext();
906
+ }
907
+ }
908
+
909
+ /** Extract sessionId from a ServerMessage if present. */
910
+ function extractSessionId(msg: ServerMessage): string | undefined {
911
+ const record = msg as unknown as Record<string, unknown>;
912
+ if ("sessionId" in msg && typeof record.sessionId === "string") {
913
+ return record.sessionId as string;
914
+ }
915
+ return undefined;
1306
916
  }