@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
@@ -69,51 +69,37 @@ mock.module("../prompts/user-reference.js", () => ({
69
69
  resolveUserPronouns: () => null,
70
70
  }));
71
71
 
72
+ // Stub persona-resolver so tests can dictate the slug `buildSystemPrompt`
73
+ // sees without needing to write contact rows to the test DB. The user
74
+ // and channel persona files themselves now flow through bundled sections
75
+ // (`10-user-persona` / `11-channel-persona`) that read from disk, so
76
+ // persona *content* is exercised by writing the file under TEST_DIR
77
+ // rather than mocking it here. Tests mutate `mockPersona` in place;
78
+ // the default (all-null) matches a fresh workspace with no contacts
79
+ // and no `users/default.md`.
80
+ const mockPersona: {
81
+ userSlug: string | null;
82
+ guardianPersona: string | null;
83
+ } = { userSlug: null, guardianPersona: null };
84
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
85
+ const realPersonaResolver = require("../prompts/persona-resolver.js");
86
+ mock.module("../prompts/persona-resolver.js", () => ({
87
+ ...realPersonaResolver,
88
+ resolveUserSlug: () => mockPersona.userSlug,
89
+ resolveGuardianPersona: () => mockPersona.guardianPersona,
90
+ }));
91
+
72
92
  // Import after mock
73
- const {
74
- buildSystemPrompt,
75
- ensurePromptFiles,
76
- stripCommentLines,
77
- SYSTEM_PROMPT_CACHE_BOUNDARY,
78
- } = await import("../prompts/system-prompt.js");
79
-
80
- /**
81
- * Extract BOOTSTRAP.md content + the user persona from the dynamic block
82
- * of the system prompt, stripping configuration, skills catalog, and
83
- * connected services.
84
- *
85
- * Neither SOUL.md nor IDENTITY.md flows through this helper — they
86
- * render as the `09-soul` and `08-identity` workspace-backed sections in
87
- * the static (cached) prefix. Tests that assert on their content slice
88
- * the static block directly.
89
- */
90
- function basePrompt(result: string): string {
91
- // The workspace files are in the dynamic block after the cache boundary.
92
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
93
- let s =
94
- boundaryIdx >= 0
95
- ? result.slice(boundaryIdx + SYSTEM_PROMPT_CACHE_BOUNDARY.length)
96
- : result;
97
- for (const heading of [
98
- "## Configuration",
99
- "## Skills Catalog",
100
- "## External Communications Identity",
101
- "# Connected Services",
102
- "## Dynamic Skill Authoring Workflow",
103
- ]) {
104
- if (s.startsWith(heading)) {
105
- s = "";
106
- break;
107
- }
108
- const idx = s.indexOf(`\n\n${heading}`);
109
- if (idx !== -1) s = s.slice(0, idx);
110
- }
111
- return s;
112
- }
93
+ const { buildSystemPrompt, ensurePromptFiles, stripCommentLines } =
94
+ await import("../prompts/system-prompt.js");
113
95
 
