@vellumai/assistant 0.4.26 → 0.4.29

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 (1301) hide show
  1. package/.env.example +2 -2
  2. package/AGENTS.md +5 -0
  3. package/ARCHITECTURE.md +169 -69
  4. package/Dockerfile +1 -1
  5. package/README.md +111 -112
  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 +10 -9
  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 +3 -0
  15. package/scripts/test.sh +89 -5
  16. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +46 -0
  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 +36 -23
  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__/approval-routes-http.test.ts +2 -2
  24. package/src/__tests__/asset-materialize-tool.test.ts +7 -7
  25. package/src/__tests__/asset-search-tool.test.ts +7 -7
  26. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  27. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +217 -0
  28. package/src/__tests__/call-controller.test.ts +99 -69
  29. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  30. package/src/__tests__/channel-approval-routes.test.ts +113 -70
  31. package/src/__tests__/channel-guardian.test.ts +173 -282
  32. package/src/__tests__/channel-readiness-service.test.ts +6 -2
  33. package/src/__tests__/channel-reply-delivery.test.ts +2 -2
  34. package/src/__tests__/channel-retry-sweep.test.ts +14 -14
  35. package/src/__tests__/checker.test.ts +12 -31
  36. package/src/__tests__/claude-code-tool-profiles.test.ts +1 -1
  37. package/src/__tests__/commit-message-enrichment-service.test.ts +67 -59
  38. package/src/__tests__/compaction.benchmark.test.ts +6 -2
  39. package/src/__tests__/computer-use-tools.test.ts +1 -1
  40. package/src/__tests__/config-schema.test.ts +66 -7
  41. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -29
  42. package/src/__tests__/contacts-tools.test.ts +63 -2
  43. package/src/__tests__/context-overflow-approval.test.ts +141 -0
  44. package/src/__tests__/context-overflow-policy.test.ts +171 -0
  45. package/src/__tests__/context-overflow-reducer.test.ts +533 -0
  46. package/src/__tests__/context-window-manager.test.ts +97 -0
  47. package/src/__tests__/conversation-attention-telegram.test.ts +38 -46
  48. package/src/__tests__/conversation-pairing.test.ts +2 -2
  49. package/src/__tests__/conversation-routes-guardian-reply.test.ts +214 -10
  50. package/src/__tests__/conversation-routes.test.ts +4 -7
  51. package/src/__tests__/credential-broker-browser-fill.test.ts +13 -2
  52. package/src/__tests__/credential-security-e2e.test.ts +1 -1
  53. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  54. package/src/__tests__/credential-vault-unit.test.ts +1 -1
  55. package/src/__tests__/credential-vault.test.ts +11 -8
  56. package/src/__tests__/daemon-lifecycle.test.ts +2 -2
  57. package/src/__tests__/daemon-server-session-init.test.ts +6 -6
  58. package/src/__tests__/delete-managed-skill-tool.test.ts +1 -1
  59. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -2
  60. package/src/__tests__/emit-signal-routing-intent.test.ts +4 -0
  61. package/src/__tests__/encrypted-store.test.ts +10 -7
  62. package/src/__tests__/ephemeral-permissions.test.ts +3 -3
  63. package/src/__tests__/file-edit-tool.test.ts +1 -1
  64. package/src/__tests__/file-read-tool.test.ts +1 -1
  65. package/src/__tests__/file-write-tool.test.ts +1 -1
  66. package/src/__tests__/fixtures/credential-security-fixtures.ts +87 -64
  67. package/src/__tests__/fixtures/media-reuse-fixtures.ts +37 -31
  68. package/src/__tests__/fixtures/mock-signup-server.ts +171 -115
  69. package/src/__tests__/fixtures/proxy-fixtures.ts +39 -39
  70. package/src/__tests__/followup-tools.test.ts +1 -1
  71. package/src/__tests__/gateway-only-guard.test.ts +3 -0
  72. package/src/__tests__/guardian-actions-endpoint.test.ts +543 -1
  73. package/src/__tests__/guardian-control-plane-policy.test.ts +15 -15
  74. package/src/__tests__/guardian-dispatch.test.ts +79 -1
  75. package/src/__tests__/guardian-grant-minting.test.ts +14 -14
  76. package/src/__tests__/guardian-outbound-http.test.ts +1 -2
  77. package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -41
  78. package/src/__tests__/guardian-routing-invariants.test.ts +2 -5
  79. package/src/__tests__/guardian-routing-state.test.ts +36 -52
  80. package/src/__tests__/guardian-verification-intent-routing.test.ts +4 -6
  81. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  82. package/src/__tests__/handle-user-message-secret-resume.test.ts +39 -1
  83. package/src/__tests__/handlers-cu-observation-blob.test.ts +21 -10
  84. package/src/__tests__/handlers-telegram-config.test.ts +14 -14
  85. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +23 -2
  86. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  87. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  88. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  89. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  90. package/src/__tests__/heartbeat-service.test.ts +45 -2
  91. package/src/__tests__/host-file-edit-tool.test.ts +1 -1
  92. package/src/__tests__/host-file-read-tool.test.ts +1 -1
  93. package/src/__tests__/host-file-write-tool.test.ts +1 -1
  94. package/src/__tests__/host-shell-tool.test.ts +1 -1
  95. package/src/__tests__/inbound-invite-redemption.test.ts +16 -18
  96. package/src/__tests__/ingress-reconcile.test.ts +2 -2
  97. package/src/__tests__/ingress-routes-http.test.ts +2 -1
  98. package/src/__tests__/integrations-cli.test.ts +256 -0
  99. package/src/__tests__/intent-routing.test.ts +4 -5
  100. package/src/__tests__/invite-redemption-service.test.ts +4 -3
  101. package/src/__tests__/ipc-snapshot.test.ts +28 -0
  102. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -1
  103. package/src/__tests__/mcp-cli.test.ts +136 -57
  104. package/src/__tests__/mcp-client-auth.test.ts +95 -0
  105. package/src/__tests__/media-generate-image.test.ts +2 -2
  106. package/src/__tests__/media-reuse-story.e2e.test.ts +8 -8
  107. package/src/__tests__/memory-regressions.test.ts +6 -6
  108. package/src/__tests__/messaging-send-tool.test.ts +1 -1
  109. package/src/__tests__/migration-cross-version-compatibility.test.ts +1855 -0
  110. package/src/__tests__/migration-export-http.test.ts +540 -0
  111. package/src/__tests__/migration-import-commit-http.test.ts +823 -0
  112. package/src/__tests__/migration-import-preflight-http.test.ts +755 -0
  113. package/src/__tests__/migration-parity-persistence.test.ts +1854 -0
  114. package/src/__tests__/migration-transport.test.ts +904 -0
  115. package/src/__tests__/migration-validate-http.test.ts +698 -0
  116. package/src/__tests__/migration-wizard.test.ts +1289 -0
  117. package/src/__tests__/non-member-access-request.test.ts +17 -17
  118. package/src/__tests__/notification-decision-strategy.test.ts +110 -2
  119. package/src/__tests__/notification-deep-link.test.ts +18 -0
  120. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  121. package/src/__tests__/oauth2-gateway-transport.test.ts +1 -1
  122. package/src/__tests__/playbook-execution.test.ts +1 -1
  123. package/src/__tests__/playbook-tools.test.ts +1 -1
  124. package/src/__tests__/provider-streaming.benchmark.test.ts +3 -1
  125. package/src/__tests__/proxy-approval-callback.test.ts +1 -1
  126. package/src/__tests__/qdrant-manager.test.ts +40 -11
  127. package/src/__tests__/rebind-secrets-screen.test.ts +839 -0
  128. package/src/__tests__/recording-handler.test.ts +2 -2
  129. package/src/__tests__/recording-intent-handler.test.ts +3 -3
  130. package/src/__tests__/recording-state-machine.test.ts +2 -2
  131. package/src/__tests__/relay-server.test.ts +506 -227
  132. package/src/__tests__/reminder-store.test.ts +8 -0
  133. package/src/__tests__/reminder.test.ts +8 -0
  134. package/src/__tests__/{resolve-guardian-trust-class.test.ts → resolve-trust-class.test.ts} +11 -17
  135. package/src/__tests__/scaffold-managed-skill-tool.test.ts +1 -1
  136. package/src/__tests__/schedule-tools.test.ts +1 -1
  137. package/src/__tests__/script-proxy-certs.test.ts +1 -1
  138. package/src/__tests__/script-proxy-connect-tunnel.test.ts +2 -3
  139. package/src/__tests__/script-proxy-decision-trace.test.ts +2 -2
  140. package/src/__tests__/script-proxy-http-forwarder.test.ts +1 -1
  141. package/src/__tests__/script-proxy-injection-runtime.test.ts +5 -5
  142. package/src/__tests__/script-proxy-mitm-handler.test.ts +4 -4
  143. package/src/__tests__/script-proxy-policy-runtime.test.ts +2 -2
  144. package/src/__tests__/script-proxy-policy.test.ts +2 -2
  145. package/src/__tests__/script-proxy-session-manager.test.ts +4 -7
  146. package/src/__tests__/script-proxy-session-runtime.test.ts +1 -6
  147. package/src/__tests__/secret-onetime-send.test.ts +4 -4
  148. package/src/__tests__/secret-scanner-executor.test.ts +2 -2
  149. package/src/__tests__/send-endpoint-busy.test.ts +11 -9
  150. package/src/__tests__/send-notification-tool.test.ts +2 -2
  151. package/src/__tests__/session-abort-tool-results.test.ts +17 -2
  152. package/src/__tests__/session-agent-loop.test.ts +456 -35
  153. package/src/__tests__/session-confirmation-signals.test.ts +3 -2
  154. package/src/__tests__/session-conflict-gate.test.ts +20 -3
  155. package/src/__tests__/session-init.benchmark.test.ts +2 -2
  156. package/src/__tests__/session-load-history-repair.test.ts +7 -7
  157. package/src/__tests__/session-pre-run-repair.test.ts +17 -2
  158. package/src/__tests__/session-profile-injection.test.ts +20 -3
  159. package/src/__tests__/session-provider-retry-repair.test.ts +86 -6
  160. package/src/__tests__/session-queue.test.ts +33 -18
  161. package/src/__tests__/session-runtime-assembly.test.ts +147 -1
  162. package/src/__tests__/session-runtime-workspace.test.ts +40 -0
  163. package/src/__tests__/session-slash-known.test.ts +21 -3
  164. package/src/__tests__/session-slash-queue.test.ts +17 -2
  165. package/src/__tests__/session-slash-unknown.test.ts +17 -2
  166. package/src/__tests__/session-surfaces-deselection.test.ts +208 -0
  167. package/src/__tests__/session-workspace-cache-state.test.ts +2 -2
  168. package/src/__tests__/session-workspace-injection.test.ts +17 -2
  169. package/src/__tests__/session-workspace-tool-tracking.test.ts +17 -2
  170. package/src/__tests__/shell-credential-ref.test.ts +1 -1
  171. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  172. package/src/__tests__/skill-load-feature-flag.test.ts +1 -1
  173. package/src/__tests__/skill-load-tool.test.ts +1 -1
  174. package/src/__tests__/skill-script-runner-host.test.ts +1 -1
  175. package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -1
  176. package/src/__tests__/skill-script-runner.test.ts +1 -1
  177. package/src/__tests__/skill-tool-factory.test.ts +1 -1
  178. package/src/__tests__/slack-skill.test.ts +3 -2
  179. package/src/__tests__/subagent-tools.test.ts +3 -3
  180. package/src/__tests__/swarm-recursion.test.ts +1 -1
  181. package/src/__tests__/swarm-session-integration.test.ts +1 -1
  182. package/src/__tests__/swarm-tool.test.ts +1 -1
  183. package/src/__tests__/task-management-tools.test.ts +1 -1
  184. package/src/__tests__/task-tools.test.ts +1 -1
  185. package/src/__tests__/terminal-tools.test.ts +1 -1
  186. package/src/__tests__/test-support/browser-skill-harness.ts +39 -27
  187. package/src/__tests__/test-support/computer-use-skill-harness.ts +14 -14
  188. package/src/__tests__/tool-approval-handler.test.ts +15 -15
  189. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -1
  190. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
  191. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  192. package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
  193. package/src/__tests__/tool-executor.test.ts +23 -182
  194. package/src/__tests__/tool-grant-request-escalation.test.ts +11 -11
  195. package/src/__tests__/tool-permission-simulate-handler.test.ts +4 -4
  196. package/src/__tests__/transfer-progress-screen.test.ts +1180 -0
  197. package/src/__tests__/trust-context-guards.test.ts +25 -29
  198. package/src/__tests__/trusted-contact-approval-notifier.test.ts +23 -21
  199. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +37 -40
  200. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +29 -25
  201. package/src/__tests__/trusted-contact-multichannel.test.ts +25 -24
  202. package/src/__tests__/trusted-contact-verification.test.ts +63 -77
  203. package/src/__tests__/turn-commit.test.ts +18 -18
  204. package/src/__tests__/twilio-provider.test.ts +7 -7
  205. package/src/__tests__/validation-results-screen.test.ts +1107 -0
  206. package/src/__tests__/view-image-tool.test.ts +1 -1
  207. package/src/__tests__/voice-invite-redemption.test.ts +3 -2
  208. package/src/__tests__/voice-scoped-grant-consumer.test.ts +12 -12
  209. package/src/__tests__/voice-session-bridge.test.ts +24 -24
  210. package/src/agent/attachments.ts +3 -1
  211. package/src/agent/loop.ts +13 -13
  212. package/src/agent/message-types.ts +13 -7
  213. package/src/amazon/cart.ts +59 -32
  214. package/src/amazon/checkout.ts +25 -14
  215. package/src/amazon/client.ts +68 -48
  216. package/src/amazon/product-details.ts +3 -3
  217. package/src/amazon/request-extractor.ts +46 -31
  218. package/src/amazon/search.ts +6 -4
  219. package/src/amazon/session.ts +33 -24
  220. package/src/approvals/AGENTS.md +26 -0
  221. package/src/approvals/approval-primitive.ts +87 -64
  222. package/src/approvals/guardian-decision-primitive.ts +172 -81
  223. package/src/approvals/guardian-request-resolvers.ts +262 -155
  224. package/src/autonomy/autonomy-resolver.ts +7 -5
  225. package/src/autonomy/autonomy-store.ts +34 -19
  226. package/src/autonomy/disposition-mapper.ts +5 -5
  227. package/src/autonomy/index.ts +6 -6
  228. package/src/autonomy/types.ts +7 -3
  229. package/src/browser-extension-relay/client.ts +50 -19
  230. package/src/browser-extension-relay/protocol.ts +11 -11
  231. package/src/browser-extension-relay/server.ts +45 -20
  232. package/src/bundler/app-bundler.ts +75 -50
  233. package/src/bundler/bundle-scanner.ts +145 -41
  234. package/src/bundler/bundle-signer.ts +16 -14
  235. package/src/bundler/signature-verifier.ts +36 -33
  236. package/src/calls/call-constants.ts +10 -3
  237. package/src/calls/call-controller.ts +473 -214
  238. package/src/calls/call-conversation-messages.ts +25 -15
  239. package/src/calls/call-domain.ts +401 -148
  240. package/src/calls/call-pointer-message-composer.ts +26 -21
  241. package/src/calls/call-pointer-messages.ts +52 -28
  242. package/src/calls/call-recovery.ts +53 -37
  243. package/src/calls/call-state-machine.ts +37 -7
  244. package/src/calls/call-state.ts +35 -13
  245. package/src/calls/call-store.ts +165 -77
  246. package/src/calls/elevenlabs-client.ts +39 -20
  247. package/src/calls/guardian-action-sweep.ts +42 -24
  248. package/src/calls/guardian-dispatch.ts +79 -56
  249. package/src/calls/guardian-question-copy.ts +28 -23
  250. package/src/calls/relay-server.ts +1121 -532
  251. package/src/calls/speaker-identification.ts +21 -15
  252. package/src/calls/twilio-config.ts +34 -17
  253. package/src/calls/twilio-provider.ts +108 -55
  254. package/src/calls/twilio-rest.ts +212 -100
  255. package/src/calls/twilio-routes.ts +165 -92
  256. package/src/calls/types.ts +55 -7
  257. package/src/calls/voice-quality.ts +6 -4
  258. package/src/calls/voice-session-bridge.ts +181 -133
  259. package/src/channels/config.ts +17 -13
  260. package/src/channels/types.ts +38 -10
  261. package/src/cli/amazon.ts +333 -227
  262. package/src/cli/config-commands.ts +236 -146
  263. package/src/cli/core-commands.ts +403 -329
  264. package/src/cli/email-guardrails.ts +38 -19
  265. package/src/cli/email.ts +207 -153
  266. package/src/cli/influencer.ts +58 -56
  267. package/src/cli/integrations.ts +362 -0
  268. package/src/cli/ipc-client.ts +24 -19
  269. package/src/cli/map.ts +176 -129
  270. package/src/cli/mcp.ts +260 -152
  271. package/src/cli/sequence.ts +165 -107
  272. package/src/cli/twitter.ts +302 -218
  273. package/src/cli.ts +418 -279
  274. package/src/commands/cc-command-registry.ts +52 -27
  275. package/src/config/agent-schema.ts +217 -134
  276. package/src/config/assistant-feature-flags.ts +23 -18
  277. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +19 -0
  278. package/src/config/bundled-skills/app-builder/tools/app-create.ts +7 -4
  279. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +6 -3
  280. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +7 -4
  281. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +6 -3
  282. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +6 -3
  283. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +7 -4
  284. package/src/config/bundled-skills/app-builder/tools/app-list.ts +6 -3
  285. package/src/config/bundled-skills/app-builder/tools/app-query.ts +6 -3
  286. package/src/config/bundled-skills/app-builder/tools/app-update.ts +6 -3
  287. package/src/config/bundled-skills/browser/tools/browser-click.ts +5 -2
  288. package/src/config/bundled-skills/browser/tools/browser-close.ts +5 -2
  289. package/src/config/bundled-skills/browser/tools/browser-extract.ts +5 -2
  290. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +5 -2
  291. package/src/config/bundled-skills/browser/tools/browser-hover.ts +5 -2
  292. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +5 -2
  293. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +5 -2
  294. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +5 -2
  295. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +5 -2
  296. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +5 -2
  297. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +5 -2
  298. package/src/config/bundled-skills/browser/tools/browser-type.ts +5 -2
  299. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +13 -6
  300. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +5 -2
  301. package/src/config/bundled-skills/claude-code/TOOLS.json +4 -0
  302. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +5 -2
  303. package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
  304. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +6 -3
  305. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +6 -3
  306. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +10 -3
  307. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +6 -3
  308. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +6 -3
  309. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +6 -3
  310. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +10 -3
  311. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +6 -3
  312. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +10 -3
  313. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +10 -3
  314. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +6 -3
  315. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +6 -3
  316. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +6 -3
  317. package/src/config/bundled-skills/configure-settings/SKILL.md +28 -14
  318. package/src/config/bundled-skills/contacts/SKILL.md +446 -15
  319. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +99 -20
  320. package/src/config/bundled-skills/contacts/tools/contact-search.ts +74 -17
  321. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +89 -26
  322. package/src/config/bundled-skills/document/tools/document-create.ts +5 -2
  323. package/src/config/bundled-skills/document/tools/document-update.ts +5 -2
  324. package/src/config/bundled-skills/doordash/doordash-cli.ts +17 -7
  325. package/src/config/bundled-skills/email-setup/SKILL.md +9 -9
  326. package/src/config/bundled-skills/followups/tools/followup-create.ts +5 -2
  327. package/src/config/bundled-skills/followups/tools/followup-list.ts +5 -2
  328. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +5 -2
  329. package/src/config/bundled-skills/google-calendar/calendar-client.ts +44 -32
  330. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +11 -5
  331. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +13 -7
  332. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +11 -5
  333. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +13 -7
  334. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +28 -12
  335. package/src/config/bundled-skills/google-calendar/tools/shared.ts +6 -4
  336. package/src/config/bundled-skills/google-calendar/types.ts +3 -3
  337. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +46 -24
  338. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +36 -19
  339. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +60 -35
  340. package/src/config/bundled-skills/mcp-setup/SKILL.md +75 -0
  341. package/src/config/bundled-skills/media-processing/SKILL.md +55 -15
  342. package/src/config/bundled-skills/media-processing/TOOLS.json +20 -2
  343. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +12 -10
  344. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +34 -19
  345. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +82 -66
  346. package/src/config/bundled-skills/media-processing/services/audio-transcribe.ts +148 -0
  347. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +1 -1
  348. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +8 -3
  349. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +117 -53
  350. package/src/config/bundled-skills/media-processing/services/gemini-video.ts +273 -0
  351. package/src/config/bundled-skills/media-processing/services/preprocess.ts +185 -97
  352. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +32 -27
  353. package/src/config/bundled-skills/media-processing/services/reduce.ts +101 -24
  354. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +121 -55
  355. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +58 -24
  356. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +177 -91
  357. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +98 -70
  358. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +59 -19
  359. package/src/config/bundled-skills/media-processing/tools/media-status.ts +26 -10
  360. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +29 -14
  361. package/src/config/bundled-skills/messaging/SKILL.md +7 -5
  362. package/src/config/bundled-skills/messaging/TOOLS.json +7 -7
  363. package/src/config/bundled-skills/messaging/tools/gmail-archive-by-query.ts +31 -13
  364. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +16 -10
  365. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +18 -9
  366. package/src/config/bundled-skills/messaging/tools/gmail-download-attachment.ts +23 -16
  367. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +28 -12
  368. package/src/config/bundled-skills/messaging/tools/gmail-filters.ts +41 -21
  369. package/src/config/bundled-skills/messaging/tools/gmail-follow-up.ts +44 -23
  370. package/src/config/bundled-skills/messaging/tools/gmail-forward.ts +73 -33
  371. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +15 -9
  372. package/src/config/bundled-skills/messaging/tools/gmail-list-attachments.ts +22 -14
  373. package/src/config/bundled-skills/messaging/tools/gmail-outreach-scan.ts +99 -50
  374. package/src/config/bundled-skills/messaging/tools/gmail-send-draft.ts +14 -8
  375. package/src/config/bundled-skills/messaging/tools/gmail-send-with-attachments.ts +63 -44
  376. package/src/config/bundled-skills/messaging/tools/gmail-sender-digest.ts +90 -46
  377. package/src/config/bundled-skills/messaging/tools/gmail-summarize-thread.ts +43 -22
  378. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +15 -9
  379. package/src/config/bundled-skills/messaging/tools/gmail-triage.ts +51 -22
  380. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +62 -26
  381. package/src/config/bundled-skills/messaging/tools/gmail-vacation.ts +34 -19
  382. package/src/config/bundled-skills/messaging/tools/google-contacts.ts +32 -16
  383. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +10 -4
  384. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +91 -47
  385. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +21 -9
  386. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +9 -3
  387. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +30 -17
  388. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +10 -4
  389. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +14 -6
  390. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +16 -5
  391. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +63 -36
  392. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +10 -4
  393. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +30 -12
  394. package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +48 -29
  395. package/src/config/bundled-skills/messaging/tools/scan-result-store.ts +20 -6
  396. package/src/config/bundled-skills/messaging/tools/send-notification.ts +1 -1
  397. package/src/config/bundled-skills/messaging/tools/sequence-analytics.ts +59 -22
  398. package/src/config/bundled-skills/messaging/tools/sequence-cancel.ts +13 -7
  399. package/src/config/bundled-skills/messaging/tools/sequence-create.ts +27 -12
  400. package/src/config/bundled-skills/messaging/tools/sequence-delete.ts +14 -6
  401. package/src/config/bundled-skills/messaging/tools/sequence-enroll.ts +30 -11
  402. package/src/config/bundled-skills/messaging/tools/sequence-enrollment-list.ts +16 -8
  403. package/src/config/bundled-skills/messaging/tools/sequence-get.ts +31 -13
  404. package/src/config/bundled-skills/messaging/tools/sequence-import.ts +38 -22
  405. package/src/config/bundled-skills/messaging/tools/sequence-list.ts +16 -7
  406. package/src/config/bundled-skills/messaging/tools/sequence-pause.ts +29 -10
  407. package/src/config/bundled-skills/messaging/tools/sequence-resume.ts +16 -8
  408. package/src/config/bundled-skills/messaging/tools/sequence-update.ts +35 -16
  409. package/src/config/bundled-skills/messaging/tools/shared.ts +26 -12
  410. package/src/config/bundled-skills/notifications/tools/send-notification.ts +69 -34
  411. package/src/config/bundled-skills/notifications/tools/shared.ts +1 -1
  412. package/src/config/bundled-skills/phone-calls/SKILL.md +46 -48
  413. package/src/config/bundled-skills/phone-calls/tools/call-end.ts +1 -1
  414. package/src/config/bundled-skills/phone-calls/tools/call-start.ts +1 -1
  415. package/src/config/bundled-skills/phone-calls/tools/call-status.ts +1 -1
  416. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +91 -51
  417. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +30 -16
  418. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +66 -27
  419. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +89 -42
  420. package/src/config/bundled-skills/public-ingress/SKILL.md +26 -19
  421. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +5 -2
  422. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +5 -2
  423. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +5 -2
  424. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +5 -2
  425. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +5 -2
  426. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +5 -2
  427. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +5 -2
  428. package/src/config/bundled-skills/screen-recording/SKILL.md +11 -3
  429. package/src/config/bundled-skills/self-upgrade/SKILL.md +9 -8
  430. package/src/config/bundled-skills/slack/TOOLS.json +33 -15
  431. package/src/config/bundled-skills/slack/tools/shared.ts +7 -5
  432. package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +11 -5
  433. package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +11 -5
  434. package/src/config/bundled-skills/slack/tools/slack-configure-channels.ts +46 -16
  435. package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +11 -5
  436. package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +28 -0
  437. package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +12 -6
  438. package/src/config/bundled-skills/sms-setup/SKILL.md +5 -8
  439. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +5 -2
  440. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +5 -2
  441. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +5 -2
  442. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +5 -2
  443. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +5 -2
  444. package/src/config/bundled-skills/tasks/tools/task-delete.ts +5 -2
  445. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +5 -2
  446. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +5 -2
  447. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +5 -2
  448. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +5 -2
  449. package/src/config/bundled-skills/tasks/tools/task-list.ts +5 -2
  450. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +5 -2
  451. package/src/config/bundled-skills/tasks/tools/task-run.ts +5 -2
  452. package/src/config/bundled-skills/tasks/tools/task-save.ts +5 -2
  453. package/src/config/bundled-skills/telegram-setup/SKILL.md +7 -8
  454. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +232 -127
  455. package/src/config/bundled-skills/twilio-setup/SKILL.md +7 -12
  456. package/src/config/bundled-skills/twitter/SKILL.md +19 -2
  457. package/src/config/bundled-skills/voice-setup/SKILL.md +5 -5
  458. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +5 -2
  459. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +5 -2
  460. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +5 -2
  461. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +5 -2
  462. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +5 -2
  463. package/src/config/bundled-skills/weather/tools/get-weather.ts +5 -2
  464. package/src/config/calls-schema.ts +108 -63
  465. package/src/config/computer-use-prompt.ts +7 -7
  466. package/src/config/core-schema.ts +239 -155
  467. package/src/config/defaults.ts +2 -2
  468. package/src/config/elevenlabs-schema.ts +15 -15
  469. package/src/config/env-registry.ts +33 -33
  470. package/src/config/feature-flag-registry.json +31 -7
  471. package/src/config/loader.ts +118 -58
  472. package/src/config/mcp-schema.ts +29 -15
  473. package/src/config/memory-schema.ts +434 -229
  474. package/src/config/notifications-schema.ts +4 -4
  475. package/src/config/sandbox-schema.ts +2 -2
  476. package/src/config/schema.ts +12 -2
  477. package/src/config/skill-state.ts +27 -15
  478. package/src/config/skills-schema.ts +72 -23
  479. package/src/config/skills.ts +303 -143
  480. package/src/config/system-prompt.ts +25 -6
  481. package/src/config/types.ts +1 -1
  482. package/src/config/update-bulletin-format.ts +3 -3
  483. package/src/config/update-bulletin-state.ts +15 -6
  484. package/src/config/update-bulletin-template-path.ts +8 -4
  485. package/src/config/update-bulletin.ts +33 -14
  486. package/src/config/user-reference.ts +8 -8
  487. package/src/contacts/contact-events.ts +21 -0
  488. package/src/contacts/contact-store.ts +622 -100
  489. package/src/contacts/contacts-write.ts +287 -0
  490. package/src/contacts/index.ts +13 -4
  491. package/src/contacts/startup-migration.ts +21 -0
  492. package/src/contacts/types.ts +47 -2
  493. package/src/context/token-estimator.ts +54 -31
  494. package/src/context/tool-result-truncation.ts +41 -7
  495. package/src/context/window-manager.ts +225 -120
  496. package/src/daemon/approval-generators.ts +83 -55
  497. package/src/daemon/approved-devices-store.ts +33 -20
  498. package/src/daemon/assistant-attachments.ts +134 -98
  499. package/src/daemon/auth-manager.ts +17 -15
  500. package/src/daemon/classifier.ts +117 -46
  501. package/src/daemon/computer-use-session.ts +316 -187
  502. package/src/daemon/config-watcher.ts +91 -44
  503. package/src/daemon/connection-policy.ts +18 -10
  504. package/src/daemon/context-overflow-approval.ts +48 -0
  505. package/src/daemon/context-overflow-policy.ts +50 -0
  506. package/src/daemon/context-overflow-reducer.ts +300 -0
  507. package/src/daemon/daemon-control.ts +79 -51
  508. package/src/daemon/date-context.ts +119 -69
  509. package/src/daemon/dictation-profile-store.ts +94 -48
  510. package/src/daemon/dictation-text-processing.ts +33 -12
  511. package/src/daemon/doordash-steps.ts +92 -49
  512. package/src/daemon/guardian-action-generators.ts +62 -46
  513. package/src/daemon/guardian-verification-intent.ts +31 -18
  514. package/src/daemon/handlers/apps.ts +257 -111
  515. package/src/daemon/handlers/avatar.ts +20 -15
  516. package/src/daemon/handlers/computer-use.ts +82 -39
  517. package/src/daemon/handlers/config-channels.ts +146 -69
  518. package/src/daemon/handlers/config-heartbeat.ts +114 -59
  519. package/src/daemon/handlers/config-inbox.ts +277 -106
  520. package/src/daemon/handlers/config-ingress.ts +127 -55
  521. package/src/daemon/handlers/config-integrations.ts +145 -88
  522. package/src/daemon/handlers/config-model.ts +58 -22
  523. package/src/daemon/handlers/config-platform.ts +40 -16
  524. package/src/daemon/handlers/config-scheduling.ts +109 -48
  525. package/src/daemon/handlers/config-slack-channel.ts +67 -35
  526. package/src/daemon/handlers/config-slack.ts +21 -20
  527. package/src/daemon/handlers/config-telegram.ts +100 -70
  528. package/src/daemon/handlers/config-tools.ts +103 -55
  529. package/src/daemon/handlers/config-trust.ts +50 -20
  530. package/src/daemon/handlers/config.ts +72 -24
  531. package/src/daemon/handlers/contacts.ts +163 -0
  532. package/src/daemon/handlers/diagnostics.ts +90 -48
  533. package/src/daemon/handlers/documents.ts +74 -46
  534. package/src/daemon/handlers/guardian-actions.ts +118 -71
  535. package/src/daemon/handlers/home-base.ts +19 -16
  536. package/src/daemon/handlers/identity.ts +65 -45
  537. package/src/daemon/handlers/index.ts +78 -54
  538. package/src/daemon/handlers/misc.ts +664 -234
  539. package/src/daemon/handlers/navigate-settings.ts +14 -11
  540. package/src/daemon/handlers/oauth-connect.ts +48 -35
  541. package/src/daemon/handlers/open-bundle-handler.ts +31 -24
  542. package/src/daemon/handlers/pairing.ts +51 -25
  543. package/src/daemon/handlers/publish.ts +55 -33
  544. package/src/daemon/handlers/recording.ts +378 -162
  545. package/src/daemon/handlers/sessions.ts +923 -423
  546. package/src/daemon/handlers/shared.ts +202 -117
  547. package/src/daemon/handlers/signing.ts +25 -6
  548. package/src/daemon/handlers/subagents.ts +117 -56
  549. package/src/daemon/handlers/twitter-auth.ts +70 -49
  550. package/src/daemon/handlers/work-items.ts +264 -112
  551. package/src/daemon/handlers/workspace-files.ts +27 -20
  552. package/src/daemon/handlers.ts +2 -2
  553. package/src/daemon/history-repair.ts +16 -15
  554. package/src/daemon/identity-helpers.ts +4 -4
  555. package/src/daemon/install-cli-launchers.ts +33 -22
  556. package/src/daemon/ipc-blob-store.ts +38 -24
  557. package/src/daemon/ipc-contract/apps.ts +61 -49
  558. package/src/daemon/ipc-contract/computer-use.ts +47 -37
  559. package/src/daemon/ipc-contract/contacts.ts +69 -0
  560. package/src/daemon/ipc-contract/diagnostics.ts +14 -14
  561. package/src/daemon/ipc-contract/documents.ts +8 -8
  562. package/src/daemon/ipc-contract/guardian-actions.ts +4 -4
  563. package/src/daemon/ipc-contract/inbox.ts +16 -16
  564. package/src/daemon/ipc-contract/integrations.ts +57 -44
  565. package/src/daemon/ipc-contract/memory.ts +3 -5
  566. package/src/daemon/ipc-contract/messages.ts +95 -69
  567. package/src/daemon/ipc-contract/notifications.ts +10 -6
  568. package/src/daemon/ipc-contract/pairing.ts +8 -8
  569. package/src/daemon/ipc-contract/schedules.ts +20 -20
  570. package/src/daemon/ipc-contract/sessions.ts +88 -57
  571. package/src/daemon/ipc-contract/settings.ts +12 -7
  572. package/src/daemon/ipc-contract/shared.ts +9 -7
  573. package/src/daemon/ipc-contract/skills.ts +46 -26
  574. package/src/daemon/ipc-contract/subagents.ts +9 -9
  575. package/src/daemon/ipc-contract/trust.ts +11 -11
  576. package/src/daemon/ipc-contract/work-items.ts +33 -28
  577. package/src/daemon/ipc-contract/workspace.ts +28 -21
  578. package/src/daemon/ipc-contract-inventory.json +8 -0
  579. package/src/daemon/ipc-contract-inventory.ts +29 -26
  580. package/src/daemon/ipc-contract.ts +111 -44
  581. package/src/daemon/ipc-handler.ts +27 -19
  582. package/src/daemon/ipc-protocol.ts +22 -12
  583. package/src/daemon/ipc-validate.ts +91 -46
  584. package/src/daemon/lifecycle.ts +25 -1
  585. package/src/daemon/main.ts +10 -8
  586. package/src/daemon/media-visibility-policy.ts +3 -1
  587. package/src/daemon/pairing-store.ts +72 -40
  588. package/src/daemon/providers-setup.ts +35 -25
  589. package/src/daemon/recording-executor.ts +37 -30
  590. package/src/daemon/recording-intent-fallback.ts +58 -28
  591. package/src/daemon/recording-intent.ts +71 -61
  592. package/src/daemon/ride-shotgun-handler.ts +201 -121
  593. package/src/daemon/seed-files.ts +28 -17
  594. package/src/daemon/server.ts +23 -14
  595. package/src/daemon/session-agent-loop-handlers.ts +261 -135
  596. package/src/daemon/session-agent-loop.ts +795 -253
  597. package/src/daemon/session-attachments.ts +104 -39
  598. package/src/daemon/session-conflict-gate.ts +72 -28
  599. package/src/daemon/session-dynamic-profile.ts +36 -22
  600. package/src/daemon/session-error.ts +50 -45
  601. package/src/daemon/session-evictor.ts +17 -10
  602. package/src/daemon/session-history.ts +201 -89
  603. package/src/daemon/session-lifecycle.ts +79 -42
  604. package/src/daemon/session-media-retry.ts +89 -41
  605. package/src/daemon/session-memory.ts +77 -55
  606. package/src/daemon/session-messaging.ts +261 -111
  607. package/src/daemon/session-notifiers.ts +57 -45
  608. package/src/daemon/session-process.ts +370 -154
  609. package/src/daemon/session-queue-manager.ts +30 -13
  610. package/src/daemon/session-runtime-assembly.ts +61 -15
  611. package/src/daemon/session-skill-tools.ts +84 -36
  612. package/src/daemon/session-slash.ts +178 -113
  613. package/src/daemon/session-surfaces.ts +498 -211
  614. package/src/daemon/session-tool-setup.ts +22 -17
  615. package/src/daemon/session-usage.ts +26 -13
  616. package/src/daemon/session-workspace.ts +7 -4
  617. package/src/daemon/session.ts +18 -19
  618. package/src/daemon/shutdown-handlers.ts +36 -33
  619. package/src/daemon/tls-certs.ts +90 -57
  620. package/src/daemon/tool-side-effects.ts +97 -65
  621. package/src/daemon/trace-emitter.ts +8 -7
  622. package/src/daemon/video-thumbnail.ts +55 -25
  623. package/src/daemon/watch-handler.ts +164 -86
  624. package/src/email/provider.ts +1 -1
  625. package/src/email/providers/agentmail.ts +87 -45
  626. package/src/email/providers/index.ts +19 -14
  627. package/src/email/service.ts +52 -24
  628. package/src/email/types.ts +2 -2
  629. package/src/errors.ts +1 -1
  630. package/src/events/bus.ts +30 -10
  631. package/src/events/domain-events.ts +19 -13
  632. package/src/events/index.ts +6 -6
  633. package/src/events/tool-audit-listener.ts +34 -20
  634. package/src/events/tool-domain-event-publisher.ts +22 -20
  635. package/src/events/tool-metrics-listener.ts +26 -21
  636. package/src/events/tool-notification-listener.ts +5 -5
  637. package/src/events/tool-profiling-listener.ts +33 -23
  638. package/src/events/tool-trace-listener.ts +70 -46
  639. package/src/export/formatter.ts +38 -32
  640. package/src/followups/followup-store.ts +43 -36
  641. package/src/followups/index.ts +2 -2
  642. package/src/followups/types.ts +1 -1
  643. package/src/gallery/default-gallery.ts +37 -34
  644. package/src/gallery/gallery-manifest.ts +9 -9
  645. package/src/heartbeat/heartbeat-service.ts +59 -37
  646. package/src/home-base/app-link-store.ts +14 -12
  647. package/src/home-base/bootstrap.ts +14 -8
  648. package/src/home-base/prebuilt/seed.ts +35 -26
  649. package/src/home-base/prebuilt-home-base-updater.ts +14 -8
  650. package/src/hooks/cli.ts +56 -43
  651. package/src/hooks/config.ts +27 -14
  652. package/src/hooks/discovery.ts +53 -33
  653. package/src/hooks/manager.ts +50 -26
  654. package/src/hooks/runner.ts +35 -29
  655. package/src/hooks/templates.ts +38 -15
  656. package/src/hooks/types.ts +13 -13
  657. package/src/inbound/platform-callback-registration.ts +21 -15
  658. package/src/inbound/public-ingress-urls.ts +9 -6
  659. package/src/index.ts +20 -19
  660. package/src/influencer/client.ts +269 -108
  661. package/src/instrument.ts +3 -1
  662. package/src/logfire.ts +64 -39
  663. package/src/mcp/client.ts +107 -55
  664. package/src/mcp/manager.ts +45 -18
  665. package/src/mcp/mcp-oauth-provider.ts +114 -62
  666. package/src/media/gemini-image-service.ts +28 -21
  667. package/src/memory/account-store.ts +16 -9
  668. package/src/memory/admin.ts +87 -57
  669. package/src/memory/app-git-service.ts +77 -47
  670. package/src/memory/app-store.ts +151 -77
  671. package/src/memory/attachments-store.ts +123 -53
  672. package/src/memory/canonical-guardian-store.ts +190 -48
  673. package/src/memory/channel-delivery-store.ts +5 -5
  674. package/src/memory/channel-guardian-store.ts +31 -16
  675. package/src/memory/checkpoints.ts +14 -7
  676. package/src/memory/clarification-resolver.ts +219 -104
  677. package/src/memory/conflict-intent.ts +74 -23
  678. package/src/memory/conflict-policy.ts +20 -7
  679. package/src/memory/conflict-store.ts +144 -94
  680. package/src/memory/contradiction-checker.ts +257 -132
  681. package/src/memory/conversation-attention-store.ts +72 -32
  682. package/src/memory/conversation-bootstrap.ts +28 -0
  683. package/src/memory/conversation-crud.ts +12 -5
  684. package/src/memory/conversation-display-order-migration.ts +7 -7
  685. package/src/memory/conversation-key-store.ts +18 -13
  686. package/src/memory/conversation-queries.ts +130 -52
  687. package/src/memory/conversation-store.ts +43 -26
  688. package/src/memory/conversation-title-service.ts +89 -66
  689. package/src/memory/db-init.ts +90 -2
  690. package/src/memory/db.ts +10 -3
  691. package/src/memory/delivery-channels.ts +12 -6
  692. package/src/memory/delivery-crud.ts +26 -12
  693. package/src/memory/delivery-status.ts +19 -16
  694. package/src/memory/embedding-backend.ts +205 -77
  695. package/src/memory/embedding-gemini.ts +23 -10
  696. package/src/memory/embedding-local.ts +89 -44
  697. package/src/memory/embedding-ollama.ts +25 -13
  698. package/src/memory/embedding-openai.ts +20 -11
  699. package/src/memory/embedding-runtime-manager.ts +163 -90
  700. package/src/memory/entity-extractor.ts +185 -123
  701. package/src/memory/external-conversation-store.ts +30 -12
  702. package/src/memory/fingerprint.ts +2 -2
  703. package/src/memory/fts-reconciler.ts +57 -28
  704. package/src/memory/guardian-action-store.ts +162 -100
  705. package/src/memory/guardian-approvals.ts +63 -129
  706. package/src/memory/guardian-rate-limits.ts +20 -9
  707. package/src/memory/guardian-verification.ts +82 -35
  708. package/src/memory/indexer.ts +96 -55
  709. package/src/memory/ingress-invite-store.ts +28 -169
  710. package/src/memory/items-extractor.ts +313 -157
  711. package/src/memory/job-handlers/backfill.ts +116 -63
  712. package/src/memory/job-handlers/cleanup.ts +64 -41
  713. package/src/memory/job-handlers/conflict.ts +90 -49
  714. package/src/memory/job-handlers/embedding.ts +32 -17
  715. package/src/memory/job-handlers/extraction.ts +58 -33
  716. package/src/memory/job-handlers/index-maintenance.ts +31 -17
  717. package/src/memory/job-handlers/media-processing.ts +65 -24
  718. package/src/memory/job-handlers/summarization.ts +186 -128
  719. package/src/memory/job-utils.ts +100 -57
  720. package/src/memory/jobs-store.ts +235 -142
  721. package/src/memory/jobs-worker.ts +167 -83
  722. package/src/memory/llm-request-log-store.ts +13 -11
  723. package/src/memory/llm-usage-store.ts +35 -26
  724. package/src/memory/media-store.ts +151 -44
  725. package/src/memory/message-content.ts +28 -18
  726. package/src/memory/migrations/001-job-deferrals.ts +11 -5
  727. package/src/memory/migrations/002-tool-invocations-fk.ts +14 -6
  728. package/src/memory/migrations/003-memory-fts-backfill.ts +11 -5
  729. package/src/memory/migrations/004-entity-relation-dedup.ts +17 -11
  730. package/src/memory/migrations/005-fingerprint-scope-unique.ts +36 -21
  731. package/src/memory/migrations/006-scope-salted-fingerprints.ts +35 -20
  732. package/src/memory/migrations/007-assistant-id-to-self.ts +40 -27
  733. package/src/memory/migrations/008-remove-assistant-id-columns.ts +58 -36
  734. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +36 -22
  735. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +21 -11
  736. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +30 -15
  737. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +4 -2
  738. package/src/memory/migrations/013-guardian-action-tables.ts +29 -11
  739. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +35 -21
  740. package/src/memory/migrations/015-drop-active-search-index.ts +17 -11
  741. package/src/memory/migrations/016-memory-segments-indexes.ts +7 -3
  742. package/src/memory/migrations/017-memory-items-indexes.ts +4 -2
  743. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -5
  744. package/src/memory/migrations/019-notification-tables-schema-migration.ts +34 -20
  745. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +87 -53
  746. package/src/memory/migrations/021-conversation-status-indexes.ts +7 -3
  747. package/src/memory/migrations/022-add-origin-interface.ts +4 -2
  748. package/src/memory/migrations/023-memory-item-sources-indexes.ts +4 -2
  749. package/src/memory/migrations/024-embedding-vector-blob.ts +34 -18
  750. package/src/memory/migrations/025-messages-fts-backfill.ts +11 -5
  751. package/src/memory/migrations/026-guardian-verification-sessions.ts +80 -14
  752. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +42 -26
  753. package/src/memory/migrations/027-notification-delivery-pairing-columns.ts +22 -8
  754. package/src/memory/migrations/027a-guardian-bootstrap-token.ts +11 -3
  755. package/src/memory/migrations/028-call-session-mode.ts +13 -3
  756. package/src/memory/migrations/028-notification-delivery-client-ack.ts +22 -8
  757. package/src/memory/migrations/029-channel-inbound-delivered-segments.ts +7 -3
  758. package/src/memory/migrations/030-guardian-action-followup.ts +46 -8
  759. package/src/memory/migrations/030-guardian-verification-purpose.ts +4 -2
  760. package/src/memory/migrations/031-conversations-thread-type-index.ts +4 -2
  761. package/src/memory/migrations/032-guardian-delivery-conversation-index.ts +4 -2
  762. package/src/memory/migrations/032-notification-delivery-thread-decision.ts +22 -8
  763. package/src/memory/migrations/033-scoped-approval-grants.ts +1 -1
  764. package/src/memory/migrations/034-guardian-action-tool-metadata.ts +15 -3
  765. package/src/memory/migrations/035-guardian-action-supersession.ts +15 -3
  766. package/src/memory/migrations/036-normalize-phone-identities.ts +101 -87
  767. package/src/memory/migrations/037-voice-invite-columns.ts +22 -4
  768. package/src/memory/migrations/038-actor-token-records.ts +5 -9
  769. package/src/memory/migrations/039-actor-refresh-token-records.ts +7 -13
  770. package/src/memory/migrations/100-core-tables.ts +1 -1
  771. package/src/memory/migrations/101-watchers-and-logs.ts +1 -1
  772. package/src/memory/migrations/103-complex-migrations.ts +9 -9
  773. package/src/memory/migrations/104-core-indexes.ts +188 -64
  774. package/src/memory/migrations/105-contacts-and-triage.ts +28 -10
  775. package/src/memory/migrations/106-call-sessions.ts +58 -16
  776. package/src/memory/migrations/107-followups.ts +16 -6
  777. package/src/memory/migrations/108-tasks-and-work-items.ts +43 -11
  778. package/src/memory/migrations/109-external-conversation-bindings.ts +11 -5
  779. package/src/memory/migrations/110-channel-guardian.ts +48 -10
  780. package/src/memory/migrations/111-media-assets.ts +52 -18
  781. package/src/memory/migrations/112-assistant-inbox.ts +32 -12
  782. package/src/memory/migrations/113-late-migrations.ts +12 -12
  783. package/src/memory/migrations/114-notifications.ts +28 -12
  784. package/src/memory/migrations/115-sequences.ts +10 -4
  785. package/src/memory/migrations/116-messages-fts.ts +1 -1
  786. package/src/memory/migrations/117-conversation-attention.ts +16 -6
  787. package/src/memory/migrations/118-reminder-routing-intent.ts +7 -3
  788. package/src/memory/migrations/119-schema-indexes-and-columns.ts +35 -15
  789. package/src/memory/migrations/120-fk-cascade-rebuilds.ts +36 -17
  790. package/src/memory/migrations/121-canonical-guardian-requests.ts +25 -9
  791. package/src/memory/migrations/122-canonical-guardian-requester-chat-id.ts +11 -3
  792. package/src/memory/migrations/123-canonical-guardian-deliveries-destination-index.ts +4 -2
  793. package/src/memory/migrations/124-voice-invite-display-metadata.ts +15 -3
  794. package/src/memory/migrations/125-guardian-principal-id-columns.ts +22 -4
  795. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +174 -126
  796. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +58 -42
  797. package/src/memory/migrations/128-contacts-role-principal.ts +26 -0
  798. package/src/memory/migrations/129-contact-channels-access-fields.ts +105 -0
  799. package/src/memory/migrations/130-contact-channels-type-ext-chat-id-index.ts +15 -0
  800. package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +134 -0
  801. package/src/memory/migrations/132-contacts-assistant-id.ts +21 -0
  802. package/src/memory/migrations/index.ts +82 -73
  803. package/src/memory/migrations/registry.ts +53 -37
  804. package/src/memory/migrations/validate-migration-state.ts +73 -46
  805. package/src/memory/profile-compiler.ts +58 -24
  806. package/src/memory/published-pages-store.ts +12 -16
  807. package/src/memory/qdrant-circuit-breaker.ts +28 -20
  808. package/src/memory/qdrant-client.ts +99 -63
  809. package/src/memory/qdrant-manager.ts +89 -57
  810. package/src/memory/query-builder.ts +9 -7
  811. package/src/memory/raw-query.ts +63 -14
  812. package/src/memory/recall-cache.ts +15 -8
  813. package/src/memory/retrieval-budget.ts +0 -1
  814. package/src/memory/retriever.ts +385 -192
  815. package/src/memory/schema-migration.ts +1 -1
  816. package/src/memory/schema.ts +44 -56
  817. package/src/memory/scoped-approval-grants.ts +99 -45
  818. package/src/memory/search/entity.ts +102 -40
  819. package/src/memory/search/formatting.ts +70 -52
  820. package/src/memory/search/lexical.ts +82 -43
  821. package/src/memory/search/ranking.ts +103 -39
  822. package/src/memory/search/semantic.ts +59 -35
  823. package/src/memory/search/types.ts +8 -8
  824. package/src/memory/segmenter.ts +20 -12
  825. package/src/memory/shared-app-links-store.ts +21 -16
  826. package/src/memory/task-memory-cleanup.ts +18 -8
  827. package/src/memory/tool-usage-store.ts +27 -19
  828. package/src/memory/validation.ts +4 -2
  829. package/src/messaging/activity-analyzer.ts +7 -7
  830. package/src/messaging/draft-store.ts +13 -10
  831. package/src/messaging/email-classifier.ts +73 -37
  832. package/src/messaging/index.ts +3 -3
  833. package/src/messaging/outreach-classifier.ts +76 -38
  834. package/src/messaging/provider-types.ts +2 -4
  835. package/src/messaging/provider.ts +37 -8
  836. package/src/messaging/providers/gmail/adapter.ts +183 -66
  837. package/src/messaging/providers/gmail/client.ts +3 -1
  838. package/src/messaging/providers/gmail/mime-builder.ts +21 -19
  839. package/src/messaging/providers/gmail/people-client.ts +22 -9
  840. package/src/messaging/providers/gmail/types.ts +6 -6
  841. package/src/messaging/providers/slack/adapter.ts +93 -43
  842. package/src/messaging/providers/slack/client.ts +100 -41
  843. package/src/messaging/providers/slack/types.ts +6 -0
  844. package/src/messaging/providers/sms/adapter.ts +76 -40
  845. package/src/messaging/providers/sms/client.ts +4 -4
  846. package/src/messaging/providers/telegram-bot/adapter.ts +52 -30
  847. package/src/messaging/providers/telegram-bot/client.ts +7 -7
  848. package/src/messaging/providers/whatsapp/adapter.ts +58 -31
  849. package/src/messaging/providers/whatsapp/client.ts +4 -4
  850. package/src/messaging/registry.ts +9 -5
  851. package/src/messaging/style-analyzer.ts +69 -39
  852. package/src/messaging/thread-summarizer.ts +101 -53
  853. package/src/messaging/triage-engine.ts +111 -82
  854. package/src/messaging/types.ts +10 -10
  855. package/src/migrations/config-merge.ts +18 -10
  856. package/src/migrations/data-layout.ts +35 -22
  857. package/src/migrations/data-merge.ts +17 -7
  858. package/src/migrations/hooks-merge.ts +43 -16
  859. package/src/migrations/index.ts +6 -6
  860. package/src/migrations/log.ts +9 -5
  861. package/src/migrations/skills-merge.ts +17 -7
  862. package/src/migrations/workspace-layout.ts +39 -25
  863. package/src/notifications/AGENTS.md +5 -0
  864. package/src/notifications/adapters/macos.ts +21 -14
  865. package/src/notifications/adapters/sms.ts +28 -15
  866. package/src/notifications/adapters/telegram.ts +24 -15
  867. package/src/notifications/broadcaster.ts +108 -52
  868. package/src/notifications/conversation-pairing.ts +64 -29
  869. package/src/notifications/copy-composer.ts +165 -95
  870. package/src/notifications/decision-engine.ts +353 -147
  871. package/src/notifications/decisions-store.ts +26 -10
  872. package/src/notifications/deliveries-store.ts +23 -13
  873. package/src/notifications/destination-resolver.ts +42 -24
  874. package/src/notifications/deterministic-checks.ts +78 -27
  875. package/src/notifications/emit-signal.ts +83 -45
  876. package/src/notifications/events-store.ts +13 -7
  877. package/src/notifications/guardian-question-mode.ts +125 -75
  878. package/src/notifications/preference-extractor.ts +85 -53
  879. package/src/notifications/preference-summary.ts +31 -18
  880. package/src/notifications/preferences-store.ts +29 -18
  881. package/src/notifications/runtime-dispatch.ts +22 -12
  882. package/src/notifications/signal.ts +4 -4
  883. package/src/notifications/thread-candidates.ts +59 -23
  884. package/src/notifications/thread-seed-composer.ts +45 -27
  885. package/src/notifications/types.ts +19 -10
  886. package/src/oauth/connect-orchestrator.ts +105 -54
  887. package/src/oauth/connect-types.ts +3 -3
  888. package/src/oauth/provider-profiles.ts +80 -59
  889. package/src/oauth/scope-policy.ts +5 -2
  890. package/src/oauth/token-persistence.ts +58 -24
  891. package/src/outbound-proxy/certs.ts +284 -0
  892. package/src/outbound-proxy/config.ts +94 -0
  893. package/src/outbound-proxy/connect-tunnel.ts +84 -0
  894. package/src/outbound-proxy/health.ts +62 -0
  895. package/src/outbound-proxy/host-pattern-match.ts +67 -0
  896. package/src/outbound-proxy/http-forwarder.ts +162 -0
  897. package/src/outbound-proxy/index.ts +80 -0
  898. package/src/outbound-proxy/logging.ts +193 -0
  899. package/src/outbound-proxy/mitm-handler.ts +292 -0
  900. package/src/outbound-proxy/policy.ts +172 -0
  901. package/src/outbound-proxy/router.ts +64 -0
  902. package/src/outbound-proxy/server.ts +145 -0
  903. package/src/outbound-proxy/types.ts +150 -0
  904. package/src/permissions/checker.ts +481 -189
  905. package/src/permissions/defaults.ts +135 -108
  906. package/src/permissions/prompter.ts +53 -27
  907. package/src/permissions/secret-prompter.ts +21 -15
  908. package/src/permissions/shell-identity.ts +47 -16
  909. package/src/permissions/trust-store.ts +185 -73
  910. package/src/permissions/types.ts +22 -12
  911. package/src/permissions/workspace-policy.ts +47 -38
  912. package/src/playbooks/index.ts +10 -2
  913. package/src/playbooks/playbook-compiler.ts +30 -24
  914. package/src/playbooks/types.ts +11 -8
  915. package/src/providers/anthropic/client.ts +325 -168
  916. package/src/providers/failover.ts +57 -22
  917. package/src/providers/fireworks/client.ts +9 -5
  918. package/src/providers/gemini/client.ts +61 -39
  919. package/src/providers/model-intents.ts +40 -33
  920. package/src/providers/ollama/client.ts +7 -7
  921. package/src/providers/openai/client.ts +106 -68
  922. package/src/providers/openrouter/client.ts +9 -5
  923. package/src/providers/provider-send-message.ts +59 -27
  924. package/src/providers/ratelimit.ts +25 -8
  925. package/src/providers/registry.ts +86 -38
  926. package/src/providers/retry.ts +84 -36
  927. package/src/providers/stream-timeout.ts +5 -3
  928. package/src/providers/types.ts +7 -6
  929. package/src/runtime/AGENTS.md +42 -0
  930. package/src/runtime/access-request-helper.ts +118 -68
  931. package/src/runtime/actor-refresh-token-store.ts +21 -16
  932. package/src/runtime/actor-token-store.ts +25 -18
  933. package/src/runtime/actor-trust-resolver.ts +183 -80
  934. package/src/runtime/approval-conversation-turn.ts +39 -26
  935. package/src/runtime/approval-message-composer.ts +116 -84
  936. package/src/runtime/assistant-event-hub.ts +25 -6
  937. package/src/runtime/assistant-event.ts +4 -4
  938. package/src/runtime/assistant-scope.ts +1 -1
  939. package/src/runtime/auth/__tests__/guard-tests.test.ts +36 -14
  940. package/src/runtime/auth/context.ts +8 -7
  941. package/src/runtime/auth/credential-service.ts +60 -38
  942. package/src/runtime/auth/external-assistant-id.ts +16 -8
  943. package/src/runtime/auth/index.ts +23 -16
  944. package/src/runtime/auth/route-policy.ts +170 -104
  945. package/src/runtime/auth/scopes.ts +22 -29
  946. package/src/runtime/auth/subject.ts +19 -13
  947. package/src/runtime/auth/token-service.ts +3 -3
  948. package/src/runtime/auth/types.ts +23 -23
  949. package/src/runtime/channel-approval-parser.ts +37 -14
  950. package/src/runtime/channel-approval-types.ts +12 -4
  951. package/src/runtime/channel-approvals.ts +41 -23
  952. package/src/runtime/channel-guardian-service.ts +144 -103
  953. package/src/runtime/channel-invite-transport.ts +4 -2
  954. package/src/runtime/channel-invite-transports/telegram.ts +16 -10
  955. package/src/runtime/channel-invite-transports/voice.ts +7 -7
  956. package/src/runtime/channel-readiness-service.ts +139 -90
  957. package/src/runtime/channel-readiness-types.ts +4 -2
  958. package/src/runtime/channel-reply-delivery.ts +21 -11
  959. package/src/runtime/channel-retry-sweep.ts +111 -62
  960. package/src/runtime/confirmation-request-guardian-bridge.ts +73 -54
  961. package/src/runtime/gateway-client.ts +86 -53
  962. package/src/runtime/guardian-action-conversation-turn.ts +34 -18
  963. package/src/runtime/guardian-action-followup-executor.ts +115 -45
  964. package/src/runtime/guardian-action-grant-minter.ts +40 -24
  965. package/src/runtime/guardian-action-message-composer.ts +105 -84
  966. package/src/runtime/guardian-decision-types.ts +28 -13
  967. package/src/runtime/guardian-outbound-actions.ts +9 -0
  968. package/src/runtime/guardian-reply-router.ts +274 -145
  969. package/src/runtime/guardian-vellum-migration.ts +38 -24
  970. package/src/runtime/guardian-verification-templates.ts +8 -11
  971. package/src/runtime/http-router.ts +175 -0
  972. package/src/runtime/http-server.ts +931 -669
  973. package/src/runtime/http-types.ts +2 -2
  974. package/src/runtime/ingress-service.ts +182 -89
  975. package/src/runtime/invite-redemption-service.ts +211 -134
  976. package/src/runtime/invite-redemption-templates.ts +18 -11
  977. package/src/runtime/local-actor-identity.ts +73 -55
  978. package/src/runtime/middleware/auth.ts +25 -14
  979. package/src/runtime/middleware/error-handler.ts +15 -11
  980. package/src/runtime/middleware/rate-limiter.ts +23 -17
  981. package/src/runtime/middleware/request-logger.ts +4 -4
  982. package/src/runtime/middleware/twilio-validation.ts +29 -20
  983. package/src/runtime/migrations/migration-transport.ts +575 -0
  984. package/src/runtime/migrations/migration-wizard.ts +715 -0
  985. package/src/runtime/migrations/rebind-secrets-screen.ts +351 -0
  986. package/src/runtime/migrations/transfer-progress-screen.ts +321 -0
  987. package/src/runtime/migrations/validation-results-screen.ts +467 -0
  988. package/src/runtime/migrations/vbundle-builder.ts +295 -0
  989. package/src/runtime/migrations/vbundle-import-analyzer.ts +212 -0
  990. package/src/runtime/migrations/vbundle-importer.ts +339 -0
  991. package/src/runtime/migrations/vbundle-validator.ts +356 -0
  992. package/src/runtime/pending-interactions.ts +16 -7
  993. package/src/runtime/routes/access-request-decision.ts +73 -52
  994. package/src/runtime/routes/app-routes.ts +56 -38
  995. package/src/runtime/routes/approval-routes.ts +165 -74
  996. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +930 -0
  997. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +82 -0
  998. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +151 -0
  999. package/src/runtime/routes/attachment-routes.ts +59 -48
  1000. package/src/runtime/routes/brain-graph-routes.ts +85 -69
  1001. package/src/runtime/routes/call-routes.ts +79 -38
  1002. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +10 -10
  1003. package/src/runtime/routes/channel-delivery-routes.ts +19 -14
  1004. package/src/runtime/routes/channel-guardian-routes.ts +3 -3
  1005. package/src/runtime/routes/channel-inbound-routes.ts +2 -2
  1006. package/src/runtime/routes/channel-readiness-routes.ts +12 -6
  1007. package/src/runtime/routes/channel-route-shared.ts +33 -25
  1008. package/src/runtime/routes/channel-routes.ts +4 -6
  1009. package/src/runtime/routes/contact-routes.ts +205 -16
  1010. package/src/runtime/routes/conversation-attention-routes.ts +57 -28
  1011. package/src/runtime/routes/conversation-routes.ts +321 -174
  1012. package/src/runtime/routes/debug-routes.ts +14 -10
  1013. package/src/runtime/routes/events-routes.ts +90 -57
  1014. package/src/runtime/routes/global-search-routes.ts +266 -0
  1015. package/src/runtime/routes/guardian-action-routes.ts +147 -56
  1016. package/src/runtime/routes/guardian-approval-interception.ts +255 -880
  1017. package/src/runtime/routes/guardian-approval-prompt.ts +40 -24
  1018. package/src/runtime/routes/guardian-approval-reply-helpers.ts +135 -0
  1019. package/src/runtime/routes/guardian-bootstrap-routes.ts +55 -36
  1020. package/src/runtime/routes/guardian-expiry-sweep.ts +63 -37
  1021. package/src/runtime/routes/guardian-refresh-routes.ts +40 -19
  1022. package/src/runtime/routes/identity-routes.ts +71 -42
  1023. package/src/runtime/routes/inbound-conversation.ts +17 -11
  1024. package/src/runtime/routes/inbound-message-handler.ts +278 -1460
  1025. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +658 -0
  1026. package/src/runtime/routes/inbound-stages/background-dispatch.ts +492 -0
  1027. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +214 -0
  1028. package/src/runtime/routes/inbound-stages/edit-intercept.ts +116 -0
  1029. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +167 -0
  1030. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +185 -0
  1031. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +132 -0
  1032. package/src/runtime/routes/inbound-stages/verification-intercept.ts +340 -0
  1033. package/src/runtime/routes/ingress-routes.ts +34 -23
  1034. package/src/runtime/routes/integration-routes.ts +60 -21
  1035. package/src/runtime/routes/migration-routes.ts +434 -0
  1036. package/src/runtime/routes/pairing-routes.ts +157 -79
  1037. package/src/runtime/routes/secret-routes.ts +6 -2
  1038. package/src/runtime/routes/twilio-routes.ts +443 -249
  1039. package/src/runtime/tool-grant-request-helper.ts +36 -27
  1040. package/src/runtime/{guardian-context-resolver.ts → trust-context-resolver.ts} +29 -41
  1041. package/src/schedule/integration-status.ts +44 -9
  1042. package/src/schedule/recurrence-engine.ts +47 -24
  1043. package/src/schedule/recurrence-types.ts +12 -7
  1044. package/src/schedule/schedule-store.ts +166 -83
  1045. package/src/schedule/scheduler.ts +26 -22
  1046. package/src/security/encrypted-store.ts +68 -38
  1047. package/src/security/keychain.ts +183 -120
  1048. package/src/security/oauth-callback-registry.ts +3 -3
  1049. package/src/security/oauth2.ts +226 -138
  1050. package/src/security/redaction.ts +24 -24
  1051. package/src/security/secret-allowlist.ts +46 -21
  1052. package/src/security/secret-ingress.ts +15 -7
  1053. package/src/security/secret-scanner.ts +193 -104
  1054. package/src/security/secure-keys.ts +9 -3
  1055. package/src/security/token-manager.ts +99 -40
  1056. package/src/security/tool-approval-digest.ts +3 -3
  1057. package/src/sequence/analytics.ts +52 -27
  1058. package/src/sequence/engine.ts +135 -72
  1059. package/src/sequence/guardrails.ts +32 -20
  1060. package/src/sequence/importer.ts +75 -37
  1061. package/src/sequence/reply-matcher.ts +36 -18
  1062. package/src/sequence/store.ts +137 -75
  1063. package/src/sequence/types.ts +30 -16
  1064. package/src/services/published-app-updater.ts +26 -16
  1065. package/src/services/vercel-deploy.ts +19 -15
  1066. package/src/skills/active-skill-tools.ts +3 -3
  1067. package/src/skills/clawhub.ts +178 -90
  1068. package/src/skills/include-graph.ts +24 -17
  1069. package/src/skills/managed-store.ts +89 -42
  1070. package/src/skills/path-classifier.ts +10 -10
  1071. package/src/skills/remote-skill-policy.ts +31 -22
  1072. package/src/skills/slash-commands.ts +36 -30
  1073. package/src/skills/tool-manifest.ts +60 -31
  1074. package/src/skills/version-hash.ts +25 -15
  1075. package/src/slack/slack-webhook.ts +19 -15
  1076. package/src/subagent/index.ts +4 -8
  1077. package/src/subagent/manager.ts +119 -69
  1078. package/src/subagent/types.ts +9 -12
  1079. package/src/swarm/backend-claude-code.ts +124 -45
  1080. package/src/swarm/checkpoint.ts +36 -16
  1081. package/src/swarm/graph-utils.ts +1 -3
  1082. package/src/swarm/index.ts +38 -19
  1083. package/src/swarm/limits.ts +13 -4
  1084. package/src/swarm/orchestrator.ts +108 -57
  1085. package/src/swarm/plan-validator.ts +23 -17
  1086. package/src/swarm/router-planner.ts +51 -22
  1087. package/src/swarm/router-prompts.ts +4 -1
  1088. package/src/swarm/synthesizer.ts +26 -18
  1089. package/src/swarm/types.ts +14 -4
  1090. package/src/swarm/worker-backend.ts +36 -26
  1091. package/src/swarm/worker-prompts.ts +13 -9
  1092. package/src/swarm/worker-runner.ts +40 -34
  1093. package/src/tasks/candidate-store.ts +14 -6
  1094. package/src/tasks/ephemeral-permissions.ts +9 -5
  1095. package/src/tasks/task-compiler.ts +41 -38
  1096. package/src/tasks/task-runner.ts +54 -26
  1097. package/src/tasks/task-scheduler.ts +1 -1
  1098. package/src/tasks/task-store.ts +20 -7
  1099. package/src/tasks/tool-sanitizer.ts +3 -3
  1100. package/src/tools/apps/definitions.ts +23 -15
  1101. package/src/tools/apps/executors.ts +118 -37
  1102. package/src/tools/apps/open-proxy.ts +5 -5
  1103. package/src/tools/apps/registry.ts +2 -2
  1104. package/src/tools/assets/materialize.ts +59 -41
  1105. package/src/tools/assets/search.ts +86 -48
  1106. package/src/tools/browser/api-map.ts +52 -36
  1107. package/src/tools/browser/auth-cache.ts +21 -18
  1108. package/src/tools/browser/auth-detector.ts +43 -28
  1109. package/src/tools/browser/auto-navigate.ts +149 -68
  1110. package/src/tools/browser/browser-execution.ts +9 -3
  1111. package/src/tools/browser/headless-browser.ts +287 -150
  1112. package/src/tools/browser/jit-auth.ts +37 -21
  1113. package/src/tools/browser/network-recorder.ts +138 -56
  1114. package/src/tools/browser/recording-store.ts +22 -15
  1115. package/src/tools/browser/runtime-check.ts +8 -5
  1116. package/src/tools/browser/x-auto-navigate.ts +88 -47
  1117. package/src/tools/calls/call-end.ts +9 -6
  1118. package/src/tools/calls/call-start.ts +30 -20
  1119. package/src/tools/calls/call-status.ts +8 -5
  1120. package/src/tools/claude-code/claude-code.ts +301 -165
  1121. package/src/tools/computer-use/definitions.ts +159 -130
  1122. package/src/tools/computer-use/registry.ts +2 -2
  1123. package/src/tools/computer-use/request-computer-control.ts +21 -13
  1124. package/src/tools/computer-use/skill-proxy-bridge.ts +1 -1
  1125. package/src/tools/credentials/account-registry.ts +52 -35
  1126. package/src/tools/credentials/broker-types.ts +1 -1
  1127. package/src/tools/credentials/broker.ts +97 -55
  1128. package/src/tools/credentials/domain-policy.ts +5 -2
  1129. package/src/tools/credentials/host-pattern-match.ts +15 -8
  1130. package/src/tools/credentials/metadata-store.ts +93 -43
  1131. package/src/tools/credentials/policy-types.ts +5 -2
  1132. package/src/tools/credentials/policy-validate.ts +21 -14
  1133. package/src/tools/credentials/post-connect-hooks.ts +18 -7
  1134. package/src/tools/credentials/resolve.ts +11 -10
  1135. package/src/tools/credentials/selection.ts +30 -25
  1136. package/src/tools/credentials/tool-policy.ts +5 -2
  1137. package/src/tools/credentials/vault.ts +452 -183
  1138. package/src/tools/document/document-tool.ts +23 -17
  1139. package/src/tools/document/editor-template.ts +12 -7
  1140. package/src/tools/execution-target.ts +13 -10
  1141. package/src/tools/execution-timeout.ts +6 -5
  1142. package/src/tools/executor.ts +141 -74
  1143. package/src/tools/filesystem/edit.ts +82 -45
  1144. package/src/tools/filesystem/fuzzy-match.ts +70 -32
  1145. package/src/tools/filesystem/read.ts +46 -28
  1146. package/src/tools/filesystem/view-image.ts +86 -42
  1147. package/src/tools/filesystem/write.ts +53 -32
  1148. package/src/tools/followups/followup_create.ts +43 -17
  1149. package/src/tools/followups/followup_list.ts +28 -13
  1150. package/src/tools/followups/followup_resolve.ts +9 -6
  1151. package/src/tools/guardian-control-plane-policy.ts +15 -14
  1152. package/src/tools/host-filesystem/edit.ts +77 -42
  1153. package/src/tools/host-filesystem/read.ts +52 -33
  1154. package/src/tools/host-filesystem/write.ts +50 -29
  1155. package/src/tools/host-terminal/host-shell.ts +97 -61
  1156. package/src/tools/mcp/mcp-tool-factory.ts +21 -14
  1157. package/src/tools/memory/definitions.ts +60 -28
  1158. package/src/tools/memory/handlers.ts +149 -77
  1159. package/src/tools/memory/register.ts +39 -16
  1160. package/src/tools/network/__tests__/web-search.test.ts +236 -177
  1161. package/src/tools/network/domain-normalize.ts +13 -9
  1162. package/src/tools/network/script-proxy/__tests__/logging.test.ts +193 -123
  1163. package/src/tools/network/script-proxy/__tests__/policy.test.ts +225 -127
  1164. package/src/tools/network/script-proxy/index.ts +1 -17
  1165. package/src/tools/network/script-proxy/session-manager.ts +151 -84
  1166. package/src/tools/network/url-safety.ts +56 -34
  1167. package/src/tools/network/web-fetch.ts +273 -155
  1168. package/src/tools/network/web-search.ts +166 -81
  1169. package/src/tools/permission-checker.ts +6 -25
  1170. package/src/tools/policy-context.ts +8 -5
  1171. package/src/tools/registry.ts +73 -46
  1172. package/src/tools/reminder/reminder-store.ts +65 -44
  1173. package/src/tools/reminder/reminder.ts +76 -35
  1174. package/src/tools/schedule/create.ts +44 -21
  1175. package/src/tools/schedule/delete.ts +8 -5
  1176. package/src/tools/schedule/list.ts +39 -19
  1177. package/src/tools/schedule/update.ts +49 -26
  1178. package/src/tools/secret-detection-handler.ts +130 -49
  1179. package/src/tools/sensitive-output-placeholders.ts +15 -8
  1180. package/src/tools/shared/filesystem/edit-engine.ts +45 -14
  1181. package/src/tools/shared/filesystem/errors.ts +18 -18
  1182. package/src/tools/shared/filesystem/file-ops-service.ts +59 -32
  1183. package/src/tools/shared/filesystem/format-diff.ts +21 -11
  1184. package/src/tools/shared/filesystem/path-policy.ts +17 -13
  1185. package/src/tools/shared/filesystem/size-guard.ts +8 -4
  1186. package/src/tools/shared/filesystem/types.ts +2 -2
  1187. package/src/tools/shared/shell-output.ts +4 -3
  1188. package/src/tools/side-effects.ts +36 -28
  1189. package/src/tools/skills/delete-managed.ts +30 -17
  1190. package/src/tools/skills/load.ts +88 -46
  1191. package/src/tools/skills/sandbox-runner.ts +62 -46
  1192. package/src/tools/skills/scaffold-managed.ts +98 -48
  1193. package/src/tools/skills/script-contract.ts +5 -2
  1194. package/src/tools/skills/skill-script-runner.ts +29 -13
  1195. package/src/tools/skills/skill-tool-factory.ts +20 -10
  1196. package/src/tools/subagent/abort.ts +10 -4
  1197. package/src/tools/subagent/message.ts +14 -8
  1198. package/src/tools/subagent/read.ts +20 -11
  1199. package/src/tools/subagent/spawn.ts +14 -6
  1200. package/src/tools/subagent/status.ts +7 -4
  1201. package/src/tools/swarm/delegate.ts +75 -49
  1202. package/src/tools/system/avatar-generator.ts +46 -33
  1203. package/src/tools/system/navigate-settings.ts +29 -19
  1204. package/src/tools/system/open-system-settings.ts +30 -20
  1205. package/src/tools/system/request-permission.ts +59 -44
  1206. package/src/tools/system/version.ts +27 -16
  1207. package/src/tools/system/voice-config.ts +116 -53
  1208. package/src/tools/tasks/index.ts +8 -8
  1209. package/src/tools/tasks/task-delete.ts +61 -22
  1210. package/src/tools/tasks/task-list.ts +23 -11
  1211. package/src/tools/tasks/task-run.ts +41 -16
  1212. package/src/tools/tasks/task-save.ts +27 -10
  1213. package/src/tools/tasks/work-item-enqueue.ts +114 -48
  1214. package/src/tools/tasks/work-item-list.ts +20 -10
  1215. package/src/tools/tasks/work-item-remove.ts +49 -15
  1216. package/src/tools/tasks/work-item-run.ts +34 -13
  1217. package/src/tools/tasks/work-item-update.ts +84 -31
  1218. package/src/tools/terminal/backends/native.ts +64 -35
  1219. package/src/tools/terminal/backends/types.ts +6 -2
  1220. package/src/tools/terminal/parser.ts +200 -125
  1221. package/src/tools/terminal/safe-env.ts +27 -21
  1222. package/src/tools/terminal/sandbox-diagnostics.ts +31 -13
  1223. package/src/tools/terminal/sandbox.ts +10 -6
  1224. package/src/tools/terminal/shell.ts +124 -68
  1225. package/src/tools/tool-approval-handler.ts +193 -138
  1226. package/src/tools/types.ts +43 -23
  1227. package/src/tools/ui-surface/definitions.ts +124 -89
  1228. package/src/tools/ui-surface/registry.ts +2 -2
  1229. package/src/tools/watch/screen-watch.ts +50 -32
  1230. package/src/tools/watch/watch-state.ts +41 -15
  1231. package/src/tools/watcher/create.ts +37 -15
  1232. package/src/tools/watcher/delete.ts +9 -6
  1233. package/src/tools/watcher/digest.ts +10 -6
  1234. package/src/tools/watcher/list.ts +37 -14
  1235. package/src/tools/watcher/update.ts +33 -18
  1236. package/src/tools/weather/service.ts +331 -174
  1237. package/src/twitter/client.ts +261 -138
  1238. package/src/twitter/oauth-client.ts +17 -13
  1239. package/src/twitter/router.ts +51 -23
  1240. package/src/twitter/session.ts +27 -18
  1241. package/src/types/qrcode.d.ts +6 -3
  1242. package/src/usage/actors.ts +16 -16
  1243. package/src/usage/types.ts +3 -3
  1244. package/src/util/bundled-asset.ts +10 -6
  1245. package/src/util/canonicalize-identity.ts +11 -4
  1246. package/src/util/clipboard.ts +7 -7
  1247. package/src/util/content-id.ts +3 -3
  1248. package/src/util/debounce.ts +3 -2
  1249. package/src/util/diff.ts +55 -33
  1250. package/src/util/errors.ts +26 -26
  1251. package/src/util/fs.ts +8 -2
  1252. package/src/util/log-redact.ts +12 -12
  1253. package/src/util/logger.ts +112 -51
  1254. package/src/util/network-info.ts +13 -5
  1255. package/src/util/object.ts +4 -2
  1256. package/src/util/phone.ts +4 -4
  1257. package/src/util/platform.ts +80 -58
  1258. package/src/util/pricing.ts +49 -31
  1259. package/src/util/retry.ts +18 -7
  1260. package/src/util/row-mapper.ts +7 -4
  1261. package/src/util/silently.ts +7 -4
  1262. package/src/util/spawn.ts +48 -0
  1263. package/src/util/spinner.ts +9 -7
  1264. package/src/util/time.ts +16 -3
  1265. package/src/util/truncate.ts +1 -1
  1266. package/src/util/voice-code.ts +6 -4
  1267. package/src/util/xml.ts +5 -1
  1268. package/src/version.ts +12 -8
  1269. package/src/watcher/engine.ts +71 -44
  1270. package/src/watcher/provider-registry.ts +1 -1
  1271. package/src/watcher/providers/github.ts +40 -23
  1272. package/src/watcher/providers/gmail.ts +59 -38
  1273. package/src/watcher/providers/google-calendar.ts +62 -48
  1274. package/src/watcher/providers/linear.ts +219 -150
  1275. package/src/watcher/providers/slack.ts +93 -27
  1276. package/src/watcher/watcher-store.ts +75 -55
  1277. package/src/work-items/work-item-runner.ts +62 -29
  1278. package/src/work-items/work-item-store.ts +137 -47
  1279. package/src/workspace/commit-message-enrichment-service.ts +65 -25
  1280. package/src/workspace/commit-message-provider.ts +14 -12
  1281. package/src/workspace/git-service.ts +355 -239
  1282. package/src/workspace/heartbeat-service.ts +74 -37
  1283. package/src/workspace/provider-commit-message-generator.ts +95 -70
  1284. package/src/workspace/top-level-renderer.ts +10 -8
  1285. package/src/workspace/top-level-scanner.ts +9 -3
  1286. package/src/workspace/turn-commit.ts +63 -36
  1287. package/src/__tests__/ingress-member-store.test.ts +0 -294
  1288. package/src/__tests__/script-proxy-router.test.ts +0 -215
  1289. package/src/config/bundled-skills/trusted-contacts/SKILL.md +0 -372
  1290. package/src/memory/guardian-bindings.ts +0 -158
  1291. package/src/memory/ingress-member-store.ts +0 -352
  1292. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -77
  1293. package/src/tools/network/script-proxy/certs.ts +0 -7
  1294. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -1
  1295. package/src/tools/network/script-proxy/http-forwarder.ts +0 -2
  1296. package/src/tools/network/script-proxy/logging.ts +0 -12
  1297. package/src/tools/network/script-proxy/mitm-handler.ts +0 -2
  1298. package/src/tools/network/script-proxy/policy.ts +0 -4
  1299. package/src/tools/network/script-proxy/router.ts +0 -2
  1300. package/src/tools/network/script-proxy/server.ts +0 -5
  1301. package/src/tools/network/script-proxy/types.ts +0 -19
