@vellumai/assistant 0.8.5 → 0.8.6

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 (544) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +1 -1
  3. package/bunfig.toml +6 -1
  4. package/docs/credential-execution-service.md +6 -6
  5. package/docs/plugins.md +4 -3
  6. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  7. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  9. package/openapi.yaml +1900 -166
  10. package/package.json +1 -1
  11. package/src/__tests__/actor-token-service.test.ts +3 -2
  12. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  13. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  14. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  15. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  16. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  17. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  18. package/src/__tests__/approval-cascade.test.ts +1 -0
  19. package/src/__tests__/approval-routes-http.test.ts +9 -13
  20. package/src/__tests__/assert-not-live-db.ts +79 -0
  21. package/src/__tests__/assistant-feature-flags-integration.test.ts +9 -25
  22. package/src/__tests__/audit-log-rotation.test.ts +2 -2
  23. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  24. package/src/__tests__/background-workers-disk-pressure.test.ts +5 -8
  25. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  26. package/src/__tests__/btw-routes.test.ts +3 -2
  27. package/src/__tests__/call-controller.test.ts +3 -2
  28. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  29. package/src/__tests__/channel-guardian.test.ts +3 -2
  30. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  31. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  32. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  33. package/src/__tests__/checker.test.ts +12 -12
  34. package/src/__tests__/compaction-events.test.ts +1 -0
  35. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  36. package/src/__tests__/compactor-call-site-logging.test.ts +1 -0
  37. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  38. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +7 -5
  39. package/src/__tests__/computer-use-tools.test.ts +12 -14
  40. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  41. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  42. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  43. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  44. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  45. package/src/__tests__/config-schema.test.ts +10 -10
  46. package/src/__tests__/connection-model-compat.test.ts +83 -0
  47. package/src/__tests__/contacts-tools.test.ts +3 -2
  48. package/src/__tests__/context-token-estimator.test.ts +22 -0
  49. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  50. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -0
  51. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  52. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  53. package/src/__tests__/conversation-agent-loop-overflow.test.ts +34 -0
  54. package/src/__tests__/conversation-agent-loop.test.ts +488 -2
  55. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  56. package/src/__tests__/conversation-app-control-instantiation.test.ts +29 -19
  57. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  58. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  59. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  60. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  61. package/src/__tests__/conversation-error.test.ts +30 -0
  62. package/src/__tests__/conversation-fork-crud.test.ts +69 -8
  63. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  64. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  65. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  66. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  67. package/src/__tests__/conversation-lifecycle.test.ts +1 -0
  68. package/src/__tests__/conversation-list-source.test.ts +3 -2
  69. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  70. package/src/__tests__/conversation-load-history-stripped.test.ts +1 -0
  71. package/src/__tests__/conversation-pairing.test.ts +53 -0
  72. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  73. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  74. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -0
  75. package/src/__tests__/conversation-queue.test.ts +333 -291
  76. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -18
  77. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  78. package/src/__tests__/conversation-routes-slash-commands.test.ts +33 -2
  79. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  80. package/src/__tests__/conversation-skill-tools.test.ts +38 -142
  81. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  82. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  83. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  84. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  85. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  86. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  87. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  88. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  89. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  90. package/src/__tests__/conversation-sync-tags.test.ts +128 -12
  91. package/src/__tests__/conversation-title-service.test.ts +1 -0
  92. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  93. package/src/__tests__/conversation-usage.test.ts +1 -0
  94. package/src/__tests__/conversation-workspace-cache-state.test.ts +1 -0
  95. package/src/__tests__/conversation-workspace-injection.test.ts +5 -0
  96. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -0
  97. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  98. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  99. package/src/__tests__/credential-execution-client.test.ts +72 -1
  100. package/src/__tests__/credential-execution-feature-gates.test.ts +10 -12
  101. package/src/__tests__/credential-health-service.test.ts +252 -3
  102. package/src/__tests__/credential-security-invariants.test.ts +5 -5
  103. package/src/__tests__/credential-vault-unit.test.ts +19 -19
  104. package/src/__tests__/credential-vault.test.ts +5 -5
  105. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  106. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  107. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  108. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  109. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  110. package/src/__tests__/db-test-helpers.ts +58 -0
  111. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  112. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  113. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  114. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  115. package/src/__tests__/dm-persistence.test.ts +26 -40
  116. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  117. package/src/__tests__/document-find-replace.test.ts +3 -2
  118. package/src/__tests__/document-tool-security.test.ts +81 -2
  119. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  120. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  121. package/src/__tests__/encrypted-store.test.ts +11 -9
  122. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  123. package/src/__tests__/filing-service.test.ts +1 -0
  124. package/src/__tests__/first-greeting.test.ts +62 -12
  125. package/src/__tests__/gateway-flag-listener.test.ts +0 -1
  126. package/src/__tests__/gemini-provider.test.ts +26 -0
  127. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  128. package/src/__tests__/guardian-outbound-http.test.ts +3 -2
  129. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  130. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -0
  131. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  132. package/src/__tests__/heartbeat-service.test.ts +1 -0
  133. package/src/__tests__/helpers/mock-logger.ts +26 -0
  134. package/src/__tests__/host-bash-routes.test.ts +1 -0
  135. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  136. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  137. package/src/__tests__/host-shell-tool.test.ts +5 -4
  138. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  139. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  140. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  141. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  142. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  143. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  144. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  145. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  146. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  147. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  148. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  149. package/src/__tests__/llm-resolver.test.ts +331 -0
  150. package/src/__tests__/llm-schema.test.ts +1 -1
  151. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  152. package/src/__tests__/mcp-abort-signal.test.ts +14 -0
  153. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  154. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  155. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  156. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  157. package/src/__tests__/model-intents.test.ts +3 -3
  158. package/src/__tests__/native-web-search.test.ts +30 -2
  159. package/src/__tests__/notification-deep-link.test.ts +62 -0
  160. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  161. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  162. package/src/__tests__/oauth-store.test.ts +3 -2
  163. package/src/__tests__/onboarding-template-contract.test.ts +3 -2
  164. package/src/__tests__/openai-provider.test.ts +8 -9
  165. package/src/__tests__/openai-responses-provider.test.ts +70 -10
  166. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  167. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  168. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  169. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  170. package/src/__tests__/plugin-bootstrap.test.ts +9 -11
  171. package/src/__tests__/plugin-tool-contribution.test.ts +41 -38
  172. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  173. package/src/__tests__/process-message-display-content.test.ts +19 -22
  174. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  175. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  176. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  177. package/src/__tests__/recording-handler.test.ts +1 -0
  178. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  179. package/src/__tests__/registry.test.ts +82 -76
  180. package/src/__tests__/relay-server.test.ts +10 -10
  181. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  182. package/src/__tests__/schedule-store.test.ts +16 -1
  183. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  184. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  185. package/src/__tests__/secure-keys.test.ts +3 -3
  186. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  187. package/src/__tests__/server-history-render.test.ts +4 -1
  188. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  189. package/src/__tests__/skill-feature-flags.test.ts +14 -16
  190. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  191. package/src/__tests__/skill-projection-feature-flag.test.ts +44 -30
  192. package/src/__tests__/skill-projection.benchmark.test.ts +5 -7
  193. package/src/__tests__/skill-tool-factory.test.ts +96 -95
  194. package/src/__tests__/slack-channel-config.test.ts +3 -3
  195. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  196. package/src/__tests__/subagent-disposal.test.ts +27 -8
  197. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  198. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  199. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  200. package/src/__tests__/subagent-notify-parent.test.ts +5 -4
  201. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  202. package/src/__tests__/subagent-tools.test.ts +2 -1
  203. package/src/__tests__/suggestion-routes.test.ts +1 -0
  204. package/src/__tests__/system-prompt.test.ts +38 -0
  205. package/src/__tests__/test-preload-verifier.ts +68 -0
  206. package/src/__tests__/test-preload.ts +32 -39
  207. package/src/__tests__/tool-executor-lifecycle-events.test.ts +20 -7
  208. package/src/__tests__/tool-executor.test.ts +55 -10
  209. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  210. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  211. package/src/__tests__/twilio-routes.test.ts +3 -2
  212. package/src/__tests__/validate-input.test.ts +381 -0
  213. package/src/__tests__/verification-control-plane-policy.test.ts +1 -0
  214. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  215. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  216. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  217. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  218. package/src/acp/session-manager.ts +5 -6
  219. package/src/agent/loop.ts +80 -0
  220. package/src/api/README.md +124 -2
  221. package/src/api/constants/call-sites.ts +27 -0
  222. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  223. package/src/api/events/assistant-text-delta.ts +32 -0
  224. package/src/api/events/assistant-turn-start.ts +33 -0
  225. package/src/api/events/document-comment-created.ts +48 -0
  226. package/src/api/events/document-comment-deleted.ts +24 -0
  227. package/src/api/events/document-comment-reopened.ts +25 -0
  228. package/src/api/events/document-comment-resolved.ts +27 -0
  229. package/src/api/events/generation-cancelled.ts +24 -0
  230. package/src/api/events/generation-handoff.ts +41 -0
  231. package/src/api/events/message-complete.ts +42 -0
  232. package/src/api/events/open-url.ts +30 -0
  233. package/src/{events → api/events}/relationship-state-updated.ts +3 -3
  234. package/src/api/events/tool-use-start.ts +32 -0
  235. package/src/api/index.ts +128 -3
  236. package/src/api/responses/llm-context-response.ts +39 -0
  237. package/src/api/responses/llm-request-log-entry.ts +93 -0
  238. package/src/api/responses/memory-recall-log.ts +65 -0
  239. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  240. package/src/background-wake/background-wake-routes.test.ts +687 -52
  241. package/src/background-wake/platform-client.test.ts +308 -0
  242. package/src/background-wake/platform-client.ts +167 -0
  243. package/src/background-wake/publisher.ts +91 -0
  244. package/src/background-wake/runtime-registry.ts +2 -2
  245. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  246. package/src/calls/guardian-dispatch.ts +1 -0
  247. package/src/calls/voice-session-bridge.ts +4 -4
  248. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  249. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  250. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  251. package/src/cli/commands/channels/index.ts +229 -0
  252. package/src/cli/commands/memory-v3-render.ts +147 -0
  253. package/src/cli/commands/memory-v3.ts +255 -4
  254. package/src/cli/commands/notifications.ts +365 -55
  255. package/src/cli/lib/open-browser.ts +7 -2
  256. package/src/cli/program.ts +2 -0
  257. package/src/config/assistant-feature-flags.ts +23 -42
  258. package/src/config/bundled-skills/document-editor/SKILL.md +5 -1
  259. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  260. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  261. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  262. package/src/config/call-site-defaults.ts +1 -1
  263. package/src/config/feature-flag-cache.ts +86 -0
  264. package/src/config/feature-flag-registry.json +17 -17
  265. package/src/config/llm-context-resolution.ts +10 -1
  266. package/src/config/llm-resolver.ts +121 -15
  267. package/src/config/loader.ts +4 -5
  268. package/src/config/schemas/__tests__/memory-v2.test.ts +15 -0
  269. package/src/config/schemas/heartbeat.ts +1 -1
  270. package/src/config/schemas/llm.ts +90 -1
  271. package/src/config/schemas/memory-v2.ts +26 -0
  272. package/src/config/schemas/services.ts +6 -2
  273. package/src/config/seed-inference-profiles.ts +36 -16
  274. package/src/context/token-estimator.ts +10 -5
  275. package/src/credential-execution/executable-discovery.ts +40 -0
  276. package/src/credential-execution/process-manager.ts +6 -2
  277. package/src/credential-health/credential-health-service.ts +125 -40
  278. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  279. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  280. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -2
  281. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  282. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  283. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  284. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  285. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  286. package/src/daemon/conversation-agent-loop-handlers.ts +389 -68
  287. package/src/daemon/conversation-agent-loop.ts +132 -28
  288. package/src/daemon/conversation-error.ts +33 -5
  289. package/src/daemon/conversation-messaging.ts +84 -43
  290. package/src/daemon/conversation-process.ts +74 -37
  291. package/src/daemon/conversation-runtime-assembly.ts +29 -9
  292. package/src/daemon/conversation-skill-tools.ts +14 -30
  293. package/src/daemon/conversation-surfaces.ts +69 -34
  294. package/src/daemon/conversation-tool-setup.ts +33 -48
  295. package/src/daemon/conversation.ts +26 -46
  296. package/src/daemon/daemon-control.ts +1 -1
  297. package/src/daemon/daemon-skill-host.ts +9 -2
  298. package/src/daemon/disk-pressure-guard.ts +27 -29
  299. package/src/daemon/first-greeting.ts +31 -13
  300. package/src/daemon/handlers/shared.ts +6 -1
  301. package/src/daemon/lifecycle.ts +12 -12
  302. package/src/daemon/mcp-reload-service.ts +1 -1
  303. package/src/daemon/meet-manifest-loader.ts +10 -17
  304. package/src/daemon/message-types/conversations.ts +20 -22
  305. package/src/daemon/message-types/document-comments.ts +8 -44
  306. package/src/daemon/message-types/home.ts +2 -2
  307. package/src/daemon/message-types/integrations.ts +2 -7
  308. package/src/daemon/message-types/messages.ts +23 -38
  309. package/src/daemon/message-types/subagents.ts +6 -0
  310. package/src/daemon/process-message.ts +9 -9
  311. package/src/daemon/providers-setup.ts +1 -1
  312. package/src/daemon/server.ts +16 -0
  313. package/src/daemon/switch-inference-profile-tool.ts +13 -3
  314. package/src/daemon/tool-setup-types.ts +0 -6
  315. package/src/daemon/wake-target-adapter.ts +10 -0
  316. package/src/documents/document-store.ts +38 -0
  317. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  318. package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -0
  319. package/src/heartbeat/heartbeat-service.ts +63 -0
  320. package/src/home/__tests__/feed-writer.test.ts +161 -0
  321. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  322. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  323. package/src/home/feed-writer.ts +146 -7
  324. package/src/home/suggested-prompts.ts +27 -145
  325. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  326. package/src/ipc/gateway-client.test.ts +4 -1
  327. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  328. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  329. package/src/ipc/skill-routes/memory.ts +4 -3
  330. package/src/ipc/skill-routes/registries.ts +28 -29
  331. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +1 -0
  332. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  333. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  334. package/src/memory/__tests__/memory-retrospective-job.test.ts +1 -0
  335. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  336. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  337. package/src/memory/conversation-attention-store.ts +17 -3
  338. package/src/memory/conversation-crud.ts +352 -112
  339. package/src/memory/db-connection.ts +29 -19
  340. package/src/memory/db-init.ts +4 -0
  341. package/src/memory/db-singleton.ts +77 -0
  342. package/src/memory/delivery-channels.ts +82 -0
  343. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  344. package/src/memory/graph/retriever.test.ts +3 -3
  345. package/src/memory/job-handlers/embedding.test.ts +3 -2
  346. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  347. package/src/memory/jobs-worker.ts +12 -1
  348. package/src/memory/llm-request-log-source-clickhouse.ts +80 -0
  349. package/src/memory/llm-request-log-source-local.ts +24 -0
  350. package/src/memory/llm-request-log-source.ts +31 -0
  351. package/src/memory/llm-request-log-store.ts +188 -3
  352. package/src/memory/memory-v2-activation-log-store.ts +95 -1
  353. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  354. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  355. package/src/memory/migrations/index.ts +2 -0
  356. package/src/memory/schema/conversations.ts +9 -1
  357. package/src/memory/schema/inference.ts +0 -1
  358. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  359. package/src/memory/v2/__tests__/harness-metrics.test.ts +9 -0
  360. package/src/memory/v2/__tests__/harness-replay-input.test.ts +9 -4
  361. package/src/memory/v2/__tests__/harness-runner.test.ts +26 -0
  362. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  363. package/src/memory/v2/harness/metrics.ts +5 -1
  364. package/src/memory/v2/harness/replay-input.ts +19 -3
  365. package/src/memory/v2/harness/runner.ts +6 -0
  366. package/src/memory/v2/harness/trace.ts +6 -0
  367. package/src/memory/v3/__tests__/consolidation-job.test.ts +2 -4
  368. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  369. package/src/memory/v3/__tests__/edges.test.ts +144 -1
  370. package/src/memory/v3/__tests__/filter.test.ts +48 -0
  371. package/src/memory/v3/__tests__/gate.test.ts +96 -33
  372. package/src/memory/v3/__tests__/index-composition.test.ts +58 -0
  373. package/src/memory/v3/__tests__/loop.test.ts +250 -5
  374. package/src/memory/v3/__tests__/scouts.test.ts +49 -0
  375. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  376. package/src/memory/v3/__tests__/shadow-middleware.test.ts +88 -2
  377. package/src/memory/v3/__tests__/traversal.test.ts +39 -0
  378. package/src/memory/v3/__tests__/tree-walk.test.ts +77 -0
  379. package/src/memory/v3/__tests__/validate.test.ts +32 -0
  380. package/src/memory/v3/coretrieval-seed.ts +240 -0
  381. package/src/memory/v3/edges.ts +58 -21
  382. package/src/memory/v3/filter.ts +27 -22
  383. package/src/memory/v3/gate.ts +51 -36
  384. package/src/memory/v3/index-composition.ts +18 -5
  385. package/src/memory/v3/loop.ts +65 -17
  386. package/src/memory/v3/scouts.ts +15 -4
  387. package/src/memory/v3/shadow-diff.ts +287 -0
  388. package/src/memory/v3/shadow-middleware.ts +44 -2
  389. package/src/memory/v3/traversal.ts +6 -1
  390. package/src/memory/v3/tree-walk.ts +6 -1
  391. package/src/memory/v3/validate.ts +56 -33
  392. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  393. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  394. package/src/notifications/adapters/slack.ts +45 -11
  395. package/src/notifications/broadcaster.ts +114 -63
  396. package/src/notifications/conversation-pairing.ts +23 -3
  397. package/src/notifications/decisions-store.ts +32 -1
  398. package/src/notifications/deliveries-store.ts +45 -0
  399. package/src/notifications/edit-notification.ts +201 -0
  400. package/src/notifications/emit-signal.ts +11 -1
  401. package/src/notifications/signal.ts +10 -0
  402. package/src/notifications/types.ts +37 -0
  403. package/src/oauth/byo-connection.test.ts +67 -3
  404. package/src/oauth/byo-connection.ts +32 -5
  405. package/src/oauth/connect-orchestrator.ts +9 -0
  406. package/src/oauth/connection-resolver.test.ts +76 -0
  407. package/src/oauth/connection-resolver.ts +49 -10
  408. package/src/oauth/manual-token-connection.ts +51 -3
  409. package/src/oauth/seed-providers.ts +3 -0
  410. package/src/permissions/approval-policy.test.ts +19 -5
  411. package/src/permissions/approval-policy.ts +14 -3
  412. package/src/permissions/checker.ts +21 -8
  413. package/src/platform/client.test.ts +24 -1
  414. package/src/platform/client.ts +8 -0
  415. package/src/platform/feature-gate.ts +15 -0
  416. package/src/plugins/defaults/injectors.ts +2 -8
  417. package/src/plugins/defaults/persistence.ts +25 -6
  418. package/src/plugins/types.ts +57 -13
  419. package/src/proactive-artifact/job.test.ts +1 -0
  420. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  421. package/src/prompts/system-prompt.ts +38 -40
  422. package/src/prompts/template-detection.ts +10 -4
  423. package/src/prompts/templates/BOOTSTRAP.md +7 -11
  424. package/src/prompts/templates/IDENTITY.md +0 -2
  425. package/src/providers/__tests__/connection-model-compat.test.ts +3 -4
  426. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  427. package/src/providers/call-site-routing.ts +33 -9
  428. package/src/providers/connection-model-compat.ts +23 -0
  429. package/src/providers/connection-resolution.ts +39 -20
  430. package/src/providers/fireworks/client.ts +1 -0
  431. package/src/providers/gemini/client.ts +24 -3
  432. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  433. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  434. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  435. package/src/providers/inference/auth.ts +0 -8
  436. package/src/providers/inference/connections.ts +3 -66
  437. package/src/providers/inference/resolve-auth.ts +2 -3
  438. package/src/providers/model-catalog.ts +35 -1
  439. package/src/providers/model-intents.ts +3 -3
  440. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  441. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  442. package/src/providers/openai/chat-completions-provider.ts +110 -12
  443. package/src/providers/openai/codex-models.ts +2 -0
  444. package/src/providers/openai/responses-provider.ts +53 -53
  445. package/src/providers/openrouter/client.ts +13 -8
  446. package/src/providers/provider-send-message.ts +18 -9
  447. package/src/providers/registry.ts +48 -8
  448. package/src/providers/retry.ts +16 -4
  449. package/src/providers/search-provider-catalog.ts +17 -9
  450. package/src/providers/types.ts +9 -0
  451. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  452. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  453. package/src/runtime/access-request-helper.ts +1 -0
  454. package/src/runtime/auth/route-policy.ts +10 -0
  455. package/src/runtime/channel-readiness-service.ts +68 -0
  456. package/src/runtime/channel-reply-delivery.ts +23 -0
  457. package/src/runtime/channel-retry-sweep.ts +47 -14
  458. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  459. package/src/runtime/migrations/vbundle-builder.ts +3 -2
  460. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  461. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  462. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +98 -0
  463. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  464. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  465. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  466. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +51 -3
  467. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  468. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  469. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  470. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  471. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  472. package/src/runtime/routes/app-management-routes.ts +111 -4
  473. package/src/runtime/routes/background-wake-routes.ts +188 -20
  474. package/src/runtime/routes/btw-routes.ts +4 -4
  475. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  476. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  477. package/src/runtime/routes/conversation-list-routes.ts +147 -0
  478. package/src/runtime/routes/conversation-management-routes.ts +39 -14
  479. package/src/runtime/routes/conversation-query-routes.ts +60 -10
  480. package/src/runtime/routes/conversation-routes.ts +186 -140
  481. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  482. package/src/runtime/routes/documents-routes.ts +10 -1
  483. package/src/runtime/routes/group-routes.ts +11 -0
  484. package/src/runtime/routes/home-feed-routes.ts +129 -0
  485. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  486. package/src/runtime/routes/identity-routes.ts +30 -9
  487. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  488. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  489. package/src/runtime/routes/index.ts +2 -0
  490. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  491. package/src/runtime/routes/integrations/vercel.ts +15 -0
  492. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  493. package/src/runtime/routes/memory-v3-routes.ts +160 -2
  494. package/src/runtime/routes/migration-routes.ts +20 -13
  495. package/src/runtime/routes/notification-routes.ts +63 -1
  496. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  497. package/src/runtime/routes/surface-action-routes.ts +1 -38
  498. package/src/runtime/routes/surface-content-routes.ts +12 -5
  499. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  500. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  501. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  502. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  503. package/src/runtime/sync/resource-sync-events.ts +1 -1
  504. package/src/runtime/tool-grant-request-helper.ts +1 -0
  505. package/src/schedule/schedule-store.ts +8 -1
  506. package/src/schedule/scheduler.ts +111 -15
  507. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  508. package/src/security/encrypted-store.ts +7 -16
  509. package/src/security/store-path-override.ts +61 -0
  510. package/src/signals/user-message.ts +5 -8
  511. package/src/skills/validate-input.ts +177 -0
  512. package/src/subagent/manager.ts +13 -13
  513. package/src/subagent/types.ts +6 -0
  514. package/src/tasks/tool-sanitizer.ts +2 -2
  515. package/src/tools/apps/definitions.ts +35 -21
  516. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  517. package/src/tools/computer-use/definitions.ts +268 -266
  518. package/src/tools/document/document-tool.ts +131 -8
  519. package/src/tools/execution-target.ts +2 -5
  520. package/src/tools/executor.ts +18 -55
  521. package/src/tools/host-filesystem/edit.test.ts +1 -0
  522. package/src/tools/host-filesystem/read.test.ts +1 -0
  523. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  524. package/src/tools/host-filesystem/write.test.ts +1 -0
  525. package/src/tools/mcp/mcp-tool-factory.ts +0 -2
  526. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  527. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  528. package/src/tools/network/managed-search-proxy.ts +183 -0
  529. package/src/tools/network/web-search.ts +199 -44
  530. package/src/tools/policy-context.ts +3 -1
  531. package/src/tools/registry.ts +146 -103
  532. package/src/tools/schedule/create.ts +1 -1
  533. package/src/tools/skills/skill-tool-factory.ts +17 -36
  534. package/src/tools/subagent/spawn.ts +3 -0
  535. package/src/tools/tool-approval-handler.ts +10 -4
  536. package/src/tools/tool-name-aliases.ts +72 -14
  537. package/src/tools/types.ts +17 -15
  538. package/src/tools/ui-surface/definitions.ts +98 -86
  539. package/src/types/onboarding-context.ts +6 -0
  540. package/src/usage/attribution.ts +32 -1
  541. package/src/util/browser.ts +7 -2
  542. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  543. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  544. package/src/workspace/migrations/registry.ts +4 -0
