@vellumai/assistant 0.10.2 → 0.10.3-dev.202606251939.1e7d8ac

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 (545) hide show
  1. package/bun.lock +20 -0
  2. package/docs/workspace-tools.md +42 -33
  3. package/eslint-rules/cli-no-daemon-internals.js +6 -0
  4. package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-delivery-contract.test.ts +91 -0
  5. package/node_modules/@vellumai/gateway-client/src/__tests__/trust-verdict-contract.test.ts +31 -0
  6. package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +44 -0
  7. package/node_modules/@vellumai/gateway-client/src/guardian-delivery-contract.ts +48 -0
  8. package/node_modules/@vellumai/gateway-client/src/index.ts +14 -0
  9. package/node_modules/@vellumai/gateway-client/src/trust-verdict-contract.ts +17 -0
  10. package/node_modules/@vellumai/service-contracts/package.json +1 -0
  11. package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +28 -0
  12. package/node_modules/@vellumai/service-contracts/src/channels.ts +41 -0
  13. package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
  14. package/openapi.yaml +156 -46
  15. package/package.json +4 -1
  16. package/scripts/test.sh +36 -15
  17. package/src/__tests__/actor-token-service.test.ts +36 -14
  18. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +82 -31
  19. package/src/__tests__/agent-loop-override-profile.test.ts +1 -0
  20. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  21. package/src/__tests__/agent-wake-override-profile.test.ts +2 -0
  22. package/src/__tests__/annotate-activity-metadata.test.ts +2 -0
  23. package/src/__tests__/annotate-risk-options.test.ts +2 -0
  24. package/src/__tests__/approval-cascade.test.ts +2 -0
  25. package/src/__tests__/assistant-attachments.test.ts +42 -0
  26. package/src/__tests__/background-workers-disk-pressure.test.ts +2 -0
  27. package/src/__tests__/btw-routes.test.ts +2 -0
  28. package/src/__tests__/build-persisted-content.test.ts +2 -0
  29. package/src/__tests__/call-controller.test.ts +19 -0
  30. package/src/__tests__/channel-approval-routes.test.ts +21 -26
  31. package/src/__tests__/channel-delivery-store.test.ts +28 -0
  32. package/src/__tests__/channel-guardian.test.ts +164 -78
  33. package/src/__tests__/channel-inbound-disk-pressure.test.ts +11 -19
  34. package/src/__tests__/channel-reply-delivery.test.ts +2 -0
  35. package/src/__tests__/code-search-tool.test.ts +585 -0
  36. package/src/__tests__/compaction-events.test.ts +2 -0
  37. package/src/__tests__/compaction-ledger-store.test.ts +128 -0
  38. package/src/__tests__/compaction.benchmark.test.ts +2 -0
  39. package/src/__tests__/compactor-call-site-logging.test.ts +2 -0
  40. package/src/__tests__/compactor-low-watermark-cut.test.ts +2 -0
  41. package/src/__tests__/compactor-preserved-tail-count.test.ts +2 -0
  42. package/src/__tests__/compactor-summary-call-truncation.test.ts +2 -0
  43. package/src/__tests__/compactor-web-search-strip.test.ts +2 -0
  44. package/src/__tests__/config-loader-backfill.test.ts +123 -10
  45. package/src/__tests__/config-schema.test.ts +1 -0
  46. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +31 -29
  47. package/src/__tests__/consult-deadline.test.ts +60 -0
  48. package/src/__tests__/contact-store-interaction-info.test.ts +156 -0
  49. package/src/__tests__/contact-store-user-file.test.ts +7 -10
  50. package/src/__tests__/contacts-relay-reads.test.ts +19 -24
  51. package/src/__tests__/contacts-write.test.ts +0 -2
  52. package/src/__tests__/conversation-abort-tool-results.test.ts +2 -0
  53. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -0
  54. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
  55. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -0
  56. package/src/__tests__/conversation-agent-loop.test.ts +134 -0
  57. package/src/__tests__/conversation-analysis-routes.test.ts +2 -0
  58. package/src/__tests__/conversation-app-control-lifecycle.test.ts +2 -0
  59. package/src/__tests__/conversation-attention-telegram.test.ts +9 -11
  60. package/src/__tests__/conversation-confirmation-signals.test.ts +2 -0
  61. package/src/__tests__/conversation-fork-crud.test.ts +354 -24
  62. package/src/__tests__/conversation-history-web-search.test.ts +2 -0
  63. package/src/__tests__/conversation-load-history-repair.test.ts +2 -0
  64. package/src/__tests__/conversation-load-history-stripped.test.ts +2 -0
  65. package/src/__tests__/conversation-pairing.test.ts +2 -0
  66. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +2 -0
  67. package/src/__tests__/conversation-process-callsite.test.ts +2 -0
  68. package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -0
  69. package/src/__tests__/conversation-queue.test.ts +91 -0
  70. package/src/__tests__/conversation-routes-guardian-reply.test.ts +14 -0
  71. package/src/__tests__/conversation-routes-slash-commands.test.ts +14 -0
  72. package/src/__tests__/conversation-slash-queue.test.ts +2 -0
  73. package/src/__tests__/conversation-slash-unknown.test.ts +2 -0
  74. package/src/__tests__/conversation-speed-override.test.ts +2 -0
  75. package/src/__tests__/conversation-surfaces-task-progress.test.ts +29 -0
  76. package/src/__tests__/conversation-title-service.test.ts +2 -0
  77. package/src/__tests__/conversation-tool-setup-attribution.test.ts +47 -0
  78. package/src/__tests__/conversation-usage.test.ts +2 -0
  79. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  80. package/src/__tests__/conversation-workspace-injection.test.ts +2 -0
  81. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +2 -0
  82. package/src/__tests__/credential-security-invariants.test.ts +1 -1
  83. package/src/__tests__/db-compaction-events-migration.test.ts +129 -0
  84. package/src/__tests__/db-migration-rollback.test.ts +205 -171
  85. package/src/__tests__/db-test-helpers.ts +5 -4
  86. package/src/__tests__/delete-propagation.test.ts +5 -3
  87. package/src/__tests__/deterministic-verification-control-plane.test.ts +4 -2
  88. package/src/__tests__/disk-pressure-guard.test.ts +41 -0
  89. package/src/__tests__/dm-backfill.test.ts +6 -4
  90. package/src/__tests__/dm-persistence.test.ts +2 -0
  91. package/src/__tests__/emit-signal-routing-intent.test.ts +7 -6
  92. package/src/__tests__/events-dev-bypass-actor.test.ts +7 -1
  93. package/src/__tests__/exploration-drift-hook.test.ts +3 -2
  94. package/src/__tests__/filing-service.test.ts +2 -0
  95. package/src/__tests__/guardian-binding-drift-heal.test.ts +104 -19
  96. package/src/__tests__/guardian-dispatch.test.ts +140 -1
  97. package/src/__tests__/guardian-expiry-notifier.test.ts +282 -0
  98. package/src/__tests__/guardian-outbound-http.test.ts +13 -0
  99. package/src/__tests__/guardian-routing-state.test.ts +6 -10
  100. package/src/__tests__/heartbeat-disk-pressure.test.ts +2 -0
  101. package/src/__tests__/heartbeat-service.test.ts +2 -0
  102. package/src/__tests__/helpers/channel-test-adapter.ts +46 -19
  103. package/src/__tests__/helpers/create-guardian-binding.ts +15 -23
  104. package/src/__tests__/helpers/mock-logger.ts +1 -0
  105. package/src/__tests__/helpers/seed-contact-channel.ts +96 -0
  106. package/src/__tests__/host-app-control-routes.test.ts +24 -30
  107. package/src/__tests__/host-bash-routes.test.ts +31 -41
  108. package/src/__tests__/host-browser-routes.test.ts +26 -32
  109. package/src/__tests__/host-cu-routes-targeted.test.ts +25 -33
  110. package/src/__tests__/host-file-routes-targeted.test.ts +40 -52
  111. package/src/__tests__/host-transfer-routes-targeted.test.ts +31 -43
  112. package/src/__tests__/http-user-message-parity.test.ts +290 -8
  113. package/src/__tests__/inbound-invite-redemption.test.ts +115 -10
  114. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  115. package/src/__tests__/invite-redemption-service.test.ts +471 -53
  116. package/src/__tests__/invite-routes-http.test.ts +34 -0
  117. package/src/__tests__/invite-service-ipc.test.ts +65 -2
  118. package/src/__tests__/llm-context-normalization.test.ts +105 -0
  119. package/src/__tests__/llm-request-log-error-payload.test.ts +71 -9
  120. package/src/__tests__/llm-usage-store.test.ts +25 -0
  121. package/src/__tests__/mcp-config-secret-boundary.test.ts +392 -0
  122. package/src/__tests__/mcp-health-check.test.ts +2 -1
  123. package/src/__tests__/media-stream-server-integration.test.ts +127 -0
  124. package/src/__tests__/memory-retrieval-hook.test.ts +2 -0
  125. package/src/__tests__/messaging-send-tool.test.ts +2 -0
  126. package/src/__tests__/migration-import-from-url.test.ts +2 -2
  127. package/src/__tests__/mtime-cache.test.ts +275 -5
  128. package/src/__tests__/native-web-search.test.ts +2 -0
  129. package/src/__tests__/non-member-access-request.test.ts +191 -17
  130. package/src/__tests__/notification-broadcaster.test.ts +4 -0
  131. package/src/__tests__/notification-decision-recipient-context.test.ts +33 -32
  132. package/src/__tests__/notification-deep-link.test.ts +6 -0
  133. package/src/__tests__/notification-guardian-path.test.ts +19 -0
  134. package/src/__tests__/onboarding-persona-write.test.ts +52 -22
  135. package/src/__tests__/openai-provider.test.ts +22 -12
  136. package/src/__tests__/openai-responses-provider.test.ts +12 -2
  137. package/src/__tests__/outbound-slack-persistence.test.ts +2 -0
  138. package/src/__tests__/pending-interactions-resolved-event.test.ts +7 -4
  139. package/src/__tests__/persist-onboarding-artifacts.test.ts +1 -0
  140. package/src/__tests__/persistence-secret-redaction.test.ts +2 -0
  141. package/src/__tests__/persona-resolver.test.ts +75 -45
  142. package/src/__tests__/plugin-bootstrap.test.ts +21 -83
  143. package/src/__tests__/plugin-disabled-state.test.ts +190 -0
  144. package/src/__tests__/plugin-pipeline.test.ts +96 -0
  145. package/src/__tests__/plugin-route-contribution.test.ts +6 -19
  146. package/src/__tests__/plugin-tool-contribution.test.ts +5 -20
  147. package/src/__tests__/plugin-types.test.ts +2 -4
  148. package/src/__tests__/process-message-background-slack.test.ts +2 -0
  149. package/src/__tests__/process-message-display-content.test.ts +2 -0
  150. package/src/__tests__/provider-error-scenarios.test.ts +5 -4
  151. package/src/__tests__/provider-usage-tracking.test.ts +39 -0
  152. package/src/__tests__/reaction-intercept-cold-cache-warm.test.ts +135 -0
  153. package/src/__tests__/reaction-intercept-member-verdict-warm.test.ts +158 -0
  154. package/src/__tests__/reaction-persistence.test.ts +51 -4
  155. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +2 -0
  156. package/src/__tests__/registry.test.ts +4 -1
  157. package/src/__tests__/relay-server.test.ts +758 -32
  158. package/src/__tests__/runtime-attachment-metadata.test.ts +9 -12
  159. package/src/__tests__/secret-ingress-http.test.ts +14 -0
  160. package/src/__tests__/send-endpoint-busy.test.ts +30 -8
  161. package/src/__tests__/settings-routes.test.ts +32 -0
  162. package/src/__tests__/skills.test.ts +44 -0
  163. package/src/__tests__/slack-inbound-verification.test.ts +47 -2
  164. package/src/__tests__/sse-actor-principal-guardian-source.test.ts +79 -0
  165. package/src/__tests__/steer-on-enqueue-question.test.ts +181 -0
  166. package/src/__tests__/stt-hints.test.ts +44 -15
  167. package/src/__tests__/subagent-detail.test.ts +27 -0
  168. package/src/__tests__/subagent-disposal.test.ts +65 -0
  169. package/src/__tests__/subagent-fork-prompt-role.test.ts +195 -0
  170. package/src/__tests__/subagent-fork-spawn.test.ts +6 -7
  171. package/src/__tests__/subagent-notify-parent.test.ts +2 -0
  172. package/src/__tests__/subagent-role-registry.test.ts +24 -6
  173. package/src/__tests__/subagent-spawn-and-await.test.ts +546 -0
  174. package/src/__tests__/subagent-spawn-tool-fork.test.ts +2 -0
  175. package/src/__tests__/subagent-tools.test.ts +398 -1
  176. package/src/__tests__/suggestion-routes.test.ts +2 -0
  177. package/src/__tests__/thread-backfill.test.ts +3 -3
  178. package/src/__tests__/title-generate-hook.test.ts +2 -0
  179. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -0
  180. package/src/__tests__/tool-executor.test.ts +16 -11
  181. package/src/__tests__/tool-preview-lifecycle.test.ts +2 -0
  182. package/src/__tests__/tool-result-metadata-plumbing.test.ts +2 -0
  183. package/src/__tests__/tool-start-timestamp.test.ts +2 -0
  184. package/src/__tests__/trusted-contact-approval-notifier.test.ts +37 -51
  185. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +12 -12
  186. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -7
  187. package/src/__tests__/trusted-contact-multichannel.test.ts +16 -7
  188. package/src/__tests__/trusted-contact-verification.test.ts +79 -54
  189. package/src/__tests__/twilio-routes.test.ts +96 -0
  190. package/src/__tests__/ui-file-upload-surface.test.ts +86 -0
  191. package/src/__tests__/verification-control-plane-policy.test.ts +2 -0
  192. package/src/__tests__/voice-guardian-cold-cache-warm.test.ts +137 -0
  193. package/src/__tests__/voice-invite-redemption.test.ts +216 -20
  194. package/src/__tests__/web-search-backend-failure.test.ts +2 -0
  195. package/src/__tests__/workspace-migration-102-preserve-heartbeat-enabled-for-existing-workspaces.test.ts +3 -3
  196. package/src/__tests__/workspace-migration-111-prune-seeded-callsite-defaults.test.ts +208 -0
  197. package/src/__tests__/workspace-migration-112-remove-advisor-callsite-override.test.ts +170 -0
  198. package/src/__tests__/workspace-migration-drop-user-md.test.ts +196 -238
  199. package/src/__tests__/workspace-migration-remove-hooks.test.ts +14 -35
  200. package/src/__tests__/workspace-tool-loader.test.ts +195 -2
  201. package/src/a2a/__tests__/e2e-a2a-channel.test.ts +35 -47
  202. package/src/agent/loop-exclusive-tool.test.ts +154 -0
  203. package/src/agent/loop-native-web-search.test.ts +200 -0
  204. package/src/agent/loop.ts +164 -1
  205. package/src/api/constants/sse-replay.ts +41 -0
  206. package/src/api/events/conversation-notice.ts +26 -0
  207. package/src/api/index.ts +19 -1
  208. package/src/api/responses/llm-request-log-entry.ts +29 -0
  209. package/src/api/responses/subagent-detail.ts +17 -0
  210. package/src/api/surfaces.ts +39 -3
  211. package/src/approvals/guardian-channel-delivery.ts +30 -0
  212. package/src/approvals/guardian-expiry-notifier.ts +148 -0
  213. package/src/approvals/guardian-request-resolvers.ts +17 -15
  214. package/src/calls/__tests__/relay-setup-router.test.ts +267 -17
  215. package/src/calls/call-domain.ts +3 -3
  216. package/src/calls/guardian-dispatch.ts +14 -9
  217. package/src/calls/inbound-trust-reader.ts +24 -2
  218. package/src/calls/media-stream-server.ts +21 -0
  219. package/src/calls/relay-access-wait.ts +6 -6
  220. package/src/calls/relay-server.ts +188 -51
  221. package/src/calls/relay-setup-router.ts +47 -17
  222. package/src/calls/relay-verification.ts +4 -4
  223. package/src/calls/stt-hints.ts +9 -12
  224. package/src/calls/twilio-routes.ts +14 -4
  225. package/src/channels/types.ts +10 -20
  226. package/src/cli/commands/__tests__/cache.test.ts +8 -1
  227. package/src/cli/commands/__tests__/conversations-slack.test.ts +1 -0
  228. package/src/cli/commands/cache.ts +194 -181
  229. package/src/cli/commands/contacts.ts +10 -7
  230. package/src/cli/commands/db/__tests__/repair.test.ts +6 -5
  231. package/src/cli/commands/db/status.ts +37 -1
  232. package/src/cli/commands/mcp.ts +252 -218
  233. package/src/cli/commands/memory/__tests__/worker.test.ts +432 -0
  234. package/src/cli/commands/memory/index.ts +2 -0
  235. package/src/cli/commands/memory/worker.ts +242 -0
  236. package/src/cli/commands/plugins.ts +125 -13
  237. package/src/cli/lib/__tests__/install-from-github.test.ts +102 -0
  238. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +160 -1
  239. package/src/cli/lib/__tests__/publish-plugin.test.ts +404 -0
  240. package/src/cli/lib/list-installed-plugins.ts +179 -1
  241. package/src/cli/lib/publish-plugin.ts +633 -0
  242. package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +143 -0
  243. package/src/config/__tests__/sync-gated-profiles.test.ts +16 -10
  244. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +27 -17
  245. package/src/config/bundled-skills/contacts/tools/contact-search.ts +13 -3
  246. package/src/config/bundled-skills/subagent/SKILL.md +17 -2
  247. package/src/config/bundled-skills/subagent/TOOLS.json +5 -4
  248. package/src/config/call-site-defaults.ts +0 -6
  249. package/src/config/feature-flag-registry.json +5 -13
  250. package/src/config/llm-resolver.ts +0 -3
  251. package/src/config/loader.ts +38 -5
  252. package/src/config/prune-seeded-callsite-defaults.ts +110 -0
  253. package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
  254. package/src/config/schemas/call-site-catalog.ts +0 -7
  255. package/src/config/schemas/heartbeat.ts +2 -5
  256. package/src/config/schemas/llm.ts +3 -12
  257. package/src/config/schemas/memory-lifecycle.ts +12 -0
  258. package/src/config/schemas/memory-v3.ts +7 -0
  259. package/src/config/schemas/memory.ts +4 -0
  260. package/src/config/schemas/timeouts.ts +8 -0
  261. package/src/config/seed-inference-profiles.ts +30 -34
  262. package/src/config/skills.ts +27 -5
  263. package/src/config/sync-gated-profiles.ts +12 -16
  264. package/src/contacts/__tests__/contacts-write-revoke-relay.test.ts +128 -0
  265. package/src/contacts/__tests__/guardian-delivery-reader.test.ts +312 -0
  266. package/src/contacts/__tests__/member-write-relay.test.ts +226 -0
  267. package/src/contacts/contact-store.ts +25 -236
  268. package/src/contacts/contacts-write.ts +18 -55
  269. package/src/contacts/gateway-channel-read.ts +51 -0
  270. package/src/contacts/guardian-delivery-reader.ts +223 -0
  271. package/src/contacts/member-write-relay.ts +183 -0
  272. package/src/contacts/types.ts +2 -15
  273. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +35 -0
  274. package/src/daemon/__tests__/conversation-tool-setup.test.ts +0 -44
  275. package/src/daemon/assistant-attachments.ts +27 -4
  276. package/src/daemon/conversation-agent-loop.ts +28 -0
  277. package/src/daemon/conversation-notices.ts +60 -0
  278. package/src/daemon/conversation-process.ts +35 -16
  279. package/src/daemon/conversation-surfaces.ts +111 -38
  280. package/src/daemon/conversation-tool-setup.ts +71 -30
  281. package/src/daemon/conversation.ts +23 -1
  282. package/src/daemon/disk-pressure-guard.ts +12 -2
  283. package/src/daemon/event-loop-watchdog.ts +28 -1
  284. package/src/daemon/external-plugins-bootstrap.ts +17 -41
  285. package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -1
  286. package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -2
  287. package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +25 -2
  288. package/src/daemon/handlers/__tests__/config-channels.test.ts +220 -0
  289. package/src/daemon/handlers/config-a2a.ts +6 -14
  290. package/src/daemon/handlers/config-channels.ts +67 -26
  291. package/src/daemon/handlers/conversations.ts +77 -0
  292. package/src/daemon/lifecycle.ts +16 -0
  293. package/src/daemon/mcp-reload-service.ts +10 -0
  294. package/src/daemon/memory-v2-startup.test.ts +72 -0
  295. package/src/daemon/memory-v2-startup.ts +87 -19
  296. package/src/daemon/message-types/conversations.ts +2 -0
  297. package/src/daemon/message-types/surfaces.ts +12 -12
  298. package/src/daemon/server.ts +0 -4
  299. package/src/daemon/shutdown-handlers.ts +20 -0
  300. package/src/daemon/tool-setup-types.ts +9 -0
  301. package/src/heartbeat/heartbeat-service.ts +5 -0
  302. package/src/home/relationship-state-writer.ts +5 -0
  303. package/src/hooks/hook-loader.ts +341 -0
  304. package/src/ipc/__tests__/clients-list-ipc.test.ts +1 -1
  305. package/src/ipc/assistant-server.ts +2 -2
  306. package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +1 -0
  307. package/src/mcp/client.ts +15 -1
  308. package/src/mcp/mcp-auth-orchestrator.ts +6 -1
  309. package/src/mcp/mcp-header-store.ts +134 -0
  310. package/src/mcp/mcp-oauth-provider.ts +19 -8
  311. package/src/memory/__tests__/301-create-watchdog-events.test.ts +110 -0
  312. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  313. package/src/memory/__tests__/prompt-override.test.ts +192 -0
  314. package/src/memory/__tests__/watchdog-events-store.test.ts +161 -0
  315. package/src/memory/compaction-ledger-store.ts +107 -0
  316. package/src/memory/conversation-crud.ts +129 -61
  317. package/src/memory/db-connection.ts +22 -3
  318. package/src/memory/db-init.ts +37 -503
  319. package/src/memory/db-singleton.ts +6 -4
  320. package/src/memory/jobs-worker.ts +104 -0
  321. package/src/memory/llm-request-log-store.ts +26 -1
  322. package/src/memory/llm-usage-store.ts +48 -20
  323. package/src/memory/memory-retrospective-job.ts +14 -8
  324. package/src/memory/migrations/209-strip-thinking-from-consolidated.ts +152 -56
  325. package/src/memory/migrations/300-add-processing-started-at.ts +30 -0
  326. package/src/memory/migrations/301-create-watchdog-events.ts +45 -0
  327. package/src/memory/migrations/302-create-compaction-events.ts +107 -0
  328. package/src/memory/migrations/__tests__/209-strip-thinking-from-consolidated.test.ts +297 -0
  329. package/src/memory/migrations/__tests__/run-migrations.test.ts +2 -2
  330. package/src/memory/migrations/run-migrations.ts +106 -10
  331. package/src/memory/migrations/validate-migration-state.ts +105 -67
  332. package/src/memory/prompt-override.ts +129 -0
  333. package/src/memory/schema/conversations.ts +37 -0
  334. package/src/memory/schema/infrastructure.ts +20 -0
  335. package/src/memory/steps.ts +1294 -0
  336. package/src/memory/v2/__tests__/cli-command-store.test.ts +25 -0
  337. package/src/memory/v2/__tests__/skill-store.test.ts +80 -0
  338. package/src/memory/v2/cli-command-store.ts +75 -38
  339. package/src/memory/v2/prompts/consolidation.ts +13 -82
  340. package/src/memory/v2/prompts/router.ts +21 -93
  341. package/src/memory/v2/skill-store.ts +68 -31
  342. package/src/memory/watchdog-events-store.ts +87 -0
  343. package/src/memory/worker-control.ts +204 -0
  344. package/src/memory/worker-process.ts +89 -0
  345. package/src/messaging/channel-binding-metadata.ts +31 -0
  346. package/src/messaging/provider-types.ts +8 -0
  347. package/src/messaging/providers/slack/binding-metadata.ts +60 -0
  348. package/src/notifications/__tests__/broadcaster.test.ts +8 -8
  349. package/src/notifications/__tests__/connected-channels.test.ts +86 -0
  350. package/src/notifications/__tests__/decision-engine.test.ts +78 -9
  351. package/src/notifications/__tests__/destination-resolver.test.ts +151 -0
  352. package/src/notifications/broadcaster.ts +8 -1
  353. package/src/notifications/decision-engine.ts +15 -7
  354. package/src/notifications/destination-resolver.ts +53 -25
  355. package/src/notifications/emit-signal.ts +34 -15
  356. package/src/onboarding/checkin-event.test.ts +222 -0
  357. package/src/onboarding/checkin-event.ts +321 -0
  358. package/src/onboarding/schedule-checkin.ts +190 -0
  359. package/src/permissions/question-prompter.test.ts +1 -1
  360. package/src/permissions/question-prompter.ts +7 -4
  361. package/src/plugin-api/index.ts +12 -12
  362. package/src/plugin-api/types.ts +12 -14
  363. package/src/plugin-api/vision-support.test.ts +28 -4
  364. package/src/plugin-api/vision-support.ts +66 -31
  365. package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +2 -2
  366. package/src/plugins/defaults/empty-response/hooks/stop.ts +2 -2
  367. package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +4 -3
  368. package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +2 -2
  369. package/src/plugins/defaults/history-repair/hooks/stop.ts +2 -2
  370. package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +2 -2
  371. package/src/plugins/defaults/image-fallback/__tests__/image-fallback.test.ts +47 -7
  372. package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +12 -13
  373. package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +14 -22
  374. package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +42 -11
  375. package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +2 -2
  376. package/src/plugins/defaults/image-recovery/hooks/stop.ts +2 -2
  377. package/src/plugins/defaults/index.ts +0 -35
  378. package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +2 -2
  379. package/src/plugins/defaults/max-tokens-continue/hooks/stop.ts +2 -2
  380. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +2 -2
  381. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
  382. package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +33 -3
  383. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +48 -4
  384. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +4 -8
  385. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +2 -2
  386. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +2 -2
  387. package/src/plugins/defaults/memory-v3-shadow/injector.ts +43 -15
  388. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +11 -2
  389. package/src/plugins/defaults/memory-v3-shadow/pool-select.test.ts +146 -0
  390. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +77 -13
  391. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +12 -11
  392. package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +2 -2
  393. package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +2 -2
  394. package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +2 -2
  395. package/src/plugins/defaults/title-generate/hooks/stop.ts +2 -2
  396. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +2 -2
  397. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +2 -2
  398. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +2 -2
  399. package/src/plugins/disabled-state.ts +31 -0
  400. package/src/plugins/external-plugin-loader.ts +2 -2
  401. package/src/plugins/mtime-cache.ts +186 -330
  402. package/src/plugins/pipeline.ts +111 -13
  403. package/src/plugins/registry.ts +59 -16
  404. package/src/plugins/surface-import.ts +121 -0
  405. package/src/plugins/types.ts +7 -9
  406. package/src/prompts/persona-resolver.ts +43 -11
  407. package/src/providers/anthropic/client.ts +5 -0
  408. package/src/providers/call-site-routing.ts +45 -0
  409. package/src/providers/model-catalog.ts +16 -0
  410. package/src/providers/openai/__tests__/api-error-normalization.test.ts +321 -0
  411. package/src/providers/openai/api-error-normalization.ts +270 -0
  412. package/src/providers/openai/chat-completions-provider.ts +37 -83
  413. package/src/providers/openai/responses-provider.ts +50 -46
  414. package/src/providers/openrouter/client.ts +5 -0
  415. package/src/providers/provider-send-message.ts +10 -0
  416. package/src/providers/ratelimit.ts +10 -0
  417. package/src/providers/registry.ts +1 -1
  418. package/src/providers/retry.ts +10 -0
  419. package/src/providers/types.ts +22 -0
  420. package/src/providers/usage-tracking.ts +10 -0
  421. package/src/runtime/__tests__/channel-verification-service.test.ts +133 -0
  422. package/src/runtime/__tests__/guardian-vellum-migration.test.ts +184 -0
  423. package/src/runtime/__tests__/is-guardian-bound-for-channel.test.ts +66 -0
  424. package/src/runtime/__tests__/local-principal-trust.test.ts +162 -0
  425. package/src/runtime/__tests__/member-verdict-cache.test.ts +119 -0
  426. package/src/runtime/__tests__/trust-verdict-consumer.test.ts +401 -123
  427. package/src/runtime/access-request-helper.ts +18 -39
  428. package/src/runtime/actor-trust-resolver.ts +46 -19
  429. package/src/runtime/anchored-guardian.test.ts +109 -0
  430. package/src/runtime/anchored-guardian.ts +86 -0
  431. package/src/runtime/assistant-event-hub.ts +1 -1
  432. package/src/runtime/assistant-stream-state.ts +9 -2
  433. package/src/runtime/auth/__tests__/require-bound-guardian.test.ts +99 -0
  434. package/src/runtime/auth/require-bound-guardian.ts +21 -11
  435. package/src/runtime/channel-verification-service.ts +56 -31
  436. package/src/runtime/confirmation-request-guardian-bridge.ts +3 -3
  437. package/src/runtime/guardian-vellum-migration.ts +69 -8
  438. package/src/runtime/invite-redemption-service.ts +213 -187
  439. package/src/runtime/local-actor-identity.test.ts +108 -0
  440. package/src/runtime/local-actor-identity.ts +85 -13
  441. package/src/runtime/local-principal-trust.ts +52 -0
  442. package/src/runtime/member-verdict-cache.ts +0 -0
  443. package/src/runtime/pending-interactions.ts +11 -1
  444. package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +56 -5
  445. package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
  446. package/src/runtime/routes/__tests__/contact-routes.test.ts +305 -0
  447. package/src/runtime/routes/__tests__/global-search-routes.test.ts +91 -0
  448. package/src/runtime/routes/__tests__/http-adapter-actor-header.test.ts +129 -0
  449. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +188 -0
  450. package/src/runtime/routes/browser-routes.ts +1 -1
  451. package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +13 -5
  452. package/src/runtime/routes/channel-verification-routes.ts +3 -3
  453. package/src/runtime/routes/contact-routes.ts +26 -43
  454. package/src/runtime/routes/conversation-cli-routes.ts +4 -5
  455. package/src/runtime/routes/conversation-list-routes.ts +4 -7
  456. package/src/runtime/routes/conversation-query-routes.ts +72 -0
  457. package/src/runtime/routes/conversation-routes.ts +84 -85
  458. package/src/runtime/routes/events-routes.ts +2 -2
  459. package/src/runtime/routes/global-search-routes.ts +3 -1
  460. package/src/runtime/routes/guardian-action-routes.ts +4 -5
  461. package/src/runtime/routes/host-app-control-routes.ts +5 -4
  462. package/src/runtime/routes/host-bash-routes.ts +5 -4
  463. package/src/runtime/routes/host-browser-routes.ts +9 -11
  464. package/src/runtime/routes/host-cu-routes.ts +5 -4
  465. package/src/runtime/routes/host-file-routes.ts +5 -4
  466. package/src/runtime/routes/host-transfer-routes.ts +6 -6
  467. package/src/runtime/routes/http-adapter.ts +16 -1
  468. package/src/runtime/routes/identity-routes.ts +3 -2
  469. package/src/runtime/routes/inbound-message-handler.ts +5 -5
  470. package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +97 -5
  471. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +61 -59
  472. package/src/runtime/routes/inbound-stages/background-dispatch.ts +13 -5
  473. package/src/runtime/routes/inbound-stages/escalation-intercept.ts +7 -7
  474. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +21 -8
  475. package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -3
  476. package/src/runtime/routes/inbound-stages/reaction-intercept.ts +19 -0
  477. package/src/runtime/routes/index.ts +2 -0
  478. package/src/runtime/routes/llm-context-normalization.ts +83 -0
  479. package/src/runtime/routes/mcp-auth-routes.ts +171 -19
  480. package/src/runtime/routes/migration-rollback-routes.ts +4 -3
  481. package/src/runtime/routes/migration-routes.ts +4 -1
  482. package/src/runtime/routes/onboarding-checkin-routes.ts +86 -0
  483. package/src/runtime/routes/settings-routes.ts +8 -3
  484. package/src/runtime/routes/subagents-routes.ts +5 -0
  485. package/src/runtime/routes/surface-action-routes.ts +42 -56
  486. package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
  487. package/src/runtime/services/conversation-serializer.ts +13 -58
  488. package/src/runtime/tool-grant-request-helper.ts +3 -3
  489. package/src/runtime/trust-verdict-consumer.ts +103 -40
  490. package/src/runtime/verification-outbound-actions.ts +18 -18
  491. package/src/signals/user-message.ts +16 -0
  492. package/src/subagent/__tests__/consult-prompt.test.ts +35 -0
  493. package/src/{plugins/defaults/advisor/__tests__/transcript.test.ts → subagent/__tests__/consult-transcript.test.ts} +47 -10
  494. package/src/{plugins/defaults/advisor/steering.ts → subagent/consult-prompt.ts} +22 -32
  495. package/src/{plugins/defaults/advisor/transcript.ts → subagent/consult-transcript.ts} +18 -8
  496. package/src/subagent/index.ts +1 -1
  497. package/src/subagent/manager.ts +254 -33
  498. package/src/subagent/types.ts +11 -4
  499. package/src/telemetry/types.ts +34 -1
  500. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
  501. package/src/telemetry/usage-telemetry-reporter.ts +87 -3
  502. package/src/tools/ask-question/ask-question-tool.test.ts +29 -0
  503. package/src/tools/ask-question/ask-question-tool.ts +13 -0
  504. package/src/tools/executor.ts +4 -4
  505. package/src/tools/filesystem/search.ts +543 -0
  506. package/src/tools/registry.ts +38 -0
  507. package/src/tools/shared/filesystem/path-policy.ts +12 -5
  508. package/src/tools/subagent/consult-deadline.ts +49 -0
  509. package/src/tools/subagent/spawn.ts +234 -5
  510. package/src/tools/tool-approval-handler.ts +1 -1
  511. package/src/tools/tool-defaults.ts +9 -2
  512. package/src/tools/tool-manifest.ts +3 -0
  513. package/src/tools/types.ts +131 -25
  514. package/src/tools/workspace-tools/loader.ts +348 -244
  515. package/src/util/errors.ts +26 -1
  516. package/src/util/logger.ts +9 -0
  517. package/src/util/platform.ts +19 -0
  518. package/src/util/telemetry-db-path.ts +24 -0
  519. package/src/workflows/library.test.ts +140 -0
  520. package/src/workflows/library.ts +82 -28
  521. package/src/workspace/migrations/017-seed-persona-dirs.ts +3 -34
  522. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +3 -24
  523. package/src/workspace/migrations/031-drop-user-md.ts +232 -148
  524. package/src/workspace/migrations/048-remove-workspace-hooks.ts +14 -66
  525. package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +134 -0
  526. package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +64 -0
  527. package/src/workspace/migrations/registry.ts +4 -0
  528. package/src/__tests__/workspace-tools-watcher-flag.test.ts +0 -70
  529. package/src/daemon/workspace-tools-watcher.ts +0 -328
  530. package/src/memory/migrations/registry.ts +0 -573
  531. package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +0 -56
  532. package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +0 -43
  533. package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +0 -137
  534. package/src/plugins/defaults/advisor/__tests__/consult.test.ts +0 -153
  535. package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +0 -138
  536. package/src/plugins/defaults/advisor/advisor-gate.ts +0 -29
  537. package/src/plugins/defaults/advisor/advisor-state-store.ts +0 -94
  538. package/src/plugins/defaults/advisor/config.ts +0 -21
  539. package/src/plugins/defaults/advisor/consult.ts +0 -93
  540. package/src/plugins/defaults/advisor/hooks/post-model-call.ts +0 -34
  541. package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +0 -30
  542. package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +0 -19
  543. package/src/plugins/defaults/advisor/package.json +0 -14
  544. package/src/plugins/defaults/advisor/tools/advisor.ts +0 -65
  545. package/src/providers/openai/__tests__/api-error-detail.test.ts +0 -120
