@vellumai/assistant 0.6.4 → 0.6.5

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 (717) hide show
  1. package/.prettierignore +5 -0
  2. package/ARCHITECTURE.md +32 -36
  3. package/Dockerfile +12 -0
  4. package/README.md +3 -4
  5. package/bun.lock +8 -3
  6. package/docs/architecture/integrations.md +1 -20
  7. package/docs/architecture/security.md +16 -16
  8. package/docs/error-handling.md +111 -0
  9. package/docs/skills.md +10 -10
  10. package/docs/stt-provider-onboarding.md +2 -1
  11. package/knip.json +9 -2
  12. package/node_modules/@vellumai/ces-contracts/package.json +2 -1
  13. package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
  14. package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
  15. package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
  16. package/node_modules/@vellumai/credential-storage/package.json +2 -2
  17. package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
  18. package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
  19. package/node_modules/@vellumai/egress-proxy/package.json +2 -2
  20. package/openapi.yaml +123 -11
  21. package/package.json +6 -3
  22. package/scripts/generate-openapi.ts +50 -11
  23. package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
  24. package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
  25. package/src/__tests__/agent-loop.test.ts +112 -1
  26. package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
  27. package/src/__tests__/anthropic-provider.test.ts +171 -2
  28. package/src/__tests__/approval-cascade.test.ts +31 -10
  29. package/src/__tests__/approval-routes-http.test.ts +134 -10
  30. package/src/__tests__/assistant-attachments.test.ts +44 -0
  31. package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
  32. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  33. package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
  34. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
  35. package/src/__tests__/browser-skill-endstate.test.ts +51 -182
  36. package/src/__tests__/btw-routes.test.ts +47 -1
  37. package/src/__tests__/call-controller.test.ts +1 -2
  38. package/src/__tests__/call-site-routing-provider.test.ts +214 -0
  39. package/src/__tests__/catalog-cache.test.ts +27 -4
  40. package/src/__tests__/channel-approval-routes.test.ts +4 -4
  41. package/src/__tests__/channel-reply-delivery.test.ts +300 -2
  42. package/src/__tests__/checker.test.ts +428 -501
  43. package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
  44. package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
  45. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  46. package/src/__tests__/config-analysis.test.ts +11 -28
  47. package/src/__tests__/config-loader-backfill.test.ts +174 -0
  48. package/src/__tests__/config-loader-corrupt.test.ts +183 -0
  49. package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
  50. package/src/__tests__/config-schema-cmd.test.ts +11 -5
  51. package/src/__tests__/config-schema.test.ts +427 -114
  52. package/src/__tests__/config-watcher.test.ts +2 -2
  53. package/src/__tests__/contact-store-user-file.test.ts +72 -73
  54. package/src/__tests__/contacts-write.test.ts +4 -4
  55. package/src/__tests__/context-token-estimator.test.ts +191 -1
  56. package/src/__tests__/context-window-manager.test.ts +530 -2
  57. package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
  58. package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
  59. package/src/__tests__/conversation-agent-loop.test.ts +412 -82
  60. package/src/__tests__/conversation-attachments.test.ts +1 -1
  61. package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
  62. package/src/__tests__/conversation-error.test.ts +37 -6
  63. package/src/__tests__/conversation-history-web-search.test.ts +6 -0
  64. package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
  65. package/src/__tests__/conversation-lifecycle.test.ts +336 -0
  66. package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
  67. package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
  68. package/src/__tests__/conversation-process-callsite.test.ts +306 -0
  69. package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
  70. package/src/__tests__/conversation-queue.test.ts +41 -26
  71. package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
  72. package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
  73. package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
  74. package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
  75. package/src/__tests__/conversation-skill-tools.test.ts +12 -146
  76. package/src/__tests__/conversation-slash-queue.test.ts +34 -19
  77. package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
  78. package/src/__tests__/conversation-speed-override.test.ts +30 -11
  79. package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
  80. package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
  81. package/src/__tests__/conversation-title-service.test.ts +2 -2
  82. package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
  83. package/src/__tests__/conversation-unread-route.test.ts +2 -2
  84. package/src/__tests__/conversation-usage.test.ts +3 -1
  85. package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
  86. package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
  87. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
  89. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  90. package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
  91. package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
  92. package/src/__tests__/credential-vault-unit.test.ts +135 -19
  93. package/src/__tests__/credentials-cli.test.ts +1 -9
  94. package/src/__tests__/cross-provider-web-search.test.ts +84 -0
  95. package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
  96. package/src/__tests__/delete-propagation.test.ts +437 -0
  97. package/src/__tests__/dm-backfill.test.ts +417 -0
  98. package/src/__tests__/dm-persistence.test.ts +227 -0
  99. package/src/__tests__/edit-propagation.test.ts +280 -0
  100. package/src/__tests__/ephemeral-permissions.test.ts +93 -3
  101. package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
  102. package/src/__tests__/estimator-calibration.test.ts +213 -0
  103. package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
  104. package/src/__tests__/file-write-tool.test.ts +151 -1
  105. package/src/__tests__/filing-service.test.ts +255 -0
  106. package/src/__tests__/gemini-provider.test.ts +0 -3
  107. package/src/__tests__/guardian-grant-minting.test.ts +8 -0
  108. package/src/__tests__/headless-browser-interactions.test.ts +1 -1
  109. package/src/__tests__/heartbeat-service.test.ts +96 -15
  110. package/src/__tests__/host-shell-tool.test.ts +124 -18
  111. package/src/__tests__/http-user-message-parity.test.ts +29 -1
  112. package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
  113. package/src/__tests__/intent-routing.test.ts +1 -40
  114. package/src/__tests__/llm-catalog-parity.test.ts +174 -0
  115. package/src/__tests__/llm-context-normalization.test.ts +121 -0
  116. package/src/__tests__/llm-resolver.test.ts +214 -0
  117. package/src/__tests__/llm-schema.test.ts +223 -0
  118. package/src/__tests__/managed-proxy-context.test.ts +6 -2
  119. package/src/__tests__/messaging-skill-split.test.ts +3 -34
  120. package/src/__tests__/migration-import-from-url.test.ts +684 -0
  121. package/src/__tests__/model-intents.test.ts +9 -83
  122. package/src/__tests__/notification-decision-fallback.test.ts +0 -10
  123. package/src/__tests__/notification-decision-identity.test.ts +0 -9
  124. package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
  125. package/src/__tests__/oauth-store.test.ts +10 -7
  126. package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
  127. package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
  128. package/src/__tests__/openai-provider.test.ts +7 -0
  129. package/src/__tests__/openai-responses-provider.test.ts +396 -0
  130. package/src/__tests__/openrouter-provider-only.test.ts +135 -0
  131. package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
  132. package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
  133. package/src/__tests__/permission-mode.test.ts +16 -0
  134. package/src/__tests__/permission-types.test.ts +0 -1
  135. package/src/__tests__/persona-resolver.test.ts +13 -13
  136. package/src/__tests__/pkb-autoinject.test.ts +37 -1
  137. package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
  138. package/src/__tests__/pricing.test.ts +50 -3
  139. package/src/__tests__/profiler-routes.test.ts +1 -1
  140. package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
  141. package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
  142. package/src/__tests__/provider-error-scenarios.test.ts +135 -6
  143. package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
  144. package/src/__tests__/provider-registry-ollama.test.ts +1 -2
  145. package/src/__tests__/proxy-approval-callback.test.ts +0 -1
  146. package/src/__tests__/reaction-persistence.test.ts +560 -0
  147. package/src/__tests__/relay-server.test.ts +1 -1
  148. package/src/__tests__/require-fresh-approval.test.ts +1 -1
  149. package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
  150. package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
  151. package/src/__tests__/risk-classifier-parity.test.ts +230 -0
  152. package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
  153. package/src/__tests__/secret-ingress-http.test.ts +28 -0
  154. package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
  156. package/src/__tests__/secret-scanner-executor.test.ts +1 -1
  157. package/src/__tests__/send-endpoint-busy.test.ts +29 -1
  158. package/src/__tests__/server-history-render.test.ts +31 -0
  159. package/src/__tests__/shell-parser-property.test.ts +13 -13
  160. package/src/__tests__/skill-cache-store.test.ts +182 -0
  161. package/src/__tests__/skills.test.ts +19 -33
  162. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  163. package/src/__tests__/slack-skill.test.ts +3 -8
  164. package/src/__tests__/starter-bundle.test.ts +35 -0
  165. package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
  166. package/src/__tests__/suggestion-routes.test.ts +160 -3
  167. package/src/__tests__/system-prompt.test.ts +22 -35
  168. package/src/__tests__/task-runner.test.ts +3 -1
  169. package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
  170. package/src/__tests__/terminal-tools.test.ts +8 -0
  171. package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
  172. package/src/__tests__/thread-backfill.test.ts +941 -0
  173. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
  174. package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
  175. package/src/__tests__/tool-executor.test.ts +60 -94
  176. package/src/__tests__/trust-store.test.ts +442 -109
  177. package/src/__tests__/update-bulletin-job.test.ts +389 -0
  178. package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
  179. package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
  180. package/src/__tests__/voice-session-bridge.test.ts +39 -0
  181. package/src/__tests__/volume-security-guard.test.ts +3 -2
  182. package/src/__tests__/web-search-history.test.ts +337 -0
  183. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
  184. package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
  185. package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
  186. package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
  187. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
  188. package/src/__tests__/workspace-policy.test.ts +1 -13
  189. package/src/acp/client-handler.ts +1 -2
  190. package/src/agent/loop.ts +209 -17
  191. package/src/avatar/resvg-lazy.test.ts +136 -0
  192. package/src/avatar/resvg-lazy.ts +82 -9
  193. package/src/avatar/traits-png-sync.ts +21 -1
  194. package/src/browser/__tests__/operations.test.ts +163 -0
  195. package/src/browser/identifiers.ts +51 -0
  196. package/src/browser/operations.ts +660 -0
  197. package/src/browser/types.ts +81 -0
  198. package/src/calls/guardian-question-copy.ts +2 -2
  199. package/src/calls/telephony-stt-routing.ts +1 -1
  200. package/src/calls/voice-session-bridge.ts +1 -0
  201. package/src/cli/AGENTS.md +1 -1
  202. package/src/cli/commands/__tests__/attachment.test.ts +438 -0
  203. package/src/cli/commands/__tests__/browser.test.ts +554 -0
  204. package/src/cli/commands/__tests__/cache.test.ts +623 -0
  205. package/src/cli/commands/__tests__/email-list.test.ts +6 -0
  206. package/src/cli/commands/__tests__/email-send.test.ts +93 -1
  207. package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
  208. package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
  209. package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
  210. package/src/cli/commands/__tests__/task.test.ts +913 -0
  211. package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
  212. package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
  213. package/src/cli/commands/__tests__/ui.test.ts +1215 -0
  214. package/src/cli/commands/__tests__/watchers.test.ts +716 -0
  215. package/src/cli/commands/attachment.ts +182 -0
  216. package/src/cli/commands/browser.ts +350 -0
  217. package/src/cli/commands/cache.ts +341 -0
  218. package/src/cli/commands/completions.ts +0 -3
  219. package/src/cli/commands/config.ts +6 -6
  220. package/src/cli/commands/conversations-import.ts +347 -0
  221. package/src/cli/commands/conversations.ts +14 -1
  222. package/src/cli/commands/email.ts +234 -194
  223. package/src/cli/commands/image-generation.ts +300 -0
  224. package/src/cli/commands/inference.ts +200 -0
  225. package/src/cli/commands/memory.ts +127 -17
  226. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
  227. package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
  228. package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
  229. package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
  230. package/src/cli/commands/stt.ts +339 -0
  231. package/src/cli/commands/task.ts +795 -0
  232. package/src/cli/commands/trust.ts +50 -19
  233. package/src/cli/commands/tts.ts +273 -0
  234. package/src/cli/commands/ui.ts +670 -0
  235. package/src/cli/commands/watchers.ts +509 -0
  236. package/src/cli/lib/daemon-credential-client.ts +0 -19
  237. package/src/cli/program.ts +23 -4
  238. package/src/cli.ts +0 -37
  239. package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
  240. package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
  241. package/src/config/bundled-skills/messaging/SKILL.md +2 -2
  242. package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
  243. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
  244. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
  245. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
  246. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
  247. package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
  248. package/src/config/bundled-skills/settings/TOOLS.json +3 -3
  249. package/src/config/bundled-tool-registry.ts +0 -175
  250. package/src/config/env.ts +7 -2
  251. package/src/config/feature-flag-registry.json +25 -9
  252. package/src/config/llm-resolver.ts +128 -0
  253. package/src/config/loader.ts +194 -10
  254. package/src/config/raw-config-utils.ts +30 -2
  255. package/src/config/sanitize-for-transfer.ts +35 -0
  256. package/src/config/schema.ts +30 -41
  257. package/src/config/schemas/analysis.ts +3 -22
  258. package/src/config/schemas/calls.ts +0 -4
  259. package/src/config/schemas/filing.ts +2 -7
  260. package/src/config/schemas/heartbeat.ts +0 -5
  261. package/src/config/schemas/inference.ts +3 -23
  262. package/src/config/schemas/llm.ts +318 -0
  263. package/src/config/schemas/memory-processing.ts +1 -9
  264. package/src/config/schemas/notifications.ts +4 -11
  265. package/src/config/schemas/platform.ts +3 -9
  266. package/src/config/schemas/security.ts +33 -0
  267. package/src/config/schemas/services.ts +9 -4
  268. package/src/config/schemas/stt.ts +1 -0
  269. package/src/config/schemas/tts.ts +53 -0
  270. package/src/config/schemas/updates.ts +1 -1
  271. package/src/config/schemas/workspace-git.ts +3 -40
  272. package/src/config/skills.ts +2 -2
  273. package/src/context/__tests__/compact-prompt.test.ts +45 -0
  274. package/src/context/__tests__/microcompact.test.ts +805 -0
  275. package/src/context/estimator-calibration.ts +136 -0
  276. package/src/context/microcompact.ts +443 -0
  277. package/src/context/prompts/compact.md +12 -0
  278. package/src/context/token-estimator.ts +61 -3
  279. package/src/context/window-manager.ts +229 -25
  280. package/src/credential-execution/approval-bridge.ts +0 -1
  281. package/src/credential-execution/executable-discovery.ts +19 -8
  282. package/src/credential-execution/process-manager.test.ts +109 -0
  283. package/src/credential-execution/process-manager.ts +65 -2
  284. package/src/daemon/approval-generators.ts +29 -4
  285. package/src/daemon/assistant-attachments.ts +24 -13
  286. package/src/daemon/classifier.ts +2 -2
  287. package/src/daemon/config-watcher.ts +0 -1
  288. package/src/daemon/context-overflow-reducer.ts +4 -1
  289. package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
  290. package/src/daemon/conversation-agent-loop.ts +462 -80
  291. package/src/daemon/conversation-attachments.ts +2 -6
  292. package/src/daemon/conversation-error.ts +36 -1
  293. package/src/daemon/conversation-lifecycle.ts +30 -6
  294. package/src/daemon/conversation-messaging.ts +73 -4
  295. package/src/daemon/conversation-process.ts +10 -4
  296. package/src/daemon/conversation-queue-manager.ts +3 -0
  297. package/src/daemon/conversation-runtime-assembly.ts +760 -29
  298. package/src/daemon/conversation-slash.ts +2 -2
  299. package/src/daemon/conversation-surfaces.ts +389 -1
  300. package/src/daemon/conversation-tool-setup.ts +10 -5
  301. package/src/daemon/conversation-usage.ts +1 -1
  302. package/src/daemon/conversation.ts +118 -30
  303. package/src/daemon/external-skills-bootstrap.ts +41 -0
  304. package/src/daemon/guardian-action-generators.ts +34 -14
  305. package/src/daemon/handlers/config-model.test.ts +86 -0
  306. package/src/daemon/handlers/config-model.ts +54 -12
  307. package/src/daemon/handlers/conversations.ts +9 -2
  308. package/src/daemon/handlers/shared.ts +39 -11
  309. package/src/daemon/handlers/skills.ts +2 -2
  310. package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
  311. package/src/daemon/lifecycle.ts +76 -14
  312. package/src/daemon/message-types/conversations.ts +14 -0
  313. package/src/daemon/message-types/messages.ts +9 -1
  314. package/src/daemon/message-types/trust.ts +0 -2
  315. package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
  316. package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
  317. package/src/daemon/pkb-context-tracker.test.ts +169 -0
  318. package/src/daemon/pkb-context-tracker.ts +125 -0
  319. package/src/daemon/pkb-reminder-builder.test.ts +70 -0
  320. package/src/daemon/pkb-reminder-builder.ts +31 -0
  321. package/src/daemon/providers-setup.ts +6 -0
  322. package/src/daemon/server.ts +117 -9
  323. package/src/daemon/tool-side-effects.ts +0 -9
  324. package/src/daemon/watch-handler.ts +4 -4
  325. package/src/daemon/web-search-history.ts +126 -0
  326. package/src/events/domain-events.ts +0 -1
  327. package/src/filing/filing-service.ts +9 -10
  328. package/src/heartbeat/heartbeat-service.ts +76 -28
  329. package/src/home/__tests__/feed-scheduler.test.ts +39 -11
  330. package/src/home/__tests__/rollup-producer.test.ts +44 -0
  331. package/src/home/assistant-feed-authoring.ts +4 -0
  332. package/src/home/emit-feed-event.ts +4 -0
  333. package/src/home/feed-scheduler.ts +20 -4
  334. package/src/home/feed-types.ts +56 -2
  335. package/src/home/relationship-state-writer.ts +2 -2
  336. package/src/home/rollup-producer.ts +34 -5
  337. package/src/home/suggested-prompts.ts +101 -0
  338. package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
  339. package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
  340. package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
  341. package/src/ipc/__tests__/socket-path.test.ts +73 -0
  342. package/src/ipc/__tests__/task-ipc.test.ts +577 -0
  343. package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
  344. package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
  345. package/src/ipc/cli-client.ts +2 -1
  346. package/src/ipc/cli-server.ts +26 -8
  347. package/src/ipc/gateway-client.ts +4 -4
  348. package/src/ipc/routes/attachment.ts +114 -0
  349. package/src/ipc/routes/browser-context.ts +61 -0
  350. package/src/ipc/routes/browser.ts +96 -0
  351. package/src/ipc/routes/cache.ts +96 -0
  352. package/src/ipc/routes/index.ts +17 -1
  353. package/src/ipc/routes/task-queue.ts +226 -0
  354. package/src/ipc/routes/task.ts +173 -0
  355. package/src/ipc/routes/ui-request.ts +50 -0
  356. package/src/ipc/routes/watcher.ts +203 -0
  357. package/src/ipc/socket-path.ts +100 -0
  358. package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
  359. package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
  360. package/src/memory/admin.ts +18 -0
  361. package/src/memory/conversation-analyze-job.ts +14 -13
  362. package/src/memory/conversation-attention-store.ts +13 -6
  363. package/src/memory/conversation-crud.ts +103 -3
  364. package/src/memory/conversation-group-migration.ts +38 -6
  365. package/src/memory/conversation-title-service.ts +7 -4
  366. package/src/memory/db-init.ts +2 -0
  367. package/src/memory/embedding-backend.ts +1 -1
  368. package/src/memory/graph/compaction.ts +299 -0
  369. package/src/memory/graph/consolidation.ts +4 -4
  370. package/src/memory/graph/conversation-graph-memory.ts +89 -29
  371. package/src/memory/graph/extraction.test.ts +272 -2
  372. package/src/memory/graph/extraction.ts +173 -51
  373. package/src/memory/graph/graph-search.test.ts +92 -0
  374. package/src/memory/graph/graph-search.ts +4 -1
  375. package/src/memory/graph/narrative.ts +2 -2
  376. package/src/memory/graph/pattern-scan.ts +2 -2
  377. package/src/memory/graph/retriever.test.ts +459 -0
  378. package/src/memory/graph/retriever.ts +230 -48
  379. package/src/memory/graph/store.ts +41 -0
  380. package/src/memory/graph/tool-handlers.ts +27 -0
  381. package/src/memory/graph/tools.ts +6 -1
  382. package/src/memory/indexer.ts +5 -5
  383. package/src/memory/job-handlers/conversation-starters.ts +23 -20
  384. package/src/memory/job-handlers/summarization.ts +2 -2
  385. package/src/memory/job-utils.ts +7 -1
  386. package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
  387. package/src/memory/jobs/embed-pkb-file.ts +54 -0
  388. package/src/memory/jobs-store.ts +44 -3
  389. package/src/memory/jobs-worker.ts +4 -0
  390. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
  391. package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
  392. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
  393. package/src/memory/migrations/index.ts +1 -0
  394. package/src/memory/pkb/pkb-index.test.ts +368 -0
  395. package/src/memory/pkb/pkb-index.ts +255 -0
  396. package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
  397. package/src/memory/pkb/pkb-reconcile.ts +148 -0
  398. package/src/memory/pkb/pkb-search.test.ts +438 -0
  399. package/src/memory/pkb/pkb-search.ts +137 -0
  400. package/src/memory/pkb/types.ts +53 -0
  401. package/src/memory/qdrant-client.ts +122 -1
  402. package/src/memory/slack-thread-store.ts +37 -0
  403. package/src/messaging/providers/gmail/adapter.ts +6 -16
  404. package/src/messaging/providers/gmail/client.ts +22 -0
  405. package/src/messaging/providers/gmail/types.ts +7 -0
  406. package/src/messaging/providers/slack/adapter.ts +14 -2
  407. package/src/messaging/providers/slack/backfill.test.ts +257 -0
  408. package/src/messaging/providers/slack/backfill.ts +101 -0
  409. package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
  410. package/src/messaging/providers/slack/message-metadata.ts +123 -0
  411. package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
  412. package/src/messaging/providers/slack/render-transcript.ts +443 -0
  413. package/src/messaging/style-analyzer.ts +5 -2
  414. package/src/notifications/README.md +9 -5
  415. package/src/notifications/decision-engine.ts +3 -9
  416. package/src/notifications/preference-extractor.ts +2 -6
  417. package/src/oauth/oauth-store.ts +1 -0
  418. package/src/oauth/platform-connection.test.ts +47 -0
  419. package/src/oauth/platform-connection.ts +15 -5
  420. package/src/oauth/seed-providers.ts +4 -2
  421. package/src/permissions/approval-policy.test.ts +948 -0
  422. package/src/permissions/approval-policy.ts +257 -0
  423. package/src/permissions/bash-risk-classifier.test.ts +1208 -0
  424. package/src/permissions/bash-risk-classifier.ts +707 -0
  425. package/src/permissions/checker.ts +217 -708
  426. package/src/permissions/command-registry.test.ts +535 -0
  427. package/src/permissions/command-registry.ts +825 -0
  428. package/src/permissions/defaults.ts +26 -78
  429. package/src/permissions/file-risk-classifier.test.ts +535 -0
  430. package/src/permissions/file-risk-classifier.ts +274 -0
  431. package/src/permissions/risk-types.ts +205 -0
  432. package/src/permissions/secret-prompter.ts +53 -2
  433. package/src/permissions/skill-risk-classifier.test.ts +311 -0
  434. package/src/permissions/skill-risk-classifier.ts +214 -0
  435. package/src/permissions/trust-client.ts +52 -25
  436. package/src/permissions/trust-store-interface.ts +1 -6
  437. package/src/permissions/trust-store.ts +161 -62
  438. package/src/permissions/types.ts +23 -14
  439. package/src/permissions/web-risk-classifier.test.ts +170 -0
  440. package/src/permissions/web-risk-classifier.ts +89 -0
  441. package/src/permissions/workspace-policy.ts +1 -16
  442. package/src/platform/client.ts +19 -1
  443. package/src/prompts/persona-resolver.ts +3 -3
  444. package/src/prompts/system-prompt.ts +19 -20
  445. package/src/prompts/templates/SOUL.md +2 -2
  446. package/src/prompts/update-bulletin-job.ts +190 -0
  447. package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
  448. package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
  449. package/src/providers/__tests__/retry-callsite.test.ts +424 -0
  450. package/src/providers/anthropic/client.ts +183 -14
  451. package/src/providers/call-site-routing.ts +71 -0
  452. package/src/providers/gemini/client.ts +65 -2
  453. package/src/providers/managed-proxy/constants.ts +2 -1
  454. package/src/providers/model-catalog.ts +501 -33
  455. package/src/providers/model-intents.ts +4 -4
  456. package/src/providers/openai/chat-completions-provider.ts +57 -1
  457. package/src/providers/openai/responses-provider.ts +86 -9
  458. package/src/providers/openrouter/client.ts +76 -9
  459. package/src/providers/provider-env-vars.ts +56 -0
  460. package/src/providers/provider-send-message.ts +22 -5
  461. package/src/providers/ratelimit.ts +4 -0
  462. package/src/providers/registry.ts +19 -8
  463. package/src/providers/retry.ts +174 -39
  464. package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
  465. package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
  466. package/src/providers/speech-to-text/provider-catalog.ts +17 -0
  467. package/src/providers/speech-to-text/resolve.ts +7 -0
  468. package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
  469. package/src/providers/speech-to-text/xai-realtime.ts +796 -0
  470. package/src/providers/speech-to-text/xai.test.ts +155 -0
  471. package/src/providers/speech-to-text/xai.ts +97 -0
  472. package/src/providers/types.ts +93 -3
  473. package/src/runtime/AGENTS.md +2 -2
  474. package/src/runtime/__tests__/agent-wake.test.ts +43 -2
  475. package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
  476. package/src/runtime/agent-wake.ts +63 -22
  477. package/src/runtime/auth/route-policy.ts +4 -0
  478. package/src/runtime/btw-sidechain.ts +13 -3
  479. package/src/runtime/channel-reply-delivery.ts +106 -2
  480. package/src/runtime/decision-token.ts +116 -0
  481. package/src/runtime/gateway-client.ts +2 -2
  482. package/src/runtime/http-router.ts +32 -0
  483. package/src/runtime/http-server.ts +52 -1
  484. package/src/runtime/http-types.ts +23 -1
  485. package/src/runtime/interactive-ui.ts +362 -0
  486. package/src/runtime/invite-instruction-generator.ts +2 -2
  487. package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
  488. package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
  489. package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
  490. package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
  491. package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
  492. package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
  493. package/src/runtime/migrations/gcs-signed-url.ts +162 -0
  494. package/src/runtime/migrations/vbundle-importer.ts +154 -9
  495. package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
  496. package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
  497. package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
  498. package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
  499. package/src/runtime/migrations/vbundle-validator.ts +15 -6
  500. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
  501. package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
  502. package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
  503. package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
  504. package/src/runtime/routes/approval-routes.ts +12 -17
  505. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
  506. package/src/runtime/routes/avatar-routes.ts +20 -4
  507. package/src/runtime/routes/btw-routes.ts +1 -4
  508. package/src/runtime/routes/conversation-management-routes.ts +20 -2
  509. package/src/runtime/routes/conversation-routes.ts +133 -27
  510. package/src/runtime/routes/debug-routes.ts +1 -1
  511. package/src/runtime/routes/diagnostics-routes.ts +6 -4
  512. package/src/runtime/routes/events-routes.ts +16 -0
  513. package/src/runtime/routes/guardian-approval-interception.ts +33 -3
  514. package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
  515. package/src/runtime/routes/home-feed-routes.ts +120 -2
  516. package/src/runtime/routes/inbound-message-handler.ts +912 -2
  517. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
  518. package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
  519. package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
  520. package/src/runtime/routes/integrations/slack/channel.ts +25 -3
  521. package/src/runtime/routes/llm-context-normalization.ts +23 -1
  522. package/src/runtime/routes/migration-routes.ts +720 -124
  523. package/src/runtime/routes/settings-routes.ts +4 -2
  524. package/src/runtime/routes/trust-rules-routes.ts +30 -14
  525. package/src/runtime/routes/work-items-routes.test.ts +1 -1
  526. package/src/runtime/routes/work-items-routes.ts +3 -2
  527. package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
  528. package/src/runtime/services/analyze-conversation.ts +12 -16
  529. package/src/runtime/skill-route-registry.ts +28 -6
  530. package/src/schedule/scheduler.ts +8 -0
  531. package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
  532. package/src/security/__tests__/untrusted-content.test.ts +109 -0
  533. package/src/security/oauth2.ts +98 -35
  534. package/src/security/secure-keys.ts +7 -8
  535. package/src/security/token-manager.ts +27 -13
  536. package/src/security/untrusted-content.ts +102 -0
  537. package/src/skills/catalog-cache.ts +26 -7
  538. package/src/skills/catalog-install.ts +31 -3
  539. package/src/skills/skill-cache-store.ts +97 -0
  540. package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
  541. package/src/stt/daemon-batch-transcriber.ts +33 -0
  542. package/src/stt/stt-stream-session.ts +8 -1
  543. package/src/stt/types.ts +5 -1
  544. package/src/subagent/manager.ts +41 -13
  545. package/src/tasks/ephemeral-permissions.ts +9 -4
  546. package/src/telemetry/usage-telemetry-reporter.ts +27 -5
  547. package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
  548. package/src/tools/browser/browser-execution.ts +65 -38
  549. package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
  550. package/src/tools/credentials/tool-policy.ts +39 -5
  551. package/src/tools/credentials/vault.ts +9 -4
  552. package/src/tools/executor.ts +4 -0
  553. package/src/tools/filesystem/write.ts +52 -0
  554. package/src/tools/host-terminal/host-shell.ts +45 -5
  555. package/src/tools/memory/register.test.ts +185 -0
  556. package/src/tools/memory/register.ts +3 -1
  557. package/src/tools/network/web-fetch.ts +20 -10
  558. package/src/tools/network/web-search.ts +19 -4
  559. package/src/tools/permission-checker.ts +36 -15
  560. package/src/tools/policy-context.ts +25 -8
  561. package/src/tools/registry.ts +55 -3
  562. package/src/tools/side-effects.ts +0 -11
  563. package/src/tools/skills/execute.ts +2 -2
  564. package/src/tools/skills/sandbox-runner.ts +5 -2
  565. package/src/tools/terminal/backends/native.ts +51 -2
  566. package/src/tools/terminal/safe-env.ts +3 -2
  567. package/src/tools/terminal/shell.ts +1 -0
  568. package/src/tools/tool-manifest.ts +6 -21
  569. package/src/tools/types.ts +12 -3
  570. package/src/tools/verification-control-plane-policy.ts +1 -1
  571. package/src/tts/__tests__/provider-adapters.test.ts +240 -13
  572. package/src/tts/provider-catalog.ts +18 -0
  573. package/src/tts/providers/index.ts +2 -0
  574. package/src/tts/providers/xai-provider.ts +224 -0
  575. package/src/tts/types.ts +46 -0
  576. package/src/types/tar-stream.d.ts +66 -0
  577. package/src/util/json.ts +17 -0
  578. package/src/util/platform.ts +2 -2
  579. package/src/util/pricing.ts +15 -5
  580. package/src/watcher/engine.ts +1 -1
  581. package/src/watcher/providers/google-calendar.ts +134 -8
  582. package/src/watcher/providers/outlook-calendar.ts +42 -2
  583. package/src/workspace/git-service.ts +23 -4
  584. package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
  585. package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
  586. package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
  587. package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
  588. package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
  589. package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
  590. package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
  591. package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
  592. package/src/workspace/migrations/AGENTS.md +1 -1
  593. package/src/workspace/migrations/registry.ts +16 -0
  594. package/src/workspace/provider-commit-message-generator.ts +19 -38
  595. package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
  596. package/src/__tests__/gmail-archive-gate.test.ts +0 -246
  597. package/src/__tests__/gmail-preferences.test.ts +0 -117
  598. package/src/__tests__/outlook-attachments.test.ts +0 -301
  599. package/src/__tests__/outlook-automation-tools.test.ts +0 -425
  600. package/src/__tests__/outlook-categories.test.ts +0 -212
  601. package/src/__tests__/outlook-compose-tools.test.ts +0 -325
  602. package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
  603. package/src/__tests__/outlook-follow-up.test.ts +0 -196
  604. package/src/__tests__/outlook-trash.test.ts +0 -77
  605. package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
  606. package/src/__tests__/update-bulletin-format.test.ts +0 -181
  607. package/src/__tests__/update-bulletin-state.test.ts +0 -135
  608. package/src/__tests__/update-bulletin.test.ts +0 -478
  609. package/src/__tests__/update-template-contract.test.ts +0 -29
  610. package/src/cli/commands/doctor.ts +0 -341
  611. package/src/config/bundled-skills/browser/SKILL.md +0 -88
  612. package/src/config/bundled-skills/browser/TOOLS.json +0 -516
  613. package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
  614. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
  615. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
  616. package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
  617. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
  618. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
  619. package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
  620. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
  621. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
  622. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
  623. package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
  624. package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
  625. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
  626. package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
  627. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
  628. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
  629. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
  630. package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
  631. package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
  632. package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
  633. package/src/config/bundled-skills/gmail/SKILL.md +0 -221
  634. package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
  635. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
  636. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
  637. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
  638. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
  639. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
  640. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
  641. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
  642. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
  643. package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
  644. package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
  645. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
  646. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
  647. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
  648. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
  649. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
  650. package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
  651. package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
  652. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  653. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
  654. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
  655. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
  656. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
  657. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
  658. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
  659. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
  660. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
  661. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  662. package/src/config/bundled-skills/outlook/SKILL.md +0 -196
  663. package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
  664. package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
  665. package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
  666. package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
  667. package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
  668. package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
  669. package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
  670. package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
  671. package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
  672. package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
  673. package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
  674. package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
  675. package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
  676. package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
  677. package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
  678. package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
  679. package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
  680. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
  681. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
  682. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
  683. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
  684. package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
  685. package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
  686. package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
  687. package/src/config/bundled-skills/slack/SKILL.md +0 -108
  688. package/src/config/bundled-skills/tasks/SKILL.md +0 -37
  689. package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
  690. package/src/config/bundled-skills/tasks/icon.svg +0 -34
  691. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
  692. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
  693. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
  694. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
  695. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
  696. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
  697. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
  698. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
  699. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
  700. package/src/config/bundled-skills/watcher/SKILL.md +0 -31
  701. package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
  702. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
  703. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
  704. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
  705. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
  706. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
  707. package/src/prompts/templates/UPDATES.md +0 -50
  708. package/src/prompts/update-bulletin-format.ts +0 -85
  709. package/src/prompts/update-bulletin-state.ts +0 -58
  710. package/src/prompts/update-bulletin-template-path.ts +0 -13
  711. package/src/prompts/update-bulletin.ts +0 -139
  712. package/src/shared/provider-env-vars.ts +0 -19
  713. package/src/tools/watcher/create.ts +0 -86
  714. package/src/tools/watcher/delete.ts +0 -36
  715. package/src/tools/watcher/digest.ts +0 -54
  716. package/src/tools/watcher/list.ts +0 -83
  717. package/src/tools/watcher/update.ts +0 -71