@@ -29,10 +29,18 @@ const log = getLogger("provider-registry");
29
29
  const providers = new Map<string, Provider>();
30
30
  const routingSources = new Map<string, "user-key" | "managed-proxy">();
31
31
  const OPENAI_COMPATIBLE_ENDPOINTS_FLAG = "openai-compatible-endpoints";
32
+ const NATIVE_WEB_SEARCH_PROVIDER_IDS = new Set(["anthropic", "openai"]);
32
33
 
33
- /** Per-connection provider cache, keyed by connection name. */
34
+ /** Per-connection provider cache, keyed by connection name and model. */
34
35
  const connectionProviders = new Map<string, Provider>();
35
36
 
37
+ function getConnectionProviderCacheKey(
38
+ connection: ProviderConnection,
39
+ model: string,
40
+ ): string {
41
+ return `${connection.name}\u0000${model}`;
42
+ }
43
+
36
44
  function registerProvider(name: string, provider: Provider): void {
37
45
  providers.set(name, new UsageTrackingProvider(provider));
38
46
  }
@@ -98,6 +106,30 @@ function resolveModel(config: ProvidersConfig, providerName: string): string {
98
106
  return getProviderDefaultModel(providerName);
99
107
  }
100
108
 
109
+ export function isNativeWebSearchCapableProvider(
110
+ providerName: string,
111
+ model: string,
112
+ ): boolean {
113
+ if (NATIVE_WEB_SEARCH_PROVIDER_IDS.has(providerName)) {
114
+ return true;
115
+ }
116
+ if (providerName === "openrouter" && model.startsWith("anthropic/")) {
117
+ return true;
118
+ }
119
+ return false;
120
+ }
121
+
122
+ function shouldUseNativeWebSearch(
123
+ config: ProvidersConfig,
124
+ providerName: string,
125
+ model: string,
126
+ ): boolean {
127
+ return (
128
+ config.services["web-search"].provider === "inference-provider-native" &&
129
+ isNativeWebSearchCapableProvider(providerName, model)
130
+ );
131
+ }
132
+
101
133
  /**
102
134
  * Resolve provider credentials. User key takes precedence; managed proxy is
103
135
  * used as a fallback when platform prerequisites are available.
@@ -135,8 +167,6 @@ export async function initializeProviders(
135
167
 
136
168
  const streamTimeoutMs =
137
169
  (config.timeouts?.providerStreamTimeoutSec ?? 1800) * 1000;
138
- const useNativeWebSearch =
139
- config.services["web-search"].provider === "inference-provider-native";
140
170
  const mainAgentProvider = resolveCallSiteConfig(
141
171
  "mainAgent",
142
172
  config.llm,
@@ -174,6 +204,11 @@ export async function initializeProviders(
174
204
  }
175
205
 
176
206
  const model = resolveModel(config, entry.id);
207
+ const useNativeWebSearch = shouldUseNativeWebSearch(
208
+ config,
209
+ entry.id,
210
+ model,
211
+ );
177
212
  const adapter = buildProviderAdapter(entry.id, {
178
213
  apiKey,
179
214
  model,
@@ -221,6 +256,7 @@ export async function initializeProviders(
221
256
  export async function resolveProviderFromConnection(
222
257
  connection: ProviderConnection,
223
258
  config: ProvidersConfig,
259
+ opts: { model?: string } = {},
224
260
  ): Promise<Provider | null> {
225
261
  if (
226
262
  connection.provider === "openai-compatible" &&
@@ -229,7 +265,9 @@ export async function resolveProviderFromConnection(
229
265
  return null;
230
266
  }
231
267
 
232
- const cached = connectionProviders.get(connection.name);
268
+ const model = opts.model ?? resolveModel(config, connection.provider);
269
+ const cacheKey = getConnectionProviderCacheKey(connection, model);
270
+ const cached = connectionProviders.get(cacheKey);
233
271
  if (cached) return cached;
234
272
 
235
273
  const authResult = await resolveAuth(connection.auth, connection.provider, {
@@ -259,9 +297,11 @@ export async function resolveProviderFromConnection(
259
297
 
260
298
  const streamTimeoutMs =
261
299
  (config.timeouts?.providerStreamTimeoutSec ?? 1800) * 1000;
262
- const useNativeWebSearch =
263
- config.services["web-search"].provider === "inference-provider-native";
264
- const model = resolveModel(config, connection.provider);
300
+ const useNativeWebSearch = shouldUseNativeWebSearch(
301
+ config,
302
+ connection.provider,
303
+ model,
304
+ );
265
305
 
266
306
  const provider = createAdapterFromConnection(
267
307
  connection,
@@ -274,7 +314,7 @@ export async function resolveProviderFromConnection(
274
314
  );
275
315
 
276
316
  if (provider) {
277
- connectionProviders.set(connection.name, provider);
317
+ connectionProviders.set(cacheKey, provider);
278
318
  }
279
319
 
280
320
  return provider;
@@ -34,6 +34,7 @@ const USAGE_ATTRIBUTION_HEADER_NAMES = {
34
34
  inferenceProfileSource: "X-Vellum-Inference-Profile-Source",
35
35
  resolvedProvider: "X-Vellum-Resolved-Provider",
36
36
  resolvedModel: "X-Vellum-Resolved-Model",
37
+ resolvedMixArm: "X-Vellum-Resolved-Mix-Arm",
37
38
  } as const;
38
39
 
39
40
  /** Providers that support the `effort` config (extended thinking / reasoning). */
