@vellumai/assistant 0.4.26 → 0.4.30

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 (1360) hide show
  1. package/.env.example +2 -2
  2. package/AGENTS.md +5 -0
  3. package/ARCHITECTURE.md +207 -105
  4. package/Dockerfile +1 -1
  5. package/README.md +111 -113
  6. package/bun.lock +0 -3
  7. package/docs/architecture/integrations.md +0 -1
  8. package/docs/architecture/memory.md +100 -63
  9. package/docs/error-handling.md +71 -0
  10. package/docs/runbook-trusted-contacts.md +89 -52
  11. package/docs/trusted-contact-access.md +48 -46
  12. package/package.json +3 -3
  13. package/scripts/compare-benchmarks.sh +12 -5
  14. package/scripts/ipc/check-swift-decoder-drift.ts +5 -3
  15. package/scripts/test.sh +89 -5
  16. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +50 -37
  17. package/src/__tests__/access-request-decision.test.ts +0 -1
  18. package/src/__tests__/account-registry.test.ts +1 -1
  19. package/src/__tests__/actor-token-service.test.ts +40 -26
  20. package/src/__tests__/agent-loop-thinking.test.ts +29 -13
  21. package/src/__tests__/agent-loop.test.ts +2 -1
  22. package/src/__tests__/app-builder-tool-scripts.test.ts +1 -1
  23. package/src/__tests__/app-executors.test.ts +7 -17
  24. package/src/__tests__/approval-routes-http.test.ts +2 -2
  25. package/src/__tests__/asset-materialize-tool.test.ts +7 -7
  26. package/src/__tests__/asset-search-tool.test.ts +7 -7
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +18 -10
  28. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  29. package/src/__tests__/browser-skill-endstate.test.ts +10 -1
  30. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +218 -0
  31. package/src/__tests__/call-controller.test.ts +99 -69
  32. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +157 -114
  34. package/src/__tests__/channel-approval.test.ts +8 -0
  35. package/src/__tests__/channel-approvals.test.ts +39 -1
  36. package/src/__tests__/channel-guardian.test.ts +176 -275
  37. package/src/__tests__/channel-readiness-service.test.ts +6 -2
  38. package/src/__tests__/channel-reply-delivery.test.ts +33 -2
  39. package/src/__tests__/channel-retry-sweep.test.ts +14 -14
  40. package/src/__tests__/checker.test.ts +12 -31
  41. package/src/__tests__/claude-code-tool-profiles.test.ts +1 -1
  42. package/src/__tests__/commit-message-enrichment-service.test.ts +71 -59
  43. package/src/__tests__/compaction.benchmark.test.ts +6 -2
  44. package/src/__tests__/computer-use-tools.test.ts +1 -1
  45. package/src/__tests__/config-schema.test.ts +66 -7
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -29
  47. package/src/__tests__/contacts-tools.test.ts +63 -2
  48. package/src/__tests__/context-overflow-approval.test.ts +141 -0
  49. package/src/__tests__/context-overflow-policy.test.ts +171 -0
  50. package/src/__tests__/context-overflow-reducer.test.ts +533 -0
  51. package/src/__tests__/context-window-manager.test.ts +97 -0
  52. package/src/__tests__/conversation-attention-telegram.test.ts +38 -46
  53. package/src/__tests__/conversation-pairing.test.ts +2 -2
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +214 -10
  55. package/src/__tests__/conversation-routes.test.ts +4 -7
  56. package/src/__tests__/credential-broker-browser-fill.test.ts +13 -2
  57. package/src/__tests__/credential-security-e2e.test.ts +1 -1
  58. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  59. package/src/__tests__/credential-vault-unit.test.ts +1 -1
  60. package/src/__tests__/credential-vault.test.ts +11 -8
  61. package/src/__tests__/daemon-lifecycle.test.ts +2 -2
  62. package/src/__tests__/daemon-server-session-init.test.ts +6 -6
  63. package/src/__tests__/delete-managed-skill-tool.test.ts +1 -1
  64. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -2
  65. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +9 -0
  66. package/src/__tests__/emit-signal-routing-intent.test.ts +4 -0
  67. package/src/__tests__/encrypted-store.test.ts +10 -7
  68. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  69. package/src/__tests__/file-edit-tool.test.ts +1 -1
  70. package/src/__tests__/file-read-tool.test.ts +1 -1
  71. package/src/__tests__/file-write-tool.test.ts +1 -1
  72. package/src/__tests__/fixtures/credential-security-fixtures.ts +87 -64
  73. package/src/__tests__/fixtures/media-reuse-fixtures.ts +37 -31
  74. package/src/__tests__/fixtures/mock-signup-server.ts +171 -115
  75. package/src/__tests__/fixtures/proxy-fixtures.ts +39 -39
  76. package/src/__tests__/followup-tools.test.ts +1 -1
  77. package/src/__tests__/gateway-only-guard.test.ts +4 -0
  78. package/src/__tests__/gemini-image-service.test.ts +2 -2
  79. package/src/__tests__/guardian-actions-endpoint.test.ts +543 -1
  80. package/src/__tests__/guardian-control-plane-policy.test.ts +15 -15
  81. package/src/__tests__/guardian-dispatch.test.ts +79 -1
  82. package/src/__tests__/guardian-grant-minting.test.ts +20 -20
  83. package/src/__tests__/guardian-outbound-http.test.ts +1 -2
  84. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -41
  85. package/src/__tests__/guardian-routing-invariants.test.ts +36 -16
  86. package/src/__tests__/guardian-routing-state.test.ts +36 -52
  87. package/src/__tests__/guardian-verification-intent-routing.test.ts +4 -6
  88. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +6 -8
  89. package/src/__tests__/handle-user-message-secret-resume.test.ts +39 -1
  90. package/src/__tests__/handlers-cu-observation-blob.test.ts +21 -10
  91. package/src/__tests__/handlers-telegram-config.test.ts +14 -14
  92. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +23 -2
  93. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  94. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  95. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  96. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  97. package/src/__tests__/heartbeat-service.test.ts +45 -2
  98. package/src/__tests__/host-file-edit-tool.test.ts +1 -1
  99. package/src/__tests__/host-file-read-tool.test.ts +1 -1
  100. package/src/__tests__/host-file-write-tool.test.ts +1 -1
  101. package/src/__tests__/host-shell-tool.test.ts +1 -1
  102. package/src/__tests__/inbound-invite-redemption.test.ts +17 -19
  103. package/src/__tests__/ingress-reconcile.test.ts +2 -2
  104. package/src/__tests__/integrations-cli.test.ts +232 -0
  105. package/src/__tests__/intent-routing.test.ts +7 -5
  106. package/src/__tests__/invite-redemption-service.test.ts +5 -4
  107. package/src/__tests__/{ingress-routes-http.test.ts → invite-routes-http.test.ts} +42 -321
  108. package/src/__tests__/ipc-snapshot.test.ts +32 -31
  109. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  110. package/src/__tests__/mcp-cli.test.ts +136 -57
  111. package/src/__tests__/mcp-client-auth.test.ts +95 -0
  112. package/src/__tests__/media-generate-image.test.ts +2 -2
  113. package/src/__tests__/media-reuse-story.e2e.test.ts +8 -8
  114. package/src/__tests__/memory-regressions.test.ts +6 -6
  115. package/src/__tests__/messaging-send-tool.test.ts +1 -1
  116. package/src/__tests__/migration-cross-version-compatibility.test.ts +1855 -0
  117. package/src/__tests__/migration-export-http.test.ts +540 -0
  118. package/src/__tests__/migration-import-commit-http.test.ts +823 -0
  119. package/src/__tests__/migration-import-preflight-http.test.ts +755 -0
  120. package/src/__tests__/migration-parity-persistence.test.ts +1854 -0
  121. package/src/__tests__/migration-transport.test.ts +904 -0
  122. package/src/__tests__/migration-validate-http.test.ts +698 -0
  123. package/src/__tests__/migration-wizard.test.ts +1289 -0
  124. package/src/__tests__/nl-approval-parser.test.ts +305 -0
  125. package/src/__tests__/non-member-access-request.test.ts +17 -17
  126. package/src/__tests__/notification-decision-strategy.test.ts +110 -2
  127. package/src/__tests__/notification-deep-link.test.ts +18 -0
  128. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  129. package/src/__tests__/oauth-provider-profiles.test.ts +34 -0
  130. package/src/__tests__/oauth2-gateway-transport.test.ts +1 -1
  131. package/src/__tests__/playbook-execution.test.ts +1 -1
  132. package/src/__tests__/playbook-tools.test.ts +1 -1
  133. package/src/__tests__/provider-error-scenarios.test.ts +68 -0
  134. package/src/__tests__/provider-streaming.benchmark.test.ts +3 -1
  135. package/src/__tests__/proxy-approval-callback.test.ts +1 -1
  136. package/src/__tests__/qdrant-manager.test.ts +40 -11
  137. package/src/__tests__/rebind-secrets-screen.test.ts +839 -0
  138. package/src/__tests__/recording-handler.test.ts +2 -2
  139. package/src/__tests__/recording-intent-handler.test.ts +3 -3
  140. package/src/__tests__/recording-state-machine.test.ts +2 -2
  141. package/src/__tests__/relay-server.test.ts +507 -228
  142. package/src/__tests__/reminder-store.test.ts +8 -0
  143. package/src/__tests__/reminder.test.ts +8 -0
  144. package/src/__tests__/{resolve-guardian-trust-class.test.ts → resolve-trust-class.test.ts} +11 -17
  145. package/src/__tests__/retry-after-extraction.test.ts +111 -0
  146. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  147. package/src/__tests__/schedule-tools.test.ts +1 -1
  148. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  149. package/src/__tests__/script-proxy-connect-tunnel.test.ts +2 -3
  150. package/src/__tests__/script-proxy-decision-trace.test.ts +2 -2
  151. package/src/__tests__/script-proxy-http-forwarder.test.ts +1 -1
  152. package/src/__tests__/script-proxy-injection-runtime.test.ts +5 -5
  153. package/src/__tests__/script-proxy-mitm-handler.test.ts +4 -4
  154. package/src/__tests__/script-proxy-policy-runtime.test.ts +2 -2
  155. package/src/__tests__/script-proxy-policy.test.ts +2 -2
  156. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +127 -0
  157. package/src/__tests__/script-proxy-session-manager.test.ts +4 -7
  158. package/src/__tests__/script-proxy-session-runtime.test.ts +1 -6
  159. package/src/__tests__/secret-onetime-send.test.ts +4 -4
  160. package/src/__tests__/secret-scanner-executor.test.ts +2 -2
  161. package/src/__tests__/send-endpoint-busy.test.ts +11 -9
  162. package/src/__tests__/send-notification-tool.test.ts +2 -2
  163. package/src/__tests__/session-abort-tool-results.test.ts +17 -2
  164. package/src/__tests__/session-agent-loop.test.ts +456 -35
  165. package/src/__tests__/session-confirmation-signals.test.ts +3 -2
  166. package/src/__tests__/session-conflict-gate.test.ts +20 -3
  167. package/src/__tests__/session-init.benchmark.test.ts +2 -2
  168. package/src/__tests__/session-load-history-repair.test.ts +7 -7
  169. package/src/__tests__/session-media-retry.test.ts +147 -0
  170. package/src/__tests__/session-pre-run-repair.test.ts +17 -2
  171. package/src/__tests__/session-profile-injection.test.ts +20 -3
  172. package/src/__tests__/session-provider-retry-repair.test.ts +86 -6
  173. package/src/__tests__/session-queue.test.ts +33 -18
  174. package/src/__tests__/session-runtime-assembly.test.ts +147 -1
  175. package/src/__tests__/session-runtime-workspace.test.ts +40 -0
  176. package/src/__tests__/session-slash-known.test.ts +21 -3
  177. package/src/__tests__/session-slash-queue.test.ts +17 -2
  178. package/src/__tests__/session-slash-unknown.test.ts +17 -2
  179. package/src/__tests__/session-surfaces-deselection.test.ts +208 -0
  180. package/src/__tests__/session-workspace-cache-state.test.ts +2 -2
  181. package/src/__tests__/session-workspace-injection.test.ts +17 -2
  182. package/src/__tests__/session-workspace-tool-tracking.test.ts +17 -2
  183. package/src/__tests__/shell-credential-ref.test.ts +1 -1
  184. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  185. package/src/__tests__/skill-feature-flags-integration.test.ts +9 -5
  186. package/src/__tests__/skill-feature-flags.test.ts +18 -12
  187. package/src/__tests__/skill-load-feature-flag.test.ts +5 -4
  188. package/src/__tests__/skill-load-tool.test.ts +1 -1
  189. package/src/__tests__/skill-script-runner-host.test.ts +1 -1
  190. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -1
  191. package/src/__tests__/skill-script-runner.test.ts +1 -1
  192. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  193. package/src/__tests__/slack-block-formatting.test.ts +100 -0
  194. package/src/__tests__/slack-inbound-verification.test.ts +346 -0
  195. package/src/__tests__/slack-reaction-approvals.test.ts +77 -0
  196. package/src/__tests__/slack-skill.test.ts +4 -2
  197. package/src/__tests__/starter-task-flow.test.ts +0 -1
  198. package/src/__tests__/subagent-tools.test.ts +3 -3
  199. package/src/__tests__/swarm-recursion.test.ts +1 -1
  200. package/src/__tests__/swarm-session-integration.test.ts +1 -1
  201. package/src/__tests__/swarm-tool.test.ts +1 -1
  202. package/src/__tests__/task-management-tools.test.ts +1 -1
  203. package/src/__tests__/task-tools.test.ts +1 -1
  204. package/src/__tests__/terminal-tools.test.ts +1 -1
  205. package/src/__tests__/test-support/browser-skill-harness.ts +39 -27
  206. package/src/__tests__/test-support/computer-use-skill-harness.ts +14 -14
  207. package/src/__tests__/tool-approval-handler.test.ts +15 -15
  208. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  209. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  210. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  211. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  212. package/src/__tests__/tool-executor.test.ts +23 -182
  213. package/src/__tests__/tool-grant-request-escalation.test.ts +11 -11
  214. package/src/__tests__/tool-permission-simulate-handler.test.ts +4 -4
  215. package/src/__tests__/transfer-progress-screen.test.ts +1180 -0
  216. package/src/__tests__/trust-context-guards.test.ts +25 -29
  217. package/src/__tests__/trusted-contact-approval-notifier.test.ts +23 -21
  218. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +37 -40
  219. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +29 -25
  220. package/src/__tests__/trusted-contact-multichannel.test.ts +25 -24
  221. package/src/__tests__/trusted-contact-verification.test.ts +64 -76
  222. package/src/__tests__/turn-commit.test.ts +18 -18
  223. package/src/__tests__/twilio-provider.test.ts +7 -7
  224. package/src/__tests__/validation-results-screen.test.ts +1107 -0
  225. package/src/__tests__/view-image-tool.test.ts +1 -1
  226. package/src/__tests__/voice-invite-redemption.test.ts +4 -3
  227. package/src/__tests__/voice-scoped-grant-consumer.test.ts +12 -12
  228. package/src/__tests__/voice-session-bridge.test.ts +24 -24
  229. package/src/agent/attachments.ts +3 -1
  230. package/src/agent/loop.ts +13 -13
  231. package/src/agent/message-types.ts +13 -7
  232. package/src/amazon/cart.ts +59 -32
  233. package/src/amazon/checkout.ts +25 -14
  234. package/src/amazon/client.ts +61 -58
  235. package/src/amazon/product-details.ts +3 -3
  236. package/src/amazon/request-extractor.ts +46 -31
  237. package/src/amazon/search.ts +6 -4
  238. package/src/amazon/session.ts +33 -24
  239. package/src/approvals/AGENTS.md +26 -0
  240. package/src/approvals/approval-primitive.ts +87 -64
  241. package/src/approvals/guardian-decision-primitive.ts +172 -81
  242. package/src/approvals/guardian-request-resolvers.ts +262 -155
  243. package/src/autonomy/autonomy-resolver.ts +7 -5
  244. package/src/autonomy/autonomy-store.ts +34 -19
  245. package/src/autonomy/disposition-mapper.ts +5 -5
  246. package/src/autonomy/index.ts +6 -6
  247. package/src/autonomy/types.ts +7 -3
  248. package/src/browser-extension-relay/client.ts +50 -19
  249. package/src/browser-extension-relay/protocol.ts +11 -11
  250. package/src/browser-extension-relay/server.ts +45 -20
  251. package/src/bundler/app-bundler.ts +75 -50
  252. package/src/bundler/bundle-scanner.ts +145 -41
  253. package/src/bundler/bundle-signer.ts +16 -14
  254. package/src/bundler/signature-verifier.ts +36 -33
  255. package/src/calls/call-constants.ts +10 -3
  256. package/src/calls/call-controller.ts +473 -214
  257. package/src/calls/call-conversation-messages.ts +25 -15
  258. package/src/calls/call-domain.ts +401 -148
  259. package/src/calls/call-pointer-message-composer.ts +26 -21
  260. package/src/calls/call-pointer-messages.ts +52 -28
  261. package/src/calls/call-recovery.ts +53 -37
  262. package/src/calls/call-state-machine.ts +37 -7
  263. package/src/calls/call-state.ts +35 -13
  264. package/src/calls/call-store.ts +165 -77
  265. package/src/calls/elevenlabs-client.ts +39 -20
  266. package/src/calls/guardian-action-sweep.ts +42 -24
  267. package/src/calls/guardian-dispatch.ts +79 -56
  268. package/src/calls/guardian-question-copy.ts +28 -23
  269. package/src/calls/relay-server.ts +1149 -532
  270. package/src/calls/speaker-identification.ts +21 -15
  271. package/src/calls/twilio-config.ts +34 -17
  272. package/src/calls/twilio-provider.ts +108 -55
  273. package/src/calls/twilio-rest.ts +212 -100
  274. package/src/calls/twilio-routes.ts +165 -92
  275. package/src/calls/types.ts +55 -7
  276. package/src/calls/voice-quality.ts +6 -4
  277. package/src/calls/voice-session-bridge.ts +181 -133
  278. package/src/channels/config.ts +18 -14
  279. package/src/channels/types.ts +38 -10
  280. package/src/cli/amazon.ts +333 -227
  281. package/src/cli/config-commands.ts +236 -146
  282. package/src/cli/core-commands.ts +403 -329
  283. package/src/cli/email-guardrails.ts +38 -19
  284. package/src/cli/email.ts +207 -153
  285. package/src/cli/influencer.ts +58 -56
  286. package/src/cli/integrations.ts +306 -0
  287. package/src/cli/ipc-client.ts +24 -19
  288. package/src/cli/map.ts +176 -129
  289. package/src/cli/mcp.ts +260 -152
  290. package/src/cli/sequence.ts +165 -107
  291. package/src/cli/twitter.ts +302 -218
  292. package/src/cli.ts +418 -279
  293. package/src/commands/cc-command-registry.ts +52 -27
  294. package/src/config/agent-schema.ts +217 -134
  295. package/src/config/assistant-feature-flags.ts +23 -18
  296. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +19 -0
  297. package/src/config/bundled-skills/app-builder/SKILL.md +193 -1500
  298. package/src/config/bundled-skills/app-builder/TOOLS.json +70 -18
  299. package/src/config/bundled-skills/app-builder/tools/app-create.ts +7 -4
  300. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +6 -3
  301. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +7 -4
  302. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +6 -3
  303. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +6 -3
  304. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +7 -4
  305. package/src/config/bundled-skills/app-builder/tools/app-list.ts +6 -3
  306. package/src/config/bundled-skills/app-builder/tools/app-query.ts +6 -3
  307. package/src/config/bundled-skills/app-builder/tools/app-update.ts +6 -3
  308. package/src/config/bundled-skills/browser/TOOLS.json +59 -2
  309. package/src/config/bundled-skills/browser/tools/browser-click.ts +5 -2
  310. package/src/config/bundled-skills/browser/tools/browser-close.ts +5 -2
  311. package/src/config/bundled-skills/browser/tools/browser-extract.ts +5 -2
  312. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +5 -2
  313. package/src/config/bundled-skills/browser/tools/browser-hover.ts +5 -2
  314. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +5 -2
  315. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +5 -2
  316. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +5 -2
  317. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +5 -2
  318. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +5 -2
  319. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +5 -2
  320. package/src/config/bundled-skills/browser/tools/browser-type.ts +5 -2
  321. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +13 -6
  322. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +5 -2
  323. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +4 -0
  324. package/src/config/bundled-skills/claude-code/TOOLS.json +4 -0
  325. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +5 -2
  326. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  327. package/src/config/bundled-skills/computer-use/TOOLS.json +50 -2
  328. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +6 -3
  329. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +6 -3
  330. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +10 -3
  331. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +6 -3
  332. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +6 -3
  333. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +6 -3
  334. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +10 -3
  335. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +6 -3
  336. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +10 -3
  337. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +10 -3
  338. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +6 -3
  339. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +6 -3
  340. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +6 -3
  341. package/src/config/bundled-skills/configure-settings/SKILL.md +28 -14
  342. package/src/config/bundled-skills/contacts/SKILL.md +453 -15
  343. package/src/config/bundled-skills/contacts/TOOLS.json +22 -2
  344. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +79 -20
  345. package/src/config/bundled-skills/contacts/tools/contact-search.ts +55 -18
  346. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +64 -19
  347. package/src/config/bundled-skills/document/TOOLS.json +8 -0
  348. package/src/config/bundled-skills/document/tools/document-create.ts +5 -2
  349. package/src/config/bundled-skills/document/tools/document-update.ts +5 -2
  350. package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -7
  351. package/src/config/bundled-skills/email-setup/SKILL.md +12 -9
  352. package/src/config/bundled-skills/followups/TOOLS.json +12 -0
  353. package/src/config/bundled-skills/followups/tools/followup-create.ts +5 -2
  354. package/src/config/bundled-skills/followups/tools/followup-list.ts +5 -2
  355. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +5 -2
  356. package/src/config/bundled-skills/google-calendar/TOOLS.json +124 -26
  357. package/src/config/bundled-skills/google-calendar/calendar-client.ts +44 -32
  358. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +11 -5
  359. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +13 -7
  360. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +11 -5
  361. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +13 -7
  362. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +28 -12
  363. package/src/config/bundled-skills/google-calendar/tools/shared.ts +6 -4
  364. package/src/config/bundled-skills/google-calendar/types.ts +3 -3
  365. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +88 -33
  366. package/src/config/bundled-skills/image-studio/TOOLS.json +12 -2
  367. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +48 -25
  368. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +13 -3
  369. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +60 -35
  370. package/src/config/bundled-skills/mcp-setup/SKILL.md +75 -0
  371. package/src/config/bundled-skills/media-processing/SKILL.md +55 -15
  372. package/src/config/bundled-skills/media-processing/TOOLS.json +48 -2
  373. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +12 -10
  374. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +34 -19
  375. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +82 -66
  376. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +148 -0
  377. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +1 -1
  378. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +8 -3
  379. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +117 -53
  380. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +273 -0
  381. package/src/config/bundled-skills/media-processing/services/preprocess.ts +185 -97
  382. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +32 -27
  383. package/src/config/bundled-skills/media-processing/services/reduce.ts +101 -24
  384. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +121 -55
  385. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +58 -24
  386. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +198 -92
  387. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +98 -70
  388. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +59 -19
  389. package/src/config/bundled-skills/media-processing/tools/media-status.ts +26 -10
  390. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +29 -14
  391. package/src/config/bundled-skills/messaging/SKILL.md +7 -5
  392. package/src/config/bundled-skills/messaging/TOOLS.json +232 -186
  393. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +31 -13
  394. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +16 -10
  395. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +18 -9
  396. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +23 -16
  397. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +28 -12
  398. package/src/config/bundled-skills/messaging/tools/gmail-filters.ts +41 -21
  399. package/src/config/bundled-skills/messaging/tools/gmail-follow-up.ts +44 -23
  400. package/src/config/bundled-skills/messaging/tools/gmail-forward.ts +73 -33
  401. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +15 -9
  402. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +22 -14
  403. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +99 -50
  404. package/src/config/bundled-skills/messaging/tools/gmail-send-draft.ts +14 -8
  405. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +63 -44
  406. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +90 -46
  407. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +43 -22
  408. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +15 -9
  409. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +51 -22
  410. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +62 -26
  411. package/src/config/bundled-skills/messaging/tools/gmail-vacation.ts +34 -19
  412. package/src/config/bundled-skills/messaging/tools/google-contacts.ts +32 -16
  413. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +10 -4
  414. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +91 -47
  415. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +21 -9
  416. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +9 -3
  417. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +30 -17
  418. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +10 -4
  419. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +14 -6
  420. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +16 -5
  421. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +63 -36
  422. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +10 -4
  423. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +30 -12
  424. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +48 -29
  425. package/src/config/bundled-skills/messaging/tools/scan-result-store.ts +20 -6
  426. package/src/config/bundled-skills/messaging/tools/send-notification.ts +1 -1
  427. package/src/config/bundled-skills/messaging/tools/sequence-analytics.ts +59 -22
  428. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +13 -7
  429. package/src/config/bundled-skills/messaging/tools/sequence-create.ts +27 -12
  430. package/src/config/bundled-skills/messaging/tools/sequence-delete.ts +14 -6
  431. package/src/config/bundled-skills/messaging/tools/sequence-enroll.ts +30 -11
  432. package/src/config/bundled-skills/messaging/tools/sequence-enrollment-list.ts +16 -8
  433. package/src/config/bundled-skills/messaging/tools/sequence-get.ts +31 -13
  434. package/src/config/bundled-skills/messaging/tools/sequence-import.ts +38 -22
  435. package/src/config/bundled-skills/messaging/tools/sequence-list.ts +16 -7
  436. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +29 -10
  437. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +16 -8
  438. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +35 -16
  439. package/src/config/bundled-skills/messaging/tools/shared.ts +26 -12
  440. package/src/config/bundled-skills/notifications/SKILL.md +3 -2
  441. package/src/config/bundled-skills/notifications/TOOLS.json +7 -13
  442. package/src/config/bundled-skills/notifications/tools/send-notification.ts +69 -34
  443. package/src/config/bundled-skills/notifications/tools/shared.ts +1 -1
  444. package/src/config/bundled-skills/phone-calls/SKILL.md +46 -48
  445. package/src/config/bundled-skills/phone-calls/TOOLS.json +13 -1
  446. package/src/config/bundled-skills/phone-calls/tools/call-end.ts +1 -1
  447. package/src/config/bundled-skills/phone-calls/tools/call-start.ts +1 -1
  448. package/src/config/bundled-skills/phone-calls/tools/call-status.ts +1 -1
  449. package/src/config/bundled-skills/playbooks/TOOLS.json +16 -0
  450. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +91 -51
  451. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +30 -16
  452. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +66 -27
  453. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +89 -42
  454. package/src/config/bundled-skills/public-ingress/SKILL.md +26 -19
  455. package/src/config/bundled-skills/reminder/TOOLS.json +15 -2
  456. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +5 -2
  457. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +5 -2
  458. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +5 -2
  459. package/src/config/bundled-skills/schedule/SKILL.md +33 -15
  460. package/src/config/bundled-skills/schedule/TOOLS.json +17 -1
  461. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +5 -2
  462. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +5 -2
  463. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +5 -2
  464. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +5 -2
  465. package/src/config/bundled-skills/screen-recording/SKILL.md +11 -3
  466. package/src/config/bundled-skills/self-upgrade/SKILL.md +9 -8
  467. package/src/config/bundled-skills/slack/SKILL.md +30 -1
  468. package/src/config/bundled-skills/slack/TOOLS.json +122 -17
  469. package/src/config/bundled-skills/slack/tools/shared.ts +7 -5
  470. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +11 -5
  471. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +11 -5
  472. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +146 -0
  473. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +46 -16
  474. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +11 -5
  475. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +28 -0
  476. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +12 -6
  477. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +120 -0
  478. package/src/config/bundled-skills/slack-app-setup/SKILL.md +200 -0
  479. package/src/config/bundled-skills/sms-setup/SKILL.md +5 -8
  480. package/src/config/bundled-skills/subagent/TOOLS.json +22 -2
  481. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +5 -2
  482. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +5 -2
  483. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +5 -2
  484. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +5 -2
  485. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +5 -2
  486. package/src/config/bundled-skills/tasks/TOOLS.json +86 -14
  487. package/src/config/bundled-skills/tasks/tools/task-delete.ts +5 -2
  488. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +5 -2
  489. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +5 -2
  490. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +5 -2
  491. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +5 -2
  492. package/src/config/bundled-skills/tasks/tools/task-list.ts +5 -2
  493. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +5 -2
  494. package/src/config/bundled-skills/tasks/tools/task-run.ts +5 -2
  495. package/src/config/bundled-skills/tasks/tools/task-save.ts +5 -2
  496. package/src/config/bundled-skills/telegram-setup/SKILL.md +7 -8
  497. package/src/config/bundled-skills/transcribe/TOOLS.json +4 -0
  498. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +232 -127
  499. package/src/config/bundled-skills/twilio-setup/SKILL.md +7 -12
  500. package/src/config/bundled-skills/twitter/SKILL.md +19 -2
  501. package/src/config/bundled-skills/voice-setup/SKILL.md +5 -5
  502. package/src/config/bundled-skills/watcher/TOOLS.json +20 -0
  503. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +5 -2
  504. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +5 -2
  505. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +5 -2
  506. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +5 -2
  507. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +5 -2
  508. package/src/config/bundled-skills/weather/TOOLS.json +4 -0
  509. package/src/config/bundled-skills/weather/tools/get-weather.ts +5 -2
  510. package/src/config/bundled-tool-registry.ts +2 -0
  511. package/src/config/calls-schema.ts +108 -63
  512. package/src/config/channel-permission-profiles.ts +155 -0
  513. package/src/config/computer-use-prompt.ts +7 -7
  514. package/src/config/core-schema.ts +239 -155
  515. package/src/config/defaults.ts +2 -2
  516. package/src/config/elevenlabs-schema.ts +15 -15
  517. package/src/config/env-registry.ts +33 -33
  518. package/src/config/env.ts +4 -1
  519. package/src/config/feature-flag-registry.json +31 -7
  520. package/src/config/loader.ts +118 -58
  521. package/src/config/mcp-schema.ts +29 -15
  522. package/src/config/memory-schema.ts +434 -229
  523. package/src/config/notifications-schema.ts +4 -4
  524. package/src/config/sandbox-schema.ts +2 -2
  525. package/src/config/schema.ts +12 -2
  526. package/src/config/skill-state.ts +27 -15
  527. package/src/config/skills-schema.ts +72 -23
  528. package/src/config/skills.ts +303 -143
  529. package/src/config/system-prompt.ts +25 -6
  530. package/src/config/types.ts +1 -1
  531. package/src/config/update-bulletin-format.ts +3 -3
  532. package/src/config/update-bulletin-state.ts +15 -6
  533. package/src/config/update-bulletin-template-path.ts +8 -4
  534. package/src/config/update-bulletin.ts +33 -14
  535. package/src/config/user-reference.ts +8 -8
  536. package/src/contacts/contact-events.ts +21 -0
  537. package/src/contacts/contact-store.ts +813 -100
  538. package/src/contacts/contacts-write.ts +287 -0
  539. package/src/contacts/index.ts +13 -4
  540. package/src/contacts/startup-migration.ts +21 -0
  541. package/src/contacts/types.ts +73 -2
  542. package/src/context/token-estimator.ts +54 -31
  543. package/src/context/tool-result-truncation.ts +41 -7
  544. package/src/context/window-manager.ts +225 -120
  545. package/src/daemon/approval-generators.ts +83 -55
  546. package/src/daemon/approved-devices-store.ts +33 -20
  547. package/src/daemon/assistant-attachments.ts +157 -101
  548. package/src/daemon/auth-manager.ts +17 -15
  549. package/src/daemon/classifier.ts +117 -46
  550. package/src/daemon/computer-use-session.ts +316 -187
  551. package/src/daemon/config-watcher.ts +91 -44
  552. package/src/daemon/connection-policy.ts +18 -10
  553. package/src/daemon/context-overflow-approval.ts +48 -0
  554. package/src/daemon/context-overflow-policy.ts +50 -0
  555. package/src/daemon/context-overflow-reducer.ts +300 -0
  556. package/src/daemon/daemon-control.ts +79 -51
  557. package/src/daemon/date-context.ts +119 -69
  558. package/src/daemon/dictation-profile-store.ts +94 -48
  559. package/src/daemon/dictation-text-processing.ts +33 -12
  560. package/src/daemon/doordash-steps.ts +92 -49
  561. package/src/daemon/guardian-action-generators.ts +62 -46
  562. package/src/daemon/guardian-verification-intent.ts +35 -19
  563. package/src/daemon/handlers/apps.ts +258 -113
  564. package/src/daemon/handlers/avatar.ts +20 -15
  565. package/src/daemon/handlers/computer-use.ts +82 -39
  566. package/src/daemon/handlers/config-channels.ts +146 -69
  567. package/src/daemon/handlers/config-heartbeat.ts +114 -59
  568. package/src/daemon/handlers/config-inbox.ts +213 -160
  569. package/src/daemon/handlers/config-ingress.ts +127 -55
  570. package/src/daemon/handlers/config-integrations.ts +145 -88
  571. package/src/daemon/handlers/config-model.ts +58 -22
  572. package/src/daemon/handlers/config-platform.ts +40 -16
  573. package/src/daemon/handlers/config-scheduling.ts +109 -48
  574. package/src/daemon/handlers/config-slack-channel.ts +67 -35
  575. package/src/daemon/handlers/config-slack.ts +21 -20
  576. package/src/daemon/handlers/config-telegram.ts +100 -70
  577. package/src/daemon/handlers/config-tools.ts +103 -55
  578. package/src/daemon/handlers/config-trust.ts +50 -20
  579. package/src/daemon/handlers/config.ts +72 -24
  580. package/src/daemon/handlers/contacts.ts +163 -0
  581. package/src/daemon/handlers/diagnostics.ts +90 -48
  582. package/src/daemon/handlers/documents.ts +74 -46
  583. package/src/daemon/handlers/guardian-actions.ts +57 -77
  584. package/src/daemon/handlers/home-base.ts +19 -16
  585. package/src/daemon/handlers/identity.ts +65 -45
  586. package/src/daemon/handlers/index.ts +78 -54
  587. package/src/daemon/handlers/misc.ts +664 -234
  588. package/src/daemon/handlers/navigate-settings.ts +14 -11
  589. package/src/daemon/handlers/oauth-connect.ts +48 -35
  590. package/src/daemon/handlers/open-bundle-handler.ts +31 -24
  591. package/src/daemon/handlers/pairing.ts +51 -25
  592. package/src/daemon/handlers/publish.ts +55 -33
  593. package/src/daemon/handlers/recording.ts +378 -162
  594. package/src/daemon/handlers/sessions.ts +922 -423
  595. package/src/daemon/handlers/shared.ts +202 -117
  596. package/src/daemon/handlers/signing.ts +25 -6
  597. package/src/daemon/handlers/subagents.ts +117 -56
  598. package/src/daemon/handlers/twitter-auth.ts +70 -49
  599. package/src/daemon/handlers/work-items.ts +264 -112
  600. package/src/daemon/handlers/workspace-files.ts +27 -20
  601. package/src/daemon/handlers.ts +2 -2
  602. package/src/daemon/history-repair.ts +16 -15
  603. package/src/daemon/identity-helpers.ts +4 -4
  604. package/src/daemon/install-cli-launchers.ts +33 -22
  605. package/src/daemon/ipc-blob-store.ts +38 -24
  606. package/src/daemon/ipc-contract/apps.ts +61 -50
  607. package/src/daemon/ipc-contract/computer-use.ts +47 -37
  608. package/src/daemon/ipc-contract/contacts.ts +69 -0
  609. package/src/daemon/ipc-contract/diagnostics.ts +14 -14
  610. package/src/daemon/ipc-contract/documents.ts +8 -8
  611. package/src/daemon/ipc-contract/guardian-actions.ts +4 -4
  612. package/src/daemon/ipc-contract/inbox.ts +12 -71
  613. package/src/daemon/ipc-contract/integrations.ts +57 -44
  614. package/src/daemon/ipc-contract/memory.ts +3 -5
  615. package/src/daemon/ipc-contract/messages.ts +95 -69
  616. package/src/daemon/ipc-contract/notifications.ts +10 -6
  617. package/src/daemon/ipc-contract/pairing.ts +8 -8
  618. package/src/daemon/ipc-contract/schedules.ts +20 -20
  619. package/src/daemon/ipc-contract/sessions.ts +89 -57
  620. package/src/daemon/ipc-contract/settings.ts +12 -7
  621. package/src/daemon/ipc-contract/shared.ts +9 -7
  622. package/src/daemon/ipc-contract/skills.ts +46 -26
  623. package/src/daemon/ipc-contract/subagents.ts +9 -9
  624. package/src/daemon/ipc-contract/surfaces.ts +0 -1
  625. package/src/daemon/ipc-contract/trust.ts +11 -11
  626. package/src/daemon/ipc-contract/work-items.ts +33 -28
  627. package/src/daemon/ipc-contract/workspace.ts +28 -21
  628. package/src/daemon/ipc-contract-inventory.json +10 -4
  629. package/src/daemon/ipc-contract-inventory.ts +29 -26
  630. package/src/daemon/ipc-contract.ts +111 -44
  631. package/src/daemon/ipc-handler.ts +27 -19
  632. package/src/daemon/ipc-protocol.ts +22 -12
  633. package/src/daemon/ipc-validate.ts +91 -46
  634. package/src/daemon/lifecycle.ts +39 -3
  635. package/src/daemon/main.ts +10 -8
  636. package/src/daemon/media-visibility-policy.ts +3 -1
  637. package/src/daemon/pairing-store.ts +72 -40
  638. package/src/daemon/providers-setup.ts +35 -25
  639. package/src/daemon/recording-executor.ts +37 -30
  640. package/src/daemon/recording-intent-fallback.ts +58 -28
  641. package/src/daemon/recording-intent.ts +71 -61
  642. package/src/daemon/ride-shotgun-handler.ts +201 -121
  643. package/src/daemon/seed-files.ts +28 -17
  644. package/src/daemon/server.ts +23 -14
  645. package/src/daemon/session-agent-loop-handlers.ts +270 -135
  646. package/src/daemon/session-agent-loop.ts +796 -253
  647. package/src/daemon/session-attachments.ts +109 -40
  648. package/src/daemon/session-conflict-gate.ts +72 -28
  649. package/src/daemon/session-dynamic-profile.ts +36 -22
  650. package/src/daemon/session-error.ts +68 -45
  651. package/src/daemon/session-evictor.ts +17 -10
  652. package/src/daemon/session-history.ts +201 -89
  653. package/src/daemon/session-lifecycle.ts +80 -44
  654. package/src/daemon/session-media-retry.ts +104 -42
  655. package/src/daemon/session-memory.ts +77 -55
  656. package/src/daemon/session-messaging.ts +261 -111
  657. package/src/daemon/session-notifiers.ts +57 -45
  658. package/src/daemon/session-process.ts +370 -154
  659. package/src/daemon/session-queue-manager.ts +30 -13
  660. package/src/daemon/session-runtime-assembly.ts +61 -15
  661. package/src/daemon/session-skill-tools.ts +84 -36
  662. package/src/daemon/session-slash.ts +178 -113
  663. package/src/daemon/session-surfaces.ts +498 -212
  664. package/src/daemon/session-tool-setup.ts +24 -16
  665. package/src/daemon/session-usage.ts +26 -13
  666. package/src/daemon/session-workspace.ts +7 -4
  667. package/src/daemon/session.ts +18 -19
  668. package/src/daemon/shutdown-handlers.ts +36 -33
  669. package/src/daemon/tls-certs.ts +90 -57
  670. package/src/daemon/tool-side-effects.ts +97 -65
  671. package/src/daemon/trace-emitter.ts +8 -7
  672. package/src/daemon/video-thumbnail.ts +55 -25
  673. package/src/daemon/watch-handler.ts +164 -86
  674. package/src/email/provider.ts +1 -1
  675. package/src/email/providers/agentmail.ts +87 -45
  676. package/src/email/providers/index.ts +19 -14
  677. package/src/email/service.ts +52 -24
  678. package/src/email/types.ts +2 -2
  679. package/src/errors.ts +1 -1
  680. package/src/events/bus.ts +30 -10
  681. package/src/events/domain-events.ts +20 -13
  682. package/src/events/index.ts +6 -6
  683. package/src/events/tool-audit-listener.ts +34 -20
  684. package/src/events/tool-domain-event-publisher.ts +22 -20
  685. package/src/events/tool-metrics-listener.ts +26 -21
  686. package/src/events/tool-notification-listener.ts +5 -5
  687. package/src/events/tool-profiling-listener.ts +33 -23
  688. package/src/events/tool-trace-listener.ts +70 -46
  689. package/src/export/formatter.ts +38 -32
  690. package/src/followups/followup-store.ts +43 -36
  691. package/src/followups/index.ts +2 -2
  692. package/src/followups/types.ts +1 -1
  693. package/src/gallery/default-gallery.ts +37 -34
  694. package/src/gallery/gallery-manifest.ts +9 -9
  695. package/src/heartbeat/heartbeat-service.ts +59 -37
  696. package/src/home-base/app-link-store.ts +14 -12
  697. package/src/home-base/bootstrap.ts +14 -8
  698. package/src/home-base/prebuilt/seed.ts +34 -26
  699. package/src/home-base/prebuilt-home-base-updater.ts +14 -8
  700. package/src/hooks/cli.ts +56 -43
  701. package/src/hooks/config.ts +27 -14
  702. package/src/hooks/discovery.ts +53 -33
  703. package/src/hooks/manager.ts +50 -26
  704. package/src/hooks/runner.ts +35 -29
  705. package/src/hooks/templates.ts +38 -15
  706. package/src/hooks/types.ts +13 -13
  707. package/src/inbound/platform-callback-registration.ts +21 -15
  708. package/src/inbound/public-ingress-urls.ts +9 -6
  709. package/src/index.ts +20 -19
  710. package/src/influencer/client.ts +261 -117
  711. package/src/instrument.ts +3 -1
  712. package/src/logfire.ts +64 -39
  713. package/src/mcp/client.ts +107 -55
  714. package/src/mcp/manager.ts +45 -18
  715. package/src/mcp/mcp-oauth-provider.ts +114 -62
  716. package/src/media/gemini-image-service.ts +75 -23
  717. package/src/memory/account-store.ts +16 -9
  718. package/src/memory/admin.ts +87 -57
  719. package/src/memory/app-git-service.ts +77 -47
  720. package/src/memory/app-store.ts +148 -78
  721. package/src/memory/attachments-store.ts +123 -53
  722. package/src/memory/canonical-guardian-store.ts +190 -48
  723. package/src/memory/channel-delivery-store.ts +5 -5
  724. package/src/memory/channel-guardian-store.ts +31 -16
  725. package/src/memory/checkpoints.ts +14 -7
  726. package/src/memory/clarification-resolver.ts +219 -104
  727. package/src/memory/conflict-intent.ts +74 -23
  728. package/src/memory/conflict-policy.ts +20 -7
  729. package/src/memory/conflict-store.ts +144 -94
  730. package/src/memory/contradiction-checker.ts +257 -132
  731. package/src/memory/conversation-attention-store.ts +74 -32
  732. package/src/memory/conversation-bootstrap.ts +28 -0
  733. package/src/memory/conversation-crud.ts +12 -5
  734. package/src/memory/conversation-display-order-migration.ts +7 -7
  735. package/src/memory/conversation-key-store.ts +18 -13
  736. package/src/memory/conversation-queries.ts +130 -52
  737. package/src/memory/conversation-store.ts +43 -26
  738. package/src/memory/conversation-title-service.ts +89 -66
  739. package/src/memory/db-init.ts +94 -2
  740. package/src/memory/db.ts +10 -3
  741. package/src/memory/delivery-channels.ts +12 -6
  742. package/src/memory/delivery-crud.ts +26 -12
  743. package/src/memory/delivery-status.ts +19 -16
  744. package/src/memory/embedding-backend.ts +205 -77
  745. package/src/memory/embedding-gemini.ts +23 -10
  746. package/src/memory/embedding-local.ts +89 -44
  747. package/src/memory/embedding-ollama.ts +25 -13
  748. package/src/memory/embedding-openai.ts +20 -11
  749. package/src/memory/embedding-runtime-manager.ts +163 -90
  750. package/src/memory/entity-extractor.ts +185 -123
  751. package/src/memory/external-conversation-store.ts +30 -12
  752. package/src/memory/fingerprint.ts +2 -2
  753. package/src/memory/fts-reconciler.ts +57 -28
  754. package/src/memory/guardian-action-store.ts +162 -100
  755. package/src/memory/guardian-approvals.ts +63 -129
  756. package/src/memory/guardian-rate-limits.ts +20 -9
  757. package/src/memory/guardian-verification.ts +82 -35
  758. package/src/memory/indexer.ts +96 -55
  759. package/src/memory/{ingress-invite-store.ts → invite-store.ts} +28 -169
  760. package/src/memory/items-extractor.ts +313 -157
  761. package/src/memory/job-handlers/backfill.ts +116 -63
  762. package/src/memory/job-handlers/cleanup.ts +64 -41
  763. package/src/memory/job-handlers/conflict.ts +90 -49
  764. package/src/memory/job-handlers/embedding.ts +32 -17
  765. package/src/memory/job-handlers/extraction.ts +58 -33
  766. package/src/memory/job-handlers/index-maintenance.ts +31 -17
  767. package/src/memory/job-handlers/media-processing.ts +65 -24
  768. package/src/memory/job-handlers/summarization.ts +186 -128
  769. package/src/memory/job-utils.ts +100 -57
  770. package/src/memory/jobs-store.ts +235 -142
  771. package/src/memory/jobs-worker.ts +167 -83
  772. package/src/memory/llm-request-log-store.ts +13 -11
  773. package/src/memory/llm-usage-store.ts +35 -26
  774. package/src/memory/media-store.ts +151 -44
  775. package/src/memory/message-content.ts +28 -18
  776. package/src/memory/migrations/001-job-deferrals.ts +11 -5
  777. package/src/memory/migrations/002-tool-invocations-fk.ts +14 -6
  778. package/src/memory/migrations/003-memory-fts-backfill.ts +11 -5
  779. package/src/memory/migrations/004-entity-relation-dedup.ts +17 -11
  780. package/src/memory/migrations/005-fingerprint-scope-unique.ts +36 -21
  781. package/src/memory/migrations/006-scope-salted-fingerprints.ts +35 -20
  782. package/src/memory/migrations/007-assistant-id-to-self.ts +40 -27
  783. package/src/memory/migrations/008-remove-assistant-id-columns.ts +58 -36
  784. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +36 -22
  785. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +21 -11
  786. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +30 -15
  787. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +4 -2
  788. package/src/memory/migrations/013-guardian-action-tables.ts +29 -11
  789. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +35 -21
  790. package/src/memory/migrations/015-drop-active-search-index.ts +17 -11
  791. package/src/memory/migrations/016-memory-segments-indexes.ts +7 -3
  792. package/src/memory/migrations/017-memory-items-indexes.ts +4 -2
  793. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -5
  794. package/src/memory/migrations/019-notification-tables-schema-migration.ts +34 -20
  795. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +87 -53
  796. package/src/memory/migrations/021-conversation-status-indexes.ts +7 -3
  797. package/src/memory/migrations/022-add-origin-interface.ts +4 -2
  798. package/src/memory/migrations/023-memory-item-sources-indexes.ts +4 -2
  799. package/src/memory/migrations/024-embedding-vector-blob.ts +34 -18
  800. package/src/memory/migrations/025-messages-fts-backfill.ts +11 -5
  801. package/src/memory/migrations/026-guardian-verification-sessions.ts +80 -14
  802. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +42 -26
  803. package/src/memory/migrations/027-notification-delivery-pairing-columns.ts +22 -8
  804. package/src/memory/migrations/027a-guardian-bootstrap-token.ts +11 -3
  805. package/src/memory/migrations/028-call-session-mode.ts +13 -3
  806. package/src/memory/migrations/028-notification-delivery-client-ack.ts +22 -8
  807. package/src/memory/migrations/029-channel-inbound-delivered-segments.ts +7 -3
  808. package/src/memory/migrations/030-guardian-action-followup.ts +46 -8
  809. package/src/memory/migrations/030-guardian-verification-purpose.ts +4 -2
  810. package/src/memory/migrations/031-conversations-thread-type-index.ts +4 -2
  811. package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +4 -2
  812. package/src/memory/migrations/032-notification-delivery-thread-decision.ts +22 -8
  813. package/src/memory/migrations/033-scoped-approval-grants.ts +1 -1
  814. package/src/memory/migrations/034-guardian-action-tool-metadata.ts +15 -3
  815. package/src/memory/migrations/035-guardian-action-supersession.ts +15 -3
  816. package/src/memory/migrations/036-normalize-phone-identities.ts +101 -87
  817. package/src/memory/migrations/037-voice-invite-columns.ts +22 -4
  818. package/src/memory/migrations/038-actor-token-records.ts +5 -9
  819. package/src/memory/migrations/039-actor-refresh-token-records.ts +7 -13
  820. package/src/memory/migrations/100-core-tables.ts +1 -1
  821. package/src/memory/migrations/101-watchers-and-logs.ts +1 -1
  822. package/src/memory/migrations/103-complex-migrations.ts +9 -9
  823. package/src/memory/migrations/104-core-indexes.ts +188 -64
  824. package/src/memory/migrations/105-contacts-and-triage.ts +28 -10
  825. package/src/memory/migrations/106-call-sessions.ts +58 -16
  826. package/src/memory/migrations/107-followups.ts +16 -6
  827. package/src/memory/migrations/108-tasks-and-work-items.ts +43 -11
  828. package/src/memory/migrations/109-external-conversation-bindings.ts +11 -5
  829. package/src/memory/migrations/110-channel-guardian.ts +48 -10
  830. package/src/memory/migrations/111-media-assets.ts +52 -18
  831. package/src/memory/migrations/112-assistant-inbox.ts +32 -12
  832. package/src/memory/migrations/113-late-migrations.ts +12 -12
  833. package/src/memory/migrations/114-notifications.ts +28 -12
  834. package/src/memory/migrations/115-sequences.ts +10 -4
  835. package/src/memory/migrations/116-messages-fts.ts +1 -1
  836. package/src/memory/migrations/117-conversation-attention.ts +16 -6
  837. package/src/memory/migrations/118-reminder-routing-intent.ts +7 -3
  838. package/src/memory/migrations/119-schema-indexes-and-columns.ts +35 -15
  839. package/src/memory/migrations/120-fk-cascade-rebuilds.ts +36 -17
  840. package/src/memory/migrations/121-canonical-guardian-requests.ts +25 -9
  841. package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +11 -3
  842. package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +4 -2
  843. package/src/memory/migrations/124-voice-invite-display-metadata.ts +15 -3
  844. package/src/memory/migrations/125-guardian-principal-id-columns.ts +22 -4
  845. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +174 -126
  846. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +58 -42
  847. package/src/memory/migrations/128-contacts-role-principal.ts +26 -0
  848. package/src/memory/migrations/129-contact-channels-access-fields.ts +105 -0
  849. package/src/memory/migrations/130-contact-channels-type-ext-chat-id-index.ts +15 -0
  850. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +134 -0
  851. package/src/memory/migrations/132-contacts-assistant-id.ts +21 -0
  852. package/src/memory/migrations/133-assistant-contact-metadata.ts +21 -0
  853. package/src/memory/migrations/index.ts +83 -73
  854. package/src/memory/migrations/registry.ts +53 -37
  855. package/src/memory/migrations/validate-migration-state.ts +73 -46
  856. package/src/memory/profile-compiler.ts +58 -24
  857. package/src/memory/published-pages-store.ts +12 -16
  858. package/src/memory/qdrant-circuit-breaker.ts +28 -20
  859. package/src/memory/qdrant-client.ts +99 -63
  860. package/src/memory/qdrant-manager.ts +89 -57
  861. package/src/memory/query-builder.ts +9 -7
  862. package/src/memory/raw-query.ts +63 -14
  863. package/src/memory/recall-cache.ts +15 -8
  864. package/src/memory/retrieval-budget.ts +0 -1
  865. package/src/memory/retriever.ts +385 -192
  866. package/src/memory/schema-migration.ts +1 -1
  867. package/src/memory/schema.ts +56 -56
  868. package/src/memory/scoped-approval-grants.ts +99 -45
  869. package/src/memory/search/entity.ts +102 -40
  870. package/src/memory/search/formatting.ts +70 -52
  871. package/src/memory/search/lexical.ts +82 -43
  872. package/src/memory/search/ranking.ts +103 -39
  873. package/src/memory/search/semantic.ts +59 -35
  874. package/src/memory/search/types.ts +8 -8
  875. package/src/memory/segmenter.ts +20 -12
  876. package/src/memory/shared-app-links-store.ts +21 -16
  877. package/src/memory/slack-thread-store.ts +187 -0
  878. package/src/memory/task-memory-cleanup.ts +18 -8
  879. package/src/memory/tool-usage-store.ts +27 -19
  880. package/src/memory/validation.ts +4 -2
  881. package/src/messaging/activity-analyzer.ts +7 -7
  882. package/src/messaging/draft-store.ts +13 -10
  883. package/src/messaging/email-classifier.ts +73 -37
  884. package/src/messaging/index.ts +3 -3
  885. package/src/messaging/outreach-classifier.ts +76 -38
  886. package/src/messaging/provider-types.ts +2 -4
  887. package/src/messaging/provider.ts +37 -8
  888. package/src/messaging/providers/gmail/adapter.ts +183 -66
  889. package/src/messaging/providers/gmail/client.ts +3 -1
  890. package/src/messaging/providers/gmail/mime-builder.ts +21 -19
  891. package/src/messaging/providers/gmail/people-client.ts +22 -9
  892. package/src/messaging/providers/gmail/types.ts +6 -6
  893. package/src/messaging/providers/slack/adapter.ts +93 -43
  894. package/src/messaging/providers/slack/client.ts +165 -48
  895. package/src/messaging/providers/slack/types.ts +10 -0
  896. package/src/messaging/providers/sms/adapter.ts +76 -40
  897. package/src/messaging/providers/sms/client.ts +4 -4
  898. package/src/messaging/providers/telegram-bot/adapter.ts +52 -30
  899. package/src/messaging/providers/telegram-bot/client.ts +7 -7
  900. package/src/messaging/providers/whatsapp/adapter.ts +58 -31
  901. package/src/messaging/providers/whatsapp/client.ts +4 -4
  902. package/src/messaging/registry.ts +9 -5
  903. package/src/messaging/style-analyzer.ts +69 -39
  904. package/src/messaging/thread-summarizer.ts +101 -53
  905. package/src/messaging/triage-engine.ts +111 -82
  906. package/src/messaging/types.ts +10 -10
  907. package/src/migrations/config-merge.ts +18 -10
  908. package/src/migrations/data-layout.ts +35 -22
  909. package/src/migrations/data-merge.ts +17 -7
  910. package/src/migrations/hooks-merge.ts +43 -16
  911. package/src/migrations/index.ts +6 -6
  912. package/src/migrations/log.ts +9 -5
  913. package/src/migrations/skills-merge.ts +17 -7
  914. package/src/migrations/workspace-layout.ts +39 -25
  915. package/src/notifications/AGENTS.md +5 -0
  916. package/src/notifications/adapters/macos.ts +21 -14
  917. package/src/notifications/adapters/slack.ts +90 -0
  918. package/src/notifications/adapters/sms.ts +28 -15
  919. package/src/notifications/adapters/telegram.ts +24 -15
  920. package/src/notifications/broadcaster.ts +108 -52
  921. package/src/notifications/conversation-pairing.ts +64 -29
  922. package/src/notifications/copy-composer.ts +165 -95
  923. package/src/notifications/decision-engine.ts +353 -147
  924. package/src/notifications/decisions-store.ts +26 -10
  925. package/src/notifications/deliveries-store.ts +23 -13
  926. package/src/notifications/destination-resolver.ts +83 -24
  927. package/src/notifications/deterministic-checks.ts +78 -27
  928. package/src/notifications/emit-signal.ts +95 -41
  929. package/src/notifications/events-store.ts +13 -7
  930. package/src/notifications/guardian-question-mode.ts +125 -75
  931. package/src/notifications/preference-extractor.ts +85 -53
  932. package/src/notifications/preference-summary.ts +31 -18
  933. package/src/notifications/preferences-store.ts +29 -18
  934. package/src/notifications/runtime-dispatch.ts +22 -12
  935. package/src/notifications/signal.ts +4 -4
  936. package/src/notifications/thread-candidates.ts +59 -23
  937. package/src/notifications/thread-seed-composer.ts +45 -27
  938. package/src/notifications/types.ts +19 -10
  939. package/src/oauth/connect-orchestrator.ts +105 -54
  940. package/src/oauth/connect-types.ts +3 -3
  941. package/src/oauth/provider-profiles.ts +102 -59
  942. package/src/oauth/scope-policy.ts +5 -2
  943. package/src/oauth/token-persistence.ts +58 -24
  944. package/src/outbound-proxy/certs.ts +284 -0
  945. package/src/outbound-proxy/config.ts +94 -0
  946. package/src/outbound-proxy/connect-tunnel.ts +84 -0
  947. package/src/outbound-proxy/health.ts +62 -0
  948. package/src/outbound-proxy/host-pattern-match.ts +67 -0
  949. package/src/outbound-proxy/http-forwarder.ts +162 -0
  950. package/src/outbound-proxy/index.ts +80 -0
  951. package/src/outbound-proxy/logging.ts +193 -0
  952. package/src/outbound-proxy/mitm-handler.ts +292 -0
  953. package/src/outbound-proxy/policy.ts +172 -0
  954. package/src/outbound-proxy/router.ts +64 -0
  955. package/src/outbound-proxy/server.ts +145 -0
  956. package/src/outbound-proxy/types.ts +150 -0
  957. package/src/permissions/checker.ts +481 -189
  958. package/src/permissions/defaults.ts +135 -108
  959. package/src/permissions/prompter.ts +53 -27
  960. package/src/permissions/secret-prompter.ts +21 -15
  961. package/src/permissions/shell-identity.ts +47 -16
  962. package/src/permissions/trust-store.ts +185 -73
  963. package/src/permissions/types.ts +22 -12
  964. package/src/permissions/workspace-policy.ts +47 -38
  965. package/src/playbooks/index.ts +10 -2
  966. package/src/playbooks/playbook-compiler.ts +30 -24
  967. package/src/playbooks/types.ts +11 -8
  968. package/src/providers/anthropic/client.ts +328 -168
  969. package/src/providers/failover.ts +57 -22
  970. package/src/providers/fireworks/client.ts +9 -5
  971. package/src/providers/gemini/client.ts +61 -39
  972. package/src/providers/model-intents.ts +40 -33
  973. package/src/providers/ollama/client.ts +7 -7
  974. package/src/providers/openai/client.ts +109 -68
  975. package/src/providers/openrouter/client.ts +9 -5
  976. package/src/providers/provider-send-message.ts +59 -27
  977. package/src/providers/ratelimit.ts +25 -8
  978. package/src/providers/registry.ts +86 -38
  979. package/src/providers/retry.ts +93 -37
  980. package/src/providers/stream-timeout.ts +5 -3
  981. package/src/providers/types.ts +7 -6
  982. package/src/runtime/AGENTS.md +42 -0
  983. package/src/runtime/access-request-helper.ts +118 -68
  984. package/src/runtime/actor-refresh-token-store.ts +21 -16
  985. package/src/runtime/actor-token-store.ts +25 -18
  986. package/src/runtime/actor-trust-resolver.ts +191 -80
  987. package/src/runtime/approval-conversation-turn.ts +39 -26
  988. package/src/runtime/approval-message-composer.ts +116 -84
  989. package/src/runtime/assistant-event-hub.ts +25 -6
  990. package/src/runtime/assistant-event.ts +4 -4
  991. package/src/runtime/assistant-scope.ts +1 -1
  992. package/src/runtime/auth/__tests__/guard-tests.test.ts +36 -14
  993. package/src/runtime/auth/context.ts +8 -7
  994. package/src/runtime/auth/credential-service.ts +60 -38
  995. package/src/runtime/auth/external-assistant-id.ts +16 -8
  996. package/src/runtime/auth/index.ts +23 -16
  997. package/src/runtime/auth/require-bound-guardian.ts +44 -0
  998. package/src/runtime/auth/route-policy.ts +166 -104
  999. package/src/runtime/auth/scopes.ts +22 -29
  1000. package/src/runtime/auth/subject.ts +19 -13
  1001. package/src/runtime/auth/token-service.ts +3 -3
  1002. package/src/runtime/auth/types.ts +23 -23
  1003. package/src/runtime/channel-approval-parser.ts +37 -14
  1004. package/src/runtime/channel-approval-types.ts +30 -4
  1005. package/src/runtime/channel-approvals.ts +49 -23
  1006. package/src/runtime/channel-guardian-service.ts +144 -103
  1007. package/src/runtime/channel-invite-transport.ts +5 -3
  1008. package/src/runtime/channel-invite-transports/telegram.ts +16 -10
  1009. package/src/runtime/channel-invite-transports/voice.ts +7 -7
  1010. package/src/runtime/channel-readiness-service.ts +139 -90
  1011. package/src/runtime/channel-readiness-types.ts +4 -2
  1012. package/src/runtime/channel-reply-delivery.ts +83 -14
  1013. package/src/runtime/channel-retry-sweep.ts +111 -62
  1014. package/src/runtime/confirmation-request-guardian-bridge.ts +73 -54
  1015. package/src/runtime/gateway-client.ts +122 -55
  1016. package/src/runtime/gateway-internal-client.ts +86 -0
  1017. package/src/runtime/guardian-action-conversation-turn.ts +34 -18
  1018. package/src/runtime/guardian-action-followup-executor.ts +115 -45
  1019. package/src/runtime/guardian-action-grant-minter.ts +40 -24
  1020. package/src/runtime/guardian-action-message-composer.ts +105 -84
  1021. package/src/runtime/guardian-action-service.ts +127 -0
  1022. package/src/runtime/guardian-decision-types.ts +28 -13
  1023. package/src/runtime/guardian-outbound-actions.ts +9 -0
  1024. package/src/runtime/guardian-reply-router.ts +274 -145
  1025. package/src/runtime/guardian-vellum-migration.ts +38 -24
  1026. package/src/runtime/guardian-verification-templates.ts +24 -12
  1027. package/src/runtime/http-router.ts +175 -0
  1028. package/src/runtime/http-server.ts +913 -680
  1029. package/src/runtime/http-types.ts +2 -2
  1030. package/src/runtime/invite-redemption-service.ts +211 -134
  1031. package/src/runtime/invite-redemption-templates.ts +18 -11
  1032. package/src/runtime/{ingress-service.ts → invite-service.ts} +92 -151
  1033. package/src/runtime/local-actor-identity.ts +73 -55
  1034. package/src/runtime/middleware/auth.ts +25 -14
  1035. package/src/runtime/middleware/error-handler.ts +15 -11
  1036. package/src/runtime/middleware/rate-limiter.ts +23 -17
  1037. package/src/runtime/middleware/request-logger.ts +4 -4
  1038. package/src/runtime/middleware/twilio-validation.ts +29 -20
  1039. package/src/runtime/migrations/migration-transport.ts +575 -0
  1040. package/src/runtime/migrations/migration-wizard.ts +715 -0
  1041. package/src/runtime/migrations/rebind-secrets-screen.ts +351 -0
  1042. package/src/runtime/migrations/transfer-progress-screen.ts +321 -0
  1043. package/src/runtime/migrations/validation-results-screen.ts +467 -0
  1044. package/src/runtime/migrations/vbundle-builder.ts +295 -0
  1045. package/src/runtime/migrations/vbundle-import-analyzer.ts +212 -0
  1046. package/src/runtime/migrations/vbundle-importer.ts +339 -0
  1047. package/src/runtime/migrations/vbundle-validator.ts +356 -0
  1048. package/src/runtime/nl-approval-parser.ts +138 -0
  1049. package/src/runtime/pending-interactions.ts +16 -7
  1050. package/src/runtime/routes/access-request-decision.ts +73 -52
  1051. package/src/runtime/routes/app-routes.ts +56 -38
  1052. package/src/runtime/routes/approval-routes.ts +144 -92
  1053. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +930 -0
  1054. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +82 -0
  1055. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +151 -0
  1056. package/src/runtime/routes/attachment-routes.ts +59 -48
  1057. package/src/runtime/routes/brain-graph-routes.ts +85 -69
  1058. package/src/runtime/routes/call-routes.ts +79 -38
  1059. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +10 -10
  1060. package/src/runtime/routes/channel-delivery-routes.ts +19 -14
  1061. package/src/runtime/routes/channel-guardian-routes.ts +3 -3
  1062. package/src/runtime/routes/channel-inbound-routes.ts +2 -2
  1063. package/src/runtime/routes/channel-readiness-routes.ts +12 -6
  1064. package/src/runtime/routes/channel-route-shared.ts +67 -25
  1065. package/src/runtime/routes/channel-routes.ts +4 -6
  1066. package/src/runtime/routes/contact-routes.ts +374 -17
  1067. package/src/runtime/routes/conversation-attention-routes.ts +57 -28
  1068. package/src/runtime/routes/conversation-routes.ts +321 -174
  1069. package/src/runtime/routes/debug-routes.ts +14 -10
  1070. package/src/runtime/routes/events-routes.ts +90 -57
  1071. package/src/runtime/routes/global-search-routes.ts +266 -0
  1072. package/src/runtime/routes/guardian-action-routes.ts +112 -113
  1073. package/src/runtime/routes/guardian-approval-interception.ts +325 -874
  1074. package/src/runtime/routes/guardian-approval-prompt.ts +40 -24
  1075. package/src/runtime/routes/guardian-approval-reply-helpers.ts +135 -0
  1076. package/src/runtime/routes/guardian-bootstrap-routes.ts +55 -36
  1077. package/src/runtime/routes/guardian-expiry-sweep.ts +63 -37
  1078. package/src/runtime/routes/guardian-refresh-routes.ts +40 -19
  1079. package/src/runtime/routes/identity-routes.ts +71 -42
  1080. package/src/runtime/routes/inbound-conversation.ts +17 -11
  1081. package/src/runtime/routes/inbound-message-handler.ts +305 -1459
  1082. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +880 -0
  1083. package/src/runtime/routes/inbound-stages/background-dispatch.ts +600 -0
  1084. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +214 -0
  1085. package/src/runtime/routes/inbound-stages/edit-intercept.ts +116 -0
  1086. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +167 -0
  1087. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +185 -0
  1088. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +132 -0
  1089. package/src/runtime/routes/inbound-stages/verification-intercept.ts +340 -0
  1090. package/src/runtime/routes/integration-routes.ts +60 -21
  1091. package/src/runtime/routes/invite-routes.ts +140 -0
  1092. package/src/runtime/routes/migration-routes.ts +434 -0
  1093. package/src/runtime/routes/pairing-routes.ts +157 -79
  1094. package/src/runtime/routes/secret-routes.ts +6 -2
  1095. package/src/runtime/routes/twilio-routes.ts +443 -249
  1096. package/src/runtime/slack-block-formatting.ts +176 -0
  1097. package/src/runtime/tool-grant-request-helper.ts +36 -27
  1098. package/src/runtime/{guardian-context-resolver.ts → trust-context-resolver.ts} +29 -41
  1099. package/src/schedule/integration-status.ts +44 -9
  1100. package/src/schedule/recurrence-engine.ts +47 -24
  1101. package/src/schedule/recurrence-types.ts +12 -7
  1102. package/src/schedule/schedule-store.ts +166 -83
  1103. package/src/schedule/scheduler.ts +37 -24
  1104. package/src/security/encrypted-store.ts +68 -38
  1105. package/src/security/keychain.ts +183 -120
  1106. package/src/security/oauth-callback-registry.ts +3 -3
  1107. package/src/security/oauth2.ts +226 -138
  1108. package/src/security/redaction.ts +24 -24
  1109. package/src/security/secret-allowlist.ts +46 -21
  1110. package/src/security/secret-ingress.ts +15 -7
  1111. package/src/security/secret-scanner.ts +193 -104
  1112. package/src/security/secure-keys.ts +9 -3
  1113. package/src/security/token-manager.ts +99 -40
  1114. package/src/security/tool-approval-digest.ts +3 -3
  1115. package/src/sequence/analytics.ts +52 -27
  1116. package/src/sequence/engine.ts +135 -72
  1117. package/src/sequence/guardrails.ts +32 -20
  1118. package/src/sequence/importer.ts +75 -37
  1119. package/src/sequence/reply-matcher.ts +36 -18
  1120. package/src/sequence/store.ts +137 -75
  1121. package/src/sequence/types.ts +30 -16
  1122. package/src/services/published-app-updater.ts +26 -16
  1123. package/src/services/vercel-deploy.ts +19 -15
  1124. package/src/skills/active-skill-tools.ts +3 -3
  1125. package/src/skills/clawhub.ts +178 -90
  1126. package/src/skills/include-graph.ts +24 -17
  1127. package/src/skills/managed-store.ts +89 -42
  1128. package/src/skills/path-classifier.ts +10 -10
  1129. package/src/skills/remote-skill-policy.ts +31 -22
  1130. package/src/skills/slash-commands.ts +36 -30
  1131. package/src/skills/tool-manifest.ts +60 -31
  1132. package/src/skills/version-hash.ts +25 -15
  1133. package/src/slack/slack-webhook.ts +19 -15
  1134. package/src/subagent/index.ts +4 -8
  1135. package/src/subagent/manager.ts +119 -69
  1136. package/src/subagent/types.ts +9 -12
  1137. package/src/swarm/backend-claude-code.ts +124 -45
  1138. package/src/swarm/checkpoint.ts +36 -16
  1139. package/src/swarm/graph-utils.ts +1 -3
  1140. package/src/swarm/index.ts +38 -19
  1141. package/src/swarm/limits.ts +13 -4
  1142. package/src/swarm/orchestrator.ts +108 -57
  1143. package/src/swarm/plan-validator.ts +23 -17
  1144. package/src/swarm/router-planner.ts +51 -22
  1145. package/src/swarm/router-prompts.ts +4 -1
  1146. package/src/swarm/synthesizer.ts +26 -18
  1147. package/src/swarm/types.ts +14 -4
  1148. package/src/swarm/worker-backend.ts +36 -26
  1149. package/src/swarm/worker-prompts.ts +13 -9
  1150. package/src/swarm/worker-runner.ts +40 -34
  1151. package/src/tasks/candidate-store.ts +14 -6
  1152. package/src/tasks/ephemeral-permissions.ts +9 -5
  1153. package/src/tasks/task-compiler.ts +41 -38
  1154. package/src/tasks/task-runner.ts +54 -26
  1155. package/src/tasks/task-scheduler.ts +1 -1
  1156. package/src/tasks/task-store.ts +20 -7
  1157. package/src/tasks/tool-sanitizer.ts +3 -3
  1158. package/src/tools/apps/definitions.ts +23 -15
  1159. package/src/tools/apps/executors.ts +122 -40
  1160. package/src/tools/apps/open-proxy.ts +5 -5
  1161. package/src/tools/apps/registry.ts +2 -2
  1162. package/src/tools/assets/materialize.ts +59 -41
  1163. package/src/tools/assets/search.ts +86 -48
  1164. package/src/tools/browser/api-map.ts +52 -36
  1165. package/src/tools/browser/auth-cache.ts +21 -18
  1166. package/src/tools/browser/auth-detector.ts +43 -28
  1167. package/src/tools/browser/auto-navigate.ts +149 -68
  1168. package/src/tools/browser/browser-execution.ts +9 -3
  1169. package/src/tools/browser/headless-browser.ts +287 -150
  1170. package/src/tools/browser/jit-auth.ts +37 -21
  1171. package/src/tools/browser/network-recorder.ts +138 -56
  1172. package/src/tools/browser/recording-store.ts +22 -15
  1173. package/src/tools/browser/runtime-check.ts +8 -5
  1174. package/src/tools/browser/x-auto-navigate.ts +88 -47
  1175. package/src/tools/calls/call-end.ts +10 -7
  1176. package/src/tools/calls/call-start.ts +30 -20
  1177. package/src/tools/calls/call-status.ts +8 -5
  1178. package/src/tools/claude-code/claude-code.ts +301 -165
  1179. package/src/tools/computer-use/definitions.ts +175 -130
  1180. package/src/tools/computer-use/registry.ts +2 -2
  1181. package/src/tools/computer-use/request-computer-control.ts +21 -13
  1182. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  1183. package/src/tools/credentials/account-registry.ts +52 -35
  1184. package/src/tools/credentials/broker-types.ts +1 -1
  1185. package/src/tools/credentials/broker.ts +97 -55
  1186. package/src/tools/credentials/domain-policy.ts +5 -2
  1187. package/src/tools/credentials/host-pattern-match.ts +15 -8
  1188. package/src/tools/credentials/metadata-store.ts +93 -43
  1189. package/src/tools/credentials/policy-types.ts +5 -2
  1190. package/src/tools/credentials/policy-validate.ts +21 -14
  1191. package/src/tools/credentials/post-connect-hooks.ts +18 -7
  1192. package/src/tools/credentials/resolve.ts +11 -10
  1193. package/src/tools/credentials/selection.ts +30 -25
  1194. package/src/tools/credentials/tool-policy.ts +5 -2
  1195. package/src/tools/credentials/vault.ts +538 -185
  1196. package/src/tools/document/document-tool.ts +23 -17
  1197. package/src/tools/document/editor-template.ts +12 -7
  1198. package/src/tools/execution-target.ts +13 -10
  1199. package/src/tools/execution-timeout.ts +6 -5
  1200. package/src/tools/executor.ts +141 -74
  1201. package/src/tools/filesystem/edit.ts +82 -45
  1202. package/src/tools/filesystem/fuzzy-match.ts +70 -32
  1203. package/src/tools/filesystem/read.ts +46 -28
  1204. package/src/tools/filesystem/view-image.ts +86 -42
  1205. package/src/tools/filesystem/write.ts +53 -32
  1206. package/src/tools/followups/followup_create.ts +43 -17
  1207. package/src/tools/followups/followup_list.ts +28 -13
  1208. package/src/tools/followups/followup_resolve.ts +9 -6
  1209. package/src/tools/guardian-control-plane-policy.ts +15 -14
  1210. package/src/tools/host-filesystem/edit.ts +77 -42
  1211. package/src/tools/host-filesystem/read.ts +52 -33
  1212. package/src/tools/host-filesystem/write.ts +50 -29
  1213. package/src/tools/host-terminal/host-shell.ts +97 -61
  1214. package/src/tools/mcp/mcp-tool-factory.ts +21 -14
  1215. package/src/tools/memory/definitions.ts +60 -28
  1216. package/src/tools/memory/handlers.ts +149 -77
  1217. package/src/tools/memory/register.ts +39 -16
  1218. package/src/tools/network/__tests__/web-search.test.ts +236 -177
  1219. package/src/tools/network/domain-normalize.ts +13 -9
  1220. package/src/tools/network/script-proxy/__tests__/logging.test.ts +193 -123
  1221. package/src/tools/network/script-proxy/__tests__/policy.test.ts +225 -127
  1222. package/src/tools/network/script-proxy/index.ts +1 -17
  1223. package/src/tools/network/script-proxy/session-manager.ts +178 -86
  1224. package/src/tools/network/url-safety.ts +56 -34
  1225. package/src/tools/network/web-fetch.ts +273 -155
  1226. package/src/tools/network/web-search.ts +166 -81
  1227. package/src/tools/permission-checker.ts +24 -25
  1228. package/src/tools/policy-context.ts +8 -5
  1229. package/src/tools/registry.ts +73 -46
  1230. package/src/tools/reminder/reminder-store.ts +65 -44
  1231. package/src/tools/reminder/reminder.ts +76 -35
  1232. package/src/tools/schedule/create.ts +44 -21
  1233. package/src/tools/schedule/delete.ts +8 -5
  1234. package/src/tools/schedule/list.ts +39 -19
  1235. package/src/tools/schedule/update.ts +49 -26
  1236. package/src/tools/secret-detection-handler.ts +130 -49
  1237. package/src/tools/sensitive-output-placeholders.ts +15 -8
  1238. package/src/tools/shared/filesystem/edit-engine.ts +45 -14
  1239. package/src/tools/shared/filesystem/errors.ts +18 -18
  1240. package/src/tools/shared/filesystem/file-ops-service.ts +59 -32
  1241. package/src/tools/shared/filesystem/format-diff.ts +21 -11
  1242. package/src/tools/shared/filesystem/path-policy.ts +17 -13
  1243. package/src/tools/shared/filesystem/size-guard.ts +8 -4
  1244. package/src/tools/shared/filesystem/types.ts +2 -2
  1245. package/src/tools/shared/shell-output.ts +4 -3
  1246. package/src/tools/side-effects.ts +36 -28
  1247. package/src/tools/skills/delete-managed.ts +30 -17
  1248. package/src/tools/skills/load.ts +88 -46
  1249. package/src/tools/skills/sandbox-runner.ts +62 -46
  1250. package/src/tools/skills/scaffold-managed.ts +98 -48
  1251. package/src/tools/skills/script-contract.ts +5 -2
  1252. package/src/tools/skills/skill-script-runner.ts +29 -13
  1253. package/src/tools/skills/skill-tool-factory.ts +20 -10
  1254. package/src/tools/subagent/abort.ts +10 -4
  1255. package/src/tools/subagent/message.ts +14 -8
  1256. package/src/tools/subagent/read.ts +20 -11
  1257. package/src/tools/subagent/spawn.ts +14 -6
  1258. package/src/tools/subagent/status.ts +7 -4
  1259. package/src/tools/swarm/delegate.ts +75 -49
  1260. package/src/tools/system/avatar-generator.ts +46 -33
  1261. package/src/tools/system/navigate-settings.ts +29 -19
  1262. package/src/tools/system/open-system-settings.ts +30 -20
  1263. package/src/tools/system/request-permission.ts +59 -44
  1264. package/src/tools/system/version.ts +27 -16
  1265. package/src/tools/system/voice-config.ts +116 -53
  1266. package/src/tools/tasks/index.ts +8 -8
  1267. package/src/tools/tasks/task-delete.ts +61 -22
  1268. package/src/tools/tasks/task-list.ts +23 -11
  1269. package/src/tools/tasks/task-run.ts +41 -16
  1270. package/src/tools/tasks/task-save.ts +27 -10
  1271. package/src/tools/tasks/work-item-enqueue.ts +114 -48
  1272. package/src/tools/tasks/work-item-list.ts +20 -10
  1273. package/src/tools/tasks/work-item-remove.ts +49 -15
  1274. package/src/tools/tasks/work-item-run.ts +34 -13
  1275. package/src/tools/tasks/work-item-update.ts +84 -31
  1276. package/src/tools/terminal/backends/native.ts +64 -35
  1277. package/src/tools/terminal/backends/types.ts +6 -2
  1278. package/src/tools/terminal/parser.ts +200 -125
  1279. package/src/tools/terminal/safe-env.ts +27 -21
  1280. package/src/tools/terminal/sandbox-diagnostics.ts +31 -13
  1281. package/src/tools/terminal/sandbox.ts +10 -6
  1282. package/src/tools/terminal/shell.ts +134 -68
  1283. package/src/tools/tool-approval-handler.ts +239 -140
  1284. package/src/tools/types.ts +79 -22
  1285. package/src/tools/ui-surface/definitions.ts +124 -89
  1286. package/src/tools/ui-surface/registry.ts +2 -2
  1287. package/src/tools/watch/screen-watch.ts +50 -32
  1288. package/src/tools/watch/watch-state.ts +41 -15
  1289. package/src/tools/watcher/create.ts +37 -15
  1290. package/src/tools/watcher/delete.ts +9 -6
  1291. package/src/tools/watcher/digest.ts +10 -6
  1292. package/src/tools/watcher/list.ts +37 -14
  1293. package/src/tools/watcher/update.ts +33 -18
  1294. package/src/tools/weather/service.ts +331 -174
  1295. package/src/twitter/client.ts +261 -138
  1296. package/src/twitter/oauth-client.ts +17 -13
  1297. package/src/twitter/router.ts +51 -23
  1298. package/src/twitter/session.ts +27 -18
  1299. package/src/types/qrcode.d.ts +6 -3
  1300. package/src/usage/actors.ts +16 -16
  1301. package/src/usage/types.ts +3 -3
  1302. package/src/util/bundled-asset.ts +10 -6
  1303. package/src/util/canonicalize-identity.ts +11 -4
  1304. package/src/util/clipboard.ts +7 -7
  1305. package/src/util/content-id.ts +3 -3
  1306. package/src/util/debounce.ts +3 -2
  1307. package/src/util/diff.ts +55 -33
  1308. package/src/util/errors.ts +31 -27
  1309. package/src/util/fs.ts +8 -2
  1310. package/src/util/log-redact.ts +12 -12
  1311. package/src/util/logger.ts +112 -51
  1312. package/src/util/network-info.ts +13 -5
  1313. package/src/util/object.ts +4 -2
  1314. package/src/util/phone.ts +4 -4
  1315. package/src/util/platform.ts +80 -58
  1316. package/src/util/pricing.ts +49 -31
  1317. package/src/util/retry.ts +39 -7
  1318. package/src/util/row-mapper.ts +7 -4
  1319. package/src/util/silently.ts +7 -4
  1320. package/src/util/spawn.ts +48 -0
  1321. package/src/util/spinner.ts +9 -7
  1322. package/src/util/time.ts +16 -3
  1323. package/src/util/truncate.ts +1 -1
  1324. package/src/util/voice-code.ts +6 -4
  1325. package/src/util/xml.ts +5 -1
  1326. package/src/version.ts +12 -8
  1327. package/src/watcher/engine.ts +71 -44
  1328. package/src/watcher/provider-registry.ts +1 -1
  1329. package/src/watcher/providers/github.ts +40 -23
  1330. package/src/watcher/providers/gmail.ts +59 -38
  1331. package/src/watcher/providers/google-calendar.ts +62 -48
  1332. package/src/watcher/providers/linear.ts +219 -150
  1333. package/src/watcher/providers/slack.ts +125 -29
  1334. package/src/watcher/watcher-store.ts +75 -55
  1335. package/src/work-items/work-item-runner.ts +62 -29
  1336. package/src/work-items/work-item-store.ts +137 -47
  1337. package/src/workspace/commit-message-enrichment-service.ts +65 -25
  1338. package/src/workspace/commit-message-provider.ts +14 -12
  1339. package/src/workspace/git-service.ts +355 -239
  1340. package/src/workspace/heartbeat-service.ts +74 -37
  1341. package/src/workspace/provider-commit-message-generator.ts +95 -70
  1342. package/src/workspace/top-level-renderer.ts +10 -8
  1343. package/src/workspace/top-level-scanner.ts +9 -3
  1344. package/src/workspace/turn-commit.ts +63 -36
  1345. package/src/__tests__/ingress-member-store.test.ts +0 -294
  1346. package/src/__tests__/script-proxy-router.test.ts +0 -215
  1347. package/src/config/bundled-skills/trusted-contacts/SKILL.md +0 -372
  1348. package/src/memory/guardian-bindings.ts +0 -158
  1349. package/src/memory/ingress-member-store.ts +0 -352
  1350. package/src/runtime/routes/ingress-routes.ts +0 -229
  1351. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -77
  1352. package/src/tools/network/script-proxy/certs.ts +0 -7
  1353. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -1
  1354. package/src/tools/network/script-proxy/http-forwarder.ts +0 -2
  1355. package/src/tools/network/script-proxy/logging.ts +0 -12
  1356. package/src/tools/network/script-proxy/mitm-handler.ts +0 -2
  1357. package/src/tools/network/script-proxy/policy.ts +0 -4
  1358. package/src/tools/network/script-proxy/router.ts +0 -2
  1359. package/src/tools/network/script-proxy/server.ts +0 -5
  1360. package/src/tools/network/script-proxy/types.ts +0 -19