@@ -1,52 +1,45 @@
1
1
  /**
2
2
  * Approval interception: checks for pending approvals and handles inbound
3
3
  * messages as decisions, reminders, or conversational follow-ups.
4
+ *
5
+ * This module is the top-level dispatcher. It delegates to strategy modules:
6
+ * - guardian-callback-strategy.ts — guardian callback button and text decisions
7
+ * - guardian-text-engine-strategy.ts — conversational engine for plain-text messages
8
+ * - guardian-legacy-fallback-strategy.ts — deterministic parser fallback
4
9
  */
5
- import { applyGuardianDecision } from '../../approvals/guardian-decision-primitive.js';
6
- import type { ChannelId } from '../../channels/types.js';
10
+ import { applyGuardianDecision } from "../../approvals/guardian-decision-primitive.js";
11
+ import type { ChannelId } from "../../channels/types.js";
12
+ import type { TrustContext } from "../../daemon/session-runtime-assembly.js";
7
13
  import {
8
- getAllPendingApprovalsByGuardianChat,
9
- getPendingApprovalByRequestAndGuardianChat,
10
14
  getPendingApprovalForRequest,
11
15
  getUnresolvedApprovalForRequest,
12
- type GuardianApprovalRequest,
13
16
  updateApprovalDecision,
14
- } from '../../memory/channel-guardian-store.js';
15
- import { emitNotificationSignal } from '../../notifications/emit-signal.js';
16
- import { getLogger } from '../../util/logger.js';
17
- import { runApprovalConversationTurn } from '../approval-conversation-turn.js';
18
- import { composeApprovalMessageGenerative } from '../approval-message-composer.js';
19
- import { parseApprovalDecision } from '../channel-approval-parser.js';
20
- import type {
21
- ApprovalAction,
22
- ApprovalDecisionResult,
23
- } from '../channel-approval-types.js';
17
+ } from "../../memory/channel-guardian-store.js";
18
+ import { getLogger } from "../../util/logger.js";
19
+ import { runApprovalConversationTurn } from "../approval-conversation-turn.js";
20
+ import { composeApprovalMessageGenerative } from "../approval-message-composer.js";
21
+ import type { ApprovalDecisionResult } from "../channel-approval-types.js";
24
22
  import {
25
23
  getApprovalInfoByConversation,
26
24
  getChannelApprovalPrompt,
27
25
  handleChannelDecision,
28
- } from '../channel-approvals.js';
29
- import { deliverChannelReply } from '../gateway-client.js';
26
+ } from "../channel-approvals.js";
27
+ import { deliverChannelReply } from "../gateway-client.js";
30
28
  import type {
31
29
  ApprovalConversationContext,
32
30
  ApprovalConversationGenerator,
33
31
  ApprovalCopyGenerator,
34
- } from '../http-types.js';
35
- import {
36
- deliverVerificationCodeToGuardian,
37
- type DeliveryResult,
38
- handleAccessRequestDecision,
39
- notifyRequesterOfApproval,
40
- notifyRequesterOfDeliveryFailure,
41
- notifyRequesterOfDenial,
42
- } from './access-request-decision.js';
32
+ } from "../http-types.js";
33
+ import { handleGuardianCallbackDecision } from "./approval-strategies/guardian-callback-strategy.js";
34
+ import { handleGuardianLegacyFallback } from "./approval-strategies/guardian-legacy-fallback-strategy.js";
35
+ import { handleGuardianTextEngineDecision } from "./approval-strategies/guardian-text-engine-strategy.js";
43
36
  import {
44
37
  buildGuardianDenyContext,
45
- type GuardianContext,
46
38
  parseCallbackData,
47
- } from './channel-route-shared.js';
39
+ } from "./channel-route-shared.js";
40
+ import { deliverStaleApprovalReply } from "./guardian-approval-reply-helpers.js";
48
41
 
