@vellumai/assistant 0.10.2-dev.202606250318.5e7cfb0 → 0.10.2

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 (430) hide show
  1. package/bun.lock +0 -20
  2. package/docs/workspace-tools.md +33 -42
  3. package/eslint-rules/cli-no-daemon-internals.js +0 -6
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +0 -31
  5. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +0 -44
  6. package/node_modules/@vellumai/gateway-client/src/index.ts +0 -14
  7. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +0 -17
  8. package/node_modules/@vellumai/service-contracts/package.json +0 -1
  9. package/node_modules/@vellumai/service-contracts/src/index.ts +0 -1
  10. package/openapi.yaml +0 -155
  11. package/package.json +1 -4
  12. package/scripts/test.sh +15 -36
  13. package/src/__tests__/actor-token-service.test.ts +14 -36
  14. package/src/__tests__/agent-loop-override-profile.test.ts +0 -1
  15. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -2
  16. package/src/__tests__/agent-wake-override-profile.test.ts +0 -2
  17. package/src/__tests__/annotate-activity-metadata.test.ts +0 -2
  18. package/src/__tests__/annotate-risk-options.test.ts +0 -2
  19. package/src/__tests__/approval-cascade.test.ts +0 -2
  20. package/src/__tests__/assistant-attachments.test.ts +0 -42
  21. package/src/__tests__/background-workers-disk-pressure.test.ts +0 -2
  22. package/src/__tests__/btw-routes.test.ts +0 -2
  23. package/src/__tests__/build-persisted-content.test.ts +0 -2
  24. package/src/__tests__/call-controller.test.ts +0 -19
  25. package/src/__tests__/channel-guardian.test.ts +58 -94
  26. package/src/__tests__/channel-reply-delivery.test.ts +0 -2
  27. package/src/__tests__/compaction-events.test.ts +0 -2
  28. package/src/__tests__/compaction.benchmark.test.ts +0 -2
  29. package/src/__tests__/compactor-call-site-logging.test.ts +0 -2
  30. package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -2
  31. package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -2
  32. package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -2
  33. package/src/__tests__/compactor-web-search-strip.test.ts +0 -2
  34. package/src/__tests__/config-loader-backfill.test.ts +10 -123
  35. package/src/__tests__/config-schema.test.ts +0 -1
  36. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +29 -31
  37. package/src/__tests__/contacts-relay-reads.test.ts +15 -13
  38. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -2
  39. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +0 -2
  40. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +0 -2
  41. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  42. package/src/__tests__/conversation-agent-loop.test.ts +0 -134
  43. package/src/__tests__/conversation-analysis-routes.test.ts +0 -2
  44. package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -2
  45. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -2
  46. package/src/__tests__/conversation-history-web-search.test.ts +0 -2
  47. package/src/__tests__/conversation-load-history-repair.test.ts +0 -2
  48. package/src/__tests__/conversation-load-history-stripped.test.ts +0 -2
  49. package/src/__tests__/conversation-pairing.test.ts +0 -2
  50. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -2
  51. package/src/__tests__/conversation-process-callsite.test.ts +0 -2
  52. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -2
  53. package/src/__tests__/conversation-queue.test.ts +0 -91
  54. package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -14
  55. package/src/__tests__/conversation-routes-slash-commands.test.ts +0 -14
  56. package/src/__tests__/conversation-slash-queue.test.ts +0 -2
  57. package/src/__tests__/conversation-slash-unknown.test.ts +0 -2
  58. package/src/__tests__/conversation-speed-override.test.ts +0 -2
  59. package/src/__tests__/conversation-surfaces-task-progress.test.ts +0 -29
  60. package/src/__tests__/conversation-title-service.test.ts +0 -2
  61. package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -47
  62. package/src/__tests__/conversation-usage.test.ts +0 -2
  63. package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -2
  64. package/src/__tests__/conversation-workspace-injection.test.ts +0 -2
  65. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -2
  66. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  67. package/src/__tests__/db-migration-rollback.test.ts +171 -205
  68. package/src/__tests__/db-test-helpers.ts +4 -5
  69. package/src/__tests__/deterministic-verification-control-plane.test.ts +2 -4
  70. package/src/__tests__/disk-pressure-guard.test.ts +0 -41
  71. package/src/__tests__/dm-persistence.test.ts +0 -2
  72. package/src/__tests__/emit-signal-routing-intent.test.ts +5 -10
  73. package/src/__tests__/events-dev-bypass-actor.test.ts +1 -7
  74. package/src/__tests__/exploration-drift-hook.test.ts +2 -3
  75. package/src/__tests__/filing-service.test.ts +0 -2
  76. package/src/__tests__/guardian-binding-drift-heal.test.ts +10 -75
  77. package/src/__tests__/guardian-dispatch.test.ts +1 -95
  78. package/src/__tests__/guardian-outbound-http.test.ts +0 -13
  79. package/src/__tests__/heartbeat-disk-pressure.test.ts +0 -2
  80. package/src/__tests__/heartbeat-service.test.ts +0 -2
  81. package/src/__tests__/helpers/channel-test-adapter.ts +7 -1
  82. package/src/__tests__/host-app-control-routes.test.ts +30 -24
  83. package/src/__tests__/host-bash-routes.test.ts +41 -31
  84. package/src/__tests__/host-browser-routes.test.ts +32 -26
  85. package/src/__tests__/host-cu-routes-targeted.test.ts +33 -25
  86. package/src/__tests__/host-file-routes-targeted.test.ts +52 -40
  87. package/src/__tests__/host-transfer-routes-targeted.test.ts +43 -31
  88. package/src/__tests__/http-user-message-parity.test.ts +8 -290
  89. package/src/__tests__/inbound-invite-redemption.test.ts +0 -28
  90. package/src/__tests__/inbound-slack-persistence.test.ts +0 -2
  91. package/src/__tests__/invite-redemption-service.test.ts +0 -198
  92. package/src/__tests__/llm-context-normalization.test.ts +0 -105
  93. package/src/__tests__/llm-request-log-error-payload.test.ts +9 -71
  94. package/src/__tests__/llm-usage-store.test.ts +0 -25
  95. package/src/__tests__/mcp-health-check.test.ts +1 -2
  96. package/src/__tests__/media-stream-server-integration.test.ts +0 -127
  97. package/src/__tests__/memory-retrieval-hook.test.ts +0 -2
  98. package/src/__tests__/messaging-send-tool.test.ts +0 -2
  99. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  100. package/src/__tests__/mtime-cache.test.ts +5 -146
  101. package/src/__tests__/native-web-search.test.ts +0 -2
  102. package/src/__tests__/non-member-access-request.test.ts +17 -189
  103. package/src/__tests__/notification-broadcaster.test.ts +0 -4
  104. package/src/__tests__/notification-decision-recipient-context.test.ts +32 -33
  105. package/src/__tests__/notification-deep-link.test.ts +0 -6
  106. package/src/__tests__/notification-guardian-path.test.ts +0 -19
  107. package/src/__tests__/openai-provider.test.ts +12 -22
  108. package/src/__tests__/openai-responses-provider.test.ts +2 -12
  109. package/src/__tests__/outbound-slack-persistence.test.ts +0 -2
  110. package/src/__tests__/pending-interactions-resolved-event.test.ts +4 -7
  111. package/src/__tests__/persistence-secret-redaction.test.ts +0 -2
  112. package/src/__tests__/plugin-bootstrap.test.ts +73 -3
  113. package/src/__tests__/plugin-route-contribution.test.ts +17 -4
  114. package/src/__tests__/plugin-tool-contribution.test.ts +18 -3
  115. package/src/__tests__/plugin-types.test.ts +2 -0
  116. package/src/__tests__/process-message-background-slack.test.ts +0 -2
  117. package/src/__tests__/process-message-display-content.test.ts +0 -2
  118. package/src/__tests__/provider-error-scenarios.test.ts +4 -5
  119. package/src/__tests__/provider-usage-tracking.test.ts +0 -39
  120. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +0 -2
  121. package/src/__tests__/registry.test.ts +1 -4
  122. package/src/__tests__/relay-server.test.ts +25 -694
  123. package/src/__tests__/runtime-attachment-metadata.test.ts +1 -0
  124. package/src/__tests__/secret-ingress-http.test.ts +0 -14
  125. package/src/__tests__/send-endpoint-busy.test.ts +8 -30
  126. package/src/__tests__/skills.test.ts +0 -44
  127. package/src/__tests__/slack-inbound-verification.test.ts +2 -47
  128. package/src/__tests__/stt-hints.test.ts +13 -44
  129. package/src/__tests__/subagent-detail.test.ts +0 -27
  130. package/src/__tests__/subagent-disposal.test.ts +0 -65
  131. package/src/__tests__/subagent-notify-parent.test.ts +0 -2
  132. package/src/__tests__/subagent-role-registry.test.ts +2 -7
  133. package/src/__tests__/subagent-spawn-tool-fork.test.ts +0 -2
  134. package/src/__tests__/subagent-tools.test.ts +0 -2
  135. package/src/__tests__/suggestion-routes.test.ts +0 -2
  136. package/src/__tests__/title-generate-hook.test.ts +0 -2
  137. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -2
  138. package/src/__tests__/tool-executor.test.ts +11 -16
  139. package/src/__tests__/tool-preview-lifecycle.test.ts +0 -2
  140. package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -2
  141. package/src/__tests__/tool-start-timestamp.test.ts +0 -2
  142. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +10 -10
  143. package/src/__tests__/twilio-routes.test.ts +0 -96
  144. package/src/__tests__/ui-file-upload-surface.test.ts +0 -86
  145. package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
  146. package/src/__tests__/voice-invite-redemption.test.ts +0 -33
  147. package/src/__tests__/web-search-backend-failure.test.ts +0 -2
  148. package/src/__tests__/workspace-migration-remove-hooks.test.ts +35 -14
  149. package/src/__tests__/workspace-tool-loader.test.ts +2 -195
  150. package/src/__tests__/workspace-tools-watcher-flag.test.ts +70 -0
  151. package/src/agent/loop.ts +0 -56
  152. package/src/api/index.ts +1 -19
  153. package/src/api/responses/llm-request-log-entry.ts +0 -29
  154. package/src/api/responses/subagent-detail.ts +0 -17
  155. package/src/api/surfaces.ts +3 -39
  156. package/src/approvals/guardian-request-resolvers.ts +11 -1
  157. package/src/calls/__tests__/relay-setup-router.test.ts +4 -262
  158. package/src/calls/call-domain.ts +3 -3
  159. package/src/calls/guardian-dispatch.ts +8 -10
  160. package/src/calls/inbound-trust-reader.ts +1 -17
  161. package/src/calls/media-stream-server.ts +0 -21
  162. package/src/calls/relay-server.ts +50 -167
  163. package/src/calls/relay-setup-router.ts +7 -37
  164. package/src/calls/relay-verification.ts +4 -4
  165. package/src/calls/stt-hints.ts +12 -9
  166. package/src/calls/twilio-routes.ts +4 -14
  167. package/src/channels/types.ts +20 -10
  168. package/src/cli/commands/__tests__/cache.test.ts +1 -8
  169. package/src/cli/commands/cache.ts +181 -194
  170. package/src/cli/commands/db/__tests__/repair.test.ts +5 -6
  171. package/src/cli/commands/db/status.ts +1 -37
  172. package/src/cli/commands/mcp.ts +218 -252
  173. package/src/cli/commands/memory/index.ts +0 -2
  174. package/src/cli/commands/plugins.ts +3 -75
  175. package/src/cli/lib/__tests__/install-from-github.test.ts +0 -102
  176. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +1 -160
  177. package/src/cli/lib/list-installed-plugins.ts +1 -179
  178. package/src/config/__tests__/sync-gated-profiles.test.ts +3 -11
  179. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +17 -27
  180. package/src/config/bundled-skills/contacts/tools/contact-search.ts +3 -13
  181. package/src/config/bundled-skills/subagent/SKILL.md +1 -1
  182. package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
  183. package/src/config/feature-flag-registry.json +13 -5
  184. package/src/config/loader.ts +5 -38
  185. package/src/config/schemas/__tests__/memory-v3.test.ts +0 -1
  186. package/src/config/schemas/memory-lifecycle.ts +0 -12
  187. package/src/config/schemas/memory-v3.ts +0 -7
  188. package/src/config/schemas/memory.ts +0 -4
  189. package/src/config/schemas/timeouts.ts +0 -8
  190. package/src/config/seed-inference-profiles.ts +11 -21
  191. package/src/config/skills.ts +5 -27
  192. package/src/config/sync-gated-profiles.ts +13 -12
  193. package/src/contacts/contacts-write.ts +0 -3
  194. package/src/daemon/assistant-attachments.ts +4 -27
  195. package/src/daemon/conversation-agent-loop.ts +0 -28
  196. package/src/daemon/conversation-process.ts +16 -35
  197. package/src/daemon/conversation-surfaces.ts +38 -111
  198. package/src/daemon/conversation-tool-setup.ts +16 -50
  199. package/src/daemon/conversation.ts +1 -13
  200. package/src/daemon/disk-pressure-guard.ts +2 -12
  201. package/src/daemon/event-loop-watchdog.ts +1 -28
  202. package/src/daemon/external-plugins-bootstrap.ts +34 -4
  203. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -25
  204. package/src/daemon/handlers/config-a2a.ts +14 -6
  205. package/src/daemon/handlers/config-channels.ts +22 -78
  206. package/src/daemon/handlers/conversations.ts +0 -77
  207. package/src/daemon/lifecycle.ts +0 -4
  208. package/src/daemon/mcp-reload-service.ts +0 -10
  209. package/src/daemon/memory-v2-startup.test.ts +0 -72
  210. package/src/daemon/memory-v2-startup.ts +19 -87
  211. package/src/daemon/message-types/conversations.ts +0 -2
  212. package/src/daemon/message-types/surfaces.ts +12 -12
  213. package/src/daemon/server.ts +4 -0
  214. package/src/daemon/shutdown-handlers.ts +0 -20
  215. package/src/daemon/tool-setup-types.ts +0 -9
  216. package/src/daemon/workspace-tools-watcher.ts +328 -0
  217. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  218. package/src/ipc/assistant-server.ts +2 -2
  219. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
  220. package/src/mcp/client.ts +1 -15
  221. package/src/mcp/mcp-auth-orchestrator.ts +1 -6
  222. package/src/mcp/mcp-oauth-provider.ts +8 -19
  223. package/src/memory/__tests__/memory-retrospective-job.test.ts +0 -8
  224. package/src/memory/conversation-crud.ts +0 -38
  225. package/src/memory/db-connection.ts +3 -22
  226. package/src/memory/db-init.ts +502 -36
  227. package/src/memory/db-singleton.ts +4 -6
  228. package/src/memory/jobs-worker.ts +0 -58
  229. package/src/memory/llm-request-log-store.ts +1 -26
  230. package/src/memory/llm-usage-store.ts +20 -48
  231. package/src/memory/memory-retrospective-job.ts +8 -9
  232. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +56 -130
  233. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  234. package/src/memory/migrations/registry.ts +573 -0
  235. package/src/memory/migrations/run-migrations.ts +6 -90
  236. package/src/memory/migrations/validate-migration-state.ts +66 -101
  237. package/src/memory/schema/conversations.ts +0 -9
  238. package/src/memory/schema/infrastructure.ts +0 -20
  239. package/src/memory/v2/__tests__/cli-command-store.test.ts +0 -25
  240. package/src/memory/v2/__tests__/skill-store.test.ts +0 -80
  241. package/src/memory/v2/cli-command-store.ts +38 -75
  242. package/src/memory/v2/prompts/consolidation.ts +82 -13
  243. package/src/memory/v2/prompts/router.ts +93 -21
  244. package/src/memory/v2/skill-store.ts +31 -68
  245. package/src/notifications/__tests__/broadcaster.test.ts +8 -16
  246. package/src/notifications/__tests__/decision-engine.test.ts +9 -78
  247. package/src/notifications/broadcaster.ts +1 -8
  248. package/src/notifications/decision-engine.ts +7 -15
  249. package/src/notifications/destination-resolver.ts +24 -68
  250. package/src/notifications/emit-signal.ts +14 -39
  251. package/src/permissions/question-prompter.test.ts +1 -1
  252. package/src/permissions/question-prompter.ts +4 -7
  253. package/src/plugin-api/index.ts +6 -6
  254. package/src/plugin-api/types.ts +5 -3
  255. package/src/plugin-api/vision-support.test.ts +4 -28
  256. package/src/plugin-api/vision-support.ts +31 -66
  257. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -161
  258. package/src/plugins/defaults/advisor/consult.ts +6 -110
  259. package/src/plugins/defaults/advisor/steering.ts +2 -14
  260. package/src/plugins/defaults/advisor/tools/advisor.ts +5 -32
  261. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +1 -2
  262. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +7 -47
  263. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +11 -10
  264. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +20 -12
  265. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +11 -42
  266. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +3 -33
  267. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +4 -48
  268. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +8 -4
  269. package/src/plugins/defaults/memory-v3-shadow/injector.ts +15 -43
  270. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +2 -11
  271. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +13 -77
  272. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +11 -12
  273. package/src/plugins/mtime-cache.ts +291 -76
  274. package/src/plugins/pipeline.ts +13 -111
  275. package/src/plugins/types.ts +2 -0
  276. package/src/providers/anthropic/client.ts +0 -5
  277. package/src/providers/call-site-routing.ts +0 -4
  278. package/src/providers/model-catalog.ts +0 -16
  279. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  280. package/src/providers/openai/chat-completions-provider.ts +83 -37
  281. package/src/providers/openai/responses-provider.ts +46 -50
  282. package/src/providers/openrouter/client.ts +0 -5
  283. package/src/providers/provider-send-message.ts +0 -4
  284. package/src/providers/ratelimit.ts +0 -4
  285. package/src/providers/retry.ts +0 -4
  286. package/src/providers/types.ts +0 -9
  287. package/src/providers/usage-tracking.ts +0 -4
  288. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +3 -335
  289. package/src/runtime/access-request-helper.ts +39 -19
  290. package/src/runtime/actor-trust-resolver.ts +2 -2
  291. package/src/runtime/assistant-event-hub.ts +1 -1
  292. package/src/runtime/assistant-stream-state.ts +2 -9
  293. package/src/runtime/auth/require-bound-guardian.ts +11 -21
  294. package/src/runtime/channel-verification-service.ts +31 -56
  295. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  296. package/src/runtime/guardian-vellum-migration.ts +7 -66
  297. package/src/runtime/invite-redemption-service.ts +187 -198
  298. package/src/runtime/local-actor-identity.ts +11 -76
  299. package/src/runtime/pending-interactions.ts +1 -11
  300. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +5 -56
  301. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  302. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +0 -187
  303. package/src/runtime/routes/browser-routes.ts +1 -1
  304. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +5 -13
  305. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  306. package/src/runtime/routes/contact-routes.ts +32 -8
  307. package/src/runtime/routes/conversation-cli-routes.ts +5 -4
  308. package/src/runtime/routes/conversation-list-routes.ts +7 -4
  309. package/src/runtime/routes/conversation-query-routes.ts +0 -72
  310. package/src/runtime/routes/conversation-routes.ts +85 -84
  311. package/src/runtime/routes/events-routes.ts +2 -2
  312. package/src/runtime/routes/global-search-routes.ts +1 -3
  313. package/src/runtime/routes/guardian-action-routes.ts +5 -4
  314. package/src/runtime/routes/host-app-control-routes.ts +4 -5
  315. package/src/runtime/routes/host-bash-routes.ts +4 -5
  316. package/src/runtime/routes/host-browser-routes.ts +11 -9
  317. package/src/runtime/routes/host-cu-routes.ts +4 -5
  318. package/src/runtime/routes/host-file-routes.ts +4 -5
  319. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  320. package/src/runtime/routes/http-adapter.ts +1 -1
  321. package/src/runtime/routes/identity-routes.ts +2 -3
  322. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  323. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +5 -97
  324. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +49 -61
  325. package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -16
  326. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  327. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +8 -21
  328. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +3 -14
  329. package/src/runtime/routes/index.ts +0 -2
  330. package/src/runtime/routes/llm-context-normalization.ts +0 -83
  331. package/src/runtime/routes/mcp-auth-routes.ts +19 -171
  332. package/src/runtime/routes/migration-rollback-routes.ts +3 -4
  333. package/src/runtime/routes/migration-routes.ts +1 -4
  334. package/src/runtime/routes/subagents-routes.ts +0 -5
  335. package/src/runtime/routes/surface-action-routes.ts +56 -42
  336. package/src/runtime/services/__tests__/conversation-serializer.test.ts +0 -1
  337. package/src/runtime/services/conversation-serializer.ts +9 -7
  338. package/src/runtime/tool-grant-request-helper.ts +3 -3
  339. package/src/runtime/trust-verdict-consumer.ts +9 -85
  340. package/src/runtime/verification-outbound-actions.ts +18 -18
  341. package/src/signals/user-message.ts +0 -16
  342. package/src/subagent/manager.ts +0 -9
  343. package/src/subagent/types.ts +3 -3
  344. package/src/telemetry/types.ts +1 -34
  345. package/src/telemetry/usage-telemetry-reporter.test.ts +2 -3
  346. package/src/telemetry/usage-telemetry-reporter.ts +3 -87
  347. package/src/tools/ask-question/ask-question-tool.test.ts +0 -29
  348. package/src/tools/ask-question/ask-question-tool.ts +0 -13
  349. package/src/tools/executor.ts +4 -4
  350. package/src/tools/registry.ts +0 -18
  351. package/src/tools/shared/filesystem/path-policy.ts +5 -12
  352. package/src/tools/tool-approval-handler.ts +1 -1
  353. package/src/tools/tool-defaults.ts +2 -9
  354. package/src/tools/tool-manifest.ts +0 -3
  355. package/src/tools/types.ts +2 -17
  356. package/src/tools/workspace-tools/loader.ts +244 -348
  357. package/src/util/errors.ts +1 -26
  358. package/src/util/platform.ts +0 -5
  359. package/src/workflows/library.test.ts +0 -140
  360. package/src/workflows/library.ts +28 -82
  361. package/src/workspace/migrations/017-seed-persona-dirs.ts +34 -3
  362. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +24 -3
  363. package/src/workspace/migrations/048-remove-workspace-hooks.ts +66 -14
  364. package/src/workspace/migrations/registry.ts +0 -2
  365. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +0 -91
  366. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +0 -48
  367. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +0 -28
  368. package/node_modules/@vellumai/service-contracts/src/channels.ts +0 -41
  369. package/src/__tests__/code-search-tool.test.ts +0 -585
  370. package/src/__tests__/guardian-expiry-notifier.test.ts +0 -282
  371. package/src/__tests__/mcp-config-secret-boundary.test.ts +0 -390
  372. package/src/__tests__/plugin-pipeline.test.ts +0 -96
  373. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +0 -102
  374. package/src/__tests__/steer-on-enqueue-question.test.ts +0 -181
  375. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +0 -208
  376. package/src/agent/loop-exclusive-tool.test.ts +0 -150
  377. package/src/api/constants/sse-replay.ts +0 -41
  378. package/src/api/events/conversation-notice.ts +0 -26
  379. package/src/approvals/guardian-channel-delivery.ts +0 -30
  380. package/src/approvals/guardian-expiry-notifier.ts +0 -148
  381. package/src/cli/commands/memory/__tests__/worker.test.ts +0 -302
  382. package/src/cli/commands/memory/worker.ts +0 -175
  383. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -143
  384. package/src/config/prune-seeded-callsite-defaults.ts +0 -110
  385. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +0 -129
  386. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +0 -312
  387. package/src/contacts/__tests__/member-write-relay.test.ts +0 -202
  388. package/src/contacts/guardian-delivery-reader.ts +0 -223
  389. package/src/contacts/member-write-relay.ts +0 -189
  390. package/src/daemon/conversation-notices.ts +0 -60
  391. package/src/daemon/handlers/__tests__/config-channels.test.ts +0 -225
  392. package/src/hooks/hook-loader.ts +0 -341
  393. package/src/mcp/mcp-header-store.ts +0 -134
  394. package/src/memory/__tests__/301-create-watchdog-events.test.ts +0 -110
  395. package/src/memory/__tests__/prompt-override.test.ts +0 -192
  396. package/src/memory/__tests__/watchdog-events-store.test.ts +0 -161
  397. package/src/memory/migrations/300-add-processing-started-at.ts +0 -30
  398. package/src/memory/migrations/301-create-watchdog-events.ts +0 -45
  399. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +0 -224
  400. package/src/memory/prompt-override.ts +0 -129
  401. package/src/memory/steps.ts +0 -573
  402. package/src/memory/watchdog-events-store.ts +0 -87
  403. package/src/memory/worker-control.ts +0 -118
  404. package/src/memory/worker-process.ts +0 -72
  405. package/src/notifications/__tests__/connected-channels.test.ts +0 -114
  406. package/src/notifications/__tests__/destination-resolver.test.ts +0 -256
  407. package/src/onboarding/checkin-event.test.ts +0 -222
  408. package/src/onboarding/checkin-event.ts +0 -321
  409. package/src/onboarding/schedule-checkin.ts +0 -190
  410. package/src/plugins/defaults/advisor/__tests__/context-pack-gating.test.ts +0 -106
  411. package/src/plugins/defaults/advisor/__tests__/context-pack.test.ts +0 -60
  412. package/src/plugins/defaults/advisor/context-pack.ts +0 -288
  413. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +0 -146
  414. package/src/plugins/surface-import.ts +0 -121
  415. package/src/providers/openai/__tests__/api-error-normalization.test.ts +0 -321
  416. package/src/providers/openai/api-error-normalization.ts +0 -270
  417. package/src/runtime/__tests__/channel-verification-service.test.ts +0 -133
  418. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -181
  419. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +0 -66
  420. package/src/runtime/__tests__/local-principal-trust.test.ts +0 -164
  421. package/src/runtime/anchored-guardian.test.ts +0 -156
  422. package/src/runtime/anchored-guardian.ts +0 -135
  423. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +0 -99
  424. package/src/runtime/local-principal-trust.ts +0 -52
  425. package/src/runtime/routes/__tests__/contact-routes.test.ts +0 -212
  426. package/src/runtime/routes/__tests__/global-search-routes.test.ts +0 -93
  427. package/src/runtime/routes/onboarding-checkin-routes.ts +0 -86
  428. package/src/tools/filesystem/search.ts +0 -543
  429. package/src/util/telemetry-db-path.ts +0 -24
  430. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +0 -134