@@ -8,40 +8,53 @@
8
8
  * barge-in, state machine, guardian verification).
9
9
  */
10
10
 
11
- import { getGatewayInternalBaseUrl } from '../config/env.js';
12
- import type { ServerMessage } from '../daemon/ipc-contract.js';
13
- import type { GuardianRuntimeContext } from '../daemon/session-runtime-assembly.js';
11
+ import { getGatewayInternalBaseUrl } from "../config/env.js";
12
+ import type { ServerMessage } from "../daemon/ipc-contract.js";
13
+ import type { TrustContext } from "../daemon/session-runtime-assembly.js";
14
14
  import {
15
15
  expireCanonicalGuardianRequest,
16
16
  getCanonicalRequestByPendingQuestionId,
17
17
  getPendingCanonicalRequestByCallSessionId,
18
18
  listCanonicalGuardianDeliveries,
19
- } from '../memory/canonical-guardian-store.js';
20
- import { revokeScopedApprovalGrantsForContext } from '../memory/scoped-approval-grants.js';
21
- import { DAEMON_INTERNAL_ASSISTANT_ID } from '../runtime/assistant-scope.js';
22
- import { mintDaemonDeliveryToken } from '../runtime/auth/token-service.js';
23
- import { computeToolApprovalDigest } from '../security/tool-approval-digest.js';
24
- import { getLogger } from '../util/logger.js';
25
- import { getMaxCallDurationMs, getSilenceTimeoutMs, getUserConsultationTimeoutMs } from './call-constants.js';
26
- import { persistCallCompletionMessage } from './call-conversation-messages.js';
27
- import { addPointerMessage, formatDuration } from './call-pointer-messages.js';
28
- import { fireCallCompletionNotifier, fireCallQuestionNotifier, fireCallTranscriptNotifier,registerCallController, unregisterCallController } from './call-state.js';
19
+ } from "../memory/canonical-guardian-store.js";
20
+ import { revokeScopedApprovalGrantsForContext } from "../memory/scoped-approval-grants.js";
21
+ import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
22
+ import { mintDaemonDeliveryToken } from "../runtime/auth/token-service.js";
23
+ import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
24
+ import { getLogger } from "../util/logger.js";
25
+ import {
26
+ getMaxCallDurationMs,
27
+ getSilenceTimeoutMs,
28
+ getUserConsultationTimeoutMs,
29
+ } from "./call-constants.js";
30
+ import { persistCallCompletionMessage } from "./call-conversation-messages.js";
31
+ import { addPointerMessage, formatDuration } from "./call-pointer-messages.js";
32
+ import {
33
+ fireCallCompletionNotifier,
34
+ fireCallQuestionNotifier,
35
+ fireCallTranscriptNotifier,
36
+ registerCallController,
37
+ unregisterCallController,
38
+ } from "./call-state.js";
29
39
  import {
30
40
  createPendingQuestion,
31
41
  expirePendingQuestions,
32
42
  getCallSession,
33
43
  recordCallEvent,
34
44
  updateCallSession,
35
- } from './call-store.js';
36
- import { sendGuardianExpiryNotices } from './guardian-action-sweep.js';
37
- import { dispatchGuardianQuestion } from './guardian-dispatch.js';
38
- import type { RelayConnection } from './relay-server.js';
39
- import type { PromptSpeakerContext } from './speaker-identification.js';
40
- import { startVoiceTurn, type VoiceTurnHandle } from './voice-session-bridge.js';
45
+ } from "./call-store.js";
46
+ import { sendGuardianExpiryNotices } from "./guardian-action-sweep.js";
47
+ import { dispatchGuardianQuestion } from "./guardian-dispatch.js";
48
+ import type { RelayConnection } from "./relay-server.js";
49
+ import type { PromptSpeakerContext } from "./speaker-identification.js";
50
+ import {
51
+ startVoiceTurn,
52
+ type VoiceTurnHandle,
53
+ } from "./voice-session-bridge.js";
41
54
 