49
- const log = getLogger('runtime-http');
42
+ const log = getLogger("runtime-http");
50
43
 
51
44
  export interface ApprovalInterceptionParams {
52
45
  conversationId: string;
@@ -57,7 +50,7 @@ export interface ApprovalInterceptionParams {
57
50
  actorExternalId?: string;
58
51
  replyCallbackUrl: string;
59
52
  bearerToken?: string;
60
- guardianCtx: GuardianContext;
53
+ trustCtx: TrustContext;
61
54
  assistantId: string;
62
55
  approvalCopyGenerator?: ApprovalCopyGenerator;
63
56
  approvalConversationGenerator?: ApprovalConversationGenerator;
@@ -65,7 +58,11 @@ export interface ApprovalInterceptionParams {
65
58
 
66
59
  export interface ApprovalInterceptionResult {
67
60
  handled: boolean;
68
- type?: 'decision_applied' | 'assistant_turn' | 'guardian_decision_applied' | 'stale_ignored';
61
+ type?:
62
+ | "decision_applied"
63
+ | "assistant_turn"
64
+ | "guardian_decision_applied"
65
+ | "stale_ignored";
69
66
  }
70
67
 
71
68
  /**
@@ -90,7 +87,7 @@ export async function handleApprovalInterception(
90
87
  actorExternalId,
91
88
  replyCallbackUrl,
92
89
  bearerToken,
93
- guardianCtx,
90
+ trustCtx,
94
91
  assistantId,
95
92
  approvalCopyGenerator,
96
93
  approvalConversationGenerator,
@@ -99,449 +96,22 @@ export async function handleApprovalInterception(
99
96
  // ── Guardian approval decision path ──
100
97
  // When the sender is the guardian and there's a pending guardian approval
101
98
  // request targeting this chat, the message might be a decision on behalf
102
- // of a non-guardian requester.
103
- if (
104
- guardianCtx.trustClass === 'guardian' &&
105
- actorExternalId
106
- ) {
107
- // Callback/button path: deterministic and takes priority.
108
- let callbackDecision: ApprovalDecisionResult | null = null;
109
- if (callbackData) {
110
- callbackDecision = parseCallbackData(callbackData, sourceChannel);
111
- }
112
-
113
- // When a callback button provides a request ID, use the scoped lookup so
114
- // the decision resolves to exactly the right approval even when
115
- // multiple approvals target the same guardian chat.
116
- let guardianApproval = callbackDecision?.requestId
117
- ? getPendingApprovalByRequestAndGuardianChat(callbackDecision.requestId, sourceChannel, conversationExternalId, assistantId)
118
- : null;
119
-
120
- // When the scoped lookup didn't resolve an approval (either because
121
- // there was no callback or the requestId pointed to a stale/expired request),
122
- // fall back to checking all pending approvals for this guardian chat.
123
- if (!guardianApproval && callbackDecision) {
124
- const allPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
125
- if (allPending.length === 1) {
126
- guardianApproval = allPending[0];
127
- } else if (allPending.length > 1) {
128
- // The callback targeted a stale/expired request but the guardian has other
129
- // pending approvals. Inform them the clicked approval is no longer valid.
130
- try {
131
- const staleText = await composeApprovalMessageGenerative({
132
- scenario: 'guardian_disambiguation',
133
- pendingCount: allPending.length,
134
- channel: sourceChannel,
135
- }, {}, approvalCopyGenerator);
136
- await deliverChannelReply(replyCallbackUrl, {
137
- chatId: conversationExternalId,
138
- text: staleText,
139
- assistantId,
140
- }, bearerToken);
141
- } catch (err) {
142
- log.error({ err, conversationExternalId }, 'Failed to deliver stale callback disambiguation notice');
143
- }
144
- return { handled: true, type: 'stale_ignored' };
145
- }
146
- }
147
-
148
- // For plain-text messages (no callback), check if there are any pending
149
- // approvals for this guardian chat to route through the conversation engine.
150
- if (!guardianApproval && !callbackDecision) {
151
- const allPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
152
- if (allPending.length === 1) {
153
- guardianApproval = allPending[0];
154
- } else if (allPending.length > 1) {
155
- // Multiple pending — pick the first approval matching this sender as
156
- // primary context. The conversation engine sees all matching approvals
157
- // via pendingApprovals and can disambiguate.
158
- guardianApproval = allPending.find(a => a.guardianExternalUserId === actorExternalId) ?? allPending[0];
159
- }
160
- }
161
-
162
- if (guardianApproval) {
163
- // Validate that the sender is the specific guardian who was assigned
164
- // this approval request. This is a defense-in-depth check — the
165
- // trustClass check above already verifies the sender is a guardian,
166
- // but this catches edge cases like binding rotation between request
167
- // creation and decision.
168
- if (actorExternalId !== guardianApproval.guardianExternalUserId) {
169
- log.warn(
170
- { conversationExternalId, actorExternalId, expectedGuardian: guardianApproval.guardianExternalUserId },
171
- 'Non-guardian sender attempted to act on guardian approval request',
172
- );
173
- try {
174
- const mismatchText = await composeApprovalMessageGenerative({
175
- scenario: 'guardian_identity_mismatch',
176
- channel: sourceChannel,
177
- }, {}, approvalCopyGenerator);
178
- await deliverChannelReply(replyCallbackUrl, {
179
- chatId: conversationExternalId,
180
- text: mismatchText,
181
- assistantId,
182
- }, bearerToken);
183
- } catch (err) {
184
- log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity rejection notice');
185
- }
186
- return { handled: true, type: 'guardian_decision_applied' };
187
- }
188
-
189
- if (callbackDecision) {
190
- // Access request approvals don't have a pending interaction in the
191
- // session tracker, so they need a separate decision path that creates
192
- // a verification session instead of resuming an agent loop.
193
- if (guardianApproval.toolName === 'ingress_access_request') {
194
- const accessResult = await handleAccessRequestApproval(
195
- guardianApproval,
196
- callbackDecision.action === 'reject' ? 'deny' : 'approve',
197
- actorExternalId,
198
- replyCallbackUrl,
199
- assistantId,
200
- bearerToken,
201
- );
202
- return accessResult;
203
- }
204
-
205
- // Apply the decision through the unified guardian decision primitive.
206
- // The primitive handles approve_always downgrade, approval info capture,
207
- // record update, and scoped grant minting.
208
- const result = applyGuardianDecision({
209
- approval: guardianApproval,
210
- decision: callbackDecision,
211
- actorExternalUserId: actorExternalId,
212
- actorChannel: sourceChannel,
213
- });
214
-
215
- if (result.applied) {
216
- // Notify the requester's chat about the outcome with the tool name
217
- const effectiveAction = callbackDecision.action === 'approve_always' ? 'approve_once' : callbackDecision.action;
218
- const outcomeText = await composeApprovalMessageGenerative({
219
- scenario: 'guardian_decision_outcome',
220
- decision: effectiveAction === 'reject' ? 'denied' : 'approved',
221
- toolName: guardianApproval.toolName,
222
- channel: sourceChannel,
223
- }, {}, approvalCopyGenerator);
224
- try {
225
- await deliverChannelReply(replyCallbackUrl, {
226
- chatId: guardianApproval.requesterChatId,
227
- text: outcomeText,
228
- assistantId,
229
- }, bearerToken);
230
- } catch (err) {
231
- log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to notify requester of guardian decision');
232
- }
233
-
234
- // Post-decision delivery is handled by the onEvent callback
235
- // in the session that registered the pending interaction.
236
- return { handled: true, type: 'guardian_decision_applied' };
237
- }
238
-
239
- // Race condition: callback arrived after request was already resolved.
240
- return { handled: true, type: 'stale_ignored' };
241
- }
242
-
243
- // ── Conversational engine for guardian plain-text messages ──
244
- // Gather all pending guardian approvals for this chat so the engine
245
- // can handle disambiguation when multiple are pending.
246
- const allGuardianPending = getAllPendingApprovalsByGuardianChat(sourceChannel, conversationExternalId, assistantId);
247
- // Only present approvals that belong to this sender so the engine
248
- // does not offer disambiguation for requests assigned to a rotated
249
- // guardian the sender cannot act on.
250
- const senderPending = allGuardianPending.filter(a => a.guardianExternalUserId === actorExternalId);
251
- const effectivePending = senderPending.length > 0 ? senderPending : allGuardianPending;
252
- if (effectivePending.length > 0 && approvalConversationGenerator && content) {
253
- const guardianAllowedActions = ['approve_once', 'reject'];
254
- const engineContext: ApprovalConversationContext = {
255
- toolName: guardianApproval.toolName,
256
- allowedActions: guardianAllowedActions,
257
- role: 'guardian',
258
- pendingApprovals: effectivePending.map((a) => ({ requestId: a.requestId ?? a.runId, toolName: a.toolName })),
259
- userMessage: content,
260
- };
261
-
262
- const engineResult = await runApprovalConversationTurn(engineContext, approvalConversationGenerator);
263
-
264
- if (engineResult.disposition === 'keep_pending') {
265
- // Non-decision follow-up (clarification, disambiguation, etc.)
266
- try {
267
- await deliverChannelReply(replyCallbackUrl, {
268
- chatId: conversationExternalId,
269
- text: engineResult.replyText,
270
- assistantId,
271
- }, bearerToken);
272
- } catch (err) {
273
- log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to deliver guardian conversation reply');
274
- }
275
- return { handled: true, type: 'assistant_turn' };
276
- }
277
-
278
- // Decision-bearing disposition from the engine
279
- let decisionAction = engineResult.disposition as ApprovalAction;
280
-
281
- // Belt-and-suspenders: guardians cannot use broad allow modes even if
282
- // the engine returns them (the engine's allowedActions validation should
283
- // already prevent this, but enforce it here too).
284
- if (decisionAction === 'approve_always' || decisionAction === 'approve_10m' || decisionAction === 'approve_thread') {
285
- decisionAction = 'approve_once';
286
- }
287
-
288
- // Resolve the target approval: use targetRequestId from the engine if
289
- // provided, otherwise use the single guardian approval.
290
- const targetApproval = engineResult.targetRequestId
291
- ? allGuardianPending.find((a) => (a.requestId ?? a.runId) === engineResult.targetRequestId) ?? guardianApproval
292
- : guardianApproval;
293
-
294
- // Re-validate guardian identity against the resolved target. The
295
- // engine may select a different pending approval (via targetRequestId)
296
- // that was assigned to a different guardian. Without this check a
297
- // currently bound guardian could act on a request assigned to a
298
- // previous guardian after a binding rotation.
299
- if (actorExternalId !== targetApproval.guardianExternalUserId) {
300
- log.warn(
301
- { conversationExternalId, actorExternalId, expectedGuardian: targetApproval.guardianExternalUserId, targetRequestId: engineResult.targetRequestId },
302
- 'Guardian identity mismatch on engine-selected target approval',
303
- );
304
- try {
305
- const mismatchText = await composeApprovalMessageGenerative({
306
- scenario: 'guardian_identity_mismatch',
307
- channel: sourceChannel,
308
- }, {}, approvalCopyGenerator);
309
- await deliverChannelReply(replyCallbackUrl, {
310
- chatId: conversationExternalId,
311
- text: mismatchText,
312
- assistantId,
313
- }, bearerToken);
314
- } catch (err) {
315
- log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity mismatch notice for engine target');
316
- }
317
- return { handled: true, type: 'guardian_decision_applied' };
318
- }
319
-
320
- // Access request approvals need a separate decision path.
321
- if (targetApproval.toolName === 'ingress_access_request') {
322
- const accessResult = await handleAccessRequestApproval(
323
- targetApproval,
324
- decisionAction === 'reject' ? 'deny' : 'approve',
325
- actorExternalId,
326
- replyCallbackUrl,
327
- assistantId,
328
- bearerToken,
329
- );
330
- return accessResult;
331
- }
332
-
333
- const engineDecision: ApprovalDecisionResult = {
334
- action: decisionAction,
335
- source: 'plain_text',
336
- ...(engineResult.targetRequestId ? { requestId: engineResult.targetRequestId } : {}),
337
- };
338
-
339
- // Apply the decision through the unified guardian decision primitive.
340
- const result = applyGuardianDecision({
341
- approval: targetApproval,
342
- decision: engineDecision,
343
- actorExternalUserId: actorExternalId,
344
- actorChannel: sourceChannel,
345
- });
346
-
347
- if (result.applied) {
348
- // Notify the requester's chat about the outcome
349
- const outcomeText = await composeApprovalMessageGenerative({
350
- scenario: 'guardian_decision_outcome',
351
- decision: decisionAction === 'reject' ? 'denied' : 'approved',
352
- toolName: targetApproval.toolName,
353
- channel: sourceChannel,
354
- }, {}, approvalCopyGenerator);
355
- try {
356
- await deliverChannelReply(replyCallbackUrl, {
357
- chatId: targetApproval.requesterChatId,
358
- text: outcomeText,
359
- assistantId,
360
- }, bearerToken);
361
- } catch (err) {
362
- log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to notify requester of guardian decision');
363
- }
364
-
365
- // Deliver the engine's reply to the guardian
366
- try {
367
- await deliverChannelReply(replyCallbackUrl, {
368
- chatId: conversationExternalId,
369
- text: engineResult.replyText,
370
- assistantId,
371
- }, bearerToken);
372
- } catch (err) {
373
- log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to deliver guardian decision reply');
374
- }
375
-
376
- return { handled: true, type: 'guardian_decision_applied' };
377
- }
378
-
379
- // Race condition: request was already resolved. Deliver a stale notice
380
- // instead of the engine's optimistic reply.
381
- try {
382
- const staleText = await composeApprovalMessageGenerative({
383
- scenario: 'approval_already_resolved',
384
- channel: sourceChannel,
385
- }, {}, approvalCopyGenerator);
386
- await deliverChannelReply(replyCallbackUrl, {
387
- chatId: conversationExternalId,
388
- text: staleText,
389
- assistantId,
390
- }, bearerToken);
391
- } catch (err) {
392
- log.error({ err, conversationId: targetApproval.conversationId }, 'Failed to deliver stale guardian approval notice');
393
- }
394
-
395
- return { handled: true, type: 'stale_ignored' };
396
- }
397
-
398
- // ── Legacy fallback when no conversational engine is available ──
399
- // Use the deterministic parser to handle guardian plain-text so that
400
- // simple yes/no replies still work when the engine is not injected.
401
- if (content && !approvalConversationGenerator) {
402
- const legacyGuardianDecision = parseApprovalDecision(content);
403
- if (legacyGuardianDecision) {
404
- // Guardians cannot approve_always — downgrade to approve_once.
405
- if (legacyGuardianDecision.action === 'approve_always') {
406
- legacyGuardianDecision.action = 'approve_once';
407
- }
408
-
409
- // Resolve the target approval: when a [ref:<requestId>] tag is
410
- // present, look up the specific pending approval by that requestId
411
- // so the decision applies to the correct conversation even when
412
- // multiple guardian approvals are pending.
413
- let targetLegacyApproval = guardianApproval;
414
- if (legacyGuardianDecision.requestId) {
415
- const resolvedByRequest = getPendingApprovalByRequestAndGuardianChat(
416
- legacyGuardianDecision.requestId,
417
- sourceChannel,
418
- conversationExternalId,
419
- assistantId,
420
- );
421
- if (!resolvedByRequest) {
422
- // The referenced request doesn't match any pending guardian
423
- // approval — it may have expired or already been resolved.
424
- try {
425
- const staleText = await composeApprovalMessageGenerative({
426
- scenario: 'guardian_disambiguation',
427
- channel: sourceChannel,
428
- }, {}, approvalCopyGenerator);
429
- await deliverChannelReply(replyCallbackUrl, {
430
- chatId: conversationExternalId,
431
- text: staleText,
432
- assistantId,
433
- }, bearerToken);
434
- } catch (err) {
435
- log.error({ err, conversationExternalId }, 'Failed to deliver stale approval notice (legacy path)');
436
- }
437
- return { handled: true, type: 'stale_ignored' };
438
- }
439
- targetLegacyApproval = resolvedByRequest;
440
- }
441
-
442
- // Re-validate guardian identity against the resolved target.
443
- // The default guardianApproval was already checked, but a
444
- // requestId-resolved approval may belong to a different guardian.
445
- if (actorExternalId !== targetLegacyApproval.guardianExternalUserId) {
446
- log.warn(
447
- { conversationExternalId, actorExternalId, expectedGuardian: targetLegacyApproval.guardianExternalUserId, requestId: legacyGuardianDecision.requestId },
448
- 'Guardian identity mismatch on legacy ref-resolved target approval',
449
- );
450
- try {
451
- const mismatchText = await composeApprovalMessageGenerative({
452
- scenario: 'guardian_identity_mismatch',
453
- channel: sourceChannel,
454
- }, {}, approvalCopyGenerator);
455
- await deliverChannelReply(replyCallbackUrl, {
456
- chatId: conversationExternalId,
457
- text: mismatchText,
458
- assistantId,
459
- }, bearerToken);
460
- } catch (err) {
461
- log.error({ err, conversationExternalId }, 'Failed to deliver guardian identity mismatch notice (legacy path)');
462
- }
463
- return { handled: true, type: 'guardian_decision_applied' };
464
- }
465
-
466
- // Access request approvals need a separate decision path.
467
- if (targetLegacyApproval.toolName === 'ingress_access_request') {
468
- const accessResult = await handleAccessRequestApproval(
469
- targetLegacyApproval,
470
- legacyGuardianDecision.action === 'reject' ? 'deny' : 'approve',
471
- actorExternalId,
472
- replyCallbackUrl,
473
- assistantId,
474
- bearerToken,
475
- );
476
- return accessResult;
477
- }
478
-
479
- // Apply the decision through the unified guardian decision primitive.
480
- const result = applyGuardianDecision({
481
- approval: targetLegacyApproval,
482
- decision: legacyGuardianDecision,
483
- actorExternalUserId: actorExternalId,
484
- actorChannel: sourceChannel,
485
- });
486
-
487
- if (result.applied) {
488
- // Notify the requester's chat about the outcome
489
- const outcomeText = await composeApprovalMessageGenerative({
490
- scenario: 'guardian_decision_outcome',
491
- decision: legacyGuardianDecision.action === 'reject' ? 'denied' : 'approved',
492
- toolName: targetLegacyApproval.toolName,
493
- channel: sourceChannel,
494
- }, {}, approvalCopyGenerator);
495
- try {
496
- await deliverChannelReply(replyCallbackUrl, {
497
- chatId: targetLegacyApproval.requesterChatId,
498
- text: outcomeText,
499
- assistantId,
500
- }, bearerToken);
501
- } catch (err) {
502
- log.error({ err, conversationId: targetLegacyApproval.conversationId }, 'Failed to notify requester of guardian decision (legacy path)');
503
- }
504
-
505
- return { handled: true, type: 'guardian_decision_applied' };
506
- }
507
-
508
- // Race condition: request was already resolved. Deliver stale notice.
509
- try {
510
- const staleText = await composeApprovalMessageGenerative({
511
- scenario: 'approval_already_resolved',
512
- channel: sourceChannel,
513
- }, {}, approvalCopyGenerator);
514
- await deliverChannelReply(replyCallbackUrl, {
515
- chatId: conversationExternalId,
516
- text: staleText,
517
- assistantId,
518
- }, bearerToken);
519
- } catch (err) {
520
- log.error({ err, conversationId: targetLegacyApproval.conversationId }, 'Failed to deliver stale guardian legacy fallback notice');
521
- }
522
- return { handled: true, type: 'stale_ignored' };
523
- }
524
-
525
- // No decision could be parsed — send a generic reminder to the guardian
526
- try {
527
- const reminderText = await composeApprovalMessageGenerative({
528
- scenario: 'reminder_prompt',
529
- toolName: guardianApproval.toolName,
530
- channel: sourceChannel,
531
- }, {}, approvalCopyGenerator);
532
- await deliverChannelReply(replyCallbackUrl, {
533
- chatId: conversationExternalId,
534
- text: reminderText,
535
- assistantId,
536
- }, bearerToken);
537
- } catch (err) {
538
- log.error({ err, conversationId: guardianApproval.conversationId }, 'Failed to deliver guardian reminder (legacy path)');
539
- }
540
- return { handled: true, type: 'assistant_turn' };
541
- }
542
-
543
- // No content and no engine — nothing to do, fall through to standard
544
- // approval interception below.
99
+ // of a non-guardian requester. Delegated to the guardian callback strategy.
100
+ if (trustCtx.trustClass === "guardian" && actorExternalId) {
101
+ const guardianResult = await handleGuardianCallbackDecision({
102
+ content,
103
+ callbackData,
104
+ conversationExternalId,
105
+ sourceChannel,
106
+ actorExternalId,
107
+ replyCallbackUrl,
108
+ bearerToken,
109
+ assistantId,
110
+ approvalCopyGenerator,
111
+ approvalConversationGenerator,
112
+ });
113
+ if (guardianResult) {
114
+ return guardianResult;
545
115
  }
546
116
  }
547
117
 
@@ -553,7 +123,8 @@ export async function handleApprovalInterception(
553
123
  // unknown trust + explicit denial reason (`no_identity` / `no_binding`).
554
124
  // Unknown without a denial reason means identity-known, non-member sender
555
125
  // in a shared channel; that case must not force-reject someone else's request.
556
- const isLegacyUnverifiedSender = guardianCtx.trustClass === 'unknown' && !!guardianCtx.denialReason;
126
+ const isLegacyUnverifiedSender =
127
+ trustCtx.trustClass === "unknown" && !!trustCtx.denialReason;
557
128
 
558
129
  // When the sender is from a legacy-unverified channel actor, auto-deny any
559
130
  // pending confirmation and block self-approval.
@@ -562,14 +133,14 @@ export async function handleApprovalInterception(
562
133
  if (pending.length > 0) {
563
134
  handleChannelDecision(
564
135
  conversationId,
565
- { action: 'reject', source: 'plain_text' },
136
+ { action: "reject", source: "plain_text" },
566
137
  buildGuardianDenyContext(
567
138
  pending[0].toolName,
568
- guardianCtx.denialReason ?? 'no_binding',
139
+ trustCtx.denialReason ?? "no_binding",
569
140
  sourceChannel,
570
141
  ),
571
142
  );
572
- return { handled: true, type: 'decision_applied' };
143
+ return { handled: true, type: "decision_applied" };
573
144
  }
574
145
  }
575
146
 
@@ -579,12 +150,15 @@ export async function handleApprovalInterception(
579
150
  //
580
151
  // Include identity-known, non-member senders (`unknown` without denialReason)
581
152
  // so shared-channel participants can't approve/deny someone else's pending request.
582
- const isIdentityKnownNonGuardian = guardianCtx.trustClass === 'trusted_contact'
583
- || (guardianCtx.trustClass === 'unknown' && !guardianCtx.denialReason);
153
+ const isIdentityKnownNonGuardian =
154
+ trustCtx.trustClass === "trusted_contact" ||
155
+ (trustCtx.trustClass === "unknown" && !trustCtx.denialReason);
584
156
  if (isIdentityKnownNonGuardian) {
585
157
  const pending = getApprovalInfoByConversation(conversationId);
586
158
  if (pending.length > 0) {
587
- const guardianApprovalForRequest = getPendingApprovalForRequest(pending[0].requestId);
159
+ const guardianApprovalForRequest = getPendingApprovalForRequest(
160
+ pending[0].requestId,
161
+ );
588
162
  if (guardianApprovalForRequest) {
589
163
  // Allow the requester to cancel their own pending guardian request.
590
164
  // Only reject/cancel is permitted — self-approval is still blocked.
@@ -599,24 +173,30 @@ export async function handleApprovalInterception(
599
173
  if (approvalConversationGenerator) {
600
174
  const cancelContext: ApprovalConversationContext = {
601
175
  toolName: pending[0].toolName,
602
- allowedActions: ['reject'],
603
- role: 'requester',
604
- pendingApprovals: pending.map(p => ({ requestId: p.requestId, toolName: p.toolName })),
176
+ allowedActions: ["reject"],
177
+ role: "requester",
178
+ pendingApprovals: pending.map((p) => ({
179
+ requestId: p.requestId,
180
+ toolName: p.toolName,
181
+ })),
605
182
  userMessage: content,
606
183
  };
607
- const cancelResult = await runApprovalConversationTurn(cancelContext, approvalConversationGenerator);
608
- if (cancelResult.disposition === 'reject') {
184
+ const cancelResult = await runApprovalConversationTurn(
185
+ cancelContext,
186
+ approvalConversationGenerator,
187
+ );
188
+ if (cancelResult.disposition === "reject") {
609
189
  requesterCancelIntent = true;
610
190
  cancelReplyText = cancelResult.replyText;
611
- } else if (cancelResult.disposition === 'keep_pending') {
191
+ } else if (cancelResult.disposition === "keep_pending") {
612
192
  requesterFollowupReplyText = cancelResult.replyText;
613
193
  }
614
194
  }
615
195
 
616
196
  if (requesterCancelIntent) {
617
197
  const rejectDecision: ApprovalDecisionResult = {
618
- action: 'reject',
619
- source: 'plain_text',
198
+ action: "reject",
199
+ source: "plain_text",
620
200
  };
621
201
  // Apply the cancel decision through the unified primitive.
622
202
  // The primitive handles record update and (no-op) grant logic.
@@ -628,119 +208,152 @@ export async function handleApprovalInterception(
628
208
  });
629
209
  if (cancelApplyResult.applied) {
630
210
  // Notify requester
631
- const replyText = cancelReplyText ?? await composeApprovalMessageGenerative({
632
- scenario: 'requester_cancel',
633
- toolName: pending[0].toolName,
634
- channel: sourceChannel,
635
- }, {}, approvalCopyGenerator);
211
+ const replyText =
212
+ cancelReplyText ??
213
+ (await composeApprovalMessageGenerative(
214
+ {
215
+ scenario: "requester_cancel",
216
+ toolName: pending[0].toolName,
217
+ channel: sourceChannel,
218
+ },
219
+ {},
220
+ approvalCopyGenerator,
221
+ ));
636
222
  try {
637
- await deliverChannelReply(replyCallbackUrl, {
638
- chatId: conversationExternalId,
639
- text: replyText,
640
- assistantId,
641
- }, bearerToken);
223
+ await deliverChannelReply(
224
+ replyCallbackUrl,
225
+ {
226
+ chatId: conversationExternalId,
227
+ text: replyText,
228
+ assistantId,
229
+ },
230
+ bearerToken,
231
+ );
642
232
  } catch (err) {
643
- log.error({ err, conversationId }, 'Failed to deliver requester cancel notice');
233
+ log.error(
234
+ { err, conversationId },
235
+ "Failed to deliver requester cancel notice",
236
+ );
644
237
  }
645
238
 
646
239
  // Notify guardian that the request was cancelled
647
240
  try {
648
- const guardianNotice = await composeApprovalMessageGenerative({
649
- scenario: 'guardian_decision_outcome',
650
- decision: 'denied',
651
- toolName: pending[0].toolName,
652
- channel: sourceChannel,
653
- }, {}, approvalCopyGenerator);
654
- await deliverChannelReply(replyCallbackUrl, {
655
- chatId: guardianApprovalForRequest.guardianChatId,
656
- text: guardianNotice,
657
- assistantId,
658
- }, bearerToken);
241
+ const guardianNotice = await composeApprovalMessageGenerative(
242
+ {
243
+ scenario: "guardian_decision_outcome",
244
+ decision: "denied",
245
+ toolName: pending[0].toolName,
246
+ channel: sourceChannel,
247
+ },
248
+ {},
249
+ approvalCopyGenerator,
250
+ );
251
+ await deliverChannelReply(
252
+ replyCallbackUrl,
253
+ {
254
+ chatId: guardianApprovalForRequest.guardianChatId,
255
+ text: guardianNotice,
256
+ assistantId,
257
+ },
258
+ bearerToken,
259
+ );
659
260
  } catch (err) {
660
- log.error({ err, conversationId }, 'Failed to notify guardian of requester cancellation');
261
+ log.error(
262
+ { err, conversationId },
263
+ "Failed to notify guardian of requester cancellation",
264
+ );
661
265
  }
662
266
 
663
- return { handled: true, type: 'decision_applied' };
267
+ return { handled: true, type: "decision_applied" };
664
268
  }
665
269
 
666
270
  // Race condition: approval was already resolved elsewhere.
667
- try {
668
- const staleText = await composeApprovalMessageGenerative({
669
- scenario: 'approval_already_resolved',
670
- channel: sourceChannel,
671
- }, {}, approvalCopyGenerator);
672
- await deliverChannelReply(replyCallbackUrl, {
673
- chatId: conversationExternalId,
674
- text: staleText,
675
- assistantId,
676
- }, bearerToken);
677
- } catch (err) {
678
- log.error({ err, conversationId }, 'Failed to deliver stale requester-cancel notice');
679
- }
680
- return { handled: true, type: 'stale_ignored' };
271
+ await deliverStaleApprovalReply({
272
+ scenario: "approval_already_resolved",
273
+ sourceChannel,
274
+ replyCallbackUrl,
275
+ chatId: conversationExternalId,
276
+ assistantId,
277
+ bearerToken,
278
+ approvalCopyGenerator,
279
+ logger: log,
280
+ errorLogMessage:
281
+ "Failed to deliver stale requester-cancel notice",
282
+ errorLogContext: { conversationId },
283
+ });
284
+ return { handled: true, type: "stale_ignored" };
681
285
  }
682
286
 
683
287
  if (requesterFollowupReplyText) {
684
288
  try {
685
- await deliverChannelReply(replyCallbackUrl, {
686
- chatId: conversationExternalId,
687
- text: requesterFollowupReplyText,
688
- assistantId,
689
- }, bearerToken);
289
+ await deliverChannelReply(
290
+ replyCallbackUrl,
291
+ {
292
+ chatId: conversationExternalId,
293
+ text: requesterFollowupReplyText,
294
+ assistantId,
295
+ },
296
+ bearerToken,
297
+ );
690
298
  } catch (err) {
691
- log.error({ err, conversationId }, 'Failed to deliver requester follow-up reply while awaiting guardian');
299
+ log.error(
300
+ { err, conversationId },
301
+ "Failed to deliver requester follow-up reply while awaiting guardian",
302
+ );
692
303
  }
693
- return { handled: true, type: 'assistant_turn' };
304
+ return { handled: true, type: "assistant_turn" };
694
305
  }
695
306
  }
696
307
 
697
308
  // Not a cancel intent — tell the requester their request is pending
698
- try {
699
- const pendingText = await composeApprovalMessageGenerative({
700
- scenario: 'request_pending_guardian',
701
- channel: sourceChannel,
702
- }, {}, approvalCopyGenerator);
703
- await deliverChannelReply(replyCallbackUrl, {
704
- chatId: conversationExternalId,
705
- text: pendingText,
706
- assistantId,
707
- }, bearerToken);
708
- } catch (err) {
709
- log.error({ err, conversationId }, 'Failed to deliver guardian-pending notice to requester');
710
- }
711
- return { handled: true, type: 'assistant_turn' };
309
+ await deliverStaleApprovalReply({
310
+ scenario: "request_pending_guardian",
311
+ sourceChannel,
312
+ replyCallbackUrl,
313
+ chatId: conversationExternalId,
314
+ assistantId,
315
+ bearerToken,
316
+ approvalCopyGenerator,
317
+ logger: log,
318
+ errorLogMessage:
319
+ "Failed to deliver guardian-pending notice to requester",
320
+ errorLogContext: { conversationId },
321
+ });
322
+ return { handled: true, type: "assistant_turn" };
712
323
  }
713
324
 
714
325
  // Check for an expired-but-unresolved guardian approval. If the approval
715
326
  // expired without a guardian decision, auto-deny and transition
716
327
  // the approval to 'expired'. Without this, the requester could bypass
717
328
  // guardian-only controls by simply waiting for the TTL to elapse.
718
- const unresolvedApproval = getUnresolvedApprovalForRequest(pending[0].requestId);
329
+ const unresolvedApproval = getUnresolvedApprovalForRequest(
330
+ pending[0].requestId,
331
+ );
719
332
  if (unresolvedApproval) {
720
- updateApprovalDecision(unresolvedApproval.id, { status: 'expired' });
333
+ updateApprovalDecision(unresolvedApproval.id, { status: "expired" });
721
334
 
722
335
  // Auto-deny the underlying request so it does not remain actionable
723
336
  const expiredDecision: ApprovalDecisionResult = {
724
- action: 'reject',
725
- source: 'plain_text',
337
+ action: "reject",
338
+ source: "plain_text",
726
339
  };
727
340
  handleChannelDecision(conversationId, expiredDecision);
728
341
 
729
- try {
730
- const expiredText = await composeApprovalMessageGenerative({
731
- scenario: 'guardian_expired_requester',
732
- toolName: pending[0].toolName,
733
- channel: sourceChannel,
734
- }, {}, approvalCopyGenerator);
735
- await deliverChannelReply(replyCallbackUrl, {
736
- chatId: conversationExternalId,
737
- text: expiredText,
738
- assistantId,
739
- }, bearerToken);
740
- } catch (err) {
741
- log.error({ err, conversationId }, 'Failed to deliver guardian-expiry notice to requester');
742
- }
743
- return { handled: true, type: 'decision_applied' };
342
+ await deliverStaleApprovalReply({
343
+ scenario: "guardian_expired_requester",
344
+ sourceChannel,
345
+ replyCallbackUrl,
346
+ chatId: conversationExternalId,
347
+ assistantId,
348
+ bearerToken,
349
+ approvalCopyGenerator,
350
+ logger: log,
351
+ errorLogMessage:
352
+ "Failed to deliver guardian-expiry notice to requester",
353
+ extraContext: { toolName: pending[0].toolName },
354
+ errorLogContext: { conversationId },
355
+ });
356
+ return { handled: true, type: "decision_applied" };
744
357
  }
745
358
 
746
359
  // Guard: non-guardian actors with a guardian binding must not self-approve
@@ -751,25 +364,32 @@ export async function handleApprovalInterception(
751
364
  // persisted, any non-guardian actor could otherwise fall through to the
752
365
  // standard conversational engine / legacy parser and resolve their own
753
366
  // pending request via handleChannelDecision.
754
- if (guardianCtx.trustClass !== 'guardian' && guardianCtx.guardianExternalUserId) {
367
+ if (
368
+ trustCtx.trustClass !== "guardian" &&
369
+ trustCtx.guardianExternalUserId
370
+ ) {
755
371
  log.info(
756
- { conversationId, conversationExternalId, guardianExternalUserId: guardianCtx.guardianExternalUserId },
757
- 'Blocking non-guardian self-approval: pending confirmation exists but guardian approval row not yet created',
372
+ {
373
+ conversationId,
374
+ conversationExternalId,
375
+ guardianExternalUserId: trustCtx.guardianExternalUserId,
376
+ },
377
+ "Blocking non-guardian self-approval: pending confirmation exists but guardian approval row not yet created",
758
378
  );
759
- try {
760
- const pendingText = await composeApprovalMessageGenerative({
761
- scenario: 'request_pending_guardian',
762
- channel: sourceChannel,
763
- }, {}, approvalCopyGenerator);
764
- await deliverChannelReply(replyCallbackUrl, {
765
- chatId: conversationExternalId,
766
- text: pendingText,
767
- assistantId,
768
- }, bearerToken);
769
- } catch (err) {
770
- log.error({ err, conversationId }, 'Failed to deliver guardian-pending notice to non-guardian actor (pre-row guard)');
771
- }
772
- return { handled: true, type: 'assistant_turn' };
379
+ await deliverStaleApprovalReply({
380
+ scenario: "request_pending_guardian",
381
+ sourceChannel,
382
+ replyCallbackUrl,
383
+ chatId: conversationExternalId,
384
+ assistantId,
385
+ bearerToken,
386
+ approvalCopyGenerator,
387
+ logger: log,
388
+ errorLogMessage:
389
+ "Failed to deliver guardian-pending notice to non-guardian actor (pre-row guard)",
390
+ errorLogContext: { conversationId },
391
+ });
392
+ return { handled: true, type: "assistant_turn" };
773
393
  }
774
394
  }
775
395
  }
@@ -784,12 +404,15 @@ export async function handleApprovalInterception(
784
404
  // previous approval prompt) must not apply to a different pending interaction.
785
405
  if (cbDecision.requestId) {
786
406
  const pending = getApprovalInfoByConversation(conversationId);
787
- if (pending.length === 0 || !pending.some(p => p.requestId === cbDecision.requestId)) {
407
+ if (
408
+ pending.length === 0 ||
409
+ !pending.some((p) => p.requestId === cbDecision.requestId)
410
+ ) {
788
411
  log.warn(
789
412
  { conversationId, callbackRequestId: cbDecision.requestId },
790
- 'Callback request ID does not match any pending interaction, ignoring stale button press',
413
+ "Callback request ID does not match any pending interaction, ignoring stale button press",
791
414
  );
792
- return { handled: true, type: 'stale_ignored' };
415
+ return { handled: true, type: "stale_ignored" };
793
416
  }
794
417
  }
795
418
 
@@ -798,321 +421,73 @@ export async function handleApprovalInterception(
798
421
  if (result.applied) {
799
422
  // Post-decision delivery is handled by the onEvent callback
800
423
  // in the session that registered the pending interaction.
801
- return { handled: true, type: 'decision_applied' };
424
+ return { handled: true, type: "decision_applied" };
802
425
  }
803
426
 
804
427
  // Race condition: request was already resolved between the stale check
805
428
  // above and the decision attempt.
806
- return { handled: true, type: 'stale_ignored' };
429
+ return { handled: true, type: "stale_ignored" };
807
430
  }
808
431
  }
809
432
 
810
433
  // ── Conversational approval engine for plain-text messages ──
811
- // Instead of deterministic keyword matching and reminder prompts, delegate
812
- // to the conversational approval engine which can classify natural language
813
- // and respond conversationally.
434
+ // Delegates to the text engine strategy which classifies natural language
435
+ // and responds conversationally.
814
436
  const pending = getApprovalInfoByConversation(conversationId);
815
437
  if (pending.length > 0 && approvalConversationGenerator && content) {
816
438
  const allowedActions = pendingPrompt.actions.map((a) => a.id);
817
- const engineContext: ApprovalConversationContext = {
818
- toolName: pending[0].toolName,
819
- allowedActions,
820
- role: 'requester',
821
- pendingApprovals: pending.map((p) => ({ requestId: p.requestId, toolName: p.toolName })),
822
- userMessage: content,
823
- };
824
-
825
- const engineResult = await runApprovalConversationTurn(engineContext, approvalConversationGenerator);
826
-
827
- if (engineResult.disposition === 'keep_pending') {
828
- // Non-decision follow-up — deliver the engine's reply and keep the request pending
829
- try {
830
- await deliverChannelReply(replyCallbackUrl, {
831
- chatId: conversationExternalId,
832
- text: engineResult.replyText,
833
- assistantId,
834
- }, bearerToken);
835
- } catch (err) {
836
- log.error({ err, conversationId }, 'Failed to deliver approval conversation reply');
837
- }
838
- return { handled: true, type: 'assistant_turn' };
839
- }
840
-
841
- // Decision-bearing disposition — map to ApprovalDecisionResult and apply
842
- const decisionAction = engineResult.disposition as ApprovalAction;
843
- const engineDecision: ApprovalDecisionResult = {
844
- action: decisionAction,
845
- source: 'plain_text',
846
- ...(engineResult.targetRequestId ? { requestId: engineResult.targetRequestId } : {}),
847
- };
848
-
849
- const result = handleChannelDecision(conversationId, engineDecision);
850
-
851
- if (result.applied) {
852
- // Deliver the engine's reply text to the user
853
- try {
854
- await deliverChannelReply(replyCallbackUrl, {
855
- chatId: conversationExternalId,
856
- text: engineResult.replyText,
857
- assistantId,
858
- }, bearerToken);
859
- } catch (err) {
860
- log.error({ err, conversationId }, 'Failed to deliver approval decision reply');
861
- }
862
-
863
- return { handled: true, type: 'decision_applied' };
864
- }
865
-
866
- // Race condition: request was already resolved by expiry sweep or
867
- // concurrent callback. Deliver a stale notice instead of the
868
- // engine's optimistic reply.
869
- try {
870
- const staleText = await composeApprovalMessageGenerative({
871
- scenario: 'approval_already_resolved',
872
- channel: sourceChannel,
873
- }, {}, approvalCopyGenerator);
874
- await deliverChannelReply(replyCallbackUrl, {
875
- chatId: conversationExternalId,
876
- text: staleText,
877
- assistantId,
878
- }, bearerToken);
879
- } catch (err) {
880
- log.error({ err, conversationId }, 'Failed to deliver stale approval notice');
881
- }
882
-
883
- return { handled: true, type: 'stale_ignored' };
884
- }
885
-
886
- // Fallback: no conversational generator available or no content — use
887
- // the legacy deterministic path as a safety net. This preserves backward
888
- // compatibility when the generator is not injected.
889
- if (content) {
890
- const legacyDecision = parseApprovalDecision(content);
891
- if (legacyDecision) {
892
- if (legacyDecision.requestId) {
893
- if (pending.length === 0 || !pending.some(p => p.requestId === legacyDecision.requestId)) {
894
- return { handled: true, type: 'stale_ignored' };
895
- }
896
- }
897
- const result = handleChannelDecision(conversationId, legacyDecision);
898
- if (result.applied) {
899
- return { handled: true, type: 'decision_applied' };
900
- }
901
-
902
- // Race condition: request was already resolved.
903
- try {
904
- const staleText = await composeApprovalMessageGenerative({
905
- scenario: 'approval_already_resolved',
906
- channel: sourceChannel,
907
- }, {}, approvalCopyGenerator);
908
- await deliverChannelReply(replyCallbackUrl, {
909
- chatId: conversationExternalId,
910
- text: staleText,
911
- assistantId,
912
- }, bearerToken);
913
- } catch (err) {
914
- log.error({ err, conversationId }, 'Failed to deliver stale approval notice (legacy path)');
915
- }
916
- return { handled: true, type: 'stale_ignored' };
917
- }
918
- }
919
-
920
- // No decision could be extracted and no conversational engine is available —
921
- // deliver a simple status reply rather than a reminder prompt.
922
- try {
923
- const statusText = await composeApprovalMessageGenerative({
924
- scenario: 'reminder_prompt',
925
- channel: sourceChannel,
926
- toolName: pending.length > 0 ? pending[0].toolName : undefined,
927
- }, {}, approvalCopyGenerator);
928
- await deliverChannelReply(replyCallbackUrl, {
929
- chatId: conversationExternalId,
930
- text: statusText,
931
- assistantId,
932
- }, bearerToken);
933
- } catch (err) {
934
- log.error({ err, conversationId }, 'Failed to deliver approval status reply');
935
- }
936
-
937
- return { handled: true, type: 'assistant_turn' };
938
- }
939
-
940
- // ---------------------------------------------------------------------------
941
- // Access request decision helper
942
- // ---------------------------------------------------------------------------
943
-
944
- /**
945
- * Handle a guardian's decision on an `ingress_access_request` approval.
946
- * Delegates to the access-request-decision module and orchestrates
947
- * notification delivery.
948
- *
949
- * On approve: creates a verification session, delivers the code to the
950
- * guardian, and notifies the requester to expect a code.
951
- *
952
- * On deny: marks the request as denied and notifies the requester.
953
- */
954
- async function handleAccessRequestApproval(
955
- approval: GuardianApprovalRequest,
956
- action: 'approve' | 'deny',
957
- decidedByExternalUserId: string,
958
- replyCallbackUrl: string,
959
- assistantId: string,
960
- bearerToken?: string,
961
- ): Promise<ApprovalInterceptionResult> {
962
- const decisionResult = handleAccessRequestDecision(
963
- approval,
964
- action,
965
- decidedByExternalUserId,
966
- );
967
-
968
- if (decisionResult.type === 'stale' || decisionResult.type === 'idempotent') {
969
- return { handled: true, type: 'stale_ignored' };
970
- }
971
-
972
- if (decisionResult.type === 'denied') {
973
- await notifyRequesterOfDenial({
439
+ return handleGuardianTextEngineDecision({
440
+ conversationId,
441
+ conversationExternalId,
442
+ sourceChannel,
974
443
  replyCallbackUrl,
975
- requesterChatId: approval.requesterChatId,
444
+ content,
976
445
  assistantId,
977
446
  bearerToken,
447
+ approvalCopyGenerator,
448
+ approvalConversationGenerator,
449
+ pending,
450
+ allowedActions,
978
451
  });
979
-
980
- // Emit both guardian_decision and denied signals so all lifecycle
981
- // observers are notified of the denial.
982
- const deniedPayload = {
983
- sourceChannel: approval.channel,
984
- requesterExternalUserId: approval.requesterExternalUserId,
985
- requesterChatId: approval.requesterChatId,
986
- decidedByExternalUserId,
987
- decision: 'denied' as const,
988
- };
989
-
990
- void emitNotificationSignal({
991
- sourceEventName: 'ingress.trusted_contact.guardian_decision',
992
- sourceChannel: approval.channel,
993
- sourceSessionId: approval.conversationId,
994
- assistantId,
995
- attentionHints: {
996
- requiresAction: false,
997
- urgency: 'medium',
998
- isAsyncBackground: false,
999
- visibleInSourceNow: false,
1000
- },
1001
- contextPayload: deniedPayload,
1002
- dedupeKey: `trusted-contact:guardian-decision:${approval.id}`,
1003
- });
1004
-
1005
- void emitNotificationSignal({
1006
- sourceEventName: 'ingress.trusted_contact.denied',
1007
- sourceChannel: approval.channel,
1008
- sourceSessionId: approval.conversationId,
1009
- assistantId,
1010
- attentionHints: {
1011
- requiresAction: false,
1012
- urgency: 'low',
1013
- isAsyncBackground: false,
1014
- visibleInSourceNow: false,
1015
- },
1016
- contextPayload: deniedPayload,
1017
- dedupeKey: `trusted-contact:denied:${approval.id}`,
1018
- });
1019
-
1020
- return { handled: true, type: 'guardian_decision_applied' };
1021
452
  }
1022
453
 
1023
- // Approved: deliver the verification code to the guardian and notify the requester.
1024
- const requesterIdentifier = approval.requesterExternalUserId;
1025
-
1026
- let codeDelivered = true;
1027
- if (decisionResult.verificationCode) {
1028
- const deliveryResult: DeliveryResult = await deliverVerificationCodeToGuardian({
454
+ // ── Legacy deterministic fallback ──
455
+ // When no conversational engine is available, use the deterministic parser
456
+ // as a safety net for backward compatibility.
457
+ if (content) {
458
+ const legacyResult = await handleGuardianLegacyFallback({
459
+ conversationId,
460
+ conversationExternalId,
461
+ sourceChannel,
1029
462
  replyCallbackUrl,
1030
- guardianChatId: approval.guardianChatId,
1031
- requesterIdentifier,
1032
- verificationCode: decisionResult.verificationCode,
463
+ content,
1033
464
  assistantId,
1034
465
  bearerToken,
466
+ approvalCopyGenerator,
467
+ pending,
1035
468
  });
1036
- if (!deliveryResult.ok) {
1037
- log.error(
1038
- { reason: deliveryResult.reason, approvalId: approval.id },
1039
- 'Skipping requester notification — verification code was not delivered to guardian',
1040
- );
1041
- codeDelivered = false;
469
+ if (legacyResult) {
470
+ return legacyResult;
1042
471
  }
1043
472
  }
1044
473
 
1045
- if (codeDelivered) {
1046
- await notifyRequesterOfApproval({
1047
- replyCallbackUrl,
1048
- requesterChatId: approval.requesterChatId,
1049
- assistantId,
1050
- bearerToken,
1051
- });
1052
- } else {
1053
- // Let the requester know something went wrong without revealing details
1054
- await notifyRequesterOfDeliveryFailure({
1055
- replyCallbackUrl,
1056
- requesterChatId: approval.requesterChatId,
1057
- assistantId,
1058
- bearerToken,
1059
- });
1060
- }
1061
-
1062
- // Don't emit guardian_decision for approvals that still require code
1063
- // verification — the guardian already received the code, and emitting
1064
- // this signal prematurely causes the notification pipeline to deliver
1065
- // a confusing "approved" message before the requester has verified.
1066
- // The guardian_decision signal should only fire once access is fully granted
1067
- // (i.e. after code consumption), which is handled in the verification path.
1068
- if (!decisionResult.verificationSessionId) {
1069
- void emitNotificationSignal({
1070
- sourceEventName: 'ingress.trusted_contact.guardian_decision',
1071
- sourceChannel: approval.channel,
1072
- sourceSessionId: approval.conversationId,
1073
- assistantId,
1074
- attentionHints: {
1075
- requiresAction: false,
1076
- urgency: 'medium',
1077
- isAsyncBackground: false,
1078
- visibleInSourceNow: false,
1079
- },
1080
- contextPayload: {
1081
- sourceChannel: approval.channel,
1082
- requesterExternalUserId: approval.requesterExternalUserId,
1083
- requesterChatId: approval.requesterChatId,
1084
- decidedByExternalUserId,
1085
- decision: 'approved',
1086
- },
1087
- dedupeKey: `trusted-contact:guardian-decision:${approval.id}`,
1088
- });
1089
- }
1090
-
1091
- // Emit verification_sent with visibleInSourceNow=true so the notification
1092
- // pipeline suppresses delivery — the guardian already received the
1093
- // verification code directly. Without this flag, the pipeline generates
1094
- // a redundant LLM message like "Good news! Your request has been approved."
1095
- if (decisionResult.verificationSessionId && codeDelivered) {
1096
- void emitNotificationSignal({
1097
- sourceEventName: 'ingress.trusted_contact.verification_sent',
1098
- sourceChannel: approval.channel,
1099
- sourceSessionId: approval.conversationId,
1100
- assistantId,
1101
- attentionHints: {
1102
- requiresAction: false,
1103
- urgency: 'low',
1104
- isAsyncBackground: true,
1105
- visibleInSourceNow: true,
1106
- },
1107
- contextPayload: {
1108
- sourceChannel: approval.channel,
1109
- requesterExternalUserId: approval.requesterExternalUserId,
1110
- requesterChatId: approval.requesterChatId,
1111
- verificationSessionId: decisionResult.verificationSessionId,
1112
- },
1113
- dedupeKey: `trusted-contact:verification-sent:${decisionResult.verificationSessionId}`,
1114
- });
1115
- }
474
+ // No decision could be extracted and no conversational engine is available —
475
+ // deliver a simple status reply rather than a reminder prompt.
476
+ await deliverStaleApprovalReply({
477
+ scenario: "reminder_prompt",
478
+ sourceChannel,
479
+ replyCallbackUrl,
480
+ chatId: conversationExternalId,
481
+ assistantId,
482
+ bearerToken,
483
+ approvalCopyGenerator,
484
+ logger: log,
485
+ errorLogMessage: "Failed to deliver approval status reply",
486
+ extraContext: {
487
+ toolName: pending.length > 0 ? pending[0].toolName : undefined,
488
+ },
489
+ errorLogContext: { conversationId },
490
+ });
1116
491
 
1117
- return { handled: true, type: 'guardian_decision_applied' };
492
+ return { handled: true, type: "assistant_turn" };
1118
493
  }