package/bun.lock CHANGED
@@ -38,6 +38,7 @@
38
38
  "playwright": "1.58.2",
39
39
  "postgres": "3.4.8",
40
40
  "quickjs-emscripten": "0.32.0",
41
+ "re2js": "2.8.3",
41
42
  "rrule": "2.8.1",
42
43
  "semver": "7.8.0",
43
44
  "stemmer": "2.0.1",
@@ -54,6 +55,7 @@
54
55
  "@types/node": "25.5.0",
55
56
  "@types/semver": "7.5.8",
56
57
  "@types/uuid": "10.0.0",
58
+ "@typescript/native-preview": "7.0.0-dev.20260624.1",
57
59
  "ajv": "8.18.0",
58
60
  "drizzle-kit": "0.31.10",
59
61
  "eslint": "10.0.3",
@@ -454,6 +456,22 @@
454
456
 
455
457
  "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="],
456
458
 
459
+ "@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260624.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260624.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260624.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260624.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260624.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260624.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260624.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260624.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-ogwfNo1xuAutOF8RbTCo3Ut0q/65u2ucOeHizi6O14q+3vnelNS+u8qVC2QWXubMcwtuN5E9cbfPslvGC4kdwA=="],
460
+
461
+ "@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260624.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-g8CqDkYCHTCYdhBHXs5cMraBurOS+KrcMFxE0SsaKZoI6Tnp+le1aWvxUBbzNKJYyThHJqb/1mLopzEJxJCuKA=="],
462
+
463
+ "@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260624.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-P00JVvSV90eioYDuINAKmOSA8yhFTWLq6RvS5lrCfUuDlcgr2kSOgZAfFHIksHBVz6ZXpAXpa0dHPmc5SJ3Ymw=="],
464
+
465
+ "@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260624.1", "", { "os": "linux", "cpu": "arm" }, "sha512-eWHELvfQMkVRjafMd+3ATgM9p9yAergJaM4AOY8AekCNWnHFwUrp/ohh+ryyMUIqque5jjb/kuTiOiGj728I2Q=="],
466
+
467
+ "@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260624.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-cppM2yTZ/Gd1hOXy8NEJcUBxJ0O0zl9CU3OU1ZWZ/OHWWX/ukEzCCr94SUwJhjIWOylBCpIYkrvYoTwxNa94XQ=="],
468
+
469
+ "@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260624.1", "", { "os": "linux", "cpu": "x64" }, "sha512-FaB8rS+rKYz4nDrEsHsF3b4cn7eCKCYroMJReA375OuQ6PHcmCNQ6QlVetA0dfFBxTTgejmoKyfw9xgAA5P4Yw=="],
470
+
471
+ "@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260624.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-BgkqbCmSHDb5UxqWaFlFFJ/DHNT3lEUO4W8627ap6+QthJZuXk2imiHAX3PgYXC6en9fLLyR6jjcseAa4CCshg=="],
472
+
473
+ "@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260624.1", "", { "os": "win32", "cpu": "x64" }, "sha512-WaZ+ue63NgB2j/lqjirfevh/TqcsCxSqnKhGGiRnlxHyYIBcoq+x7KngyEnyGIaywJE1PcFeXA+2EMSIPlSEiQ=="],
474
+
457
475
  "@vellumai/ces-client": ["@vellumai/ces-client@file:../packages/ces-client", { "dependencies": { "@vellumai/service-contracts": "file:../service-contracts" }, "devDependencies": { "@types/bun": "1.2.4", "typescript": "5.7.3" } }],
