@vellumai/assistant 0.8.4 → 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 (802) hide show
  1. package/AGENTS.md +33 -1
  2. package/ARCHITECTURE.md +3 -3
  3. package/bunfig.toml +6 -1
  4. package/docs/browser-use-architecture-phase2.md +1 -1
  5. package/docs/credential-execution-service.md +6 -6
  6. package/docs/plugins.md +4 -3
  7. package/knip.json +2 -1
  8. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +12 -13
  9. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +4 -1
  10. package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +16 -14
  11. package/openapi.yaml +2748 -216
  12. package/package.json +1 -1
  13. package/src/__tests__/actor-token-service.test.ts +3 -2
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +102 -9
  15. package/src/__tests__/agent-loop-override-profile.test.ts +2 -1
  16. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
  17. package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
  18. package/src/__tests__/always-loaded-tools-guard.test.ts +2 -2
  19. package/src/__tests__/annotate-risk-options.test.ts +1 -0
  20. package/src/__tests__/anthropic-provider.test.ts +34 -37
  21. package/src/__tests__/approval-cascade.test.ts +1 -0
  22. package/src/__tests__/approval-routes-http.test.ts +9 -13
  23. package/src/__tests__/assert-not-live-db.ts +79 -0
  24. package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
  25. package/src/__tests__/assistant-feature-flags-integration.test.ts +12 -28
  26. package/src/__tests__/audit-log-rotation.test.ts +72 -18
  27. package/src/__tests__/auto-analysis-end-to-end.test.ts +6 -6
  28. package/src/__tests__/background-workers-disk-pressure.test.ts +8 -11
  29. package/src/__tests__/browser-skill-endstate.test.ts +3 -3
  30. package/src/__tests__/btw-routes.test.ts +5 -5
  31. package/src/__tests__/call-controller.test.ts +3 -3
  32. package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
  33. package/src/__tests__/channel-approval-routes.test.ts +3 -2
  34. package/src/__tests__/channel-guardian.test.ts +6 -5
  35. package/src/__tests__/channel-readiness-slack-remote.test.ts +175 -0
  36. package/src/__tests__/channel-reply-delivery.test.ts +35 -0
  37. package/src/__tests__/channel-retry-sweep.test.ts +320 -3
  38. package/src/__tests__/checker.test.ts +18 -27
  39. package/src/__tests__/compaction-events.test.ts +2 -0
  40. package/src/__tests__/compaction-trail-store.test.ts +264 -0
  41. package/src/__tests__/compactor-call-site-logging.test.ts +215 -0
  42. package/src/__tests__/compactor-preserved-tail-count.test.ts +1 -0
  43. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +12 -16
  44. package/src/__tests__/computer-use-tools.test.ts +14 -18
  45. package/src/__tests__/config-loader-backfill.test.ts +13 -28
  46. package/src/__tests__/config-loader-corrupt.test.ts +5 -5
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +93 -26
  48. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +3 -3
  49. package/src/__tests__/config-managed-gemini-defaults.test.ts +3 -4
  50. package/src/__tests__/config-schema.test.ts +10 -10
  51. package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
  52. package/src/__tests__/connection-model-compat.test.ts +83 -0
  53. package/src/__tests__/contacts-tools.test.ts +3 -2
  54. package/src/__tests__/context-token-estimator.test.ts +22 -0
  55. package/src/__tests__/conversation-abort-tool-results.test.ts +5 -0
  56. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +2 -1
  57. package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +55 -0
  58. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -1
  59. package/src/__tests__/conversation-agent-loop-overflow.test.ts +231 -2
  60. package/src/__tests__/conversation-agent-loop.test.ts +581 -54
  61. package/src/__tests__/conversation-analysis-routes.test.ts +1 -0
  62. package/src/__tests__/conversation-app-control-instantiation.test.ts +31 -24
  63. package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -0
  64. package/src/__tests__/conversation-attention-store.test.ts +101 -0
  65. package/src/__tests__/conversation-attention-telegram.test.ts +3 -2
  66. package/src/__tests__/conversation-clear-safety.test.ts +25 -25
  67. package/src/__tests__/conversation-confirmation-signals.test.ts +1 -0
  68. package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
  69. package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
  70. package/src/__tests__/conversation-error.test.ts +61 -0
  71. package/src/__tests__/conversation-fork-crud.test.ts +239 -15
  72. package/src/__tests__/conversation-fork-route.test.ts +3 -2
  73. package/src/__tests__/conversation-history-web-search.test.ts +1 -0
  74. package/src/__tests__/conversation-inference-profile-list.test.ts +3 -2
  75. package/src/__tests__/conversation-inference-profile-route.test.ts +3 -2
  76. package/src/__tests__/conversation-lifecycle.test.ts +53 -11
  77. package/src/__tests__/conversation-list-source.test.ts +3 -2
  78. package/src/__tests__/conversation-load-history-repair.test.ts +2 -1
  79. package/src/__tests__/{conversation-load-cleaned-at.test.ts → conversation-load-history-stripped.test.ts} +14 -13
  80. package/src/__tests__/conversation-pairing.test.ts +53 -0
  81. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +26 -7
  82. package/src/__tests__/conversation-process-callsite.test.ts +1 -0
  83. package/src/__tests__/conversation-provider-retry-repair.test.ts +6 -0
  84. package/src/__tests__/conversation-queue.test.ts +333 -291
  85. package/src/__tests__/conversation-routes-disk-view.test.ts +112 -18
  86. package/src/__tests__/conversation-routes-guardian-reply.test.ts +33 -8
  87. package/src/__tests__/conversation-routes-slash-commands.test.ts +68 -2
  88. package/src/__tests__/conversation-runtime-assembly.test.ts +78 -0
  89. package/src/__tests__/conversation-skill-tools.test.ts +40 -147
  90. package/src/__tests__/conversation-slash-queue.test.ts +84 -32
  91. package/src/__tests__/conversation-slash-unknown.test.ts +5 -0
  92. package/src/__tests__/conversation-speed-override.test.ts +1 -0
  93. package/src/__tests__/conversation-store.test.ts +1 -1
  94. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +46 -0
  95. package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -0
  96. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +6 -3
  97. package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -3
  98. package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -3
  99. package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -17
  100. package/src/__tests__/conversation-sync-tags.test.ts +218 -35
  101. package/src/__tests__/conversation-title-service.test.ts +1 -0
  102. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +30 -0
  103. package/src/__tests__/conversation-usage.test.ts +1 -0
  104. package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -0
  105. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  106. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +6 -1
  107. package/src/__tests__/credential-broker-browser-fill.test.ts +3 -3
  108. package/src/__tests__/credential-broker-server-use.test.ts +5 -5
  109. package/src/__tests__/credential-execution-client.test.ts +72 -1
  110. package/src/__tests__/credential-execution-feature-gates.test.ts +19 -19
  111. package/src/__tests__/credential-execution-tools.test.ts +6 -6
  112. package/src/__tests__/credential-health-service.test.ts +252 -3
  113. package/src/__tests__/credential-security-invariants.test.ts +6 -5
  114. package/src/__tests__/credential-vault-unit.test.ts +21 -21
  115. package/src/__tests__/credential-vault.test.ts +5 -5
  116. package/src/__tests__/cross-provider-web-search.test.ts +56 -2
  117. package/src/__tests__/db-connection-isolation.test.ts +7 -6
  118. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +8 -10
  119. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +7 -10
  120. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +9 -15
  121. package/src/__tests__/db-test-helpers.ts +58 -0
  122. package/src/__tests__/disk-pressure-guard.test.ts +58 -41
  123. package/src/__tests__/disk-pressure-lifecycle.test.ts +13 -10
  124. package/src/__tests__/disk-pressure-routes.test.ts +0 -33
  125. package/src/__tests__/disk-pressure-tools.test.ts +0 -4
  126. package/src/__tests__/dm-persistence.test.ts +26 -40
  127. package/src/__tests__/document-create-dedupe.test.ts +189 -0
  128. package/src/__tests__/document-find-replace.test.ts +3 -2
  129. package/src/__tests__/document-tool-security.test.ts +81 -2
  130. package/src/__tests__/dynamic-page-surface.test.ts +2 -2
  131. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +5 -4
  132. package/src/__tests__/email-html-renderer.test.ts +12 -0
  133. package/src/__tests__/encrypted-store-test-helpers.ts +56 -0
  134. package/src/__tests__/encrypted-store.test.ts +11 -9
  135. package/src/__tests__/feature-flag-test-helpers.ts +53 -0
  136. package/src/__tests__/filing-service.test.ts +1 -0
  137. package/src/__tests__/first-greeting.test.ts +62 -12
  138. package/src/__tests__/gateway-flag-listener.test.ts +236 -0
  139. package/src/__tests__/gemini-provider.test.ts +104 -0
  140. package/src/__tests__/guardian-action-sweep.test.ts +3 -2
  141. package/src/__tests__/guardian-dispatch.test.ts +0 -1
  142. package/src/__tests__/guardian-outbound-http.test.ts +10 -7
  143. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +48 -3
  144. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -1
  145. package/src/__tests__/heartbeat-disk-pressure.test.ts +5 -0
  146. package/src/__tests__/heartbeat-service.test.ts +5 -0
  147. package/src/__tests__/helpers/mock-logger.ts +26 -0
  148. package/src/__tests__/host-bash-routes.test.ts +1 -0
  149. package/src/__tests__/host-cu-routes-targeted.test.ts +1 -0
  150. package/src/__tests__/host-file-routes-targeted.test.ts +1 -0
  151. package/src/__tests__/host-shell-tool.test.ts +6 -5
  152. package/src/__tests__/host-transfer-routes-targeted.test.ts +1 -0
  153. package/src/__tests__/http-conversation-lineage.test.ts +3 -2
  154. package/src/__tests__/http-user-message-parity.test.ts +29 -7
  155. package/src/__tests__/identity-intro-cache.test.ts +133 -22
  156. package/src/__tests__/inbound-slack-persistence.test.ts +44 -72
  157. package/src/__tests__/inference-profile-reaper.test.ts +3 -2
  158. package/src/__tests__/inference-profile-session-ipc.test.ts +3 -2
  159. package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
  160. package/src/__tests__/injector-disk-pressure.test.ts +3 -17
  161. package/src/__tests__/inline-skill-load-permissions.test.ts +4 -4
  162. package/src/__tests__/list-messages-hidden-metadata.test.ts +80 -0
  163. package/src/__tests__/list-messages-tool-merge.test.ts +70 -11
  164. package/src/__tests__/llm-context-normalization.test.ts +42 -0
  165. package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
  166. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
  167. package/src/__tests__/llm-resolver.test.ts +408 -9
  168. package/src/__tests__/llm-schema.test.ts +1 -1
  169. package/src/__tests__/llm-usage-store.test.ts +66 -0
  170. package/src/__tests__/logger.test.ts +89 -0
  171. package/src/__tests__/manual-token-reconciliation.test.ts +76 -1
  172. package/src/__tests__/mcp-abort-signal.test.ts +16 -2
  173. package/src/__tests__/mcp-client-auth.test.ts +14 -0
  174. package/src/__tests__/media-generate-image.test.ts +31 -0
  175. package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
  176. package/src/__tests__/messaging-send-tool.test.ts +1 -0
  177. package/src/__tests__/migration-import-from-url.test.ts +3 -3
  178. package/src/__tests__/mock-gateway-ipc.ts +18 -2
  179. package/src/__tests__/model-intents.test.ts +4 -6
  180. package/src/__tests__/native-web-search.test.ts +30 -2
  181. package/src/__tests__/notification-deep-link.test.ts +62 -0
  182. package/src/__tests__/notification-guardian-path.test.ts +0 -1
  183. package/src/__tests__/oauth-commands-routes.test.ts +37 -0
  184. package/src/__tests__/oauth-provider-visibility.test.ts +8 -8
  185. package/src/__tests__/oauth-store.test.ts +3 -2
  186. package/src/__tests__/onboarding-template-contract.test.ts +4 -3
  187. package/src/__tests__/openai-provider.test.ts +54 -9
  188. package/src/__tests__/openai-responses-provider.test.ts +176 -14
  189. package/src/__tests__/openrouter-provider-only.test.ts +27 -5
  190. package/src/__tests__/outbound-slack-persistence.test.ts +46 -1
  191. package/src/__tests__/pending-interactions-resolved-event.test.ts +0 -1
  192. package/src/__tests__/persistence-pipeline.test.ts +139 -1
  193. package/src/__tests__/persistence-secret-redaction.test.ts +83 -12
  194. package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
  195. package/src/__tests__/platform.test.ts +2 -2
  196. package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
  197. package/src/__tests__/plugin-bootstrap.test.ts +11 -13
  198. package/src/__tests__/plugin-tool-contribution.test.ts +50 -40
  199. package/src/__tests__/plugin-types.test.ts +3 -2
  200. package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
  201. package/src/__tests__/pricing.test.ts +12 -0
  202. package/src/__tests__/process-message-background-slack.test.ts +21 -16
  203. package/src/__tests__/process-message-display-content.test.ts +19 -22
  204. package/src/__tests__/provider-catalog-visibility.test.ts +9 -9
  205. package/src/__tests__/provider-platform-proxy-integration.test.ts +216 -4
  206. package/src/__tests__/provider-registry-ollama.test.ts +45 -22
  207. package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
  208. package/src/__tests__/recording-handler.test.ts +1 -0
  209. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +1 -0
  210. package/src/__tests__/registry.test.ts +84 -84
  211. package/src/__tests__/relay-server.test.ts +10 -10
  212. package/src/__tests__/require-fresh-approval.test.ts +2 -2
  213. package/src/__tests__/runtime-attachment-metadata.test.ts +3 -2
  214. package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
  215. package/src/__tests__/schedule-store.test.ts +16 -1
  216. package/src/__tests__/scheduler-reuse-conversation.test.ts +48 -3
  217. package/src/__tests__/secret-ingress-http.test.ts +5 -1
  218. package/src/__tests__/secure-keys.test.ts +3 -3
  219. package/src/__tests__/send-endpoint-busy.test.ts +81 -42
  220. package/src/__tests__/server-history-render.test.ts +4 -1
  221. package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
  222. package/src/__tests__/skill-feature-flags-integration.test.ts +8 -10
  223. package/src/__tests__/skill-feature-flags.test.ts +16 -18
  224. package/src/__tests__/skill-load-feature-flag.test.ts +5 -5
  225. package/src/__tests__/skill-projection-feature-flag.test.ts +48 -37
  226. package/src/__tests__/skill-projection.benchmark.test.ts +7 -13
  227. package/src/__tests__/skill-tool-factory.test.ts +97 -96
  228. package/src/__tests__/slack-channel-config.test.ts +3 -3
  229. package/src/__tests__/subagent-call-site-routing.test.ts +11 -3
  230. package/src/__tests__/subagent-disposal.test.ts +27 -8
  231. package/src/__tests__/subagent-fork-notifications.test.ts +24 -9
  232. package/src/__tests__/subagent-fork-spawn.test.ts +13 -4
  233. package/src/__tests__/subagent-manager-notify.test.ts +20 -8
  234. package/src/__tests__/subagent-notify-parent.test.ts +6 -5
  235. package/src/__tests__/subagent-spawn-tool-fork.test.ts +58 -0
  236. package/src/__tests__/subagent-tools.test.ts +2 -1
  237. package/src/__tests__/suggestion-routes.test.ts +2 -0
  238. package/src/__tests__/sync-message-contract.test.ts +59 -0
  239. package/src/__tests__/system-prompt.test.ts +183 -131
  240. package/src/__tests__/terminal-tools.test.ts +1 -1
  241. package/src/__tests__/test-preload-verifier.ts +68 -0
  242. package/src/__tests__/test-preload.ts +32 -39
  243. package/src/__tests__/tool-approval-handler.test.ts +1 -5
  244. package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
  245. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
  246. package/src/__tests__/tool-executor-lifecycle-events.test.ts +35 -12
  247. package/src/__tests__/tool-executor.test.ts +64 -72
  248. package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
  249. package/src/__tests__/tool-preview-lifecycle.test.ts +1 -0
  250. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  251. package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
  252. package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
  253. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
  254. package/src/__tests__/twilio-routes.test.ts +3 -2
  255. package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
  256. package/src/__tests__/usage-routes.test.ts +3 -0
  257. package/src/__tests__/validate-input.test.ts +381 -0
  258. package/src/__tests__/verification-control-plane-policy.test.ts +3 -2
  259. package/src/__tests__/voice-scoped-grant-consumer.test.ts +2 -1
  260. package/src/__tests__/voice-session-bridge.test.ts +37 -28
  261. package/src/__tests__/workspace-git-service.test.ts +6 -5
  262. package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
  263. package/src/__tests__/workspace-migration-090-memory-router-cost-optimized-profile.test.ts +326 -0
  264. package/src/__tests__/workspace-migration-091-retighten-migration-onboarding-thread.test.ts +166 -0
  265. package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
  266. package/src/acp/prepare-agent-env.ts +78 -0
  267. package/src/acp/session-manager.ts +6 -7
  268. package/src/agent/loop.ts +88 -0
  269. package/src/api/README.md +127 -0
  270. package/src/api/constants/call-sites.ts +27 -0
  271. package/src/api/events/assistant-outbound-attachment.ts +51 -0
  272. package/src/api/events/assistant-text-delta.ts +32 -0
  273. package/src/api/events/assistant-turn-start.ts +33 -0
  274. package/src/api/events/document-comment-created.ts +48 -0
  275. package/src/api/events/document-comment-deleted.ts +24 -0
  276. package/src/api/events/document-comment-reopened.ts +25 -0
  277. package/src/api/events/document-comment-resolved.ts +27 -0
  278. package/src/api/events/generation-cancelled.ts +24 -0
  279. package/src/api/events/generation-handoff.ts +41 -0
  280. package/src/api/events/message-complete.ts +42 -0
  281. package/src/api/events/open-url.ts +30 -0
  282. package/src/api/events/relationship-state-updated.ts +25 -0
  283. package/src/api/events/tool-use-start.ts +32 -0
  284. package/src/api/index.ts +129 -0
  285. package/src/api/package.json +10 -0
  286. package/src/api/responses/llm-context-response.ts +39 -0
  287. package/src/api/responses/llm-request-log-entry.ts +93 -0
  288. package/src/api/responses/memory-recall-log.ts +65 -0
  289. package/src/api/responses/memory-v2-activation-log.ts +78 -0
  290. package/src/background-wake/background-wake-routes.test.ts +868 -0
  291. package/src/background-wake/platform-client.test.ts +308 -0
  292. package/src/background-wake/platform-client.ts +167 -0
  293. package/src/background-wake/publisher.ts +91 -0
  294. package/src/background-wake/runtime-registry.ts +24 -0
  295. package/src/background-wake/wake-intent-hooks.test.ts +282 -0
  296. package/src/calls/guardian-dispatch.ts +1 -0
  297. package/src/calls/voice-session-bridge.ts +4 -4
  298. package/src/cli/commands/__tests__/browser.test.ts +23 -5
  299. package/src/cli/commands/__tests__/conversations-slack.test.ts +16 -0
  300. package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
  301. package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
  302. package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
  303. package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
  304. package/src/cli/commands/__tests__/memory-v2.test.ts +1 -0
  305. package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
  306. package/src/cli/commands/__tests__/notifications.test.ts +184 -40
  307. package/src/cli/commands/browser.ts +247 -0
  308. package/src/cli/commands/channels/__tests__/channels.test.ts +143 -0
  309. package/src/cli/commands/channels/index.ts +229 -0
  310. package/src/cli/commands/domain.ts +91 -41
  311. package/src/cli/commands/inference.ts +93 -40
  312. package/src/cli/commands/memory-v2-compare-render.ts +115 -0
  313. package/src/cli/commands/memory-v2.ts +176 -1
  314. package/src/cli/commands/memory-v3-render.ts +491 -0
  315. package/src/cli/commands/memory-v3.ts +567 -0
  316. package/src/cli/commands/notifications.ts +365 -55
  317. package/src/cli/lib/open-browser.ts +7 -2
  318. package/src/cli/program.ts +4 -0
  319. package/src/config/assistant-feature-flags.ts +39 -46
  320. package/src/config/bundled-skills/document-editor/SKILL.md +16 -3
  321. package/src/config/bundled-skills/document-editor/TOOLS.json +18 -0
  322. package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
  323. package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
  324. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
  325. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
  326. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
  327. package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
  328. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
  329. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
  330. package/src/config/bundled-skills/schedule/SKILL.md +1 -1
  331. package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
  332. package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -0
  333. package/src/config/bundled-tool-registry.ts +2 -0
  334. package/src/config/call-site-defaults.ts +8 -7
  335. package/src/config/feature-flag-cache.ts +86 -0
  336. package/src/config/feature-flag-registry.json +33 -17
  337. package/src/config/llm-context-resolution.ts +10 -1
  338. package/src/config/llm-resolver.ts +121 -15
  339. package/src/config/loader.ts +4 -5
  340. package/src/config/schemas/__tests__/memory-v2.test.ts +228 -1
  341. package/src/config/schemas/call-site-catalog.ts +21 -7
  342. package/src/config/schemas/heartbeat.ts +1 -1
  343. package/src/config/schemas/llm.ts +102 -2
  344. package/src/config/schemas/memory-v2.ts +272 -0
  345. package/src/config/schemas/memory.ts +2 -1
  346. package/src/config/schemas/services.ts +6 -2
  347. package/src/config/seed-inference-profiles.ts +36 -16
  348. package/src/context/compactor.ts +52 -0
  349. package/src/context/token-estimator.ts +10 -5
  350. package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
  351. package/src/conversations/message-consolidation.ts +404 -0
  352. package/src/credential-execution/executable-discovery.ts +40 -0
  353. package/src/credential-execution/process-manager.ts +6 -2
  354. package/src/credential-health/credential-health-service.ts +125 -40
  355. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -6
  356. package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +13 -15
  357. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +2 -3
  358. package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -0
  359. package/src/daemon/__tests__/meet-manifest-loader.test.ts +25 -12
  360. package/src/daemon/__tests__/native-web-search-metadata.test.ts +1 -0
  361. package/src/daemon/__tests__/switch-inference-profile-tool.test.ts +107 -0
  362. package/src/daemon/__tests__/web-search-status-text.test.ts +1 -0
  363. package/src/daemon/conversation-agent-loop-handlers.ts +390 -80
  364. package/src/daemon/conversation-agent-loop.ts +244 -90
  365. package/src/daemon/conversation-error.ts +64 -6
  366. package/src/daemon/conversation-lifecycle.ts +27 -22
  367. package/src/daemon/conversation-messaging.ts +84 -43
  368. package/src/daemon/conversation-process.ts +74 -37
  369. package/src/daemon/conversation-runtime-assembly.ts +38 -17
  370. package/src/daemon/conversation-skill-tools.ts +14 -30
  371. package/src/daemon/conversation-surfaces.ts +69 -34
  372. package/src/daemon/conversation-tool-setup.ts +77 -32
  373. package/src/daemon/conversation-usage.ts +2 -0
  374. package/src/daemon/conversation.ts +40 -75
  375. package/src/daemon/daemon-control.ts +1 -1
  376. package/src/daemon/daemon-skill-host.ts +9 -2
  377. package/src/daemon/disk-pressure-guard.ts +39 -29
  378. package/src/daemon/first-greeting.ts +31 -13
  379. package/src/daemon/handlers/config-model.test.ts +1 -0
  380. package/src/daemon/handlers/conversations.ts +11 -3
  381. package/src/daemon/handlers/shared.ts +6 -1
  382. package/src/daemon/host-browser-proxy.ts +5 -5
  383. package/src/daemon/host-cu-proxy.ts +4 -4
  384. package/src/daemon/host-file-proxy.ts +4 -4
  385. package/src/daemon/host-proxy-base.ts +4 -4
  386. package/src/daemon/host-transfer-proxy.ts +10 -10
  387. package/src/daemon/lifecycle.ts +29 -26
  388. package/src/daemon/mcp-reload-service.ts +1 -1
  389. package/src/daemon/meet-manifest-loader.ts +11 -24
  390. package/src/daemon/message-types/conversations.ts +22 -27
  391. package/src/daemon/message-types/document-comments.ts +8 -44
  392. package/src/daemon/message-types/home.ts +2 -14
  393. package/src/daemon/message-types/integrations.ts +2 -7
  394. package/src/daemon/message-types/messages.ts +25 -48
  395. package/src/daemon/message-types/subagents.ts +6 -0
  396. package/src/daemon/message-types/sync.ts +14 -0
  397. package/src/daemon/process-message.ts +9 -9
  398. package/src/daemon/providers-setup.ts +1 -1
  399. package/src/daemon/server.ts +16 -0
  400. package/src/daemon/shutdown-handlers.ts +24 -5
  401. package/src/daemon/switch-inference-profile-tool.ts +62 -0
  402. package/src/daemon/tool-setup-types.ts +7 -0
  403. package/src/daemon/wake-target-adapter.ts +10 -0
  404. package/src/documents/document-store.ts +38 -0
  405. package/src/export/__tests__/transcript-formatter.test.ts +1 -0
  406. package/src/heartbeat/__tests__/heartbeat-service.test.ts +30 -1
  407. package/src/heartbeat/heartbeat-service.ts +63 -0
  408. package/src/home/__tests__/feed-writer.test.ts +161 -0
  409. package/src/home/__tests__/post-connect-feed.test.ts +1 -0
  410. package/src/home/__tests__/suggested-prompts.test.ts +55 -59
  411. package/src/home/feed-writer.ts +146 -7
  412. package/src/home/home-greeting.ts +0 -9
  413. package/src/home/suggested-prompts.ts +27 -154
  414. package/src/ipc/__tests__/cli-ipc.test.ts +1 -0
  415. package/src/ipc/gateway-client.test.ts +4 -1
  416. package/src/ipc/gateway-flag-listener.ts +123 -0
  417. package/src/ipc/skill-routes/__tests__/memory.test.ts +1 -0
  418. package/src/ipc/skill-routes/__tests__/registries.test.ts +36 -7
  419. package/src/ipc/skill-routes/memory.ts +4 -3
  420. package/src/ipc/skill-routes/registries.ts +35 -40
  421. package/src/memory/__tests__/db-async-query.test.ts +165 -0
  422. package/src/memory/__tests__/db-maintenance.test.ts +115 -0
  423. package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +242 -0
  424. package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
  425. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +26 -5
  426. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +1 -0
  427. package/src/memory/__tests__/memory-retrospective-job.test.ts +8 -0
  428. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +1 -0
  429. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +31 -0
  430. package/src/memory/auto-analysis-enqueue.ts +5 -1
  431. package/src/memory/conversation-attention-store.ts +17 -3
  432. package/src/memory/conversation-crud.ts +423 -182
  433. package/src/memory/conversation-starters-cadence.ts +3 -1
  434. package/src/memory/conversation-title-service.ts +19 -3
  435. package/src/memory/db-async-query.ts +214 -0
  436. package/src/memory/db-connection.ts +29 -19
  437. package/src/memory/db-init.ts +14 -0
  438. package/src/memory/db-maintenance.ts +30 -21
  439. package/src/memory/db-singleton.ts +77 -0
  440. package/src/memory/delivery-channels.ts +82 -0
  441. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +2 -4
  442. package/src/memory/graph/bootstrap.ts +8 -1
  443. package/src/memory/graph/capability-seed.ts +7 -3
  444. package/src/memory/graph/conversation-graph-memory.ts +100 -17
  445. package/src/memory/graph/extraction.ts +1 -5
  446. package/src/memory/graph/graph-search.ts +7 -1
  447. package/src/memory/graph/retriever.test.ts +3 -3
  448. package/src/memory/indexer.ts +28 -18
  449. package/src/memory/job-handlers/cleanup.ts +76 -18
  450. package/src/memory/job-handlers/conversation-starters.ts +1 -4
  451. package/src/memory/job-handlers/embedding.test.ts +3 -2
  452. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -2
  453. package/src/memory/jobs/embed-pkb-file.ts +6 -1
  454. package/src/memory/jobs-store.ts +14 -0
  455. package/src/memory/jobs-worker.ts +66 -22
  456. package/src/memory/llm-request-log-source-clickhouse.ts +122 -2
  457. package/src/memory/llm-request-log-source-local.ts +31 -0
  458. package/src/memory/llm-request-log-source.ts +40 -2
  459. package/src/memory/llm-request-log-store.ts +228 -1
  460. package/src/memory/llm-usage-store.ts +24 -0
  461. package/src/memory/memory-retrospective-enqueue.ts +8 -1
  462. package/src/memory/memory-retrospective-job.ts +5 -0
  463. package/src/memory/memory-v2-activation-log-store.ts +110 -7
  464. package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
  465. package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
  466. package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
  467. package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
  468. package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
  469. package/src/memory/migrations/265-drop-provider-connection-status.ts +26 -0
  470. package/src/memory/migrations/266-messages-client-message-id.ts +43 -0
  471. package/src/memory/migrations/index.ts +19 -0
  472. package/src/memory/migrations/registry.ts +33 -0
  473. package/src/memory/schema/conversations.ts +10 -2
  474. package/src/memory/schema/inference.ts +0 -1
  475. package/src/memory/schema/infrastructure.ts +21 -0
  476. package/src/memory/tool-usage-store.ts +36 -8
  477. package/src/memory/v2/__tests__/backfill-jobs.test.ts +5 -2
  478. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
  479. package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
  480. package/src/memory/v2/__tests__/harness-metrics.test.ts +83 -0
  481. package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
  482. package/src/memory/v2/__tests__/harness-replay-input.test.ts +230 -0
  483. package/src/memory/v2/__tests__/harness-runner.test.ts +135 -0
  484. package/src/memory/v2/__tests__/injection.test.ts +127 -98
  485. package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
  486. package/src/memory/v2/__tests__/router.test.ts +171 -3
  487. package/src/memory/v2/__tests__/sweep-job.test.ts +6 -3
  488. package/src/memory/v2/harness/compare.ts +57 -0
  489. package/src/memory/v2/harness/metrics.ts +128 -0
  490. package/src/memory/v2/harness/oracle.ts +145 -0
  491. package/src/memory/v2/harness/replay-input.ts +240 -0
  492. package/src/memory/v2/harness/retriever.ts +74 -0
  493. package/src/memory/v2/harness/router-retriever.ts +43 -0
  494. package/src/memory/v2/harness/runner.ts +112 -0
  495. package/src/memory/v2/harness/trace.ts +64 -0
  496. package/src/memory/v2/injection.ts +21 -15
  497. package/src/memory/v2/prompts/router.ts +26 -1
  498. package/src/memory/v2/qdrant.ts +14 -2
  499. package/src/memory/v2/router.ts +171 -18
  500. package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
  501. package/src/memory/v3/__tests__/consolidation-job.test.ts +466 -0
  502. package/src/memory/v3/__tests__/coretrieval-seed.test.ts +270 -0
  503. package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
  504. package/src/memory/v3/__tests__/edges.test.ts +706 -0
  505. package/src/memory/v3/__tests__/filter.test.ts +560 -0
  506. package/src/memory/v3/__tests__/gate.test.ts +637 -0
  507. package/src/memory/v3/__tests__/index-composition.test.ts +291 -0
  508. package/src/memory/v3/__tests__/loop.test.ts +775 -0
  509. package/src/memory/v3/__tests__/retriever.test.ts +226 -0
  510. package/src/memory/v3/__tests__/scouts.test.ts +489 -0
  511. package/src/memory/v3/__tests__/shadow-diff.test.ts +225 -0
  512. package/src/memory/v3/__tests__/shadow-middleware.test.ts +398 -0
  513. package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
  514. package/src/memory/v3/__tests__/traversal.test.ts +508 -0
  515. package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
  516. package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
  517. package/src/memory/v3/__tests__/tree-walk.test.ts +784 -0
  518. package/src/memory/v3/__tests__/validate.test.ts +277 -0
  519. package/src/memory/v3/auto-edges.ts +223 -0
  520. package/src/memory/v3/coactivation-store.ts +124 -0
  521. package/src/memory/v3/consolidation-job.ts +323 -0
  522. package/src/memory/v3/coretrieval-seed.ts +240 -0
  523. package/src/memory/v3/edge-learning-job.ts +160 -0
  524. package/src/memory/v3/edges.ts +286 -0
  525. package/src/memory/v3/filter.ts +286 -0
  526. package/src/memory/v3/gate.ts +349 -0
  527. package/src/memory/v3/index-composition.ts +126 -0
  528. package/src/memory/v3/llm-capture.ts +46 -0
  529. package/src/memory/v3/loop.ts +430 -0
  530. package/src/memory/v3/maintenance.ts +144 -0
  531. package/src/memory/v3/prompt-context.ts +33 -0
  532. package/src/memory/v3/prompts/consolidation.ts +458 -0
  533. package/src/memory/v3/prompts/system-prompts.ts +196 -0
  534. package/src/memory/v3/retriever.ts +33 -0
  535. package/src/memory/v3/scouts.ts +431 -0
  536. package/src/memory/v3/shadow-diff.ts +287 -0
  537. package/src/memory/v3/shadow-middleware.ts +347 -0
  538. package/src/memory/v3/traversal.ts +211 -0
  539. package/src/memory/v3/tree-index.ts +237 -0
  540. package/src/memory/v3/tree-store.ts +394 -0
  541. package/src/memory/v3/tree-walk.ts +356 -0
  542. package/src/memory/v3/types.ts +65 -0
  543. package/src/memory/v3/validate.ts +323 -0
  544. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +1 -0
  545. package/src/notifications/__tests__/home-feed-side-effect.test.ts +1 -0
  546. package/src/notifications/adapters/macos.ts +18 -1
  547. package/src/notifications/adapters/platform.ts +1 -1
  548. package/src/notifications/adapters/slack.ts +45 -11
  549. package/src/notifications/broadcaster.ts +114 -63
  550. package/src/notifications/conversation-pairing.ts +23 -3
  551. package/src/notifications/decision-engine.ts +1 -4
  552. package/src/notifications/decisions-store.ts +32 -1
  553. package/src/notifications/deliveries-store.ts +45 -0
  554. package/src/notifications/edit-notification.ts +201 -0
  555. package/src/notifications/emit-signal.ts +40 -50
  556. package/src/notifications/signal.ts +10 -0
  557. package/src/notifications/types.ts +37 -0
  558. package/src/oauth/byo-connection.test.ts +67 -3
  559. package/src/oauth/byo-connection.ts +32 -5
  560. package/src/oauth/connect-orchestrator.ts +9 -0
  561. package/src/oauth/connection-resolver.test.ts +76 -0
  562. package/src/oauth/connection-resolver.ts +49 -10
  563. package/src/oauth/manual-token-connection.ts +51 -3
  564. package/src/oauth/seed-providers.ts +3 -0
  565. package/src/permissions/approval-policy.test.ts +19 -5
  566. package/src/permissions/approval-policy.ts +14 -3
  567. package/src/permissions/checker.ts +21 -8
  568. package/src/permissions/prompter.ts +3 -3
  569. package/src/permissions/question-prompter.ts +5 -2
  570. package/src/permissions/secret-prompter.ts +2 -2
  571. package/src/platform/client.test.ts +24 -1
  572. package/src/platform/client.ts +8 -0
  573. package/src/platform/feature-gate.ts +15 -0
  574. package/src/plugin-api/index.ts +4 -0
  575. package/src/plugin-api/types.ts +7 -33
  576. package/src/plugins/defaults/index.ts +6 -0
  577. package/src/plugins/defaults/injectors.ts +20 -19
  578. package/src/plugins/defaults/persistence.ts +25 -6
  579. package/src/plugins/external-plugin-loader.ts +5 -68
  580. package/src/plugins/types.ts +68 -29
  581. package/src/proactive-artifact/aux-message-injector.ts +17 -4
  582. package/src/proactive-artifact/job.test.ts +1 -0
  583. package/src/prompts/__tests__/system-prompt.test.ts +4 -4
  584. package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
  585. package/src/prompts/persona-resolver.ts +36 -21
  586. package/src/prompts/sections.ts +39 -7
  587. package/src/prompts/system-prompt.ts +84 -221
  588. package/src/prompts/template-detection.ts +10 -4
  589. package/src/prompts/templates/BOOTSTRAP.md +9 -13
  590. package/src/prompts/templates/IDENTITY.md +0 -2
  591. package/src/prompts/templates/system-sections.ts +230 -8
  592. package/src/providers/__tests__/connection-model-compat.test.ts +233 -0
  593. package/src/providers/__tests__/registry-native-web-search.test.ts +122 -0
  594. package/src/providers/__tests__/retry-callsite.test.ts +85 -5
  595. package/src/providers/anthropic/client.ts +32 -66
  596. package/src/providers/call-site-routing.ts +42 -6
  597. package/src/providers/connection-model-compat.ts +61 -0
  598. package/src/providers/connection-resolution.ts +47 -14
  599. package/src/providers/fireworks/client.ts +1 -0
  600. package/src/providers/gemini/client.ts +70 -6
  601. package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +0 -2
  602. package/src/providers/inference/__tests__/base-url-security.test.ts +2 -3
  603. package/src/providers/inference/__tests__/{connections-status-label.test.ts → connections-label.test.ts} +12 -111
  604. package/src/providers/inference/adapter-factory.ts +3 -0
  605. package/src/providers/inference/auth.ts +0 -8
  606. package/src/providers/inference/connections.ts +3 -66
  607. package/src/providers/inference/resolve-auth.ts +2 -3
  608. package/src/providers/minimax/client.ts +106 -0
  609. package/src/providers/model-catalog.ts +78 -1
  610. package/src/providers/model-intents.ts +4 -4
  611. package/src/providers/openai/__tests__/api-error-detail.test.ts +120 -0
  612. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +157 -5
  613. package/src/providers/openai/chat-completions-provider.ts +116 -15
  614. package/src/providers/openai/codex-models.ts +20 -0
  615. package/src/providers/openai/responses-provider.ts +87 -30
  616. package/src/providers/openrouter/client.ts +13 -8
  617. package/src/providers/provider-send-message.ts +20 -5
  618. package/src/providers/registry.ts +48 -8
  619. package/src/providers/retry.ts +50 -7
  620. package/src/providers/search-provider-catalog.ts +17 -9
  621. package/src/providers/thinking-config.ts +26 -1
  622. package/src/providers/types.ts +9 -0
  623. package/src/providers/usage-tracking.ts +2 -0
  624. package/src/runtime/AGENTS.md +2 -2
  625. package/src/runtime/__tests__/agent-wake.test.ts +1 -0
  626. package/src/runtime/__tests__/background-job-runner.test.ts +1 -0
  627. package/src/runtime/access-request-helper.ts +1 -0
  628. package/src/runtime/agent-wake.ts +1 -0
  629. package/src/runtime/assistant-event-hub.ts +76 -6
  630. package/src/runtime/auth/route-policy.ts +46 -0
  631. package/src/runtime/btw-sidechain.ts +0 -6
  632. package/src/runtime/channel-readiness-service.ts +68 -0
  633. package/src/runtime/channel-reply-delivery.ts +23 -0
  634. package/src/runtime/channel-retry-sweep.ts +47 -14
  635. package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
  636. package/src/runtime/http-types.ts +0 -2
  637. package/src/runtime/migrations/vbundle-builder.ts +12 -4
  638. package/src/runtime/pending-interactions.ts +0 -1
  639. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +1 -0
  640. package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +406 -0
  641. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +204 -0
  642. package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +1 -1
  643. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +209 -1
  644. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +13 -50
  645. package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +76 -9
  646. package/src/runtime/routes/__tests__/memory-v3-simulate-params.test.ts +35 -0
  647. package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
  648. package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -2
  649. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +294 -0
  650. package/src/runtime/routes/__tests__/task-routes.test.ts +48 -3
  651. package/src/runtime/routes/acp-routes-list.test.ts +3 -0
  652. package/src/runtime/routes/acp-routes.test.ts +255 -6
  653. package/src/runtime/routes/acp-routes.ts +8 -1
  654. package/src/runtime/routes/app-management-routes.ts +111 -4
  655. package/src/runtime/routes/avatar-routes.ts +10 -10
  656. package/src/runtime/routes/background-wake-routes.ts +356 -0
  657. package/src/runtime/routes/browser-tabs-routes.ts +200 -0
  658. package/src/runtime/routes/btw-routes.ts +4 -10
  659. package/src/runtime/routes/conversation-analysis-routes.ts +6 -0
  660. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  661. package/src/runtime/routes/conversation-compaction-routes.ts +263 -0
  662. package/src/runtime/routes/conversation-list-routes.ts +159 -4
  663. package/src/runtime/routes/conversation-management-routes.ts +108 -26
  664. package/src/runtime/routes/conversation-query-routes.ts +200 -44
  665. package/src/runtime/routes/conversation-routes.ts +409 -521
  666. package/src/runtime/routes/conversation-starter-routes.ts +6 -3
  667. package/src/runtime/routes/conversations-import-routes.ts +19 -6
  668. package/src/runtime/routes/disk-pressure-routes.ts +1 -1
  669. package/src/runtime/routes/documents-routes.ts +10 -1
  670. package/src/runtime/routes/domain-routes.ts +60 -10
  671. package/src/runtime/routes/email-routes.ts +5 -2
  672. package/src/runtime/routes/events-routes.ts +54 -10
  673. package/src/runtime/routes/group-routes.ts +35 -8
  674. package/src/runtime/routes/home-feed-routes.ts +129 -0
  675. package/src/runtime/routes/host-browser-routes.ts +10 -2
  676. package/src/runtime/routes/host-cu-routes.ts +2 -2
  677. package/src/runtime/routes/identity-intro-cache.ts +61 -16
  678. package/src/runtime/routes/identity-routes.ts +30 -9
  679. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
  680. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +530 -6
  681. package/src/runtime/routes/inbound-stages/background-dispatch.ts +57 -8
  682. package/src/runtime/routes/index.ts +10 -0
  683. package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
  684. package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
  685. package/src/runtime/routes/inference-provider-connection-routes.ts +5 -26
  686. package/src/runtime/routes/integrations/vercel.ts +15 -0
  687. package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
  688. package/src/runtime/routes/llm-context-normalization.ts +7 -2
  689. package/src/runtime/routes/memory-item-routes.ts +8 -3
  690. package/src/runtime/routes/memory-v2-routes.ts +215 -5
  691. package/src/runtime/routes/memory-v3-routes.ts +474 -0
  692. package/src/runtime/routes/migration-routes.ts +32 -28
  693. package/src/runtime/routes/notification-routes.ts +63 -1
  694. package/src/runtime/routes/oauth-commands-routes.ts +6 -1
  695. package/src/runtime/routes/plugins-routes.ts +337 -0
  696. package/src/runtime/routes/rename-conversation-routes.ts +6 -2
  697. package/src/runtime/routes/secret-routes.ts +25 -5
  698. package/src/runtime/routes/settings-routes.ts +12 -11
  699. package/src/runtime/routes/slack-channel-routes.ts +5 -4
  700. package/src/runtime/routes/surface-action-routes.ts +1 -38
  701. package/src/runtime/routes/surface-content-routes.ts +12 -5
  702. package/src/runtime/routes/surface-conversation-resolver.ts +65 -0
  703. package/src/runtime/routes/wipe-conversation-routes.ts +3 -0
  704. package/src/runtime/routes/workspace-routes.ts +25 -10
  705. package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -0
  706. package/src/runtime/slack-dm-text-delivery.ts +177 -0
  707. package/src/runtime/sync/resource-sync-events.ts +106 -38
  708. package/src/runtime/sync/sync-publisher.test.ts +49 -0
  709. package/src/runtime/sync/sync-publisher.ts +2 -1
  710. package/src/runtime/tool-grant-request-helper.ts +1 -0
  711. package/src/runtime/verification-outbound-actions.ts +73 -1
  712. package/src/schedule/schedule-store.ts +8 -1
  713. package/src/schedule/scheduler.ts +111 -15
  714. package/src/security/__tests__/provider-key-env-fallback.test.ts +3 -3
  715. package/src/security/encrypted-store.ts +7 -16
  716. package/src/security/store-path-override.ts +61 -0
  717. package/src/signals/user-message.ts +5 -8
  718. package/src/skills/validate-input.ts +177 -0
  719. package/src/subagent/manager.ts +13 -13
  720. package/src/subagent/types.ts +6 -0
  721. package/src/tasks/tool-sanitizer.ts +2 -2
  722. package/src/telemetry/types.ts +12 -0
  723. package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
  724. package/src/telemetry/usage-telemetry-reporter.ts +1 -0
  725. package/src/tools/acp/spawn.test.ts +119 -0
  726. package/src/tools/acp/spawn.ts +15 -2
  727. package/src/tools/apps/definitions.ts +36 -28
  728. package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
  729. package/src/tools/ask-question/ask-question-tool.ts +38 -45
  730. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +2 -8
  731. package/src/tools/browser/__tests__/pinned-tabs.test.ts +70 -0
  732. package/src/tools/browser/browser-execution.ts +16 -3
  733. package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
  734. package/src/tools/browser/cdp-client/__tests__/types.test.ts +3 -0
  735. package/src/tools/browser/cdp-client/cdp-inspect-client.ts +12 -0
  736. package/src/tools/browser/cdp-client/extension-cdp-client.ts +27 -1
  737. package/src/tools/browser/cdp-client/factory.ts +100 -17
  738. package/src/tools/browser/cdp-client/local-cdp-client.ts +12 -0
  739. package/src/tools/browser/cdp-client/types.ts +65 -0
  740. package/src/tools/browser/pinned-tabs.ts +96 -40
  741. package/src/tools/computer-use/definitions.ts +282 -336
  742. package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
  743. package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
  744. package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
  745. package/src/tools/credentials/vault.ts +3 -9
  746. package/src/tools/document/document-tool.ts +189 -7
  747. package/src/tools/execution-target.ts +18 -23
  748. package/src/tools/executor.ts +24 -56
  749. package/src/tools/filesystem/edit.ts +3 -9
  750. package/src/tools/filesystem/list.ts +3 -9
  751. package/src/tools/filesystem/read.ts +3 -9
  752. package/src/tools/filesystem/write.ts +3 -9
  753. package/src/tools/host-filesystem/edit.test.ts +1 -0
  754. package/src/tools/host-filesystem/edit.ts +3 -9
  755. package/src/tools/host-filesystem/read.test.ts +1 -0
  756. package/src/tools/host-filesystem/read.ts +3 -9
  757. package/src/tools/host-filesystem/transfer.test.ts +31 -6
  758. package/src/tools/host-filesystem/transfer.ts +3 -9
  759. package/src/tools/host-filesystem/write.test.ts +1 -0
  760. package/src/tools/host-filesystem/write.ts +3 -9
  761. package/src/tools/host-terminal/host-shell.ts +3 -9
  762. package/src/tools/mcp/mcp-tool-factory.ts +1 -10
  763. package/src/tools/memory/register.test.ts +1 -1
  764. package/src/tools/memory/register.ts +4 -9
  765. package/src/tools/network/__tests__/managed-search-proxy.test.ts +282 -0
  766. package/src/tools/network/__tests__/web-search.test.ts +211 -3
  767. package/src/tools/network/managed-search-proxy.ts +183 -0
  768. package/src/tools/network/web-fetch.ts +3 -9
  769. package/src/tools/network/web-search.ts +224 -76
  770. package/src/tools/policy-context.ts +3 -1
  771. package/src/tools/registry.ts +150 -123
  772. package/src/tools/schedule/create.ts +1 -1
  773. package/src/tools/schema-transforms.ts +1 -1
  774. package/src/tools/skills/execute.ts +3 -9
  775. package/src/tools/skills/load.ts +3 -9
  776. package/src/tools/skills/skill-tool-factory.ts +18 -44
  777. package/src/tools/subagent/notify-parent.ts +3 -9
  778. package/src/tools/subagent/spawn.ts +3 -0
  779. package/src/tools/system/request-permission.ts +3 -9
  780. package/src/tools/terminal/shell.ts +3 -9
  781. package/src/tools/tool-approval-handler.ts +10 -4
  782. package/src/tools/tool-defaults.ts +94 -0
  783. package/src/tools/tool-name-aliases.ts +72 -14
  784. package/src/tools/types.ts +32 -101
  785. package/src/tools/ui-surface/definitions.ts +104 -108
  786. package/src/types/onboarding-context.ts +6 -0
  787. package/src/usage/attribution.ts +32 -1
  788. package/src/usage/pricing.ts +23 -0
  789. package/src/usage/types.ts +12 -0
  790. package/src/util/browser.ts +7 -2
  791. package/src/util/logger.ts +16 -7
  792. package/src/util/platform.ts +7 -2
  793. package/src/util/sqlite3-runtime.ts +65 -0
  794. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
  795. package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
  796. package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +109 -0
  797. package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +41 -0
  798. package/src/workspace/migrations/registry.ts +6 -0
  799. package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
  800. package/src/__tests__/message-complete-display-id.test.ts +0 -175
  801. package/src/daemon/query-complexity-router.ts +0 -75
  802. package/src/prompts/cache-boundary.ts +0 -8