@@ -0,0 +1,255 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
4
+
5
+ import { resolveCallSiteConfig } from "../config/llm-resolver.js";
6
+ import { LLMSchema } from "../config/schemas/llm.js";
7
+
8
+ const testWorkspaceDir = process.env.VELLUM_WORKSPACE_DIR!;
9
+
10
+ // Mock config loader. Filing's `runOnce()` reads `getConfig().filing`, and
11
+ // `executeRun()` no longer reads `config.speed` (PR 8) — the call site is
12
+ // hardcoded to 'filingAgent' and the resolver picks up `llm.callSites.filingAgent`
13
+ // inside the daemon's processMessage path.
14
+ let mockConfig = {
15
+ filing: {
16
+ enabled: true,
17
+ intervalMs: 60_000,
18
+ speed: "standard" as "standard" | "fast",
19
+ activeHoursStart: null as number | null,
20
+ activeHoursEnd: null as number | null,
21
+ },
22
+ };
23
+
24
+ mock.module("../config/loader.js", () => ({
25
+ getConfig: () => mockConfig,
26
+ loadConfig: () => mockConfig,
27
+ loadRawConfig: () => ({}),
28
+ saveRawConfig: () => {},
29
+ invalidateConfigCache: () => {},
30
+ }));
31
+
32
+ // Mock conversation store
33
+ const createdConversations: Array<{ title: string; conversationType: string }> =
34
+ [];
35
+ let conversationIdCounter = 0;
36
+
37
+ mock.module("../memory/conversation-crud.js", () => ({
38
+ getConversationType: () => "default",
39
+ setConversationOriginChannelIfUnset: () => {},
40
+ updateConversationContextWindow: () => {},
41
+ deleteMessageById: () => {},
42
+ updateConversationTitle: () => {},
43
+ updateConversationUsage: () => {},
44
+ addMessage: () => ({ id: "mock-msg-id" }),
45
+ getMessages: () => [],
46
+ getConversation: () => ({
47
+ id: "conv-1",
48
+ contextSummary: null,
49
+ contextCompactedMessageCount: 0,
50
+ totalInputTokens: 0,
51
+ totalOutputTokens: 0,
52
+ totalEstimatedCost: 0,
53
+ title: null,
54
+ }),
55
+ getMessageById: () => null,
56
+ provenanceFromTrustContext: () => ({
57
+ source: "user",
58
+ trustContext: undefined,
59
+ }),
60
+ getConversationOriginInterface: () => null,
61
+ getConversationOriginChannel: () => null,
62
+ createConversation: (opts: { title: string; conversationType: string }) => {
63
+ createdConversations.push(opts);
64
+ return { id: `conv-${++conversationIdCounter}`, ...opts };
65
+ },
66
+ }));
67
+
68
+ // Mock logger
69
+ mock.module("../util/logger.js", () => ({
70
+ getLogger: () => ({
71
+ info: () => {},
72
+ debug: () => {},
73
+ warn: () => {},
74
+ error: () => {},
75
+ }),
76
+ }));
77
+
78
+ // Mock conversation title service
79
+ mock.module("../memory/conversation-title-service.js", () => ({
80
+ GENERATING_TITLE: "Generating title...",
81
+ queueGenerateConversationTitle: () => {},
82
+ }));
83
+
84
+ // Import after mocks are set up
85
+ const { FilingService } = await import("../filing/filing-service.js");
86
+
87
+ describe("FilingService", () => {
88
+ let processMessageCalls: Array<{
89
+ conversationId: string;
90
+ content: string;
91
+ options?: { speed?: string; callSite?: string };
92
+ }>;
93
+
94
+ afterEach(() => {
95
+ // Clean up workspace files between tests so buffer-existence tests don't leak
96
+ const bufferPath = join(testWorkspaceDir, "pkb", "buffer.md");
97
+ try {
98
+ writeFileSync(bufferPath, "");
99
+ } catch {
100
+ // best-effort
101
+ }
102
+ });
103
+
104
+ beforeEach(() => {
105
+ processMessageCalls = [];
106
+ createdConversations.length = 0;
107
+ conversationIdCounter = 0;
108
+
109
+ mockConfig = {
110
+ filing: {
111
+ enabled: true,
112
+ intervalMs: 60_000,
113
+ speed: "standard",
114
+ activeHoursStart: null,
115
+ activeHoursEnd: null,
116
+ },
117
+ };
118
+
119
+ // Seed buffer.md with content so runOnce doesn't skip
120
+ const pkbDir = join(testWorkspaceDir, "pkb");
121
+ try {
122
+ mkdirSync(pkbDir, { recursive: true });
123
+ } catch {
124
+ // best-effort
125
+ }
126
+ writeFileSync(join(pkbDir, "buffer.md"), "- some buffered fact\n");
127
+ });
128
+
129
+ function createService(overrides?: {
130
+ processMessage?: (
131
+ id: string,
132
+ content: string,
133
+ options?: { speed?: string; callSite?: string },
134
+ ) => Promise<{ messageId: string }>;
135
+ }) {
136
+ return new FilingService({
137
+ processMessage:
138
+ overrides?.processMessage ??
139
+ (async (
140
+ conversationId: string,
141
+ content: string,
142
+ options?: { speed?: string; callSite?: string },
143
+ ) => {
144
+ processMessageCalls.push({ conversationId, content, options });
145
+ return { messageId: "msg-1" };
146
+ }),
147
+ });
148
+ }
149
+
150
+ test("runOnce() passes callSite: 'filingAgent' to processMessage", async () => {
151
+ const service = createService();
152
+ await service.runOnce();
153
+
154
+ expect(processMessageCalls).toHaveLength(1);
155
+ expect(processMessageCalls[0].options).toEqual({ callSite: "filingAgent" });
156
+ expect(processMessageCalls[0].options?.callSite).toBe("filingAgent");
157
+ });
158
+
159
+ test("runOnce() does not pass legacy 'speed' kwarg even when filing.speed is set", async () => {
160
+ // Filing's schema still carries `speed` (PR 19 will remove it), but PR 8
161
+ // stopped reading it. Ensure the new wiring no longer leaks the legacy
162
+ // kwarg through to processMessage.
163
+ mockConfig.filing.speed = "fast";
164
+ const service = createService();
165
+ await service.runOnce();
166
+
167
+ expect(processMessageCalls).toHaveLength(1);
168
+ expect(processMessageCalls[0].options?.speed).toBeUndefined();
169
+ expect(processMessageCalls[0].options?.callSite).toBe("filingAgent");
170
+ });
171
+
172
+ test("runOnce() invokes processMessage with the filing prompt template", async () => {
173
+ const service = createService();
174
+ await service.runOnce();
175
+
176
+ expect(processMessageCalls).toHaveLength(1);
177
+ expect(processMessageCalls[0].conversationId).toBe("conv-1");
178
+ expect(processMessageCalls[0].content).toContain(
179
+ "periodic knowledge base filing job",
180
+ );
181
+ });
182
+
183
+ test("creates background conversation with generating title placeholder", async () => {
184
+ const service = createService();
185
+ await service.runOnce();
186
+
187
+ expect(createdConversations).toHaveLength(1);
188
+ expect(createdConversations[0].title).toBe("Generating title...");
189
+ expect(createdConversations[0].conversationType).toBe("background");
190
+ });
191
+
192
+ describe("llm.callSites.filingAgent resolution", () => {
193
+ // These tests verify that the call-site name used by FilingService
194
+ // ('filingAgent') resolves through the unified `llm` config the way
195
+ // downstream consumers expect.
196
+
197
+ test("resolves to llm.default when no filingAgent override exists", () => {
198
+ const llm = LLMSchema.parse({
199
+ default: {
200
+ provider: "anthropic",
201
+ model: "claude-opus-4-7",
202
+ maxTokens: 64000,
203
+ effort: "max",
204
+ speed: "standard",
205
+ },
206
+ });
207
+ const resolved = resolveCallSiteConfig("filingAgent", llm);
208
+ expect(resolved.model).toBe("claude-opus-4-7");
209
+ expect(resolved.speed).toBe("standard");
210
+ });
211
+
212
+ test("call-site override on filingAgent wins over llm.default", () => {
213
+ const llm = LLMSchema.parse({
214
+ default: {
215
+ provider: "anthropic",
216
+ model: "claude-opus-4-7",
217
+ maxTokens: 64000,
218
+ effort: "max",
219
+ speed: "standard",
220
+ },
221
+ callSites: {
222
+ filingAgent: { speed: "fast", model: "claude-haiku-4-7" },
223
+ },
224
+ });
225
+ const resolved = resolveCallSiteConfig("filingAgent", llm);
226
+ expect(resolved.model).toBe("claude-haiku-4-7");
227
+ expect(resolved.speed).toBe("fast");
228
+ // Sibling defaults remain untouched.
229
+ expect(resolved.provider).toBe("anthropic");
230
+ expect(resolved.maxTokens).toBe(64000);
231
+ });
232
+
233
+ test("filingAgent profile reference resolves through profile fragment", () => {
234
+ const llm = LLMSchema.parse({
235
+ default: {
236
+ provider: "anthropic",
237
+ model: "claude-opus-4-7",
238
+ maxTokens: 64000,
239
+ effort: "max",
240
+ speed: "standard",
241
+ },
242
+ profiles: {
243
+ background: { speed: "fast", effort: "low" },
244
+ },
245
+ callSites: {
246
+ filingAgent: { profile: "background" },
247
+ },
248
+ });
249
+ const resolved = resolveCallSiteConfig("filingAgent", llm);
250
+ expect(resolved.speed).toBe("fast");
251
+ expect(resolved.effort).toBe("low");
252
+ expect(resolved.model).toBe("claude-opus-4-7");
253
+ });
254
+ });
255
+ });
@@ -422,7 +422,6 @@ describe("GeminiProvider", () => {
422
422
  expect(contents[1].role).toBe("model");
423
423
  expect(contents[1].parts[0]).toEqual({
424
424
  functionCall: {
425
- id: "call_abc",
426
425
  name: "file_read",
427
426
  args: { path: "/tmp/test" },
428
427
  },
@@ -430,7 +429,6 @@ describe("GeminiProvider", () => {
430
429
  expect(contents[2].role).toBe("user");
431
430
  expect(contents[2].parts[0]).toEqual({
432
431
  functionResponse: {
433
- id: "call_abc",
434
432
  name: "file_read",
435
433
  response: { output: "file content here" },
436
434
  },
@@ -464,7 +462,6 @@ describe("GeminiProvider", () => {
464
462
  }>;
465
463
  expect(contents[0].parts[0]).toEqual({
466
464
  functionResponse: {
467
- id: "unknown_id",
468
465
  name: "unknown_id",
469
466
  response: { output: "some result" },
470
467
  },
@@ -31,6 +31,10 @@ import {
31
31
  import * as approvalMessageComposer from "../runtime/approval-message-composer.js";
32
32
  import * as gatewayClient from "../runtime/gateway-client.js";
33
33
  import * as pendingInteractions from "../runtime/pending-interactions.js";
34
+ import {
35
+ _clearApprovalPromptTsTrackerForTesting,
36
+ trackApprovalPromptTs,
37
+ } from "../runtime/routes/approval-prompt-ts-tracker.js";
34
38
  import { handleApprovalInterception } from "../runtime/routes/guardian-approval-interception.js";
35
39
  import { computeToolApprovalDigest } from "../security/tool-approval-digest.js";
36
40
 
@@ -60,6 +64,7 @@ function resetTables(): void {
60
64
  /* tables may not exist yet */
61
65
  }
62
66
  pendingInteractions.clear();
67
+ _clearApprovalPromptTsTrackerForTesting();
63
68
  }
64
69
 
65
70
  function createTestGuardianApproval(
@@ -227,6 +232,8 @@ describe("guardian grant minting on tool-approval decisions", () => {
227
232
  TOOL_NAME,
228
233
  TOOL_INPUT,
229
234
  );
235
+ const approvalMessageTs = "1700000000.000100";
236
+ trackApprovalPromptTs("slack", GUARDIAN_CHAT, approvalMessageTs);
230
237
 
231
238
  const result = await handleApprovalInterception({
232
239
  conversationId: "guardian-conv-1",
@@ -238,6 +245,7 @@ describe("guardian grant minting on tool-approval decisions", () => {
238
245
  replyCallbackUrl: "https://gateway.test/deliver",
239
246
  trustCtx: makeTrustContext(),
240
247
  assistantId: ASSISTANT_ID,
248
+ approvalMessageTs,
241
249
  });
242
250
 
243
251
  expect(result.handled).toBe(true);
@@ -392,7 +392,7 @@ describe("executeBrowserClick (CDP)", () => {
392
392
  const result = await executeBrowserClick({ element_id: "e99" }, ctx);
393
393
  expect(result.isError).toBe(true);
394
394
  expect(result.content).toContain('element_id "e99" not found');
395
- expect(result.content).toContain("browser_snapshot");
395
+ expect(result.content).toContain("snapshot");
396
396
  // Resolution failed before acquiring a CdpClient.
397
397
  expect(sendCalls).toHaveLength(0);
398
398
  });
@@ -9,7 +9,6 @@ let mockConfig = {
9
9
  heartbeat: {
10
10
  enabled: true,
11
11
  intervalMs: 60_000,
12
- speed: "standard" as "standard" | "fast",
13
12
  activeHoursStart: undefined as number | undefined,
14
13
  activeHoursEnd: undefined as number | undefined,
15
14
  },
@@ -126,11 +125,44 @@ const IDENTITY_TEMPLATE = readFileSync(
126
125
  const { stripCommentLines } = await import("../util/strip-comment-lines.js");
127
126
  const SCAFFOLD_PERSONA = stripCommentLines(GUARDIAN_PERSONA_TEMPLATE).trim();
128
127
 
128
+ // Resolver wiring — used by the end-to-end resolution test below to verify
129
+ // that `callSite: 'heartbeatAgent'` resolves to the correct config when
130
+ // `llm.callSites.heartbeatAgent` is defined.
131
+ const { resolveCallSiteConfig } = await import("../config/llm-resolver.js");
132
+ const { LLMSchema } = await import("../config/schemas/llm.js");
133
+
134
+ // Minimal fully-specified `llm.default` block. The resolver requires every
135
+ // `LLMConfigBase` field to be present in `default`, so we provide the same
136
+ // fixture the resolver test suite uses.
137
+ const LLM_DEFAULT = {
138
+ provider: "anthropic" as const,
139
+ model: "claude-opus-4-7",
140
+ maxTokens: 64000,
141
+ effort: "max" as const,
142
+ speed: "standard" as const,
143
+ temperature: null,
144
+ thinking: { enabled: true, streamThinking: true },
145
+ contextWindow: {
146
+ enabled: true,
147
+ maxInputTokens: 200000,
148
+ targetBudgetRatio: 0.3,
149
+ compactThreshold: 0.8,
150
+ summaryBudgetRatio: 0.05,
151
+ overflowRecovery: {
152
+ enabled: true,
153
+ safetyMarginRatio: 0.05,
154
+ maxAttempts: 3,
155
+ interactiveLatestTurnCompression: "summarize" as const,
156
+ nonInteractiveLatestTurnCompression: "truncate" as const,
157
+ },
158
+ },
159
+ };
160
+
129
161
  describe("HeartbeatService", () => {
130
162
  let processMessageCalls: Array<{
131
163
  conversationId: string;
132
164
  content: string;
133
- options?: { speed?: string };
165
+ options?: { callSite?: string };
134
166
  }>;
135
167
  let alerterCalls: Array<{ type: string; title: string; body: string }>;
136
168
 
@@ -152,7 +184,6 @@ describe("HeartbeatService", () => {
152
184
  heartbeat: {
153
185
  enabled: true,
154
186
  intervalMs: 60_000,
155
- speed: "standard",
156
187
  activeHoursStart: undefined,
157
188
  activeHoursEnd: undefined,
158
189
  },
@@ -163,7 +194,7 @@ describe("HeartbeatService", () => {
163
194
  processMessage?: (
164
195
  id: string,
165
196
  content: string,
166
- options?: { speed?: string },
197
+ options?: { callSite?: string },
167
198
  ) => Promise<{ messageId: string }>;
168
199
  getCurrentHour?: () => number;
169
200
  }) {
@@ -173,7 +204,7 @@ describe("HeartbeatService", () => {
173
204
  (async (
174
205
  conversationId: string,
175
206
  content: string,
176
- options?: { speed?: string },
207
+ options?: { callSite?: string },
177
208
  ) => {
178
209
  processMessageCalls.push({ conversationId, content, options });
179
210
  return { messageId: "msg-1" };
@@ -504,32 +535,52 @@ describe("HeartbeatService", () => {
504
535
  expect(service.nextRunAt).toBeNull();
505
536
  });
506
537
 
507
- test("passes heartbeat config speed to processMessage", async () => {
508
- mockConfig.heartbeat.speed = "standard";
538
+ test("passes callSite='heartbeatAgent' to processMessage", async () => {
509
539
  const service = createService();
510
540
  await service.runOnce();
511
541
 
512
542
  expect(processMessageCalls).toHaveLength(1);
513
- expect(processMessageCalls[0].options).toEqual({ speed: "standard" });
543
+ expect(processMessageCalls[0].options).toEqual({
544
+ callSite: "heartbeatAgent",
545
+ });
514
546
  });
515
547
 
516
- test("heartbeat uses its own speed even when global config differs", async () => {
517
- // Simulate: global config has fast, but heartbeat config has standard
518
- mockConfig.heartbeat.speed = "standard";
548
+ test("processMessage receives only callSite no legacy speed knob", async () => {
549
+ // The heartbeat service unconditionally passes `callSite:
550
+ // 'heartbeatAgent'` and nothing else. The resolver maps that identifier
551
+ // to whatever `llm.callSites.heartbeatAgent` (or `llm.default`)
552
+ // configures.
519
553
  const service = createService();
520
554
  await service.runOnce();
521
555
 
522
556
  expect(processMessageCalls).toHaveLength(1);
523
- expect(processMessageCalls[0].options?.speed).toBe("standard");
557
+ expect(processMessageCalls[0].options).toEqual({
558
+ callSite: "heartbeatAgent",
559
+ });
524
560
  });
525
561
 
526
- test("heartbeat passes fast speed when explicitly configured", async () => {
527
- mockConfig.heartbeat.speed = "fast";
562
+ test("end-to-end: llm.callSites.heartbeatAgent.speed resolves to 'fast'", async () => {
563
+ // Verifies the contract that PR 7 establishes: heartbeat passes
564
+ // `callSite: 'heartbeatAgent'`, and the LLM resolver maps that to the
565
+ // configured speed via `llm.callSites.heartbeatAgent`. The heartbeat
566
+ // service itself doesn't call the resolver — that happens downstream in
567
+ // the provider layer (see PR 5) — so this test asserts both halves of
568
+ // the wiring: (a) the call site identifier flows through to
569
+ // processMessage, and (b) the resolver maps that identifier to the
570
+ // user's configured speed.
571
+ const llm = LLMSchema.parse({
572
+ default: LLM_DEFAULT,
573
+ callSites: {
574
+ heartbeatAgent: { speed: "fast" },
575
+ },
576
+ });
528
577
  const service = createService();
529
578
  await service.runOnce();
530
579
 
531
580
  expect(processMessageCalls).toHaveLength(1);
532
- expect(processMessageCalls[0].options?.speed).toBe("fast");
581
+ expect(processMessageCalls[0].options?.callSite).toBe("heartbeatAgent");
582
+ const resolved = resolveCallSiteConfig("heartbeatAgent", llm);
583
+ expect(resolved.speed).toBe("fast");
533
584
  });
534
585
 
535
586
  describe("isShallowProfile", () => {
@@ -672,4 +723,34 @@ describe("HeartbeatService", () => {
672
723
  expect(existsSync(tsPath)).toBe(true);
673
724
  });
674
725
  });
726
+
727
+ describe("credential health gating", () => {
728
+ test("prompt includes credential-status when providers are unhealthy", () => {
729
+ const service = createService();
730
+ const { prompt } = service.buildPrompt("- Check email", ["google"]);
731
+
732
+ expect(prompt).toContain("<credential-status>");
733
+ expect(prompt).toContain("google");
734
+ expect(prompt).toContain(
735
+ "Do NOT attempt to use tools for these providers",
736
+ );
737
+ });
738
+
739
+ test("prompt omits credential-status when all providers are healthy", () => {
740
+ const service = createService();
741
+ const { prompt } = service.buildPrompt("- Check email", []);
742
+
743
+ expect(prompt).not.toContain("<credential-status>");
744
+ });
745
+
746
+ test("prompt lists multiple unhealthy providers", () => {
747
+ const service = createService();
748
+ const { prompt } = service.buildPrompt("- Check things", [
749
+ "google",
750
+ "slack",
751
+ ]);
752
+
753
+ expect(prompt).toContain("google, slack");
754
+ });
755
+ });
675
756
  });
@@ -674,6 +674,18 @@ describe("host_bash — spawn error handling", () => {
674
674
  expect(result.isError).toBe(false);
675
675
  expect(result.content).toContain("<command_completed />");
676
676
  });
677
+
678
+ test("injects __CONVERSATION_ID for local host_bash execution", async () => {
679
+ const result = await hostShellTool.execute(
680
+ {
681
+ command: 'echo "$__CONVERSATION_ID"',
682
+ },
683
+ makeContext(),
684
+ );
685
+
686
+ expect(result.isError).toBe(false);
687
+ expect(result.content.trim()).toBe("test-conversation");
688
+ });
677
689
  });
678
690
 
679
691
  // ---------------------------------------------------------------------------
@@ -681,6 +693,34 @@ describe("host_bash — spawn error handling", () => {
681
693
  // ---------------------------------------------------------------------------
682
694
 
683
695
  describe("host_bash — proxy delegation", () => {
696
+ const ROUTING_ENV_KEYS = [
697
+ "BASE_DATA_DIR",
698
+ "VELLUM_WORKSPACE_DIR",
699
+ "VELLUM_DATA_DIR",
700
+ "VELLUM_ENVIRONMENT",
701
+ "INTERNAL_GATEWAY_BASE_URL",
702
+ ] as const;
703
+
704
+ function captureEnv(
705
+ keys: readonly string[],
706
+ ): Record<string, string | undefined> {
707
+ const snapshot: Record<string, string | undefined> = {};
708
+ for (const key of keys) {
709
+ snapshot[key] = process.env[key];
710
+ }
711
+ return snapshot;
712
+ }
713
+
714
+ function restoreEnv(snapshot: Record<string, string | undefined>): void {
715
+ for (const [key, value] of Object.entries(snapshot)) {
716
+ if (value === undefined) {
717
+ delete process.env[key];
718
+ } else {
719
+ process.env[key] = value;
720
+ }
721
+ }
722
+ }
723
+
684
724
  function makeMockProxy(result: ToolExecutionResult) {
685
725
  const calls: Array<{
686
726
  input: {
@@ -843,6 +883,12 @@ describe("host_bash — proxy delegation", () => {
843
883
  "ces-shell-lockdown": true,
844
884
  });
845
885
 
886
+ const envSnapshot = captureEnv(ROUTING_ENV_KEYS);
887
+ // Keep this test focused on lockdown propagation behavior only.
888
+ for (const key of ROUTING_ENV_KEYS) {
889
+ delete process.env[key];
890
+ }
891
+
846
892
  try {
847
893
  const proxyResult: ToolExecutionResult = {
848
894
  content: "proxied",
@@ -863,32 +909,92 @@ describe("host_bash — proxy delegation", () => {
863
909
 
864
910
  expect(result).toBe(proxyResult);
865
911
  expect(calls.length).toBe(1);
866
- expect(calls[0].input.env).toEqual({ VELLUM_UNTRUSTED_SHELL: "1" });
912
+ expect(calls[0].input.env).toEqual({
913
+ VELLUM_UNTRUSTED_SHELL: "1",
914
+ __CONVERSATION_ID: "test-conversation",
915
+ });
867
916
  } finally {
868
917
  _setOverridesForTesting({});
918
+ restoreEnv(envSnapshot);
869
919
  }
870
920
  });
871
921
 
872
922
  test("does not propagate env to proxy when CES lockdown is inactive", async () => {
873
- const proxyResult: ToolExecutionResult = {
874
- content: "proxied",
875
- isError: false,
876
- };
877
- const { proxy, calls } = makeMockProxy(proxyResult);
923
+ const envSnapshot = captureEnv(ROUTING_ENV_KEYS);
924
+ for (const key of ROUTING_ENV_KEYS) {
925
+ delete process.env[key];
926
+ }
878
927
 
879
- const ctx: ToolContext = {
880
- ...makeContext(),
881
- trustClass: "guardian", // trusted actor — no lockdown
882
- hostBashProxy: proxy as unknown as ToolContext["hostBashProxy"],
883
- };
928
+ try {
929
+ const proxyResult: ToolExecutionResult = {
930
+ content: "proxied",
931
+ isError: false,
932
+ };
933
+ const { proxy, calls } = makeMockProxy(proxyResult);
884
934
 
885
- const result = await hostShellTool.execute(
886
- { command: "echo no-lockdown" },
887
- ctx,
888
- );
935
+ const ctx: ToolContext = {
936
+ ...makeContext(),
937
+ trustClass: "guardian", // trusted actor — no lockdown
938
+ hostBashProxy: proxy as unknown as ToolContext["hostBashProxy"],
939
+ };
889
940
 
890
- expect(result).toBe(proxyResult);
891
- expect(calls.length).toBe(1);
892
- expect(calls[0].input.env).toBeUndefined();
941
+ const result = await hostShellTool.execute(
942
+ { command: "echo no-lockdown" },
943
+ ctx,
944
+ );
945
+
946
+ expect(result).toBe(proxyResult);
947
+ expect(calls.length).toBe(1);
948
+ expect(calls[0].input.env).toEqual({
949
+ __CONVERSATION_ID: "test-conversation",
950
+ });
951
+ } finally {
952
+ restoreEnv(envSnapshot);
953
+ }
954
+ });
955
+
956
+ test("propagates daemon routing env vars to proxy for nested assistant CLI calls", async () => {
957
+ const envSnapshot = captureEnv([
958
+ ...ROUTING_ENV_KEYS,
959
+ "VELLUM_UNTRUSTED_SHELL",
960
+ ]);
961
+ process.env.BASE_DATA_DIR = "/tmp/vellum-instance";
962
+ process.env.VELLUM_WORKSPACE_DIR = "/tmp/vellum-instance/.vellum/workspace";
963
+ process.env.VELLUM_DATA_DIR = "/tmp/vellum-instance/.vellum/workspace/data";
964
+ process.env.VELLUM_ENVIRONMENT = "local";
965
+ process.env.INTERNAL_GATEWAY_BASE_URL = "http://127.0.0.1:7830";
966
+ delete process.env.VELLUM_UNTRUSTED_SHELL;
967
+
968
+ try {
969
+ const proxyResult: ToolExecutionResult = {
970
+ content: "proxied",
971
+ isError: false,
972
+ };
973
+ const { proxy, calls } = makeMockProxy(proxyResult);
974
+
975
+ const ctx: ToolContext = {
976
+ ...makeContext(),
977
+ trustClass: "guardian", // trusted actor — no lockdown
978
+ hostBashProxy: proxy as unknown as ToolContext["hostBashProxy"],
979
+ };
980
+
981
+ const result = await hostShellTool.execute(
982
+ { command: "assistant browser status --json" },
983
+ ctx,
984
+ );
985
+
986
+ expect(result).toBe(proxyResult);
987
+ expect(calls.length).toBe(1);
988
+ expect(calls[0].input.env).toEqual({
989
+ BASE_DATA_DIR: "/tmp/vellum-instance",
990
+ VELLUM_WORKSPACE_DIR: "/tmp/vellum-instance/.vellum/workspace",
991
+ VELLUM_DATA_DIR: "/tmp/vellum-instance/.vellum/workspace/data",
992
+ VELLUM_ENVIRONMENT: "local",
993
+ INTERNAL_GATEWAY_BASE_URL: "http://127.0.0.1:7830",
994
+ __CONVERSATION_ID: "test-conversation",
995
+ });
996
+ } finally {
997
+ restoreEnv(envSnapshot);
998
+ }
893
999
  });
894
1000
  });