@vellumai/assistant 0.10.12-dev.202607250047.75b9ec6 → 0.10.12-staging.1

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 (385) hide show
  1. package/README.md +1 -1
  2. package/docs/trusted-contact-access.md +15 -29
  3. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +0 -1
  4. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +1 -69
  5. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +0 -1
  6. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +1 -69
  7. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  8. package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +1 -69
  9. package/openapi.yaml +7 -28
  10. package/package.json +1 -1
  11. package/src/__tests__/acp-session.test.ts +3 -3
  12. package/src/__tests__/approval-cascade.test.ts +5 -5
  13. package/src/__tests__/approval-routes-http.test.ts +3 -3
  14. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
  15. package/src/__tests__/assistant-event-hub-targeted.test.ts +11 -13
  16. package/src/__tests__/assistant-event-hub.test.ts +11 -13
  17. package/src/__tests__/assistant-event.test.ts +9 -12
  18. package/src/__tests__/assistant-id-boundary-guard.test.ts +58 -0
  19. package/src/__tests__/assistant-stream-state.test.ts +3 -5
  20. package/src/__tests__/avatar-identity-sync.test.ts +3 -3
  21. package/src/__tests__/call-setup-flow-name-capture.test.ts +3 -65
  22. package/src/__tests__/channel-approvals.test.ts +27 -0
  23. package/src/__tests__/channel-guardian.test.ts +512 -85
  24. package/src/__tests__/channel-readiness-slack-remote.test.ts +3 -151
  25. package/src/__tests__/channel-retry-sweep.test.ts +2 -344
  26. package/src/__tests__/channel-setup-panel-ack.test.ts +9 -12
  27. package/src/__tests__/chat-reveal-guard-priming.test.ts +28 -28
  28. package/src/__tests__/compaction-events.test.ts +8 -8
  29. package/src/__tests__/config-loader-backfill.test.ts +5 -4
  30. package/src/__tests__/config-loader-platform-defaults.test.ts +28 -54
  31. package/src/__tests__/config-model-image-provider.test.ts +0 -20
  32. package/src/__tests__/config-schema.test.ts +1 -12
  33. package/src/__tests__/config-set-platform-guard.test.ts +12 -11
  34. package/src/__tests__/config-sounds-sync.test.ts +4 -4
  35. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -2
  36. package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +3 -3
  37. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
  38. package/src/__tests__/conversation-agent-loop-overflow.test.ts +12 -12
  39. package/src/__tests__/conversation-agent-loop.test.ts +29 -29
  40. package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
  41. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  42. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  43. package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
  44. package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +4 -4
  45. package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
  46. package/src/__tests__/conversation-queue.test.ts +81 -81
  47. package/src/__tests__/conversation-runtime-assembly.test.ts +0 -27
  48. package/src/__tests__/conversation-slash-queue.test.ts +11 -11
  49. package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
  50. package/src/__tests__/conversation-speed-override.test.ts +2 -2
  51. package/src/__tests__/conversation-starter-routes.test.ts +2 -2
  52. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +16 -18
  53. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
  54. package/src/__tests__/conversation-surfaces-app-open.test.ts +4 -7
  55. package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
  56. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
  57. package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
  58. package/src/__tests__/conversation-surfaces-state-update.test.ts +6 -9
  59. package/src/__tests__/conversation-surfaces-table-action.test.ts +3 -6
  60. package/src/__tests__/conversation-surfaces-task-progress.test.ts +49 -49
  61. package/src/__tests__/conversation-sync-tags.test.ts +5 -5
  62. package/src/__tests__/conversation-usage.test.ts +0 -27
  63. package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
  64. package/src/__tests__/credential-security-invariants.test.ts +0 -2
  65. package/src/__tests__/daemon-assistant-events.test.ts +15 -15
  66. package/src/__tests__/emit-event-signal.test.ts +6 -6
  67. package/src/__tests__/events-tail-route.test.ts +4 -6
  68. package/src/__tests__/guardian-card-withdrawal.test.ts +0 -57
  69. package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
  70. package/src/__tests__/host-browser-proxy.test.ts +1 -1
  71. package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
  72. package/src/__tests__/image-credentials.test.ts +8 -65
  73. package/src/__tests__/introduction-card-resolver.test.ts +4 -55
  74. package/src/__tests__/list-messages-page-latest.test.ts +2 -2
  75. package/src/__tests__/log-redact.test.ts +0 -18
  76. package/src/__tests__/managed-profile-guard.test.ts +0 -27
  77. package/src/__tests__/media-generate-image.test.ts +11 -62
  78. package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
  79. package/src/__tests__/memory-upsert-concurrency.test.ts +1 -1
  80. package/src/__tests__/non-member-access-request.test.ts +137 -87
  81. package/src/__tests__/notification-deep-link.test.ts +12 -12
  82. package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
  83. package/src/__tests__/openai-responses-prompt-cache.test.ts +7 -27
  84. package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
  85. package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
  86. package/src/__tests__/playbook-execution.test.ts +2 -2
  87. package/src/__tests__/playbook-tools.test.ts +2 -2
  88. package/src/__tests__/plugin-event-hub-facade.test.ts +15 -18
  89. package/src/__tests__/provider-platform-proxy-integration.test.ts +1 -0
  90. package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -7
  91. package/src/__tests__/request-secret-standalone-channel-gate.test.ts +3 -3
  92. package/src/__tests__/runtime-events-sse-parity.test.ts +10 -10
  93. package/src/__tests__/runtime-events-sse.test.ts +1 -1
  94. package/src/__tests__/schedule-routes.test.ts +2 -2
  95. package/src/__tests__/schedule-store.test.ts +3 -3
  96. package/src/__tests__/secret-patterns.test.ts +27 -0
  97. package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
  98. package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
  99. package/src/__tests__/secret-response-routing.test.ts +3 -3
  100. package/src/__tests__/secret-scanner.test.ts +0 -36
  101. package/src/__tests__/send-endpoint-busy.test.ts +7 -7
  102. package/src/__tests__/slack-inbound-verification.test.ts +20 -45
  103. package/src/__tests__/slack-share-routes.test.ts +3 -3
  104. package/src/__tests__/starter-task-flow.test.ts +3 -6
  105. package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
  106. package/src/__tests__/subagent-disposal.test.ts +10 -10
  107. package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
  108. package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
  109. package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
  110. package/src/__tests__/subagent-manager-notify.test.ts +10 -10
  111. package/src/__tests__/subagent-spawn-and-await.test.ts +13 -13
  112. package/src/__tests__/sync-message-contract.test.ts +3 -3
  113. package/src/__tests__/task-memory-cleanup.test.ts +11 -13
  114. package/src/__tests__/tool-preview-lifecycle.test.ts +28 -28
  115. package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
  116. package/src/__tests__/tool-start-timestamp.test.ts +4 -4
  117. package/src/__tests__/trusted-contact-multichannel.test.ts +4 -0
  118. package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
  119. package/src/__tests__/ui-work-result-surface.test.ts +3 -3
  120. package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
  121. package/src/__tests__/voice-session-bridge.test.ts +44 -44
  122. package/src/acp/__tests__/client-handler.test.ts +3 -3
  123. package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
  124. package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
  125. package/src/acp/client-handler.ts +3 -3
  126. package/src/acp/session-manager.ts +8 -8
  127. package/src/api/events/subagent-event.ts +2 -2
  128. package/src/api/index.ts +0 -30
  129. package/src/approvals/guardian-card-withdrawal.ts +8 -53
  130. package/src/approvals/guardian-decision-primitive.ts +1 -24
  131. package/src/approvals/guardian-request-resolvers.ts +6 -38
  132. package/src/calls/call-controller.ts +27 -27
  133. package/src/calls/call-setup-flow.ts +5 -22
  134. package/src/calls/voice-session-bridge.ts +7 -7
  135. package/src/cli/commands/config.ts +8 -23
  136. package/src/cli/lib/bundled-marketplace.json +0 -12
  137. package/src/cli.ts +109 -2
  138. package/src/config/__tests__/default-profile-catalog.test.ts +2 -48
  139. package/src/config/__tests__/deployment-context-defaults.test.ts +0 -9
  140. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +7 -13
  141. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -3
  142. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +2 -5
  143. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +2 -5
  144. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +2 -5
  145. package/src/config/call-site-defaults.ts +17 -14
  146. package/src/config/default-profile-catalog.ts +51 -125
  147. package/src/config/default-profile-names.ts +0 -27
  148. package/src/config/feature-flag-registry.json +0 -8
  149. package/src/config/llm-resolver.ts +2 -2
  150. package/src/config/loader.ts +1 -7
  151. package/src/config/raw-config-utils.ts +1 -1
  152. package/src/config/schemas/llm.ts +1 -9
  153. package/src/config/schemas/services.ts +2 -10
  154. package/src/contacts/member-status.ts +1 -21
  155. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
  156. package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
  157. package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
  158. package/src/daemon/channel-ui-capability.ts +8 -38
  159. package/src/daemon/conversation-agent-loop-handlers.ts +3 -3
  160. package/src/daemon/conversation-agent-loop.ts +4 -4
  161. package/src/daemon/conversation-messaging.ts +14 -25
  162. package/src/daemon/conversation-notifiers.ts +2 -2
  163. package/src/daemon/conversation-process.ts +4 -4
  164. package/src/daemon/conversation-queue-manager.ts +7 -7
  165. package/src/daemon/conversation-runtime-assembly.ts +0 -11
  166. package/src/daemon/conversation-surfaces.ts +4 -4
  167. package/src/daemon/conversation-tool-setup.ts +3 -8
  168. package/src/daemon/conversation-usage.ts +14 -24
  169. package/src/daemon/conversation.ts +11 -11
  170. package/src/daemon/handlers/config-channels.ts +134 -40
  171. package/src/daemon/handlers/config-model.ts +7 -15
  172. package/src/daemon/host-proxy-base.ts +4 -4
  173. package/src/daemon/lifecycle.ts +0 -8
  174. package/src/daemon/message-protocol.ts +151 -16
  175. package/src/daemon/message-types/acp.ts +20 -0
  176. package/src/daemon/message-types/apps.ts +356 -0
  177. package/src/daemon/message-types/background-tools.ts +14 -0
  178. package/src/daemon/message-types/bookmarks.ts +13 -0
  179. package/src/daemon/message-types/computer-use.ts +12 -0
  180. package/src/daemon/message-types/contacts.ts +13 -0
  181. package/src/daemon/message-types/conversations.ts +345 -9
  182. package/src/daemon/message-types/document-comments.ts +14 -0
  183. package/src/daemon/message-types/documents.ts +13 -0
  184. package/src/daemon/message-types/home.ts +15 -0
  185. package/src/daemon/message-types/host-app-control.ts +9 -0
  186. package/src/daemon/message-types/host-bash.ts +12 -0
  187. package/src/daemon/message-types/host-browser.ts +7 -0
  188. package/src/daemon/message-types/host-cu.ts +10 -0
  189. package/src/daemon/message-types/host-file.ts +12 -0
  190. package/src/daemon/message-types/host-transfer.ts +12 -0
  191. package/src/daemon/message-types/host-ui-snapshot.ts +7 -0
  192. package/src/daemon/message-types/integrations.ts +249 -0
  193. package/src/daemon/message-types/memory.ts +10 -0
  194. package/src/daemon/message-types/messages.ts +48 -0
  195. package/src/daemon/message-types/notifications.ts +7 -0
  196. package/src/daemon/message-types/schedules.ts +14 -0
  197. package/src/daemon/message-types/settings.ts +17 -0
  198. package/src/daemon/message-types/skills.ts +5 -0
  199. package/src/daemon/message-types/subagents.ts +63 -0
  200. package/src/daemon/message-types/surfaces.ts +82 -34
  201. package/src/daemon/message-types/sync.ts +2 -0
  202. package/src/daemon/message-types/upgrades.ts +14 -0
  203. package/src/daemon/message-types/workflows.ts +25 -0
  204. package/src/daemon/message-types/workspace.ts +137 -0
  205. package/src/daemon/process-message.ts +5 -5
  206. package/src/daemon/tool-setup-types.ts +0 -12
  207. package/src/daemon/tool-side-effects.ts +10 -10
  208. package/src/daemon/wake-conversation-ops.ts +4 -4
  209. package/src/home/conversation-starter-checkpoints.ts +2 -2
  210. package/src/home/job-handlers/conversation-starters.ts +11 -15
  211. package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
  212. package/src/ipc/routes/events-ipc-routes.ts +3 -3
  213. package/src/mcp/mcp-oauth-provider.ts +1 -59
  214. package/src/media/app-icon-generator.ts +8 -15
  215. package/src/media/avatar-router.ts +5 -9
  216. package/src/media/image-credentials.ts +10 -42
  217. package/src/media/image-service.ts +13 -1
  218. package/src/media/types.ts +3 -26
  219. package/src/messaging/providers/slack/__tests__/auth.test.ts +86 -1
  220. package/src/messaging/providers/slack/auth.ts +54 -18
  221. package/src/messaging/providers/slack/withdraw.test.ts +0 -71
  222. package/src/messaging/providers/slack/withdraw.ts +5 -53
  223. package/src/monitoring/recovery/run-recovery.ts +0 -2
  224. package/src/notifications/adapters/macos.ts +3 -3
  225. package/src/notifications/adapters/slack.ts +0 -6
  226. package/src/oauth/AGENTS.md +1 -1
  227. package/src/permissions/confirmation-guardian-request.test.ts +2 -2
  228. package/src/permissions/confirmation-guardian-request.ts +2 -2
  229. package/src/permissions/prompter.ts +5 -5
  230. package/src/permissions/question-prompter.test.ts +8 -8
  231. package/src/permissions/secret-prompter.ts +2 -2
  232. package/src/persistence/conversation-crud.ts +1 -4
  233. package/src/persistence/conversation-title-service.ts +0 -25
  234. package/src/persistence/delivery-crud.ts +3 -27
  235. package/src/persistence/delivery-status.ts +2 -60
  236. package/src/persistence/embeddings/graph-node-orphan-sweep.ts +3 -9
  237. package/src/persistence/migrations/340-sweep-orphaned-graph-node-vectors.test.ts +0 -16
  238. package/src/persistence/migrations/341-sweep-cacheless-graph-node-vectors.test.ts +8 -5
  239. package/src/persistence/raw-query.ts +0 -14
  240. package/src/persistence/schema/conversations.ts +1 -2
  241. package/src/persistence/steps.ts +0 -30
  242. package/src/playbooks/playbook-compiler.ts +2 -5
  243. package/src/plugin-api/conversation-turn.ts +4 -4
  244. package/src/plugin-api/event-hub-facade.ts +4 -6
  245. package/src/plugin-api/index.ts +4 -17
  246. package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +2 -8
  247. package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +0 -154
  248. package/src/plugins/defaults/memory/graph/bootstrap.test.ts +0 -22
  249. package/src/plugins/defaults/memory/graph/bootstrap.ts +3 -6
  250. package/src/plugins/defaults/memory/graph/capability-seed.ts +5 -9
  251. package/src/plugins/defaults/memory/graph/consolidation.ts +3 -11
  252. package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +28 -28
  253. package/src/plugins/defaults/memory/graph/decay.ts +2 -3
  254. package/src/plugins/defaults/memory/graph/graph-search.ts +2 -3
  255. package/src/plugins/defaults/memory/graph/retriever.test.ts +11 -7
  256. package/src/plugins/defaults/memory/graph/store.test.ts +6 -4
  257. package/src/plugins/defaults/memory/graph/store.ts +22 -43
  258. package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +0 -35
  259. package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +0 -29
  260. package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +17 -24
  261. package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +4 -38
  262. package/src/plugins/defaults/memory/src/memory-item-routes.ts +10 -44
  263. package/src/plugins/defaults/memory/task-memory-cleanup.ts +25 -94
  264. package/src/plugins/defaults/memory/v2/backfill-jobs.ts +2 -12
  265. package/src/plugins/defaults/memory/v2/migration.ts +5 -2
  266. package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +12 -104
  267. package/src/plugins/defaults/platform-hosted/routes/reengage.ts +12 -104
  268. package/src/plugins/types.ts +2 -2
  269. package/src/prompts/templates/system-sections.ts +0 -2
  270. package/src/providers/__tests__/registry-native-web-search.test.ts +1 -0
  271. package/src/providers/anthropic/client.ts +9 -11
  272. package/src/providers/inference/connections.ts +14 -30
  273. package/src/providers/model-catalog.ts +0 -51
  274. package/src/providers/openai/responses-provider.ts +4 -13
  275. package/src/providers/registry.ts +1 -0
  276. package/src/runtime/AGENTS.md +0 -8
  277. package/src/runtime/access-request-helper.ts +58 -71
  278. package/src/runtime/agent-wake.ts +31 -9
  279. package/src/runtime/assistant-event-hub.ts +18 -18
  280. package/src/runtime/assistant-event.ts +11 -23
  281. package/src/runtime/assistant-stream-state.ts +4 -4
  282. package/src/runtime/channel-approval-types.ts +0 -22
  283. package/src/runtime/channel-approvals.ts +25 -0
  284. package/src/runtime/channel-readiness-service.ts +7 -105
  285. package/src/runtime/channel-retry-sweep.ts +22 -200
  286. package/src/runtime/guardian-action-service.ts +1 -14
  287. package/src/runtime/http-types.ts +2 -2
  288. package/src/runtime/introduction-policy.test.ts +0 -8
  289. package/src/runtime/introduction-policy.ts +2 -14
  290. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +0 -28
  291. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +0 -160
  292. package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +0 -29
  293. package/src/runtime/routes/__tests__/user-routes-cli.test.ts +0 -7
  294. package/src/runtime/routes/acp-routes.ts +2 -2
  295. package/src/runtime/routes/brain-graph-routes.ts +11 -11
  296. package/src/runtime/routes/browser-tabs-routes.ts +1 -2
  297. package/src/runtime/routes/canned-message-complete.ts +2 -2
  298. package/src/runtime/routes/conversation-query-routes.ts +24 -57
  299. package/src/runtime/routes/conversation-routes.ts +2 -8
  300. package/src/runtime/routes/debug-routes.ts +2 -2
  301. package/src/runtime/routes/defer-routes.ts +4 -7
  302. package/src/runtime/routes/events-routes.ts +1 -2
  303. package/src/runtime/routes/global-search-routes.ts +2 -8
  304. package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
  305. package/src/runtime/routes/image-generation-routes.ts +9 -12
  306. package/src/runtime/routes/inbound-message-handler.ts +64 -187
  307. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +52 -60
  308. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +40 -25
  309. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -158
  310. package/src/runtime/routes/inbound-stages/background-dispatch.ts +30 -95
  311. package/src/runtime/routes/inference-provider-connection-routes.ts +6 -101
  312. package/src/runtime/routes/integrations/slack/__tests__/token-routing.test.ts +85 -38
  313. package/src/runtime/routes/integrations/slack/channels.ts +13 -9
  314. package/src/runtime/routes/integrations/slack/share.ts +21 -12
  315. package/src/runtime/routes/mcp-auth-routes.ts +44 -42
  316. package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
  317. package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
  318. package/src/runtime/routes/sequence-routes.ts +6 -7
  319. package/src/runtime/routes/suggest-trust-rule-routes.ts +19 -6
  320. package/src/runtime/routes/surface-action-routes.ts +0 -10
  321. package/src/runtime/routes/ui-request-routes.ts +1 -2
  322. package/src/runtime/routes/user-routes-cli.ts +1 -2
  323. package/src/runtime/routes/watcher-routes.ts +6 -9
  324. package/src/runtime/routes/workspace-routes.test.ts +2 -2
  325. package/src/runtime/slack-reply-session.test.ts +12 -12
  326. package/src/runtime/slack-reply-session.ts +17 -17
  327. package/src/runtime/sync/sync-publisher.test.ts +5 -7
  328. package/src/security/AGENTS.md +1 -1
  329. package/src/security/credential-key.ts +0 -17
  330. package/src/security/secret-ingress.ts +105 -14
  331. package/src/security/secret-patterns.ts +139 -8
  332. package/src/security/secret-scanner.ts +3 -8
  333. package/src/signals/emit-event.ts +3 -3
  334. package/src/signals/event-stream.ts +5 -5
  335. package/src/subagent/manager.ts +15 -15
  336. package/src/tools/acp/context.ts +5 -5
  337. package/src/tools/ask-question/ask-question-tool.test.ts +1 -87
  338. package/src/tools/ask-question/ask-question-tool.ts +0 -58
  339. package/src/tools/browser/browser-screencast.ts +6 -6
  340. package/src/tools/subagent/spawn.ts +3 -3
  341. package/src/tools/tool-types.ts +0 -8
  342. package/src/tools/types.ts +0 -9
  343. package/src/util/log-redact.ts +3 -7
  344. package/src/workflows/leaf-runner.ts +5 -5
  345. package/src/workspace/migrations/registry.ts +0 -2
  346. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
  347. package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
  348. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
  349. package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
  350. package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +0 -449
  351. package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +0 -468
  352. package/src/__tests__/slack-required-scopes-mirror.test.ts +0 -81
  353. package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +0 -284
  354. package/src/api/events/app-files-changed.ts +0 -20
  355. package/src/api/events/oauth-connect-result.ts +0 -26
  356. package/src/api/events/platform-disconnected.ts +0 -21
  357. package/src/api/events/show-platform-login.ts +0 -20
  358. package/src/api/events/ui-surface-undo-result.ts +0 -27
  359. package/src/daemon/__tests__/channel-ui-capability.test.ts +0 -26
  360. package/src/mcp/__tests__/mcp-oauth-provider.test.ts +0 -75
  361. package/src/monitoring/recovery/__tests__/orphaned-channel-events.test.ts +0 -144
  362. package/src/monitoring/recovery/orphaned-channel-events.ts +0 -72
  363. package/src/persistence/migrations/349-move-memory-graph-tables-to-memory-db.ts +0 -227
  364. package/src/persistence/migrations/350-conversations-total-input-tokens-nullable.ts +0 -77
  365. package/src/persistence/migrations/__tests__/350-conversations-total-input-tokens-nullable.test.ts +0 -75
  366. package/src/plugin-api/__tests__/publish-event.test.ts +0 -54
  367. package/src/plugin-api/publish-event.ts +0 -39
  368. package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +0 -87
  369. package/src/providers/inference/__tests__/credential-slot-repair.test.ts +0 -138
  370. package/src/providers/inference/credential-slot-repair.ts +0 -110
  371. package/src/runtime/routes/__tests__/browser-tabs-routes.test.ts +0 -35
  372. package/src/runtime/routes/__tests__/defer-routes.test.ts +0 -39
  373. package/src/runtime/routes/__tests__/events-routes.test.ts +0 -40
  374. package/src/runtime/routes/__tests__/mcp-auth-routes.test.ts +0 -69
  375. package/src/runtime/routes/__tests__/sequence-routes.test.ts +0 -56
  376. package/src/runtime/routes/__tests__/ui-request-routes.test.ts +0 -37
  377. package/src/runtime/routes/__tests__/watcher-routes.test.ts +0 -42
  378. package/src/runtime/routes/inbound-stages/channel-turn-admission.test.ts +0 -141
  379. package/src/runtime/routes/inbound-stages/channel-turn-admission.ts +0 -111
  380. package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +0 -53
  381. package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +0 -64
  382. package/src/runtime/routes/parse-body.ts +0 -31
  383. package/src/util/single-flight.test.ts +0 -88
  384. package/src/util/single-flight.ts +0 -57
  385. package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +0 -128
