@vellumai/assistant 0.4.41 → 0.4.43

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 (843) hide show
  1. package/.env.example +1 -6
  2. package/.prettierignore +3 -0
  3. package/ARCHITECTURE.md +131 -393
  4. package/Dockerfile +0 -1
  5. package/README.md +73 -83
  6. package/bun.lock +8 -2
  7. package/docs/architecture/integrations.md +16 -21
  8. package/docs/architecture/memory.md +1 -1
  9. package/docs/architecture/scheduling.md +63 -63
  10. package/docs/architecture/security.md +3 -3
  11. package/docs/runbook-trusted-contacts.md +11 -12
  12. package/docs/trusted-contact-access.md +39 -39
  13. package/package.json +5 -8
  14. package/src/__tests__/access-request-decision.test.ts +4 -4
  15. package/src/__tests__/active-skill-tools.test.ts +49 -34
  16. package/src/__tests__/actor-token-service.test.ts +55 -85
  17. package/src/__tests__/amazon-cdp-integration.test.ts +14 -26
  18. package/src/__tests__/app-bundler.test.ts +14 -368
  19. package/src/__tests__/app-compiler.test.ts +0 -1
  20. package/src/__tests__/app-executors.test.ts +10 -1
  21. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +1 -1
  22. package/src/__tests__/approval-primitive.test.ts +2 -4
  23. package/src/__tests__/approval-routes-http.test.ts +1 -1
  24. package/src/__tests__/asset-materialize-tool.test.ts +1 -4
  25. package/src/__tests__/asset-search-tool.test.ts +1 -4
  26. package/src/__tests__/assistant-attachments.test.ts +23 -0
  27. package/src/__tests__/assistant-feature-flags-integration.test.ts +4 -8
  28. package/src/__tests__/assistant-id-boundary-guard.test.ts +5 -5
  29. package/src/__tests__/attachments-store.test.ts +1 -4
  30. package/src/__tests__/avatar-e2e.test.ts +43 -23
  31. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  32. package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -9
  33. package/src/__tests__/call-controller.test.ts +4 -8
  34. package/src/__tests__/call-conversation-messages.test.ts +1 -1
  35. package/src/__tests__/call-domain.test.ts +250 -8
  36. package/src/__tests__/call-pointer-message-composer.test.ts +14 -14
  37. package/src/__tests__/call-pointer-messages.test.ts +7 -11
  38. package/src/__tests__/call-recovery.test.ts +47 -0
  39. package/src/__tests__/call-routes-http.test.ts +13 -0
  40. package/src/__tests__/call-start-guardian-guard.test.ts +1 -1
  41. package/src/__tests__/callback-handoff-copy.test.ts +5 -5
  42. package/src/__tests__/canonical-guardian-store.test.ts +3 -3
  43. package/src/__tests__/channel-approval-routes.test.ts +101 -134
  44. package/src/__tests__/channel-approval.test.ts +0 -201
  45. package/src/__tests__/channel-approvals.test.ts +2 -2
  46. package/src/__tests__/channel-delivery-store.test.ts +16 -24
  47. package/src/__tests__/channel-guardian.test.ts +641 -740
  48. package/src/__tests__/channel-invite-transport.test.ts +1 -2
  49. package/src/__tests__/channel-policy.test.ts +9 -12
  50. package/src/__tests__/channel-readiness-service.test.ts +156 -45
  51. package/src/__tests__/channel-reply-delivery.test.ts +3 -3
  52. package/src/__tests__/channel-retry-sweep.test.ts +7 -7
  53. package/src/__tests__/checker.test.ts +10 -7
  54. package/src/__tests__/chrome-cdp.test.ts +57 -17
  55. package/src/__tests__/cli-help-reference-sync.test.ts +26 -0
  56. package/src/__tests__/compaction.benchmark.test.ts +25 -5
  57. package/src/__tests__/computer-use-session-lifecycle.test.ts +1 -1
  58. package/src/__tests__/computer-use-session-working-dir.test.ts +2 -6
  59. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +1 -1
  60. package/src/__tests__/config-loader-backfill.test.ts +310 -0
  61. package/src/__tests__/config-watcher.test.ts +1 -5
  62. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +3 -5
  63. package/src/__tests__/connection-policy.test.ts +3 -62
  64. package/src/__tests__/contacts-tools.test.ts +0 -2
  65. package/src/__tests__/context-memory-e2e.test.ts +11 -7
  66. package/src/__tests__/context-overflow-policy.test.ts +2 -2
  67. package/src/__tests__/context-window-manager.test.ts +220 -61
  68. package/src/__tests__/conversation-attention-store.test.ts +178 -2
  69. package/src/__tests__/conversation-attention-telegram.test.ts +8 -11
  70. package/src/__tests__/conversation-pairing.test.ts +14 -14
  71. package/src/__tests__/conversation-routes-guardian-reply.test.ts +1 -1
  72. package/src/__tests__/conversation-store.test.ts +2 -2
  73. package/src/__tests__/conversation-unread-route.test.ts +155 -0
  74. package/src/__tests__/credential-metadata-store.test.ts +0 -2
  75. package/src/__tests__/credential-security-invariants.test.ts +9 -16
  76. package/src/__tests__/credentials-cli.test.ts +49 -5
  77. package/src/__tests__/daemon-assistant-events.test.ts +4 -22
  78. package/src/__tests__/db-migration-rollback.test.ts +2 -2
  79. package/src/__tests__/deterministic-verification-control-plane.test.ts +19 -19
  80. package/src/__tests__/dictation-mode-detection.test.ts +1 -1
  81. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  82. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -6
  83. package/src/__tests__/email-cli.test.ts +12 -12
  84. package/src/__tests__/email-service-config-fallback.test.ts +1 -1
  85. package/src/__tests__/emit-signal-routing-intent.test.ts +3 -18
  86. package/src/__tests__/event-bus.test.ts +0 -1
  87. package/src/__tests__/followup-tools.test.ts +0 -2
  88. package/src/__tests__/gateway-client-managed-outbound.test.ts +6 -6
  89. package/src/__tests__/gateway-only-enforcement.test.ts +13 -77
  90. package/src/__tests__/gateway-only-guard.test.ts +5 -0
  91. package/src/__tests__/guardian-action-conversation-turn.test.ts +3 -3
  92. package/src/__tests__/guardian-action-followup-executor.test.ts +29 -94
  93. package/src/__tests__/guardian-action-followup-store.test.ts +2 -12
  94. package/src/__tests__/guardian-action-grant-mint-consume.test.ts +48 -194
  95. package/src/__tests__/guardian-action-late-reply.test.ts +12 -12
  96. package/src/__tests__/guardian-action-store.test.ts +2 -2
  97. package/src/__tests__/guardian-action-sweep.test.ts +5 -5
  98. package/src/__tests__/guardian-decision-primitive-canonical.test.ts +1 -3
  99. package/src/__tests__/guardian-dispatch.test.ts +5 -46
  100. package/src/__tests__/guardian-grant-minting.test.ts +5 -44
  101. package/src/__tests__/guardian-outbound-http.test.ts +95 -114
  102. package/src/__tests__/guardian-question-mode.test.ts +1 -4
  103. package/src/__tests__/guardian-routing-invariants.test.ts +5 -13
  104. package/src/__tests__/guardian-routing-state.test.ts +3 -3
  105. package/src/__tests__/guardian-verification-voice-binding.test.ts +64 -7
  106. package/src/__tests__/guardian-verify-setup-skill-regression.test.ts +2 -2
  107. package/src/__tests__/handle-user-message-secret-resume.test.ts +3 -5
  108. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +16 -34
  109. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  110. package/src/__tests__/headless-browser-navigate.test.ts +1 -1
  111. package/src/__tests__/headless-browser-read-tools.test.ts +1 -1
  112. package/src/__tests__/headless-browser-snapshot.test.ts +1 -1
  113. package/src/__tests__/heartbeat-service.test.ts +1 -1
  114. package/src/__tests__/home-base-bootstrap.test.ts +0 -2
  115. package/src/__tests__/host-shell-tool.test.ts +3 -12
  116. package/src/__tests__/inbound-invite-redemption.test.ts +2 -2
  117. package/src/__tests__/ingress-url-consistency.test.ts +0 -64
  118. package/src/__tests__/integration-status.test.ts +8 -8
  119. package/src/__tests__/intent-routing.test.ts +9 -13
  120. package/src/__tests__/invite-redemption-service.test.ts +4 -4
  121. package/src/__tests__/invite-routes-http.test.ts +10 -10
  122. package/src/__tests__/llm-usage-store.test.ts +45 -9
  123. package/src/__tests__/local-gateway-health.test.ts +209 -0
  124. package/src/__tests__/managed-avatar-client.test.ts +23 -12
  125. package/src/__tests__/managed-skill-lifecycle.test.ts +1 -2
  126. package/src/__tests__/managed-store.test.ts +29 -12
  127. package/src/__tests__/managed-twitter-guardrails.test.ts +353 -0
  128. package/src/__tests__/mcp-cli.test.ts +1 -1
  129. package/src/__tests__/mcp-health-check.test.ts +1 -1
  130. package/src/__tests__/media-generate-image.test.ts +1 -1
  131. package/src/__tests__/media-reuse-story.e2e.test.ts +1 -4
  132. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +9 -6
  133. package/src/__tests__/memory-regressions.test.ts +1 -166
  134. package/src/__tests__/messaging-send-tool.test.ts +8 -4
  135. package/src/__tests__/migration-export-http.test.ts +2 -2
  136. package/src/__tests__/migration-transport.test.ts +44 -0
  137. package/src/__tests__/non-member-access-request.test.ts +49 -36
  138. package/src/__tests__/notification-broadcaster.test.ts +15 -15
  139. package/src/__tests__/notification-decision-fallback.test.ts +2 -2
  140. package/src/__tests__/notification-decision-strategy.test.ts +4 -4
  141. package/src/__tests__/notification-deep-link.test.ts +3 -3
  142. package/src/__tests__/notification-guardian-path.test.ts +6 -44
  143. package/src/__tests__/notification-routing-intent.test.ts +11 -7
  144. package/src/__tests__/oauth-cli.test.ts +1 -1
  145. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -6
  146. package/src/__tests__/onboarding-template-contract.test.ts +2 -2
  147. package/src/__tests__/platform.test.ts +168 -5
  148. package/src/__tests__/playbook-execution.test.ts +0 -2
  149. package/src/__tests__/playbook-tools.test.ts +0 -2
  150. package/src/__tests__/pricing.test.ts +125 -0
  151. package/src/__tests__/provider-error-scenarios.test.ts +9 -3
  152. package/src/__tests__/recording-handler.test.ts +46 -80
  153. package/src/__tests__/recording-state-machine.test.ts +112 -183
  154. package/src/__tests__/registry.test.ts +1 -1
  155. package/src/__tests__/relay-server.test.ts +69 -71
  156. package/src/__tests__/reminder-store.test.ts +3 -3
  157. package/src/__tests__/request-file-tool.test.ts +2 -2
  158. package/src/__tests__/ride-shotgun-handler.test.ts +2 -33
  159. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -3
  160. package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
  161. package/src/__tests__/scaffold-managed-skill-tool.test.ts +4 -4
  162. package/src/__tests__/schedule-store.test.ts +13 -4
  163. package/src/__tests__/schedule-tools.test.ts +0 -2
  164. package/src/__tests__/scheduler-recurrence.test.ts +3 -4
  165. package/src/__tests__/scoped-approval-grants.test.ts +3 -5
  166. package/src/__tests__/scoped-grant-security-matrix.test.ts +6 -8
  167. package/src/__tests__/secret-prompt-log-hygiene.test.ts +1 -1
  168. package/src/__tests__/secret-response-routing.test.ts +1 -1
  169. package/src/__tests__/send-endpoint-busy.test.ts +1 -1
  170. package/src/__tests__/sequence-store.test.ts +0 -2
  171. package/src/__tests__/server-history-render.test.ts +2 -199
  172. package/src/__tests__/session-abort-tool-results.test.ts +9 -3
  173. package/src/__tests__/session-agent-loop.test.ts +107 -3
  174. package/src/__tests__/session-confirmation-signals.test.ts +10 -4
  175. package/src/__tests__/session-conflict-gate.test.ts +9 -3
  176. package/src/__tests__/session-init.benchmark.test.ts +22 -13
  177. package/src/__tests__/session-load-history-repair.test.ts +6 -3
  178. package/src/__tests__/session-pre-run-repair.test.ts +9 -3
  179. package/src/__tests__/session-profile-injection.test.ts +9 -3
  180. package/src/__tests__/session-provider-retry-repair.test.ts +10 -4
  181. package/src/__tests__/session-queue.test.ts +10 -4
  182. package/src/__tests__/session-runtime-assembly.test.ts +28 -18
  183. package/src/__tests__/session-skill-tools.test.ts +2 -3
  184. package/src/__tests__/session-slash-known.test.ts +11 -4
  185. package/src/__tests__/session-slash-queue.test.ts +11 -4
  186. package/src/__tests__/session-slash-unknown.test.ts +12 -4
  187. package/src/__tests__/session-surfaces-deselection.test.ts +2 -2
  188. package/src/__tests__/session-surfaces-task-progress.test.ts +3 -3
  189. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -1
  190. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -1
  191. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -1
  192. package/src/__tests__/session-usage.test.ts +180 -0
  193. package/src/__tests__/session-workspace-cache-state.test.ts +8 -2
  194. package/src/__tests__/session-workspace-injection.test.ts +8 -2
  195. package/src/__tests__/session-workspace-tool-tracking.test.ts +8 -2
  196. package/src/__tests__/skill-feature-flags-integration.test.ts +5 -11
  197. package/src/__tests__/skill-feature-flags.test.ts +1 -0
  198. package/src/__tests__/skill-include-graph.test.ts +1 -0
  199. package/src/__tests__/skill-load-feature-flag.test.ts +3 -9
  200. package/src/__tests__/skill-load-tool.test.ts +90 -12
  201. package/src/__tests__/skill-projection-feature-flag.test.ts +14 -15
  202. package/src/__tests__/skills-uninstall.test.ts +131 -0
  203. package/src/__tests__/skills.test.ts +32 -16
  204. package/src/__tests__/slack-block-formatting.test.ts +1 -1
  205. package/src/__tests__/slack-channel-config.test.ts +71 -12
  206. package/src/__tests__/slack-inbound-verification.test.ts +7 -7
  207. package/src/__tests__/slack-share-routes.test.ts +1 -1
  208. package/src/__tests__/slack-skill.test.ts +2 -2
  209. package/src/__tests__/slash-commands-catalog.test.ts +1 -0
  210. package/src/__tests__/slash-commands-resolver.test.ts +1 -0
  211. package/src/__tests__/starter-task-flow.test.ts +1 -1
  212. package/src/__tests__/subagent-manager-notify.test.ts +1 -1
  213. package/src/__tests__/subagent-tools.test.ts +2 -2
  214. package/src/__tests__/system-prompt.test.ts +4 -8
  215. package/src/__tests__/task-compiler.test.ts +0 -2
  216. package/src/__tests__/task-management-tools.test.ts +0 -2
  217. package/src/__tests__/task-runner.test.ts +0 -2
  218. package/src/__tests__/task-scheduler.test.ts +2 -2
  219. package/src/__tests__/telegram-bot-username-resolution.test.ts +46 -44
  220. package/src/__tests__/terminal-tools.test.ts +1 -11
  221. package/src/__tests__/thread-seed-composer.test.ts +3 -1
  222. package/src/__tests__/tool-approval-handler.test.ts +5 -7
  223. package/src/__tests__/tool-executor.test.ts +2 -2
  224. package/src/__tests__/tool-grant-request-escalation.test.ts +3 -5
  225. package/src/__tests__/tool-notification-listener.test.ts +1 -1
  226. package/src/__tests__/tool-profiling-listener.test.ts +1 -1
  227. package/src/__tests__/tool-trace-listener.test.ts +1 -2
  228. package/src/__tests__/trace-emitter.test.ts +1 -1
  229. package/src/__tests__/trust-context-guards.test.ts +1 -1
  230. package/src/__tests__/trust-store.test.ts +44 -395
  231. package/src/__tests__/trusted-contact-approval-notifier.test.ts +6 -8
  232. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +5 -7
  233. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +6 -6
  234. package/src/__tests__/trusted-contact-multichannel.test.ts +54 -47
  235. package/src/__tests__/trusted-contact-verification.test.ts +12 -12
  236. package/src/__tests__/twilio-config.test.ts +11 -2
  237. package/src/__tests__/twilio-provider.test.ts +6 -4
  238. package/src/__tests__/twilio-routes.test.ts +408 -86
  239. package/src/__tests__/twitter-platform-proxy-client.test.ts +450 -0
  240. package/src/__tests__/update-bulletin-format.test.ts +1 -1
  241. package/src/__tests__/update-bulletin-state.test.ts +1 -1
  242. package/src/__tests__/update-bulletin.test.ts +4 -8
  243. package/src/__tests__/update-template-contract.test.ts +1 -1
  244. package/src/__tests__/usage-cache-backfill-migration.test.ts +406 -0
  245. package/src/__tests__/usage-routes.test.ts +23 -5
  246. package/src/__tests__/user-reference.test.ts +1 -1
  247. package/src/__tests__/{guardian-control-plane-policy.test.ts → verification-control-plane-policy.test.ts} +142 -170
  248. package/src/__tests__/{guardian-verification-intent-routing.test.ts → verification-session-intent-routing.test.ts} +16 -16
  249. package/src/__tests__/view-image-tool.test.ts +0 -2
  250. package/src/__tests__/voice-ingress-preflight.test.ts +36 -0
  251. package/src/__tests__/voice-invite-redemption.test.ts +18 -18
  252. package/src/__tests__/voice-scoped-grant-consumer.test.ts +7 -7
  253. package/src/__tests__/voice-session-bridge.test.ts +14 -16
  254. package/src/__tests__/workspace-policy.test.ts +1 -1
  255. package/src/approvals/AGENTS.md +4 -4
  256. package/src/approvals/approval-primitive.ts +2 -2
  257. package/src/approvals/guardian-decision-primitive.ts +1 -1
  258. package/src/approvals/guardian-request-resolvers.ts +3 -4
  259. package/src/bundler/app-bundler.ts +29 -217
  260. package/src/bundler/app-compiler.ts +131 -103
  261. package/src/bundler/compiler-tools.ts +248 -0
  262. package/src/calls/active-call-lease.ts +207 -0
  263. package/src/calls/call-constants.ts +0 -7
  264. package/src/calls/call-controller.ts +1 -1
  265. package/src/calls/call-conversation-messages.ts +6 -6
  266. package/src/calls/call-domain.ts +73 -38
  267. package/src/calls/call-pointer-message-composer.ts +6 -6
  268. package/src/calls/call-pointer-messages.ts +14 -13
  269. package/src/calls/call-recovery.ts +2 -0
  270. package/src/calls/call-store.ts +21 -28
  271. package/src/calls/guardian-action-sweep.ts +6 -8
  272. package/src/calls/guardian-dispatch.ts +2 -6
  273. package/src/calls/relay-access-wait.ts +4 -4
  274. package/src/calls/relay-server.ts +69 -80
  275. package/src/calls/relay-setup-router.ts +16 -21
  276. package/src/calls/relay-verification.ts +27 -28
  277. package/src/calls/twilio-config.ts +28 -3
  278. package/src/calls/twilio-provider.ts +5 -5
  279. package/src/calls/twilio-rest.ts +26 -27
  280. package/src/calls/twilio-routes.ts +67 -54
  281. package/src/calls/types.ts +8 -8
  282. package/src/calls/voice-ingress-preflight.ts +110 -0
  283. package/src/calls/voice-session-bridge.ts +7 -7
  284. package/src/channels/config.ts +1 -10
  285. package/src/{config/channel-permission-profiles.ts → channels/permission-profiles.ts} +1 -1
  286. package/src/channels/types.ts +2 -13
  287. package/src/cli/__tests__/notifications.test.ts +1 -1
  288. package/src/{amazon → cli/commands/amazon}/client.ts +99 -42
  289. package/src/cli/{amazon.ts → commands/amazon/index.ts} +12 -17
  290. package/src/{amazon → cli/commands/amazon}/request-extractor.ts +39 -3
  291. package/src/cli/commands/amazon/session.ts +116 -0
  292. package/src/cli/{audit.ts → commands/audit.ts} +2 -4
  293. package/src/cli/{autonomy.ts → commands/autonomy.ts} +1 -3
  294. package/src/cli/commands/browser-relay.ts +520 -0
  295. package/src/cli/commands/channel-verification-sessions.ts +442 -0
  296. package/src/cli/{completions.ts → commands/completions.ts} +1 -3
  297. package/src/cli/{config.ts → commands/config.ts} +3 -5
  298. package/src/cli/{contacts.ts → commands/contacts.ts} +263 -16
  299. package/src/cli/{credentials.ts → commands/credentials.ts} +9 -10
  300. package/src/cli/{default-action.ts → commands/default-action.ts} +3 -3
  301. package/src/cli/{dev.ts → commands/dev.ts} +4 -6
  302. package/src/cli/{doctor.ts → commands/doctor.ts} +36 -60
  303. package/src/cli/{email.ts → commands/email.ts} +2 -2
  304. package/src/cli/{keys.ts → commands/keys.ts} +6 -6
  305. package/src/cli/{map.ts → commands/map.ts} +85 -93
  306. package/src/cli/{mcp.ts → commands/mcp.ts} +5 -7
  307. package/src/cli/{memory.ts → commands/memory.ts} +6 -7
  308. package/src/cli/{notifications.ts → commands/notifications.ts} +8 -10
  309. package/src/cli/{oauth.ts → commands/oauth.ts} +2 -2
  310. package/src/cli/commands/platform.ts +176 -0
  311. package/src/cli/{sequence.ts → commands/sequence.ts} +3 -3
  312. package/src/cli/{sessions.ts → commands/sessions.ts} +32 -52
  313. package/src/cli/commands/skills.ts +498 -0
  314. package/src/cli/{trust.ts → commands/trust.ts} +2 -4
  315. package/src/{__tests__/twitter-cli-error-shaping.test.ts → cli/commands/twitter/__tests__/cli-error-shaping.test.ts} +43 -2
  316. package/src/cli/commands/twitter/__tests__/cli-read-routing.test.ts +483 -0
  317. package/src/{__tests__/twitter-cli-routing.test.ts → cli/commands/twitter/__tests__/cli-routing.test.ts} +130 -4
  318. package/src/{__tests__/twitter-oauth-client.test.ts → cli/commands/twitter/__tests__/oauth-client.test.ts} +2 -2
  319. package/src/{twitter → cli/commands/twitter}/client.ts +17 -7
  320. package/src/cli/{twitter.ts → commands/twitter/index.ts} +322 -273
  321. package/src/cli/commands/twitter/router.ts +396 -0
  322. package/src/cli/commands/twitter/session.ts +121 -0
  323. package/src/cli/db.ts +1 -0
  324. package/src/cli/http-client.ts +87 -0
  325. package/src/cli/logger.ts +6 -0
  326. package/src/cli/main-screen.tsx +4 -3
  327. package/src/cli/output.ts +19 -0
  328. package/src/cli/program.ts +29 -27
  329. package/src/cli/reference.ts +27 -37
  330. package/src/cli.ts +452 -240
  331. package/src/config/assistant-feature-flags.ts +3 -15
  332. package/src/config/bundled-skills/_shared/CLI_RETRIEVAL_PATTERN.md +3 -6
  333. package/src/config/bundled-skills/agentmail/SKILL.md +4 -4
  334. package/src/config/bundled-skills/amazon/SKILL.md +15 -5
  335. package/src/config/bundled-skills/api-mapping/SKILL.md +4 -4
  336. package/src/config/bundled-skills/app-builder/SKILL.md +21 -6
  337. package/src/config/bundled-skills/browser/SKILL.md +4 -5
  338. package/src/config/bundled-skills/chatgpt-import/SKILL.md +4 -4
  339. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
  340. package/src/config/bundled-skills/claude-code/SKILL.md +4 -4
  341. package/src/config/bundled-skills/cli-discover/SKILL.md +4 -4
  342. package/src/config/bundled-skills/computer-use/SKILL.md +4 -4
  343. package/src/config/bundled-skills/contacts/SKILL.md +87 -229
  344. package/src/config/bundled-skills/deploy-fullstack-vercel/SKILL.md +4 -4
  345. package/src/config/bundled-skills/document/SKILL.md +4 -3
  346. package/src/config/bundled-skills/document-writer/SKILL.md +4 -4
  347. package/src/config/bundled-skills/doordash/SKILL.md +4 -11
  348. package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +8 -16
  349. package/src/config/bundled-skills/doordash/doordash-cli.ts +120 -86
  350. package/src/config/bundled-skills/doordash/lib/session.ts +1 -2
  351. package/src/config/bundled-skills/doordash/lib/shared/platform.ts +26 -9
  352. package/src/config/bundled-skills/elevenlabs-voice/SKILL.md +140 -0
  353. package/src/config/bundled-skills/email-setup/SKILL.md +4 -4
  354. package/src/config/bundled-skills/followups/SKILL.md +4 -3
  355. package/src/config/bundled-skills/frontend-design/SKILL.md +2 -0
  356. package/src/config/bundled-skills/google-calendar/SKILL.md +4 -4
  357. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +4 -6
  358. package/src/config/bundled-skills/guardian-verify-setup/SKILL.md +26 -41
  359. package/src/config/bundled-skills/image-studio/SKILL.md +4 -5
  360. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +1 -1
  361. package/src/config/bundled-skills/influencer/SKILL.md +19 -19
  362. package/src/{influencer → config/bundled-skills/influencer/scripts}/client.ts +73 -56
  363. package/src/config/bundled-skills/influencer/scripts/influencer.ts +267 -0
  364. package/src/config/bundled-skills/knowledge-graph/SKILL.md +4 -2
  365. package/src/config/bundled-skills/macos-automation/SKILL.md +4 -5
  366. package/src/config/bundled-skills/mcp-setup/SKILL.md +4 -4
  367. package/src/config/bundled-skills/media-processing/SKILL.md +3 -2
  368. package/src/config/bundled-skills/messaging/SKILL.md +6 -33
  369. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -5
  370. package/src/config/bundled-skills/notifications/SKILL.md +4 -4
  371. package/src/config/bundled-skills/notion/SKILL.md +4 -4
  372. package/src/config/bundled-skills/notion-oauth-setup/SKILL.md +4 -5
  373. package/src/config/bundled-skills/oauth-setup/SKILL.md +4 -5
  374. package/src/config/bundled-skills/phone-calls/SKILL.md +24 -458
  375. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +83 -0
  376. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +57 -0
  377. package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +67 -0
  378. package/src/config/bundled-skills/playbooks/SKILL.md +4 -3
  379. package/src/config/bundled-skills/public-ingress/SKILL.md +65 -14
  380. package/src/config/bundled-skills/reminder/SKILL.md +4 -3
  381. package/src/config/bundled-skills/restaurant-reservation/SKILL.md +4 -6
  382. package/src/config/bundled-skills/schedule/SKILL.md +4 -3
  383. package/src/config/bundled-skills/screen-recording/SKILL.md +4 -3
  384. package/src/config/bundled-skills/self-upgrade/SKILL.md +4 -4
  385. package/src/config/bundled-skills/skills-catalog/SKILL.md +4 -4
  386. package/src/config/bundled-skills/slack/SKILL.md +4 -8
  387. package/src/config/bundled-skills/slack/tools/slack-channel-permissions.ts +1 -1
  388. package/src/config/bundled-skills/slack-app-setup/SKILL.md +66 -88
  389. package/src/config/bundled-skills/slack-digest-setup/SKILL.md +4 -5
  390. package/src/config/bundled-skills/slack-oauth-setup/SKILL.md +4 -5
  391. package/src/config/bundled-skills/start-the-day/SKILL.md +4 -4
  392. package/src/config/bundled-skills/subagent/SKILL.md +4 -3
  393. package/src/config/bundled-skills/tasks/SKILL.md +4 -3
  394. package/src/config/bundled-skills/telegram-setup/SKILL.md +63 -112
  395. package/src/config/bundled-skills/time-based-actions/SKILL.md +4 -3
  396. package/src/config/bundled-skills/transcribe/SKILL.md +4 -3
  397. package/src/config/bundled-skills/twilio-setup/SKILL.md +23 -50
  398. package/src/config/bundled-skills/twitter/SKILL.md +56 -14
  399. package/src/config/bundled-skills/typescript-eval/SKILL.md +4 -4
  400. package/src/config/bundled-skills/vercel-token-setup/SKILL.md +4 -5
  401. package/src/config/bundled-skills/voice-setup/SKILL.md +19 -45
  402. package/src/config/bundled-skills/watcher/SKILL.md +4 -3
  403. package/src/config/env-registry.ts +1 -10
  404. package/src/config/feature-flag-registry.json +0 -16
  405. package/src/config/loader.ts +78 -38
  406. package/src/config/schema.ts +143 -106
  407. package/src/config/schemas/channels.ts +80 -0
  408. package/src/config/schemas/heartbeat.ts +51 -0
  409. package/src/config/schemas/inference.ts +136 -0
  410. package/src/config/schemas/ingress.ts +81 -0
  411. package/src/config/schemas/logging.ts +21 -0
  412. package/src/config/schemas/memory-lifecycle.ts +67 -0
  413. package/src/config/schemas/memory-processing.ts +215 -0
  414. package/src/config/schemas/memory-retrieval.ts +222 -0
  415. package/src/config/schemas/memory-storage.ts +83 -0
  416. package/src/config/schemas/memory.ts +58 -0
  417. package/src/config/schemas/platform.ts +64 -0
  418. package/src/config/schemas/security.ts +54 -0
  419. package/src/config/schemas/swarm.ts +50 -0
  420. package/src/config/schemas/timeouts.ts +47 -0
  421. package/src/config/{agent-schema.ts → schemas/workspace-git.ts} +0 -97
  422. package/src/config/skill-state.ts +3 -13
  423. package/src/config/skills.ts +233 -75
  424. package/src/config/types.ts +1 -20
  425. package/src/contacts/contact-store.ts +12 -49
  426. package/src/contacts/contacts-write.ts +1 -5
  427. package/src/contacts/index.ts +0 -2
  428. package/src/contacts/types.ts +0 -8
  429. package/src/context/window-manager.ts +73 -14
  430. package/src/daemon/assistant-attachments.ts +9 -0
  431. package/src/daemon/computer-use-session.ts +3 -3
  432. package/src/daemon/connection-policy.ts +6 -21
  433. package/src/daemon/context-overflow-policy.ts +1 -1
  434. package/src/daemon/daemon-control.ts +46 -54
  435. package/src/daemon/doordash-steps.ts +1 -1
  436. package/src/daemon/handlers/config-channels.ts +407 -71
  437. package/src/daemon/handlers/config-ingress.ts +17 -85
  438. package/src/daemon/handlers/config-model.ts +145 -123
  439. package/src/daemon/handlers/config-slack-channel.ts +43 -29
  440. package/src/daemon/handlers/config-telegram.ts +32 -27
  441. package/src/daemon/handlers/config-voice.ts +1 -4
  442. package/src/daemon/handlers/dictation.ts +11 -16
  443. package/src/daemon/handlers/identity.ts +5 -6
  444. package/src/daemon/handlers/pairing.ts +5 -13
  445. package/src/daemon/handlers/recording.ts +97 -199
  446. package/src/daemon/handlers/session-history.ts +110 -96
  447. package/src/daemon/handlers/session-user-message.ts +29 -57
  448. package/src/daemon/handlers/sessions.ts +240 -137
  449. package/src/daemon/handlers/shared.ts +62 -95
  450. package/src/daemon/handlers/skills.ts +492 -543
  451. package/src/daemon/lifecycle.ts +168 -55
  452. package/src/daemon/main.ts +1 -0
  453. package/src/daemon/{ipc-contract.ts → message-protocol.ts} +49 -49
  454. package/src/daemon/{ipc-contract → message-types}/computer-use.ts +0 -3
  455. package/src/daemon/{ipc-contract → message-types}/diagnostics.ts +0 -16
  456. package/src/daemon/{ipc-contract → message-types}/integrations.ts +29 -13
  457. package/src/daemon/{ipc-contract → message-types}/memory.ts +8 -0
  458. package/src/daemon/{ipc-contract → message-types}/notifications.ts +15 -1
  459. package/src/daemon/{ipc-contract → message-types}/sessions.ts +1 -0
  460. package/src/daemon/{ipc-contract → message-types}/shared.ts +0 -8
  461. package/src/daemon/{ipc-contract → message-types}/workspace.ts +2 -2
  462. package/src/daemon/providers-setup.ts +0 -5
  463. package/src/daemon/recording-executor.ts +0 -7
  464. package/src/daemon/ride-shotgun-handler.ts +9 -13
  465. package/src/daemon/server.ts +136 -510
  466. package/src/daemon/session-agent-loop-handlers.ts +22 -7
  467. package/src/daemon/session-agent-loop.ts +86 -24
  468. package/src/daemon/session-attachments.ts +1 -1
  469. package/src/daemon/session-error.ts +1 -1
  470. package/src/daemon/session-history.ts +20 -15
  471. package/src/daemon/session-lifecycle.ts +9 -7
  472. package/src/daemon/session-memory.ts +15 -1
  473. package/src/daemon/session-messaging.ts +10 -6
  474. package/src/daemon/session-notifiers.ts +10 -8
  475. package/src/daemon/session-process.ts +34 -25
  476. package/src/daemon/session-queue-manager.ts +1 -1
  477. package/src/daemon/session-runtime-assembly.ts +6 -25
  478. package/src/daemon/session-surfaces.ts +2 -2
  479. package/src/daemon/session-tool-setup.ts +1 -1
  480. package/src/daemon/session-usage.ts +119 -18
  481. package/src/daemon/session.ts +13 -9
  482. package/src/daemon/tool-side-effects.ts +6 -5
  483. package/src/daemon/trace-emitter.ts +1 -1
  484. package/src/daemon/{guardian-verification-intent.ts → verification-session-intent.ts} +16 -16
  485. package/src/daemon/watch-handler.ts +2 -5
  486. package/src/email/service.ts +8 -8
  487. package/src/events/domain-events.ts +0 -1
  488. package/src/events/tool-notification-listener.ts +1 -1
  489. package/src/followups/followup-store.ts +1 -2
  490. package/src/followups/types.ts +0 -6
  491. package/src/heartbeat/heartbeat-service.ts +1 -1
  492. package/src/inbound/platform-callback-registration.ts +1 -1
  493. package/src/inbound/public-ingress-urls.ts +0 -8
  494. package/src/index.ts +12 -0
  495. package/src/mcp/client.ts +1 -1
  496. package/src/mcp/manager.ts +1 -1
  497. package/src/memory/app-store.ts +1 -42
  498. package/src/memory/{guardian-verification.ts → channel-verification-sessions.ts} +110 -93
  499. package/src/memory/conversation-attention-store.ts +154 -0
  500. package/src/memory/conversation-bootstrap.ts +1 -1
  501. package/src/memory/conversation-crud.ts +53 -1
  502. package/src/memory/conversation-display-order-migration.ts +2 -3
  503. package/src/memory/conversation-queries.ts +1 -29
  504. package/src/memory/conversation-title-service.ts +26 -21
  505. package/src/memory/db-connection.ts +1 -8
  506. package/src/memory/db-init.ts +20 -0
  507. package/src/memory/delivery-crud.ts +4 -34
  508. package/src/memory/external-conversation-store.ts +1 -1
  509. package/src/memory/format-recall.ts +47 -0
  510. package/src/memory/guardian-action-store.ts +4 -5
  511. package/src/memory/guardian-rate-limits.ts +0 -3
  512. package/src/memory/invite-store.ts +1 -1
  513. package/src/memory/job-handlers/backfill.ts +9 -2
  514. package/src/memory/job-handlers/extraction.ts +2 -7
  515. package/src/memory/job-handlers/summarization.ts +1 -1
  516. package/src/memory/llm-usage-store.ts +11 -0
  517. package/src/memory/migrations/114-notifications.ts +12 -40
  518. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +357 -0
  519. package/src/memory/migrations/141-rename-verification-table.ts +55 -0
  520. package/src/memory/migrations/142-rename-verification-session-id-column.ts +32 -0
  521. package/src/memory/migrations/143-rename-guardian-verification-values.ts +48 -0
  522. package/src/memory/migrations/144-rename-voice-to-phone.ts +147 -0
  523. package/src/memory/migrations/index.ts +5 -0
  524. package/src/memory/migrations/registry.ts +30 -0
  525. package/src/memory/qdrant-circuit-breaker.ts +5 -0
  526. package/src/memory/retriever.test.ts +707 -0
  527. package/src/memory/retriever.ts +120 -116
  528. package/src/memory/schema/calls.ts +3 -7
  529. package/src/memory/schema/guardian.ts +2 -2
  530. package/src/memory/search/lexical.ts +4 -1
  531. package/src/memory/search/query-expansion.test.ts +70 -0
  532. package/src/memory/search/query-expansion.ts +118 -0
  533. package/src/memory/search/types.ts +18 -17
  534. package/src/messaging/providers/telegram-bot/adapter.ts +1 -1
  535. package/src/messaging/providers/whatsapp/adapter.ts +1 -4
  536. package/src/messaging/registry.ts +0 -1
  537. package/src/notifications/README.md +13 -22
  538. package/src/notifications/adapters/macos.ts +1 -1
  539. package/src/notifications/conversation-pairing.ts +2 -2
  540. package/src/notifications/copy-composer.ts +2 -2
  541. package/src/notifications/decision-engine.ts +1 -10
  542. package/src/notifications/destination-resolver.ts +2 -3
  543. package/src/notifications/emit-signal.ts +2 -8
  544. package/src/notifications/guardian-question-mode.ts +5 -8
  545. package/src/notifications/signal.ts +1 -2
  546. package/src/notifications/types.ts +1 -1
  547. package/src/oauth/token-persistence.ts +25 -1
  548. package/src/permissions/checker.ts +4 -29
  549. package/src/permissions/defaults.ts +6 -6
  550. package/src/permissions/prompter.ts +1 -1
  551. package/src/permissions/secret-prompter.ts +1 -1
  552. package/src/permissions/shell-identity.ts +1 -1
  553. package/src/permissions/trust-store.ts +13 -76
  554. package/src/permissions/workspace-policy.ts +1 -1
  555. package/src/{config → prompts}/computer-use-prompt.ts +1 -1
  556. package/src/{config → prompts}/system-prompt.ts +40 -21
  557. package/src/runtime/AGENTS.md +6 -8
  558. package/src/runtime/access-request-helper.ts +36 -55
  559. package/src/runtime/actor-trust-resolver.ts +1 -24
  560. package/src/runtime/approval-message-composer.ts +6 -2
  561. package/src/runtime/assistant-event.ts +1 -1
  562. package/src/runtime/auth/__tests__/ipc-auth-context.test.ts +1 -1
  563. package/src/runtime/auth/__tests__/subject.test.ts +32 -0
  564. package/src/runtime/auth/route-policy.ts +140 -24
  565. package/src/runtime/auth/subject.ts +9 -0
  566. package/src/runtime/auth/token-service.ts +11 -0
  567. package/src/runtime/auth/types.ts +1 -1
  568. package/src/runtime/channel-approval-types.ts +1 -1
  569. package/src/runtime/channel-approvals.ts +1 -1
  570. package/src/runtime/channel-invite-transport.ts +0 -2
  571. package/src/runtime/channel-invite-transports/slack.ts +5 -19
  572. package/src/runtime/channel-invite-transports/telegram.ts +17 -34
  573. package/src/runtime/channel-invite-transports/voice.ts +1 -1
  574. package/src/runtime/channel-readiness-service.ts +24 -159
  575. package/src/runtime/channel-readiness-types.ts +5 -1
  576. package/src/runtime/channel-reply-delivery.ts +43 -3
  577. package/src/runtime/channel-retry-sweep.ts +14 -22
  578. package/src/runtime/{channel-guardian-service.ts → channel-verification-service.ts} +50 -53
  579. package/src/runtime/confirmation-request-guardian-bridge.ts +2 -3
  580. package/src/runtime/gateway-client.ts +12 -15
  581. package/src/runtime/guardian-action-followup-executor.ts +8 -73
  582. package/src/runtime/guardian-action-grant-minter.ts +45 -61
  583. package/src/runtime/guardian-action-message-composer.ts +4 -4
  584. package/src/runtime/guardian-reply-router.ts +3 -3
  585. package/src/runtime/http-server.ts +133 -24
  586. package/src/runtime/http-types.ts +34 -1
  587. package/src/runtime/invite-instruction-generator.ts +1 -3
  588. package/src/runtime/invite-redemption-service.ts +5 -5
  589. package/src/runtime/invite-service.ts +7 -7
  590. package/src/runtime/local-actor-identity.ts +28 -2
  591. package/src/runtime/local-gateway-health.ts +275 -0
  592. package/src/runtime/middleware/twilio-validation.ts +3 -3
  593. package/src/runtime/migrations/migration-transport.ts +18 -3
  594. package/src/runtime/migrations/rebind-secrets-screen.ts +2 -2
  595. package/src/runtime/nl-approval-parser.ts +2 -3
  596. package/src/runtime/routes/access-request-decision.ts +2 -2
  597. package/src/runtime/routes/app-management-routes.ts +921 -0
  598. package/src/runtime/routes/approval-routes.ts +76 -7
  599. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +38 -203
  600. package/src/runtime/routes/channel-delivery-routes.ts +5 -4
  601. package/src/runtime/routes/channel-route-shared.ts +1 -3
  602. package/src/runtime/routes/channel-routes.ts +1 -4
  603. package/src/runtime/routes/channel-verification-routes.ts +257 -0
  604. package/src/runtime/routes/computer-use-routes.ts +595 -0
  605. package/src/runtime/routes/contact-routes.ts +1 -317
  606. package/src/runtime/routes/conversation-attention-routes.ts +6 -5
  607. package/src/runtime/routes/conversation-routes.ts +11 -18
  608. package/src/runtime/routes/debug-routes.ts +1 -1
  609. package/src/runtime/routes/diagnostics-routes.ts +813 -0
  610. package/src/runtime/routes/documents-routes.ts +227 -0
  611. package/src/runtime/routes/guardian-approval-interception.ts +25 -48
  612. package/src/runtime/routes/guardian-bootstrap-routes.ts +3 -3
  613. package/src/runtime/routes/guardian-expiry-sweep.ts +2 -2
  614. package/src/runtime/routes/guardian-refresh-routes.ts +11 -6
  615. package/src/runtime/routes/inbound-conversation.ts +3 -10
  616. package/src/runtime/routes/inbound-message-handler.ts +7 -6
  617. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +22 -22
  618. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +44 -0
  619. package/src/runtime/routes/inbound-stages/background-dispatch.ts +140 -22
  620. package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +4 -4
  621. package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -5
  622. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +3 -3
  623. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -4
  624. package/src/runtime/routes/inbound-stages/verification-intercept.ts +13 -14
  625. package/src/runtime/routes/integrations/slack/channel.ts +72 -0
  626. package/src/runtime/routes/{slack-share-routes.ts → integrations/slack/share.ts} +9 -9
  627. package/src/runtime/routes/integrations/telegram.ts +111 -0
  628. package/src/runtime/routes/integrations/twilio.ts +451 -0
  629. package/src/runtime/routes/invite-routes.ts +2 -2
  630. package/src/runtime/routes/pairing-routes.ts +1 -1
  631. package/src/runtime/routes/recording-routes.ts +332 -0
  632. package/src/{daemon/handlers/config-scheduling.ts → runtime/routes/schedule-routes.ts} +91 -106
  633. package/src/runtime/routes/session-management-routes.ts +167 -0
  634. package/src/runtime/routes/session-query-routes.ts +204 -0
  635. package/src/runtime/routes/settings-routes.ts +977 -0
  636. package/src/runtime/routes/skills-routes.ts +266 -0
  637. package/src/runtime/routes/subagents-routes.ts +246 -0
  638. package/src/runtime/routes/surface-action-routes.ts +100 -10
  639. package/src/runtime/routes/surface-content-routes.ts +1 -1
  640. package/src/runtime/routes/work-items-routes.ts +809 -0
  641. package/src/runtime/routes/workspace-routes.test.ts +778 -0
  642. package/src/runtime/routes/workspace-routes.ts +410 -0
  643. package/src/runtime/routes/workspace-utils.ts +88 -0
  644. package/src/runtime/telegram-streaming-delivery.test.ts +597 -0
  645. package/src/runtime/telegram-streaming-delivery.ts +380 -0
  646. package/src/runtime/tool-grant-request-helper.ts +1 -2
  647. package/src/runtime/trust-context-resolver.ts +0 -1
  648. package/src/runtime/{guardian-outbound-actions.ts → verification-outbound-actions.ts} +23 -188
  649. package/src/runtime/verification-rate-limiter.ts +2 -2
  650. package/src/runtime/{guardian-verification-templates.ts → verification-templates.ts} +2 -28
  651. package/src/schedule/integration-status.ts +2 -2
  652. package/src/schedule/schedule-store.ts +7 -9
  653. package/src/sequence/engine.ts +1 -1
  654. package/src/skills/active-skill-tools.ts +0 -8
  655. package/src/skills/clawhub.ts +1 -10
  656. package/src/skills/managed-store.ts +14 -4
  657. package/src/skills/slash-commands.ts +1 -1
  658. package/src/subagent/manager.ts +1 -1
  659. package/src/subagent/types.ts +1 -1
  660. package/src/tasks/SPEC.md +10 -10
  661. package/src/tasks/task-scheduler.ts +1 -1
  662. package/src/telegram/bot-username.ts +13 -0
  663. package/src/tools/assets/materialize.ts +1 -1
  664. package/src/tools/assets/search.ts +1 -1
  665. package/src/tools/browser/browser-execution.ts +2 -2
  666. package/src/tools/browser/browser-manager.ts +88 -11
  667. package/src/tools/browser/browser-screencast.ts +1 -1
  668. package/src/tools/browser/headless-browser.ts +0 -17
  669. package/src/tools/browser/jit-auth.ts +1 -1
  670. package/src/tools/browser/recording-store.ts +19 -1
  671. package/src/tools/browser/runtime-check.ts +4 -2
  672. package/src/tools/calls/call-start.ts +3 -3
  673. package/src/tools/credentials/metadata-store.ts +0 -13
  674. package/src/tools/credentials/vault.ts +7 -31
  675. package/src/tools/followups/followup_create.ts +0 -8
  676. package/src/tools/mcp/mcp-tool-factory.ts +1 -1
  677. package/src/tools/memory/definitions.ts +32 -10
  678. package/src/tools/memory/handlers.test.ts +573 -0
  679. package/src/tools/memory/handlers.ts +222 -65
  680. package/src/tools/memory/register.ts +53 -24
  681. package/src/tools/network/script-proxy/session-manager.ts +1 -12
  682. package/src/tools/schedule/update.ts +0 -8
  683. package/src/tools/skills/load.ts +3 -3
  684. package/src/tools/subagent/read.ts +1 -1
  685. package/src/tools/system/voice-config.ts +2 -14
  686. package/src/tools/terminal/safe-env.ts +5 -18
  687. package/src/tools/tool-approval-handler.ts +4 -4
  688. package/src/tools/tool-manifest.ts +4 -2
  689. package/src/tools/types.ts +1 -1
  690. package/src/tools/{guardian-control-plane-policy.ts → verification-control-plane-policy.ts} +37 -39
  691. package/src/twitter/platform-proxy-client.ts +405 -0
  692. package/src/usage/types.ts +21 -0
  693. package/src/util/canonicalize-identity.ts +2 -6
  694. package/src/util/cookie-session.ts +35 -51
  695. package/src/util/platform.ts +93 -86
  696. package/src/util/pricing.ts +180 -43
  697. package/src/work-items/work-item-runner.ts +1 -1
  698. package/scripts/ipc/check-contract-inventory.ts +0 -107
  699. package/scripts/ipc/check-swift-decoder-drift.ts +0 -184
  700. package/scripts/ipc/generate-swift.ts +0 -528
  701. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -3043
  702. package/src/__tests__/app-migration.test.ts +0 -148
  703. package/src/__tests__/config-loader-migration.test.ts +0 -85
  704. package/src/__tests__/daemon-lifecycle.test.ts +0 -715
  705. package/src/__tests__/daemon-server-session-init.test.ts +0 -864
  706. package/src/__tests__/guardian-actions-endpoint.test.ts +0 -1452
  707. package/src/__tests__/handlers-add-trust-rule-metadata.test.ts +0 -228
  708. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -397
  709. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -218
  710. package/src/__tests__/handlers-slack-config.test.ts +0 -140
  711. package/src/__tests__/handlers-telegram-config.test.ts +0 -1317
  712. package/src/__tests__/handlers-twitter-config.test.ts +0 -1145
  713. package/src/__tests__/ingress-reconcile.test.ts +0 -606
  714. package/src/__tests__/integrations-cli.test.ts +0 -232
  715. package/src/__tests__/ipc-blob-store.test.ts +0 -329
  716. package/src/__tests__/ipc-contract-inventory.test.ts +0 -69
  717. package/src/__tests__/ipc-contract.test.ts +0 -76
  718. package/src/__tests__/ipc-protocol.test.ts +0 -120
  719. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -250
  720. package/src/__tests__/ipc-snapshot.test.ts +0 -2197
  721. package/src/__tests__/ipc-validate.test.ts +0 -471
  722. package/src/__tests__/migration-cli-flows.test.ts +0 -186
  723. package/src/__tests__/migration-ordering.test.ts +0 -267
  724. package/src/__tests__/oauth-connect-handler.test.ts +0 -361
  725. package/src/__tests__/platform-move-helper.test.ts +0 -108
  726. package/src/__tests__/platform-socket-path.test.ts +0 -52
  727. package/src/__tests__/platform-workspace-migration.test.ts +0 -1051
  728. package/src/__tests__/recording-intent-handler.test.ts +0 -1155
  729. package/src/__tests__/script-proxy-profile-template-fallback.test.ts +0 -127
  730. package/src/__tests__/sms-messaging-provider.test.ts +0 -156
  731. package/src/__tests__/tool-permission-simulate-handler.test.ts +0 -367
  732. package/src/__tests__/twitter-auth-handler.test.ts +0 -561
  733. package/src/__tests__/work-item-output.test.ts +0 -150
  734. package/src/amazon/session.ts +0 -58
  735. package/src/cli/channels.ts +0 -51
  736. package/src/cli/influencer.ts +0 -319
  737. package/src/cli/integrations.ts +0 -372
  738. package/src/cli/ipc-client.ts +0 -88
  739. package/src/config/bundled-skills/configure-settings/SKILL.md +0 -86
  740. package/src/config/bundled-skills/doordash/lib/shared/ipc.ts +0 -32
  741. package/src/config/bundled-skills/sms-setup/SKILL.md +0 -210
  742. package/src/config/core-schema.ts +0 -434
  743. package/src/config/memory-schema.ts +0 -617
  744. package/src/daemon/auth-manager.ts +0 -106
  745. package/src/daemon/handlers/apps.ts +0 -758
  746. package/src/daemon/handlers/avatar.ts +0 -73
  747. package/src/daemon/handlers/browser.ts +0 -3
  748. package/src/daemon/handlers/computer-use.ts +0 -231
  749. package/src/daemon/handlers/config-dispatch.ts +0 -29
  750. package/src/daemon/handlers/config-heartbeat.ts +0 -299
  751. package/src/daemon/handlers/config-inbox.ts +0 -457
  752. package/src/daemon/handlers/config-integrations.ts +0 -409
  753. package/src/daemon/handlers/config-platform.ts +0 -77
  754. package/src/daemon/handlers/config-slack.ts +0 -41
  755. package/src/daemon/handlers/config-tools.ts +0 -226
  756. package/src/daemon/handlers/config-trust.ts +0 -135
  757. package/src/daemon/handlers/config.ts +0 -64
  758. package/src/daemon/handlers/contacts.ts +0 -193
  759. package/src/daemon/handlers/diagnostics.ts +0 -382
  760. package/src/daemon/handlers/documents.ts +0 -188
  761. package/src/daemon/handlers/guardian-actions.ts +0 -82
  762. package/src/daemon/handlers/home-base.ts +0 -82
  763. package/src/daemon/handlers/index.ts +0 -222
  764. package/src/daemon/handlers/misc.ts +0 -1139
  765. package/src/daemon/handlers/navigate-settings.ts +0 -29
  766. package/src/daemon/handlers/oauth-connect.ts +0 -202
  767. package/src/daemon/handlers/open-bundle-handler.ts +0 -88
  768. package/src/daemon/handlers/publish.ts +0 -176
  769. package/src/daemon/handlers/signing.ts +0 -56
  770. package/src/daemon/handlers/subagents.ts +0 -286
  771. package/src/daemon/handlers/twitter-auth.ts +0 -220
  772. package/src/daemon/handlers/work-items.ts +0 -796
  773. package/src/daemon/handlers/workspace-files.ts +0 -84
  774. package/src/daemon/handlers.ts +0 -16
  775. package/src/daemon/ipc-blob-store.ts +0 -246
  776. package/src/daemon/ipc-contract-inventory.json +0 -348
  777. package/src/daemon/ipc-contract-inventory.ts +0 -202
  778. package/src/daemon/ipc-handler.ts +0 -120
  779. package/src/daemon/ipc-protocol.ts +0 -85
  780. package/src/daemon/ipc-validate.ts +0 -254
  781. package/src/memory/app-migration.ts +0 -114
  782. package/src/memory/channel-delivery-store.ts +0 -40
  783. package/src/memory/channel-guardian-store.ts +0 -83
  784. package/src/memory/conversation-store.ts +0 -102
  785. package/src/memory/schema-migration.ts +0 -38
  786. package/src/messaging/providers/sms/adapter.ts +0 -232
  787. package/src/messaging/providers/sms/client.ts +0 -93
  788. package/src/messaging/providers/sms/types.ts +0 -7
  789. package/src/migrations/config-merge.ts +0 -62
  790. package/src/migrations/data-layout.ts +0 -89
  791. package/src/migrations/data-merge.ts +0 -44
  792. package/src/migrations/hooks-merge.ts +0 -118
  793. package/src/migrations/index.ts +0 -6
  794. package/src/migrations/log.ts +0 -28
  795. package/src/migrations/skills-merge.ts +0 -44
  796. package/src/migrations/workspace-layout.ts +0 -94
  797. package/src/notifications/adapters/sms.ts +0 -94
  798. package/src/runtime/channel-approval-parser.ts +0 -123
  799. package/src/runtime/channel-invite-transports/sms.ts +0 -53
  800. package/src/runtime/routes/approval-strategies/guardian-legacy-fallback-strategy.ts +0 -82
  801. package/src/runtime/routes/integration-routes.ts +0 -381
  802. package/src/runtime/routes/twilio-routes.ts +0 -1251
  803. package/src/twitter/router.ts +0 -131
  804. package/src/twitter/session.ts +0 -54
  805. package/src/watcher/providers/slack.ts +0 -282
  806. /package/src/{amazon → cli/commands/amazon}/cart.ts +0 -0
  807. /package/src/{amazon → cli/commands/amazon}/checkout.ts +0 -0
  808. /package/src/{amazon → cli/commands/amazon}/product-details.ts +0 -0
  809. /package/src/{amazon → cli/commands/amazon}/search.ts +0 -0
  810. /package/src/{twitter → cli/commands/twitter}/oauth-client.ts +0 -0
  811. /package/src/config/{calls-schema.ts → schemas/calls.ts} +0 -0
  812. /package/src/config/{elevenlabs-schema.ts → schemas/elevenlabs.ts} +0 -0
  813. /package/src/config/{mcp-schema.ts → schemas/mcp.ts} +0 -0
  814. /package/src/config/{notifications-schema.ts → schemas/notifications.ts} +0 -0
  815. /package/src/config/{sandbox-schema.ts → schemas/sandbox.ts} +0 -0
  816. /package/src/config/{skills-schema.ts → schemas/skills.ts} +0 -0
  817. /package/src/daemon/{ipc-contract → message-types}/apps.ts +0 -0
  818. /package/src/daemon/{ipc-contract → message-types}/browser.ts +0 -0
  819. /package/src/daemon/{ipc-contract → message-types}/contacts.ts +0 -0
  820. /package/src/daemon/{ipc-contract → message-types}/documents.ts +0 -0
  821. /package/src/daemon/{ipc-contract → message-types}/guardian-actions.ts +0 -0
  822. /package/src/daemon/{ipc-contract → message-types}/inbox.ts +0 -0
  823. /package/src/daemon/{ipc-contract → message-types}/messages.ts +0 -0
  824. /package/src/daemon/{ipc-contract → message-types}/pairing.ts +0 -0
  825. /package/src/daemon/{ipc-contract → message-types}/schedules.ts +0 -0
  826. /package/src/daemon/{ipc-contract → message-types}/settings.ts +0 -0
  827. /package/src/daemon/{ipc-contract → message-types}/skills.ts +0 -0
  828. /package/src/daemon/{ipc-contract → message-types}/subagents.ts +0 -0
  829. /package/src/daemon/{ipc-contract → message-types}/surfaces.ts +0 -0
  830. /package/src/daemon/{ipc-contract → message-types}/trust.ts +0 -0
  831. /package/src/daemon/{ipc-contract → message-types}/work-items.ts +0 -0
  832. /package/src/{cli/email-guardrails.ts → email/guardrails.ts} +0 -0
  833. /package/src/{config → prompts}/__tests__/build-cli-reference-section.test.ts +0 -0
  834. /package/src/{config → prompts}/templates/BOOTSTRAP.md +0 -0
  835. /package/src/{config → prompts}/templates/IDENTITY.md +0 -0
  836. /package/src/{config → prompts}/templates/SOUL.md +0 -0
  837. /package/src/{config → prompts}/templates/UPDATES.md +0 -0
  838. /package/src/{config → prompts}/templates/USER.md +0 -0
  839. /package/src/{config → prompts}/update-bulletin-format.ts +0 -0
  840. /package/src/{config → prompts}/update-bulletin-state.ts +0 -0
  841. /package/src/{config → prompts}/update-bulletin-template-path.ts +0 -0
  842. /package/src/{config → prompts}/update-bulletin.ts +0 -0
  843. /package/src/{config → prompts}/user-reference.ts +0 -0
