@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
@@ -13,6 +13,8 @@ let connectionStore: Record<
13
13
  > = {};
14
14
  let deletedConnectionIds: string[] = [];
15
15
  let createdConnections: Array<{ provider: string; accountInfo?: string }> = [];
16
+ let updatedConnections: Array<{ id: string; accountInfo?: string | null }> = [];
17
+ let telegramBotUsername: string | undefined;
16
18
  const warnings: string[] = [];
17
19
 
18
20
  // ---------------------------------------------------------------------------
@@ -41,6 +43,10 @@ mock.module("../security/secure-keys.js", () => ({
41
43
  },
42
44
  }));
43
45
 
46
+ mock.module("../telegram/bot-username.js", () => ({
47
+ getTelegramBotUsername: () => telegramBotUsername,
48
+ }));
49
+
44
50
  mock.module("../oauth/oauth-store.js", () => ({
45
51
  getConnectionByProvider: (provider: string) =>
46
52
  connectionStore[provider] ?? undefined,
@@ -72,7 +78,16 @@ mock.module("../oauth/oauth-store.js", () => ({
72
78
  };
73
79
  return { id: `conn-${params.provider}` };
74
80
  },
75
- updateConnection: () => {},
81
+ updateConnection: (id: string, updates: { accountInfo?: string | null }) => {
82
+ updatedConnections.push({ id, accountInfo: updates.accountInfo });
83
+ for (const conn of Object.values(connectionStore)) {
84
+ if (conn.id === id) {
85
+ conn.accountInfo = updates.accountInfo;
86
+ return true;
87
+ }
88
+ }
89
+ return false;
90
+ },
76
91
  upsertApp: async (_provider: string, _clientId: string) => ({
77
92
  id: "app-1",
78
93
  }),
@@ -119,6 +134,8 @@ describe("syncManualTokenConnection", () => {
119
134
  connectionStore = {};
120
135
  deletedConnectionIds = [];
121
136
  createdConnections = [];
137
+ updatedConnections = [];
138
+ telegramBotUsername = undefined;
122
139
  warnings.length = 0;
123
140
  });
124
141
 
@@ -291,6 +308,62 @@ describe("syncManualTokenConnection", () => {
291
308
  { provider: "telegram", accountInfo: undefined },
292
309
  ]);
293
310
  });
311
+
312
+ test("creates telegram connection with configured bot username when account is omitted", async () => {
313
+ telegramBotUsername = "example_bot";
314
+ setCredentialResult("telegram", "bot_token", {
315
+ value: "bot-token",
316
+ unreachable: false,
317
+ });
318
+ setCredentialResult("telegram", "webhook_secret", {
319
+ value: "webhook-secret",
320
+ unreachable: false,
321
+ });
322
+
323
+ await syncManualTokenConnection("telegram");
324
+
325
+ expect(createdConnections).toEqual([
326
+ { provider: "telegram", accountInfo: "@example_bot" },
327
+ ]);
328
+ });
329
+
330
+ test("updates existing telegram connection with configured bot username when account is omitted", async () => {
331
+ telegramBotUsername = "@example_bot";
332
+ seedConnection("telegram");
333
+ setCredentialResult("telegram", "bot_token", {
334
+ value: "bot-token",
335
+ unreachable: false,
336
+ });
337
+ setCredentialResult("telegram", "webhook_secret", {
338
+ value: "webhook-secret",
339
+ unreachable: false,
340
+ });
341
+
342
+ await syncManualTokenConnection("telegram");
343
+
344
+ expect(updatedConnections).toEqual([
345
+ { id: "conn-telegram", accountInfo: "@example_bot" },
346
+ ]);
347
+ expect(connectionStore["telegram"]?.accountInfo).toBe("@example_bot");
348
+ });
349
+
350
+ test("preserves existing telegram account label when deriving bot username lazily", async () => {
351
+ telegramBotUsername = "@example_bot";
352
+ seedConnection("telegram", { accountInfo: "@existing_bot" });
353
+ setCredentialResult("telegram", "bot_token", {
354
+ value: "bot-token",
355
+ unreachable: false,
356
+ });
357
+ setCredentialResult("telegram", "webhook_secret", {
358
+ value: "webhook-secret",
359
+ unreachable: false,
360
+ });
361
+
362
+ await syncManualTokenConnection("telegram");
363
+
364
+ expect(updatedConnections).toEqual([]);
365
+ expect(connectionStore["telegram"]?.accountInfo).toBe("@existing_bot");
366
+ });
294
367
  });