package/README.md CHANGED
@@ -145,7 +145,7 @@ All approval prompt delivery paths use a **fail-closed** policy -- if the prompt
145
145
 
146
146
  ### Plain-Text Fallback for Non-Rich Channels
147
147
 
148
- Channels that do not support rich inline approval UI (e.g., inline keyboards) receive plain-text instructions embedded in the message body. The `supportsInlineOptions` channel capability (`channelSupportsInlineOptions()`) determines whether to send the structured `promptText` (for channels whose adapter renders inline buttons like Telegram) or the `plainTextFallback` string (for all other channels). The fallback text includes instructions so the user can respond via text; the conversational approval engine then classifies the free-text response.
148
+ Channels that do not support rich inline approval UI (e.g., inline keyboards) receive plain-text instructions embedded in the message body. The `channelSupportsRichApprovalUI()` check determines whether to send the structured `promptText` (for rich channels like Telegram) or the `plainTextFallback` string (for all other channels). The fallback text includes instructions so the user can respond via text; the conversational approval engine then classifies the free-text response.
149
149
 
150
150
  ### Key modules
151
151
 
@@ -39,7 +39,7 @@ Design doc defining how unknown users gain access to a Vellum assistant via chan
39
39
 
40
40
  This ensures unknown inbound access attempts always trigger guardian notification, even when the requester's source channel has no guardian binding.
