@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
@@ -11,7 +11,11 @@ import type { ChannelId, InterfaceId } from "../../../channels/types.js";
11
11
  import { findGuardianForChannel } from "../../../contacts/contact-store.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
  linkMessage,
17
21
  storeReplyMessageId,
@@ -44,6 +48,10 @@ import type {
44
48
  MessageProcessor,
45
49
  SlackInboundMessageMetadata,
46
50
  } from "../../http-types.js";
51
+ import {
52
+ createSlackDmTextDeliveryController,
53
+ isSlackDeliveryCallbackUrl,
54
+ } from "../../slack-dm-text-delivery.js";
47
55
  import { resolveRoutingState } from "../../trust-context-resolver.js";
48
56
  import { deliverReplyViaCallback } from "../channel-delivery-routes.js";
49
57
  import { deliverGeneratedApprovalPrompt } from "../guardian-approval-prompt.js";
@@ -228,6 +236,21 @@ export function processChannelMessageInBackground(
228
236
  }
229
237
  : undefined;
230
238
  let replyMessageId: string | undefined;
239
+ const slackDmTextDelivery = createSlackDmTextDeliveryController({
240
+ sourceChannel,
241
+ chatType,
242
+ replyCallbackUrl,
243
+ chatId: externalChatId,
244
+ assistantId,
245
+ deliveredTextResponseIndexes:
246
+ getSlackDmLiveDeliveredTextResponseIndexes(eventId),
247
+ onTextResponseDelivered: (responseIndex, reason) => {
248
+ addSlackDmLiveDeliveredTextResponseIndex(eventId, responseIndex);
249
+ if (reason === "before_tool") {
250
+ slackThinkingStatus?.refreshAfterReply();
251
+ }
252
+ },
253
+ });
231
254
  const observeAgentEvent = (msg: ServerMessage): void => {
232
255
  if (
233
256
  msg.type === "message_complete" &&
@@ -236,6 +259,7 @@ export function processChannelMessageInBackground(
236
259
  ) {
237
260
  replyMessageId = msg.messageId;
238
261
  }
262
+ slackDmTextDelivery?.observeEvent(msg);
239
263
  slackThinkingStatus?.observeEvent(msg);
240
264
  };
241
265
 
@@ -297,12 +321,21 @@ export function processChannelMessageInBackground(
297
321
  { err, conversationId },
298
322
  "Background channel message processing failed",
299
323
  );
324
+ if (slackDmTextDelivery) {
325
+ await slackDmTextDelivery.waitForPendingDeliveries();
326
+ }
300
327
  recordProcessingFailure(eventId, err);
301
328
  return;
302
329
  }
303
330
 