42
- const log = getLogger('call-controller');
55
+ const log = getLogger("call-controller");
43
56
 
44
- type ControllerState = 'idle' | 'processing' | 'speaking';
57
+ type ControllerState = "idle" | "processing" | "speaking";
45
58
 
46
59
  /**
47
60
  * Tracks a pending guardian input request independently of the controller's
@@ -86,7 +99,7 @@ function extractBalancedJson(
86
99
 
87
100
  const prefixIdx = prefixMatch.index;
88
101
  const jsonStart = prefixIdx + prefixMatch[0].length;
89
- if (jsonStart >= text.length || text[jsonStart] !== '{') return null;
102
+ if (jsonStart >= text.length || text[jsonStart] !== "{") return null;
90
103
 
91
104
  let depth = 0;
92
105
  let inString = false;
@@ -100,7 +113,7 @@ function extractBalancedJson(
100
113
  continue;
101
114
  }
102
115
 
103
- if (ch === '\\' && inString) {
116
+ if (ch === "\\" && inString) {
104
117
  escape = true;
105
118
  continue;
106
119
  }
@@ -112,9 +125,9 @@ function extractBalancedJson(
112
125
 
113
126
  if (inString) continue;
114
127
 
115
- if (ch === '{') {
128
+ if (ch === "{") {
116
129
  depth++;
117
- } else if (ch === '}') {
130
+ } else if (ch === "}") {
118
131
  depth--;
119
132
  if (depth === 0) {
120
133
  const jsonEnd = i + 1;
@@ -129,7 +142,7 @@ function extractBalancedJson(
129
142
  // Require the closing ']' to be present before considering this
130
143
  // a complete match. If it hasn't arrived yet (streaming), return
131
144
  // null so the caller keeps buffering.
132
- if (bracketIdx >= text.length || text[bracketIdx] !== ']') {
145
+ if (bracketIdx >= text.length || text[bracketIdx] !== "]") {
133
146
  return null;
134
147
  }
135
148
  const fullMatchEnd = bracketIdx + 1;
@@ -152,7 +165,9 @@ function stripGuardianApprovalMarkers(text: string): string {
152
165
  for (;;) {
153
166
  const match = extractBalancedJson(result);
154
167
  if (!match) break;
155
- result = result.slice(0, match.startIndex) + result.slice(match.startIndex + match.fullMatch.length);
168
+ result =
169
+ result.slice(0, match.startIndex) +
170
+ result.slice(match.startIndex + match.fullMatch.length);
156
171
  }
157
172
  return result;
158
173
  }
@@ -164,31 +179,32 @@ const CALL_OPENING_ACK_MARKER_REGEX = /\[CALL_OPENING_ACK\]/g;
164
179
  const END_CALL_MARKER_REGEX = /\[END_CALL\]/g;
165
180
  const GUARDIAN_TIMEOUT_MARKER_REGEX = /\[GUARDIAN_TIMEOUT\]/g;
166
181
  const GUARDIAN_UNAVAILABLE_MARKER_REGEX = /\[GUARDIAN_UNAVAILABLE\]/g;
167
- const CALL_OPENING_MARKER = '[CALL_OPENING]';
168
- const CALL_OPENING_ACK_MARKER = '[CALL_OPENING_ACK]';
169
- const END_CALL_MARKER = '[END_CALL]';
182
+ const CALL_OPENING_MARKER = "[CALL_OPENING]";
183
+ const CALL_OPENING_ACK_MARKER = "[CALL_OPENING_ACK]";
184
+ const END_CALL_MARKER = "[END_CALL]";
170
185
 
171
186
  function stripInternalSpeechMarkers(text: string): string {
172
187
  let result = stripGuardianApprovalMarkers(text);
173
188
  result = result
174
- .replace(ASK_GUARDIAN_MARKER_REGEX, '')
175
- .replace(USER_ANSWERED_MARKER_REGEX, '')
176
- .replace(USER_INSTRUCTION_MARKER_REGEX, '')
177
- .replace(CALL_OPENING_MARKER_REGEX, '')
178
- .replace(CALL_OPENING_ACK_MARKER_REGEX, '')
179
- .replace(END_CALL_MARKER_REGEX, '')
180
- .replace(GUARDIAN_TIMEOUT_MARKER_REGEX, '')
181
- .replace(GUARDIAN_UNAVAILABLE_MARKER_REGEX, '');
189
+ .replace(ASK_GUARDIAN_MARKER_REGEX, "")
190
+ .replace(USER_ANSWERED_MARKER_REGEX, "")
191
+ .replace(USER_INSTRUCTION_MARKER_REGEX, "")
192
+ .replace(CALL_OPENING_MARKER_REGEX, "")
193
+ .replace(CALL_OPENING_ACK_MARKER_REGEX, "")
194
+ .replace(END_CALL_MARKER_REGEX, "")
195
+ .replace(GUARDIAN_TIMEOUT_MARKER_REGEX, "")
196
+ .replace(GUARDIAN_UNAVAILABLE_MARKER_REGEX, "");
182
197
  return result;
183
198
  }
184
199
 
185
200
  export class CallController {
186
201
  private callSessionId: string;
187
202
  private relay: RelayConnection;
188
- private state: ControllerState = 'idle';
203
+ private state: ControllerState = "idle";
189
204
  private abortController: AbortController = new AbortController();
190
205
  private currentTurnHandle: VoiceTurnHandle | null = null;
191
206
  private currentTurnPromise: Promise<void> | null = null;
207
+ private destroyed = false;
192
208
  private silenceTimer: ReturnType<typeof setTimeout> | null = null;
193
209
  private durationTimer: ReturnType<typeof setTimeout> | null = null;
194
210
  private durationWarningTimer: ReturnType<typeof setTimeout> | null = null;
@@ -216,7 +232,7 @@ export class CallController {
216
232
  /** Assistant identity for scoping guardian bindings. */