41
41
 
42
- 4. **Guardian decides.** All decisions route through the guardian decision primitive (`applyGuardianDecision`, `approvals/guardian-decision-primitive.ts`) and commit via the gateway's `guardian_requests_decide` IPC op: the status CAS and the decision's ACL outcome execute in ONE gateway transaction, so an `approved` request can never exist without its ACL write. The introduction card supports four outcomes: **approve** (start the verification handshake), **trust** (activate directly, no code — used for workspace-vouched identities), **leave unverified** (the `leave_unverified` action id — park the sender as an `unverified` contact, **silently**: the requester is not notified and only learns if they message again; a later trust-requiring inbound re-fires the flow), and **block** (revoke the sender's channel and notify them their request was declined). Note the `unverified` contact left by "leave unverified" is not a guaranteed keep-out — it is still admitted under the permissive admission floors (`any_contact`, `strangers`); **block** (→ revoked) is the hard keep-out.
42
+ 4. **Guardian decides.** All decisions route through the guardian decision primitive (`applyGuardianDecision`, `approvals/guardian-decision-primitive.ts`) and commit via the gateway's `guardian_requests_decide` IPC op: the status CAS and the decision's ACL outcome execute in ONE gateway transaction, so an `approved` request can never exist without its ACL write. The introduction card supports four outcomes: **approve** (start the verification handshake), **trust** (activate directly, no code — used for workspace-vouched identities), **deny** (persist a terminal denial), and **block**.
43
43
  5. **On approval the gateway mints a verification session.** The decide op carries a `mint_outbound_session` outcome; inside the decide transaction the gateway (`gateway/src/verification/session-service.ts`) generates a 6-digit code, persists only its SHA-256 hash in `channel_verification_sessions` (identity-bound to the requester, `verificationPurpose: 'trusted_contact'`), and returns the raw secret to the daemon in the decide response for delivery.
44
44
  6. **The code is delivered.** The daemon delivers the code to the guardian's verified channel (ephemeral + DM on Slack shared channels so other members never see it). On Slack the code is also DM'd straight to the requester; on other channels the guardian relays it out-of-band (in person, text message, phone call). That out-of-band transfer is the trust anchor: it proves the requester has a real-world relationship with the guardian.
45
45
  7. **Requester enters the code** back to the assistant on the same channel. The **gateway** intercepts bare verification codes at ingress (`gateway/src/verification/text-verification.ts`) whenever an interceptable session exists for that channel — the daemon never sees verification code messages.
@@ -52,14 +52,14 @@ Design doc defining how unknown users gain access to a Vellum assistant via chan
52
52
  requested -> pending_guardian -> verification_pending -> active | denied | expired
53
53
  ```
54
54
 
55
- | State | Description | Store representation |
56
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57
- | `requested` | Unknown user messaged the assistant and was denied. The system records the access attempt. | No member record exists. The inbound is logged in `channel_inbound_events` (assistant DB). A notification signal is emitted via `emitNotificationSignal()`. |
58
- | `pending_guardian` | The guardian has been notified and a decision is pending. | A `guardian_requests` record (gateway DB) with `status: 'pending'`, `kind: 'access_request'`. |
59
- | `verification_pending` | The guardian approved. A verification session is active with a 6-digit code waiting for the requester to enter. | Gateway `channel_verification_sessions` record with `status: 'awaiting_response'`, identity-bound to the requester. The guardian request is `status: 'approved'`. |
60
- | `active` | The requester entered the correct code (or the guardian chose direct trust). They are now a trusted contact. | Gateway `contact_channels` record with `status: 'active'`, `policy: 'allow'`; identity mirrored to the assistant DB. The verification session is `status: 'consumed'`. |
61
- | `denied` | The guardian resolved the request without granting access — `leave_unverified` (park) or `block` (keep-out). | The guardian request has `status: 'denied'` for both. `leave_unverified` persists an `unverified` contact — a neutral park, so a later trust-requiring inbound **re-fires** the flow; `block` revokes the channel — a durable keep-out, so re-contact is suppressed. Suppression keys off the durable **contact status** (`revoked`/`blocked`), never this request status. |
62
- | `expired` | The guardian never responded (approval TTL elapsed) or the requester never entered the code (session TTL elapsed). | Guardian request: `status: 'expired'` (CAS-expired by the gateway via the daemon's expiry sweep). Verification session: expires naturally when `expiresAt < Date.now()`. |
55
+ | State | Description | Store representation |
56
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | `requested` | Unknown user messaged the assistant and was denied. The system records the access attempt. | No member record exists. The inbound is logged in `channel_inbound_events` (assistant DB). A notification signal is emitted via `emitNotificationSignal()`. |
58
+ | `pending_guardian` | The guardian has been notified and a decision is pending. | A `guardian_requests` record (gateway DB) with `status: 'pending'`, `kind: 'access_request'`. |
59
+ | `verification_pending` | The guardian approved. A verification session is active with a 6-digit code waiting for the requester to enter. | Gateway `channel_verification_sessions` record with `status: 'awaiting_response'`, identity-bound to the requester. The guardian request is `status: 'approved'`. |
60
+ | `active` | The requester entered the correct code (or the guardian chose direct trust). They are now a trusted contact. | Gateway `contact_channels` record with `status: 'active'`, `policy: 'allow'`; identity mirrored to the assistant DB. The verification session is `status: 'consumed'`. |
61
+ | `denied` | The guardian explicitly denied the request. | The guardian request has `status: 'denied'`. The sender is persisted as an unverified contact and later inbound is suppressed (terminal-deny). |
62
+ | `expired` | The guardian never responded (approval TTL elapsed) or the requester never entered the code (session TTL elapsed). | Guardian request: `status: 'expired'` (CAS-expired by the gateway via the daemon's expiry sweep). Verification session: expires naturally when `expiresAt < Date.now()`. |
63
63
 
64
64
  ## Identity Binding Rules
65
65
 
@@ -112,16 +112,7 @@ Identity binding ensures the verification code can only be consumed by the inten
112
112
  | -------------------------------------------------- | ------------------- | ------------------------------------------------------------- |
113
113
  | gateway `guardian-request-service.ts` (gateway DB) | `guardian_requests` | Updated to `status: 'denied'`, `decidedByExternalUserId` set. |
114
114
 
115
- No trusted-contact activation happens. The `leave_unverified` outcome persists the sender as an `unverified` contact **and sends no requester notification** (silent park); `block` instead revokes the channel and **does** notify the requester ("Your access request was declined.").
116
-
117
- The two outcomes differ on re-contact. Suppression of re-prompting keys off the **durable contact status**, not this `denied` request status:
118
-
119
- - `leave_unverified` → `unverified` contact: a neutral park, **not** kept out. If the contact later does something that needs trust — e.g. DMs on a `trusted_contacts` channel — the deny-path flow **re-fires** (self-verify challenge + a fresh guardian card), so the guardian decides afresh. The guardian's way to stop the prompts is to `block`.
120
- - `block` → `revoked` contact: a durable keep-out. Re-contact is suppressed (no challenge, no guardian notification) on every floor.
121
-
122
- The resolved approval card mirrors this distinction on every surface (in-app, Slack): a `leave_unverified` park reads as a neutral **"Left unverified"**, while `block` reads as **"Denied"**. Both share the `denied` request status, so the card presentation is keyed off the decided action, not the status (see `PARK_ACTION_SET` / `isParkAction` in `runtime/channel-approval-types.ts`).
123
-
124
- Separately, the admitted-mode introduction **nudge** (for a contact who cleared the floor unclassified) is quieted once the guardian has decided the contact, so a classified contact is not re-nudged across conversations. That is distinct from the deny-path re-fire above.
115
+ No trusted-contact activation happens. The sender is persisted as an unverified contact, and the terminal-deny check suppresses re-prompting the guardian for the same sender.
125
116
 
126
117
  ### Stage: `expired`
127
118
 
@@ -200,15 +191,10 @@ sequenceDiagram
200
191
  GW->>A: Forward with allow verdict
201
192
  A->>A: Process message normally
202
193
 
203
- else Guardian leaves unverified
204
- G->>A: Leave unverified (inline button / app / plain text)
205
- A->>A: Resolver seeds unverified contact (neutral park —<br/>a trust-requiring re-contact re-fires the flow)
206
- A-->>U: (No notification — user only learns<br/>if they message again)
207
-
208
- else Guardian blocks
209
- G->>A: Block
210
- A->>A: Resolver revokes the channel (durable keep-out —<br/>re-contact suppressed)
211
- A-->>U: "Your access request was declined."
194
+ else Guardian denies
195
+ G->>A: Deny (inline button / app / plain text)
196
+ A->>A: Resolver persists denial (terminal-deny)
197
+ A-->>U: (No notification — user only knows<br/>they were denied if they message again)
212
198
 
213
199
  else Guardian never responds
214
200
  Note over A: runGuardianExpirySweep()<br/>runs every 60 seconds
@@ -255,7 +241,7 @@ sequenceDiagram
255
241
 
256
242
  - If the unknown user messages the assistant multiple times before the guardian responds, each message hits the ACL denial path independently.
257
243
  - `notifyGuardianOfAccessRequest()` dedupes on the existing pending guardian request for the same (assistant, channel, requester), and the notification pipeline's `dedupeKey` prevents duplicate notification events.
258
- - A **durable keep-out** — a `revoked` or `blocked` contact — suppresses re-prompting entirely (`isKeptOutStatus(previousMemberStatus)`). A `leave_unverified` park (`unverified` contact) is **not** a keep-out and re-fires; only `block` stops the prompts. An approval whose verification window is still open also suppresses a fresh request (the sender is told to enter their code instead).
244
+ - A prior terminal deny suppresses re-prompting entirely, and an approval whose verification window is still open suppresses a fresh request (the sender is told to enter their code instead).
259
245
 
260
246
  ### Requester already has a member record in non-active state
261
247
 
@@ -17,7 +17,6 @@
17
17
  "./rpc": "./src/rpc.ts",
18
18
  "./attachment-naming": "./src/attachment-naming.ts",
19
19
  "./redacted-credential": "./src/redacted-credential.ts",
20
- "./secret-detection": "./src/secret-detection.ts",
21
20
  "./error": "./src/error.ts"
22
21
  },
23
22
  "scripts": {
@@ -109,77 +109,12 @@ export type RemoteWebPairingTokenResponse =
109
109
  // only) so both Node and browser callers share one implementation.
110
110
 
111
111
  /** Why a public base URL can't be advertised in a pairing challenge. */
112
- export type PublicBaseUrlRejection =
113
- | "unparseable"
114
- | "loopback"
115
- | "non-https"
116
- | "service-website";
112
+ export type PublicBaseUrlRejection = "unparseable" | "loopback" | "non-https";
117
113
 
118
114
  export type PublicBaseUrlResult =
119
115
  | { ok: true; url: string }
120
116
  | { ok: false; reason: PublicBaseUrlRejection };
121
117
 
122
- /**
123
- * Hosts that are a tunnel/ingress vendor's own website, not a user's assistant
124
- * endpoint. These are the tunnel vendors our docs mention, and their sites are
125
- * exactly where a lost user grabs a URL from — e.g. a Tailscale admin invite
126
- * link (`login.tailscale.com/admin/invite/…`), which is https and non-loopback
127
- * and so clears every other check. Pairing refuses them with a targeted message
128
- * rather than minting a challenge the scanning device can never reach.
129
- */
130
- export const TUNNEL_PROVIDER_WEBSITE_HOSTS = [
131
- "login.tailscale.com",
132
- "tailscale.com",
133
- "www.tailscale.com",
134
- "ngrok.com",
135
- "dashboard.ngrok.com",
136
- "dash.cloudflare.com",
137
- "cloudflare.com",
138
- "www.cloudflare.com",
139
- ] as const;
140
-
141
- /**
142
- * A URL whose exact host is a tunnel/ingress vendor's own website (see
143
- * {@link TUNNEL_PROVIDER_WEBSITE_HOSTS}). Exact-host only: a user's real
144
- * Tailscale endpoint (`*.ts.net`) or Cloudflare-fronted domain is never a
145
- * listed host, so a legitimate address is never mistaken for a vendor site.
146
- */
147
- export function isTunnelProviderWebsiteUrl(url: string): boolean {
148
- let hostname: string;
149
- try {
150
- // WHATWG URL lowercases the hostname during parsing.
151
- hostname = new URL(url).hostname;
152
- } catch {
153
- return false;
154
- }
155
- return (TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(
156
- hostname,
157
- );
158
- }
159
-
160
- /**
161
- * The display name of the tunnel/ingress vendor a service-website URL points
162
- * at (`"Tailscale"` / `"ngrok"` / `"Cloudflare"`), or null when the host is not
163
- * a known vendor site. Drives the "This is <Name>'s website" pairing guidance.
164
- */
165
- export function tunnelProviderWebsiteName(url: string): string | null {
166
- let hostname: string;
167
- try {
168
- hostname = new URL(url).hostname;
169
- } catch {
170
- return null;
171
- }
172
- if (
173
- !(TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(hostname)
174
- ) {
175
- return null;
176
- }
177
- if (hostname.includes("tailscale")) return "Tailscale";
178
- if (hostname.includes("ngrok")) return "ngrok";
179
- if (hostname.includes("cloudflare")) return "Cloudflare";
180
- return null;
181
- }
182
-
183
118
  /**
184
119
  * A loopback URL — `localhost`, `[::1]`, or `127.x.x.x`. A pairing link that
185
120
  * encodes a loopback address is unreachable from the scanning device.
@@ -232,9 +167,6 @@ export function resolvePublicBaseUrl(raw: string): PublicBaseUrlResult {
232
167
  if (isLoopbackPublicUrl(normalized)) {
233
168
  return { ok: false, reason: "loopback" };
234
169
  }
235
- if (isTunnelProviderWebsiteUrl(normalized)) {
236
- return { ok: false, reason: "service-website" };
237
- }
238
170
  if (new URL(normalized).protocol !== "https:") {
239
171
  return { ok: false, reason: "non-https" };
240
172
  }
@@ -17,7 +17,6 @@
17
17
  "./rpc": "./src/rpc.ts",
18
18
  "./attachment-naming": "./src/attachment-naming.ts",
19
19
  "./redacted-credential": "./src/redacted-credential.ts",
20
- "./secret-detection": "./src/secret-detection.ts",
21
20
  "./error": "./src/error.ts"
22
21
  },
23
22
  "scripts": {
@@ -109,77 +109,12 @@ export type RemoteWebPairingTokenResponse =
109
109
  // only) so both Node and browser callers share one implementation.
110
110
 
111
111
  /** Why a public base URL can't be advertised in a pairing challenge. */
112
- export type PublicBaseUrlRejection =
113
- | "unparseable"
114
- | "loopback"
115
- | "non-https"
116
- | "service-website";
112
+ export type PublicBaseUrlRejection = "unparseable" | "loopback" | "non-https";
117
113
 
118
114
  export type PublicBaseUrlResult =
119
115
  | { ok: true; url: string }
120
116
  | { ok: false; reason: PublicBaseUrlRejection };
121
117
 
122
- /**
123
- * Hosts that are a tunnel/ingress vendor's own website, not a user's assistant
124
- * endpoint. These are the tunnel vendors our docs mention, and their sites are
125
- * exactly where a lost user grabs a URL from — e.g. a Tailscale admin invite
126
- * link (`login.tailscale.com/admin/invite/…`), which is https and non-loopback
127
- * and so clears every other check. Pairing refuses them with a targeted message
128
- * rather than minting a challenge the scanning device can never reach.
129
- */
130
- export const TUNNEL_PROVIDER_WEBSITE_HOSTS = [
131
- "login.tailscale.com",
132
- "tailscale.com",
133
- "www.tailscale.com",
134
- "ngrok.com",
135
- "dashboard.ngrok.com",
136
- "dash.cloudflare.com",
137
- "cloudflare.com",
138
- "www.cloudflare.com",
139
- ] as const;
140
-
141
- /**
142
- * A URL whose exact host is a tunnel/ingress vendor's own website (see
143
- * {@link TUNNEL_PROVIDER_WEBSITE_HOSTS}). Exact-host only: a user's real
144
- * Tailscale endpoint (`*.ts.net`) or Cloudflare-fronted domain is never a
145
- * listed host, so a legitimate address is never mistaken for a vendor site.
146
- */
147
- export function isTunnelProviderWebsiteUrl(url: string): boolean {
148
- let hostname: string;
149
- try {
150
- // WHATWG URL lowercases the hostname during parsing.
151
- hostname = new URL(url).hostname;
152
- } catch {
153
- return false;
154
- }
155
- return (TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(
156
- hostname,
157
- );
158
- }
159
-
160
- /**
161
- * The display name of the tunnel/ingress vendor a service-website URL points
162
- * at (`"Tailscale"` / `"ngrok"` / `"Cloudflare"`), or null when the host is not
163
- * a known vendor site. Drives the "This is <Name>'s website" pairing guidance.
164
- */
165
- export function tunnelProviderWebsiteName(url: string): string | null {
166
- let hostname: string;
167
- try {
168
- hostname = new URL(url).hostname;
169
- } catch {
170
- return null;
171
- }
172
- if (
173
- !(TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(hostname)
174
- ) {
175
- return null;
176
- }
177
- if (hostname.includes("tailscale")) return "Tailscale";
178
- if (hostname.includes("ngrok")) return "ngrok";
179
- if (hostname.includes("cloudflare")) return "Cloudflare";
180
- return null;
181
- }
182
-
183
118
  /**
184
119
  * A loopback URL — `localhost`, `[::1]`, or `127.x.x.x`. A pairing link that
185
120
  * encodes a loopback address is unreachable from the scanning device.
@@ -232,9 +167,6 @@ export function resolvePublicBaseUrl(raw: string): PublicBaseUrlResult {
232
167
  if (isLoopbackPublicUrl(normalized)) {
233
168
  return { ok: false, reason: "loopback" };
234
169
  }
235
- if (isTunnelProviderWebsiteUrl(normalized)) {
236
- return { ok: false, reason: "service-website" };
237
- }
238
170
  if (new URL(normalized).protocol !== "https:") {
239
171
  return { ok: false, reason: "non-https" };
240
172
  }
@@ -17,7 +17,6 @@
17
17
  "./rpc": "./src/rpc.ts",
18
18
  "./attachment-naming": "./src/attachment-naming.ts",
19
19
  "./redacted-credential": "./src/redacted-credential.ts",
20
- "./secret-detection": "./src/secret-detection.ts",
21
20
  "./error": "./src/error.ts"
22
21
  },
23
22
  "scripts": {
@@ -109,77 +109,12 @@ export type RemoteWebPairingTokenResponse =
109
109
  // only) so both Node and browser callers share one implementation.
110
110
 
111
111
  /** Why a public base URL can't be advertised in a pairing challenge. */
112
- export type PublicBaseUrlRejection =
113
- | "unparseable"
114
- | "loopback"
115
- | "non-https"
116
- | "service-website";
112
+ export type PublicBaseUrlRejection = "unparseable" | "loopback" | "non-https";
117
113
 
118
114
  export type PublicBaseUrlResult =
119
115
  | { ok: true; url: string }
120
116
  | { ok: false; reason: PublicBaseUrlRejection };
121
117
 
122
- /**
123
- * Hosts that are a tunnel/ingress vendor's own website, not a user's assistant
124
- * endpoint. These are the tunnel vendors our docs mention, and their sites are
125
- * exactly where a lost user grabs a URL from — e.g. a Tailscale admin invite
126
- * link (`login.tailscale.com/admin/invite/…`), which is https and non-loopback
127
- * and so clears every other check. Pairing refuses them with a targeted message
128
- * rather than minting a challenge the scanning device can never reach.
129
- */
130
- export const TUNNEL_PROVIDER_WEBSITE_HOSTS = [
131
- "login.tailscale.com",
132
- "tailscale.com",
133
- "www.tailscale.com",
134
- "ngrok.com",
135
- "dashboard.ngrok.com",
136
- "dash.cloudflare.com",
137
- "cloudflare.com",
138
- "www.cloudflare.com",
139
- ] as const;
140
-
141
- /**
142
- * A URL whose exact host is a tunnel/ingress vendor's own website (see
143
- * {@link TUNNEL_PROVIDER_WEBSITE_HOSTS}). Exact-host only: a user's real
144
- * Tailscale endpoint (`*.ts.net`) or Cloudflare-fronted domain is never a
145
- * listed host, so a legitimate address is never mistaken for a vendor site.
146
- */
147
- export function isTunnelProviderWebsiteUrl(url: string): boolean {
148
- let hostname: string;
149
- try {
150
- // WHATWG URL lowercases the hostname during parsing.
151
- hostname = new URL(url).hostname;
152
- } catch {
153
- return false;
154
- }
155
- return (TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(
156
- hostname,
157
- );
158
- }
159
-
160
- /**
161
- * The display name of the tunnel/ingress vendor a service-website URL points
162
- * at (`"Tailscale"` / `"ngrok"` / `"Cloudflare"`), or null when the host is not
163
- * a known vendor site. Drives the "This is <Name>'s website" pairing guidance.
164
- */
165
- export function tunnelProviderWebsiteName(url: string): string | null {
166
- let hostname: string;
167
- try {
168
- hostname = new URL(url).hostname;
169
- } catch {
170
- return null;
171
- }
172
- if (
173
- !(TUNNEL_PROVIDER_WEBSITE_HOSTS as readonly string[]).includes(hostname)
174
- ) {
175
- return null;
176
- }
177
- if (hostname.includes("tailscale")) return "Tailscale";
178
- if (hostname.includes("ngrok")) return "ngrok";
179
- if (hostname.includes("cloudflare")) return "Cloudflare";
180
- return null;
181
- }
182
-
183
118
  /**
184
119
  * A loopback URL — `localhost`, `[::1]`, or `127.x.x.x`. A pairing link that
185
120
  * encodes a loopback address is unreachable from the scanning device.
@@ -232,9 +167,6 @@ export function resolvePublicBaseUrl(raw: string): PublicBaseUrlResult {
232
167
  if (isLoopbackPublicUrl(normalized)) {
233
168
  return { ok: false, reason: "loopback" };
234
169
  }
235
- if (isTunnelProviderWebsiteUrl(normalized)) {
236
- return { ok: false, reason: "service-website" };
237
- }
238
170
  if (new URL(normalized).protocol !== "https:") {
239
171
  return { ok: false, reason: "non-https" };
240
172
  }
package/openapi.yaml CHANGED
@@ -3,7 +3,7 @@
3
3
  openapi: 3.1.0
4
4
  info:
5
5
  title: Vellum Assistant API
6
- version: 0.10.12
6
+ version: 0.10.11
7
7
  description: Auto-generated OpenAPI specification for the Vellum Assistant runtime HTTP server.
8
8
  servers:
9
9
  - url: http://127.0.0.1:7821
@@ -17480,8 +17480,8 @@ paths:
17480
17480
  summary: Create a memory by remembering a fact
17481
17481
  description:
17482
17482
  Append a user-authored fact to the memory buffer via handleRemember. The fact surfaces in the memory graph
17483
- immediately as a pending node (its id is returned so clients can navigate to it), and a consolidation run is
17484
- nudged (deduped, backoff-respecting) so it files into concept pages promptly.
17483
+ immediately as a pending node, and a consolidation run is nudged (deduped, backoff-respecting) so it files into
17484
+ concept pages promptly.
17485
17485
  tags:
17486
17486
  - memory
17487
17487
  requestBody:
@@ -17507,11 +17507,6 @@ paths:
17507
17507
  type: string
17508
17508
  success:
17509
17509
  type: boolean
17510
- pendingNodeId:
17511
- description:
17512
- Graph node id (`buffer:<hash>`) of the pending entry this create appended, for fly-to-node navigation.
17513
- Absent when the buffer can't be re-read.
17514
- type: string
17515
17510
  required:
17516
17511
  - message
17517
17512
  - success
@@ -19356,12 +19351,6 @@ paths:
19356
19351
  - low
19357
19352
  - medium
19358
19353
  - high
19359
- bypassSecretCheck:
19360
- description:
19361
- When true, skip the secret-ingress scan for this message only. Set exclusively when the user explicitly
19362
- confirms a client-side blocked send (the composer's "Send anyway" action); it is per-message and
19363
- never persisted.
19364
- type: boolean
19365
19354
  hidden:
19366
19355
  description:
19367
19356
  "When true, persist the user message but suppress it from the UI transcript (it stays in LLM-side history
@@ -29407,12 +29396,6 @@ paths:
29407
29396
  description:
29408
29397
  Guardian-facing reply from the resolver (e.g. verification code for access-request approvals). Present only
29409
29398
  when applied is true and the resolver produced a reply.
29410
- decidedAction:
29411
- type: string
29412
- description:
29413
- The action to present on the resolved card — the resolved outcome, not necessarily the raw button (an
29414
- access-request 'reject' resolves to the 'leave_unverified' park). Present only when applied is
29415
- true; lets a client completing the card optimistically render the correct tone.
29416
29399
  required:
29417
29400
  - ok
29418
29401
  additionalProperties: false
@@ -32459,10 +32442,8 @@ components:
32459
32442
  anyOf:
32460
32443
  - type: object
32461
32444
  properties:
32462
- provider:
32463
- type: string
32464
- model:
32465
- type: string
32445
+ mode:
32446
+ $ref: "#/components/schemas/ServiceMode"
32466
32447
  additionalProperties: {}
32467
32448
  - type: "null"
32468
32449
  inference:
@@ -33273,10 +33254,8 @@ components:
33273
33254
  image-generation:
33274
33255
  type: object
33275
33256
  properties:
33276
- provider:
33277
- type: string
33278
- model:
33279
- type: string
33257
+ mode:
33258
+ $ref: "#/components/schemas/ServiceMode"
33280
33259
  additionalProperties: {}
33281
33260
  inference:
33282
33261
  type: object
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.10.12-dev.202607250047.75b9ec6",
3
+ "version": "0.10.12-staging.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -2,7 +2,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import { VellumAcpClientHandler } from "../acp/client-handler.js";
4
4
  import { AcpSessionManager } from "../acp/session-manager.js";
5
- import type { AssistantEvent } from "../daemon/message-protocol.js";
5
+ import type { ServerMessage } from "../daemon/message-protocol.js";
6
6
  import * as pendingInteractions from "../runtime/pending-interactions.js";
7
7
 
8
8
  // ---------------------------------------------------------------------------
@@ -10,8 +10,8 @@ import * as pendingInteractions from "../runtime/pending-interactions.js";
10
10
  // ---------------------------------------------------------------------------
11
11
 
12
12
  describe("VellumAcpClientHandler", () => {
13
- let sent: AssistantEvent[];
14
- let sendToVellum: (msg: AssistantEvent) => void;
13
+ let sent: ServerMessage[];
14
+ let sendToVellum: (msg: ServerMessage) => void;
15
15
  let handler: VellumAcpClientHandler;
16
16
 
17
17
  beforeEach(() => {
@@ -11,7 +11,7 @@ import { Minimatch } from "minimatch";
11
11
  import { CompactionCircuit } from "../agent/compaction-circuit.js";
12
12
  import type { AgentEvent } from "../agent/loop.js";
13
13
  import type { ConfirmationStateChangedEvent } from "../api/events/confirmation-state-changed.js";
14
- import type { AssistantEvent } from "../daemon/message-protocol.js";
14
+ import type { ServerMessage } from "../daemon/message-protocol.js";
15
15
  import type { Message, ProviderResponse } from "../providers/types.js";
16
16
  import type { ConfirmationDetails } from "../runtime/pending-interactions.js";
17
17
 
@@ -188,7 +188,7 @@ function makeProvider() {
188
188
  }
189
189
 
190
190
  function makeConversation(
191
- sendToClient?: (msg: AssistantEvent) => void,
191
+ sendToClient?: (msg: ServerMessage) => void,
192
192
  conversationId = CONV_ID,
193
193
  ): Conversation {
194
194
  return new Conversation(
@@ -257,7 +257,7 @@ beforeEach(() => {
257
257
 
258
258
  describe("approval cascading", () => {
259
259
  test("allow (one-time) does NOT cascade", () => {
260
- const emitted: AssistantEvent[] = [];
260
+ const emitted: ServerMessage[] = [];
261
261
  const conversationObj = makeConversation(
262
262
  (msg) => emitted.push(msg),
263
263
  CONV_ID,
@@ -291,7 +291,7 @@ describe("approval cascading", () => {
291
291
  });
292
292
 
293
293
  test("deny (one-time) does NOT cascade", () => {
294
- const emitted: AssistantEvent[] = [];
294
+ const emitted: ServerMessage[] = [];
295
295
  const conversationObj = makeConversation(
296
296
  (msg) => emitted.push(msg),
297
297
  CONV_ID,
@@ -325,7 +325,7 @@ describe("approval cascading", () => {
325
325
  });
326
326
 
327
327
  test("already-resolved request handled gracefully", () => {
328
- const emitted: AssistantEvent[] = [];
328
+ const emitted: ServerMessage[] = [];
329
329
  const conversationObj = makeConversation(
330
330
  (msg) => emitted.push(msg),
331
331
  CONV_ID,
@@ -7,7 +7,7 @@
7
7
  import { beforeEach, describe, expect, mock, test } from "bun:test";
8
8
 
9
9
  import type { Conversation } from "../daemon/conversation.js";
10
- import type { AssistantEvent } from "../daemon/message-protocol.js";
10
+ import type { ServerMessage } from "../daemon/message-protocol.js";
11
11
  import type { SecretPromptResult } from "../permissions/secret-prompt-types.js";
12
12
 
13
13
  mock.module("../config/env.js", () => ({
@@ -123,7 +123,7 @@ function makeIdleSession(opts?: {
123
123
  runAgentLoop: async (
124
124
  _content: string,
125
125
  _messageId: string,
126
- options?: { onEvent?: (msg: AssistantEvent) => void },
126
+ options?: { onEvent?: (msg: ServerMessage) => void },
127
127
  ) => {
128
128
  const onEvent = options?.onEvent ?? (() => {});
129
129
  onEvent({ type: "assistant_text_delta", text: "Hello!" });
@@ -186,7 +186,7 @@ function makeConfirmationEmittingSession(opts?: {
186
186
  runAgentLoop: async (
187
187
  _content: string,
188
188
  _messageId: string,
189
- options?: { onEvent?: (msg: AssistantEvent) => void },
189
+ options?: { onEvent?: (msg: ServerMessage) => void },
190
190
  ) => {
191
191
  const onEvent = options?.onEvent ?? (() => {});
192
192
  // Simulate PermissionPrompter.prompt(): self-register in pendingInteractions