@@ -106,6 +106,7 @@ mock.module("../memory/conversation-crud.js", () => ({
106
106
  provenanceFromTrustContext: () => undefined,
107
107
  setConversationOriginChannelIfUnset: () => {},
108
108
  setConversationOriginInterfaceIfUnset: () => {},
109
+ reserveMessage: mock(async () => ({ id: "msg-reserve" })),
109
110
  }));
110
111
 
111
112
  mock.module("../runtime/local-actor-identity.js", () => ({
@@ -187,7 +188,10 @@ function makeRequest(
187
188
  });
188
189
  }
189
190
 
190
- const persistUserMessageMock = mock(async () => "persisted-id");
191
+ const persistUserMessageMock = mock(async () => ({
192
+ id: "persisted-id",
193
+ deduplicated: false,
194
+ }));
191
195
  const runAgentLoopMock = mock(async () => undefined);
192
196
 
193
197
  function makeSendMessageDeps() {
@@ -25,7 +25,6 @@ mock.module("../util/logger.js", () => ({
25
25
 
26
26
  import type { CesClient } from "../credential-execution/client.js";
27
27
  import * as encryptedStore from "../security/encrypted-store.js";
28
- import { _setStorePath } from "../security/encrypted-store.js";
29
28
  import {
30
29
  _resetBackend,
31
30
  deleteSecureKeyAsync,
@@ -36,6 +35,7 @@ import {
36
35
  setCesReconnect,
37
36
  setSecureKeyAsync,
38
37
  } from "../security/secure-keys.js";
38
+ import { setStorePathForTesting } from "./encrypted-store-test-helpers.js";
39
39
 
40
40
  // ---------------------------------------------------------------------------
41
41
  // Use a temp directory for encrypted store tests
@@ -59,11 +59,11 @@ describe("secure-keys", () => {
59
59
  rmSync(TEST_DIR, { recursive: true });
60
60
  }
61
61
  mkdirSync(TEST_DIR, { recursive: true });
62
- _setStorePath(STORE_PATH);
62
+ setStorePathForTesting(STORE_PATH);
63
63
  });
64
64
 
65
65
  afterEach(() => {
66
- _setStorePath(null);
66
+ setStorePathForTesting(null);
67
67
  _resetBackend();
68
68
  delete process.env.VELLUM_DEV;
69
69
  delete process.env.VELLUM_DESKTOP_APP;
@@ -136,13 +136,9 @@ function makeCompletingConversation(): Conversation {
136
136
  const messages: unknown[] = [];
137
137
  return {
138
138
  isProcessing: () => processing,
139
- persistUserMessage: (
140
- _content: string,
141
- _attachments: unknown[],
142
- requestId?: string,
143
- ) => {
139
+ persistUserMessage: (options: { requestId?: string }) => {
144
140
  processing = true;
145
- return requestId ?? "msg-1";
141
+ return { id: options.requestId ?? "msg-1", deduplicated: false };
146
142
  },
147
143
  memoryPolicy: {
148
144
  scopeId: "default",
@@ -188,18 +184,14 @@ function makeHangingConversation(): Conversation {
188
184
  const messages: unknown[] = [];
189
185
  const enqueuedMessages: Array<{
190
186
  content: string;
191
- onEvent: (msg: ServerMessage) => void;
192
- requestId: string;
187
+ onEvent?: (msg: ServerMessage) => void;
188
+ requestId?: string;
193
189
  }> = [];
194
190
  return {
195
191
  isProcessing: () => processing,
196
- persistUserMessage: (
197
- _content: string,
198
- _attachments: unknown[],
199
- requestId?: string,
200
- ) => {
192
+ persistUserMessage: (options: { requestId?: string }) => {
201
193
  processing = true;
202
- return requestId ?? "msg-1";
194
+ return { id: options.requestId ?? "msg-1", deduplicated: false };
203
195
  },
204
196
  memoryPolicy: {
205
197
  scopeId: "default",
@@ -223,14 +215,20 @@ function makeHangingConversation(): Conversation {
223
215
  hasPendingConfirmation: () => false,
224
216
  denyAllPendingConfirmations: () => {},
225
217
  getQueueDepth: () => enqueuedMessages.length,
226
- enqueueMessage: (
227
- content: string,
228
- _attachments: unknown[],
229
- onEvent: (msg: ServerMessage) => void,
230
- requestId: string,
231
- ) => {
232
- enqueuedMessages.push({ content, onEvent, requestId });
233
- return { queued: true, requestId };
218
+ enqueueMessage: (options: {
219
+ content: string;
220
+ onEvent?: (msg: ServerMessage) => void;
221
+ requestId?: string;
222
+ }) => {
223
+ enqueuedMessages.push({
224
+ content: options.content,
225
+ onEvent: options.onEvent,
226
+ requestId: options.requestId,
227
+ });
228
+ return {
229
+ queued: true,
230
+ requestId: options.requestId ?? "hanging-req",
231
+ };
234
232
  },
235
233
  runAgentLoop: async () => {
236
234
  // Hang forever
@@ -259,14 +257,9 @@ function makePendingApprovalConversation(
259
257
  const messages: unknown[] = [];
260
258
  const runAgentLoopMock = mock(async () => {});
261
259
  const enqueueMessageMock = mock(
262
- (
263
- _content: string,
264
- _attachments: unknown[],
265
- _onEvent: (msg: ServerMessage) => void,
266
- queuedRequestId: string,
267
- ) => ({
260
+ (options: { content: string; requestId?: string }) => ({
268
261
  queued: true,
269
- requestId: queuedRequestId,
262
+ requestId: options.requestId ?? "queued-req",
270
263
  }),
271
264
  );
272
265
  const denyAllPendingConfirmationsMock = mock(() => {
@@ -278,11 +271,10 @@ function makePendingApprovalConversation(
278
271
 
279
272
  const conversation = {
280
273
  isProcessing: () => processing,
281
- persistUserMessage: (
282
- _content: string,
283
- _attachments: unknown[],
284
- reqId?: string,
285
- ) => reqId ?? "msg-1",
274
+ persistUserMessage: (options: { requestId?: string }) => ({
275
+ id: options.requestId ?? "msg-1",
276
+ deduplicated: false,
277
+ }),
286
278
  memoryPolicy: {
287
279
  scopeId: "default",
288
280
  includeDefaultFallback: false,
@@ -895,7 +887,7 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
895
887
  await stopServer();
896
888
  });
897
889
 
898
- test("accepts message when conversationKey is omitted (defaults to stable channel key)", async () => {
890
+ test("accepts message when conversationKey is omitted (vellum channel mints fresh)", async () => {
899
891
  await startServer(() => makeCompletingConversation());
900
892
 
901
893
  const res = await fetch(messagesUrl(), {
@@ -908,14 +900,24 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
908
900
  }),
909
901
  });
910
902
  expect(res.status).toBe(202);
903
+ const body = (await res.json()) as {
904
+ accepted: boolean;
905
+ conversationId: string;
906
+ };
907
+ expect(body.accepted).toBe(true);
908
+ expect(body.conversationId).toBeTruthy();
909
+
910
+ // The vellum channel never falls through to the shared
911
+ // `default:vellum:<interface>` thread: each empty-handed send mints
912
+ // a fresh conversation so the first-message id surfaces to the client.
913
+ expect(getConversationByKey("default:vellum:macos")).toBeNull();
911
914
 
912
915
  await stopServer();
913
916
  });
914
917
 
915
- test("two calls without conversationKey use the same conversation", async () => {
918
+ test("two empty-handed vellum sends each mint distinct conversations", async () => {
916
919
  await startServer(() => makeCompletingConversation());
917
920
 
918
- // First message — no conversationKey
919
921
  const res1 = await fetch(messagesUrl(), {
920
922
  method: "POST",
921
923
  headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
@@ -926,8 +928,8 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
926
928
  }),
927
929
  });
928
930
  expect(res1.status).toBe(202);
931
+ const body1 = (await res1.json()) as { conversationId: string };
929
932
 
930
- // Second message — same channel/interface, still no conversationKey
931
933
  const res2 = await fetch(messagesUrl(), {
932
934
  method: "POST",
933
935
  headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
@@ -938,12 +940,49 @@ describe("POST /v1/messages — queue-if-busy and hub publishing", () => {
938
940
  }),
939
941
  });
940
942
  expect(res2.status).toBe(202);
943
+ const body2 = (await res2.json()) as { conversationId: string };
944
+
945
+ expect(body1.conversationId).toBeTruthy();
946
+ expect(body2.conversationId).toBeTruthy();
947
+ expect(body1.conversationId).not.toBe(body2.conversationId);
948
+
949
+ await stopServer();
950
+ });
951
+
952
+ test("two empty-handed phone sends share the default channel thread", async () => {
953
+ await startServer(() => makeCompletingConversation());
954
+
955
+ const res1 = await fetch(messagesUrl(), {
956
+ method: "POST",
957
+ headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
958
+ body: JSON.stringify({
959
+ content: "First",
960
+ sourceChannel: "phone",
961
+ interface: "phone",
962
+ }),
963
+ });
964
+ expect(res1.status).toBe(202);
965
+ const body1 = (await res1.json()) as { conversationId: string };
966
+
967
+ const res2 = await fetch(messagesUrl(), {
968
+ method: "POST",
969
+ headers: { "Content-Type": "application/json", ...AUTH_HEADERS },
970
+ body: JSON.stringify({
971
+ content: "Second",
972
+ sourceChannel: "phone",
973
+ interface: "phone",
974
+ }),
975
+ });
976
+ expect(res2.status).toBe(202);
977
+ const body2 = (await res2.json()) as { conversationId: string };
941
978
 
942
- // Both should have resolved to the same default conversation key
943
- // ("default:vellum:macos"), which maps to the same conversationId.
944
- const mapping = getConversationByKey("default:vellum:macos");
979
+ // Non-vellum channels keep the legacy `default:<channel>:<interface>`
980
+ // co-location so repeated inbound messages from the same external
981
+ // channel/interface land on a single thread.
982
+ expect(body1.conversationId).toBe(body2.conversationId);
983
+ const mapping = getConversationByKey("default:phone:phone");
945
984
  expect(mapping).not.toBeNull();
946
- expect(mapping!.conversationId).toBeTruthy();
985
+ expect(mapping!.conversationId).toBe(body1.conversationId);
947
986
 
948
987
  await stopServer();
949
988
  });
@@ -578,7 +578,10 @@ describe("getAttachmentsForMessage", () => {
578
578
  db.run("DELETE FROM conversations");
579
579
  });
580
580
 
581
- async function createMessage(role: string, content: string): Promise<string> {
581
+ async function createMessage(
582
+ role: "user" | "assistant" | "system",
583
+ content: string,
584
+ ): Promise<string> {
582
585
  const conv = createConversation("test");
583
586
  const msg = await addMessage(conv.id, role, content);
584
587
  return msg.id;
@@ -287,7 +287,7 @@ describe("shell tool proxy mode", () => {
287
287
  });
288
288
 
289
289
  test("schema includes network_mode and credential_ids", () => {
290
- const def = shellTool.getDefinition();
290
+ const def = shellTool;
291
291
  const props = (def.input_schema as { properties: Record<string, unknown> })
292
292
  .properties;
293
293
  expect(props.network_mode).toBeDefined();
@@ -7,17 +7,15 @@
7
7
  */
8
8
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
9
9
 
10
- import {
11
- _setOverridesForTesting,
12
- isAssistantFeatureFlagEnabled,
13
- } from "../config/assistant-feature-flags.js";
10
+ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
11
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
14
12
 
15
13
  beforeEach(() => {
16
- _setOverridesForTesting({});
14
+ setOverridesForTesting({});
17
15
  });
18
16
 
19
17
  afterEach(() => {
20
- _setOverridesForTesting({});
18
+ setOverridesForTesting({});
21
19
  });
22
20
  import type { AssistantConfig } from "../config/schema.js";
23
21
  import { resolveSkillStates, skillFlagKey } from "../config/skill-state.js";
@@ -150,7 +148,7 @@ describe("frontmatter feature-flag integration", () => {
150
148
  });
151
149
 
152
150
  test("resolveSkillStates includes skill with featureFlag when flag is ON", () => {
153
- _setOverridesForTesting({
151
+ setOverridesForTesting({
154
152
  "email-channel": true,
155
153
  });
156
154
  const skill = buildSkillSummary("email-setup", SKILL_MD_WITH_FLAG)!;
@@ -174,7 +172,7 @@ describe("frontmatter feature-flag integration", () => {
174
172
  test("resolveSkillStates never gates skill without featureFlag", () => {
175
173
  const skill = buildSkillSummary("plain-skill", SKILL_MD_WITHOUT_FLAG)!;
176
174
  // Even with an explicit false override for this skill ID, it should pass through
177
- _setOverridesForTesting({
175
+ setOverridesForTesting({
178
176
  "plain-skill": false,
179
177
  });
180
178
  const config = makeConfig();
@@ -210,7 +208,7 @@ describe("frontmatter feature-flag integration", () => {
210
208
  expect(resolvedDefault.length).toBe(0);
211
209
 
212
210
  // Step 6: With override enabled, skill passes through
213
- _setOverridesForTesting({ [key!]: true });
211
+ setOverridesForTesting({ [key!]: true });
214
212
  const configOn = makeConfig();
215
213
  expect(isAssistantFeatureFlagEnabled(key!, configOn)).toBe(true);
216
214
 
@@ -219,7 +217,7 @@ describe("frontmatter feature-flag integration", () => {
219
217
  expect(resolvedOn[0].summary.id).toBe("email-setup");
220
218
 
221
219
  // Step 7: With override disabled, skill is filtered out
222
- _setOverridesForTesting({ [key!]: false });
220
+ setOverridesForTesting({ [key!]: false });
223
221
  const configOff = makeConfig();
224
222
  expect(isAssistantFeatureFlagEnabled(key!, configOff)).toBe(false);
225
223
 
@@ -1,19 +1,17 @@
1
1
  import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
- import {
4
- _setOverridesForTesting,
5
- isAssistantFeatureFlagEnabled,
6
- } from "../config/assistant-feature-flags.js";
3
+ import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
7
4
  import type { AssistantConfig } from "../config/schema.js";
8
5
  import { resolveSkillStates, skillFlagKey } from "../config/skill-state.js";
9
6
  import type { SkillSummary } from "../config/skills.js";
7
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
10
8
 
11
9
  beforeEach(() => {
12
- _setOverridesForTesting({});
10
+ setOverridesForTesting({});
13
11
  });
14
12
 
15
13
  afterEach(() => {
16
- _setOverridesForTesting({});
14
+ setOverridesForTesting({});
17
15
  });
18
16
 
19
17
  const DECLARED_FLAG_ID = "email-channel";
@@ -103,7 +101,7 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
103
101
  });
104
102
 
105
103
  test("returns true when skill key is explicitly true", () => {
106
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
104
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
107
105
  const config = makeConfig();
108
106
  expect(
109
107
  isAssistantFeatureFlagEnabled(
@@ -114,7 +112,7 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
114
112
  });
115
113
 
116
114
  test("returns false when skill key is explicitly false", () => {
117
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
115
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
118
116
  const config = makeConfig();
119
117
  expect(
120
118
  isAssistantFeatureFlagEnabled(
@@ -130,13 +128,13 @@ describe("isAssistantFeatureFlagEnabled with skillFlagKey", () => {
130
128
  // ---------------------------------------------------------------------------
131
129
 
132
130
  describe("isAssistantFeatureFlagEnabled", () => {
133
- test("returns true for unknown flags (open by default)", () => {
131
+ test("returns false for unknown flags (closed by default)", () => {
134
132
  const config = makeConfig();
135
- expect(isAssistantFeatureFlagEnabled("unknown", config)).toBe(true);
133
+ expect(isAssistantFeatureFlagEnabled("unknown", config)).toBe(false);
136
134
  });
137
135
 
138
136
  test("file-based override overrides registry default", () => {
139
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
137
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
140
138
  const config = makeConfig();
141
139
  expect(isAssistantFeatureFlagEnabled(DECLARED_FLAG_KEY, config)).toBe(
142
140
  false,
@@ -152,7 +150,7 @@ describe("isAssistantFeatureFlagEnabled", () => {
152
150
  });
153
151
 
154
152
  test("respects persisted overrides for undeclared keys", () => {
155
- _setOverridesForTesting({ "some-undeclared-flag": false });
153
+ setOverridesForTesting({ "some-undeclared-flag": false });
156
154
  const config = makeConfig();
157
155
  expect(isAssistantFeatureFlagEnabled("some-undeclared-flag", config)).toBe(
158
156
  false,
@@ -166,7 +164,7 @@ describe("isAssistantFeatureFlagEnabled", () => {
166
164
 
167
165
  describe("resolveSkillStates with feature flags", () => {
168
166
  test("flag OFF skill does not appear in resolved list", () => {
169
- _setOverridesForTesting({
167
+ setOverridesForTesting({
170
168
  [DECLARED_FLAG_KEY]: false,
171
169
  [ENABLED_UNDECLARED_FLAG_KEY]: true,
172
170
  });
@@ -188,7 +186,7 @@ describe("resolveSkillStates with feature flags", () => {
188
186
  });
189
187
 
190
188
  test("flag ON skill appears normally", () => {
191
- _setOverridesForTesting({
189
+ setOverridesForTesting({
192
190
  [DECLARED_FLAG_KEY]: true,
193
191
  [ENABLED_UNDECLARED_FLAG_KEY]: true,
194
192
  });
@@ -230,7 +228,7 @@ describe("resolveSkillStates with feature flags", () => {
230
228
  });
231
229
 
232
230
  test("feature flag OFF takes precedence over user-enabled config entry", () => {
233
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
231
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
234
232
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
235
233
  const config = makeConfig({
236
234
  skills: {
@@ -256,7 +254,7 @@ describe("resolveSkillStates with feature flags", () => {
256
254
  });
257
255
 
258
256
  test("multiple skills with mixed flags — persisted overrides respected", () => {
259
- _setOverridesForTesting({
257
+ setOverridesForTesting({
260
258
  [DECLARED_FLAG_KEY]: false,
261
259
  [ENABLED_UNDECLARED_FLAG_KEY]: true,
262
260
  deploy: false,
@@ -296,7 +294,7 @@ describe("resolveSkillStates with frontmatter featureFlag", () => {
296
294
  });
297
295
 
298
296
  test("skill with featureFlag is included when override enables it", () => {
299
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
297
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
300
298
  const catalog = [makeSkill(DECLARED_SKILL_ID, "bundled", DECLARED_FLAG_ID)];
301
299
  const config = makeConfig();
302
300
 
@@ -320,7 +318,7 @@ describe("resolveSkillStates with frontmatter featureFlag", () => {
320
318
  // This proves the implicit skillId→flag mapping is gone:
321
319
  // setting feature_flags.my-skill.enabled = false has no effect
322
320
  // when the skill itself does not declare a featureFlag.
323
- _setOverridesForTesting({
321
+ setOverridesForTesting({
324
322
  "my-skill": false,
325
323
  });
326
324
  const catalog = [makeSkill("my-skill")];
@@ -6,7 +6,7 @@ import { mkdirSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
8
8
 
9
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
9
+ import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
10
10
 
11
11
  const TEST_DIR = process.env.VELLUM_WORKSPACE_DIR!;
12
12
 
@@ -89,11 +89,11 @@ describe("skill_load feature flag enforcement", () => {
89
89
  beforeEach(() => {
90
90
  mkdirSync(join(TEST_DIR, "skills"), { recursive: true });
91
91
  currentConfig = {};
92
- _setOverridesForTesting({});
92
+ setOverridesForTesting({});
93
93
  });
94
94
 
95
95
  afterEach(() => {
96
- _setOverridesForTesting({});
96
+ setOverridesForTesting({});
97
97
  });
98
98
 
99
99
  test("returns deterministic error for flag OFF skill", async () => {
@@ -104,7 +104,7 @@ describe("skill_load feature flag enforcement", () => {
104
104
  "Use the feature.",
105
105
  );
106
106
 
107
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
107
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
108
108
 
109
109
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
110
110
 
@@ -121,7 +121,7 @@ describe("skill_load feature flag enforcement", () => {
121
121
  "Use the feature.",
122
122
  );
123
123
 
124
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
124
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
125
125
 
126
126
  const result = await executeSkillLoad({ skill: DECLARED_SKILL_ID });
127
127
 
@@ -45,20 +45,26 @@ mock.module("../config/skill-state.js", () => ({
45
45
 
46
46
  // Mock assistant-feature-flags to avoid loading the real module (which
47
47
  // triggers file I/O and env-registry imports that hang in test context).
48
+ // The seed-state backdoor is the test-only helper module — we mirror
49
+ // production's design: tests reach into `feature-flag-cache.ts` (or its
50
+ // test-helper wrapper) to seed cached overrides, never through the
51
+ // resolver module itself.
48
52
  let _mockOverrides: Record<string, boolean> = {};
49
53
  mock.module("../config/assistant-feature-flags.js", () => ({
50
54
  isAssistantFeatureFlagEnabled: (key: string, _config: unknown): boolean => {
51
55
  const explicit = _mockOverrides[key];
52
56
  if (typeof explicit === "boolean") return explicit;
53
- return true; // undeclared flags default to enabled
57
+ return false; // undeclared flags default to disabled
54
58
  },
55
59
  clearFeatureFlagOverridesCache: () => {
56
60
  _mockOverrides = {};
57
61
  },
58
- _setOverridesForTesting: (overrides: Record<string, boolean>) => {
62
+ getAssistantFeatureFlagDefaults: () => ({}),
63
+ }));
64
+ mock.module("./feature-flag-test-helpers.js", () => ({
65
+ setOverridesForTesting: (overrides: Record<string, boolean>) => {
59
66
  _mockOverrides = { ...overrides };
60
67
  },
61
- getAssistantFeatureFlagDefaults: () => ({}),
62
68
  }));
63
69
 
64
70
  mock.module("../skills/active-skill-tools.js", () => {
@@ -109,45 +115,35 @@ mock.module("../skills/tool-manifest.js", () => ({
109
115
  }));
110
116
 
111
117
  mock.module("../tools/skills/skill-tool-factory.js", () => ({
118
+ // Mirrors the real factory: no skillId in/out — ownership is recorded by
119
+ // the registry at `registerSkillTools(skillId, tools)` time.
112
120
  createSkillToolsFromManifest: (
113
121
  entries: SkillToolManifest["tools"],
114
- skillId: string,
115
122
  _skillDir: string,
116
- versionHash: string,
117
- bundled?: boolean,
123
+ _versionHash: string,
124
+ _bundled?: boolean,
118
125
  ): Tool[] => {
119
126
  return entries.map((entry) => ({
120
127
  name: entry.name,
121
128
  description: entry.description,
122
129
  category: entry.category,
123
130
  defaultRiskLevel: RiskLevel.Medium,
124
- origin: "skill" as const,
125
- ownerSkillId: skillId,
126
- ownerSkillVersionHash: versionHash,
127
- ownerSkillBundled: bundled ?? undefined,
128
- getDefinition: () => ({
129
- name: entry.name,
130
- description: entry.description,
131
- input_schema: entry.input_schema as object,
132
- }),
131
+ executionTarget: "sandbox" as const,
132
+ input_schema: entry.input_schema as object,
133
133
  execute: async () => ({ content: "", isError: false }),
134
134
  }));
135
135
  },
136
136
  }));
137
137
 
138
138
  mock.module("../tools/registry.js", () => ({
139
- registerSkillTools: (tools: Tool[]) => {
140
- const skillIds = new Set<string>();
141
- for (const tool of tools) {
142
- const skillId = tool.ownerSkillId!;
143
- skillIds.add(skillId);
144
- const existing = mockRegisteredTools.get(skillId) ?? [];
145
- existing.push(tool);
146
- mockRegisteredTools.set(skillId, existing);
147
- }
148
- for (const id of skillIds) {
149
- mockSkillRefCount.set(id, (mockSkillRefCount.get(id) ?? 0) + 1);
150
- }
139
+ // Matches the new signature: `registerSkillTools(skillId, tools)`. The
140
+ // skillId comes from the caller (conversation-skill-tools) and is the
141
+ // sole source of truth for ownership.
142
+ registerSkillTools: (skillId: string, tools: Tool[]) => {
143
+ const existing = mockRegisteredTools.get(skillId) ?? [];
144
+ existing.push(...tools);
145
+ mockRegisteredTools.set(skillId, existing);
146
+ mockSkillRefCount.set(skillId, (mockSkillRefCount.get(skillId) ?? 0) + 1);
151
147
  return tools;
152
148
  },
153
149
  unregisterSkillTools: (skillId: string) => {
@@ -169,6 +165,23 @@ mock.module("../tools/registry.js", () => ({
169
165
  }
170
166
  return found;
171
167
  },
168
+ // Mirrors the registry's `ownersByName` accessor: derives the owning
169
+ // skillId from `mockRegisteredTools` keying so the production
170
+ // `getToolOwner(name)` call in `conversation-skill-tools.ts` resolves to
171
+ // the same shape the real registry would return.
172
+ getToolOwner: (
173
+ name: string,
174
+ ): { kind: "skill" | "plugin" | "mcp"; id: string } | undefined => {
175
+ let ownerSkillId: string | undefined;
176
+ for (const [skillId, tools] of mockRegisteredTools.entries()) {
177
+ for (const tool of tools) {
178
+ if (tool.name === name) ownerSkillId = skillId;
179
+ }
180
+ }
181
+ return ownerSkillId === undefined
182
+ ? undefined
183
+ : { kind: "skill", id: ownerSkillId };
184
+ },
172
185
  getSkillToolNames: () => {
173
186
  const names: string[] = [];
174
187
  for (const tools of mockRegisteredTools.values()) {
@@ -215,10 +228,8 @@ mock.module("../util/logger.js", () => ({
215
228
 
216
229
  const { projectSkillTools, resetSkillToolProjection } =
217
230
  await import("../daemon/conversation-skill-tools.js");
218
- const { _setOverridesForTesting } =
219
- (await import("../config/assistant-feature-flags.js")) as {
220
- _setOverridesForTesting: (o: Record<string, boolean>) => void;
221
- };
231
+ const { setOverridesForTesting } =
232
+ await import("./feature-flag-test-helpers.js");
222
233
 
223
234
  // ---------------------------------------------------------------------------
224
235
  // Helpers
@@ -292,12 +303,12 @@ describe("projectSkillTools feature flag enforcement", () => {
292
303
  mockUnregisteredSkillIds = [];
293
304
  mockSkillRefCount = new Map();
294
305
  currentConfig = {};
295
- _setOverridesForTesting({});
306
+ setOverridesForTesting({});
296
307
  resetSkillToolProjection();
297
308
  });
298
309
 
299
310
  afterEach(() => {
300
- _setOverridesForTesting({});
311
+ setOverridesForTesting({});
301
312
  });
302
313
 
303
314
  test("no skill tools projected for flag OFF skill even with old markers", () => {
@@ -311,7 +322,7 @@ describe("projectSkillTools feature flag enforcement", () => {
311
322
  const prevActive = new Map<string, string>();
312
323
 
313
324
  // Feature flag is OFF — use protected directory override
314
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
325
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
315
326
 
316
327
  const result = projectSkillTools(history, {
317
328
  previouslyActiveSkillIds: prevActive,
@@ -332,7 +343,7 @@ describe("projectSkillTools feature flag enforcement", () => {
332
343
  const prevActive = new Map<string, string>();
333
344
 
334
345
  // Feature flag is ON — use protected directory override
335
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
346
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: true });
336
347
 
337
348
  const result = projectSkillTools(history, {
338
349
  previouslyActiveSkillIds: prevActive,
@@ -422,8 +433,8 @@ describe("projectSkillTools feature flag enforcement", () => {
422
433
  ];
423
434
  const prevActive = new Map<string, string>();
424
435
 
425
- // Declared skill is OFF, plain-skill is undeclared with no persisted override so remains ON.
426
- _setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
436
+ // Declared skill is OFF; plain-skill has no featureFlag so remains ON.
437
+ setOverridesForTesting({ [DECLARED_FLAG_KEY]: false });
427
438
 
428
439
  const result = projectSkillTools(history, {
429
440
  previouslyActiveSkillIds: prevActive,