@@ -1,1251 +0,0 @@
1
- /**
2
- * Route handlers for Twilio integration control-plane endpoints.
3
- *
4
- * GET /v1/integrations/twilio/config — get current config status
5
- * POST /v1/integrations/twilio/credentials — set Twilio credentials
6
- * DELETE /v1/integrations/twilio/credentials — clear Twilio credentials
7
- * GET /v1/integrations/twilio/numbers — list account phone numbers
8
- * POST /v1/integrations/twilio/numbers/provision — provision a new phone number
9
- * POST /v1/integrations/twilio/numbers/assign — assign an existing number
10
- * POST /v1/integrations/twilio/numbers/release — release a phone number
11
- * GET /v1/integrations/twilio/sms/compliance — get SMS compliance status
12
- * POST /v1/integrations/twilio/sms/compliance/tollfree — submit toll-free verification
13
- * PATCH /v1/integrations/twilio/sms/compliance/tollfree/:sid — update toll-free verification
14
- * DELETE /v1/integrations/twilio/sms/compliance/tollfree/:sid — delete toll-free verification
15
- * POST /v1/integrations/twilio/sms/test — send a test SMS
16
- * POST /v1/integrations/twilio/sms/doctor — run SMS diagnostics
17
- */
18
-
19
- import {
20
- deleteTollFreeVerification,
21
- fetchMessageStatus,
22
- getPhoneNumberSid,
23
- getTollFreeVerificationBySid,
24
- getTollFreeVerificationStatus,
25
- getTwilioCredentials,
26
- hasTwilioCredentials,
27
- listIncomingPhoneNumbers,
28
- provisionPhoneNumber,
29
- releasePhoneNumber,
30
- searchAvailableNumbers,
31
- submitTollFreeVerification,
32
- type TollFreeVerificationSubmitParams,
33
- updateTollFreeVerification,
34
- } from "../../calls/twilio-rest.js";
35
- import { getGatewayInternalBaseUrl } from "../../config/env.js";
36
- import { loadRawConfig, saveRawConfig } from "../../config/loader.js";
37
- import { getReadinessService } from "../../daemon/handlers/config-channels.js";
38
- import { syncTwilioWebhooks } from "../../daemon/handlers/config-ingress.js";
39
- import type { IngressConfig } from "../../inbound/public-ingress-urls.js";
40
- import {
41
- deleteSecureKeyAsync,
42
- getSecureKey,
43
- setSecureKeyAsync,
44
- } from "../../security/secure-keys.js";
45
- import {
46
- deleteCredentialMetadata,
47
- upsertCredentialMetadata,
48
- } from "../../tools/credentials/metadata-store.js";
49
- import { mintDaemonDeliveryToken } from "../auth/token-service.js";
50
- import type { RouteDefinition } from "../http-router.js";
51
-
52
- // ---------------------------------------------------------------------------
53
- // Shared helpers
54
- // ---------------------------------------------------------------------------
55
-
56
- /** In-memory store for the last SMS send test result. Shared between sms_send_test and sms_doctor. */
57
- let _lastTestResult:
58
- | {
59
- messageSid: string;
60
- to: string;
61
- initialStatus: string;
62
- finalStatus: string;
63
- errorCode?: string;
64
- errorMessage?: string;
65
- timestamp: number;
66
- }
67
- | undefined;
68
-
69
- function mapTwilioErrorRemediation(
70
- errorCode: string | undefined,
71
- ): string | undefined {
72
- if (!errorCode) return undefined;
73
- const map: Record<string, string> = {
74
- "30003":
75
- "Unreachable destination. The handset may be off or out of service.",
76
- "30004": "Message blocked by carrier or recipient.",
77
- "30005": "Unknown destination phone number. Verify the number is valid.",
78
- "30006":
79
- "Landline or unreachable carrier. SMS cannot be delivered to this number.",
80
- "30007":
81
- "Message flagged as spam by carrier. Adjust content or register for A2P.",
82
- "30008": "Unknown error from the carrier network.",
83
- "21610":
84
- "Recipient has opted out (STOP). Cannot send until they opt back in.",
85
- };
86
- return map[errorCode];
87
- }
88
-
89
- const TWILIO_USE_CASE_ALIASES: Record<string, string> = {
90
- ACCOUNT_NOTIFICATION: "ACCOUNT_NOTIFICATIONS",
91
- DELIVERY_NOTIFICATION: "DELIVERY_NOTIFICATIONS",
92
- FRAUD_ALERT: "FRAUD_ALERT_MESSAGING",
93
- POLLING_AND_VOTING: "POLLING_AND_VOTING_NON_POLITICAL",
94
- };
95
-
96
- const TWILIO_VALID_USE_CASE_CATEGORIES = [
97
- "TWO_FACTOR_AUTHENTICATION",
98
- "ACCOUNT_NOTIFICATIONS",
99
- "CUSTOMER_CARE",
100
- "CHARITY_NONPROFIT",
101
- "DELIVERY_NOTIFICATIONS",
102
- "FRAUD_ALERT_MESSAGING",
103
- "EVENTS",
104
- "HIGHER_EDUCATION",
105
- "K12",
106
- "MARKETING",
107
- "POLLING_AND_VOTING_NON_POLITICAL",
108
- "POLITICAL_ELECTION_CAMPAIGNS",
109
- "PUBLIC_SERVICE_ANNOUNCEMENT",
110
- "SECURITY_ALERT",
111
- ] as const;
112
-
113
- function normalizeUseCaseCategories(rawCategories: string[]): string[] {
114
- const normalized = rawCategories.map(
115
- (value) => TWILIO_USE_CASE_ALIASES[value] ?? value,
116
- );
117
- return Array.from(new Set(normalized));
118
- }
119
-
120
- /** Helper to clear stale assistant phone number mappings. */
121
- function pruneAssistantPhoneNumbers(
122
- sms: Record<string, unknown>,
123
- keepNumber: string,
124
- mode: "keep" | "remove",
125
- ): void {
126
- const mappings = sms.assistantPhoneNumbers as
127
- | Record<string, string>
128
- | undefined;
129
- if (mappings && typeof mappings === "object") {
130
- for (const [key, value] of Object.entries(mappings)) {
131
- const shouldDelete =
132
- mode === "keep" ? value !== keepNumber : value === keepNumber;
133
- if (shouldDelete) {
134
- delete mappings[key];
135
- }
136
- }
137
- if (Object.keys(mappings).length === 0) {
138
- delete sms.assistantPhoneNumbers;
139
- }
140
- }
141
- }
142
-
143
- // ---------------------------------------------------------------------------
144
- // Route handlers
145
- // ---------------------------------------------------------------------------
146
-
147
- /**
148
- * GET /v1/integrations/twilio/config
149
- */
150
- export function handleGetTwilioConfig(): Response {
151
- const hasCredentials = hasTwilioCredentials();
152
- const accountSid = hasCredentials
153
- ? getTwilioCredentials().accountSid
154
- : undefined;
155
- const raw = loadRawConfig();
156
- const sms = (raw?.sms ?? {}) as Record<string, unknown>;
157
- const phoneNumber = (sms.phoneNumber as string) ?? "";
158
-
159
- return Response.json({
160
- success: true,
161
- hasCredentials,
162
- accountSid: accountSid || undefined,
163
- phoneNumber: phoneNumber || undefined,
164
- });
165
- }
166
-
167
- /**
168
- * POST /v1/integrations/twilio/credentials
169
- *
170
- * Body: { accountSid: string, authToken: string }
171
- */
172
- export async function handleSetTwilioCredentials(
173
- req: Request,
174
- ): Promise<Response> {
175
- const body = (await req.json().catch(() => ({}))) as {
176
- accountSid?: string;
177
- authToken?: string;
178
- };
179
-
180
- if (!body.accountSid || !body.authToken) {
181
- return Response.json(
182
- {
183
- success: false,
184
- hasCredentials: hasTwilioCredentials(),
185
- error: "accountSid and authToken are required",
186
- },
187
- { status: 400 },
188
- );
189
- }
190
-
191
- // Validate credentials against Twilio API
192
- const authHeader =
193
- "Basic " +
194
- Buffer.from(`${body.accountSid}:${body.authToken}`).toString("base64");
195
- try {
196
- const res = await fetch(
197
- `https://api.twilio.com/2010-04-01/Accounts/${body.accountSid}.json`,
198
- { method: "GET", headers: { Authorization: authHeader } },
199
- );
200
- if (!res.ok) {
201
- const errBody = await res.text();
202
- return Response.json({
203
- success: false,
204
- hasCredentials: hasTwilioCredentials(),
205
- error: `Twilio API validation failed (${res.status}): ${errBody}`,
206
- });
207
- }
208
- } catch (err) {
209
- const message = err instanceof Error ? err.message : String(err);
210
- return Response.json({
211
- success: false,
212
- hasCredentials: hasTwilioCredentials(),
213
- error: `Failed to validate Twilio credentials: ${message}`,
214
- });
215
- }
216
-
217
- // Store credentials securely (async — writes broker + encrypted store)
218
- const sidStored = await setSecureKeyAsync(
219
- "credential:twilio:account_sid",
220
- body.accountSid,
221
- );
222
- if (!sidStored) {
223
- return Response.json({
224
- success: false,
225
- hasCredentials: false,
226
- error: "Failed to store Account SID in secure storage",
227
- });
228
- }
229
-
230
- const tokenStored = await setSecureKeyAsync(
231
- "credential:twilio:auth_token",
232
- body.authToken,
233
- );
234
- if (!tokenStored) {
235
- await deleteSecureKeyAsync("credential:twilio:account_sid");
236
- return Response.json({
237
- success: false,
238
- hasCredentials: false,
239
- error: "Failed to store Auth Token in secure storage",
240
- });
241
- }
242
-
243
- const raw = loadRawConfig();
244
- const twilio = (raw?.twilio ?? {}) as Record<string, unknown>;
245
- twilio.accountSid = body.accountSid;
246
- saveRawConfig({ ...raw, twilio });
247
-
248
- upsertCredentialMetadata("twilio", "account_sid", {
249
- injectionTemplates: [
250
- {
251
- hostPattern: "api.twilio.com",
252
- injectionType: "header" as const,
253
- headerName: "Authorization",
254
- valuePrefix: "Basic ",
255
- valueTransform: "base64" as const,
256
- composeWith: {
257
- service: "twilio",
258
- field: "auth_token",
259
- separator: ":",
260
- },
261
- },
262
- {
263
- hostPattern: "messaging.twilio.com",
264
- injectionType: "header" as const,
265
- headerName: "Authorization",
266
- valuePrefix: "Basic ",
267
- valueTransform: "base64" as const,
268
- composeWith: {
269
- service: "twilio",
270
- field: "auth_token",
271
- separator: ":",
272
- },
273
- },
274
- ],
275
- });
276
- upsertCredentialMetadata("twilio", "auth_token", {});
277
-
278
- return Response.json({ success: true, hasCredentials: true });
279
- }
280
-
281
- /**
282
- * DELETE /v1/integrations/twilio/credentials
283
- */
284
- export async function handleClearTwilioCredentials(): Promise<Response> {
285
- const r1 = await deleteSecureKeyAsync("credential:twilio:account_sid");
286
- const r2 = await deleteSecureKeyAsync("credential:twilio:auth_token");
287
-
288
- if (r1 === "error" || r2 === "error") {
289
- return Response.json(
290
- {
291
- success: false,
292
- error: "Failed to delete Twilio credentials from secure storage",
293
- },
294
- { status: 500 },
295
- );
296
- }
297
-
298
- const raw = loadRawConfig();
299
- const twilio = (raw?.twilio ?? {}) as Record<string, unknown>;
300
- delete twilio.accountSid;
301
- saveRawConfig({ ...raw, twilio });
302
-
303
- deleteCredentialMetadata("twilio", "account_sid");
304
- deleteCredentialMetadata("twilio", "auth_token");
305
-
306
- return Response.json({ success: true, hasCredentials: false });
307
- }
308
-
309
- /**
310
- * GET /v1/integrations/twilio/numbers
311
- */
312
- export async function handleListTwilioNumbers(): Promise<Response> {
313
- if (!hasTwilioCredentials()) {
314
- return Response.json({
315
- success: false,
316
- hasCredentials: false,
317
- error: "Twilio credentials not configured. Set credentials first.",
318
- });
319
- }
320
-
321
- const { accountSid, authToken } = getTwilioCredentials();
322
- const numbers = await listIncomingPhoneNumbers(accountSid, authToken);
323
-
324
- return Response.json({ success: true, hasCredentials: true, numbers });
325
- }
326
-
327
- /**
328
- * POST /v1/integrations/twilio/numbers/provision
329
- *
330
- * Body: { country?: string, areaCode?: string }
331
- */
332
- export async function handleProvisionTwilioNumber(
333
- req: Request,
334
- ): Promise<Response> {
335
- if (!hasTwilioCredentials()) {
336
- return Response.json({
337
- success: false,
338
- hasCredentials: false,
339
- error: "Twilio credentials not configured. Set credentials first.",
340
- });
341
- }
342
-
343
- const body = (await req.json().catch(() => ({}))) as {
344
- country?: string;
345
- areaCode?: string;
346
- };
347
- const { accountSid, authToken } = getTwilioCredentials();
348
- const country = body.country ?? "US";
349
-
350
- const available = await searchAvailableNumbers(
351
- accountSid,
352
- authToken,
353
- country,
354
- body.areaCode,
355
- );
356
- if (available.length === 0) {
357
- return Response.json({
358
- success: false,
359
- hasCredentials: true,
360
- error: `No available phone numbers found for country=${country}${body.areaCode ? ` areaCode=${body.areaCode}` : ""}`,
361
- });
362
- }
363
-
364
- const purchased = await provisionPhoneNumber(
365
- accountSid,
366
- authToken,
367
- available[0].phoneNumber,
368
- );
369
-
370
- const phoneStored = await setSecureKeyAsync(
371
- "credential:twilio:phone_number",
372
- purchased.phoneNumber,
373
- );
374
- if (!phoneStored) {
375
- return Response.json({
376
- success: false,
377
- hasCredentials: hasTwilioCredentials(),
378
- phoneNumber: purchased.phoneNumber,
379
- error: `Phone number ${purchased.phoneNumber} was purchased but could not be saved. Use assign to assign it manually.`,
380
- });
381
- }
382
-
383
- const raw = loadRawConfig();
384
- const sms = (raw?.sms ?? {}) as Record<string, unknown>;
385
- sms.phoneNumber = purchased.phoneNumber;
386
- pruneAssistantPhoneNumbers(sms, purchased.phoneNumber, "keep");
387
- saveRawConfig({ ...raw, sms });
388
-
389
- // Best-effort webhook configuration
390
- const webhookResult = await syncTwilioWebhooks(
391
- purchased.phoneNumber,
392
- accountSid,
393
- authToken,
394
- loadRawConfig() as IngressConfig,
395
- );
396
-
397
- return Response.json({
398
- success: true,
399
- hasCredentials: true,
400
- phoneNumber: purchased.phoneNumber,
401
- warning: webhookResult.warning,
402
- });
403
- }
404
-
405
- /**
406
- * POST /v1/integrations/twilio/numbers/assign
407
- *
408
- * Body: { phoneNumber: string }
409
- */
410
- export async function handleAssignTwilioNumber(
411
- req: Request,
412
- ): Promise<Response> {
413
- const body = (await req.json().catch(() => ({}))) as { phoneNumber?: string };
414
-
415
- if (!body.phoneNumber) {
416
- return Response.json(
417
- {
418
- success: false,
419
- hasCredentials: hasTwilioCredentials(),
420
- error: "phoneNumber is required",
421
- },
422
- { status: 400 },
423
- );
424
- }
425
-
426
- const phoneStored = await setSecureKeyAsync(
427
- "credential:twilio:phone_number",
428
- body.phoneNumber,
429
- );
430
- if (!phoneStored) {
431
- return Response.json({
432
- success: false,
433
- hasCredentials: hasTwilioCredentials(),
434
- error: "Failed to store phone number in secure storage",
435
- });
436
- }
437
-
438
- const raw = loadRawConfig();
439
- const sms = (raw?.sms ?? {}) as Record<string, unknown>;
440
- sms.phoneNumber = body.phoneNumber;
441
- pruneAssistantPhoneNumbers(sms, body.phoneNumber, "keep");
442
- saveRawConfig({ ...raw, sms });
443
-
444
- // Best-effort webhook configuration when credentials are available
445
- let webhookWarning: string | undefined;
446
- if (hasTwilioCredentials()) {
447
- const { accountSid: acctSid, authToken: acctToken } =
448
- getTwilioCredentials();
449
- const webhookResult = await syncTwilioWebhooks(
450
- body.phoneNumber,
451
- acctSid,
452
- acctToken,
453
- loadRawConfig() as IngressConfig,
454
- );
455
- webhookWarning = webhookResult.warning;
456
- }
457
-
458
- return Response.json({
459
- success: true,
460
- hasCredentials: hasTwilioCredentials(),
461
- phoneNumber: body.phoneNumber,
462
- warning: webhookWarning,
463
- });
464
- }
465
-
466
- /**
467
- * POST /v1/integrations/twilio/numbers/release
468
- *
469
- * Body: { phoneNumber?: string }
470
- */
471
- export async function handleReleaseTwilioNumber(
472
- req: Request,
473
- ): Promise<Response> {
474
- if (!hasTwilioCredentials()) {
475
- return Response.json({
476
- success: false,
477
- hasCredentials: false,
478
- error: "Twilio credentials not configured. Set credentials first.",
479
- });
480
- }
481
-
482
- const body = (await req.json().catch(() => ({}))) as { phoneNumber?: string };
483
- const raw = loadRawConfig();
484
- const sms = (raw?.sms ?? {}) as Record<string, unknown>;
485
- const phoneNumber = body.phoneNumber || (sms.phoneNumber as string) || "";
486
-
487
- if (!phoneNumber) {
488
- return Response.json({
489
- success: false,
490
- hasCredentials: true,
491
- error:
492
- "No phone number to release. Specify phoneNumber or ensure one is assigned.",
493
- });
494
- }
495
-
496
- const { accountSid, authToken } = getTwilioCredentials();
497
-
498
- await releasePhoneNumber(accountSid, authToken, phoneNumber);
499
-
500
- if (sms.phoneNumber === phoneNumber) {
501
- delete sms.phoneNumber;
502
- }
503
- pruneAssistantPhoneNumbers(sms, phoneNumber, "remove");
504
- saveRawConfig({ ...raw, sms });
505
-
506
- const storedPhone = getSecureKey("credential:twilio:phone_number");
507
- if (storedPhone === phoneNumber) {
508
- await deleteSecureKeyAsync("credential:twilio:phone_number");
509
- }
510
-
511
- return Response.json({
512
- success: true,
513
- hasCredentials: true,
514
- warning:
515
- "Phone number released from Twilio. Any associated toll-free verification context is lost.",
516
- });
517
- }
518
-
519
- /**
520
- * GET /v1/integrations/twilio/sms/compliance
521
- */
522
- export async function handleGetSmsCompliance(): Promise<Response> {
523
- if (!hasTwilioCredentials()) {
524
- return Response.json({
525
- success: false,
526
- hasCredentials: false,
527
- error: "Twilio credentials not configured. Set credentials first.",
528
- });
529
- }
530
-
531
- const raw = loadRawConfig();
532
- const sms = (raw?.sms ?? {}) as Record<string, unknown>;
533
- const phoneNumber = (sms.phoneNumber as string) ?? "";
534
-
535
- if (!phoneNumber) {
536
- return Response.json({
537
- success: false,
538
- hasCredentials: true,
539
- error: "No phone number assigned. Assign a number first.",
540
- });
541
- }
542
-
543
- const { accountSid, authToken } = getTwilioCredentials();
544
-
545
- const tollFreePrefixes = [
546
- "+1800",
547
- "+1833",
548
- "+1844",
549
- "+1855",
550
- "+1866",
551
- "+1877",
552
- "+1888",
553
- ];
554
- const isTollFree = tollFreePrefixes.some((prefix) =>
555
- phoneNumber.startsWith(prefix),
556
- );
557
- const numberType = isTollFree ? "toll_free" : "local_10dlc";
558
-
559
- if (!isTollFree) {
560
- return Response.json({
561
- success: true,
562
- hasCredentials: true,
563
- phoneNumber,
564
- compliance: { numberType },
565
- });
566
- }
567
-
568
- const phoneSid = await getPhoneNumberSid(accountSid, authToken, phoneNumber);
569
- if (!phoneSid) {
570
- return Response.json({
571
- success: false,
572
- hasCredentials: true,
573
- phoneNumber,
574
- error: `Phone number ${phoneNumber} not found on Twilio account`,
575
- });
576
- }
577
-
578
- const verification = await getTollFreeVerificationStatus(
579
- accountSid,
580
- authToken,
581
- phoneSid,
582
- );
583
-
584
- return Response.json({
585
- success: true,
586
- hasCredentials: true,
587
- phoneNumber,
588
- compliance: {
589
- numberType,
590
- tollfreePhoneNumberSid: phoneSid,
591
- verificationSid: verification?.sid,
592
- verificationStatus: verification?.status,
593
- rejectionReason: verification?.rejectionReason,
594
- rejectionReasons: verification?.rejectionReasons,
595
- errorCode: verification?.errorCode,
596
- editAllowed: verification?.editAllowed,
597
- editExpiration: verification?.editExpiration,
598
- },
599
- });
600
- }
601
-
602
- /**
603
- * POST /v1/integrations/twilio/sms/compliance/tollfree
604
- *
605
- * Body: TollFreeVerificationSubmitParams
606
- */
607
- export async function handleSubmitTollfreeVerification(
608
- req: Request,
609
- ): Promise<Response> {
610
- if (!hasTwilioCredentials()) {
611
- return Response.json({
612
- success: false,
613
- hasCredentials: false,
614
- error: "Twilio credentials not configured. Set credentials first.",
615
- });
616
- }
617
-
618
- const vp = (await req.json().catch(() => ({}))) as Record<string, unknown>;
619
-
620
- const requiredFields: Array<[string, unknown]> = [
621
- ["tollfreePhoneNumberSid", vp.tollfreePhoneNumberSid],
622
- ["businessName", vp.businessName],
623
- ["businessWebsite", vp.businessWebsite],
624
- ["notificationEmail", vp.notificationEmail],
625
- ["useCaseCategories", vp.useCaseCategories],
626
- ["useCaseSummary", vp.useCaseSummary],
627
- ["productionMessageSample", vp.productionMessageSample],
628
- ["optInImageUrls", vp.optInImageUrls],
629
- ["optInType", vp.optInType],
630
- ["messageVolume", vp.messageVolume],
631
- ];
632
-
633
- const missing = requiredFields
634
- .filter(
635
- ([, v]) => v == null || v === "" || (Array.isArray(v) && v.length === 0),
636
- )
637
- .map(([name]) => name);
638
-
639
- if (missing.length > 0) {
640
- return Response.json(
641
- {
642
- success: false,
643
- hasCredentials: true,
644
- error: `Missing required verification fields: ${missing.join(", ")}`,
645
- },
646
- { status: 400 },
647
- );
648
- }
649
-
650
- const normalizedUseCaseCategories = normalizeUseCaseCategories(
651
- vp.useCaseCategories as string[],
652
- );
653
- const invalidCategories = normalizedUseCaseCategories.filter(
654
- (c) =>
655
- !TWILIO_VALID_USE_CASE_CATEGORIES.includes(
656
- c as (typeof TWILIO_VALID_USE_CASE_CATEGORIES)[number],
657
- ),
658
- );
659
- if (invalidCategories.length > 0) {
660
- return Response.json(
661
- {
662
- success: false,
663
- hasCredentials: true,
664
- error: `Invalid useCaseCategories: ${invalidCategories.join(", ")}. Valid values: ${TWILIO_VALID_USE_CASE_CATEGORIES.join(", ")}`,
665
- },
666
- { status: 400 },
667
- );
668
- }
669
-
670
- const validOptInTypes = [
671
- "VERBAL",
672
- "WEB_FORM",
673
- "PAPER_FORM",
674
- "VIA_TEXT",
675
- "MOBILE_QR_CODE",
676
- ];
677
- if (!validOptInTypes.includes(vp.optInType as string)) {
678
- return Response.json(
679
- {
680
- success: false,
681
- hasCredentials: true,
682
- error: `Invalid optInType: ${vp.optInType}. Valid values: ${validOptInTypes.join(", ")}`,
683
- },
684
- { status: 400 },
685
- );
686
- }
687
-
688
- const validMessageVolumes = [
689
- "10",
690
- "100",
691
- "1,000",
692
- "10,000",
693
- "100,000",
694
- "250,000",
695
- "500,000",
696
- "750,000",
697
- "1,000,000",
698
- "5,000,000",
699
- "10,000,000+",
700
- ];
701
- if (!validMessageVolumes.includes(vp.messageVolume as string)) {
702
- return Response.json(
703
- {
704
- success: false,
705
- hasCredentials: true,
706
- error: `Invalid messageVolume: ${vp.messageVolume}. Valid values: ${validMessageVolumes.join(", ")}`,
707
- },
708
- { status: 400 },
709
- );
710
- }
711
-
712
- const { accountSid, authToken } = getTwilioCredentials();
713
-
714
- const submitParams: TollFreeVerificationSubmitParams = {
715
- tollfreePhoneNumberSid: vp.tollfreePhoneNumberSid as string,
716
- businessName: vp.businessName as string,
717
- businessWebsite: vp.businessWebsite as string,
718
- notificationEmail: vp.notificationEmail as string,
719
- useCaseCategories: normalizedUseCaseCategories,
720
- useCaseSummary: vp.useCaseSummary as string,
721
- productionMessageSample: vp.productionMessageSample as string,
722
- optInImageUrls: vp.optInImageUrls as string[],
723
- optInType: vp.optInType as string,
724
- messageVolume: vp.messageVolume as string,
725
- businessType: (vp.businessType as string) ?? "SOLE_PROPRIETOR",
726
- customerProfileSid: vp.customerProfileSid as string | undefined,
727
- };
728
-
729
- const verification = await submitTollFreeVerification(
730
- accountSid,
731
- authToken,
732
- submitParams,
733
- );
734
-
735
- return Response.json({
736
- success: true,
737
- hasCredentials: true,
738
- compliance: {
739
- numberType: "toll_free",
740
- verificationSid: verification.sid,
741
- verificationStatus: verification.status,
742
- },
743
- });
744
- }
745
-
746
- /**
747
- * PATCH /v1/integrations/twilio/sms/compliance/tollfree/:verificationSid
748
- *
749
- * Body: partial verification params to update
750
- */
751
- export async function handleUpdateTollfreeVerification(
752
- req: Request,
753
- verificationSid: string,
754
- ): Promise<Response> {
755
- if (!hasTwilioCredentials()) {
756
- return Response.json({
757
- success: false,
758
- hasCredentials: false,
759
- error: "Twilio credentials not configured. Set credentials first.",
760
- });
761
- }
762
-
763
- const { accountSid, authToken } = getTwilioCredentials();
764
-
765
- const currentVerification = await getTollFreeVerificationBySid(
766
- accountSid,
767
- authToken,
768
- verificationSid,
769
- );
770
- if (!currentVerification) {
771
- return Response.json({
772
- success: false,
773
- hasCredentials: true,
774
- error: `Verification ${verificationSid} was not found on this Twilio account.`,
775
- });
776
- }
777
-
778
- if (currentVerification.status === "TWILIO_REJECTED") {
779
- const expirationMillis = currentVerification.editExpiration
780
- ? Date.parse(currentVerification.editExpiration)
781
- : Number.NaN;
782
- const editExpired =
783
- Number.isFinite(expirationMillis) && Date.now() > expirationMillis;
784
- if (currentVerification.editAllowed === false || editExpired) {
785
- const detail = editExpired
786
- ? `edit_expiration=${currentVerification.editExpiration}`
787
- : "edit_allowed=false";
788
- return Response.json({
789
- success: false,
790
- hasCredentials: true,
791
- error: `Verification ${verificationSid} cannot be updated (${detail}). Delete and resubmit instead.`,
792
- compliance: {
793
- numberType: "toll_free",
794
- verificationSid: currentVerification.sid,
795
- verificationStatus: currentVerification.status,
796
- editAllowed: currentVerification.editAllowed,
797
- editExpiration: currentVerification.editExpiration,
798
- },
799
- });
800
- }
801
- }
802
-
803
- const updateParams = {
804
- ...((await req.json().catch(() => ({}))) as Record<string, unknown>),
805
- };
806
- if (updateParams.useCaseCategories) {
807
- updateParams.useCaseCategories = normalizeUseCaseCategories(
808
- updateParams.useCaseCategories as string[],
809
- );
810
- }
811
-
812
- const verification = await updateTollFreeVerification(
813
- accountSid,
814
- authToken,
815
- verificationSid,
816
- updateParams,
817
- );
818
-
819
- return Response.json({
820
- success: true,
821
- hasCredentials: true,
822
- compliance: {
823
- numberType: "toll_free",
824
- verificationSid: verification.sid,
825
- verificationStatus: verification.status,
826
- editAllowed: verification.editAllowed,
827
- editExpiration: verification.editExpiration,
828
- },
829
- });
830
- }
831
-
832
- /**
833
- * DELETE /v1/integrations/twilio/sms/compliance/tollfree/:verificationSid
834
- */
835
- export async function handleDeleteTollfreeVerification(
836
- verificationSid: string,
837
- ): Promise<Response> {
838
- if (!hasTwilioCredentials()) {
839
- return Response.json({
840
- success: false,
841
- hasCredentials: false,
842
- error: "Twilio credentials not configured. Set credentials first.",
843
- });
844
- }
845
-
846
- const { accountSid, authToken } = getTwilioCredentials();
847
-
848
- await deleteTollFreeVerification(accountSid, authToken, verificationSid);
849
-
850
- return Response.json({
851
- success: true,
852
- hasCredentials: true,
853
- warning:
854
- "Toll-free verification deleted. Re-submitting may reset your position in the review queue.",
855
- });
856
- }
857
-
858
- /**
859
- * POST /v1/integrations/twilio/sms/test
860
- *
861
- * Body: { phoneNumber: string, text?: string }
862
- */
863
- export async function handleSmsSendTest(req: Request): Promise<Response> {
864
- if (!hasTwilioCredentials()) {
865
- return Response.json({
866
- success: false,
867
- hasCredentials: false,
868
- error: "Twilio credentials not configured. Set credentials first.",
869
- });
870
- }
871
-
872
- const body = (await req.json().catch(() => ({}))) as {
873
- phoneNumber?: string;
874
- text?: string;
875
- };
876
- const to = body.phoneNumber;
877
- if (!to) {
878
- return Response.json(
879
- {
880
- success: false,
881
- hasCredentials: true,
882
- error: "phoneNumber is required for SMS send test.",
883
- },
884
- { status: 400 },
885
- );
886
- }
887
-
888
- const raw = loadRawConfig();
889
- const smsSection = (raw?.sms ?? {}) as Record<string, unknown>;
890
- const from =
891
- (smsSection.phoneNumber as string | undefined) ||
892
- getSecureKey("credential:twilio:phone_number") ||
893
- "";
894
- if (!from) {
895
- return Response.json({
896
- success: false,
897
- hasCredentials: true,
898
- error:
899
- "No phone number assigned. Run the twilio-setup skill to assign a number.",
900
- });
901
- }
902
-
903
- const { accountSid, authToken } = getTwilioCredentials();
904
- const text = body.text || "Test SMS from your Vellum assistant";
905
-
906
- // Send via gateway's /deliver/sms endpoint
907
- const bearerToken = mintDaemonDeliveryToken();
908
- const gatewayUrl = getGatewayInternalBaseUrl();
909
-
910
- const sendResp = await fetch(`${gatewayUrl}/deliver/sms`, {
911
- method: "POST",
912
- headers: {
913
- "Content-Type": "application/json",
914
- Authorization: `Bearer ${bearerToken}`,
915
- },
916
- body: JSON.stringify({ to, text }),
917
- signal: AbortSignal.timeout(30_000),
918
- });
919
-
920
- if (!sendResp.ok) {
921
- const errBody = await sendResp.text().catch(() => "<unreadable>");
922
- return Response.json({
923
- success: false,
924
- hasCredentials: true,
925
- error: `SMS send failed (${sendResp.status}): ${errBody}`,
926
- });
927
- }
928
-
929
- const sendData = (await sendResp.json().catch(() => ({}))) as {
930
- messageSid?: string;
931
- status?: string;
932
- };
933
- const messageSid = sendData.messageSid || "";
934
- const initialStatus = sendData.status || "unknown";
935
-
936
- // Poll Twilio for final status (up to 3 times, 2s apart)
937
- let finalStatus = initialStatus;
938
- let errorCode: string | undefined;
939
- let errorMessage: string | undefined;
940
-
941
- if (messageSid) {
942
- for (let i = 0; i < 3; i++) {
943
- await new Promise((r) => setTimeout(r, 2000));
944
- try {
945
- const pollResult = await fetchMessageStatus(
946
- accountSid,
947
- authToken,
948
- messageSid,
949
- );
950
- finalStatus = pollResult.status;
951
- errorCode = pollResult.errorCode;
952
- errorMessage = pollResult.errorMessage;
953
- if (["delivered", "undelivered", "failed"].includes(finalStatus)) break;
954
- } catch {
955
- break;
956
- }
957
- }
958
- }
959
-
960
- const testResult = {
961
- messageSid,
962
- to,
963
- initialStatus,
964
- finalStatus,
965
- ...(errorCode ? { errorCode } : {}),
966
- ...(errorMessage ? { errorMessage } : {}),
967
- };
968
-
969
- _lastTestResult = { ...testResult, timestamp: Date.now() };
970
-
971
- return Response.json({
972
- success: true,
973
- hasCredentials: true,
974
- testResult,
975
- });
976
- }
977
-
978
- /**
979
- * POST /v1/integrations/twilio/sms/doctor
980
- */
981
- export async function handleSmsDoctor(): Promise<Response> {
982
- const hasCredentials = hasTwilioCredentials();
983
-
984
- // 1. Channel readiness check
985
- let readinessReady = false;
986
- const readinessIssues: string[] = [];
987
- try {
988
- const readinessService = getReadinessService();
989
- const snapshots = await readinessService.getReadiness("sms", false);
990
- const snapshot = snapshots[0];
991
- if (snapshot) {
992
- readinessReady = snapshot.ready;
993
- for (const r of snapshot.reasons) {
994
- readinessIssues.push(r.text);
995
- }
996
- } else {
997
- readinessIssues.push("No readiness snapshot returned for SMS channel");
998
- }
999
- } catch (err) {
1000
- readinessIssues.push(
1001
- `Readiness check failed: ${err instanceof Error ? err.message : String(err)}`,
1002
- );
1003
- }
1004
-
1005
- // 2. Compliance status
1006
- let complianceStatus = "unknown";
1007
- let complianceDetail: string | undefined;
1008
- let complianceRemediation: string | undefined;
1009
- if (hasCredentials) {
1010
- try {
1011
- const raw = loadRawConfig();
1012
- const smsSection = (raw?.sms ?? {}) as Record<string, unknown>;
1013
- const phoneNumber =
1014
- (smsSection.phoneNumber as string | undefined) ||
1015
- getSecureKey("credential:twilio:phone_number") ||
1016
- "";
1017
- if (phoneNumber) {
1018
- const { accountSid, authToken } = getTwilioCredentials();
1019
- const isTollFree =
1020
- phoneNumber.startsWith("+1") &&
1021
- ["800", "888", "877", "866", "855", "844", "833"].some((p) =>
1022
- phoneNumber.startsWith(`+1${p}`),
1023
- );
1024
- if (isTollFree) {
1025
- try {
1026
- const phoneSid = await getPhoneNumberSid(
1027
- accountSid,
1028
- authToken,
1029
- phoneNumber,
1030
- );
1031
- if (!phoneSid) {
1032
- complianceStatus = "check_failed";
1033
- complianceDetail = `Assigned number ${phoneNumber} was not found on the Twilio account`;
1034
- complianceRemediation =
1035
- "Reassign the number in twilio-setup or update credentials to the matching account.";
1036
- } else {
1037
- const verification = await getTollFreeVerificationStatus(
1038
- accountSid,
1039
- authToken,
1040
- phoneSid,
1041
- );
1042
- if (verification) {
1043
- const status = verification.status;
1044
- complianceStatus = status;
1045
- complianceDetail = `Toll-free verification: ${status}`;
1046
- if (status === "TWILIO_APPROVED") {
1047
- complianceRemediation = undefined;
1048
- } else if (
1049
- status === "PENDING_REVIEW" ||
1050
- status === "IN_REVIEW"
1051
- ) {
1052
- complianceRemediation =
1053
- "Toll-free verification is pending. Messaging may have limited throughput until approved.";
1054
- } else if (status === "TWILIO_REJECTED") {
1055
- if (verification.editAllowed) {
1056
- complianceRemediation = verification.editExpiration
1057
- ? `Toll-free verification was rejected but can still be edited until ${verification.editExpiration}. Update and resubmit it.`
1058
- : "Toll-free verification was rejected but can still be edited. Update and resubmit it.";
1059
- } else {
1060
- complianceRemediation =
1061
- "Toll-free verification was rejected and is no longer editable. Delete and resubmit it.";
1062
- }
1063
- } else {
1064
- complianceRemediation =
1065
- "Submit a toll-free verification to enable full messaging throughput.";
1066
- }
1067
- } else {
1068
- complianceStatus = "unverified";
1069
- complianceDetail = "Toll-free number without verification";
1070
- complianceRemediation =
1071
- "Submit a toll-free verification request to avoid filtering.";
1072
- }
1073
- }
1074
- } catch {
1075
- complianceStatus = "check_failed";
1076
- complianceDetail =
1077
- "Could not retrieve toll-free verification status";
1078
- }
1079
- } else {
1080
- complianceStatus = "local_10dlc";
1081
- complianceDetail =
1082
- "Local/10DLC number — carrier registration handled externally";
1083
- }
1084
- } else {
1085
- complianceStatus = "no_number";
1086
- complianceDetail = "No phone number assigned";
1087
- complianceRemediation =
1088
- "Assign a phone number via the twilio-setup skill.";
1089
- }
1090
- } catch {
1091
- complianceStatus = "check_failed";
1092
- complianceDetail = "Could not determine compliance status";
1093
- }
1094
- } else {
1095
- complianceStatus = "no_credentials";
1096
- complianceDetail = "Twilio credentials are not configured";
1097
- complianceRemediation =
1098
- "Set Twilio credentials via the twilio-setup skill.";
1099
- }
1100
-
1101
- // 3. Last send test result
1102
- let lastSend:
1103
- | { status: string; errorCode?: string; remediation?: string }
1104
- | undefined;
1105
- if (_lastTestResult) {
1106
- lastSend = {
1107
- status: _lastTestResult.finalStatus,
1108
- ...(_lastTestResult.errorCode
1109
- ? { errorCode: _lastTestResult.errorCode }
1110
- : {}),
1111
- ...(_lastTestResult.errorCode
1112
- ? { remediation: mapTwilioErrorRemediation(_lastTestResult.errorCode) }
1113
- : {}),
1114
- };
1115
- }
1116
-
1117
- // 4. Overall status
1118
- const actionItems: string[] = [];
1119
- let overallStatus: "healthy" | "degraded" | "broken" = "healthy";
1120
-
1121
- if (!hasCredentials) {
1122
- overallStatus = "broken";
1123
- actionItems.push("Configure Twilio credentials.");
1124
- }
1125
- if (!readinessReady) {
1126
- overallStatus = "broken";
1127
- for (const issue of readinessIssues) actionItems.push(issue);
1128
- }
1129
- if (
1130
- complianceStatus === "unverified" ||
1131
- complianceStatus === "PENDING_REVIEW" ||
1132
- complianceStatus === "IN_REVIEW"
1133
- ) {
1134
- if (overallStatus === "healthy") overallStatus = "degraded";
1135
- if (complianceRemediation) actionItems.push(complianceRemediation);
1136
- }
1137
- if (
1138
- complianceStatus === "TWILIO_REJECTED" ||
1139
- complianceStatus === "no_number"
1140
- ) {
1141
- overallStatus = "broken";
1142
- if (complianceRemediation) actionItems.push(complianceRemediation);
1143
- }
1144
- if (
1145
- _lastTestResult &&
1146
- ["failed", "undelivered"].includes(_lastTestResult.finalStatus)
1147
- ) {
1148
- if (overallStatus === "healthy") overallStatus = "degraded";
1149
- const remediation = mapTwilioErrorRemediation(_lastTestResult.errorCode);
1150
- actionItems.push(
1151
- remediation ||
1152
- `Last test SMS ${_lastTestResult.finalStatus}. Check Twilio logs for details.`,
1153
- );
1154
- }
1155
-
1156
- return Response.json({
1157
- success: true,
1158
- hasCredentials,
1159
- diagnostics: {
1160
- readiness: { ready: readinessReady, issues: readinessIssues },
1161
- compliance: {
1162
- status: complianceStatus,
1163
- ...(complianceDetail ? { detail: complianceDetail } : {}),
1164
- ...(complianceRemediation
1165
- ? { remediation: complianceRemediation }
1166
- : {}),
1167
- },
1168
- ...(lastSend ? { lastSend } : {}),
1169
- overallStatus,
1170
- actionItems,
1171
- },
1172
- });
1173
- }
1174
-
1175
- // ---------------------------------------------------------------------------
1176
- // Route definitions
1177
- // ---------------------------------------------------------------------------
1178
-
1179
- export function twilioRouteDefinitions(): RouteDefinition[] {
1180
- return [
1181
- {
1182
- endpoint: "integrations/twilio/config",
1183
- method: "GET",
1184
- handler: () => handleGetTwilioConfig(),
1185
- },
1186
- {
1187
- endpoint: "integrations/twilio/credentials",
1188
- method: "POST",
1189
- handler: async ({ req }) => handleSetTwilioCredentials(req),
1190
- },
1191
- {
1192
- endpoint: "integrations/twilio/credentials",
1193
- method: "DELETE",
1194
- handler: async () => handleClearTwilioCredentials(),
1195
- },
1196
- {
1197
- endpoint: "integrations/twilio/numbers",
1198
- method: "GET",
1199
- handler: async () => handleListTwilioNumbers(),
1200
- },
1201
- {
1202
- endpoint: "integrations/twilio/numbers/provision",
1203
- method: "POST",
1204
- handler: async ({ req }) => handleProvisionTwilioNumber(req),
1205
- },
1206
- {
1207
- endpoint: "integrations/twilio/numbers/assign",
1208
- method: "POST",
1209
- handler: async ({ req }) => handleAssignTwilioNumber(req),
1210
- },
1211
- {
1212
- endpoint: "integrations/twilio/numbers/release",
1213
- method: "POST",
1214
- handler: async ({ req }) => handleReleaseTwilioNumber(req),
1215
- },
1216
- {
1217
- endpoint: "integrations/twilio/sms/compliance",
1218
- method: "GET",
1219
- handler: async () => handleGetSmsCompliance(),
1220
- },
1221
- {
1222
- endpoint: "integrations/twilio/sms/compliance/tollfree",
1223
- method: "POST",
1224
- handler: async ({ req }) => handleSubmitTollfreeVerification(req),
1225
- },
1226
- {
1227
- endpoint: "integrations/twilio/sms/compliance/tollfree/:sid",
1228
- method: "PATCH",
1229
- policyKey: "integrations/twilio/sms/compliance/tollfree",
1230
- handler: async ({ req, params }) =>
1231
- handleUpdateTollfreeVerification(req, params.sid),
1232
- },
1233
- {
1234
- endpoint: "integrations/twilio/sms/compliance/tollfree/:sid",
1235
- method: "DELETE",
1236
- policyKey: "integrations/twilio/sms/compliance/tollfree",
1237
- handler: async ({ params }) =>
1238
- handleDeleteTollfreeVerification(params.sid),
1239
- },
1240
- {
1241
- endpoint: "integrations/twilio/sms/test",
1242
- method: "POST",
1243
- handler: async ({ req }) => handleSmsSendTest(req),
1244
- },
1245
- {
1246
- endpoint: "integrations/twilio/sms/doctor",
1247
- method: "POST",
1248
- handler: async () => handleSmsDoctor(),
1249
- },
1250
- ];
1251
- }