458
476
 
459
477
  "@vellumai/credential-storage": ["@vellumai/credential-storage@file:../packages/credential-storage", { "devDependencies": { "@types/bun": "1.3.10", "typescript": "5.9.3" } }],
@@ -1040,6 +1058,8 @@
1040
1058
 
1041
1059
  "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
1042
1060
 
1061
+ "re2js": ["re2js@2.8.3", "", {}, "sha512-lUKeXVwMqU302DM/WaOm33XF2hhzjGUZ8CbLg4zSAMpW2PPkJ2+is25AROevNiw+DytFmKU5gsQ92cB1Kxy+fA=="],
1062
+
1043
1063
  "readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
1044
1064
 
1045
1065
  "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
@@ -5,9 +5,9 @@ add a brand-new one) by dropping a single file under their
5
5
  `<workspaceDir>/tools/` directory. The override survives assistant restarts,
6
6
  takes effect during the same startup phase as core tool initialization,
7
7
  and is recoverable: removing the file restores the original core behavior.
8
- When the `workspace-tools-watcher` feature flag is enabled, overrides are
9
- also hot-reloaded by a filesystem watcher (no restart required after the
10
- initial boot).
8
+ Overrides are reconciled from disk on every conversation read, so edits
9
+ under `tools/` take effect on the next conversation with no restart and no
10
+ filesystem watcher.
11
11
 