217
233
  private assistantId: string;
218
234
  /** Guardian trust context for the current caller, when available. */
219
- private guardianContext: GuardianRuntimeContext | null;
235
+ private trustContext: TrustContext | null;
220
236
  /** Conversation ID for the voice session. */
221
237
  private conversationId: string;
222
238
  /**
@@ -241,7 +257,7 @@ export class CallController {
241
257
  opts?: {
242
258
  broadcast?: (msg: ServerMessage) => void;
243
259
  assistantId?: string;
244
- guardianContext?: GuardianRuntimeContext;
260
+ trustContext?: TrustContext;
245
261
  },
246
262
  ) {
247
263
  this.callSessionId = callSessionId;
@@ -250,7 +266,7 @@ export class CallController {
250
266
  this.isInbound = !task;
251
267
  this.broadcast = opts?.broadcast;
252
268
  this.assistantId = opts?.assistantId ?? DAEMON_INTERNAL_ASSISTANT_ID;
253
- this.guardianContext = opts?.guardianContext ?? null;
269
+ this.trustContext = opts?.trustContext ?? null;
254
270
 
255
271
  // Resolve the conversation ID from the call session
256
272
  const session = getCallSession(callSessionId);
@@ -280,8 +296,8 @@ export class CallController {
280
296
  /**
281
297
  * Update guardian trust context for subsequent LLM turns.
282
298
  */