295
368
 
296
369
  describe("backfillManualTokenConnections", () => {
@@ -299,6 +372,8 @@ describe("backfillManualTokenConnections", () => {
299
372
  connectionStore = {};
300
373
  deletedConnectionIds = [];
301
374
  createdConnections = [];
375
+ updatedConnections = [];
376
+ telegramBotUsername = undefined;
302
377
  warnings.length = 0;
303
378
  });
304
379
 
@@ -8,7 +8,21 @@ mock.module("../security/secure-keys.js", () => ({
8
8
  }));
9
9
 
10
10
  mock.module("../config/env-registry.js", () => ({
11
+ getDebugStdoutLogs: () => false,
12
+ getIsContainerized: () => false,
11
13
  getIsPlatform: () => false,
14
+ isPlatformRemote: () => false,
15
+ getWorkspaceDirOverride: () => undefined,
16
+ getBackupDirOverride: () => undefined,
17
+ getBackupKeyPathOverride: () => undefined,
18
+ getCpuLimit: () => undefined,
19
+ getMinikubeStorageSize: () => undefined,
20
+ getProfilerRunId: () => undefined,
21
+ getProfilerMode: () => undefined,
22
+ getProfilerMaxBytes: () => undefined,
23
+ getProfilerMaxRuns: () => undefined,
24
+ getProfilerMinFreeMb: () => undefined,
25
+ checkUnrecognizedEnvVars: () => [],
12
26
  }));
13
27
 
14
28
  const { McpClient } = await import("../mcp/client.js");
@@ -8,7 +8,21 @@ mock.module("../security/secure-keys.js", () => ({
8
8
  }));
9
9
 
10
10
  mock.module("../config/env-registry.js", () => ({
11
+ getDebugStdoutLogs: () => false,
12
+ getIsContainerized: () => false,
11
13
  getIsPlatform: () => false,
14
+ isPlatformRemote: () => false,
15
+ getWorkspaceDirOverride: () => undefined,
16
+ getBackupDirOverride: () => undefined,
17
+ getBackupKeyPathOverride: () => undefined,
18
+ getCpuLimit: () => undefined,
19
+ getMinikubeStorageSize: () => undefined,
20
+ getProfilerRunId: () => undefined,
21
+ getProfilerMode: () => undefined,
22
+ getProfilerMaxBytes: () => undefined,
23
+ getProfilerMaxRuns: () => undefined,
24
+ getProfilerMinFreeMb: () => undefined,
25
+ checkUnrecognizedEnvVars: () => [],
12
26
  }));
13
27
 
14
28
  const { McpClient } = await import("../mcp/client.js");
@@ -79,6 +79,7 @@ const getBindingByChannelChatMock = mock(
79
79
  mock.module("../memory/conversation-crud.js", () => ({
80
80
  addMessage: addMessageMock,
81
81
  getConversation: getConversationMock,
82
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
82
83
  }));
83
84
 
84
85
  mock.module("../memory/conversation-disk-view.js", () => ({
@@ -118,13 +118,13 @@ mock.module("../config/env.js", () => ({
118
118
  // Imports (after mocks so module-level code picks up the stubs)
119
119
  // ---------------------------------------------------------------------------
120
120
 
121
- import { resetDb } from "../memory/db-connection.js";
122
121
  import { defaultV1Options } from "../runtime/migrations/__tests__/v1-test-helpers.js";
123
122
  import { buildVBundle } from "../runtime/migrations/vbundle-builder.js";
124
123
  import {
125
124
  _setUrlImportValidatorOptionsForTests,
126
125
  handleMigrationImport,
127
126
  } from "../runtime/routes/migration-routes.js";
127
+ import { resetDbForTesting } from "./db-test-helpers.js";
128
128
  import { callHandler } from "./helpers/call-route-handler.js";
129
129
  // ---------------------------------------------------------------------------
130
130
  // Local http fixture server
@@ -448,7 +448,7 @@ describe("handleMigrationImport — no-swap path omits newer-migration warning",
448
448
 
449
449
  // Drop any cached Drizzle singleton so getDb() re-opens from the
450
450
  // seeded path above when the handler calls it post-import.
451
- resetDb();
451
+ resetDbForTesting();
452
452
 
453
453
  // All-`vellum:*` credentials bundle: the streaming importer returns
454
454
  // ok=true with zero files_created/overwritten (no-swap success),
@@ -505,7 +505,7 @@ describe("handleMigrationImport — no-swap path omits newer-migration warning",
505
505
  await fixture.close();
506
506
  // Close the cached DB handle before the workspace dir gets rm'd
507
507
  // in afterEach so we don't leak WAL/SHM files across tests.
508
- resetDb();
508
+ resetDbForTesting();
509
509
  }
510
510
  });
511
511
  });
@@ -56,7 +56,9 @@ class FakePersistentIpcClient extends EventEmitter {
56
56
  if (simulateError) {
57
57
  throw new Error("Mock IPC socket error");
58
58
  }
59
- return method in ipcResults ? ipcResults[method] : undefined;
59
+ if (method in ipcResults) return ipcResults[method];
60
+ if (method === "get_feature_flags") return GET_FEATURE_FLAGS_DEFAULT;
61
+ return undefined;
60
62
  }
61
63
 
62
64
  destroy(): void {
@@ -68,6 +70,18 @@ class FakePersistentIpcClient extends EventEmitter {
68
70
  // Register the mock (called once from test-preload.ts)
69
71
  // ---------------------------------------------------------------------------
70
72
 
73
+ /**
74
+ * Sentinel returned by the mock for `get_feature_flags` when a test has not
75
+ * explicitly configured a result. Keeps the response non-empty so
76
+ * `initFeatureFlagOverrides()` does not enter its 7.75 s empty-result retry
77
+ * loop during tests that build the CLI program or otherwise trigger flag
78
+ * initialization. The sentinel key starts with a double underscore so it
79
+ * cannot collide with any real registry-declared flag.
80
+ */
81
+ const GET_FEATURE_FLAGS_DEFAULT: Record<string, boolean> = {
82
+ __test_default__: false,
83
+ };
84
+
71
85
  export function installGatewayIpcMock(): void {
72
86
  mock.module("@vellumai/gateway-client/ipc-client", () => ({
73
87
  ipcCall: async (
@@ -79,7 +93,9 @@ export function installGatewayIpcMock(): void {
79
93
  // Real ipcCall returns undefined on failure — mirror that behavior.
80
94
  return undefined;
81
95
  }
82
- return method in ipcResults ? ipcResults[method] : undefined;
96
+ if (method in ipcResults) return ipcResults[method];
97
+ if (method === "get_feature_flags") return GET_FEATURE_FLAGS_DEFAULT;
98
+ return undefined;
83
99
  },
84
100
  PersistentIpcClient: FakePersistentIpcClient,
85
101
  }));
@@ -20,7 +20,7 @@ describe("model intents", () => {
20
20
  "claude-haiku-4-5-20251001",
21
21
  );
22
22
  expect(resolveModelIntent("anthropic", "quality-optimized")).toBe(
23
- "claude-opus-4-7",
23
+ "claude-opus-4-8",
24
24
  );
25
25
  expect(resolveModelIntent("anthropic", "vision-optimized")).toBe(
26
26
  "claude-opus-4-6",
@@ -44,9 +44,9 @@ describe("model intents", () => {
44
44
  });
45
45
 
46
46
  test("falls back to provider default for unknown providers", () => {
47
- expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-7");
47
+ expect(getProviderDefaultModel("unknown-provider")).toBe("claude-opus-4-8");
48
48
  expect(resolveModelIntent("unknown-provider", "quality-optimized")).toBe(
49
- "claude-opus-4-7",
49
+ "claude-opus-4-8",
50
50
  );
51
51
  });
52
52
  });
@@ -51,8 +51,7 @@ mock.module("@anthropic-ai/sdk", () => ({
51
51
  _options?: Record<string, unknown>,
52
52
  ) => {
53
53
  lastStreamParams = JSON.parse(JSON.stringify(params));
54
- const handlers: Record<string, ((...args: unknown[]) => void)[]> =
55
- {};
54
+ const handlers: Record<string, ((...args: unknown[]) => void)[]> = {};
56
55
  return {
57
56
  on(event: string, cb: (...args: unknown[]) => void) {
58
57
  (handlers[event] ??= []).push(cb);
@@ -74,6 +73,7 @@ mock.module("@anthropic-ai/sdk", () => ({
74
73
 
75
74
  // Import after mocking
76
75
  import { AnthropicProvider } from "../providers/anthropic/client.js";
76
+ import { isNativeWebSearchCapableProvider } from "../providers/registry.js";
77
77
 
78
78
  // ---------------------------------------------------------------------------
79
79
  // Helpers
@@ -99,6 +99,34 @@ const sampleTools: ToolDefinition[] = [
99
99
  },
100
100
  ];
101
101
 
102
+ describe("Native Web Search — Selection Semantics", () => {
103
+ test("only native-capable inference providers/models request provider-native web search", () => {
104
+ expect(
105
+ isNativeWebSearchCapableProvider("anthropic", "claude-opus-4-7"),
106
+ ).toBe(true);
107
+ expect(isNativeWebSearchCapableProvider("openai", "gpt-5")).toBe(true);
108
+ expect(
109
+ isNativeWebSearchCapableProvider(
110
+ "openrouter",
111
+ "anthropic/claude-opus-4-7",
112
+ ),
113
+ ).toBe(true);
114
+
115
+ expect(
116
+ isNativeWebSearchCapableProvider(
117
+ "fireworks",
118
+ "accounts/fireworks/models/kimi-k2p6",
119
+ ),
120
+ ).toBe(false);
121
+ expect(isNativeWebSearchCapableProvider("gemini", "gemini-3.1-pro")).toBe(
122
+ false,
123
+ );
124
+ expect(isNativeWebSearchCapableProvider("openrouter", "openai/gpt-5")).toBe(
125
+ false,
126
+ );
127
+ });
128
+ });
129
+
102
130
  // ---------------------------------------------------------------------------
103
131
  // Tests — Round-trip: fromAnthropicBlock
104
132
  // ---------------------------------------------------------------------------
@@ -38,6 +38,13 @@ mock.module("../notifications/deliveries-store.js", () => ({
38
38
  findDeliveryByDecisionAndChannel: () => undefined,
39
39
  }));
40
40
 
41
+ // Mock conversation-crud so the broadcaster's source-context fallback lookup
42
+ // can be driven from tests without DB access.
43
+ let mockExistingConversations: Record<string, { id: string }> = {};
44
+ mock.module("../memory/conversation-crud.js", () => ({
45
+ getConversation: (id: string) => mockExistingConversations[id] ?? null,
46
+ }));
47
+
41
48
  // Configurable mock for conversation-pairing
42
49
  let nextPairingResult:
43
50
  | import("../notifications/conversation-pairing.js").PairingResult
@@ -141,6 +148,7 @@ class MockAdapter implements ChannelAdapter {
141
148
  describe("notification deep-link metadata", () => {
142
149
  beforeEach(() => {
143
150
  nextPairingResult = null;
151
+ mockExistingConversations = {};
144
152
  });
145
153
 
146
154
  describe("VellumAdapter", () => {
@@ -600,5 +608,59 @@ describe("notification deep-link metadata", () => {
600
608
  expect(deepLink1!.messageId).toBe("msg-delivery-1");
601
609
  expect(deepLink2!.messageId).toBe("msg-delivery-2");
602
610
  });
611
+
612
+ // ── Source-context fallback when pairing yields no conversation ──
613
+
614
+ test("falls back to signal.sourceContextId for deep link when pairing returns no conversation and sourceContextId resolves", async () => {
615
+ const vellumAdapter = new MockAdapter("vellum");
616
+ const broadcaster = new NotificationBroadcaster([vellumAdapter]);
617
+
618
+ // Passive vellum signal: pairing skips creation, returns null.
619
+ nextPairingResult = {
620
+ conversationId: null,
621
+ messageId: null,
622
+ strategy: "start_new_conversation" as const,
623
+ createdNewConversation: false,
624
+ conversationFallbackUsed: false,
625
+ };
626
+
627
+ const originConvId = "conv-origin-of-event";
628
+ mockExistingConversations[originConvId] = { id: originConvId };
629
+
630
+ const signal = makeSignal({ sourceContextId: originConvId });
631
+ const decision = makeDecision();
632
+
633
+ await broadcaster.broadcastDecision(signal, decision);
634
+
635
+ expect(vellumAdapter.sent).toHaveLength(1);
636
+ const deepLink = vellumAdapter.sent[0].deepLinkTarget;
637
+ expect(deepLink).toBeDefined();
638
+ expect(deepLink!.conversationId).toBe(originConvId);
639
+ });
640
+
641
+ test("omits conversationId from deep link when pairing returns no conversation and sourceContextId is a sentinel", async () => {
642
+ const vellumAdapter = new MockAdapter("vellum");
643
+ const broadcaster = new NotificationBroadcaster([vellumAdapter]);
644
+
645
+ nextPairingResult = {
646
+ conversationId: null,
647
+ messageId: null,
648
+ strategy: "start_new_conversation" as const,
649
+ createdNewConversation: false,
650
+ conversationFallbackUsed: false,
651
+ };
652
+
653
+ // Sentinel sourceContextId (job ID, access-req-*, etc.) — getConversation returns null.
654
+ const signal = makeSignal({ sourceContextId: "access-req-sentinel-xyz" });
655
+ const decision = makeDecision();
656
+
657
+ await broadcaster.broadcastDecision(signal, decision);
658
+
659
+ expect(vellumAdapter.sent).toHaveLength(1);
660
+ const deepLink = vellumAdapter.sent[0].deepLinkTarget;
661
+ // Decision did not carry a deepLinkTarget either — the resulting
662
+ // deep link should be undefined or have no conversationId.
663
+ expect(deepLink?.conversationId).toBeUndefined();
664
+ });
603
665
  });
604
666
  });
@@ -21,6 +21,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
21
21
 
22
22
  interface MockProviderRow {
23
23
  provider: string;
24
+ authorizeUrl: string;
24
25
  managedServiceConfigKey: string | null;
25
26
  baseUrl: string | null;
26
27
  injectionTemplates: string | null;
@@ -32,6 +33,7 @@ interface MockProviderRow {
32
33
 
33
34
  const baseProvider: MockProviderRow = {
34
35
  provider: "google",
36
+ authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
35
37
  managedServiceConfigKey: "google-oauth",
36
38
  baseUrl: "https://api.google.com",
37
39
  injectionTemplates: null,
@@ -69,6 +71,7 @@ let mockResolveResponse: {
69
71
  body: unknown;
70
72
  } = { status: 200, headers: {}, body: { ok: true } };
71
73
  let mockResolveRequests: unknown[] = [];
74
+ let mockSyncManualTokenCalls: string[] = [];
72
75
 
73
76
  const mockDisconnectOAuthProvider = mock(() => Promise.resolve());
74
77
  const mockSaveRawConfig = mock(() => undefined);
@@ -117,6 +120,12 @@ mock.module("../oauth/connection-resolver.js", () => ({
117
120
  }),
118
121
  }));
119
122
 
123
+ mock.module("../oauth/manual-token-connection.js", () => ({
124
+ syncManualTokenConnection: async (provider: string) => {
125
+ mockSyncManualTokenCalls.push(provider);
126
+ },
127
+ }));
128
+
120
129
  mock.module("../platform/client.js", () => ({
121
130
  VellumPlatformClient: {
122
131
  create: async () => {
@@ -212,6 +221,7 @@ beforeEach(() => {
212
221
  });
213
222
  mockResolveResponse = { status: 200, headers: {}, body: { ok: true } };
214
223
  mockResolveRequests = [];
224
+ mockSyncManualTokenCalls = [];
215
225
  mockDisconnectOAuthProvider.mockClear();
216
226
  mockSaveRawConfig.mockClear();
217
227
  });
@@ -475,6 +485,33 @@ describe("GET oauth/status", () => {
475
485
  expect(result.connections[0]!.grantedScopes).toEqual([]);
476
486
  });
477
487
 
488
+ test("BYO mode reconciles manual-token providers before listing status", async () => {
489
+ mockProviders.telegram = {
490
+ ...baseProvider,
491
+ provider: "telegram",
492
+ authorizeUrl: "urn:manual-token",
493
+ managedServiceConfigKey: null,
494
+ baseUrl: "https://api.telegram.org",
495
+ };
496
+ mockAllConnections.telegram = [
497
+ {
498
+ id: "conn-telegram",
499
+ accountInfo: "@example_bot",
500
+ grantedScopes: "[]",
501
+ status: "active",
502
+ hasRefreshToken: 0,
503
+ expiresAt: null,
504
+ },
505
+ ];
506
+
507
+ const result = (await getRoute("GET", "oauth/status").handler(
508
+ makeArgs({ queryParams: { provider: "telegram" } }),
509
+ )) as { connections: Array<{ account: string | null }> };
510
+
511
+ expect(mockSyncManualTokenCalls).toEqual(["telegram"]);
512
+ expect(result.connections[0]!.account).toBe("@example_bot");
513
+ });
514
+
478
515
  test("managed mode surfaces platform connections", async () => {
479
516
  mockServiceModes["google-oauth"] = "managed";
480
517
  mockFetchImpl = async () => ({
@@ -21,13 +21,13 @@ mock.module("../security/secure-keys.js", () => ({
21
21
  getSecureKeyAsync: () => Promise.resolve(undefined),
22
22
  }));
23
23
 
24
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
25
24
  import type { AssistantConfig } from "../config/schema.js";
26
- import { resetDb } from "../memory/db-connection.js";
27
25
  import { initializeDb } from "../memory/db-init.js";
28
26
  import { resetTestTables } from "../memory/raw-query.js";
29
27
  import { listProviders, seedProviders } from "../oauth/oauth-store.js";
30
28
  import { isProviderVisible } from "../oauth/provider-visibility.js";
29
+ import { resetDbForTesting } from "./db-test-helpers.js";
30
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
31
31
 
32
32
  initializeDb();
33
33
 
@@ -38,15 +38,15 @@ function makeConfig(): AssistantConfig {
38
38
 
39
39
  beforeEach(() => {
40
40
  resetTestTables("oauth_connections", "oauth_apps", "oauth_providers");
41
- _setOverridesForTesting({});
41
+ setOverridesForTesting({});
42
42
  });
43
43
 
44
44
  afterEach(() => {
45
- _setOverridesForTesting({});
45
+ setOverridesForTesting({});
46
46
  });
47
47
 
48
48
  afterAll(() => {
49
- resetDb();
49
+ resetDbForTesting();
50
50
  });
51
51
 
52
52
  describe("isProviderVisible", () => {
@@ -70,7 +70,7 @@ describe("isProviderVisible", () => {
70
70
  });
71
71
 
72
72
  test("returns true when featureFlag is set and the flag is enabled", () => {
73
- _setOverridesForTesting({ "test-gate": true });
73
+ setOverridesForTesting({ "test-gate": true });
74
74
 
75
75
  seedProviders([
76
76
  {
@@ -93,7 +93,7 @@ describe("isProviderVisible", () => {
93
93
  });
94
94
 
95
95
  test("returns false when featureFlag is set and the flag is disabled", () => {
96
- _setOverridesForTesting({ "test-gate": false });
96
+ setOverridesForTesting({ "test-gate": false });
97
97
 
98
98
  seedProviders([
99
99
  {
@@ -115,7 +115,7 @@ describe("isProviderVisible", () => {
115
115
  });
116
116
 
117
117
  test("listProviders returns all providers but isProviderVisible filters gated ones when flag is disabled", () => {
118
- _setOverridesForTesting({ "test-gate": false });
118
+ setOverridesForTesting({ "test-gate": false });
119
119
 
120
120
  seedProviders([
121
121
  {
@@ -42,7 +42,7 @@ mock.module("../oauth/credential-token-resolver.js", () => ({
42
42
 
43
43
  import { eq } from "drizzle-orm";
44
44
 
45
- import { getDb, resetDb } from "../memory/db-connection.js";
45
+ import { getDb } from "../memory/db-connection.js";
46
46
  import { getSqliteFrom } from "../memory/db-connection.js";
47
47
  import { initializeDb } from "../memory/db-init.js";
48
48
  import { migrateOAuthProvidersTokenAuthMethodDefault } from "../memory/migrations/216-oauth-providers-token-auth-method.js";
@@ -70,6 +70,7 @@ import {
70
70
  upsertApp,
71
71
  } from "../oauth/oauth-store.js";
72
72
  import { seedOAuthProviders } from "../oauth/seed-providers.js";
73
+ import { resetDbForTesting } from "./db-test-helpers.js";
73
74
  import { getMockFetchCalls, mockFetch, resetMockFetch } from "./mock-fetch.js";
74
75
 
75
76
  initializeDb();
@@ -103,7 +104,7 @@ beforeEach(() => {
103
104
  });
104
105
 
105
106
  afterAll(() => {
106
- resetDb();
107
+ resetDbForTesting();
107
108
  });
108
109
 
109
110
  // ---------------------------------------------------------------------------
@@ -111,8 +111,9 @@ describe("onboarding template contracts", () => {
111
111
  expect(identity).toContain("**Emoji:**");
112
112
  });
113
113
 
114
- test("contains parsed field format guidance", () => {
115
- expect(identity).toContain("parsed by the app");
114
+ test("does not invite assistant-owned identity restructuring", () => {
115
+ expect(identity).not.toContain("This file is yours");
116
+ expect(identity).not.toContain("parsed by the app");
116
117
  });
117
118
  });
118
119
 
@@ -1557,32 +1557,32 @@ describe("OpenRouterProvider reasoning", () => {
1557
1557
  });
1558
1558
  });
1559
1559
 
1560
- test("sends reasoning.enabled=false when thinking is explicitly disabled", async () => {
1560
+ test("omits reasoning when thinking is explicitly disabled", async () => {
1561
1561
  const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
1562
1562
  await provider.sendMessage([userMsg("hi")], undefined, undefined, {
1563
1563
  config: { thinking: { type: "disabled" } },
1564
1564
  });
1565
1565
 
1566
1566
  expect(lastCreateParams).toBeTruthy();
1567
- expect(lastCreateParams!.reasoning).toEqual({ enabled: false });
1567
+ expect(lastCreateParams!.reasoning).toBeUndefined();
1568
1568
  });
1569
1569
 
1570
- test("sends reasoning.enabled=false when thinking config is absent", async () => {
1570
+ test("omits reasoning when thinking config is absent", async () => {
1571
1571
  const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
1572
1572
  await provider.sendMessage([userMsg("hi")], undefined, undefined, {
1573
1573
  config: {},
1574
1574
  });
1575
1575
 
1576
1576
  expect(lastCreateParams).toBeTruthy();
1577
- expect(lastCreateParams!.reasoning).toEqual({ enabled: false });
1577
+ expect(lastCreateParams!.reasoning).toBeUndefined();
1578
1578
  });
1579
1579
 
1580
- test("sends reasoning.enabled=false when no options are provided", async () => {
1580
+ test("omits reasoning when no options are provided", async () => {
1581
1581
  const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
1582
1582
  await provider.sendMessage([userMsg("hi")]);
1583
1583
 
1584
1584
  expect(lastCreateParams).toBeTruthy();
1585
- expect(lastCreateParams!.reasoning).toEqual({ enabled: false });
1585
+ expect(lastCreateParams!.reasoning).toBeUndefined();
1586
1586
  });
1587
1587
 
1588
1588
  test("sends OpenRouter app-attribution headers on OpenAI-compatible requests", async () => {
@@ -1623,15 +1623,14 @@ describe("OpenRouterProvider reasoning", () => {
1623
1623
  });
1624
1624
  });
1625
1625
 
1626
- test("RetryProvider + OpenRouterProvider disables thinking end-to-end", async () => {
1626
+ test("RetryProvider + OpenRouterProvider omits reasoning when thinking disabled", async () => {
1627
1627
  const provider = new OpenRouterProvider("or-key", "x-ai/grok-4");
1628
1628
  const retry = new RetryProvider(provider);
1629
1629
 
1630
- // thinking disabled at loop-level can arrive as an explicit disabled config.
1631
1630
  await retry.sendMessage([userMsg("hi")], undefined, undefined, {
1632
1631
  config: { thinking: { type: "disabled" } },
1633
1632
  });
1634
- expect(lastCreateParams!.reasoning).toEqual({ enabled: false });
1633
+ expect(lastCreateParams!.reasoning).toBeUndefined();
1635
1634
  });
1636
1635
 
1637
1636
  test("nests effort under reasoning and omits top-level reasoning_effort", async () => {