@@ -1,312 +0,0 @@
1
- /**
2
- * Tests for the gateway-backed guardian delivery reader.
3
- *
4
- * Guardian binding is near-static, so the reader caches behind a minutes-scale
5
- * TTL, clears event-driven on invalidation, and coalesces concurrent cold-cache
6
- * reads single-flight. These tests pin the parse contract plus all three cache
7
- * behaviors (TTL hit, invalidation, single-flight) and the failure-no-poison
8
- * rule.
9
- */
10
-
11
- import { beforeEach, describe, expect, mock, test } from "bun:test";
12
-
13
- import type { GuardianDelivery } from "@vellumai/gateway-client";
14
-
15
- // ── Controllable IPC mock ────────────────────────────────────────────────────
16
-
17
- type IpcHandler = (params?: Record<string, unknown>) => unknown;
18
-
19
- const ipcHandlers = new Map<string, IpcHandler>();
20
- const ipcCallLog: Array<{
21
- method: string;
22
- params?: Record<string, unknown>;
23
- timeoutMs?: number;
24
- }> = [];
25
-
26
- mock.module("../../ipc/gateway-client.js", () => ({
27
- ipcCall: async (
28
- method: string,
29
- params?: Record<string, unknown>,
30
- timeoutMs?: number,
31
- ) => {
32
- ipcCallLog.push({ method, params, timeoutMs });
33
- const handler = ipcHandlers.get(method);
34
- return handler ? handler(params) : undefined;
35
- },
36
- ipcCallPersistent: async () => undefined,
37
- resetPersistentClient: () => {},
38
- }));
39
-
40
- import { emitContactChange } from "../contact-events.js";
41
- import {
42
- __resetGuardianDeliveryCacheForTest,
43
- anyGuardian,
44
- getGuardianDelivery,
45
- getGuardianDeliveryFresh,
46
- guardianForChannel,
47
- invalidateGuardianDeliveryCache,
48
- } from "../guardian-delivery-reader.js";
49
-
50
- const METHOD = "resolve_guardian_delivery";
51
-
52
- function countCalls(method: string): number {
53
- return ipcCallLog.filter((c) => c.method === method).length;
54
- }
55
-
56
- const telegramGuardian: GuardianDelivery = {
57
- channelType: "telegram",
58
- contactId: "contact-123",
59
- address: "@guardian",
60
- status: "active",
61
- };
62
-
63
- const emailGuardian: GuardianDelivery = {
64
- channelType: "email",
65
- contactId: "contact-456",
66
- address: "guardian@example.com",
67
- status: "active",
68
- };
69
-
70
- describe("getGuardianDelivery", () => {
71
- beforeEach(() => {
72
- __resetGuardianDeliveryCacheForTest();
73
- ipcHandlers.clear();
74
- ipcCallLog.length = 0;
75
- });
76
-
77
- test("returns the parsed guardian list", async () => {
78
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
79
-
80
- expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
81
- });
82
-
83
- test("bounds the IPC read with a short timeout", async () => {
84
- ipcHandlers.set(METHOD, () => ({ guardians: [] }));
85
-
86
- await getGuardianDelivery();
87
-
88
- const call = ipcCallLog.find((c) => c.method === METHOD);
89
- expect(call?.timeoutMs).toBe(2_000);
90
- });
91
-
92
- test("returns null when IPC transport fails (undefined)", async () => {
93
- ipcHandlers.set(METHOD, () => undefined);
94
- expect(await getGuardianDelivery()).toBeNull();
95
- });
96
-
97
- test("returns null when the IPC call throws", async () => {
98
- ipcHandlers.set(METHOD, () => {
99
- throw new Error("socket exploded");
100
- });
101
- expect(await getGuardianDelivery()).toBeNull();
102
- });
103
-
104
- test("returns null for a malformed response shape", async () => {
105
- ipcHandlers.set(METHOD, () => ({ guardians: "not-an-array" }));
106
- expect(await getGuardianDelivery()).toBeNull();
107
- });
108
-
109
- test("two calls within the TTL issue only ONE IPC call (cache hit)", async () => {
110
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
111
-
112
- await getGuardianDelivery();
113
- await getGuardianDelivery();
114
-
115
- expect(countCalls(METHOD)).toBe(1);
116
- });
117
-
118
- test("caches per channelTypes filter key", async () => {
119
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
120
-
121
- await getGuardianDelivery();
122
- await getGuardianDelivery({ channelTypes: ["telegram"] });
123
-
124
- // Distinct keys ("ALL" vs "telegram") miss each other → two IPC calls.
125
- expect(countCalls(METHOD)).toBe(2);
126
- });
127
-
128
- test("invalidateGuardianDeliveryCache() forces the next call to re-fetch", async () => {
129
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
130
-
131
- await getGuardianDelivery();
132
- invalidateGuardianDeliveryCache();
133
- await getGuardianDelivery();
134
-
135
- expect(countCalls(METHOD)).toBe(2);
136
- });
137
-
138
- test("a contact-change event clears the cache", async () => {
139
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
140
-
141
- await getGuardianDelivery();
142
- emitContactChange();
143
- await getGuardianDelivery();
144
-
145
- expect(countCalls(METHOD)).toBe(2);
146
- });
147
-
148
- test("a burst of concurrent cold-cache calls issues only ONE IPC call (single-flight)", async () => {
149
- let resolveIpc: ((value: unknown) => void) | undefined;
150
- ipcHandlers.set(
151
- METHOD,
152
- () =>
153
- new Promise((resolve) => {
154
- resolveIpc = resolve;
155
- }),
156
- );
157
-
158
- const burst = Promise.all([
159
- getGuardianDelivery(),
160
- getGuardianDelivery(),
161
- getGuardianDelivery(),
162
- ]);
163
- resolveIpc?.({ guardians: [telegramGuardian] });
164
- const results = await burst;
165
-
166
- expect(countCalls(METHOD)).toBe(1);
167
- expect(results).toEqual([
168
- [telegramGuardian],
169
- [telegramGuardian],
170
- [telegramGuardian],
171
- ]);
172
- });
173
-
174
- test("an invalidation DURING an in-flight fetch is not masked — the next call re-fetches", async () => {
175
- let resolveIpc: ((value: unknown) => void) | undefined;
176
- ipcHandlers.set(
177
- METHOD,
178
- () =>
179
- new Promise((resolve) => {
180
- resolveIpc = resolve;
181
- }),
182
- );
183
-
184
- // Start a cold fetch, invalidate before it resolves, then resolve it.
185
- const inFlight = getGuardianDelivery();
186
- invalidateGuardianDeliveryCache();
187
- resolveIpc?.({ guardians: [telegramGuardian] });
188
- expect(await inFlight).toEqual([telegramGuardian]);
189
-
190
- // The pre-invalidation result must NOT have been cached: the next read
191
- // issues a fresh IPC rather than serving the now-stale value.
192
- ipcHandlers.set(METHOD, () => ({ guardians: [emailGuardian] }));
193
- expect(await getGuardianDelivery()).toEqual([emailGuardian]);
194
- expect(countCalls(METHOD)).toBe(2);
195
- });
196
-
197
- test("a failure does NOT poison the cache — the next call retries", async () => {
198
- ipcHandlers.set(METHOD, () => undefined);
199
- expect(await getGuardianDelivery()).toBeNull();
200
-
201
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
202
- expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
203
- expect(countCalls(METHOD)).toBe(2);
204
- });
205
-
206
- test("fresh read ignores a stale cached entry and re-fetches", async () => {
207
- // Seed the cache with an empty list (the stale gateway-side view).
208
- ipcHandlers.set(METHOD, () => ({ guardians: [] }));
209
- expect(await getGuardianDelivery()).toEqual([]);
210
-
211
- // A cached read still serves the stale empty list (no new IPC)...
212
- expect(await getGuardianDelivery()).toEqual([]);
213
- expect(countCalls(METHOD)).toBe(1);
214
-
215
- // ...but a fresh read bypasses the cache and sees the now-present guardian.
216
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
217
- expect(await getGuardianDeliveryFresh()).toEqual([telegramGuardian]);
218
- expect(countCalls(METHOD)).toBe(2);
219
- });
220
-
221
- test("fresh read updates the cache with the fresh result", async () => {
222
- ipcHandlers.set(METHOD, () => ({ guardians: [] }));
223
- await getGuardianDelivery();
224
-
225
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
226
- await getGuardianDeliveryFresh();
227
-
228
- // A subsequent cached read serves the refreshed value without a new IPC.
229
- expect(await getGuardianDelivery()).toEqual([telegramGuardian]);
230
- expect(countCalls(METHOD)).toBe(2);
231
- });
232
-
233
- test("getGuardianDeliveryFresh bypasses a stale cached empty list", async () => {
234
- ipcHandlers.set(METHOD, () => ({ guardians: [] }));
235
- expect(
236
- await getGuardianDelivery({ channelTypes: ["telegram"] }),
237
- ).toEqual([]);
238
-
239
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
240
- expect(
241
- await getGuardianDeliveryFresh({ channelTypes: ["telegram"] }),
242
- ).toEqual([telegramGuardian]);
243
- expect(countCalls(METHOD)).toBe(2);
244
- });
245
-
246
- test("a burst of forceRefresh reads still coalesces single-flight", async () => {
247
- let resolveIpc: ((value: unknown) => void) | undefined;
248
- ipcHandlers.set(
249
- METHOD,
250
- () =>
251
- new Promise((resolve) => {
252
- resolveIpc = resolve;
253
- }),
254
- );
255
-
256
- const burst = Promise.all([
257
- getGuardianDeliveryFresh(),
258
- getGuardianDeliveryFresh(),
259
- getGuardianDeliveryFresh(),
260
- ]);
261
- resolveIpc?.({ guardians: [telegramGuardian] });
262
- await burst;
263
-
264
- expect(countCalls(METHOD)).toBe(1);
265
- });
266
-
267
- test("a fresh read does NOT coalesce with an in-flight non-force fetch (issues its own IPC)", async () => {
268
- // A normal read starts a fetch that will resolve to the pre-write empty
269
- // list and is still in flight when the fresh read arrives.
270
- let resolveStale: ((value: unknown) => void) | undefined;
271
- ipcHandlers.set(
272
- METHOD,
273
- () =>
274
- new Promise((resolve) => {
275
- resolveStale = resolve;
276
- }),
277
- );
278
- const stale = getGuardianDelivery();
279
-
280
- // The gateway-side write lands (not reflected in the in-flight fetch). The
281
- // fresh read must NOT reuse the stale in-flight promise — it issues its own
282
- // IPC observing the post-write guardian.
283
- ipcHandlers.set(METHOD, () => ({ guardians: [telegramGuardian] }));
284
- const fresh = await getGuardianDeliveryFresh();
285
- expect(fresh).toEqual([telegramGuardian]);
286
-
287
- // Release the stale fetch last; it must not have masked the fresh result.
288
- resolveStale?.({ guardians: [] });
289
- expect(await stale).toEqual([]);
290
- expect(countCalls(METHOD)).toBe(2);
291
- });
292
- });
293
-
294
- describe("selectors", () => {
295
- test("guardianForChannel picks the first active match for the type", () => {
296
- const inactive: GuardianDelivery = {
297
- ...telegramGuardian,
298
- contactId: "contact-999",
299
- status: "revoked",
300
- };
301
- const list = [inactive, telegramGuardian, emailGuardian];
302
-
303
- expect(guardianForChannel(list, "telegram")).toBe(telegramGuardian);
304
- expect(guardianForChannel(list, "email")).toBe(emailGuardian);
305
- expect(guardianForChannel(list, "phone")).toBeUndefined();
306
- });
307
-
308
- test("anyGuardian returns the first overall", () => {
309
- expect(anyGuardian([emailGuardian, telegramGuardian])).toBe(emailGuardian);
310
- expect(anyGuardian([])).toBeUndefined();
311
- });
312
- });
@@ -1,202 +0,0 @@
1
- /**
2
- * Tests for the gateway-first member-activation relay.
3
- *
4
- * activateMemberChannel writes the activated channel through the gateway
5
- * (source of truth) via `ipcCallPersistent("upsert_verified_channel", ...)`
6
- * first, then mirrors the activation to the assistant DB best-effort. A local
7
- * mirror failure is swallowed so the gateway-owned outcome stands; a gateway
8
- * refusal (verified:false) skips the local mirror entirely.
9
- */
10
-
11
- import { beforeEach, describe, expect, mock, test } from "bun:test";
12
-
13
- import type { ContactWriteResult } from "../types.js";
14
-
15
- type IpcCall = { method: string; params?: Record<string, unknown> };
16
-
17
- let ipcCalls: IpcCall[] = [];
18
- let ipcVerified = true;
19
- let ipcThrows = false;
20
-
21
- const ipcCallPersistentMock = mock(
22
- async (method: string, params?: Record<string, unknown>) => {
23
- ipcCalls.push({ method, params });
24
- if (ipcThrows) throw new Error("gateway unavailable");
25
- return {
26
- ok: true,
27
- verified: ipcVerified,
28
- channel: ipcVerified
29
- ? {
30
- id: "gw-ch1",
31
- contactId: (params?.contactId as string) ?? "gw-c1",
32
- type: (params?.type as string) ?? "telegram",
33
- address: (params?.address as string) ?? "addr",
34
- status: "active",
35
- verifiedAt: 1,
36
- verifiedVia: (params?.verifiedVia as string) ?? "invite",
37
- }
38
- : undefined,
39
- };
40
- },
41
- );
42
- const actualGatewayClient = await import("../../ipc/gateway-client.js");
43
- mock.module("../../ipc/gateway-client.js", () => ({
44
- ...actualGatewayClient,
45
- ipcCallPersistent: ipcCallPersistentMock,
46
- }));
47
-
48
- // Local-mirror primitive.
49
- const localResult: ContactWriteResult = {
50
- contact: { id: "c1" } as ContactWriteResult["contact"],
51
- channel: { id: "ch1", status: "active" } as ContactWriteResult["channel"],
52
- };
53
- let mirrorCallOrder = -1;
54
- const upsertContactChannelMock = mock(
55
- (_params: Record<string, unknown>): ContactWriteResult | null => {
56
- mirrorCallOrder = ipcCalls.length;
57
- return localResult;
58
- },
59
- );
60
- const actualContactsWrite = await import("../contacts-write.js");
61
- mock.module("../contacts-write.js", () => ({
62
- ...actualContactsWrite,
63
- upsertContactChannel: upsertContactChannelMock,
64
- }));
65
-
66
- const { activateMemberChannel } = await import("../member-write-relay.js");
67
-
68
- describe("activateMemberChannel gateway-first relay", () => {
69
- beforeEach(() => {
70
- ipcCalls = [];
71
- ipcVerified = true;
72
- ipcThrows = false;
73
- mirrorCallOrder = -1;
74
- ipcCallPersistentMock.mockClear();
75
- upsertContactChannelMock.mockClear();
76
- upsertContactChannelMock.mockImplementation(() => {
77
- mirrorCallOrder = ipcCalls.length;
78
- return localResult;
79
- });
80
- });
81
-
82
- test("relays to the gateway before mirroring locally, threading the target contact", async () => {
83
- const result = await activateMemberChannel({
84
- sourceChannel: "telegram",
85
- externalUserId: "user-1",
86
- externalChatId: "chat-1",
87
- displayName: "Mom",
88
- contactId: "target-mom",
89
- inviteId: "inv-1",
90
- verifiedVia: "invite",
91
- });
92
-
93
- expect(ipcCalls).toEqual([
94
- {
95
- method: "upsert_verified_channel",
96
- params: {
97
- type: "telegram",
98
- address: "user-1",
99
- externalChatId: "chat-1",
100
- displayName: "Mom",
101
- username: undefined,
102
- verifiedVia: "invite",
103
- contactId: "target-mom",
104
- allowRevokedReactivation: true,
105
- },
106
- },
107
- ]);
108
- // The local mirror ran AFTER the gateway relay.
109
- expect(mirrorCallOrder).toBe(1);
110
- expect(upsertContactChannelMock).toHaveBeenCalledTimes(1);
111
- expect(result).toEqual({
112
- status: "activated",
113
- memberId: "ch1",
114
- member: localResult,
115
- });
116
- });
117
-
118
- test("fails open and still mirrors locally when the gateway relay throws", async () => {
119
- ipcThrows = true;
120
-
121
- const result = await activateMemberChannel({
122
- sourceChannel: "telegram",
123
- externalUserId: "user-1",
124
- externalChatId: "chat-1",
125
- contactId: "target-mom",
126
- });
127
-
128
- expect(ipcCalls).toHaveLength(1);
129
- expect(upsertContactChannelMock).toHaveBeenCalledTimes(1);
130
- expect(result).toEqual({
131
- status: "activated",
132
- memberId: "ch1",
133
- member: localResult,
134
- });
135
- });
136
-
137
- test("returns the gateway channel id when the gateway verifies but the local mirror throws", async () => {
138
- upsertContactChannelMock.mockImplementation(() => {
139
- throw new Error("local mirror exploded");
140
- });
141
-
142
- const result = await activateMemberChannel({
143
- sourceChannel: "telegram",
144
- externalUserId: "user-1",
145
- externalChatId: "chat-1",
146
- });
147
-
148
- expect(ipcCalls).toHaveLength(1);
149
- // Gateway activation stands: the gateway channel id is returned even though
150
- // the best-effort local mirror produced no row.
151
- expect(result).toEqual({
152
- status: "activated",
153
- memberId: "gw-ch1",
154
- member: null,
155
- });
156
- });
157
-
158
- test("refuses when the gateway throws AND the local mirror yields no row", async () => {
159
- ipcThrows = true;
160
- upsertContactChannelMock.mockImplementation(() => {
161
- throw new Error("local mirror exploded");
162
- });
163
-
164
- const result = await activateMemberChannel({
165
- sourceChannel: "telegram",
166
- externalUserId: "user-1",
167
- externalChatId: "chat-1",
168
- });
169
-
170
- // No gateway channel (relay threw) and no local mirror: no stable id, so the
171
- // caller maps this to a non-redeemed outcome rather than crashing.
172
- expect(result).toEqual({ status: "refused" });
173
- });
174
-
175
- test("refuses the activation when the gateway denies the actor (verified:false)", async () => {
176
- ipcVerified = false;
177
-
178
- const result = await activateMemberChannel({
179
- sourceChannel: "telegram",
180
- externalUserId: "user-1",
181
- externalChatId: "chat-1",
182
- contactId: "target-mom",
183
- });
184
-
185
- expect(ipcCalls).toHaveLength(1);
186
- expect(upsertContactChannelMock).not.toHaveBeenCalled();
187
- expect(result).toEqual({ status: "refused" });
188
- });
189
-
190
- test("derives the address from externalChatId when no externalUserId is present", async () => {
191
- await activateMemberChannel({
192
- sourceChannel: "phone",
193
- externalChatId: "+15551234567",
194
- });
195
-
196
- expect(ipcCalls[0]?.params).toMatchObject({
197
- type: "phone",
198
- address: "+15551234567",
199
- externalChatId: "+15551234567",
200
- });
201
- });
202
- });