304
331
  if (replyCallbackUrl) {
305
332
  try {
333
+ if (slackDmTextDelivery) {
334
+ await slackDmTextDelivery.waitForPendingDeliveries();
335
+ }
336
+ const liveDeliveryResumeOptions =
337
+ slackDmTextDelivery?.getFinalDeliveryResumeOptions(replyMessageId);
338
+
306
339
  await deliverReplyViaCallback(
307
340
  conversationId,
308
341
  externalChatId,
@@ -311,6 +344,7 @@ export function processChannelMessageInBackground(
311
344
  {
312
345
  messageId: replyMessageId,
313
346
  sinceMessageId: userMessageId,
347
+ ...liveDeliveryResumeOptions,
314
348
  onSegmentDelivered: (count) =>
315
349
  updateDeliveredSegmentCount(eventId, count),
316
350
  },
@@ -395,11 +429,13 @@ function startTelegramTypingHeartbeat(
395
429
 
396
430
  type SlackThinkingStatusController = {
397
431
  observeEvent: (msg: ServerMessage) => void;
432
+ refreshAfterReply: () => void;
398
433
  stop: () => void;
399
434
  };
400
435
 
401
436
  type SlackThinkingStatusHandle = {
402
437
  updateLoadingMessages: (loadingMessages?: string[]) => void;
438
+ refresh: (loadingMessages?: string[]) => void;
403
439
  clear: () => void;
404
440
  };
405
441
 
@@ -440,12 +476,9 @@ function shouldEmitSlackThinkingStatus(
440
476
  sourceChannel: ChannelId,
441
477
  replyCallbackUrl?: string,
442
478
  ): boolean {
443
- if (sourceChannel !== "slack" || !replyCallbackUrl) return false;
444
- try {
445
- return new URL(replyCallbackUrl).pathname.endsWith("/deliver/slack");
446
- } catch {
447
- return replyCallbackUrl.endsWith("/deliver/slack");
448
- }
479
+ return (
480
+ sourceChannel === "slack" && isSlackDeliveryCallbackUrl(replyCallbackUrl)
481
+ );
449
482
  }
450
483
 
451
484
  export function shouldStartSlackThinkingStatusImmediately(params: {
@@ -547,6 +580,13 @@ function createSlackThinkingStatusController(params: {
547
580
  start();
548
581
  }
549
582
  },
583
+ refreshAfterReply() {
584
+ if (stopped || !slackThinkingStatus) return;
585
+ // Slack clears assistant thread status when the app sends a reply, so
586
+ // live pre-tool replies need to reassert it while work continues.
587
+ slackThinkingStatus.refresh(currentLoadingMessages);
588
+ lastSentLoadingMessageKey = getLoadingMessagesKey(currentLoadingMessages);
589
+ },
550
590
  stop() {
551
591
  stopped = true;
552
592
  slackThinkingStatus?.clear();
@@ -627,7 +667,9 @@ function getTaskProgressLoadingMessage(
627
667
 
628
668
  const activeStep = progress.steps[activeStepIndex]!;
629
669
  return [
630
- `In progress (${activeStepIndex + 1}/${progress.steps.length}): ${activeStep.label}`,
670
+ `In progress (${activeStepIndex + 1}/${progress.steps.length}): ${
671
+ activeStep.label
672
+ }`,
631
673
  ];
632
674
  }
633
675
 
@@ -656,6 +698,7 @@ function setSlackThinkingStatus(
656
698
  if (!messageTs) {
657
699
  return {
658
700
  updateLoadingMessages: () => {},
701
+ refresh: () => {},
659
702
  clear: () => {},
660
703
  };
661
704
  }
@@ -697,6 +740,7 @@ function setSlackThinkingStatus(
697
740
 
698
741
  return {
699
742
  updateLoadingMessages: () => {},
743
+ refresh: () => {},
700
744
  clear: clearReaction,
701
745
  };
702
746
  }
@@ -739,6 +783,10 @@ function setSlackThinkingStatus(
739
783
  );
740
784
  };
741
785
 
786
+ const refresh = (nextLoadingMessages?: string[]): void => {
787
+ updateLoadingMessages(nextLoadingMessages);
788
+ };
789
+
742
790
  const clearStatus = (): void => {
743
791
  if (cleared) return;
744
792
  cleared = true;
@@ -766,6 +814,7 @@ function setSlackThinkingStatus(
766
814
 
767
815
  return {
768
816
  updateLoadingMessages,
817
+ refresh,
769
818
  clear: clearStatus,
770
819
  };
771
820
  }
@@ -40,6 +40,7 @@ import { ROUTES as CONTENT_SOURCE_ROUTES } from "./content-source-routes.js";
40
40
  import { ROUTES as CONVERSATION_ANALYSIS_ROUTES } from "./conversation-analysis-routes.js";
41
41
  import { ROUTES as CONVERSATION_ATTENTION_ROUTES } from "./conversation-attention-routes.js";
42
42
  import { ROUTES as CONVERSATION_CLI_ROUTES } from "./conversation-cli-routes.js";
43
+ import { ROUTES as CONVERSATION_COMPACTION_ROUTES } from "./conversation-compaction-routes.js";
43
44
  import { ROUTES as CONVERSATION_LIST_ROUTES } from "./conversation-list-routes.js";
44
45
  import { ROUTES as CONVERSATION_MANAGEMENT_ROUTES } from "./conversation-management-routes.js";
45
46
  import { ROUTES as CONVERSATION_QUERY_ROUTES } from "./conversation-query-routes.js";
@@ -179,6 +180,7 @@ export const ROUTES: RouteDefinition[] = [
179
180
  ...CREDENTIAL_PROMPT_ROUTES,
180
181
  ...CREDENTIAL_ROUTES,
181
182
  ...DEFER_ROUTES,
183
+ ...CONVERSATION_COMPACTION_ROUTES,
182
184
  ...CONVERSATION_QUERY_ROUTES,
183
185
  ...CONVERSATION_STARTER_ROUTES,
184
186
  ...DEBUG_BASH_ROUTES,
@@ -4,7 +4,7 @@
4
4
  * GET /v1/inference/provider-connections — list all connections (optional ?provider= filter)
5
5
  * GET /v1/inference/provider-connections/:name — single connection by name
6
6
  * POST /v1/inference/provider-connections — create a new connection
7
- * PATCH /v1/inference/provider-connections/:name — update auth/label/status (cannot rename or change provider; auth is locked to platform for managed connections)
7
+ * PATCH /v1/inference/provider-connections/:name — update auth/label (cannot rename or change provider; auth is locked to platform for managed connections)
8
8
  * DELETE /v1/inference/provider-connections/:name — delete (rejects if profiles or call sites reference it; rejects outright for managed connections)
9
9
  */
10
10
 
@@ -18,7 +18,6 @@ import {
18
18
  type ConnectionModel,
19
19
  ConnectionModelSchema,
20
20
  ConnectionProviderSchema,
21
- ConnectionStatusSchema,
22
21
  ProviderConnectionSchema,
23
22
  VALID_CONNECTION_PROVIDERS,
24
23
  } from "../../providers/inference/auth.js";
@@ -223,14 +222,6 @@ async function handleCreateConnection({ body = {} }: RouteHandlerArgs) {
223
222
  throw new BadRequestError(`Invalid auth: ${authResult.error.message}`);
224
223
  }
225
224
 
226
- const statusResult =
227
- body.status !== undefined
228
- ? ConnectionStatusSchema.safeParse(body.status)
229
- : null;
230
- if (statusResult && !statusResult.success) {
231
- throw new BadRequestError(`Invalid status: must be "active" or "disabled"`);
232
- }
233
-
234
225
  const labelRaw = body.label;
235
226
  if (
236
227
  labelRaw !== undefined &&
@@ -248,7 +239,6 @@ async function handleCreateConnection({ body = {} }: RouteHandlerArgs) {
248
239
  name,
249
240
  provider: providerResult.data,
250
241
  auth: authResult.data,
251
- ...(statusResult ? { status: statusResult.data } : {}),
252
242
  ...(labelRaw !== undefined ? { label: labelRaw as string | null } : {}),
253
243
  ...customFields,
254
244
  });
@@ -302,14 +292,6 @@ async function handleUpdateConnection({
302
292
  throw new BadRequestError(`Invalid auth: ${authResult.error.message}`);
303
293
  }
304
294
 
305
- const statusResult =
306
- body.status !== undefined
307
- ? ConnectionStatusSchema.safeParse(body.status)
308
- : null;
309
- if (statusResult && !statusResult.success) {
310
- throw new BadRequestError(`Invalid status: must be "active" or "disabled"`);
311
- }
312
-
313
295
  const labelRaw = body.label;
314
296
  if (
315
297
  labelRaw !== undefined &&
@@ -323,8 +305,8 @@ async function handleUpdateConnection({
323
305
 
324
306
  // Managed connections: lock auth to `{type:"platform"}`. The boot upsert in
325
307
  // `seedCanonicalConnections` would revert any other value on next restart;
326
- // reject the write here so the surprise loop never happens. Label and status
327
- // remain user-editable (the boot upsert leaves those alone).
308
+ // reject the write here so the surprise loop never happens. Label remains
309
+ // user-editable (the boot upsert leaves it alone).
328
310
  if (
329
311
  MANAGED_CONNECTION_NAMES.has(name) &&
330
312
  authResult.data.type !== "platform"
@@ -338,7 +320,6 @@ async function handleUpdateConnection({
338
320
 
339
321
  const result = updateConnection(getDb(), name, {
340
322
  auth: authResult.data,
341
- ...(statusResult ? { status: statusResult.data } : {}),
342
323
  ...(labelRaw !== undefined ? { label: labelRaw as string | null } : {}),
343
324
  ...customFields,
344
325
  });
@@ -387,7 +368,7 @@ function handleDeleteConnection({ pathParams = {} }: RouteHandlerArgs) {
387
368
  // re-overlaid by `seed-inference-profiles.ts` on boot).
388
369
  if (MANAGED_CONNECTION_NAMES.has(name)) {
389
370
  throw new BadRequestError(
390
- `Cannot delete managed connection "${name}". This is a Vellum-managed connection disable it via PATCH status="disabled" if you want to opt out of platform inference.`,
371
+ `Cannot delete managed connection "${name}". This is a Vellum-managed connection that is re-seeded on every startup.`,
391
372
  );
392
373
  }
393
374
 
@@ -485,7 +466,6 @@ export const ROUTES: RouteDefinition[] = [
485
466
  provider: ConnectionProviderSchema,
486
467
  auth: AuthSchema,
487
468
  label: z.string().min(1).optional(),
488
- status: ConnectionStatusSchema.optional(),
489
469
  base_url: z.string().url().nullable().optional(),
490
470
  models: z.array(ConnectionModelSchema).nullable().optional(),
491
471
  }),
@@ -504,12 +484,11 @@ export const ROUTES: RouteDefinition[] = [
504
484
  policyKey: "inference/provider-connections/detail",
505
485
  summary: "Update a provider connection",
506
486
  description:
507
- "Update an existing connection. Cannot rename or change the provider. For managed connections (anthropic-managed, openai-managed, gemini-managed) the auth is locked to platform; label and status remain editable.",
487
+ "Update an existing connection. Cannot rename or change the provider. For managed connections (anthropic-managed, openai-managed, gemini-managed) the auth is locked to platform; label remains editable.",
508
488
  tags: ["inference"],
509
489
  pathParams: [{ name: "name", description: "Connection name" }],
510
490
  requestBody: z.object({
511
491
  auth: AuthSchema,
512
- status: ConnectionStatusSchema.optional(),
513
492
  label: z.string().min(1).nullable().optional(),
514
493
  base_url: z.string().url().nullable().optional(),
515
494
  models: z.array(ConnectionModelSchema).nullable().optional(),
@@ -9,6 +9,8 @@
9
9
  * ("set" or "delete") rather than using HTTP verbs directly.
10
10
  */
11
11
 
12
+ import { z } from "zod";
13
+
12
14
  import {
13
15
  deleteVercelConfig,
14
16
  getVercelConfig,
@@ -17,6 +19,12 @@ import {
17
19
  import { BadRequestError } from "../errors.js";
18
20
  import type { RouteDefinition, RouteHandlerArgs } from "../types.js";
19
21
 
22
+ const vercelConfigResponseSchema = z.object({
23
+ hasToken: z.boolean(),
24
+ success: z.boolean(),
25
+ error: z.string().optional(),
26
+ });
27
+
20
28
  // ---------------------------------------------------------------------------
21
29
  // Handlers
22
30
  // ---------------------------------------------------------------------------
@@ -66,6 +74,7 @@ export const ROUTES: RouteDefinition[] = [
66
74
  description: "Check if a Vercel API token is stored.",
67
75
  tags: ["integrations"],
68
76
  requirePolicyEnforcement: true,
77
+ responseBody: vercelConfigResponseSchema,
69
78
  handler: () => handleGetVercelConfig(),
70
79
  },
71
80
  {
@@ -77,6 +86,11 @@ export const ROUTES: RouteDefinition[] = [
77
86
  "Set or delete the Vercel API token. Action is determined by the body action field.",
78
87
  tags: ["integrations"],
79
88
  requirePolicyEnforcement: true,
89
+ requestBody: z.object({
90
+ action: z.enum(["get", "set", "delete"]).optional(),
91
+ apiToken: z.string().optional(),
92
+ }),
93
+ responseBody: vercelConfigResponseSchema,
80
94
  handler: handlePostVercelConfig,
81
95
  },
82
96
  {
@@ -87,6 +101,7 @@ export const ROUTES: RouteDefinition[] = [
87
101
  description: "Delete the stored Vercel API token.",
88
102
  tags: ["integrations"],
89
103
  requirePolicyEnforcement: true,
104
+ responseBody: vercelConfigResponseSchema,
90
105
  handler: () => handleDeleteVercelConfig(),
91
106
  },
92
107
  ];
@@ -1057,8 +1057,13 @@ function extractOpenAiResponsesRequestToolNames(tools: unknown): string[] {
1057
1057
  if (asString(tool.type) === "function" && asString(tool.name)) {
1058
1058
  return asString(tool.name);
1059
1059
  }
1060
- // Native web search tool: { type: "web_search_preview" }
1061
- if (asString(tool.type) === "web_search_preview") {
1060
+ // Native web search tools:
1061
+ // - OpenAI API: { type: "web_search_preview" }
1062
+ // - Codex subscription endpoint: { type: "web_search" }
1063
+ if (
1064
+ asString(tool.type) === "web_search_preview" ||
1065
+ asString(tool.type) === "web_search"
1066
+ ) {
1062
1067
  return "web_search";
1063
1068
  }
1064
1069
  return undefined;
@@ -22,14 +22,27 @@ import { z } from "zod";
22
22
  import { loadConfig } from "../../config/loader.js";
23
23
  import type { AssistantConfig } from "../../config/types.js";
24
24
  import { getDb } from "../../memory/db-connection.js";
25
+ import { readActivationLogsForShadowDiff } from "../../memory/memory-v2-activation-log-store.js";
25
26
  import type {
26
27
  RetrievalCost,
27
28
  RetrievalInput,
28
29
  } from "../../memory/v2/harness/retriever.js";
29
30
  import type { DescentTrace } from "../../memory/v2/harness/trace.js";
30
31
  import { loadNowText } from "../../memory/v2/now-text.js";
32
+ import {
33
+ DEFAULT_SEED_OPTIONS,
34
+ seedCoretrievalEdges,
35
+ type SeedCoretrievalResult,
36
+ } from "../../memory/v3/coretrieval-seed.js";
31
37
  import type { LlmCallRecord } from "../../memory/v3/llm-capture.js";
32
38
  import { runRetrievalLoop } from "../../memory/v3/loop.js";
39
+ import type {
40
+ ShadowDiffResult,
41
+ ShadowDiffTurn,
42
+ SlugFrequency,
43
+ UnpairedShadowTurn,
44
+ } from "../../memory/v3/shadow-diff.js";
45
+ import { computeShadowDiff } from "../../memory/v3/shadow-diff.js";
33
46
  import { getTreeIndex } from "../../memory/v3/tree-index.js";
34
47
  import type { TreeValidationReport } from "../../memory/v3/validate.js";
35
48
  import { validateTree } from "../../memory/v3/validate.js";
@@ -49,6 +62,13 @@ export type {
49
62
  TreeLevel,
50
63
  } from "../../memory/v2/harness/trace.js";
51
64
  export type { LlmCallRecord };
65
+ export type {
66
+ ShadowDiffResult,
67
+ ShadowDiffTurn,
68
+ SlugFrequency,
69
+ UnpairedShadowTurn,
70
+ };
71
+ export type { SeedCoretrievalResult };
52
72
 
53
73
  // ── Validate ────────────────────────────────────────────────────────────
54
74
 
@@ -119,7 +139,7 @@ async function handleTree({
119
139
  /** The five v3 retrieval lanes, in fanout order. */
120
140
  const V3_LANE_NAMES = ["hot", "sparse", "dense", "tree", "edges"] as const;
121
141
 
122
- const MemoryV3SimulateParams = z
142
+ export const MemoryV3SimulateParams = z
123
143
  .object({
124
144
  /** The ad-hoc user query to route a single synthetic turn against. */
125
145
  query: z.string().min(1, "memory.v3.simulate query must be non-empty"),
@@ -138,7 +158,10 @@ const MemoryV3SimulateParams = z
138
158
  * Restrict the run to this allowlist of lanes (others forced off). Omit to
139
159
  * inherit the live `memory.v3.lanes` toggles.
140
160
  */
141
- lanes: z.array(z.enum(V3_LANE_NAMES)).optional(),
161
+ lanes: z
162
+ .array(z.enum(V3_LANE_NAMES))
163
+ .min(1, "memory.v3.simulate lanes must list at least one lane")
164
+ .optional(),
142
165
  })
143
166
  .strict();
144
167
 
@@ -276,6 +299,118 @@ async function handleSimulate({
276
299
  };
277
300
  }
278
301
 
302
+ // ── Shadow-diff ─────────────────────────────────────────────────────────
303
+
304
+ /** Default pairing tolerance: a shadow row + its router sibling land ~1-2s apart. */
305
+ const DEFAULT_SHADOW_DIFF_TOLERANCE_SEC = 10;
306
+ /** Default cap on per-turn detail rows returned (aggregates are unbounded). */
307
+ const DEFAULT_SHADOW_DIFF_LIMIT = 50;
308
+ /** Milliseconds per day, for the `sinceDays` read-window cutoff. */
309
+ const MS_PER_DAY = 86_400_000;
310
+
311
+ const MemoryV3ShadowDiffParams = z
312
+ .object({
313
+ /** Only consider shadow rows newer than this many days. Omit for all rows. */
314
+ sinceDays: z
315
+ .number()
316
+ .positive("memory.v3.shadow-diff sinceDays must be positive")
317
+ .optional(),
318
+ /** Max |Δt| (seconds) to pair a shadow row with a router row. */
319
+ toleranceSec: z
320
+ .number()
321
+ .positive("memory.v3.shadow-diff toleranceSec must be positive")
322
+ .optional(),
323
+ /** Cap on per-turn detail rows in the response (newest first). */
324
+ limit: z
325
+ .number()
326
+ .int("memory.v3.shadow-diff limit must be an integer")
327
+ .positive("memory.v3.shadow-diff limit must be positive")
328
+ .optional(),
329
+ })
330
+ .strict();
331
+
332
+ /**
333
+ * Compare the v3 shadow selections against the live v2 router selections,
334
+ * turn-for-turn, from the activation log. Read-only: reads `v3_shadow` rows and
335
+ * the `router` rows they pair with (bounded to those conversations + time
336
+ * span), then diffs each pair. Requires v3 shadow mode to have been running
337
+ * (`memory.v3.enabled` + `.shadow`) so the `v3_shadow` rows exist; the route
338
+ * itself runs no LLM and writes nothing.
339
+ */
340
+ async function handleShadowDiff({
341
+ body = {},
342
+ }: RouteHandlerArgs): Promise<ShadowDiffResult> {
343
+ const { sinceDays, toleranceSec, limit } =
344
+ MemoryV3ShadowDiffParams.parse(body);
345
+
346
+ const sinceMs =
347
+ sinceDays !== undefined ? Date.now() - sinceDays * MS_PER_DAY : null;
348
+ const toleranceMs =
349
+ (toleranceSec ?? DEFAULT_SHADOW_DIFF_TOLERANCE_SEC) * 1000;
350
+
351
+ const { shadow, router } = readActivationLogsForShadowDiff({
352
+ sinceMs,
353
+ paddingMs: toleranceMs,
354
+ });
355
+
356
+ return computeShadowDiff(shadow, router, {
357
+ toleranceMs,
358
+ detailLimit: limit ?? DEFAULT_SHADOW_DIFF_LIMIT,
359
+ });
360
+ }
361
+
362
+ // ── Seed co-retrieval edges ───────────────────────────────────────────────
363
+
364
+ const MemoryV3SeedEdgesParams = z
365
+ .object({
366
+ /** A pair must co-occur on at least this many router turns to earn an edge. */
367
+ minCount: z
368
+ .number()
369
+ .int("memory.v3.seed-edges minCount must be an integer")
370
+ .positive("memory.v3.seed-edges minCount must be positive")
371
+ .optional(),
372
+ /** Neighbors kept per source node, ranked by NPMI descending. */
373
+ topK: z
374
+ .number()
375
+ .int("memory.v3.seed-edges topK must be an integer")
376
+ .positive("memory.v3.seed-edges topK must be positive")
377
+ .optional(),
378
+ /** Exclude neighbors selected on more than this fraction of all turns. */
379
+ maxNeighborFreqRatio: z
380
+ .number()
381
+ .positive("memory.v3.seed-edges maxNeighborFreqRatio must be positive")
382
+ .max(1, "memory.v3.seed-edges maxNeighborFreqRatio must be <= 1")
383
+ .optional(),
384
+ /** Flat weight each seeded edge is written at. */
385
+ seedWeight: z
386
+ .number()
387
+ .positive("memory.v3.seed-edges seedWeight must be positive")
388
+ .optional(),
389
+ })
390
+ .strict();
391
+
392
+ /**
393
+ * Build the co-retrieval graph from the v2 router's selection history and
394
+ * persist it into `memory_v3_auto_edges`. This is the one write surface among
395
+ * the v3 routes — it warm-starts the learned edge graph that the edge-expansion
396
+ * lane merges (when `memory.v3.edges.learnedAdjacencyThreshold > 0`). Idempotent:
397
+ * re-running upserts each seeded edge to the flat seed weight without unbounded
398
+ * growth. Runs no LLM.
399
+ */
400
+ async function handleSeedEdges({
401
+ body = {},
402
+ }: RouteHandlerArgs): Promise<SeedCoretrievalResult> {
403
+ const { minCount, topK, maxNeighborFreqRatio, seedWeight } =
404
+ MemoryV3SeedEdgesParams.parse(body);
405
+ return seedCoretrievalEdges(getDb(), {
406
+ minCount: minCount ?? DEFAULT_SEED_OPTIONS.minCount,
407
+ topK: topK ?? DEFAULT_SEED_OPTIONS.topK,
408
+ maxNeighborFreqRatio:
409
+ maxNeighborFreqRatio ?? DEFAULT_SEED_OPTIONS.maxNeighborFreqRatio,
410
+ seedWeight: seedWeight ?? DEFAULT_SEED_OPTIONS.seedWeight,
411
+ });
412
+ }
413
+
279
414
  // ── Route definitions ───────────────────────────────────────────────────
280
415
 
281
416
  export const ROUTES: RouteDefinition[] = [
@@ -313,4 +448,27 @@ export const ROUTES: RouteDefinition[] = [
313
448
  tags: ["memory"],
314
449
  requestBody: MemoryV3SimulateParams,
315
450
  },
451
+ {
452
+ operationId: "memory_v3_shadow_diff",
453
+ method: "POST",
454
+ endpoint: "memory/v3/shadow-diff",
455
+ handler: handleShadowDiff,
456
+ summary:
457
+ "Diff v3 shadow selections against live v2 router selections (read-only)",
458
+ description:
459
+ "Compares the v3 shadow-mode selections against the live v2 router selections turn-for-turn, from the memory activation log. Pairs each v3_shadow row with the nearest v2 router row in the same conversation (by timestamp, within a tolerance — the turn columns use different counters), then reports per-turn and aggregate overlap, what v3 surfaced that v2 did not, and what v2 had that v3 dropped, broken down by v3 provenance lane. The v2 comparand is the router's fresh per-turn pick (status='injected'), not its accumulated in-context set. Requires that v3 shadow mode has been running so v3_shadow rows exist; the route runs no LLM and writes nothing.",
460
+ tags: ["memory"],
461
+ requestBody: MemoryV3ShadowDiffParams,
462
+ },
463
+ {
464
+ operationId: "memory_v3_seed_edges",
465
+ method: "POST",
466
+ endpoint: "memory/v3/seed-edges",
467
+ handler: handleSeedEdges,
468
+ summary: "Seed the learned co-retrieval edge graph from v2 router history",
469
+ description:
470
+ "Builds an NPMI-scored co-retrieval graph from the v2 router's per-turn selections (memory_v2_activation_logs, status='injected') and persists it into memory_v3_auto_edges, warm-starting the learned edge graph that the v3 edge-expansion lane merges with curated edges when memory.v3.edges.learnedAdjacencyThreshold > 0. NPMI plus a min co-occurrence floor and an always-on frequency ceiling keep the neighborhoods associative rather than base-rate noise. Idempotent (upserts to a flat seed weight). Runs no LLM; the only write among the v3 routes.",
471
+ tags: ["memory"],
472
+ requestBody: MemoryV3SeedEdgesParams,
473
+ },
316
474
  ];
@@ -38,10 +38,7 @@ import {
38
38
  upsertCredentialMetadata,
39
39
  } from "../../tools/credentials/metadata-store.js";
40
40
  import { getLogger } from "../../util/logger.js";
41
- import {
42
- getWorkspaceDir,
43
- getWorkspaceHooksDir,
44
- } from "../../util/platform.js";
41
+ import { getWorkspaceDir, getWorkspaceHooksDir } from "../../util/platform.js";
45
42
  import { APP_VERSION } from "../../version.js";
46
43
  import { DAEMON_INTERNAL_ASSISTANT_ID } from "../assistant-scope.js";
47
44
  import {
@@ -358,11 +355,19 @@ export async function handleMigrationExport(
358
355
  checkpoint: async () => {
359
356
  // Dispatch through `runAsyncSqlite` so the WAL checkpoint runs
360
357
  // in a sqlite3 subprocess on hosts where it's available. A WAL
361
- // truncate on a multi-GB WAL file can otherwise stall the
362
- // daemon's event loop for the full duration of the flush.
363
- const result = await runAsyncSqlite(
364
- "PRAGMA wal_checkpoint(TRUNCATE)",
365
- );
358
+ // flush on a multi-GB WAL file can otherwise stall the daemon's
359
+ // event loop for the full duration of the flush.
360
+ //
361
+ // FULL (not TRUNCATE): TRUNCATE has a side effect where, if the
362
+ // WAL is empty after the checkpoint, SQLite unlinks the WAL file
363
+ // from the directory. When the daemon's in-process connection
364
+ // still holds the original WAL fd, the unlink orphans that fd
365
+ // into a "ghost WAL" only the daemon can reach, and subsequent
366
+ // connections create a fresh WAL on disk — split-brain. FULL
367
+ // gives us the same flush-completion guarantee without the
368
+ // unlink side effect. See assistant/AGENTS.md "SQLite WAL
369
+ // checkpointing".
370
+ const result = await runAsyncSqlite("PRAGMA wal_checkpoint(FULL)");
366
371
  if (!result.ok) {
367
372
  // Best-effort: if the DB can't be checkpointed (e.g. not a valid
368
373
  // SQLite file, missing WAL, etc.) we still proceed with the export
@@ -583,11 +588,13 @@ export async function handleMigrationExportToGcs({ body }: RouteHandlerArgs) {
583
588
  checkpoint: async () => {
584
589
  // Dispatch through `runAsyncSqlite` so the WAL checkpoint runs
585
590
  // in a sqlite3 subprocess on hosts where it's available. A
586
- // WAL truncate on a multi-GB WAL file can otherwise stall the
591
+ // WAL flush on a multi-GB WAL file can otherwise stall the
587
592
  // daemon's event loop for the full duration of the flush.
588
- const result = await runAsyncSqlite(
589
- "PRAGMA wal_checkpoint(TRUNCATE)",
590
- );
593
+ //
594
+ // FULL (not TRUNCATE): see the disk-export checkpoint above
595
+ // for rationale. assistant/AGENTS.md "SQLite WAL
596
+ // checkpointing".
597
+ const result = await runAsyncSqlite("PRAGMA wal_checkpoint(FULL)");
591
598
  if (!result.ok) {
592
599
  log.warn(
593
600
  { error: result.error, backend: result.backend },