283
- setGuardianContext(ctx: GuardianRuntimeContext | null): void {
284
- this.guardianContext = ctx;
299
+ setTrustContext(ctx: TrustContext | null): void {
300
+ this.trustContext = ctx;
285
301
  }
286
302
 
287
303
  /**
@@ -304,7 +320,7 @@ export class CallController {
304
320
  */
305
321
  async startInitialGreeting(): Promise<void> {
306
322
  if (this.initialGreetingStarted) return;
307
- if (this.state !== 'idle') return;
323
+ if (this.state !== "idle") return;
308
324
 
309
325
  this.initialGreetingStarted = true;
310
326
  this.resetSilenceTimer();
@@ -317,12 +333,16 @@ export class CallController {
317
333
  * Caller utterances always trigger normal turns, even when a guardian
318
334
  * consultation is pending — the consultation is tracked separately.
319
335
  */
320
- async handleCallerUtterance(transcript: string, speaker?: PromptSpeakerContext): Promise<void> {
321
- const interruptedInFlight = this.state === 'processing' || this.state === 'speaking';
336
+ async handleCallerUtterance(
337
+ transcript: string,
338
+ speaker?: PromptSpeakerContext,
339
+ ): Promise<void> {
340
+ const interruptedInFlight =
341
+ this.state === "processing" || this.state === "speaking";
322
342
  // If we're already processing or speaking, abort the in-flight generation
323
343
  if (interruptedInFlight) {
324
344
  this.abortCurrentTurn();
325
- this.llmRunVersion++; // Invalidate stale turn before awaiting teardown
345
+ this.llmRunVersion++; // Invalidate stale turn before awaiting teardown
326
346
  }
327
347
 
328
348
  // Always await any lingering turn promise, even if handleInterrupt() already ran
@@ -331,11 +351,11 @@ export class CallController {
331
351
  this.currentTurnPromise = null;
332
352
  await Promise.race([
333
353
  teardownPromise.catch(() => {}),
334
- new Promise<void>(resolve => setTimeout(resolve, 2000)),
354
+ new Promise<void>((resolve) => setTimeout(resolve, 2000)),
335
355
  ]);
336
356
  }
337
357
 
338
- this.state = 'processing';
358
+ this.state = "processing";
339
359
  this.resetSilenceTimer();
340
360
  const callerContent = this.formatCallerUtterance(transcript, speaker);
341
361
  const shouldMarkOpeningAck = this.awaitingOpeningAck;
@@ -363,7 +383,7 @@ export class CallController {
363
383
  if (!this.pendingGuardianInput) {
364
384
  log.warn(
365
385
  { callSessionId: this.callSessionId, state: this.state },
366
- 'handleUserAnswer called but no pending consultation exists',
386
+ "handleUserAnswer called but no pending consultation exists",
367
387
  );
368
388
  return false;
369
389
  }
@@ -372,7 +392,7 @@ export class CallController {
372
392
  clearTimeout(this.pendingGuardianInput.timer);
373
393
  this.pendingGuardianInput = null;
374
394
 
375
- updateCallSession(this.callSessionId, { status: 'in_progress' });
395
+ updateCallSession(this.callSessionId, { status: "in_progress" });
376
396
 
377
397
  // Inject the answer as a queued instruction so it merges into the
378
398
  // next turn naturally, respecting role-alternation. If the controller
@@ -382,7 +402,7 @@ export class CallController {
382
402
  // If the controller is idle, flush instructions immediately to
383
403
  // deliver the answer. If processing/speaking, the answer will be
384
404
  // delivered when the current turn completes via flushPendingInstructions.
385
- if (this.state === 'idle') {
405
+ if (this.state === "idle") {
386
406
  this.flushPendingInstructions();
387
407
  }
388
408
 
@@ -399,10 +419,12 @@ export class CallController {
399
419
  * position once the current turn completes.
400
420
  */
401
421
  async handleUserInstruction(instructionText: string): Promise<void> {
402
- recordCallEvent(this.callSessionId, 'user_instruction_relayed', { instruction: instructionText });
422
+ recordCallEvent(this.callSessionId, "user_instruction_relayed", {
423
+ instruction: instructionText,
424
+ });
403
425
 
404
426
  // Queue the instruction when it cannot be safely appended right now
405
- if (this.state === 'processing' || this.state === 'speaking') {
427
+ if (this.state === "processing" || this.state === "speaking") {
406
428
  this.pendingInstructions.push(`[USER_INSTRUCTION: ${instructionText}]`);
407
429
  return;
408
430
  }
@@ -418,15 +440,15 @@ export class CallController {
418
440
  * Handle caller interrupting the assistant's speech.
419
441
  */
420
442
  handleInterrupt(): void {
421
- const wasSpeaking = this.state === 'speaking';
443
+ const wasSpeaking = this.state === "speaking";
422
444
  this.abortCurrentTurn();
423
445
  this.llmRunVersion++;
424
446
  // Explicitly terminate the in-progress TTS turn so the relay can
425
447
  // immediately hand control back to the caller after barge-in.
426
448
  if (wasSpeaking) {
427
- this.relay.sendTextToken('', true);
449
+ this.relay.sendTextToken("", true);
428
450
  }
429
- this.state = 'idle';
451
+ this.state = "idle";
430
452
  // Restart silence detection so a barge-in that never yields a
431
453
  // follow-up utterance doesn't leave the call without a watchdog.
432
454
  this.resetSilenceTimer();
@@ -436,11 +458,19 @@ export class CallController {
436
458
  * Tear down all timers and abort any in-flight work.
437
459
  */
438
460
  destroy(): void {
461
+ this.destroyed = true;
439
462
  if (this.silenceTimer) clearTimeout(this.silenceTimer);
440
463
  if (this.durationTimer) clearTimeout(this.durationTimer);
441
464
  if (this.durationWarningTimer) clearTimeout(this.durationWarningTimer);
442
- if (this.pendingGuardianInput) { clearTimeout(this.pendingGuardianInput.timer); this.pendingGuardianInput = null; }
443
- if (this.durationEndTimer) { clearTimeout(this.durationEndTimer); this.durationEndTimer = null; }
465
+ if (this.pendingGuardianInput) {
466
+ clearTimeout(this.pendingGuardianInput.timer);
467
+ this.pendingGuardianInput = null;
468
+ }
469
+ if (this.durationEndTimer) {
470
+ clearTimeout(this.durationEndTimer);
471
+ this.durationEndTimer = null;
472
+ }
473
+ this.pendingInstructions = [];
444
474
  this.llmRunVersion++;
445
475
  this.abortCurrentTurn();
446
476
  this.currentTurnPromise = null;
@@ -451,16 +481,30 @@ export class CallController {
451
481
  // guardian-approval-interception minting path sets callSessionId: null
452
482
  // but always sets conversationId.
453
483
  try {
454
- let revoked = revokeScopedApprovalGrantsForContext({ callSessionId: this.callSessionId });
455
- revoked += revokeScopedApprovalGrantsForContext({ conversationId: this.conversationId });
484
+ let revoked = revokeScopedApprovalGrantsForContext({
485
+ callSessionId: this.callSessionId,
486
+ });
487
+ revoked += revokeScopedApprovalGrantsForContext({
488
+ conversationId: this.conversationId,
489
+ });
456
490
  if (revoked > 0) {
457
- log.info({ callSessionId: this.callSessionId, conversationId: this.conversationId, revokedCount: revoked }, 'Revoked scoped grants on call end');
491
+ log.info(
492
+ {
493
+ callSessionId: this.callSessionId,
494
+ conversationId: this.conversationId,
495
+ revokedCount: revoked,
496
+ },
497
+ "Revoked scoped grants on call end",
498
+ );
458
499
  }
459
500
  } catch (err) {
460
- log.warn({ err, callSessionId: this.callSessionId }, 'Failed to revoke scoped grants on call end');
501
+ log.warn(
502
+ { err, callSessionId: this.callSessionId },
503
+ "Failed to revoke scoped grants on call end",
504
+ );
461
505
  }
462
506
 
463
- log.info({ callSessionId: this.callSessionId }, 'CallController destroyed');
507
+ log.info({ callSessionId: this.callSessionId }, "CallController destroyed");
464
508
  }
465
509
 
466
510
  // ── Private ──────────────────────────────────────────────────────
@@ -478,11 +522,17 @@ export class CallController {
478
522
  this.abortController = new AbortController();
479
523
  }
480
524
 
481
- private formatCallerUtterance(transcript: string, speaker?: PromptSpeakerContext): string {
525
+ private formatCallerUtterance(
526
+ transcript: string,
527
+ speaker?: PromptSpeakerContext,
528
+ ): string {
482
529
  if (!speaker) return transcript;
483
- const safeId = speaker.speakerId.replaceAll('"', '\'');
484
- const safeLabel = speaker.speakerLabel.replaceAll('"', '\'');
485
- const confidencePart = speaker.speakerConfidence != null ? ` confidence="${speaker.speakerConfidence.toFixed(2)}"` : '';
530
+ const safeId = speaker.speakerId.replaceAll('"', "'");
531
+ const safeLabel = speaker.speakerLabel.replaceAll('"', "'");
532
+ const confidencePart =
533
+ speaker.speakerConfidence != null
534
+ ? ` confidence="${speaker.speakerConfidence.toFixed(2)}"`
535
+ : "";
486
536
  return `[SPEAKER id="${safeId}" label="${safeLabel}" source="${speaker.source}"${confidencePart}] ${transcript}`;
487
537
  }
488
538
 
@@ -497,6 +547,7 @@ export class CallController {
497
547
  }
498
548
 
499
549
  private async runTurnInner(content: string): Promise<void> {
550
+ if (this.destroyed) return;
500
551
  const runVersion = ++this.llmRunVersion;
501
552
  const runSignal = this.abortController.signal;
502
553
 
@@ -509,23 +560,23 @@ export class CallController {
509
560
  }
510
561
 
511
562
  try {
512
- this.state = 'speaking';
563
+ this.state = "speaking";
513
564
 
514
565
  // Buffer incoming tokens so we can strip control markers ([ASK_GUARDIAN:...], [END_CALL])
515
566
  // before they reach TTS. We hold text whenever an unmatched '[' appears, since it
516
567
  // could be the start of a control marker.
517
- let ttsBuffer = '';
568
+ let ttsBuffer = "";
518
569
  // Accumulate the full response text for post-turn marker detection
519
- let fullResponseText = '';
570
+ let fullResponseText = "";
520
571
 
521
572
  const flushSafeText = (): void => {
522
573
  if (!this.isCurrentRun(runVersion)) return;
523
574
  if (ttsBuffer.length === 0) return;
524
- const bracketIdx = ttsBuffer.indexOf('[');
575
+ const bracketIdx = ttsBuffer.indexOf("[");
525
576
  if (bracketIdx === -1) {
526
577
  // No bracket at all — safe to flush everything
527
578
  this.relay.sendTextToken(ttsBuffer, false);
528
- ttsBuffer = '';
579
+ ttsBuffer = "";
529
580
  } else {
530
581
  // Flush everything before the bracket
531
582
  if (bracketIdx > 0) {
@@ -538,36 +589,36 @@ export class CallController {
538
589
  // bracketed text (e.g. "[A]", "[note]") doesn't stall TTS.
539
590
  const afterBracket = ttsBuffer;
540
591
  const couldBeControl =
541
- '[ASK_GUARDIAN_APPROVAL:'.startsWith(afterBracket) ||
542
- '[ASK_GUARDIAN:'.startsWith(afterBracket) ||
543
- '[USER_ANSWERED:'.startsWith(afterBracket) ||
544
- '[USER_INSTRUCTION:'.startsWith(afterBracket) ||
545
- '[CALL_OPENING]'.startsWith(afterBracket) ||
546
- '[CALL_OPENING_ACK]'.startsWith(afterBracket) ||
547
- '[END_CALL]'.startsWith(afterBracket) ||
548
- '[GUARDIAN_TIMEOUT]'.startsWith(afterBracket) ||
549
- '[GUARDIAN_UNAVAILABLE]'.startsWith(afterBracket) ||
550
- afterBracket.startsWith('[ASK_GUARDIAN_APPROVAL:') ||
551
- afterBracket.startsWith('[ASK_GUARDIAN:') ||
552
- afterBracket.startsWith('[USER_ANSWERED:') ||
553
- afterBracket.startsWith('[USER_INSTRUCTION:') ||
554
- afterBracket === '[CALL_OPENING' ||
555
- afterBracket.startsWith('[CALL_OPENING]') ||
556
- afterBracket === '[CALL_OPENING_ACK' ||
557
- afterBracket.startsWith('[CALL_OPENING_ACK]') ||
558
- afterBracket === '[END_CALL' ||
559
- afterBracket.startsWith('[END_CALL]') ||
560
- afterBracket === '[GUARDIAN_TIMEOUT' ||
561
- afterBracket.startsWith('[GUARDIAN_TIMEOUT]') ||
562
- afterBracket === '[GUARDIAN_UNAVAILABLE' ||
563
- afterBracket.startsWith('[GUARDIAN_UNAVAILABLE]');
592
+ "[ASK_GUARDIAN_APPROVAL:".startsWith(afterBracket) ||
593
+ "[ASK_GUARDIAN:".startsWith(afterBracket) ||
594
+ "[USER_ANSWERED:".startsWith(afterBracket) ||
595
+ "[USER_INSTRUCTION:".startsWith(afterBracket) ||
596
+ "[CALL_OPENING]".startsWith(afterBracket) ||
597
+ "[CALL_OPENING_ACK]".startsWith(afterBracket) ||
598
+ "[END_CALL]".startsWith(afterBracket) ||
599
+ "[GUARDIAN_TIMEOUT]".startsWith(afterBracket) ||
600
+ "[GUARDIAN_UNAVAILABLE]".startsWith(afterBracket) ||
601
+ afterBracket.startsWith("[ASK_GUARDIAN_APPROVAL:") ||
602
+ afterBracket.startsWith("[ASK_GUARDIAN:") ||
603
+ afterBracket.startsWith("[USER_ANSWERED:") ||
604
+ afterBracket.startsWith("[USER_INSTRUCTION:") ||
605
+ afterBracket === "[CALL_OPENING" ||
606
+ afterBracket.startsWith("[CALL_OPENING]") ||
607
+ afterBracket === "[CALL_OPENING_ACK" ||
608
+ afterBracket.startsWith("[CALL_OPENING_ACK]") ||
609
+ afterBracket === "[END_CALL" ||
610
+ afterBracket.startsWith("[END_CALL]") ||
611
+ afterBracket === "[GUARDIAN_TIMEOUT" ||
612
+ afterBracket.startsWith("[GUARDIAN_TIMEOUT]") ||
613
+ afterBracket === "[GUARDIAN_UNAVAILABLE" ||
614
+ afterBracket.startsWith("[GUARDIAN_UNAVAILABLE]");
564
615
 
565
616
  if (!couldBeControl) {
566
617
  // Not a control marker prefix — flush up to the next '[' (if any)
567
- const nextBracket = ttsBuffer.indexOf('[', 1);
618
+ const nextBracket = ttsBuffer.indexOf("[", 1);
568
619
  if (nextBracket === -1) {
569
620
  this.relay.sendTextToken(ttsBuffer, false);
570
- ttsBuffer = '';
621
+ ttsBuffer = "";
571
622
  } else {
572
623
  this.relay.sendTextToken(ttsBuffer.slice(0, nextBracket), false);
573
624
  ttsBuffer = ttsBuffer.slice(nextBracket);
@@ -601,30 +652,43 @@ export class CallController {
601
652
  callSessionId: this.callSessionId,
602
653
  content,
603
654
  assistantId: this.assistantId,
604
- guardianContext: this.guardianContext ?? undefined,
655
+ trustContext: this.trustContext ?? undefined,
605
656
  isInbound: this.isInbound,
606
657
  task: this.task,
607
658
  onTextDelta,
608
659
  onComplete,
609
660
  onError,
610
661
  signal: runSignal,
611
- }).then((handle) => {
612
- if (this.isCurrentRun(runVersion)) {
613
- this.currentTurnHandle = handle;
614
- } else {
615
- // Turn was superseded before handle arrived; abort immediately
616
- handle.abort();
617
- }
618
- }).catch((err) => {
619
- reject(err);
620
- });
662
+ })
663
+ .then((handle) => {
664
+ if (this.isCurrentRun(runVersion)) {
665
+ this.currentTurnHandle = handle;
666
+ } else {
667
+ // Turn was superseded before handle arrived; abort immediately
668
+ handle.abort();
669
+ }
670
+ })
671
+ .catch((err) => {
672
+ reject(err);
673
+ });
621
674
 
622
675
  // Defensive: if the turn is aborted (e.g. barge-in) and the event
623
676
  // sink callbacks are never invoked, resolve the promise so it
624
677
  // doesn't hang forever.
625
- runSignal.addEventListener('abort', () => { resolve(); }, { once: true });
678
+ runSignal.addEventListener(
679
+ "abort",
680
+ () => {
681
+ resolve();
682
+ },
683
+ { once: true },
684
+ );
626
685
  });
627
686
 
687
+ // Eagerly mark the rejection as handled so runtimes (e.g. bun) don't
688
+ // flag it as an unhandled rejection when onError fires synchronously
689
+ // inside the Promise constructor before this await adds its handler.
690
+ // The await below still re-throws, caught by the outer try-catch.
691
+ turnComplete.catch(() => {});
628
692
  await turnComplete;
629
693
  if (!this.isCurrentRun(runVersion)) return;
630
694
 
@@ -635,7 +699,7 @@ export class CallController {
635
699
  }
636
700
 
637
701
  // Signal end of this turn's speech
638
- this.relay.sendTextToken('', true);
702
+ this.relay.sendTextToken("", true);
639
703
 
640
704
  // Mark the greeting's first response as awaiting ack
641
705
  if (this.lastSentWasOpener && fullResponseText.length > 0) {
@@ -646,12 +710,19 @@ export class CallController {
646
710
  const responseText = fullResponseText;
647
711
 
648
712
  // Record the assistant response event
649
- recordCallEvent(this.callSessionId, 'assistant_spoke', { text: responseText });
713
+ recordCallEvent(this.callSessionId, "assistant_spoke", {
714
+ text: responseText,
715
+ });
650
716
  const spokenText = stripInternalSpeechMarkers(responseText).trim();
651
717
  if (spokenText.length > 0) {
652
718
  const session = getCallSession(this.callSessionId);
653
719
  if (session) {
654
- fireCallTranscriptNotifier(session.conversationId, this.callSessionId, 'assistant', spokenText);
720
+ fireCallTranscriptNotifier(
721
+ session.conversationId,
722
+ this.callSessionId,
723
+ "assistant",
724
+ spokenText,
725
+ );
655
726
  }
656
727
  }
657
728
 
@@ -660,16 +731,34 @@ export class CallController {
660
731
  // `}]` inside JSON string values does not truncate the payload or
661
732
  // leak partial JSON into TTS output.
662
733
  const approvalMatch = extractBalancedJson(responseText);
663
- let toolApprovalMeta: { question: string; toolName: string; inputDigest: string } | null = null;
734
+ let toolApprovalMeta: {
735
+ question: string;
736
+ toolName: string;
737
+ inputDigest: string;
738
+ } | null = null;
664
739
  if (approvalMatch) {
665
740
  try {
666
- const parsed = JSON.parse(approvalMatch.json) as { question?: string; toolName?: string; input?: Record<string, unknown> };
741
+ const parsed = JSON.parse(approvalMatch.json) as {
742
+ question?: string;
743
+ toolName?: string;
744
+ input?: Record<string, unknown>;
745
+ };
667
746
  if (parsed.question && parsed.toolName && parsed.input) {
668
- const digest = computeToolApprovalDigest(parsed.toolName, parsed.input);
669
- toolApprovalMeta = { question: parsed.question, toolName: parsed.toolName, inputDigest: digest };
747
+ const digest = computeToolApprovalDigest(
748
+ parsed.toolName,
749
+ parsed.input,
750
+ );
751
+ toolApprovalMeta = {
752
+ question: parsed.question,
753
+ toolName: parsed.toolName,
754
+ inputDigest: digest,
755
+ };
670
756
  }
671
757
  } catch {
672
- log.warn({ callSessionId: this.callSessionId }, 'Failed to parse ASK_GUARDIAN_APPROVAL JSON payload');
758
+ log.warn(
759
+ { callSessionId: this.callSessionId },
760
+ "Failed to parse ASK_GUARDIAN_APPROVAL JSON payload",
761
+ );
673
762
  }
674
763
  }
675
764
 
@@ -677,29 +766,44 @@ export class CallController {
677
766
  ? null // structured approval takes precedence
678
767
  : responseText.match(ASK_GUARDIAN_CAPTURE_REGEX);
679
768
 
680
- const questionText = toolApprovalMeta?.question ?? (askMatch ? askMatch[1] : null);
769
+ const questionText =
770
+ toolApprovalMeta?.question ?? (askMatch ? askMatch[1] : null);
681
771
 
682
772
  if (questionText) {
683
773
  if (this.isCallerGuardian()) {
684
774
  // Caller IS the guardian — don't dispatch cross-channel.
685
775
  // Queue an instruction so the next turn asks them directly.
686
- log.info({ callSessionId: this.callSessionId }, 'Caller is guardian — skipping ASK_GUARDIAN dispatch, asking directly');
687
- this.pendingInstructions.push(`You just tried to use [ASK_GUARDIAN] but the person on the phone IS your guardian. Ask them directly: "${questionText}"`);
776
+ log.info(
777
+ { callSessionId: this.callSessionId },
778
+ "Caller is guardian — skipping ASK_GUARDIAN dispatch, asking directly",
779
+ );
780
+ this.pendingInstructions.push(
781
+ `You just tried to use [ASK_GUARDIAN] but the person on the phone IS your guardian. Ask them directly: "${questionText}"`,
782
+ );
688
783
  // Fall through to normal turn completion (idle + flushPendingInstructions)
689
784
  } else if (this.guardianUnavailableForCall) {
690
785
  // Guardian already timed out earlier in this call — skip the full
691
786
  // consultation wait and immediately tell the model to proceed
692
787
  // without guardian input.
693
- log.info({ callSessionId: this.callSessionId }, 'Guardian unavailable for call — skipping ASK_GUARDIAN wait');
694
- recordCallEvent(this.callSessionId, 'guardian_unavailable_skipped', { question: questionText });
788
+ log.info(
789
+ { callSessionId: this.callSessionId },
790
+ "Guardian unavailable for call — skipping ASK_GUARDIAN wait",
791
+ );
792
+ recordCallEvent(this.callSessionId, "guardian_unavailable_skipped", {
793
+ question: questionText,
794
+ });
695
795
  this.pendingInstructions.push(
696
- `[GUARDIAN_UNAVAILABLE] You tried to consult your guardian again, but they were already unreachable earlier in this call. `
697
- + `Do NOT use [ASK_GUARDIAN] again. Instead, let the caller know you cannot reach the guardian right now, `
698
- + `and continue the conversation by asking if there is anything else you can help with or if they would like a callback. `
699
- + `The unanswered question was: "${questionText}"`,
796
+ `[GUARDIAN_UNAVAILABLE] You tried to consult your guardian again, but they were already unreachable earlier in this call. ` +
797
+ `Do NOT use [ASK_GUARDIAN] again. Instead, let the caller know you cannot reach the guardian right now, ` +
798
+ `and continue the conversation by asking if there is anything else you can help with or if they would like a callback. ` +
799
+ `The unanswered question was: "${questionText}"`,
700
800
  );
701
801
  // Fall through to normal turn completion (idle + flushPendingInstructions)
702
- } else if (this.pendingInstructions.some((instr) => instr.startsWith('[USER_ANSWERED:'))) {
802
+ } else if (
803
+ this.pendingInstructions.some((instr) =>
804
+ instr.startsWith("[USER_ANSWERED:"),
805
+ )
806
+ ) {
703
807
  // A guardian answer arrived mid-turn and is queued in
704
808
  // pendingInstructions but hasn't been flushed yet. The in-flight
705
809
  // LLM response was generated without knowledge of this answer, so
@@ -707,16 +811,24 @@ export class CallController {
707
811
  // desynchronize the flow. Skip this consultation — the answer will
708
812
  // be flushed on the next turn, and if the model still needs to
709
813
  // consult a guardian, it will emit another ASK_GUARDIAN then.
710
- log.info({ callSessionId: this.callSessionId }, 'Deferring ASK_GUARDIAN — queued USER_ANSWERED pending');
711
- recordCallEvent(this.callSessionId, 'guardian_consult_deferred', { question: questionText });
814
+ log.info(
815
+ { callSessionId: this.callSessionId },
816
+ "Deferring ASK_GUARDIAN — queued USER_ANSWERED pending",
817
+ );
818
+ recordCallEvent(this.callSessionId, "guardian_consult_deferred", {
819
+ question: questionText,
820
+ });
712
821
  // Fall through to normal turn completion (idle + flushPendingInstructions)
713
822
  } else {
714
823
  // Determine the effective tool metadata for this ask. If the new
715
824
  // ask has structured tool metadata, use it; otherwise inherit from
716
825
  // the prior pending consultation (preserves tool scope on re-asks).
717
826
  const effectiveToolMeta = toolApprovalMeta
718
- ? { toolName: toolApprovalMeta.toolName, inputDigest: toolApprovalMeta.inputDigest }
719
- : this.pendingGuardianInput?.toolApprovalMeta ?? null;
827
+ ? {
828
+ toolName: toolApprovalMeta.toolName,
829
+ inputDigest: toolApprovalMeta.inputDigest,
830
+ }
831
+ : (this.pendingGuardianInput?.toolApprovalMeta ?? null);
720
832
 
721
833
  // Coalesce repeated identical asks: if a consultation is already
722
834
  // pending for the same tool/action (or same informational question),
@@ -724,18 +836,28 @@ export class CallController {
724
836
  if (this.pendingGuardianInput) {
725
837
  const isSameToolAction =
726
838
  effectiveToolMeta && this.pendingGuardianInput.toolApprovalMeta
727
- ? effectiveToolMeta.toolName === this.pendingGuardianInput.toolApprovalMeta.toolName
728
- && effectiveToolMeta.inputDigest === this.pendingGuardianInput.toolApprovalMeta.inputDigest
729
- : !effectiveToolMeta && !this.pendingGuardianInput.toolApprovalMeta;
839
+ ? effectiveToolMeta.toolName ===
840
+ this.pendingGuardianInput.toolApprovalMeta.toolName &&
841
+ effectiveToolMeta.inputDigest ===
842
+ this.pendingGuardianInput.toolApprovalMeta.inputDigest
843
+ : !effectiveToolMeta &&
844
+ !this.pendingGuardianInput.toolApprovalMeta;
730
845
 
731
846
  if (isSameToolAction) {
732
847
  // Same tool/action — coalesce. Keep the existing consultation
733
848
  // alive and skip creating a new request.
734
849
  log.info(
735
- { callSessionId: this.callSessionId, questionId: this.pendingGuardianInput.questionId },
736
- 'Coalescing repeated ASK_GUARDIAN — same tool/action already pending',
850
+ {
851
+ callSessionId: this.callSessionId,
852
+ questionId: this.pendingGuardianInput.questionId,
853
+ },
854
+ "Coalescing repeated ASK_GUARDIAN — same tool/action already pending",
855
+ );
856
+ recordCallEvent(
857
+ this.callSessionId,
858
+ "guardian_consult_coalesced",
859
+ { question: questionText },
737
860
  );
738
- recordCallEvent(this.callSessionId, 'guardian_consult_coalesced', { question: questionText });
739
861
  // Fall through to normal turn completion (idle + flushPendingInstructions)
740
862
  } else {
741
863
  // Materially different intent — supersede the old consultation.
@@ -744,14 +866,19 @@ export class CallController {
744
866
  // Expire the previous consultation's storage records so stale
745
867
  // guardian answers cannot match the old request.
746
868
  expirePendingQuestions(this.callSessionId);
747
- const previousRequest = getPendingCanonicalRequestByCallSessionId(this.callSessionId);
869
+ const previousRequest = getPendingCanonicalRequestByCallSessionId(
870
+ this.callSessionId,
871
+ );
748
872
  if (previousRequest) {
749
873
  // Immediately expire with 'superseded' reason to prevent
750
874
  // stale answers from resolving the old request.
751
875
  expireCanonicalGuardianRequest(previousRequest.id);
752
876
  log.info(
753
- { callSessionId: this.callSessionId, requestId: previousRequest.id },
754
- 'Superseded guardian action request (materially different intent)',
877
+ {
878
+ callSessionId: this.callSessionId,
879
+ requestId: previousRequest.id,
880
+ },
881
+ "Superseded guardian action request (materially different intent)",
755
882
  );
756
883
  }
757
884
 
@@ -761,7 +888,11 @@ export class CallController {
761
888
  // The previous request ID is passed through so the dispatch
762
889
  // can backfill supersession chain metadata (superseded_by_request_id)
763
890
  // once the new request has been created.
764
- this.dispatchNewConsultation(questionText, effectiveToolMeta, previousRequest?.id ?? null);
891
+ this.dispatchNewConsultation(
892
+ questionText,
893
+ effectiveToolMeta,
894
+ previousRequest?.id ?? null,
895
+ );
765
896
  }
766
897
  } else {
767
898
  // No prior consultation — dispatch fresh
@@ -785,7 +916,9 @@ export class CallController {
785
916
  // a completed call with a dangling pendingQuestion, and guardian
786
917
  // replies are cleanly rejected instead of hitting answerCall failures.
787
918
  expirePendingQuestions(this.callSessionId);
788
- const previousRequest = getPendingCanonicalRequestByCallSessionId(this.callSessionId);
919
+ const previousRequest = getPendingCanonicalRequestByCallSessionId(
920
+ this.callSessionId,
921
+ );
789
922
  if (previousRequest) {
790
923
  expireCanonicalGuardianRequest(previousRequest.id);
791
924
  }
@@ -795,37 +928,70 @@ export class CallController {
795
928
 
796
929
  const currentSession = getCallSession(this.callSessionId);
797
930
  const shouldNotifyCompletion = currentSession
798
- ? currentSession.status !== 'completed' && currentSession.status !== 'failed' && currentSession.status !== 'cancelled'
931
+ ? currentSession.status !== "completed" &&
932
+ currentSession.status !== "failed" &&
933
+ currentSession.status !== "cancelled"
799
934
  : false;
800
935
 
801
- this.relay.endSession('Call completed');
802
- updateCallSession(this.callSessionId, { status: 'completed', endedAt: Date.now() });
803
- recordCallEvent(this.callSessionId, 'call_ended', { reason: 'completed' });
936
+ this.relay.endSession("Call completed");
937
+ updateCallSession(this.callSessionId, {
938
+ status: "completed",
939
+ endedAt: Date.now(),
940
+ });
941
+ recordCallEvent(this.callSessionId, "call_ended", {
942
+ reason: "completed",
943
+ });
804
944
 
805
945
  // Notify the voice conversation
806
946
  if (shouldNotifyCompletion && currentSession) {
807
- persistCallCompletionMessage(currentSession.conversationId, this.callSessionId).catch((err) => {
808
- log.error({ err, conversationId: currentSession.conversationId, callSessionId: this.callSessionId }, 'Failed to persist call completion message');
947
+ persistCallCompletionMessage(
948
+ currentSession.conversationId,
949
+ this.callSessionId,
950
+ ).catch((err) => {
951
+ log.error(
952
+ {
953
+ err,
954
+ conversationId: currentSession.conversationId,
955
+ callSessionId: this.callSessionId,
956
+ },
957
+ "Failed to persist call completion message",
958
+ );
809
959
  });
810
- fireCallCompletionNotifier(currentSession.conversationId, this.callSessionId);
960
+ fireCallCompletionNotifier(
961
+ currentSession.conversationId,
962
+ this.callSessionId,
963
+ );
811
964
  }
812
965
 
813
966
  // Post a pointer message in the initiating conversation
814
967
  if (currentSession?.initiatedFromConversationId) {
815
- const durationMs = currentSession.startedAt ? Date.now() - currentSession.startedAt : 0;
816
- addPointerMessage(currentSession.initiatedFromConversationId, 'completed', currentSession.toNumber, {
817
- duration: durationMs > 0 ? formatDuration(durationMs) : undefined,
818
- }).catch((err) => {
819
- log.warn({ conversationId: currentSession.initiatedFromConversationId, err }, 'Skipping pointer write — origin conversation may no longer exist');
968
+ const durationMs = currentSession.startedAt
969
+ ? Date.now() - currentSession.startedAt
970
+ : 0;
971
+ addPointerMessage(
972
+ currentSession.initiatedFromConversationId,
973
+ "completed",
974
+ currentSession.toNumber,
975
+ {
976
+ duration: durationMs > 0 ? formatDuration(durationMs) : undefined,
977
+ },
978
+ ).catch((err) => {
979
+ log.warn(
980
+ {
981
+ conversationId: currentSession.initiatedFromConversationId,
982
+ err,
983
+ },
984
+ "Skipping pointer write — origin conversation may no longer exist",
985
+ );
820
986
  });
821
987
  }
822
- this.state = 'idle';
988
+ this.state = "idle";
823
989
  return;
824
990
  }
825
991
 
826
992
  // Normal turn complete — restart silence detection and flush any
827
993
  // instructions that arrived while the LLM was active.
828
- this.state = 'idle';
994
+ this.state = "idle";
829
995
  this.currentTurnHandle = null;
830
996
  this.resetSilenceTimer();
831
997
  this.flushPendingInstructions();
@@ -839,24 +1005,30 @@ export class CallController {
839
1005
  errName: err instanceof Error ? err.name : typeof err,
840
1006
  stale: !this.isCurrentRun(runVersion),
841
1007
  },
842
- 'Voice turn aborted',
1008
+ "Voice turn aborted",
843
1009
  );
844
1010
  if (this.isCurrentRun(runVersion)) {
845
- this.state = 'idle';
1011
+ this.state = "idle";
846
1012
  this.resetSilenceTimer();
847
1013
  }
848
1014
  return;
849
1015
  }
850
1016
  if (!this.isCurrentRun(runVersion)) {
851
1017
  log.debug(
852
- { callSessionId: this.callSessionId, errName: err instanceof Error ? err.name : typeof err },
853
- 'Ignoring stale voice turn error from superseded turn',
1018
+ {
1019
+ callSessionId: this.callSessionId,
1020
+ errName: err instanceof Error ? err.name : typeof err,
1021
+ },
1022
+ "Ignoring stale voice turn error from superseded turn",
854
1023
  );
855
1024
  return;
856
1025
  }
857
- log.error({ err, callSessionId: this.callSessionId }, 'Voice turn error');
858
- this.relay.sendTextToken('I\'m sorry, I encountered a technical issue. Could you repeat that?', true);
859
- this.state = 'idle';
1026
+ log.error({ err, callSessionId: this.callSessionId }, "Voice turn error");
1027
+ this.relay.sendTextToken(
1028
+ "I'm sorry, I encountered a technical issue. Could you repeat that?",
1029
+ true,
1030
+ );
1031
+ this.state = "idle";
860
1032
  this.resetSilenceTimer();
861
1033
  this.flushPendingInstructions();
862
1034
  }
@@ -864,8 +1036,7 @@ export class CallController {
864
1036
 
865
1037
  private isExpectedAbortError(err: unknown): boolean {
866
1038
  if (!(err instanceof Error)) return false;
867
- return err.name === 'AbortError'
868
- || err.name === 'APIUserAbortError';
1039
+ return err.name === "AbortError" || err.name === "APIUserAbortError";
869
1040
  }
870
1041
 
871
1042
  private isCurrentRun(runVersion: number): boolean {
@@ -873,7 +1044,7 @@ export class CallController {
873
1044
  }
874
1045
 
875
1046
  private isCallerGuardian(): boolean {
876
- return this.guardianContext?.trustClass === 'guardian';
1047
+ return this.trustContext?.trustClass === "guardian";
877
1048
  }
878
1049
 
879
1050
  /**
@@ -888,14 +1059,23 @@ export class CallController {
888
1059
  effectiveToolMeta: { toolName: string; inputDigest: string } | null,
889
1060
  supersededRequestId: string | null,
890
1061
  ): void {
891
- const pendingQuestion = createPendingQuestion(this.callSessionId, questionText);
892
- updateCallSession(this.callSessionId, { status: 'waiting_on_user' });
893
- recordCallEvent(this.callSessionId, 'user_question_asked', { question: questionText });
1062
+ const pendingQuestion = createPendingQuestion(
1063
+ this.callSessionId,
1064
+ questionText,
1065
+ );
1066
+ updateCallSession(this.callSessionId, { status: "waiting_on_user" });
1067
+ recordCallEvent(this.callSessionId, "user_question_asked", {
1068
+ question: questionText,
1069
+ });
894
1070
 
895
1071
  // Notify the conversation that a question was asked
896
1072
  const session = getCallSession(this.callSessionId);
897
1073
  if (session) {
898
- fireCallQuestionNotifier(session.conversationId, this.callSessionId, questionText);
1074
+ fireCallQuestionNotifier(
1075
+ session.conversationId,
1076
+ this.callSessionId,
1077
+ questionText,
1078
+ );
899
1079
 
900
1080
  // Dispatch guardian action request to all configured channels
901
1081
  // Capture the pending question ID in a closure for stable lookup
@@ -914,13 +1094,19 @@ export class CallController {
914
1094
  // Backfill supersession chain: now that the new request exists in
915
1095
  // the store, link the old request to the new one.
916
1096
  if (supersededRequestId) {
917
- const newRequest = getCanonicalRequestByPendingQuestionId(stablePendingQuestionId);
1097
+ const newRequest = getCanonicalRequestByPendingQuestionId(
1098
+ stablePendingQuestionId,
1099
+ );
918
1100
  if (newRequest) {
919
1101
  // Canonical store does not track supersession metadata;
920
1102
  // the old request was already expired above.
921
1103
  log.info(
922
- { callSessionId: this.callSessionId, oldRequestId: supersededRequestId, newRequestId: newRequest.id },
923
- 'Supersession chain: new canonical request created',
1104
+ {
1105
+ callSessionId: this.callSessionId,
1106
+ oldRequestId: supersededRequestId,
1107
+ newRequestId: newRequest.id,
1108
+ },
1109
+ "Supersession chain: new canonical request created",
924
1110
  );
925
1111
  }
926
1112
  }
@@ -931,22 +1117,36 @@ export class CallController {
931
1117
  // record, not the global controller state.
932
1118
  const consultationTimer = setTimeout(() => {
933
1119
  // Only fire if this consultation is still the active one
934
- if (!this.pendingGuardianInput || this.pendingGuardianInput.questionId !== pendingQuestion.id) return;
1120
+ if (
1121
+ !this.pendingGuardianInput ||
1122
+ this.pendingGuardianInput.questionId !== pendingQuestion.id
1123
+ )
1124
+ return;
935
1125
 
936
- log.info({ callSessionId: this.callSessionId }, 'Guardian consultation timed out');
1126
+ log.info(
1127
+ { callSessionId: this.callSessionId },
1128
+ "Guardian consultation timed out",
1129
+ );
937
1130
 
938
1131
  // Mark the linked guardian action request as timed out and
939
1132
  // send expiry notices to guardian destinations. Deliveries
940
1133
  // must be captured before markTimedOutWithReason changes
941
1134
  // their status.
942
- const pendingActionRequest = getPendingCanonicalRequestByCallSessionId(this.callSessionId);
1135
+ const pendingActionRequest = getPendingCanonicalRequestByCallSessionId(
1136
+ this.callSessionId,
1137
+ );
943
1138
  if (pendingActionRequest) {
944
- const canonicalDeliveries = listCanonicalGuardianDeliveries(pendingActionRequest.id);
1139
+ const canonicalDeliveries = listCanonicalGuardianDeliveries(
1140
+ pendingActionRequest.id,
1141
+ );
945
1142
  // Expire the canonical request and its deliveries
946
1143
  expireCanonicalGuardianRequest(pendingActionRequest.id);
947
1144
  log.info(
948
- { callSessionId: this.callSessionId, requestId: pendingActionRequest.id },
949
- 'Marked canonical guardian request as timed out',
1145
+ {
1146
+ callSessionId: this.callSessionId,
1147
+ requestId: pendingActionRequest.id,
1148
+ },
1149
+ "Marked canonical guardian request as timed out",
950
1150
  );
951
1151
  void sendGuardianExpiryNotices(
952
1152
  canonicalDeliveries,
@@ -955,8 +1155,12 @@ export class CallController {
955
1155
  () => mintDaemonDeliveryToken(),
956
1156
  ).catch((err) => {
957
1157
  log.error(
958
- { err, callSessionId: this.callSessionId, requestId: pendingActionRequest.id },
959
- 'Failed to send guardian action expiry notices after call timeout',
1158
+ {
1159
+ err,
1160
+ callSessionId: this.callSessionId,
1161
+ requestId: pendingActionRequest.id,
1162
+ },
1163
+ "Failed to send guardian action expiry notices after call timeout",
960
1164
  );
961
1165
  });
962
1166
  }
@@ -964,22 +1168,24 @@ export class CallController {
964
1168
  // Expire pending questions and update call state
965
1169
  expirePendingQuestions(this.callSessionId);
966
1170
  this.pendingGuardianInput = null;
967
- updateCallSession(this.callSessionId, { status: 'in_progress' });
1171
+ updateCallSession(this.callSessionId, { status: "in_progress" });
968
1172
  this.guardianUnavailableForCall = true;
969
- recordCallEvent(this.callSessionId, 'guardian_consultation_timed_out', { question: questionText });
1173
+ recordCallEvent(this.callSessionId, "guardian_consultation_timed_out", {
1174
+ question: questionText,
1175
+ });
970
1176
 
971
1177
  // Inject timeout instruction so the model addresses it on the
972
1178
  // next turn. If idle, flush immediately; otherwise it merges
973
1179
  // into the next turn completion.
974
1180
  const timeoutInstruction =
975
- `[GUARDIAN_TIMEOUT] Your guardian did not respond in time to your question: "${questionText}". `
976
- + `Apologize to the caller for the delay, let them know you were unable to reach your guardian, `
977
- + `ask if they would like to leave a message or receive a callback, `
978
- + `and ask if there are any other questions you can help with right now.`;
1181
+ `[GUARDIAN_TIMEOUT] Your guardian did not respond in time to your question: "${questionText}". ` +
1182
+ `Apologize to the caller for the delay, let them know you were unable to reach your guardian, ` +
1183
+ `ask if they would like to leave a message or receive a callback, ` +
1184
+ `and ask if there are any other questions you can help with right now.`;
979
1185
 
980
1186
  this.pendingInstructions.push(timeoutInstruction);
981
1187
 
982
- if (this.state === 'idle') {
1188
+ if (this.state === "idle") {
983
1189
  this.resetSilenceTimer();
984
1190
  this.flushPendingInstructions();
985
1191
  }
@@ -997,20 +1203,24 @@ export class CallController {
997
1203
  * Drain any instructions that were queued while the LLM was active.
998
1204
  */
999
1205
  private flushPendingInstructions(): void {
1206
+ if (this.destroyed) return;
1000
1207
  if (this.pendingInstructions.length === 0) return;
1001
1208
 
1002
- const parts = this.pendingInstructions.map(
1003
- (instr) => instr.startsWith('[') ? instr : `[USER_INSTRUCTION: ${instr}]`,
1209
+ const parts = this.pendingInstructions.map((instr) =>
1210
+ instr.startsWith("[") ? instr : `[USER_INSTRUCTION: ${instr}]`,
1004
1211
  );
1005
1212
  this.pendingInstructions = [];
1006
1213
 
1007
- const content = parts.join('\n');
1214
+ const content = parts.join("\n");
1008
1215
 
1009
1216
  this.resetSilenceTimer();
1010
1217
 
1011
1218
  // Fire-and-forget so we don't block the current turn's cleanup.
1012
1219
  this.runTurn(content).catch((err) =>
1013
- log.error({ err, callSessionId: this.callSessionId }, 'runTurn failed after flushing queued instructions'),
1220
+ log.error(
1221
+ { err, callSessionId: this.callSessionId },
1222
+ "runTurn failed after flushing queued instructions",
1223
+ ),
1014
1224
  );
1015
1225
  }
1016
1226
 
@@ -1020,44 +1230,83 @@ export class CallController {
1020
1230
 
1021
1231
  if (warningMs > 0) {
1022
1232
  this.durationWarningTimer = setTimeout(() => {
1023
- log.info({ callSessionId: this.callSessionId }, 'Call duration warning');
1233
+ log.info(
1234
+ { callSessionId: this.callSessionId },
1235
+ "Call duration warning",
1236
+ );
1024
1237
  this.relay.sendTextToken(
1025
- 'Just to let you know, we\'re running low on time for this call.',
1238
+ "Just to let you know, we're running low on time for this call.",
1026
1239
  true,
1027
1240
  );
1028
1241
  }, warningMs);
1029
1242
  }
1030
1243
 
1031
1244
  this.durationTimer = setTimeout(() => {
1032
- log.info({ callSessionId: this.callSessionId }, 'Call duration limit reached');
1245
+ log.info(
1246
+ { callSessionId: this.callSessionId },
1247
+ "Call duration limit reached",
1248
+ );
1033
1249
  this.relay.sendTextToken(
1034
- 'I\'m sorry, but we\'ve reached the maximum time for this call. Thank you for your time. Goodbye!',
1250
+ "I'm sorry, but we've reached the maximum time for this call. Thank you for your time. Goodbye!",
1035
1251
  true,
1036
1252
  );
1037
1253
  // Give TTS a moment to play, then end
1038
1254
  this.durationEndTimer = setTimeout(() => {
1039
1255
  const currentSession = getCallSession(this.callSessionId);
1040
1256
  const shouldNotifyCompletion = currentSession
1041
- ? currentSession.status !== 'completed' && currentSession.status !== 'failed' && currentSession.status !== 'cancelled'
1257
+ ? currentSession.status !== "completed" &&
1258
+ currentSession.status !== "failed" &&
1259
+ currentSession.status !== "cancelled"
1042
1260
  : false;
1043
1261
 
1044
- this.relay.endSession('Maximum call duration reached');
1045
- updateCallSession(this.callSessionId, { status: 'completed', endedAt: Date.now() });
1046
- recordCallEvent(this.callSessionId, 'call_ended', { reason: 'max_duration' });
1262
+ this.relay.endSession("Maximum call duration reached");
1263
+ updateCallSession(this.callSessionId, {
1264
+ status: "completed",
1265
+ endedAt: Date.now(),
1266
+ });
1267
+ recordCallEvent(this.callSessionId, "call_ended", {
1268
+ reason: "max_duration",
1269
+ });
1047
1270
  if (shouldNotifyCompletion && currentSession) {
1048
- persistCallCompletionMessage(currentSession.conversationId, this.callSessionId).catch((err) => {
1049
- log.error({ err, conversationId: currentSession.conversationId, callSessionId: this.callSessionId }, 'Failed to persist call completion message');
1271
+ persistCallCompletionMessage(
1272
+ currentSession.conversationId,
1273
+ this.callSessionId,
1274
+ ).catch((err) => {
1275
+ log.error(
1276
+ {
1277
+ err,
1278
+ conversationId: currentSession.conversationId,
1279
+ callSessionId: this.callSessionId,
1280
+ },
1281
+ "Failed to persist call completion message",
1282
+ );
1050
1283
  });
1051
- fireCallCompletionNotifier(currentSession.conversationId, this.callSessionId);
1284
+ fireCallCompletionNotifier(
1285
+ currentSession.conversationId,
1286
+ this.callSessionId,
1287
+ );
1052
1288
  }
1053
1289
 
1054
1290
  // Post a pointer message in the initiating conversation
1055
1291
  if (currentSession?.initiatedFromConversationId) {
1056
- const durationMs = currentSession.startedAt ? Date.now() - currentSession.startedAt : 0;
1057
- addPointerMessage(currentSession.initiatedFromConversationId, 'completed', currentSession.toNumber, {
1058
- duration: durationMs > 0 ? formatDuration(durationMs) : undefined,
1059
- }).catch((err) => {
1060
- log.warn({ conversationId: currentSession.initiatedFromConversationId, err }, 'Skipping pointer write — origin conversation may no longer exist');
1292
+ const durationMs = currentSession.startedAt
1293
+ ? Date.now() - currentSession.startedAt
1294
+ : 0;
1295
+ addPointerMessage(
1296
+ currentSession.initiatedFromConversationId,
1297
+ "completed",
1298
+ currentSession.toNumber,
1299
+ {
1300
+ duration: durationMs > 0 ? formatDuration(durationMs) : undefined,
1301
+ },
1302
+ ).catch((err) => {
1303
+ log.warn(
1304
+ {
1305
+ conversationId: currentSession.initiatedFromConversationId,
1306
+ err,
1307
+ },
1308
+ "Skipping pointer write — origin conversation may no longer exist",
1309
+ );
1061
1310
  });
1062
1311
  }
1063
1312
  }, 3000);
@@ -1066,18 +1315,28 @@ export class CallController {
1066
1315
 
1067
1316
  private resetSilenceTimer(): void {
1068
1317
  if (this.silenceTimer) clearTimeout(this.silenceTimer);
1318
+ if (this.destroyed) return;
1069
1319
  this.silenceTimer = setTimeout(() => {
1070
1320
  // During guardian wait states, the relay heartbeat timer handles
1071
1321
  // periodic updates — suppress the generic "Are you still there?"
1072
1322
  // which is confusing when the caller is waiting on a decision.
1073
1323
  // Two paths: in-call consultation (pendingGuardianInput) and
1074
1324
  // inbound access-request wait (relay state).
1075
- if (this.pendingGuardianInput || this.relay.getConnectionState() === 'awaiting_guardian_decision') {
1076
- log.debug({ callSessionId: this.callSessionId }, 'Silence timeout suppressed during guardian wait');
1325
+ if (
1326
+ this.pendingGuardianInput ||
1327
+ this.relay.getConnectionState() === "awaiting_guardian_decision"
1328
+ ) {
1329
+ log.debug(
1330
+ { callSessionId: this.callSessionId },
1331
+ "Silence timeout suppressed during guardian wait",
1332
+ );
1077
1333
  return;
1078
1334
  }
1079
- log.info({ callSessionId: this.callSessionId }, 'Silence timeout triggered');
1080
- this.relay.sendTextToken('Are you still there?', true);
1335
+ log.info(
1336
+ { callSessionId: this.callSessionId },
1337
+ "Silence timeout triggered",
1338
+ );
1339
+ this.relay.sendTextToken("Are you still there?", true);
1081
1340
  }, getSilenceTimeoutMs());
1082
1341
  }
1083
1342
  }