12
12
  This page explains the file convention, lifecycle position, and the
13
13
  "single canonical source per name" invariant the design is built around.
@@ -100,8 +100,8 @@ Workspace tools are the highest-priority origin in the tool registry:
100
100
 
101
101
  - **Same name as a core tool** → the original core tool is moved into an
102
102
  internal stash (`getCoreToolOverride(name)`) and the workspace tool takes
103
- its place. Removing the workspace file causes the watcher to restore
104
- the original — workspace tools are not destructive to the core baseline.
103
+ its place. Removing the workspace file restores the original on the next
104
+ reconcile — workspace tools are not destructive to the core baseline.
105
105
  - **Brand-new name** → registers as a net-new entry. No stash.
106
106
  - **`<name>.removed` sentinel for a core tool** → the core tool is
107
107
  stripped (stashed in the same map as override-style stashing) and no
@@ -128,35 +128,44 @@ on the incoming tool.
128
128
 
129
129
  ```
130
130
  initializeTools() # core tools register
131
- → loadWorkspaceTools() # initial workspace tool scan
131
+ → loadWorkspaceTools() # initial workspace tool reconcile
132
132
  → MCP tool registration
133
133
  → loadUserPlugins()
134
134
  → bootstrapPlugins()
135
135
 
136
- # after providers-setup completes:
137
- DaemonServer.start()
138
- WorkspaceToolsWatcher.getInstance().start() # hot register/unregister via fs.watch
136
+ # on every conversation turn (createResolveToolsCallback):
137
+ resolveTools(history)
138
+ loadWorkspaceTools() # reconcile registry against disk (fire-and-forget)
139
+ → getWorkspaceToolDefinitions() # re-read workspace tools from the registry
140
+ → getMcpToolDefinitions() # re-read MCP tools (same pattern)
139
141
  ```