@@ -195,19 +196,23 @@ function normalizeSendMessageOptions(
195
196
  delete nextConfig.usageAttributionHeaders;
196
197
  delete nextConfig.usageTracking;
197
198
 
198
- // `overrideProfile` is a routing/resolution-time concern (consumed by the
199
- // resolver below and `CallSiteRoutingProvider`'s provider selection); it is
200
- // not a wire-format field. Strip unconditionally so it never leaks into
201
- // provider request bodies even when callers set it without a `callSite`.
199
+ // `overrideProfile` and `selectionSeed` are routing/resolution-time concerns
200
+ // (consumed by the resolver below and `CallSiteRoutingProvider`'s provider
201
+ // selection); neither is a wire-format field. Strip unconditionally so they
202
+ // never leak into provider request bodies even when callers set them without
203
+ // a `callSite`.
202
204
  delete nextConfig.overrideProfile;
205
+ delete nextConfig.selectionSeed;
203
206
 
204
207
  if (config.callSite !== undefined) {
205
208
  const resolved = resolveCallSiteConfig(config.callSite, getConfig().llm, {
206
209
  overrideProfile: config.overrideProfile,
210
+ selectionSeed: config.selectionSeed,
207
211
  });
208
212
  const attribution = resolveUsageAttribution({
209
213
  callSite: config.callSite,
210
214
  overrideProfile: config.overrideProfile,
215
+ selectionSeed: config.selectionSeed,
211
216
  });
212
217
 
213
218
  const explicitModel =
@@ -225,6 +230,7 @@ function normalizeSendMessageOptions(
225
230
  profileSource: attribution.profileSource,
226
231
  resolvedProvider: attribution.resolvedProvider,
227
232
  resolvedModel: attribution.resolvedModel,
233
+ resolvedMixArm: attribution.resolvedMixArm,
228
234
  });
229
235
  if (Object.keys(usageAttributionHeaders).length > 0) {
230
236
  nextConfig.usageAttributionHeaders = usageAttributionHeaders;
@@ -446,6 +452,7 @@ function buildUsageAttributionHeaders(input: {
446
452
  profileSource: string;
447
453
  resolvedProvider: string;
448
454
  resolvedModel: string;
455
+ resolvedMixArm: string | null;
449
456
  }): Record<string, string> {
450
457
  const headers: Record<string, string> = {};
451
458
  addSanitizedHeader(
@@ -475,6 +482,11 @@ function buildUsageAttributionHeaders(input: {
475
482
  USAGE_ATTRIBUTION_HEADER_NAMES.resolvedModel,
476
483
  input.resolvedModel,
477
484
  );
485
+ addSanitizedHeader(
486
+ headers,
487
+ USAGE_ATTRIBUTION_HEADER_NAMES.resolvedMixArm,
488
+ input.resolvedMixArm,
489
+ );
478
490
  return headers;
479
491
  }
480
492
 
@@ -42,8 +42,17 @@ export interface SearchProviderCatalogEntry {
42
42
  * privacy notices). Defaults to {@link displayName} when omitted.
43
43
  */
44
44
  readonly displayNameLong?: string;
45
- /** Authentication style. `managed` providers are routed through the
46
- * inference provider; `byok` providers require a user-supplied key. */
45
+ /**
46
+ * Authentication style for the search provider choice.
47
+ *
48
+ * `managed` means the choice does not require a user-supplied search API key.
49
+ * For `inference-provider-native`, the daemon uses the inference API's native
50
+ * hosted web-search tool only when the selected inference provider/model
51
+ * supports it. Managed non-native inference providers keep the app-executed
52
+ * `web_search` tool, which can route through the platform search proxy.
53
+ *
54
+ * `byok` providers require a user-supplied key in Your Own mode.
55
+ */
47
56
  readonly kind: SearchProviderKind;
48
57
  /** Placeholder shown in the API-key input. BYOK providers only. */
49
58
  readonly apiKeyPrefix?: string;
@@ -99,19 +108,18 @@ export const SEARCH_PROVIDER_CATALOG: readonly SearchProviderCatalogEntry[] = [
99
108
  ];
100
109
 
101
110
  /** Provider ids accepted by the web-search config schema. */
102
- export const SEARCH_PROVIDER_IDS: readonly string[] = SEARCH_PROVIDER_CATALOG.map(
103
- (p) => p.id,
104
- );
111
+ export const SEARCH_PROVIDER_IDS: readonly string[] =
112
+ SEARCH_PROVIDER_CATALOG.map((p) => p.id);
105
113
 
106
114
  /** Catalog entries that store an API key under their bare provider name. */
107
115
  export const BYOK_SEARCH_PROVIDERS: readonly SearchProviderCatalogEntry[] =
108
116
  SEARCH_PROVIDER_CATALOG.filter((p) => p.kind === "byok");
109
117
 
110
118
  /** BYOK provider ids, ordered by `fallbackOrder` (ascending). */
111
- export const SEARCH_PROVIDER_FALLBACK_ORDER: readonly string[] = BYOK_SEARCH_PROVIDERS
112
- .slice()
113
- .sort((a, b) => (a.fallbackOrder ?? 0) - (b.fallbackOrder ?? 0))
114
- .map((p) => p.id);
119
+ export const SEARCH_PROVIDER_FALLBACK_ORDER: readonly string[] =
120
+ BYOK_SEARCH_PROVIDERS.slice()
121
+ .sort((a, b) => (a.fallbackOrder ?? 0) - (b.fallbackOrder ?? 0))
122
+ .map((p) => p.id);
115
123
 
116
124
  /** Look up a single catalog entry by id. Returns `undefined` if unknown. */
117
125
  export function getSearchProvider(
@@ -182,6 +182,15 @@ export interface SendMessageConfig {
182
182
  * silently fall through.
183
183
  */
184
184
  overrideProfile?: string;
185
+ /**
186
+ * Per-conversation seed for deterministic `mix`-profile expansion. The agent
187
+ * loop sets this to the conversation id so every resolver call this send
188
+ * triggers — provider/transport selection, wire-param normalization, usage
189
+ * attribution — picks the same mix constituent, stable across the
190
+ * conversation's turns and retries. A resolution/routing-time concern only;
191
+ * stripped before any provider wire request.
192
+ */
193
+ selectionSeed?: string;
185
194
  /**
186
195
  * Internal per-request HTTP headers for managed-proxy usage attribution.
187
196
  * Provider clients may pass these through SDK request options only when the
@@ -29,6 +29,7 @@ import type { DiskPressureStatus } from "../../daemon/disk-pressure-guard.js";
29
29
  mock.module("../../memory/conversation-crud.js", () => ({
30
30
  getConversationOverrideProfile: () => undefined,
31
31
  getConversation: () => ({ archivedAt: null }),
32
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
32
33
  }));
33
34
 
34
35
  const mockGetOrCreateConversationCalls: Array<{
@@ -40,6 +40,7 @@ mock.module("../../memory/conversation-crud.js", () => ({
40
40
  addMessageCalls.push({ conversationId, role, content });
41
41
  return { id: `msg-${addMessageCalls.length}` };
42
42
  },
43
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
43
44
  }));
44
45
 
45
46
  let processMessageImpl: (
@@ -217,6 +217,7 @@ export function notifyGuardianOfAccessRequest(
217
217
  sourceEventName: "ingress.access_request",
218
218
  sourceChannel: sourceChannel as NotificationSourceChannel,
219
219
  sourceContextId: `access-req-${sourceChannel}-${actorExternalId}`,
220
+ requiresConversation: true,
220
221
  ...(sameChannelOnly ? { routingIntent: "single_channel" as const } : {}),
221
222
  attentionHints: {
222
223
  requiresAction: true,
@@ -209,6 +209,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
209
209
  { endpoint: "identity/intro", scopes: ["settings.read"] },
210
210
  { endpoint: "home/state", scopes: ["settings.read"] },
211
211
  { endpoint: "home/feed", scopes: ["settings.read"] },
212
+ { endpoint: "home/feed/query", scopes: ["settings.read"] },
212
213
  { endpoint: "home/feed:PATCH", scopes: ["settings.write"] },
213
214
  { endpoint: "home/feed/actions", scopes: ["settings.write"] },
214
215
  { endpoint: "brain-graph", scopes: ["settings.read"] },
@@ -442,6 +443,7 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
442
443
  { endpoint: "messages/content", scopes: ["chat.read"] },
443
444
  { endpoint: "messages/llm-context", scopes: ["chat.read"] },
444
445
  { endpoint: "conversations/llm-context", scopes: ["chat.read"] },
446
+ { endpoint: "conversations/compaction", scopes: ["chat.read"] },
445
447
  { endpoint: "llm-request-logs/payload", scopes: ["chat.read"] },
446
448
  { endpoint: "messages/tts", scopes: ["chat.read"] },
447
449
  { endpoint: "tts/synthesize", scopes: ["chat.read"] },
@@ -490,6 +492,8 @@ const ACTOR_ENDPOINTS: Array<{ endpoint: string; scopes: Scope[] }> = [
490
492
  { endpoint: "memory/v3/validate:POST", scopes: ["settings.read"] },
491
493
  { endpoint: "memory/v3/tree:POST", scopes: ["settings.read"] },
492
494
  { endpoint: "memory/v3/simulate:POST", scopes: ["settings.read"] },
495
+ { endpoint: "memory/v3/shadow-diff:POST", scopes: ["settings.read"] },
496
+ { endpoint: "memory/v3/seed-edges:POST", scopes: ["settings.write"] },
493
497
 
494
498
  // Trust rule listing
495
499
  { endpoint: "trust-rules/manage:GET", scopes: ["settings.read"] },
@@ -868,6 +872,12 @@ registerPolicy("notifications/events", {
868
872
  allowedPrincipalTypes: ["local"],
869
873
  });
870
874
 
875
+ // Edit an already-sent notification: local-only (CLI / IPC callers)
876
+ registerPolicy("notifications/edit", {
877
+ requiredScopes: ["settings.write"],
878
+ allowedPrincipalTypes: ["local"],
879
+ });
880
+
871
881
  // Defer operations: local-only (CLI / IPC callers)
872
882
  registerPolicy("defer/create", {
873
883
  requiredScopes: ["settings.write"],
@@ -282,6 +282,74 @@ const slackProbe: ChannelProbe = {
282
282
  ),
283
283
  ];
284
284
  },
285
+ async runRemoteChecks(): Promise<ReadinessCheckResult[]> {
286
+ const botToken = await getSecureKeyAsync(
287
+ credentialKey("slack_channel", "bot_token"),
288
+ );
289
+ if (!botToken) {
290
+ return [
291
+ check(
292
+ "auth_test",
293
+ false,
294
+ "Slack auth.test ok",
295
+ "Skipped: no bot_token stored",
296
+ ),
297
+ ];
298
+ }
299
+ try {
300
+ const res = await fetch("https://slack.com/api/auth.test", {
301
+ method: "POST",
302
+ headers: { Authorization: `Bearer ${botToken}` },
303
+ });
304
+ const data = (await res.json()) as {
305
+ ok: boolean;
306
+ error?: string;
307
+ team_id?: string;
308
+ team?: string;
309
+ user?: string;
310
+ };
311
+ if (!data.ok) {
312
+ return [
313
+ check(
314
+ "auth_test",
315
+ false,
316
+ "Slack auth.test ok",
317
+ `Slack auth.test rejected bot_token: ${data.error ?? "unknown error"}`,
318
+ ),
319
+ ];
320
+ }
321
+ const raw = loadRawConfig();
322
+ const storedTeamId = getNestedValue(raw, "slack.teamId");
323
+ const teamMatches =
324
+ typeof storedTeamId !== "string" ||
325
+ storedTeamId.length === 0 ||
326
+ storedTeamId === data.team_id;
327
+ return [
328
+ check(
329
+ "auth_test",
330
+ true,
331
+ `Slack auth.test ok (workspace ${data.team ?? data.team_id ?? "unknown"}, bot ${data.user ?? "unknown"})`,
332
+ "Slack auth.test ok",
333
+ ),
334
+ check(
335
+ "workspace_match",
336
+ teamMatches,
337
+ "Stored workspace matches bot token",
338
+ `Stored workspace ${storedTeamId} does not match bot token's workspace ${data.team_id ?? "unknown"} — run 'assistant channels slack reconnect' to refresh metadata`,
339
+ ),
340
+ ];
341
+ } catch (err) {
342
+ const message = err instanceof Error ? err.message : String(err);
343
+ return [
344
+ check(
345
+ "auth_test",
346
+ false,
347
+ "Slack auth.test ok",
348
+ `Failed to reach Slack auth.test: ${message}`,
349
+ ),
350
+ ];
351
+ }
352
+ },
285
353
  };
286
354
 
287
355
  // ── Service ─────────────────────────────────────────────────────────────────
@@ -141,6 +141,29 @@ export async function deliverRenderedReplyViaCallback(
141
141
  return;
142
142
  }
143
143
 
144
+ if (startFromSegment >= deliverableSegments.length) {
145
+ if (replyAttachments) {
146
+ const result: ChannelDeliveryResult = await deliverChannelReply(
147
+ callbackUrl,
148
+ {
149
+ chatId,
150
+ attachments: replyAttachments,
151
+ assistantId,
152
+ ephemeral,
153
+ user,
154
+ messageTs,
155
+ },
156
+ );
157
+ const deliveredTs = result.ts ?? messageTs;
158
+ if (deliveredTs) {
159
+ onMessageTs?.(deliveredTs);
160
+ }
161
+ } else if (messageTs) {
162
+ onMessageTs?.(messageTs);
163
+ }
164
+ return;
165
+ }
166
+
144
167
  const isSlack = isSlackCallbackUrl(callbackUrl);
145
168
 
146
169
  // Only the first segment uses messageTs for in-place update;
@@ -11,7 +11,11 @@ import { getDiskPressureStatus } from "../daemon/disk-pressure-guard.js";
11
11
  import { classifyDiskPressureTurnPolicy } from "../daemon/disk-pressure-policy.js";
12
12
  import type { ServerMessage } from "../daemon/message-protocol.js";
13
13
  import type { TrustContext } from "../daemon/trust-context.js";
14
- import { updateDeliveredSegmentCount } from "../memory/delivery-channels.js";
14
+ import {
15
+ addSlackDmLiveDeliveredTextResponseIndex,
16
+ getSlackDmLiveDeliveredTextResponseIndexes,
17
+ updateDeliveredSegmentCount,
18
+ } from "../memory/delivery-channels.js";
15
19
  import {
16
20
  clearPayload,
17
21
  linkMessage,
@@ -33,6 +37,7 @@ import {
33
37
  } from "./channel-reply-delivery.js";
34
38
  import { deliverChannelReply } from "./gateway-client.js";
35
39
  import type { MessageProcessor } from "./http-types.js";
40
+ import { createSlackDmTextDeliveryController } from "./slack-dm-text-delivery.js";
36
41
  import { resolveRoutingStateFromRuntime } from "./trust-context-resolver.js";
37
42
 
38
43
  const log = getLogger("runtime-http");
@@ -258,6 +263,27 @@ export async function sweepFailedEvents(
258
263
  sourceMetadata.chatType.trim().length > 0
259
264
  ? sourceMetadata.chatType.trim()
260
265
  : undefined;
266
+ const replyCallbackUrl =
267
+ typeof payload.replyCallbackUrl === "string"
268
+ ? payload.replyCallbackUrl
269
+ : undefined;
270
+ const externalChatId =
271
+ typeof payload.externalChatId === "string"
272
+ ? payload.externalChatId
273
+ : undefined;
274
+ const slackDmTextDelivery = externalChatId
275
+ ? createSlackDmTextDeliveryController({
276
+ sourceChannel,
277
+ chatType: metadataChatType,
278
+ replyCallbackUrl,
279
+ chatId: externalChatId,
280
+ assistantId,
281
+ deliveredTextResponseIndexes:
282
+ getSlackDmLiveDeliveredTextResponseIndexes(event.id),
283
+ onTextResponseDelivered: (responseIndex) =>
284
+ addSlackDmLiveDeliveredTextResponseIndex(event.id, responseIndex),
285
+ })
286
+ : undefined;
261
287
  let replyMessageId: string | undefined;
262
288
  const observeAgentEvent = (msg: ServerMessage): void => {
263
289
  if (
@@ -267,6 +293,7 @@ export async function sweepFailedEvents(
267
293
  ) {
268
294
  replyMessageId = msg.messageId;
269
295
  }
296
+ slackDmTextDelivery?.observeEvent(msg);
270
297
  };
271
298
 
272
299
  let userMessageId: string | undefined;
@@ -304,26 +331,29 @@ export async function sweepFailedEvents(
304
331
  );
305
332
  } catch (err) {
306
333
  log.error({ err, eventId: event.id }, "Retry failed for channel event");
334
+ if (slackDmTextDelivery) {
335
+ await slackDmTextDelivery.waitForPendingDeliveries();
336
+ }
307
337
  recordProcessingFailure(event.id, err);
308
338
  continue;
309
339
  }
310
340
 
311
- const replyCallbackUrl =
312
- typeof payload.replyCallbackUrl === "string"
313
- ? payload.replyCallbackUrl
314
- : undefined;
315
341
  if (replyCallbackUrl) {
316
- const externalChatId =
317
- typeof payload.externalChatId === "string"
318
- ? payload.externalChatId
319
- : undefined;
320
342
  if (externalChatId) {
321
343
  try {
344
+ if (slackDmTextDelivery) {
345
+ await slackDmTextDelivery.waitForPendingDeliveries();
346
+ }
322
347
  // processMessage above generated a fresh assistant response, so any
323
- // previously tracked segment progress belongs to the old response and
324
- // must not carry over. Reset to 0 so we deliver all segments of the
325
- // new response.
326
- updateDeliveredSegmentCount(event.id, 0);
348
+ // previously tracked final-delivery progress belongs to the old
349
+ // response and must not carry over. Use live Slack DM progress as
350
+ // the new baseline before final delivery so delivery-only retries do
351
+ // not duplicate text if the callback fails before reporting progress.
352
+ const liveDeliveryResumeOptions =
353
+ slackDmTextDelivery?.getFinalDeliveryResumeOptions(replyMessageId);
354
+ const finalDeliveryStartFromSegment =
355
+ liveDeliveryResumeOptions?.startFromSegment ?? 0;
356
+ updateDeliveredSegmentCount(event.id, finalDeliveryStartFromSegment);
327
357
  await deliverReplyViaCallback(
328
358
  event.conversationId,
329
359
  externalChatId,
@@ -332,7 +362,10 @@ export async function sweepFailedEvents(
332
362
  {
333
363
  messageId: replyMessageId,
334
364
  sinceMessageId: userMessageId,
335
- startFromSegment: 0,
365
+ startFromSegment: finalDeliveryStartFromSegment,
366
+ ...(liveDeliveryResumeOptions?.messageTs
367
+ ? { messageTs: liveDeliveryResumeOptions.messageTs }
368
+ : {}),
336
369
  onSegmentDelivered: (count) =>
337
370
  updateDeliveredSegmentCount(event.id, count),
338
371
  },
@@ -12,7 +12,6 @@
12
12
  * canonical records.
13
13
  */
14
14
 
15
-
16
15
  import type { TrustContext } from "../daemon/trust-context.js";
17
16
  import {
18
17
  type CanonicalGuardianRequest,
@@ -150,6 +149,7 @@ export function bridgeConfirmationRequestToGuardian(
150
149
  sourceEventName: "guardian.question",
151
150
  sourceChannel: sourceChannel as NotificationSourceChannel,
152
151
  sourceContextId: conversationId,
152
+ requiresConversation: true,
153
153
  attentionHints: {
154
154
  requiresAction: true,
155
155
  urgency: "high",
@@ -679,7 +679,8 @@ export interface BuildExportVBundleOptions {
679
679
  * Optional callback to checkpoint the WAL before reading the database file.
680
680
  * In WAL mode, committed rows may live in the -wal file and not yet be
681
681
  * flushed to the main .db file. Callers should pass a function that runs
682
- * PRAGMA wal_checkpoint(TRUNCATE) on the live database connection.
682
+ * PRAGMA wal_checkpoint(FULL) on the live database connection. (Not
683
+ * TRUNCATE — see assistant/AGENTS.md "SQLite WAL checkpointing".)
683
684
  * Called before the workspace walk so the DB file is up to date.
684
685
  *
685
686
  * May return a Promise — `streamExportVBundle` awaits the result so an
@@ -1127,7 +1128,7 @@ export async function streamExportVBundle(
1127
1128
 
1128
1129
  // Flush WAL to the main database file before reading. Awaiting allows
1129
1130
  // the callback to dispatch the checkpoint via `runAsyncSqlite` so the
1130
- // daemon event loop stays responsive while SQLite truncates the WAL.
1131
+ // daemon event loop stays responsive while SQLite flushes the WAL.
1131
1132
  if (checkpoint) {
1132
1133
  await checkpoint();
1133
1134
  }
@@ -22,6 +22,7 @@ mock.module("../../assistant-event-hub.js", () => ({
22
22
  },
23
23
  subscribe: () => () => {},
24
24
  },
25
+ broadcastMessage: async () => {},
25
26
  }));
26
27
 
27
28
  import { getDb } from "../../../memory/db-connection.js";