114
96
  describe("buildSystemPrompt", () => {
115
97
  beforeEach(() => {
116
98
  mkdirSync(TEST_DIR, { recursive: true });
99
+ // Reset persona stub so each test starts from a fresh
100
+ // no-guardian baseline.
101
+ mockPersona.userSlug = null;
102
+ mockPersona.guardianPersona = null;
117
103
  });
118
104
 
119
105
  afterEach(() => {
@@ -123,8 +109,10 @@ describe("buildSystemPrompt", () => {
123
109
  "USER.md",
124
110
  "BOOTSTRAP.md",
125
111
  "UPDATES.md",
112
+ "VOICE.md",
126
113
  "skills",
127
114
  "users",
115
+ "channels",
128
116
  ]) {
129
117
  const p = join(TEST_DIR, name);
130
118
  if (existsSync(p)) rmSync(p, { recursive: true, force: true });
@@ -134,19 +122,11 @@ describe("buildSystemPrompt", () => {
134
122
  }
135
123
  });
136
124
 
137
- test("returns empty string when no files exist", () => {
138
- const result = buildSystemPrompt();
139
- expect(basePrompt(result)).toBe("");
140
- });
141
-
142
125
  test("uses SOUL.md when it exists", () => {
143
126
  writeFileSync(join(TEST_DIR, "SOUL.md"), "# My Soul\n\nBe awesome.");
144
127
  const result = buildSystemPrompt();
145
- // SOUL.md renders as the `09-soul` workspace-backed section in the
146
- // static (cached) prefix before SYSTEM_PROMPT_CACHE_BOUNDARY.
147
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
148
- expect(boundaryIdx).toBeGreaterThan(-1);
149
- expect(result.slice(0, boundaryIdx)).toContain("# My Soul\n\nBe awesome.");
128
+ // SOUL.md renders as the `09-soul` workspace-backed section.
129
+ expect(result).toContain("# My Soul\n\nBe awesome.");
150
130
  });
151
131
 
152
132
  test("uses IDENTITY.md when it exists", () => {
@@ -155,42 +135,78 @@ describe("buildSystemPrompt", () => {
155
135
  "# My Identity\n\nI am Vellum.",
156
136
  );
157
137
  const result = buildSystemPrompt();
158
- // IDENTITY.md renders as the `08-identity` workspace-backed section
159
- // in the static (cached) prefix before SYSTEM_PROMPT_CACHE_BOUNDARY.
160
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
161
- expect(boundaryIdx).toBeGreaterThan(-1);
162
- expect(result.slice(0, boundaryIdx)).toContain(
163
- "# My Identity\n\nI am Vellum.",
164
- );
138
+ // IDENTITY.md renders as the `08-identity` workspace-backed section.
139
+ expect(result).toContain("# My Identity\n\nI am Vellum.");
165
140
  });
166
141
 
167
142
  test("composes IDENTITY.md + SOUL.md when both exist", () => {
168
143
  writeFileSync(join(TEST_DIR, "IDENTITY.md"), "# Identity\n\nI am Vellum.");
169
144
  writeFileSync(join(TEST_DIR, "SOUL.md"), "# Soul\n\nBe thoughtful.");
170
145
  const result = buildSystemPrompt();
171
- // Both render in the static (cached) prefix, IDENTITY before SOUL
172
- // (sections `08-identity` and `09-soul`).
173
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
174
- expect(boundaryIdx).toBeGreaterThan(-1);
175
- const staticBlock = result.slice(0, boundaryIdx);
176
- expect(staticBlock).toContain("# Identity\n\nI am Vellum.");
177
- expect(staticBlock).toContain("# Soul\n\nBe thoughtful.");
178
- const identityIdx = staticBlock.indexOf("# Identity\n\nI am Vellum.");
179
- const soulIdx = staticBlock.indexOf("# Soul\n\nBe thoughtful.");
146
+ // IDENTITY renders before SOUL (sections `08-identity` then
147
+ // `09-soul`).
148
+ expect(result).toContain("# Identity\n\nI am Vellum.");
149
+ expect(result).toContain("# Soul\n\nBe thoughtful.");
150
+ const identityIdx = result.indexOf("# Identity\n\nI am Vellum.");
151
+ const soulIdx = result.indexOf("# Soul\n\nBe thoughtful.");
180
152
  expect(identityIdx).toBeLessThan(soulIdx);
181
- expect(basePrompt(result)).toBe("");
182
153
  });
183
154
 
184
155
  test("ignores empty SOUL.md", () => {
185
156
  writeFileSync(join(TEST_DIR, "SOUL.md"), " \n \n ");
157
+ writeFileSync(join(TEST_DIR, "IDENTITY.md"), "# Identity\n\nI am Vellum.");
186
158
  const result = buildSystemPrompt();
187
- expect(basePrompt(result)).toBe("");
159
+ // IDENTITY renders but SOUL is gated off by the renderer's
160
+ // empty-body check; no SOUL content should appear.
161
+ expect(result).toContain("# Identity\n\nI am Vellum.");
162
+ expect(result).not.toContain(" \n \n ");
188
163
  });
189
164
 
190
165
  test("ignores empty IDENTITY.md", () => {
191
166
  writeFileSync(join(TEST_DIR, "IDENTITY.md"), "");
167
+ writeFileSync(join(TEST_DIR, "SOUL.md"), "# Soul\n\nBe thoughtful.");
192
168
  const result = buildSystemPrompt();
193
- expect(basePrompt(result)).toBe("");
169
+ // SOUL renders but IDENTITY's empty file is gated off by the
170
+ // renderer's empty-body check.
171
+ expect(result).toContain("# Soul\n\nBe thoughtful.");
172
+ });
173
+
174
+ test("gates off the unmodified bundled IDENTITY.md template when no BOOTSTRAP.md is present", () => {
175
+ // Regression: the seeded IDENTITY.md ships with `_`-comment lines, so
176
+ // the raw workspace body never equals the comment-stripped bundled
177
+ // template. `isTemplateContent` must comment-strip BOTH sides — otherwise
178
+ // detection fails and the `08-identity` transform leaks the blank
179
+ // template scaffolding into every fresh post-onboarding prompt.
180
+ const bundledIdentity = readFileSync(
181
+ join(import.meta.dirname, "..", "prompts", "templates", "IDENTITY.md"),
182
+ "utf-8",
183
+ );
184
+ writeFileSync(join(TEST_DIR, "IDENTITY.md"), bundledIdentity);
185
+ writeFileSync(join(TEST_DIR, "SOUL.md"), "# Soul\n\nBe thoughtful.");
186
+ const result = buildSystemPrompt();
187
+ // SOUL still renders; the template scaffolding must not.
188
+ expect(result).toContain("# Soul\n\nBe thoughtful.");
189
+ expect(result).not.toContain("(not yet chosen)");
190
+ });
191
+
192
+ test("includes the unmodified bundled IDENTITY.md template during bootstrap", () => {
193
+ // The mirror case: when BOOTSTRAP.md is active the template is included
194
+ // verbatim so the model can see the field structure and produce a valid
195
+ // file_write on the first turn.
196
+ const bundledIdentity = readFileSync(
197
+ join(import.meta.dirname, "..", "prompts", "templates", "IDENTITY.md"),
198
+ "utf-8",
199
+ );
200
+ writeFileSync(join(TEST_DIR, "IDENTITY.md"), bundledIdentity);
201
+ writeFileSync(
202
+ join(TEST_DIR, "BOOTSTRAP.md"),
203
+ "# First run\n\nGet started.",
204
+ );
205
+ const result = buildSystemPrompt();
206
+ // The bundled template's placeholder scaffolding (the `(not yet chosen)`
207
+ // field markers) renders verbatim during bootstrap — the mirror of the
208
+ // gating test above, which asserts it is absent without BOOTSTRAP.md.
209
+ expect(result).toContain("(not yet chosen)");
194
210
  });
195
211
 
196
212
  test("trims whitespace from file content", () => {
@@ -198,10 +214,8 @@ describe("buildSystemPrompt", () => {
198
214
  const result = buildSystemPrompt();
199
215
  // SOUL.md renders via the `09-soul` workspace-backed section;
200
216
  // stripCommentLines + trim run inside the section renderer.
201
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
202
- const staticBlock = result.slice(0, boundaryIdx);
203
- expect(staticBlock).toContain("Be kind");
204
- expect(staticBlock).not.toContain("\n Be kind \n");
217
+ expect(result).toContain("Be kind");
218
+ expect(result).not.toContain("\n Be kind \n");
205
219
  });
206
220
 
207
221
  test("does not include skills catalog in system prompt", () => {
@@ -274,9 +288,6 @@ describe("buildSystemPrompt", () => {
274
288
  writeFileSync(join(TEST_DIR, "IDENTITY.md"), "Identity");
275
289
  writeFileSync(join(TEST_DIR, "SOUL.md"), "Soul");
276
290
  const result = buildSystemPrompt();
277
- // Both IDENTITY and SOUL render in the static (cached) prefix; the
278
- // dynamic block sliced by basePrompt is empty here.
279
- expect(basePrompt(result)).toBe("");
280
291
  expect(result).toContain("Identity");
281
292
  expect(result).toContain("Soul");
282
293
  });
@@ -292,54 +303,117 @@ describe("buildSystemPrompt", () => {
292
303
  const result = buildSystemPrompt();
293
304
  expect(result).not.toContain("stale user content");
294
305
  expect(result).toContain("Identity");
295
- expect(basePrompt(result)).toBe("");
296
306
  });
297
307
 
298
- test("uses options.userPersona instead of USER.md", () => {
308
+ test("includes resolved user persona in the static prefix", () => {
309
+ // User persona flows through the `10-user-persona` bundled section,
310
+ // which reads from `users/<userSlug>.md` (or `users/default.md` as
311
+ // a fallback). Set the slug + write the file to exercise both.
312
+ mockPersona.userSlug = "alice";
313
+ mkdirSync(join(TEST_DIR, "users"), { recursive: true });
314
+ writeFileSync(
315
+ join(TEST_DIR, "users", "alice.md"),
316
+ "# User persona\n\nName: Alice",
317
+ );
299
318
  writeFileSync(join(TEST_DIR, "IDENTITY.md"), "Identity");
300
319
  writeFileSync(join(TEST_DIR, "SOUL.md"), "Soul");
301
- const result = buildSystemPrompt({
302
- userPersona: "# User persona\n\nName: Alice",
303
- });
304
- // IDENTITY and SOUL both render in the static (cached) prefix; only
305
- // the user persona ends up in the dynamic block.
306
- expect(basePrompt(result)).toBe("# User persona\n\nName: Alice");
320
+ const result = buildSystemPrompt();
321
+ // IDENTITY, SOUL, and the user persona all render as workspace-backed
322
+ // bundled sections in the assembled prompt.
307
323
  expect(result).toContain("Identity");
308
324
  expect(result).toContain("Soul");
325
+ expect(result).toContain("# User persona");
326
+ expect(result).toContain("Name: Alice");
327
+ });
328
+
329
+ test("user persona falls back to users/default.md when the slug's file is missing", () => {
330
+ // The `10-user-persona` section's workspacePath is
331
+ // `["users/{{userSlug}}.md", "users/default.md"]` — when the
332
+ // primary file doesn't exist the renderer falls through to default.
333
+ mockPersona.userSlug = "alice";
334
+ mkdirSync(join(TEST_DIR, "users"), { recursive: true });
335
+ writeFileSync(
336
+ join(TEST_DIR, "users", "default.md"),
337
+ "# Default persona\n\nNo contact bound.",
338
+ );
339
+ const result = buildSystemPrompt();
340
+ expect(result).toContain("# Default persona");
341
+ expect(result).toContain("No contact bound.");
342
+ });
343
+
344
+ test("includes channel persona from channels/<channelSlug>.md", () => {
345
+ // Channel persona flows through the `11-channel-persona` section.
346
+ // Default channel is "vellum" when no channelCapabilities passed.
347
+ mkdirSync(join(TEST_DIR, "channels"), { recursive: true });
348
+ writeFileSync(
349
+ join(TEST_DIR, "channels", "vellum.md"),
350
+ "# Channel persona\n\nThis is the Vellum channel.",
351
+ );
352
+ const result = buildSystemPrompt();
353
+ expect(result).toContain("# Channel persona");
354
+ expect(result).toContain("This is the Vellum channel.");
355
+ });
356
+
357
+ test("includes VOICE.md as the 12-voice section with prepended heading", () => {
358
+ // VOICE.md flows through the `12-voice` bundled section. The
359
+ // section transform prepends `# Voice Profile` so the file itself
360
+ // stays heading-free; the model writes voice markers as plain
361
+ // bullets / lines.
362
+ writeFileSync(
363
+ join(TEST_DIR, "VOICE.md"),
364
+ "- Prefers lowercase. Replies tightly. Skips greetings.",
365
+ );
366
+ const result = buildSystemPrompt();
367
+ expect(result).toContain("# Voice Profile");
368
+ expect(result).toContain("Prefers lowercase");
369
+ });
370
+
371
+ test("omits the 12-voice section when VOICE.md is missing", () => {
372
+ const result = buildSystemPrompt();
373
+ expect(result).not.toContain("# Voice Profile");
374
+ });
375
+
376
+ test("omits the 12-voice section when VOICE.md is empty / whitespace-only", () => {
377
+ writeFileSync(join(TEST_DIR, "VOICE.md"), " \n\n \n");
378
+ const result = buildSystemPrompt();
379
+ expect(result).not.toContain("# Voice Profile");
309
380
  });
310
381
 
311
382
  describe("BOOTSTRAP.md user persona placeholder", () => {
312
- test("substitutes {{USER_PERSONA_FILE}} with users/<slug>.md when userSlug is provided", () => {
383
+ test("substitutes {{userSlug}} with the resolved slug when a guardian slug is resolvable", () => {
384
+ // Simulate a guardian contact whose userFile resolves to alice.md.
385
+ mockPersona.userSlug = "alice";
313
386
  writeFileSync(
314
387
  join(TEST_DIR, "BOOTSTRAP.md"),
315
- "# First run\n\nSave facts to users/{{USER_PERSONA_FILE}} immediately.",
388
+ "# First run\n\nSave facts to users/{{userSlug}}.md immediately.",
316
389
  );
317
- const result = buildSystemPrompt({ userSlug: "alice" });
390
+ const result = buildSystemPrompt();
318
391
  expect(result).toContain("users/alice.md");
319
- expect(result).not.toContain("{{USER_PERSONA_FILE}}");
392
+ expect(result).not.toContain("{{userSlug}}");
320
393
  });
321
394
 
322
- test("falls back to users/default.md when userSlug is omitted", () => {
395
+ test("falls back to users/default.md when no slug is resolvable", () => {
323
396
  writeFileSync(
324
397
  join(TEST_DIR, "BOOTSTRAP.md"),
325
- "# First run\n\nSave facts to users/{{USER_PERSONA_FILE}} immediately.",
398
+ "# First run\n\nSave facts to users/{{userSlug}}.md immediately.",
326
399
  );
327
400
  const result = buildSystemPrompt();
328
401
  expect(result).toContain("users/default.md");
329
- expect(result).not.toContain("{{USER_PERSONA_FILE}}");
402
+ expect(result).not.toContain("{{userSlug}}");
330
403
  });
331
404
 
332
405
  test("substitutes the unmodified bundled BOOTSTRAP.md template", () => {
333
406
  // Copy the real bundled BOOTSTRAP.md into the test workspace so we
334
407
  // verify substitution against the actual template the daemon ships.
408
+ mockPersona.userSlug = "alice";
335
409
  const bundled = readFileSync(
336
410
  join(import.meta.dirname, "..", "prompts", "templates", "BOOTSTRAP.md"),
337
411
  "utf-8",
338
412
  );
339
413
  writeFileSync(join(TEST_DIR, "BOOTSTRAP.md"), bundled);
340
- const result = buildSystemPrompt({ userSlug: "alice" });
414
+ const result = buildSystemPrompt();
341
415
  expect(result).toContain("users/alice.md");
342
- expect(result).not.toContain("{{USER_PERSONA_FILE}}");
416
+ expect(result).not.toContain("{{userSlug}}");
343
417
  });
344
418
  });
345
419
 
@@ -513,8 +587,14 @@ describe("buildSystemPrompt", () => {
513
587
 
514
588
  test("file with only comment lines is treated as empty", () => {
515
589
  writeFileSync(join(TEST_DIR, "SOUL.md"), "_ All comments\n_ Nothing else");
590
+ writeFileSync(join(TEST_DIR, "IDENTITY.md"), "# Identity\n\nI am Vellum.");
516
591
  const result = buildSystemPrompt();
517
- expect(basePrompt(result)).toBe("");
592
+ // Comment-only SOUL.md gets stripped down to "" by
593
+ // `stripCommentLines` and is then gated off by the renderer's
594
+ // empty-body check; only IDENTITY contributes content here.
595
+ expect(result).toContain("# Identity\n\nI am Vellum.");
596
+ expect(result).not.toContain("_ All comments");
597
+ expect(result).not.toContain("_ Nothing else");
518
598
  });
519
599
 
520
600
  describe("workspace system prompt sections", () => {
@@ -547,11 +627,7 @@ describe("buildSystemPrompt", () => {
547
627
  );
548
628
  const result = buildSystemPrompt();
549
629
  expect(result.startsWith("You are operating in demo mode.")).toBe(true);
550
- // Prefix lives in the static (cached) block.
551
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
552
- expect(boundaryIdx).toBeGreaterThan(-1);
553
- const staticBlock = result.slice(0, boundaryIdx);
554
- expect(staticBlock).toContain("You are operating in demo mode.");
630
+ expect(result).toContain("You are operating in demo mode.");
555
631
  });
556
632
 
557
633
  test("workspace file without frontmatter is rendered as-is (always-on)", () => {
@@ -627,13 +703,10 @@ describe("buildSystemPrompt", () => {
627
703
  expect(result.startsWith("Custom prefix")).toBe(true);
628
704
  // IDENTITY.md renders via 08-identity in the static prefix after
629
705
  // the 00-prefix slot.
630
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
631
- const staticBlock = result.slice(0, boundaryIdx);
632
- const prefixIdx = staticBlock.indexOf("Custom prefix");
633
- const identityIdx = staticBlock.indexOf("I am Vellum.");
706
+ const prefixIdx = result.indexOf("Custom prefix");
707
+ const identityIdx = result.indexOf("I am Vellum.");
634
708
  expect(prefixIdx).toBeGreaterThan(-1);
635
709
  expect(identityIdx).toBeGreaterThan(prefixIdx);
636
- expect(basePrompt(result)).toBe("");
637
710
  });
638
711
 
639
712
  test("parallel tool calls section is sourced from workspace when present", () => {
@@ -809,11 +882,7 @@ describe("buildSystemPrompt", () => {
809
882
  expect(result).toContain(
810
883
  "Run `assistant --help` to discover commands.",
811
884
  );
812
- // Section lives in the static (cached) block.
813
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
814
- expect(boundaryIdx).toBeGreaterThan(-1);
815
- const staticBlock = result.slice(0, boundaryIdx);
816
- expect(staticBlock).toContain("## Assistant CLI");
885
+ expect(result).toContain("## Assistant CLI");
817
886
  });
818
887
 
819
888
  test("bundled cli-reference default renders when no workspace override", () => {
@@ -854,11 +923,7 @@ describe("buildSystemPrompt", () => {
854
923
  // The no-client body (em-dash separator after sandbox `bash`) must
855
924
  // not leak when the with-client variant is active.
856
925
  expect(result).not.toContain("install tools yourself; (2) browser");
857
- // Section lives in the static (cached) block.
858
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
859
- expect(boundaryIdx).toBeGreaterThan(-1);
860
- const staticBlock = result.slice(0, boundaryIdx);
861
- expect(staticBlock).toContain("## External Service Access");
926
+ expect(result).toContain("## External Service Access");
862
927
  });
863
928
 
864
929
  test("hasNoClient=true renders the two-tier (no host_bash) priority list", () => {
@@ -967,8 +1032,7 @@ describe("buildSystemPrompt", () => {
967
1032
 
968
1033
  test("paired {{#flag}} + {{^flag}} acts as if/else", () => {
969
1034
  // Use long unique markers — single letters collide with substrings
970
- // in the rest of the system prompt (e.g. "B" lives inside
971
- // SYSTEM_PROMPT_CACHE_BOUNDARY, "A" inside "API keys").
1035
+ // in the rest of the system prompt (e.g. "A" inside "API keys").
972
1036
  mkdirSync(SYSTEM_PROMPTS_DIR, { recursive: true });
973
1037
  writeFileSync(
974
1038
  SECTION_FILE,
@@ -1033,11 +1097,7 @@ describe("buildSystemPrompt", () => {
1033
1097
  const result = buildSystemPrompt();
1034
1098
  expect(result).toContain("## Sending Files to the User");
1035
1099
  expect(result).toContain("Use the `<vellum-attachment />` tag.");
1036
- // Section lives in the static (cached) block.
1037
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
1038
- expect(boundaryIdx).toBeGreaterThan(-1);
1039
- const staticBlock = result.slice(0, boundaryIdx);
1040
- expect(staticBlock).toContain("## Sending Files to the User");
1100
+ expect(result).toContain("## Sending Files to the User");
1041
1101
  });
1042
1102
 
1043
1103
  test("renders after the cli-reference section to preserve original order", () => {
@@ -1083,11 +1143,7 @@ describe("buildSystemPrompt", () => {
1083
1143
  const result = buildSystemPrompt();
1084
1144
  expect(result).toContain("## Credential Security");
1085
1145
  expect(result).toContain("Workspace override marker BRAVO_TANGO_7.");
1086
- // Section lives in the static (cached) block.
1087
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
1088
- expect(boundaryIdx).toBeGreaterThan(-1);
1089
- const staticBlock = result.slice(0, boundaryIdx);
1090
- expect(staticBlock).toContain("## Credential Security");
1146
+ expect(result).toContain("## Credential Security");
1091
1147
  });
1092
1148
 
1093
1149
  test("bundled credential-security default renders when no workspace override", () => {
@@ -1127,11 +1183,7 @@ describe("buildSystemPrompt", () => {
1127
1183
  const result = buildSystemPrompt();
1128
1184
  expect(result).toContain("## External Content");
1129
1185
  expect(result).toContain("Workspace override marker NEBULA_9X.");
1130
- // Section lives in the static (cached) block.
1131
- const boundaryIdx = result.indexOf(SYSTEM_PROMPT_CACHE_BOUNDARY);
1132
- expect(boundaryIdx).toBeGreaterThan(-1);
1133
- const staticBlock = result.slice(0, boundaryIdx);
1134
- expect(staticBlock).toContain("## External Content");
1186
+ expect(result).toContain("## External Content");
1135
1187
  });
1136
1188
 
1137
1189
  test("bundled external-content default renders when no workspace override", () => {
@@ -288,7 +288,7 @@ describe("Shell tool input validation", () => {
288
288
  });
289
289
 
290
290
  test("tool definition includes required schema fields", () => {
291
- const def = shellTool.getDefinition();
291
+ const def = shellTool;
292
292
  const schema = def.input_schema as {
293
293
  required: string[];
294
294
  properties: Record<string, unknown>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Test preload verifier — runs immediately after test-preload.ts.
3
+ *
4
+ * Bun already exits with code 1 when a preload throws, has an unresolvable
5
+ * import, or doesn't exist on disk (verified empirically). This file is
6
+ * the explicit check for the remaining failure mode: the main preload
7
+ * ran successfully but didn't actually isolate workspace state (e.g. a
8
+ * future refactor of test-preload.ts introduces a logic bug that no-ops
9
+ * the env override).
10
+ *
11
+ * Without this verifier, that failure mode would silently let tests
12
+ * resolve `VELLUM_WORKSPACE_DIR` to the real `/workspace` and potentially
13
+ * destroy live data.
14
+ *
15
+ * Order matters: bunfig.toml lists this AFTER test-preload.ts so the
16
+ * main preload's env writes are observable here.
17
+ *
18
+ * No source-module imports — only node stdlib (matches the same rule
19
+ * test-preload.ts enforces).
20
+ *
21
+ * Positive assertion: `VELLUM_WORKSPACE_DIR` MUST resolve under
22
+ * `os.tmpdir()`. This mirrors exactly what test-preload.ts does
23
+ * (`mkdtempSync(join(tmpdir(), "vellum-test-"))`), so any other value
24
+ * indicates the preload either didn't run or didn't take effect.
25
+ */
26
+
27
+ import { realpathSync } from "node:fs";
28
+ import { tmpdir } from "node:os";
29
+ import { sep } from "node:path";
30
+
31
+ function fail(reason: string): never {
32
+ throw new Error(
33
+ [
34
+ `Test preload verifier failed: ${reason}.`,
35
+ "",
36
+ "test-preload.ts ran but did not isolate workspace state. Common",
37
+ "causes:",
38
+ " - a logic bug in test-preload.ts (env override removed/reordered)",
39
+ " - a preload phase threw silently and the verifier still picked up",
40
+ " partial state",
41
+ ].join("\n"),
42
+ );
43
+ }
44
+
45
+ function canonicalize(p: string): string {
46
+ try {
47
+ return realpathSync(p);
48
+ } catch {
49
+ return p;
50
+ }
51
+ }
52
+
53
+ const workspaceDir = process.env.VELLUM_WORKSPACE_DIR?.trim();
54
+ if (!workspaceDir) {
55
+ fail("VELLUM_WORKSPACE_DIR is not set after main preload");
56
+ }
57
+
58
+ const resolvedWorkspace = canonicalize(workspaceDir);
59
+ const tmpRoot = canonicalize(tmpdir());
60
+
61
+ if (
62
+ resolvedWorkspace !== tmpRoot &&
63
+ !resolvedWorkspace.startsWith(tmpRoot + sep)
64
+ ) {
65
+ fail(
66
+ `VELLUM_WORKSPACE_DIR resolves to ${resolvedWorkspace}, which is not under ${tmpRoot}`,
67
+ );
68
+ }
@@ -1,56 +1,42 @@
1
1
  /**
2
2
  * Shared test preload — runs before every test file.
3
3
  *
4
- * Creates a per-file temporary directory and sets VELLUM_WORKSPACE_DIR so that
5
- * all workspace-derived helpers (getDataDir, getDbPath, getConversationsDir, …)
6
- * resolve under the temp dir instead of the real ~/.vellum/workspace.
7
- *
8
- * Individual test files can retrieve the workspace dir via getWorkspaceDir()
9
- * from platform.ts, or directly from process.env.VELLUM_WORKSPACE_DIR.
4
+ * Creates a per-process temporary directory and sets VELLUM_WORKSPACE_DIR so
5
+ * that all workspace-derived helpers (getDataDir, getDbPath,
6
+ * getConversationsDir, getProtectedDir, …) resolve under the temp dir
7
+ * instead of the real $VELLUM_WORKSPACE_DIR.
10
8
  *
11
9
  * Cleanup: the temp dir is removed after all tests in the file complete.
10
+ *
11
+ * No source-module imports
12
+ * ------------------------
13
+ * The only static imports in this file are node stdlib (`node:fs`,
14
+ * `node:os`, `node:path`), `bun:test`, and helpers in this same directory.
15
+ * Importing from the assistant directly runs the risk of triggering import
16
+ * time side effects and import from node modules that may not exist in
17
+ * some environments.
12
18
  */
13
19
 
14
- import { mkdtempSync, realpathSync, rmSync } from "node:fs";
20
+ import { mkdirSync, mkdtempSync, realpathSync, rmSync } from "node:fs";
15
21
  import { tmpdir } from "node:os";
16
22
  import { join } from "node:path";
17
23
  import { afterAll } from "bun:test";
18
24
 
19
- import { installGatewayIpcMock } from "../__tests__/mock-gateway-ipc.js";
20
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
21
- import { resetDb } from "../memory/db-connection.js";
22
- import { _setStorePath } from "../security/encrypted-store.js";
25
+ import { installGatewayIpcMock } from "./mock-gateway-ipc.js";
23
26
 
24
- const testDir = realpathSync(
25
- mkdtempSync(join(tmpdir(), "vellum-test-workspace-")),
26
- );
27
+ // --- Phase 1: env override (zero source-module imports above this point) ---
28
+
29
+ // Layout: <tmpRoot>/workspace as VELLUM_WORKSPACE_DIR. The parent of
30
+ // VELLUM_WORKSPACE_DIR is what `vellumRoot()` resolves to, so a separate
31
+ // tmpRoot per process gives `getProtectedDir()` and friends per-process
32
+ // isolation without needing an explicit `setStorePathForTesting()`.
33
+ const tmpRoot = realpathSync(mkdtempSync(join(tmpdir(), "vellum-test-")));
34
+ const testDir = join(tmpRoot, "workspace");
35
+ mkdirSync(testDir);
27
36
  process.env.VELLUM_WORKSPACE_DIR = testDir;
28
37
  process.env.VELLUM_PLATFORM_URL = "https://test-platform.vellum.ai";
29
38
  process.exitCode = 0;
30
39
 
31
- // Isolate the encrypted credential store per test file. Without this,
32
- // parallel test processes all read/write the same ~/.vellum/protected/keys.enc,
33
- // causing races when one file deletes a key while another sets it.
34
- _setStorePath(join(testDir, "keys.enc"));
35
-
36
- // Mock gateway IPC so no test accidentally connects to a real gateway socket.
37
- // Tests that need to control IPC responses use mockGatewayIpc() / resetMockGatewayIpc().
38
- installGatewayIpcMock();
39
-
40
- // Pre-populate the feature-flag override cache so `initFeatureFlagOverrides()`
41
- // short-circuits its retry loop — there is no real gateway in tests, and the
42
- // retry backoff would otherwise exceed the per-test timeout for any test that
43
- // builds the CLI program. Tests exercising the retry behavior call
44
- // `clearFeatureFlagOverridesCache()` first.
45
- _setOverridesForTesting({});
46
-
47
- // Force-close any DB connection inherited from the parent process (e.g. when
48
- // the test runner is spawned by the running assistant via a pre-push hook).
49
- // Without this, the db singleton in db-connection.ts may still point at the
50
- // real ~/.vellum/workspace database, and test cleanup (DELETE FROM …) would
51
- // wipe production data — contacts, channels, credentials, etc.
52
- resetDb();
53
-
54
40
  // Prevent tests from routing credential writes through the real CES
55
41
  // (Credential Execution Service). Without this, setSecureKeyAsync() in
56
42
  // containerized environments writes to the live credential store.
@@ -59,8 +45,15 @@ const savedCesCredentialUrl = process.env.CES_CREDENTIAL_URL;
59
45
  delete process.env.IS_CONTAINERIZED;
60
46
  delete process.env.CES_CREDENTIAL_URL;
61
47
 
48
+ // --- Phase 2: install the IPC mock (no source-module imports) ---
49
+
50
+ // Mock gateway IPC so no test accidentally connects to a real gateway socket.
51
+ // The mock returns a sentinel for `get_feature_flags` to short-circuit the
52
+ // retry loop in `initFeatureFlagOverrides()`. Tests that need specific IPC
53
+ // responses use `mockGatewayIpc()` / `resetMockGatewayIpc()`.
54
+ installGatewayIpcMock();
55
+
62
56
  afterAll(() => {
63
- resetDb();
64
57
  process.exitCode = 0;
65
58
  delete process.env.VELLUM_WORKSPACE_DIR;
66
59
  delete process.env.VELLUM_PLATFORM_URL;
@@ -71,7 +64,7 @@ afterAll(() => {
71
64
  process.env.CES_CREDENTIAL_URL = savedCesCredentialUrl;
72
65
  }
73
66
  try {
74
- rmSync(testDir, { recursive: true, force: true });
67
+ rmSync(tmpRoot, { recursive: true, force: true });
75
68
  } catch {
76
69
  /* best-effort cleanup */
77
70
  }