140
142
 
141
143
  Workspace tools register _after_ core tools and _before_ every other
142
- extension surface during the initial scan so that every subsequent
143
- registration sees the workspace tool as already-owned. The initial scan
144
- (`loadWorkspaceTools()`) always runs, so workspace tools load from disk
145
- at every boot regardless of the flag.
146
-
147
- The filesystem watcher is gated on the `workspace-tools-watcher` feature
148
- flag (default off). When enabled, it runs for the lifetime of the
149
- assistant, picking up add/change/delete events on `<workspaceDir>/tools/`
150
- and reconciling the registry without requiring a restart. When disabled,
151
- no watch loop is mounted and live edits to `<workspaceDir>/tools/` take
152
- effect only on the next daemon restart. The flag is read at startup, so
153
- toggling it takes effect on restart rather than mid-process.
154
-
155
- The watcher debounces per filename stem and reconciles by re-deriving
156
- the world from disk ("given what's on disk right now for `<stem>.*`,
157
- what registry state should the assistant be in?") rather than routing
158
- on `fs.watch`'s unreliable add/change/rename event types. This is the
159
- same eventual-consistency pattern the plugin source watcher uses.
144
+ extension surface during the initial reconcile so that every subsequent
145
+ registration sees the workspace tool as already-owned. The initial
146
+ reconcile always runs at boot, so workspace tools load from disk at every
147
+ startup.
148
+
149
+ There is no filesystem watcher. Instead, `loadWorkspaceTools()` is
150
+ idempotent and is re-invoked by the per-turn tool resolver
151
+ (`createResolveToolsCallback`), which then re-reads workspace tools from
152
+ the registry the same way it re-reads MCP tools. Each reconcile re-derives
153
+ the world from disk ("given what's on disk right now under `tools/`, what
154
+ registry state should the assistant be in?") and applies the delta
155
+ registering added files, re-importing changed files, unregistering deleted
156
+ files, and restoring core tools whose `.removed` sentinel was deleted. A
157
+ conversation therefore picks up on-disk edits on its next turn, with no
158
+ restart and without being recreated.
159
+
160
+ The reconcile is fire-and-forget and eventually consistent: an edit lands
161
+ in the registry during one turn's reconcile and is read on a subsequent
162
+ turn. Unchanged files are skipped via an mtime cache, so a no-op reconcile
163
+ costs one `readdir` plus a `stat` per file and never re-imports. Concurrent
164
+ callers coalesce onto a single in-flight reconcile so their
165
+ unregister/register sequences never interleave. This is the same
166
+ eventual-consistency, re-derive-from-disk approach the plugin loader's
167
+ mtime cache uses, with the per-turn tool read — rather than a watcher —
168
+ kicking the reconcile.
160
169
 
161
170
  ## Per-tool isolation
162
171
 
@@ -182,15 +191,15 @@ the whole call without partially populating the registry.
182
191
 
183
192
  ## Unregistering
184
193
 
185
- Deleting `<workspaceDir>/tools/<name>.{ts,js,json}` triggers the file
186
- watcher's reconcile, which calls `unregisterWorkspaceTool(name)` and
187
- restores the stashed core tool when one exists, or simply deletes the
188
- entry when the workspace tool was net-new. No assistant restart is
189
- required.
194
+ Deleting `<workspaceDir>/tools/<name>.{ts,js,json}` is picked up by the
195
+ next reconcile, which calls `unregisterWorkspaceTool(name)` and restores
196
+ the stashed core tool when one exists, or simply deletes the entry when
197
+ the workspace tool was net-new. The change takes effect on the next
198
+ conversation — no assistant restart is required.
190
199
 
191
200
  To strip a core tool without substituting a replacement, drop an empty
192
201
  `<workspaceDir>/tools/<name>.removed` file. Removing that sentinel
193
202
  restores the core tool on the next reconcile. The two states (override
194
203
  vs. strip) are mutually exclusive — placing both `<name>.ts` and
195
- `<name>.removed` for the same stem causes the watcher to tear down
204
+ `<name>.removed` for the same stem causes the reconcile to tear down
196
205
  both states until the conflict is resolved on disk.
@@ -51,11 +51,17 @@ const ALLOWED_PREFIXES = {
51
51
  "../../config/schema",
52
52
  "../../config/env",
53
53
  "../../util/platform",
54
+ "../../../util/platform",
54
55
  // Memory retrospective — the retrospective CLI runs the fork-based
55
56
  // retrospective in-process (no daemon, no IPC), so it imports the
56
57
  // job handler directly. Depth-2 for commands/memory/ nesting.
57
58
  "../../memory/memory-retrospective-job",
58
59
  "../../../memory/memory-retrospective-job",
60
+ // Memory worker control — the `memory worker` CLI spawns/probes/stops
61
+ // the worker OS process directly (no daemon, no IPC), so it imports the
62
+ // shared PID-file control helpers. Depth-2 for commands/memory/ nesting.
63
+ "../../memory/worker-control",
64
+ "../../../memory/worker-control",
59
65
  "../logger",
60
66
  "../output",
61
67
  "../../logger",
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Tests for the guardian binding + delivery pull contract.
3
+ */
4
+
5
+ import { describe, expect, test } from "bun:test";
6
+
7
+ import {
8
+ GuardianDeliverySchema,
9
+ ResolveGuardianDeliveryRequestSchema,
10
+ type GuardianDelivery,
11
+ } from "../guardian-delivery-contract.js";
12
+
13
+ const fullGuardian: GuardianDelivery = {
14
+ channelType: "imessage",
15
+ contactId: "c1",
16
+ principalId: "p1",
17
+ displayName: "Guardian Name",
18
+ address: "+15555550100",
19
+ externalChatId: "ext-chat-1",
20
+ status: "active",
21
+ verifiedAt: 1699999999,
22
+ };
23
+
24
+ describe("ResolveGuardianDeliveryRequestSchema", () => {
25
+ test("parses with channelTypes", () => {
26
+ const req = { channelTypes: ["imessage", "sms"] };
27
+ expect(ResolveGuardianDeliveryRequestSchema.parse(req)).toEqual(req);
28
+ });
29
+
30
+ test("parses with channelTypes omitted", () => {
31
+ expect(ResolveGuardianDeliveryRequestSchema.parse({})).toEqual({});
32
+ });
33
+
34
+ test("defaults to {} when params are undefined (no-param IPC call)", () => {
35
+ expect(ResolveGuardianDeliveryRequestSchema.parse(undefined)).toEqual({});
36
+ });
37
+ });
38
+
39
+ describe("GuardianDeliverySchema", () => {
40
+ test("round-trips a fully-populated row", () => {
41
+ expect(GuardianDeliverySchema.parse(fullGuardian)).toEqual(fullGuardian);
42
+ });
43
+
44
+ test("requires channelType", () => {
45
+ const { channelType: _omit, ...rest } = fullGuardian;
46
+ expect(() => GuardianDeliverySchema.parse(rest)).toThrow();
47
+ });
48
+
49
+ test("requires contactId", () => {
50
+ const { contactId: _omit, ...rest } = fullGuardian;
51
+ expect(() => GuardianDeliverySchema.parse(rest)).toThrow();
52
+ });
53
+
54
+ test("requires address", () => {
55
+ const { address: _omit, ...rest } = fullGuardian;
56
+ expect(() => GuardianDeliverySchema.parse(rest)).toThrow();
57
+ });
58
+
59
+ test("requires status", () => {
60
+ const { status: _omit, ...rest } = fullGuardian;
61
+ expect(() => GuardianDeliverySchema.parse(rest)).toThrow();
62
+ });
63
+
64
+ test("optional fields accept null", () => {
65
+ const row = {
66
+ channelType: "imessage",
67
+ contactId: "c1",
68
+ address: "+15555550100",
69
+ status: "active",
70
+ principalId: null,
71
+ displayName: null,
72
+ externalChatId: null,
73
+ verifiedAt: null,
74
+ } satisfies GuardianDelivery;
75
+ expect(GuardianDeliverySchema.parse(row)).toEqual(row);
76
+ });
77
+
78
+ test("optional fields accept undefined (omitted)", () => {
79
+ const row = {
80
+ channelType: "imessage",
81
+ contactId: "c1",
82
+ address: "+15555550100",
83
+ status: "active",
84
+ } satisfies GuardianDelivery;
85
+ const parsed = GuardianDeliverySchema.parse(row);
86
+ expect(parsed.principalId).toBeUndefined();
87
+ expect(parsed.displayName).toBeUndefined();
88
+ expect(parsed.externalChatId).toBeUndefined();
89
+ expect(parsed.verifiedAt).toBeUndefined();
90
+ });
91
+ });
@@ -7,6 +7,7 @@ import { describe, expect, test } from "bun:test";
7
7
 
8
8
  import { SourceMetadataSchema } from "../inbound-contract.js";
9
9
  import {
10
+ makeResolutionFailedVerdict,
10
11
  TrustVerdictSchema,
11
12
  type TrustVerdict,
12
13
  } from "../trust-verdict-contract.js";
@@ -43,6 +44,36 @@ describe("TrustVerdictSchema", () => {
43
44
  expect(TrustVerdictSchema.parse(minimal)).toEqual(minimal);
44
45
  });
45
46
 
47
+ test("parses a verdict carrying resolutionFailed", () => {
48
+ const verdict = {
49
+ trustClass: "unknown",
50
+ canonicalSenderId: null,
51
+ resolutionFailed: true,
52
+ } satisfies TrustVerdict;
53
+ expect(TrustVerdictSchema.parse(verdict)).toEqual(verdict);
54
+ });
55
+
56
+ test("leaves resolutionFailed undefined when absent", () => {
57
+ const parsed = TrustVerdictSchema.parse({
58
+ trustClass: "unknown",
59
+ canonicalSenderId: null,
60
+ });
61
+ expect(parsed.resolutionFailed).toBeUndefined();
62
+ });
63
+
64
+ test("makeResolutionFailedVerdict builds an unknown sentinel", () => {
65
+ expect(makeResolutionFailedVerdict("+15555550100")).toEqual({
66
+ trustClass: "unknown",
67
+ canonicalSenderId: "+15555550100",
68
+ resolutionFailed: true,
69
+ });
70
+ expect(makeResolutionFailedVerdict(null)).toEqual({
71
+ trustClass: "unknown",
72
+ canonicalSenderId: null,
73
+ resolutionFailed: true,
74
+ });
75
+ });
76
+
46
77
  test("rejects an invalid trustClass", () => {
47
78
  expect(() =>
48
79
  TrustVerdictSchema.parse({
@@ -137,6 +137,50 @@ export type MarkChannelVerifiedIpcResponse = z.infer<
137
137
  typeof MarkChannelVerifiedIpcResponseSchema
138
138
  >;
139
139
 
140
+ export const UpsertVerifiedChannelIpcParamsSchema = z.object({
141
+ type: z.string().min(1),
142
+ address: z.string().min(1),
143
+ externalChatId: z.string().min(1),
144
+ displayName: z.string().optional(),
145
+ username: z.string().optional(),
146
+ // Audit source for the verification. Free text (DB column is text) so the
147
+ // invite-activation path can pass "invite"; do not narrow to an enum.
148
+ verifiedVia: z.string().optional(),
149
+ // Target contact to bind the channel to (invite redemption). When set, an
150
+ // existing channel for the same (type,address) under a different contact is
151
+ // reassigned to this contact, mirroring the assistant's
152
+ // reassignConflictingChannels.
153
+ contactId: z.string().min(1).optional(),
154
+ // Relax the revoked refusal guard so a valid invite can reactivate a revoked
155
+ // member. Blocked actors are refused regardless.
156
+ allowRevokedReactivation: z.boolean().optional(),
157
+ });
158
+
159
+ export type UpsertVerifiedChannelIpcParams = z.infer<
160
+ typeof UpsertVerifiedChannelIpcParamsSchema
161
+ >;
162
+
163
+ export const UpsertVerifiedChannelIpcResponseSchema = z.object({
164
+ ok: z.boolean(),
165
+ verified: z.boolean(),
166
+ // Present only when verified — a blocked/revoked skip omits the channel.
167
+ channel: z
168
+ .object({
169
+ id: z.string(),
170
+ contactId: z.string(),
171
+ type: z.string(),
172
+ address: z.string(),
173
+ status: z.string(),
174
+ verifiedAt: z.number().nullable(),
175
+ verifiedVia: z.string().nullable(),
176
+ })
177
+ .optional(),
178
+ });
179
+
180
+ export type UpsertVerifiedChannelIpcResponse = z.infer<
181
+ typeof UpsertVerifiedChannelIpcResponseSchema
182
+ >;
183
+
140
184
  export const MarkChannelRevokedIpcParamsSchema = z.object({
141
185
  contactChannelId: z.string().min(1),
142
186
  // Audit reason for the downgrade. The verification-revoke flow passes
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Shared contract for the gateway-owned guardian binding + delivery pull.
3
+ *
4
+ * The gateway resolves the active guardian binding(s) and their per-channel
5
+ * delivery endpoints from its DB; the daemon pulls them via the
6
+ * `resolve_guardian_delivery` IPC route. INFO (notes / userFile) is NOT
7
+ * carried here — the daemon joins it locally by `contactId`.
8
+ */
9
+
10
+ import { z } from "zod";
11
+
12
+ /**
13
+ * IPC request for `resolve_guardian_delivery`. `channelTypes` is an optional
14
+ * filter; omitted ⇒ all active guardian channels.
15
+ */
16
+ export const ResolveGuardianDeliveryRequestSchema = z
17
+ .object({
18
+ channelTypes: z.array(z.string()).optional(),
19
+ })
20
+ .default({});
21
+
22
+ export type ResolveGuardianDeliveryRequest = z.infer<
23
+ typeof ResolveGuardianDeliveryRequestSchema
24
+ >;
25
+
26
+ /**
27
+ * One active guardian binding + delivery endpoint for a single channel.
28
+ */
29
+ export const GuardianDeliverySchema = z.object({
30
+ channelType: z.string(),
31
+ contactId: z.string(),
32
+ principalId: z.string().nullable().optional(),
33
+ displayName: z.string().nullable().optional(),
34
+ address: z.string(),
35
+ externalChatId: z.string().nullable().optional(),
36
+ status: z.string(),
37
+ verifiedAt: z.number().nullable().optional(),
38
+ });
39
+
40
+ export type GuardianDelivery = z.infer<typeof GuardianDeliverySchema>;
41
+
42
+ export const ResolveGuardianDeliveryResponseSchema = z.object({
43
+ guardians: z.array(GuardianDeliverySchema),
44
+ });
45
+
46
+ export type ResolveGuardianDeliveryResponse = z.infer<
47
+ typeof ResolveGuardianDeliveryResponseSchema
48
+ >;
@@ -73,6 +73,7 @@ export type { AdmissionPolicy } from "./admission-policy-contract.js";
73
73
 
74
74
  // Trust verdict contract (gateway → daemon) — Zod schemas + derived types
75
75
  export {
76
+ makeResolutionFailedVerdict,
76
77
  ResolveInboundTrustRequestSchema,
77
78
  TRUST_CLASS_VALUES,
78
79
  TrustClassSchema,
@@ -84,3 +85,16 @@ export type {
84
85
  TrustClass,
85
86
  TrustVerdict,
86
87
  } from "./trust-verdict-contract.js";
88
+
89
+ // Guardian delivery contract (daemon → gateway pull) — Zod schemas + derived types
90
+ export {
91
+ GuardianDeliverySchema,
92
+ ResolveGuardianDeliveryRequestSchema,
93
+ ResolveGuardianDeliveryResponseSchema,
94
+ } from "./guardian-delivery-contract.js";
95
+
96
+ export type {
97
+ GuardianDelivery,
98
+ ResolveGuardianDeliveryRequest,
99
+ ResolveGuardianDeliveryResponse,
100
+ } from "./guardian-delivery-contract.js";
@@ -42,6 +42,11 @@ export const TrustVerdictSchema = z.object({
42
42
  trustClass: TrustClassSchema,
43
43
  canonicalSenderId: z.string().nullable(),
44
44
 
45
+ // Present+true ⇒ gateway attempted resolution but failed (DB error);
46
+ // consumer treats it as "could not vouch", distinct from a real `unknown`
47
+ // stranger.
48
+ resolutionFailed: z.boolean().optional(),
49
+
45
50
  // Guardian binding — present only when a guardian binding matches.
46
51
  guardianExternalUserId: z.string().optional(),
47
52
  guardianDeliveryChatId: z.string().nullable().optional(),
@@ -63,6 +68,18 @@ export const TrustVerdictSchema = z.object({
63
68
 
64
69
  export type TrustVerdict = z.infer<typeof TrustVerdictSchema>;
65
70
 
71
+ /**
72
+ * Sentinel for a gateway resolver failure; consumers treat it as
73
+ * could-not-vouch (distinct from a real `unknown` stranger). Takes the
74
+ * already-canonicalized sender id so this module stays free of the gateway's
75
+ * canonicalization util.
76
+ */
77
+ export function makeResolutionFailedVerdict(
78
+ canonicalSenderId: string | null,
79
+ ): TrustVerdict {
80
+ return { trustClass: "unknown", canonicalSenderId, resolutionFailed: true };
81
+ }
82
+
66
83
  /**
67
84
  * IPC request for `resolve_inbound_trust`. Per-actor identity keys the
68
85
  * gateway resolver needs to classify the inbound sender. The response reuses
@@ -6,6 +6,7 @@
6
6
  "type": "module",
7
7
  "exports": {
8
8
  ".": "./src/index.ts",
9
+ "./channels": "./src/channels.ts",
9
10
  "./credential-rpc": "./src/credential-rpc.ts",
10
11
  "./ingress": "./src/ingress.ts",
11
12
  "./twilio-ingress": "./src/twilio-ingress.ts",
@@ -0,0 +1,28 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { CHANNEL_IDS, isChannelId } from "../channels.js";
4
+
5
+ describe("isChannelId", () => {
6
+ test("accepts every canonical channel id", () => {
7
+ for (const id of CHANNEL_IDS) {
8
+ expect(isChannelId(id)).toBe(true);
9
+ }
10
+ });
11
+
12
+ test("includes the internal channels no external surface ingresses", () => {
13
+ // `platform` (control plane) and `vellum` (native app) are part of the
14
+ // canonical vocabulary even though the gateway never ingresses them. The
15
+ // gateway's narrower list is a compile-time-asserted subset of this set,
16
+ // so these must remain canonical for that assertion to mean anything.
17
+ expect(isChannelId("platform")).toBe(true);
18
+ expect(isChannelId("vellum")).toBe(true);
19
+ });
20
+
21
+ test("rejects unknown strings and non-string values", () => {
22
+ expect(isChannelId("discord")).toBe(false);
23
+ expect(isChannelId("")).toBe(false);
24
+ expect(isChannelId(undefined)).toBe(false);
25
+ expect(isChannelId(null)).toBe(false);
26
+ expect(isChannelId(42)).toBe(false);
27
+ });
28
+ });
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Canonical channel-id vocabulary shared between the assistant daemon and the
3
+ * gateway.
4
+ *
5
+ * A "channel" is an external messaging surface an actor can reach the
6
+ * assistant through (Slack, Telegram, WhatsApp, phone, …) plus a couple of
7
+ * internal ids (`vellum` for native app conversations, `platform` for the
8
+ * internal control plane). This is the single source of truth for that set:
9
+ * the assistant adopts it wholesale as its `ChannelId`, and the gateway
10
+ * asserts its own (narrower) inbound list is a subset of it so the two sides
11
+ * cannot silently drift.
12
+ *
13
+ * Both packages depend on `@vellumai/service-contracts`, so hoisting the set
14
+ * here (rather than maintaining a copy on each side) means adding or renaming
15
+ * a channel happens in exactly one place.
16
+ *
17
+ * Note that a consumer may legitimately handle only a *subset* of these — the
18
+ * gateway, for example, never ingresses `platform`. Use a local list guarded
19
+ * by `satisfies readonly ChannelId[]` for those cases rather than redefining
20
+ * the union.
21
+ */
22
+
23
+ export const CHANNEL_IDS = [
24
+ "telegram",
25
+ "phone",
26
+ "vellum",
27
+ "whatsapp",
28
+ "slack",
29
+ "email",
30
+ "platform",
31
+ "a2a",
32
+ ] as const;
33
+
34
+ export type ChannelId = (typeof CHANNEL_IDS)[number];
35
+
36
+ export function isChannelId(value: unknown): value is ChannelId {
37
+ return (
38
+ typeof value === "string" &&
39
+ (CHANNEL_IDS as readonly string[]).includes(value)
40
+ );
41
+ }
@@ -18,6 +18,7 @@
18
18
  * module so that both sides can depend on it without circular references.
19
19
  */
20
20
 
21
+ export * from "./channels.js";
21
22
  export * from "./transport.js";
22
23
  export * from "./error.js";
23
24
  export * from "./handles.js";